From a7166fa27d0191c269e0d88b3f7f278f1db61de0 Mon Sep 17 00:00:00 2001 From: "yue.chang" Date: Thu, 20 Apr 2023 18:47:47 +0800 Subject: [PATCH] add fairseq --- .../hashnerf/scripts/run_gui_nerf.sh | 0 .../hashnerf/scripts/run_gui_nerf_clip.sh | 0 .../hashnerf/scripts/run_gui_tensoRF.sh | 0 .../hashnerf/scripts/run_nerf.sh | 0 3d-reconstruction/hashnerf/scripts/run_sdf.sh | 0 .../hashnerf/scripts/run_tensoRF.sh | 0 cv/3d_detection/BEVFormer/pytorch/LICENSE | 0 cv/3d_detection/BEVFormer/pytorch/README.md | 0 .../pytorch/mmcv/.pre-commit-config.yaml | 0 .../BEVFormer/pytorch/mmcv/.readthedocs.yml | 0 .../BEVFormer/pytorch/mmcv/CITATION.cff | 0 .../BEVFormer/pytorch/mmcv/LICENSE | 0 .../BEVFormer/pytorch/mmcv/build_mmcv.sh | 0 .../BEVFormer/pytorch/mmcv/clean_mmcv.sh | 0 .../BEVFormer/pytorch/mmcv/install_mmcv.sh | 0 .../BEVFormer/pytorch/mmcv/mmcv/__init__.py | 0 .../pytorch/mmcv/mmcv/arraymisc/__init__.py | 0 .../mmcv/mmcv/arraymisc/quantization.py | 0 .../pytorch/mmcv/mmcv/cnn/__init__.py | 0 .../pytorch/mmcv/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/__init__.py | 0 .../mmcv/mmcv/cnn/bricks/activation.py | 0 .../mmcv/mmcv/cnn/bricks/context_block.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../mmcv/mmcv/cnn/bricks/conv_module.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/hsigmoid.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/non_local.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/norm.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/padding.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/registry.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/scale.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/swish.py | 0 .../mmcv/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/mmcv/cnn/bricks/wrappers.py | 0 .../pytorch/mmcv/mmcv/cnn/builder.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/cnn/resnet.py | 0 .../pytorch/mmcv/mmcv/cnn/utils/__init__.py | 0 .../mmcv/mmcv/cnn/utils/flops_counter.py | 0 .../mmcv/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/mmcv/mmcv/cnn/utils/sync_bn.py | 0 .../mmcv/mmcv/cnn/utils/weight_init.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/cnn/vgg.py | 0 .../pytorch/mmcv/mmcv/device/__init__.py | 0 .../pytorch/mmcv/mmcv/device/ipu/__init__.py | 0 .../mmcv/mmcv/device/ipu/dataloader.py | 0 .../device/ipu/hierarchical_data_manager.py | 0 .../mmcv/mmcv/device/ipu/hook_wrapper.py | 0 .../mmcv/mmcv/device/ipu/model_wrapper.py | 0 .../pytorch/mmcv/mmcv/device/ipu/runner.py | 0 .../pytorch/mmcv/mmcv/device/ipu/utils.py | 0 .../pytorch/mmcv/mmcv/device/mlu/__init__.py | 0 .../mmcv/mmcv/device/mlu/_functions.py | 0 .../mmcv/mmcv/device/mlu/data_parallel.py | 0 .../mmcv/mmcv/device/mlu/distributed.py | 0 .../mmcv/mmcv/device/mlu/scatter_gather.py | 0 .../pytorch/mmcv/mmcv/engine/__init__.py | 0 .../pytorch/mmcv/mmcv/engine/test.py | 0 .../pytorch/mmcv/mmcv/fileio/__init__.py | 0 .../pytorch/mmcv/mmcv/fileio/file_client.py | 0 .../mmcv/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/mmcv/fileio/handlers/base.py | 0 .../mmcv/mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/mmcv/fileio/handlers/yaml_handler.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/fileio/io.py | 0 .../pytorch/mmcv/mmcv/fileio/parse.py | 0 .../pytorch/mmcv/mmcv/image/__init__.py | 0 .../pytorch/mmcv/mmcv/image/colorspace.py | 0 .../pytorch/mmcv/mmcv/image/geometric.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/image/io.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/image/misc.py | 0 .../pytorch/mmcv/mmcv/image/photometric.py | 0 .../mmcv/mmcv/model_zoo/deprecated.json | 0 .../pytorch/mmcv/mmcv/model_zoo/mmcls.json | 0 .../mmcv/mmcv/model_zoo/open_mmlab.json | 0 .../mmcv/mmcv/model_zoo/torchvision_0.12.json | 0 .../pytorch/mmcv/mmcv/onnx/__init__.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/onnx/info.py | 0 .../mmcv/mmcv/onnx/onnx_utils/__init__.py | 0 .../mmcv/onnx/onnx_utils/symbolic_helper.py | 0 .../pytorch/mmcv/mmcv/onnx/symbolic.py | 0 .../pytorch/mmcv/mmcv/ops/__init__.py | 0 .../mmcv/mmcv/ops/active_rotated_filter.py | 0 .../mmcv/mmcv/ops/assign_score_withk.py | 0 .../pytorch/mmcv/mmcv/ops/ball_query.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/bbox.py | 0 .../pytorch/mmcv/mmcv/ops/border_align.py | 0 .../pytorch/mmcv/mmcv/ops/box_iou_rotated.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/carafe.py | 0 .../pytorch/mmcv/mmcv/ops/cc_attention.py | 0 .../pytorch/mmcv/mmcv/ops/chamfer_distance.py | 0 .../pytorch/mmcv/mmcv/ops/contour_expand.py | 0 .../pytorch/mmcv/mmcv/ops/convex_iou.py | 0 .../pytorch/mmcv/mmcv/ops/corner_pool.py | 0 .../pytorch/mmcv/mmcv/ops/correlation.py | 0 .../pytorch/mmcv/mmcv/ops/csrc/README.md | 0 .../ops/csrc/common/box_iou_rotated_utils.hpp | 0 .../active_rotated_filter_cuda_kernel.cuh | 0 .../cuda/assign_score_withk_cuda_kernel.cuh | 0 .../common/cuda/ball_query_cuda_kernel.cuh | 0 .../common/cuda/bbox_overlaps_cuda_kernel.cuh | 0 .../common/cuda/border_align_cuda_kernel.cuh | 0 .../csrc/common/cuda/box_iou_rotated_cuda.cuh | 0 .../csrc/common/cuda/carafe_cuda_kernel.cuh | 0 .../common/cuda/carafe_naive_cuda_kernel.cuh | 0 .../cuda/chamfer_distance_cuda_kernel.cuh | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../common/cuda/convex_iou_cuda_kernel.cuh | 0 .../ops/csrc/common/cuda/correlation_cuda.cuh | 0 .../common/cuda/deform_conv_cuda_kernel.cuh | 0 .../cuda/deform_roi_pool_cuda_kernel.cuh | 0 .../cuda/diff_iou_rotated_cuda_kernel.cuh | 0 .../furthest_point_sample_cuda_kernel.cuh | 0 .../common/cuda/gather_points_cuda_kernel.cuh | 0 .../common/cuda/group_points_cuda_kernel.cuh | 0 .../csrc/common/cuda/iou3d_cuda_kernel.cuh | 0 .../ops/csrc/common/cuda/knn_cuda_kernel.cuh | 0 .../common/cuda/masked_conv2d_cuda_kernel.cuh | 0 .../common/cuda/min_area_polygons_cuda.cuh | 0 .../modulated_deform_conv_cuda_kernel.cuh | 0 .../cuda/ms_deform_attn_cuda_kernel.cuh | 0 .../ops/csrc/common/cuda/nms_cuda_kernel.cuh | 0 .../ops/csrc/common/cuda/nms_rotated_cuda.cuh | 0 .../common/cuda/parrots_cudawarpfunction.cuh | 0 .../cuda/points_in_boxes_cuda_kernel.cuh | 0 .../cuda/points_in_polygons_cuda_kernel.cuh | 0 .../csrc/common/cuda/psamask_cuda_kernel.cuh | 0 .../cuda/riroi_align_rotated_cuda_kernel.cuh | 0 .../common/cuda/roi_align_cuda_kernel.cuh | 0 .../cuda/roi_align_rotated_cuda_kernel.cuh | 0 .../csrc/common/cuda/roi_pool_cuda_kernel.cuh | 0 .../cuda/roiaware_pool3d_cuda_kernel.cuh | 0 .../cuda/roipoint_pool3d_cuda_kernel.cuh | 0 .../rotated_feature_align_cuda_kernel.cuh | 0 .../cuda/scatter_points_cuda_kernel.cuh | 0 .../cuda/sigmoid_focal_loss_cuda_kernel.cuh | 0 .../cuda/softmax_focal_loss_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../cuda/three_interpolate_cuda_kernel.cuh | 0 .../csrc/common/cuda/three_nn_cuda_kernel.cuh | 0 .../common/cuda/tin_shift_cuda_kernel.cuh | 0 .../common/cuda/voxelization_cuda_kernel.cuh | 0 .../common/mlu/bbox_overlaps_mlu_kernel.mlu | 0 .../ops/csrc/common/mlu/common_mlu_helper.hpp | 0 .../mlu/focal_loss_sigmoid_mlu_kernel.mlu | 0 .../ops/csrc/common/mlu/nms_mlu_kernel.mlu | 0 .../csrc/common/mlu/psamask_mlu_kernel.mlu | 0 .../ops/csrc/common/mlu/psamask_utils.hpp | 0 .../csrc/common/mlu/roi_align_mlu_kernel.mlu | 0 .../mlu/roi_align_rotated_mlu_kernel.mlu | 0 .../common/mlu/roi_align_rotated_utils.hpp | 0 .../csrc/common/mlu/tin_shift_mlu_kernel.mlu | 0 .../ops/csrc/common/parrots_cpp_helper.hpp | 0 .../ops/csrc/common/parrots_cuda_helper.hpp | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../csrc/common/pytorch_device_registry.hpp | 0 .../ops/csrc/common/pytorch_mlu_helper.hpp | 0 .../mmcv/ops/csrc/onnxruntime/corner_pool.h | 0 .../ops/csrc/onnxruntime/cpu/corner_pool.cpp | 0 .../ops/csrc/onnxruntime/cpu/deform_conv.cpp | 0 .../ops/csrc/onnxruntime/cpu/gridSample.cpp | 0 .../onnxruntime/cpu/modulated_deform_conv.cpp | 0 .../mmcv/ops/csrc/onnxruntime/cpu/nms.cpp | 0 .../onnxruntime/cpu/onnxruntime_register.cpp | 0 .../ops/csrc/onnxruntime/cpu/reduce_ops.cpp | 0 .../ops/csrc/onnxruntime/cpu/roi_align.cpp | 0 .../onnxruntime/cpu/roi_align_rotated.cpp | 0 .../onnxruntime/cpu/rotated_feature_align.cpp | 0 .../ops/csrc/onnxruntime/cpu/soft_nms.cpp | 0 .../mmcv/ops/csrc/onnxruntime/deform_conv.h | 0 .../mmcv/ops/csrc/onnxruntime/grid_sample.h | 0 .../csrc/onnxruntime/modulated_deform_conv.h | 0 .../mmcv/mmcv/ops/csrc/onnxruntime/nms.h | 0 .../csrc/onnxruntime/onnxruntime_register.h | 0 .../onnxruntime_session_options_config_keys.h | 0 .../ops/csrc/onnxruntime/ort_mmcv_utils.h | 0 .../mmcv/ops/csrc/onnxruntime/reduce_ops.h | 0 .../mmcv/ops/csrc/onnxruntime/roi_align.h | 0 .../ops/csrc/onnxruntime/roi_align_rotated.h | 0 .../csrc/onnxruntime/rotated_feature_align.h | 0 .../mmcv/mmcv/ops/csrc/onnxruntime/soft_nms.h | 0 .../csrc/parrots/active_rotated_filter.cpp | 0 .../parrots/active_rotated_filter_parrots.cpp | 0 .../parrots/active_rotated_filter_pytorch.h | 0 .../ops/csrc/parrots/assign_score_withk.cpp | 0 .../parrots/assign_score_withk_parrots.cpp | 0 .../csrc/parrots/assign_score_withk_pytorch.h | 0 .../ops/csrc/parrots/ball_query._parrots.cpp | 0 .../mmcv/mmcv/ops/csrc/parrots/ball_query.cpp | 0 .../ops/csrc/parrots/ball_query_pytorch.h | 0 .../mmcv/ops/csrc/parrots/bbox_overlaps.cpp | 0 .../csrc/parrots/bbox_overlaps_parrots.cpp | 0 .../ops/csrc/parrots/bbox_overlaps_pytorch.h | 0 .../mmcv/ops/csrc/parrots/border_align.cpp | 0 .../ops/csrc/parrots/border_align_parrots.cpp | 0 .../ops/csrc/parrots/border_align_pytorch.h | 0 .../mmcv/ops/csrc/parrots/box_iou_rotated.cpp | 0 .../csrc/parrots/box_iou_rotated_parrots.cpp | 0 .../csrc/parrots/box_iou_rotated_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/carafe.cpp | 0 .../mmcv/ops/csrc/parrots/carafe_naive.cpp | 0 .../ops/csrc/parrots/carafe_naive_parrots.cpp | 0 .../ops/csrc/parrots/carafe_naive_pytorch.h | 0 .../mmcv/ops/csrc/parrots/carafe_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/carafe_pytorch.h | 0 .../mmcv/ops/csrc/parrots/contour_expand.cpp | 0 .../csrc/parrots/contour_expand_parrots.cpp | 0 .../ops/csrc/parrots/contour_expand_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/convex_iou.cpp | 0 .../ops/csrc/parrots/convex_iou_parrots.cpp | 0 .../ops/csrc/parrots/convex_iou_pytorch.h | 0 .../mmcv/ops/csrc/parrots/correlation.cpp | 0 .../ops/csrc/parrots/correlation_parrots.cpp | 0 .../ops/csrc/parrots/correlation_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/cudabind.cpp | 0 .../mmcv/ops/csrc/parrots/deform_conv.cpp | 0 .../ops/csrc/parrots/deform_conv_parrots.cpp | 0 .../ops/csrc/parrots/deform_conv_pytorch.h | 0 .../mmcv/ops/csrc/parrots/deform_roi_pool.cpp | 0 .../csrc/parrots/deform_roi_pool_parrots.cpp | 0 .../csrc/parrots/deform_roi_pool_pytorch.h | 0 .../ops/csrc/parrots/diff_iou_rotated.cpp | 0 .../csrc/parrots/diff_iou_rotated_parrots.cpp | 0 .../csrc/parrots/diff_iou_rotated_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/focal_loss.cpp | 0 .../ops/csrc/parrots/focal_loss_parrots.cpp | 0 .../ops/csrc/parrots/focal_loss_pytorch.h | 0 .../csrc/parrots/furthest_point_sample.cpp | 0 .../parrots/furthest_point_sample_parrots.cpp | 0 .../parrots/furthest_point_sample_pytorch.h | 0 .../ops/csrc/parrots/fused_bias_leakyrelu.cpp | 0 .../ops/csrc/parrots/fused_bias_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/gather_points.cpp | 0 .../csrc/parrots/gather_points_parrots.cpp | 0 .../ops/csrc/parrots/gather_points_pytorch.h | 0 .../mmcv/ops/csrc/parrots/group_points.cpp | 0 .../ops/csrc/parrots/group_points_parrots.cpp | 0 .../ops/csrc/parrots/group_points_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/info.cpp | 0 .../mmcv/mmcv/ops/csrc/parrots/iou3d.cpp | 0 .../mmcv/ops/csrc/parrots/iou3d_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/iou3d_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/knn.cpp | 0 .../mmcv/ops/csrc/parrots/knn_parrots.cpp | 0 .../mmcv/mmcv/ops/csrc/parrots/knn_pytorch.h | 0 .../mmcv/ops/csrc/parrots/masked_conv2d.cpp | 0 .../csrc/parrots/masked_conv2d_parrots.cpp | 0 .../ops/csrc/parrots/masked_conv2d_pytorch.h | 0 .../ops/csrc/parrots/min_area_polygons.cpp | 0 .../parrots/min_area_polygons_parrots.cpp | 0 .../csrc/parrots/min_area_polygons_pytorch.h | 0 .../csrc/parrots/modulated_deform_conv.cpp | 0 .../parrots/modulated_deform_conv_parrots.cpp | 0 .../parrots/modulated_deform_conv_pytorch.h | 0 .../mmcv/ops/csrc/parrots/ms_deform_attn.cpp | 0 .../csrc/parrots/ms_deform_attn_parrots.cpp | 0 .../mmcv/mmcv/ops/csrc/parrots/nms.cpp | 0 .../mmcv/ops/csrc/parrots/nms_parrots.cpp | 0 .../mmcv/mmcv/ops/csrc/parrots/nms_pytorch.h | 0 .../mmcv/ops/csrc/parrots/nms_rotated.cpp | 0 .../mmcv/ops/csrc/parrots/pixel_group.cpp | 0 .../ops/csrc/parrots/pixel_group_parrots.cpp | 0 .../ops/csrc/parrots/pixel_group_pytorch.h | 0 .../mmcv/ops/csrc/parrots/points_in_boxes.cpp | 0 .../csrc/parrots/points_in_boxes_parrots.cpp | 0 .../csrc/parrots/points_in_boxes_pytorch.h | 0 .../ops/csrc/parrots/points_in_polygons.cpp | 0 .../parrots/points_in_polygons_parrots.cpp | 0 .../csrc/parrots/points_in_polygons_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/psamask.cpp | 0 .../mmcv/ops/csrc/parrots/psamask_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/psamask_pytorch.h | 0 .../ops/csrc/parrots/riroi_align_rotated.cpp | 0 .../parrots/riroi_align_rotated_parrots.cpp | 0 .../parrots/riroi_align_rotated_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/roi_align.cpp | 0 .../ops/csrc/parrots/roi_align_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/roi_align_pytorch.h | 0 .../ops/csrc/parrots/roi_align_rotated.cpp | 0 .../parrots/roi_align_rotated_parrots.cpp | 0 .../csrc/parrots/roi_align_rotated_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/roi_pool.cpp | 0 .../ops/csrc/parrots/roi_pool_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/roi_pool_pytorch.h | 0 .../mmcv/ops/csrc/parrots/roiaware_pool3d.cpp | 0 .../csrc/parrots/roiaware_pool3d_parrots.cpp | 0 .../csrc/parrots/roiaware_pool3d_pytorch.h | 0 .../mmcv/ops/csrc/parrots/roipoint_pool3d.cpp | 0 .../csrc/parrots/roipoint_pool3d_parrots.cpp | 0 .../csrc/parrots/roipoint_pool3d_pytorch.h | 0 .../csrc/parrots/rotated_feature_align.cpp | 0 .../parrots/rotated_feature_align_parrots.cpp | 0 .../parrots/rotated_feature_align_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/sync_bn.cpp | 0 .../mmcv/ops/csrc/parrots/sync_bn_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/sync_bn_pytorch.h | 0 .../ops/csrc/parrots/three_interpolate.cpp | 0 .../parrots/three_interpolate_parrots.cpp | 0 .../csrc/parrots/three_interpolate_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/three_nn.cpp | 0 .../ops/csrc/parrots/three_nn_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/three_nn_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/tin_shift.cpp | 0 .../ops/csrc/parrots/tin_shift_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/tin_shift_pytorch.h | 0 .../mmcv/mmcv/ops/csrc/parrots/upfirdn2d.cpp | 0 .../ops/csrc/parrots/upfirdn2d_parrots.cpp | 0 .../mmcv/ops/csrc/parrots/voxelization.cpp | 0 .../ops/csrc/parrots/voxelization_parrots.cpp | 0 .../ops/csrc/parrots/voxelization_pytorch.h | 0 .../csrc/pytorch/active_rotated_filter.cpp | 0 .../ops/csrc/pytorch/assign_score_withk.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/ball_query.cpp | 0 .../mmcv/ops/csrc/pytorch/bbox_overlaps.cpp | 0 .../mmcv/ops/csrc/pytorch/border_align.cpp | 0 .../mmcv/ops/csrc/pytorch/box_iou_rotated.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/carafe.cpp | 0 .../mmcv/ops/csrc/pytorch/carafe_naive.cpp | 0 .../ops/csrc/pytorch/chamfer_distance.cpp | 0 .../mmcv/ops/csrc/pytorch/contour_expand.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/convex_iou.cpp | 0 .../mmcv/ops/csrc/pytorch/correlation.cpp | 0 .../pytorch/cpu/active_rotated_filter.cpp | 0 .../ops/csrc/pytorch/cpu/box_iou_rotated.cpp | 0 .../mmcv/ops/csrc/pytorch/cpu/deform_conv.cpp | 0 .../pytorch/cpu/modulated_deform_conv.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/cpu/nms.cpp | 0 .../mmcv/ops/csrc/pytorch/cpu/nms_rotated.cpp | 0 .../mmcv/ops/csrc/pytorch/cpu/pixel_group.cpp | 0 .../ops/csrc/pytorch/cpu/points_in_boxes.cpp | 0 .../mmcv/ops/csrc/pytorch/cpu/psamask.cpp | 0 .../mmcv/ops/csrc/pytorch/cpu/roi_align.cpp | 0 .../csrc/pytorch/cpu/roi_align_rotated.cpp | 0 .../pytorch/cpu/rotated_feature_align.cpp | 0 .../ops/csrc/pytorch/cpu/voxelization.cpp | 0 .../cuda/active_rotated_filter_cuda.cu | 0 .../pytorch/cuda/assign_score_withk_cuda.cu | 0 .../ops/csrc/pytorch/cuda/ball_query_cuda.cu | 0 .../csrc/pytorch/cuda/bbox_overlaps_cuda.cu | 0 .../csrc/pytorch/cuda/border_align_cuda.cu | 0 .../csrc/pytorch/cuda/box_iou_rotated_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/carafe_cuda.cu | 0 .../csrc/pytorch/cuda/carafe_naive_cuda.cu | 0 .../pytorch/cuda/chamfer_distance_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/convex_iou.cu | 0 .../ops/csrc/pytorch/cuda/correlation_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/cudabind.cpp | 0 .../ops/csrc/pytorch/cuda/deform_conv_cuda.cu | 0 .../csrc/pytorch/cuda/deform_roi_pool_cuda.cu | 0 .../pytorch/cuda/diff_iou_rotated_cuda.cu | 0 .../ops/csrc/pytorch/cuda/focal_loss_cuda.cu | 0 .../cuda/furthest_point_sample_cuda.cu | 0 .../pytorch/cuda/fused_bias_leakyrelu_cuda.cu | 0 .../csrc/pytorch/cuda/gather_points_cuda.cu | 0 .../csrc/pytorch/cuda/group_points_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/iou3d_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/knn_cuda.cu | 0 .../csrc/pytorch/cuda/masked_conv2d_cuda.cu | 0 .../csrc/pytorch/cuda/min_area_polygons.cu | 0 .../cuda/modulated_deform_conv_cuda.cu | 0 .../csrc/pytorch/cuda/ms_deform_attn_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu | 0 .../ops/csrc/pytorch/cuda/nms_rotated_cuda.cu | 0 .../csrc/pytorch/cuda/points_in_boxes_cuda.cu | 0 .../pytorch/cuda/points_in_polygons_cuda.cu | 0 .../ops/csrc/pytorch/cuda/psamask_cuda.cu | 0 .../pytorch/cuda/riroi_align_rotated_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_align_cuda.cu | 0 .../pytorch/cuda/roi_align_rotated_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_pool_cuda.cu | 0 .../csrc/pytorch/cuda/roiaware_pool3d_cuda.cu | 0 .../csrc/pytorch/cuda/roipoint_pool3d_cuda.cu | 0 .../cuda/rotated_feature_align_cuda.cu | 0 .../csrc/pytorch/cuda/scatter_points_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../pytorch/cuda/three_interpolate_cuda.cu | 0 .../ops/csrc/pytorch/cuda/three_nn_cuda.cu | 0 .../ops/csrc/pytorch/cuda/tin_shift_cuda.cu | 0 .../ops/csrc/pytorch/cuda/upfirdn2d_kernel.cu | 0 .../csrc/pytorch/cuda/voxelization_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/deform_conv.cpp | 0 .../mmcv/ops/csrc/pytorch/deform_roi_pool.cpp | 0 .../ops/csrc/pytorch/diff_iou_rotated.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/focal_loss.cpp | 0 .../csrc/pytorch/furthest_point_sample.cpp | 0 .../ops/csrc/pytorch/fused_bias_leakyrelu.cpp | 0 .../ops/csrc/pytorch/fused_spconv_ops.cpp | 0 .../mmcv/ops/csrc/pytorch/gather_points.cpp | 0 .../mmcv/ops/csrc/pytorch/group_points.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/info.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/iou3d.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/knn.cpp | 0 .../mmcv/ops/csrc/pytorch/masked_conv2d.cpp | 0 .../ops/csrc/pytorch/min_area_polygons.cpp | 0 .../csrc/pytorch/mlu/bbox_overlaps_mlu.cpp | 0 .../pytorch/mlu/focal_loss_sigmoid_mlu.cpp | 0 .../mmcv/ops/csrc/pytorch/mlu/nms_mlu.cpp | 0 .../mmcv/ops/csrc/pytorch/mlu/psamask_mlu.cpp | 0 .../ops/csrc/pytorch/mlu/roi_align_mlu.cpp | 0 .../pytorch/mlu/roi_align_rotated_mlu.cpp | 0 .../ops/csrc/pytorch/mlu/tin_shift_mlu.cpp | 0 .../csrc/pytorch/modulated_deform_conv.cpp | 0 .../mmcv/ops/csrc/pytorch/ms_deform_attn.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/nms.cpp | 0 .../mmcv/ops/csrc/pytorch/nms_rotated.cpp | 0 .../mmcv/ops/csrc/pytorch/pixel_group.cpp | 0 .../mmcv/ops/csrc/pytorch/points_in_boxes.cpp | 0 .../ops/csrc/pytorch/points_in_polygons.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/psamask.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../ops/csrc/pytorch/riroi_align_rotated.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/roi_align.cpp | 0 .../ops/csrc/pytorch/roi_align_rotated.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/roi_pool.cpp | 0 .../mmcv/ops/csrc/pytorch/roiaware_pool3d.cpp | 0 .../mmcv/ops/csrc/pytorch/roipoint_pool3d.cpp | 0 .../csrc/pytorch/rotated_feature_align.cpp | 0 .../mmcv/ops/csrc/pytorch/scatter_points.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../ops/csrc/pytorch/three_interpolate.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/three_nn.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/tin_shift.cpp | 0 .../mmcv/mmcv/ops/csrc/pytorch/upfirdn2d.cpp | 0 .../mmcv/ops/csrc/pytorch/voxelization.cpp | 0 .../csrc/tensorrt/plugins/trt_corner_pool.cpp | 0 .../plugins/trt_corner_pool_kernel.cu | 0 .../csrc/tensorrt/plugins/trt_cuda_helper.cu | 0 .../csrc/tensorrt/plugins/trt_cummaxmin.cpp | 0 .../tensorrt/plugins/trt_cummaxmin_kernel.cu | 0 .../csrc/tensorrt/plugins/trt_deform_conv.cpp | 0 .../plugins/trt_deform_conv_kernel.cu | 0 .../tensorrt/plugins/trt_grid_sampler.cpp | 0 .../plugins/trt_grid_sampler_kernel.cu | 0 .../tensorrt/plugins/trt_instance_norm.cpp | 0 .../plugins/trt_modulated_deform_conv.cpp | 0 .../trt_modulated_deform_conv_kernel.cu | 0 .../ops/csrc/tensorrt/plugins/trt_nms.cpp | 0 .../csrc/tensorrt/plugins/trt_nms_kernel.cu | 0 .../ops/csrc/tensorrt/plugins/trt_plugin.cpp | 0 .../csrc/tensorrt/plugins/trt_roi_align.cpp | 0 .../tensorrt/plugins/trt_roi_align_kernel.cu | 0 .../csrc/tensorrt/plugins/trt_scatternd.cpp | 0 .../tensorrt/plugins/trt_scatternd_kernel.cu | 0 .../ops/csrc/tensorrt/trt_corner_pool.hpp | 0 .../ops/csrc/tensorrt/trt_cuda_helper.cuh | 0 .../mmcv/ops/csrc/tensorrt/trt_cummaxmin.hpp | 0 .../ops/csrc/tensorrt/trt_deform_conv.hpp | 0 .../ops/csrc/tensorrt/trt_grid_sampler.hpp | 0 .../ops/csrc/tensorrt/trt_instance_norm.hpp | 0 .../tensorrt/trt_modulated_deform_conv.hpp | 0 .../mmcv/mmcv/ops/csrc/tensorrt/trt_nms.hpp | 0 .../mmcv/ops/csrc/tensorrt/trt_plugin.hpp | 0 .../ops/csrc/tensorrt/trt_plugin_helper.hpp | 0 .../mmcv/ops/csrc/tensorrt/trt_roi_align.hpp | 0 .../mmcv/ops/csrc/tensorrt/trt_scatternd.hpp | 0 .../mmcv/ops/csrc/tensorrt/trt_serialize.hpp | 0 .../pytorch/mmcv/mmcv/ops/deform_conv.py | 0 .../pytorch/mmcv/mmcv/ops/deform_roi_pool.py | 0 .../mmcv/mmcv/ops/deprecated_wrappers.py | 0 .../pytorch/mmcv/mmcv/ops/diff_iou_rotated.py | 0 .../pytorch/mmcv/mmcv/ops/focal_loss.py | 0 .../mmcv/mmcv/ops/furthest_point_sample.py | 0 .../mmcv/mmcv/ops/fused_bias_leakyrelu.py | 0 .../pytorch/mmcv/mmcv/ops/gather_points.py | 0 .../pytorch/mmcv/mmcv/ops/group_points.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/info.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/iou3d.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/knn.py | 0 .../pytorch/mmcv/mmcv/ops/masked_conv.py | 0 .../pytorch/mmcv/mmcv/ops/merge_cells.py | 0 .../mmcv/mmcv/ops/min_area_polygons.py | 0 .../mmcv/mmcv/ops/modulated_deform_conv.py | 0 .../mmcv/mmcv/ops/multi_scale_deform_attn.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/nms.py | 0 .../pytorch/mmcv/mmcv/ops/pixel_group.py | 0 .../pytorch/mmcv/mmcv/ops/point_sample.py | 0 .../pytorch/mmcv/mmcv/ops/points_in_boxes.py | 0 .../mmcv/mmcv/ops/points_in_polygons.py | 0 .../pytorch/mmcv/mmcv/ops/points_sampler.py | 0 .../pytorch/mmcv/mmcv/ops/psa_mask.py | 0 .../mmcv/mmcv/ops/riroi_align_rotated.py | 0 .../pytorch/mmcv/mmcv/ops/roi_align.py | 0 .../mmcv/mmcv/ops/roi_align_rotated.py | 0 .../pytorch/mmcv/mmcv/ops/roi_pool.py | 0 .../pytorch/mmcv/mmcv/ops/roiaware_pool3d.py | 0 .../pytorch/mmcv/mmcv/ops/roipoint_pool3d.py | 0 .../mmcv/mmcv/ops/rotated_feature_align.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/ops/saconv.py | 0 .../pytorch/mmcv/mmcv/ops/scatter_points.py | 0 .../pytorch/mmcv/mmcv/ops/sync_bn.py | 0 .../mmcv/mmcv/ops/three_interpolate.py | 0 .../pytorch/mmcv/mmcv/ops/three_nn.py | 0 .../pytorch/mmcv/mmcv/ops/tin_shift.py | 0 .../pytorch/mmcv/mmcv/ops/upfirdn2d.py | 0 .../pytorch/mmcv/mmcv/ops/voxelize.py | 0 .../pytorch/mmcv/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/mmcv/parallel/_functions.py | 0 .../pytorch/mmcv/mmcv/parallel/collate.py | 0 .../mmcv/mmcv/parallel/data_container.py | 0 .../mmcv/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../pytorch/mmcv/mmcv/parallel/registry.py | 0 .../mmcv/mmcv/parallel/scatter_gather.py | 0 .../pytorch/mmcv/mmcv/parallel/utils.py | 0 .../pytorch/mmcv/mmcv/runner/__init__.py | 0 .../pytorch/mmcv/mmcv/runner/base_module.py | 0 .../pytorch/mmcv/mmcv/runner/base_runner.py | 0 .../pytorch/mmcv/mmcv/runner/builder.py | 0 .../pytorch/mmcv/mmcv/runner/checkpoint.py | 0 .../mmcv/mmcv/runner/default_constructor.py | 0 .../pytorch/mmcv/mmcv/runner/dist_utils.py | 0 .../mmcv/mmcv/runner/epoch_based_runner.py | 0 .../pytorch/mmcv/mmcv/runner/fp16_utils.py | 0 .../mmcv/mmcv/runner/hooks/__init__.py | 0 .../mmcv/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/mmcv/runner/hooks/closure.py | 0 .../pytorch/mmcv/mmcv/runner/hooks/ema.py | 0 .../mmcv/mmcv/runner/hooks/evaluation.py | 0 .../pytorch/mmcv/mmcv/runner/hooks/hook.py | 0 .../mmcv/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/mmcv/runner/hooks/logger/__init__.py | 0 .../mmcv/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/mmcv/runner/hooks/logger/clearml.py | 0 .../mmcv/mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/mmcv/runner/hooks/logger/neptune.py | 0 .../mmcv/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/mmcv/runner/hooks/logger/segmind.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../mmcv/mmcv/runner/hooks/logger/text.py | 0 .../mmcv/mmcv/runner/hooks/logger/wandb.py | 0 .../mmcv/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../mmcv/mmcv/runner/hooks/optimizer.py | 0 .../mmcv/mmcv/runner/hooks/profiler.py | 0 .../mmcv/mmcv/runner/hooks/sampler_seed.py | 0 .../mmcv/mmcv/runner/hooks/sync_buffer.py | 0 .../mmcv/mmcv/runner/iter_based_runner.py | 0 .../pytorch/mmcv/mmcv/runner/log_buffer.py | 0 .../mmcv/mmcv/runner/optimizer/__init__.py | 0 .../mmcv/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../pytorch/mmcv/mmcv/runner/priority.py | 0 .../pytorch/mmcv/mmcv/runner/utils.py | 0 .../pytorch/mmcv/mmcv/tensorrt/__init__.py | 0 .../mmcv/mmcv/tensorrt/init_plugins.py | 0 .../pytorch/mmcv/mmcv/tensorrt/preprocess.py | 0 .../mmcv/mmcv/tensorrt/tensorrt_utils.py | 0 .../pytorch/mmcv/mmcv/utils/__init__.py | 0 .../pytorch/mmcv/mmcv/utils/config.py | 0 .../pytorch/mmcv/mmcv/utils/device_type.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/utils/env.py | 0 .../pytorch/mmcv/mmcv/utils/ext_loader.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/utils/hub.py | 0 .../pytorch/mmcv/mmcv/utils/logging.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/utils/misc.py | 0 .../pytorch/mmcv/mmcv/utils/parrots_jit.py | 0 .../mmcv/mmcv/utils/parrots_wrapper.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/utils/path.py | 0 .../pytorch/mmcv/mmcv/utils/progressbar.py | 0 .../pytorch/mmcv/mmcv/utils/registry.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/utils/seed.py | 0 .../pytorch/mmcv/mmcv/utils/testing.py | 0 .../pytorch/mmcv/mmcv/utils/timer.py | 0 .../pytorch/mmcv/mmcv/utils/trace.py | 0 .../pytorch/mmcv/mmcv/utils/version_utils.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/version.py | 0 .../pytorch/mmcv/mmcv/video/__init__.py | 0 .../BEVFormer/pytorch/mmcv/mmcv/video/io.py | 0 .../pytorch/mmcv/mmcv/video/optflow.py | 0 .../pytorch/mmcv/mmcv/video/processing.py | 0 .../mmcv/mmcv/visualization/__init__.py | 0 .../pytorch/mmcv/mmcv/visualization/color.py | 0 .../pytorch/mmcv/mmcv/visualization/image.py | 0 .../mmcv/mmcv/visualization/optflow.py | 0 .../BEVFormer/pytorch/mmcv/setup.py | 0 .../mmdetection3d/.github/CODE_OF_CONDUCT.md | 0 .../mmdetection3d/.github/CONTRIBUTING.md | 0 .../.github/ISSUE_TEMPLATE/config.yml | 0 .../.github/ISSUE_TEMPLATE/error-report.md | 0 .../.github/ISSUE_TEMPLATE/feature_request.md | 0 .../ISSUE_TEMPLATE/general_questions.md | 0 .../reimplementation_questions.md | 0 .../.github/pull_request_template.md | 0 .../mmdetection3d/.github/workflows/build.yml | 0 .../.github/workflows/deploy.yml | 0 .../mmdetection3d/.github/workflows/lint.yml | 0 .../.github/workflows/test_mim.yml | 0 .../pytorch/mmdetection3d/CITATION.cff | 0 .../BEVFormer/pytorch/mmdetection3d/LICENSE | 0 .../mmdetection3d/mmdet3d/.mim/configs | 1 - .../mmdet3d/.mim/model-index.yml | 1 - .../pytorch/mmdetection3d/mmdet3d/.mim/tools | 1 - .../.mim/tools/analysis_tools/analyze_logs.py | 202 + .../.mim/tools/analysis_tools/benchmark.py | 96 + .../.mim/tools/analysis_tools/get_flops.py | 92 + .../mmdet3d/.mim/tools/create_data.py | 313 + .../mmdet3d/.mim/tools/create_data.sh | 24 + .../.mim/tools/data_converter/__init__.py | 1 + .../data_converter/create_gt_database.py | 624 + .../tools/data_converter/indoor_converter.py | 121 + .../tools/data_converter/kitti_converter.py | 624 + .../tools/data_converter/kitti_data_utils.py | 619 + .../tools/data_converter/lyft_converter.py | 271 + .../tools/data_converter/lyft_data_fixer.py | 39 + .../tools/data_converter/nuimage_converter.py | 226 + .../data_converter/nuscenes_converter.py | 628 + .../tools/data_converter/s3dis_data_utils.py | 245 + .../data_converter/scannet_data_utils.py | 297 + .../data_converter/sunrgbd_data_utils.py | 223 + .../tools/data_converter/waymo_converter.py | 556 + .../tools/deployment/mmdet3d2torchserve.py | 111 + .../.mim/tools/deployment/mmdet3d_handler.py | 120 + .../.mim/tools/deployment/test_torchserver.py | 56 + .../mmdet3d/.mim/tools/dist_test.sh | 22 + .../mmdet3d/.mim/tools/dist_train.sh | 20 + .../mmdet3d/.mim/tools/misc/browse_dataset.py | 232 + .../mmdet3d/.mim/tools/misc/fuse_conv_bn.py | 68 + .../mmdet3d/.mim/tools/misc/print_config.py | 27 + .../.mim/tools/misc/visualize_results.py | 50 + .../convert_h3dnet_checkpoints.py | 177 + .../convert_votenet_checkpoints.py | 153 + .../tools/model_converters/publish_model.py | 36 + .../tools/model_converters/regnet2mmdet.py | 90 + .../mmdet3d/.mim/tools/slurm_test.sh | 24 + .../mmdet3d/.mim/tools/slurm_train.sh | 24 + .../mmdetection3d/mmdet3d/.mim/tools/test.py | 260 + .../mmdetection3d/mmdet3d/.mim/tools/train.py | 263 + .../mmdet3d/.mim/tools/update_data_coords.py | 168 + .../mmdet3d/.mim/tools/update_data_coords.sh | 22 + .../pytorch/mmdetection3d/mmdet3d/__init__.py | 0 .../mmdetection3d/mmdet3d/apis/__init__.py | 0 .../mmdetection3d/mmdet3d/apis/inference.py | 0 .../mmdetection3d/mmdet3d/apis/test.py | 0 .../mmdetection3d/mmdet3d/apis/train.py | 0 .../mmdetection3d/mmdet3d/core/__init__.py | 0 .../mmdet3d/core/anchor/__init__.py | 0 .../core/anchor/anchor_3d_generator.py | 0 .../mmdet3d/core/bbox/__init__.py | 0 .../mmdet3d/core/bbox/assigners/__init__.py | 0 .../mmdet3d/core/bbox/box_np_ops.py | 0 .../mmdet3d/core/bbox/coders/__init__.py | 0 .../bbox/coders/anchor_free_bbox_coder.py | 0 .../bbox/coders/centerpoint_bbox_coders.py | 0 .../bbox/coders/delta_xyzwhlr_bbox_coder.py | 0 .../core/bbox/coders/fcos3d_bbox_coder.py | 0 .../bbox/coders/groupfree3d_bbox_coder.py | 0 .../core/bbox/coders/monoflex_bbox_coder.py | 0 .../coders/partial_bin_based_bbox_coder.py | 0 .../core/bbox/coders/pgd_bbox_coder.py | 0 .../bbox/coders/point_xyzwhlr_bbox_coder.py | 0 .../core/bbox/coders/smoke_bbox_coder.py | 0 .../core/bbox/iou_calculators/__init__.py | 0 .../bbox/iou_calculators/iou3d_calculator.py | 0 .../mmdet3d/core/bbox/samplers/__init__.py | 0 .../samplers/iou_neg_piecewise_sampler.py | 0 .../mmdet3d/core/bbox/structures/__init__.py | 0 .../core/bbox/structures/base_box3d.py | 0 .../core/bbox/structures/box_3d_mode.py | 0 .../mmdet3d/core/bbox/structures/cam_box3d.py | 0 .../core/bbox/structures/coord_3d_mode.py | 0 .../core/bbox/structures/depth_box3d.py | 0 .../core/bbox/structures/lidar_box3d.py | 0 .../mmdet3d/core/bbox/structures/utils.py | 0 .../mmdet3d/core/bbox/transforms.py | 0 .../mmdet3d/core/evaluation/__init__.py | 0 .../mmdet3d/core/evaluation/indoor_eval.py | 0 .../core/evaluation/instance_seg_eval.py | 0 .../core/evaluation/kitti_utils/__init__.py | 0 .../core/evaluation/kitti_utils/eval.py | 0 .../core/evaluation/kitti_utils/rotate_iou.py | 0 .../mmdet3d/core/evaluation/lyft_eval.py | 0 .../core/evaluation/scannet_utils/__init__.py | 0 .../evaluate_semantic_instance.py | 0 .../core/evaluation/scannet_utils/util_3d.py | 0 .../mmdet3d/core/evaluation/seg_eval.py | 0 .../core/evaluation/waymo_utils/__init__.py | 0 .../waymo_utils/prediction_kitti_to_waymo.py | 0 .../mmdet3d/core/points/__init__.py | 0 .../mmdet3d/core/points/base_points.py | 0 .../mmdet3d/core/points/cam_points.py | 0 .../mmdet3d/core/points/depth_points.py | 0 .../mmdet3d/core/points/lidar_points.py | 0 .../mmdet3d/core/post_processing/__init__.py | 0 .../mmdet3d/core/post_processing/box3d_nms.py | 0 .../core/post_processing/merge_augs.py | 0 .../mmdet3d/core/utils/__init__.py | 0 .../mmdet3d/core/utils/array_converter.py | 0 .../mmdet3d/core/utils/gaussian.py | 0 .../mmdet3d/core/visualizer/__init__.py | 0 .../mmdet3d/core/visualizer/image_vis.py | 0 .../mmdet3d/core/visualizer/open3d_vis.py | 0 .../mmdet3d/core/visualizer/show_result.py | 0 .../mmdet3d/core/voxel/__init__.py | 0 .../mmdet3d/core/voxel/builder.py | 0 .../mmdet3d/core/voxel/voxel_generator.py | 0 .../mmdet3d/datasets/__init__.py | 0 .../mmdetection3d/mmdet3d/datasets/builder.py | 0 .../mmdet3d/datasets/custom_3d.py | 0 .../mmdet3d/datasets/custom_3d_seg.py | 0 .../mmdet3d/datasets/dataset_wrappers.py | 0 .../mmdet3d/datasets/kitti2d_dataset.py | 0 .../mmdet3d/datasets/kitti_dataset.py | 0 .../mmdet3d/datasets/kitti_mono_dataset.py | 0 .../mmdet3d/datasets/lyft_dataset.py | 0 .../mmdet3d/datasets/nuscenes_dataset.py | 0 .../mmdet3d/datasets/nuscenes_mono_dataset.py | 0 .../mmdet3d/datasets/pipelines/__init__.py | 0 .../mmdet3d/datasets/pipelines/compose.py | 0 .../datasets/pipelines/data_augment_utils.py | 0 .../mmdet3d/datasets/pipelines/dbsampler.py | 0 .../mmdet3d/datasets/pipelines/formating.py | 0 .../mmdet3d/datasets/pipelines/loading.py | 0 .../datasets/pipelines/test_time_aug.py | 0 .../datasets/pipelines/transforms_3d.py | 0 .../mmdet3d/datasets/s3dis_dataset.py | 0 .../mmdet3d/datasets/scannet_dataset.py | 0 .../mmdet3d/datasets/semantickitti_dataset.py | 0 .../mmdet3d/datasets/sunrgbd_dataset.py | 0 .../mmdetection3d/mmdet3d/datasets/utils.py | 0 .../mmdet3d/datasets/waymo_dataset.py | 0 .../mmdetection3d/mmdet3d/models/__init__.py | 0 .../mmdet3d/models/backbones/__init__.py | 0 .../mmdet3d/models/backbones/base_pointnet.py | 0 .../mmdet3d/models/backbones/dgcnn.py | 0 .../mmdet3d/models/backbones/dla.py | 0 .../mmdet3d/models/backbones/mink_resnet.py | 0 .../models/backbones/multi_backbone.py | 0 .../mmdet3d/models/backbones/nostem_regnet.py | 0 .../models/backbones/pointnet2_sa_msg.py | 0 .../models/backbones/pointnet2_sa_ssg.py | 0 .../mmdet3d/models/backbones/second.py | 0 .../mmdetection3d/mmdet3d/models/builder.py | 0 .../mmdet3d/models/decode_heads/__init__.py | 0 .../models/decode_heads/decode_head.py | 0 .../mmdet3d/models/decode_heads/dgcnn_head.py | 0 .../models/decode_heads/paconv_head.py | 0 .../models/decode_heads/pointnet2_head.py | 0 .../mmdet3d/models/dense_heads/__init__.py | 0 .../models/dense_heads/anchor3d_head.py | 0 .../dense_heads/anchor_free_mono3d_head.py | 0 .../models/dense_heads/base_conv_bbox_head.py | 0 .../dense_heads/base_mono3d_dense_head.py | 0 .../models/dense_heads/centerpoint_head.py | 0 .../mmdet3d/models/dense_heads/fcaf3d_head.py | 0 .../models/dense_heads/fcos_mono3d_head.py | 0 .../models/dense_heads/free_anchor3d_head.py | 0 .../models/dense_heads/groupfree3d_head.py | 0 .../models/dense_heads/monoflex_head.py | 0 .../models/dense_heads/parta2_rpn_head.py | 0 .../mmdet3d/models/dense_heads/pgd_head.py | 0 .../models/dense_heads/point_rpn_head.py | 0 .../models/dense_heads/shape_aware_head.py | 0 .../models/dense_heads/smoke_mono3d_head.py | 0 .../mmdet3d/models/dense_heads/ssd_3d_head.py | 0 .../models/dense_heads/train_mixins.py | 0 .../mmdet3d/models/dense_heads/vote_head.py | 0 .../mmdet3d/models/detectors/__init__.py | 0 .../mmdet3d/models/detectors/base.py | 0 .../mmdet3d/models/detectors/centerpoint.py | 0 .../models/detectors/dynamic_voxelnet.py | 0 .../mmdet3d/models/detectors/fcos_mono3d.py | 0 .../models/detectors/groupfree3dnet.py | 0 .../mmdet3d/models/detectors/h3dnet.py | 0 .../mmdet3d/models/detectors/imvotenet.py | 0 .../mmdet3d/models/detectors/imvoxelnet.py | 0 .../models/detectors/mink_single_stage.py | 0 .../models/detectors/mvx_faster_rcnn.py | 0 .../mmdet3d/models/detectors/mvx_two_stage.py | 0 .../mmdet3d/models/detectors/parta2.py | 0 .../mmdet3d/models/detectors/point_rcnn.py | 0 .../mmdet3d/models/detectors/sassd.py | 0 .../mmdet3d/models/detectors/single_stage.py | 0 .../models/detectors/single_stage_mono3d.py | 0 .../mmdet3d/models/detectors/smoke_mono3d.py | 0 .../mmdet3d/models/detectors/ssd3dnet.py | 0 .../mmdet3d/models/detectors/two_stage.py | 0 .../mmdet3d/models/detectors/votenet.py | 0 .../mmdet3d/models/detectors/voxelnet.py | 0 .../mmdet3d/models/fusion_layers/__init__.py | 0 .../models/fusion_layers/coord_transform.py | 0 .../models/fusion_layers/point_fusion.py | 0 .../models/fusion_layers/vote_fusion.py | 0 .../mmdet3d/models/losses/__init__.py | 0 .../models/losses/axis_aligned_iou_loss.py | 0 .../mmdet3d/models/losses/chamfer_distance.py | 0 .../mmdet3d/models/losses/multibin_loss.py | 0 .../losses/paconv_regularization_loss.py | 0 .../mmdet3d/models/losses/rotated_iou_loss.py | 0 .../models/losses/uncertain_smooth_l1_loss.py | 0 .../models/middle_encoders/__init__.py | 0 .../models/middle_encoders/pillar_scatter.py | 0 .../models/middle_encoders/sparse_encoder.py | 0 .../models/middle_encoders/sparse_unet.py | 0 .../mmdet3d/models/model_utils/__init__.py | 0 .../models/model_utils/edge_fusion_module.py | 0 .../mmdet3d/models/model_utils/transformer.py | 0 .../mmdet3d/models/model_utils/vote_module.py | 0 .../mmdet3d/models/necks/__init__.py | 0 .../mmdet3d/models/necks/dla_neck.py | 0 .../mmdet3d/models/necks/imvoxel_neck.py | 0 .../mmdet3d/models/necks/pointnet2_fp_neck.py | 0 .../mmdet3d/models/necks/second_fpn.py | 0 .../mmdet3d/models/necks/view_transformer.py | 0 .../mmdet3d/models/roi_heads/__init__.py | 0 .../models/roi_heads/base_3droi_head.py | 0 .../models/roi_heads/bbox_heads/__init__.py | 0 .../roi_heads/bbox_heads/h3d_bbox_head.py | 0 .../roi_heads/bbox_heads/parta2_bbox_head.py | 0 .../bbox_heads/point_rcnn_bbox_head.py | 0 .../mmdet3d/models/roi_heads/h3d_roi_head.py | 0 .../models/roi_heads/mask_heads/__init__.py | 0 .../mask_heads/pointwise_semantic_head.py | 0 .../roi_heads/mask_heads/primitive_head.py | 0 .../roi_heads/part_aggregation_roi_head.py | 0 .../models/roi_heads/point_rcnn_roi_head.py | 0 .../roi_heads/roi_extractors/__init__.py | 0 .../single_roiaware_extractor.py | 0 .../single_roipoint_extractor.py | 0 .../mmdet3d/models/segmentors/__init__.py | 0 .../mmdet3d/models/segmentors/base.py | 0 .../models/segmentors/encoder_decoder.py | 0 .../mmdet3d/models/utils/__init__.py | 0 .../mmdet3d/models/utils/clip_sigmoid.py | 0 .../mmdet3d/models/utils/edge_indices.py | 0 .../mmdet3d/models/utils/gen_keypoints.py | 0 .../mmdet3d/models/utils/handle_objs.py | 0 .../mmdetection3d/mmdet3d/models/utils/mlp.py | 0 .../mmdet3d/models/voxel_encoders/__init__.py | 0 .../models/voxel_encoders/pillar_encoder.py | 0 .../mmdet3d/models/voxel_encoders/utils.py | 0 .../models/voxel_encoders/voxel_encoder.py | 0 .../mmdetection3d/mmdet3d/ops/__init__.py | 0 .../mmdet3d/ops/dgcnn_modules/__init__.py | 0 .../ops/dgcnn_modules/dgcnn_fa_module.py | 0 .../ops/dgcnn_modules/dgcnn_fp_module.py | 0 .../ops/dgcnn_modules/dgcnn_gf_module.py | 0 .../pytorch/mmdetection3d/mmdet3d/ops/norm.py | 0 .../mmdet3d/ops/paconv/__init__.py | 0 .../mmdet3d/ops/paconv/paconv.py | 0 .../mmdetection3d/mmdet3d/ops/paconv/utils.py | 0 .../mmdet3d/ops/pointnet_modules/__init__.py | 0 .../mmdet3d/ops/pointnet_modules/builder.py | 0 .../ops/pointnet_modules/paconv_sa_module.py | 0 .../ops/pointnet_modules/point_fp_module.py | 0 .../ops/pointnet_modules/point_sa_module.py | 0 .../mmdetection3d/mmdet3d/ops/sparse_block.py | 0 .../mmdet3d/ops/spconv/__init__.py | 0 .../ops/spconv/overwrite_spconv/__init__.py | 0 .../spconv/overwrite_spconv/write_spconv2.py | 0 .../mmdetection3d/mmdet3d/utils/__init__.py | 0 .../mmdet3d/utils/collect_env.py | 0 .../mmdetection3d/mmdet3d/utils/compat_cfg.py | 0 .../mmdetection3d/mmdet3d/utils/logger.py | 0 .../mmdetection3d/mmdet3d/utils/misc.py | 0 .../mmdetection3d/mmdet3d/utils/setup_env.py | 0 .../pytorch/mmdetection3d/mmdet3d/version.py | 0 .../pytorch/mmdetection3d/requirements.txt | 0 .../mmdetection3d/requirements/build.txt | 0 .../mmdetection3d/requirements/docs.txt | 0 .../mmdetection3d/requirements/mminstall.txt | 0 .../mmdetection3d/requirements/optional.txt | 0 .../requirements/readthedocs.txt | 0 .../mmdetection3d/requirements/runtime.txt | 0 .../mmdetection3d/requirements/tests.txt | 0 .../BEVFormer/pytorch/mmdetection3d/setup.cfg | 0 .../BEVFormer/pytorch/mmdetection3d/setup.py | 0 .../mmdetection3d/tests/data/kitti/a.bin | Bin .../tests/data/kitti/kitti_dbinfos_train.pkl | Bin .../kitti_gt_database/0_Pedestrian_0.bin | Bin .../data/kitti/kitti_infos_mono3d.coco.json | 0 .../tests/data/kitti/kitti_infos_mono3d.pkl | Bin .../tests/data/kitti/kitti_infos_train.pkl | Bin .../data/kitti/mono3d_sample_results.pkl | Bin .../data/kitti/mono3d_sample_results2d.pkl | Bin .../data/kitti/training/image_2/000000.png | Bin .../data/kitti/training/image_2/000007.png | Bin .../data/kitti/training/velodyne/000000.bin | Bin .../training/velodyne_reduced/000000.bin | Bin .../host-a017_lidar1_1236118886501000046.bin | Bin .../host-a017_lidar1_1236118886701083686.bin | Bin .../host-a017_lidar1_1236118886901125926.bin | Bin .../tests/data/lyft/lyft_infos.pkl | Bin .../tests/data/lyft/lyft_infos_val.pkl | Bin .../tests/data/lyft/sample_results.pkl | Bin .../v1.01-train/maps/map_raster_palo_alto.png | Bin .../v1.01-train/v1.01-train/attribute.json | 0 .../v1.01-train/calibrated_sensor.json | 0 .../v1.01-train/v1.01-train/category.json | 0 .../v1.01-train/v1.01-train/ego_pose.json | 0 .../v1.01-train/v1.01-train/instance.json | 0 .../lyft/v1.01-train/v1.01-train/log.json | 0 .../lyft/v1.01-train/v1.01-train/map.json | 0 .../lyft/v1.01-train/v1.01-train/sample.json | 0 .../v1.01-train/sample_annotation.json | 0 .../v1.01-train/v1.01-train/sample_data.json | 0 .../lyft/v1.01-train/v1.01-train/scene.json | 0 .../lyft/v1.01-train/v1.01-train/sensor.json | 0 .../v1.01-train/v1.01-train/visibility.json | 0 .../mmdetection3d/tests/data/lyft/val.txt | 0 .../data/nuscenes/mono3d_sample_results.pkl | Bin .../tests/data/nuscenes/nus_info.pkl | Bin .../data/nuscenes/nus_infos_mono3d.coco.json | 0 ...+0800__CAM_BACK_LEFT__1531883530447423.jpg | Bin ...+0800__LIDAR_TOP__1533201470948018.pcd.bin | Bin ...-0400__LIDAR_TOP__1537287083900561.pcd.bin | Bin ...+0800__LIDAR_TOP__1533201470898274.pcd.bin | Bin .../data/ops/features_for_fps_distance.npy | Bin .../mmdetection3d/tests/data/ops/fps_idx.npy | Bin .../s3dis/instance_mask/Area_1_office_2.bin | Bin .../data/s3dis/points/Area_1_office_2.bin | Bin .../tests/data/s3dis/s3dis_infos.pkl | Bin .../s3dis/semantic_mask/Area_1_office_2.bin | Bin .../scannet/instance_mask/scene0000_00.bin | Bin .../data/scannet/points/scene0000_00.bin | Bin .../tests/data/scannet/scannet_infos.pkl | Bin .../scannet/semantic_mask/scene0000_00.bin | Bin .../semantickitti/semantickitti_infos.pkl | Bin .../sequences/00/labels/000000.label | Bin .../sequences/00/velodyne/000000.bin | Bin .../tests/data/sunrgbd/points/000001.bin | Bin .../tests/data/sunrgbd/sunrgbd_infos.pkl | Bin .../sunrgbd/sunrgbd_trainval/image/000001.jpg | Bin .../kitti_format/training/image_0/0000000.png | Bin .../kitti_format/training/image_0/1000000.png | Bin .../training/velodyne/0000000.bin | Bin .../training/velodyne/1000000.bin | Bin .../kitti_format/waymo_dbinfos_train.pkl | Bin .../waymo_gt_database/0_Car_0.bin | Bin .../waymo/kitti_format/waymo_infos_train.pkl | Bin .../waymo/kitti_format/waymo_infos_val.pkl | Bin .../tests/data/waymo/waymo_format/gt.bin | Bin .../waymo_format/validation/val.tfrecord | Bin .../test_datasets/test_dataset_wrappers.py | 0 .../test_datasets/test_kitti_dataset.py | 0 .../test_datasets/test_kitti_mono_dataset.py | 0 .../test_datasets/test_lyft_dataset.py | 0 .../test_datasets/test_nuscene_dataset.py | 0 .../test_nuscenes_mono_dataset.py | 0 .../test_datasets/test_s3dis_dataset.py | 0 .../test_datasets/test_scannet_dataset.py | 0 .../test_semantickitti_dataset.py | 0 .../test_datasets/test_sunrgbd_dataset.py | 0 .../test_datasets/test_waymo_dataset.py | 0 .../test_data_augment_utils.py | 0 .../test_test_augment_utils.py | 0 .../test_augmentations/test_transforms_3d.py | 0 .../test_pipelines/test_indoor_pipeline.py | 0 .../test_pipelines/test_indoor_sample.py | 0 .../test_load_images_from_multi_views.py | 0 .../test_load_points_from_multi_sweeps.py | 0 .../test_loadings/test_loading.py | 0 .../test_pipelines/test_outdoor_pipeline.py | 0 .../tests/test_metrics/test_indoor_eval.py | 0 .../test_metrics/test_instance_seg_eval.py | 0 .../tests/test_metrics/test_kitti_eval.py | 0 .../tests/test_metrics/test_losses.py | 0 .../tests/test_metrics/test_seg_eval.py | 0 .../tests/test_models/test_backbones.py | 0 .../test_common_modules/test_dgcnn_modules.py | 0 .../test_middle_encoders.py | 0 .../test_paconv_modules.py | 0 .../test_common_modules/test_paconv_ops.py | 0 .../test_pointnet_modules.py | 0 .../test_common_modules/test_sparse_unet.py | 0 .../test_common_modules/test_vote_module.py | 0 .../tests/test_models/test_detectors.py | 0 .../tests/test_models/test_forward.py | 0 .../test_fusion/test_fusion_coord_trans.py | 0 .../test_fusion/test_point_fusion.py | 0 .../test_fusion/test_vote_fusion.py | 0 .../test_heads/test_dgcnn_decode_head.py | 0 .../test_models/test_heads/test_heads.py | 0 .../test_heads/test_paconv_decode_head.py | 0 .../test_heads/test_parta2_bbox_head.py | 0 .../test_heads/test_pointnet2_decode_head.py | 0 .../test_heads/test_roi_extractors.py | 0 .../test_heads/test_semantic_heads.py | 0 .../tests/test_models/test_necks/test_fpn.py | 0 .../test_models/test_necks/test_necks.py | 0 .../tests/test_models/test_segmentors.py | 0 .../test_voxel_encoder/test_voxel_encoders.py | 0 .../test_voxel_generator.py | 0 .../tests/test_runtime/test_apis.py | 0 .../tests/test_runtime/test_config.py | 0 .../test_samples/parta2_roihead_inputs.npz | Bin .../tests/test_utils/test_anchors.py | 0 .../tests/test_utils/test_assigners.py | 0 .../tests/test_utils/test_bbox_coders.py | 0 .../tests/test_utils/test_box3d.py | 0 .../tests/test_utils/test_box_np_ops.py | 0 .../tests/test_utils/test_compat_cfg.py | 0 .../tests/test_utils/test_coord_3d_mode.py | 0 .../tests/test_utils/test_merge_augs.py | 0 .../tests/test_utils/test_nms.py | 0 .../tests/test_utils/test_points.py | 0 .../tests/test_utils/test_samplers.py | 0 .../tests/test_utils/test_setup_env.py | 0 .../tests/test_utils/test_utils.py | 0 .../tools/analysis_tools/analyze_logs.py | 0 .../tools/analysis_tools/benchmark.py | 0 .../tools/analysis_tools/get_flops.py | 0 .../mmdetection3d/tools/create_data.py | 0 .../mmdetection3d/tools/create_data.sh | 0 .../tools/data_converter/__init__.py | 0 .../data_converter/create_gt_database.py | 0 .../tools/data_converter/indoor_converter.py | 0 .../tools/data_converter/kitti_converter.py | 0 .../tools/data_converter/kitti_data_utils.py | 0 .../tools/data_converter/lyft_converter.py | 0 .../tools/data_converter/lyft_data_fixer.py | 0 .../tools/data_converter/nuimage_converter.py | 0 .../data_converter/nuscenes_converter.py | 0 .../tools/data_converter/s3dis_data_utils.py | 0 .../data_converter/scannet_data_utils.py | 0 .../data_converter/sunrgbd_data_utils.py | 0 .../tools/data_converter/waymo_converter.py | 0 .../tools/deployment/mmdet3d2torchserve.py | 0 .../tools/deployment/mmdet3d_handler.py | 0 .../tools/deployment/test_torchserver.py | 0 .../pytorch/mmdetection3d/tools/dist_test.sh | 0 .../pytorch/mmdetection3d/tools/dist_train.sh | 0 .../tools/misc/browse_dataset.py | 0 .../mmdetection3d/tools/misc/fuse_conv_bn.py | 0 .../mmdetection3d/tools/misc/print_config.py | 0 .../tools/misc/visualize_results.py | 0 .../convert_h3dnet_checkpoints.py | 0 .../convert_votenet_checkpoints.py | 0 .../tools/model_converters/publish_model.py | 0 .../tools/model_converters/regnet2mmdet.py | 0 .../pytorch/mmdetection3d/tools/slurm_test.sh | 0 .../mmdetection3d/tools/slurm_train.sh | 0 .../pytorch/mmdetection3d/tools/test.py | 0 .../pytorch/mmdetection3d/tools/train.py | 0 .../mmdetection3d/tools/update_data_coords.py | 0 .../mmdetection3d/tools/update_data_coords.sh | 0 .../BEVFormer/pytorch/projects/__init__.py | 0 .../configs/_base_/datasets/coco_instance.py | 0 .../_base_/datasets/kitti-3d-3class.py | 0 .../configs/_base_/datasets/kitti-3d-car.py | 0 .../configs/_base_/datasets/lyft-3d.py | 0 .../configs/_base_/datasets/nuim_instance.py | 0 .../configs/_base_/datasets/nus-3d.py | 0 .../configs/_base_/datasets/nus-mono3d.py | 0 .../_base_/datasets/range100_lyft-3d.py | 0 .../_base_/datasets/s3dis-3d-5class.py | 0 .../_base_/datasets/s3dis_seg-3d-13class.py | 0 .../_base_/datasets/scannet-3d-18class.py | 0 .../_base_/datasets/scannet_seg-3d-20class.py | 0 .../_base_/datasets/sunrgbd-3d-10class.py | 0 .../_base_/datasets/waymoD5-3d-3class.py | 0 .../configs/_base_/datasets/waymoD5-3d-car.py | 0 .../configs/_base_/default_runtime.py | 0 .../projects/configs/_base_/models/3dssd.py | 0 .../models/cascade_mask_rcnn_r50_fpn.py | 0 .../centerpoint_01voxel_second_secfpn_nus.py | 0 .../centerpoint_02pillar_second_secfpn_nus.py | 0 .../projects/configs/_base_/models/fcos3d.py | 0 .../configs/_base_/models/groupfree3d.py | 0 .../projects/configs/_base_/models/h3dnet.py | 0 .../_base_/models/hv_pointpillars_fpn_lyft.py | 0 .../_base_/models/hv_pointpillars_fpn_nus.py | 0 .../hv_pointpillars_fpn_range100_lyft.py | 0 .../models/hv_pointpillars_secfpn_kitti.py | 0 .../models/hv_pointpillars_secfpn_waymo.py | 0 .../_base_/models/hv_second_secfpn_kitti.py | 0 .../_base_/models/hv_second_secfpn_waymo.py | 0 .../configs/_base_/models/imvotenet_image.py | 0 .../_base_/models/mask_rcnn_r50_fpn.py | 0 .../configs/_base_/models/paconv_cuda_ssg.py | 0 .../configs/_base_/models/paconv_ssg.py | 0 .../projects/configs/_base_/models/parta2.py | 0 .../configs/_base_/models/pointnet2_msg.py | 0 .../configs/_base_/models/pointnet2_ssg.py | 0 .../projects/configs/_base_/models/votenet.py | 0 .../configs/_base_/schedules/cosine.py | 0 .../configs/_base_/schedules/cyclic_20e.py | 0 .../configs/_base_/schedules/cyclic_40e.py | 0 .../_base_/schedules/mmdet_schedule_1x.py | 0 .../configs/_base_/schedules/schedule_2x.py | 0 .../configs/_base_/schedules/schedule_3x.py | 0 .../_base_/schedules/seg_cosine_150e.py | 0 .../_base_/schedules/seg_cosine_200e.py | 0 .../_base_/schedules/seg_cosine_50e.py | 0 .../configs/bevformer/bevformer_base.py | 0 .../configs/bevformer/bevformer_small.py | 0 .../configs/bevformer/bevformer_tiny.py | 0 .../bevformer_fp16/bevformer_tiny_fp16.py | 0 .../configs/datasets/custom_lyft-3d.py | 0 .../configs/datasets/custom_nus-3d.py | 0 .../configs/datasets/custom_waymo-3d.py | 0 .../projects/mmdet3d_plugin/__init__.py | 0 .../mmdet3d_plugin/bevformer/__init__.py | 0 .../mmdet3d_plugin/bevformer/apis/__init__.py | 0 .../bevformer/apis/mmdet_train.py | 0 .../mmdet3d_plugin/bevformer/apis/test.py | 0 .../mmdet3d_plugin/bevformer/apis/train.py | 0 .../bevformer/dense_heads/__init__.py | 0 .../bevformer/dense_heads/bevformer_head.py | 0 .../bevformer/detectors/__init__.py | 0 .../bevformer/detectors/bevformer.py | 0 .../bevformer/detectors/bevformer_fp16.py | 0 .../bevformer/hooks/__init__.py | 0 .../bevformer/hooks/custom_hooks.py | 0 .../bevformer/modules/__init__.py | 0 .../modules/custom_base_transformer_layer.py | 0 .../bevformer/modules/decoder.py | 0 .../bevformer/modules/encoder.py | 0 .../multi_scale_deformable_attn_function.py | 0 .../modules/spatial_cross_attention.py | 0 .../modules/temporal_self_attention.py | 0 .../bevformer/modules/transformer.py | 0 .../bevformer/runner/__init__.py | 0 .../bevformer/runner/epoch_based_runner.py | 0 .../core/bbox/assigners/__init__.py | 0 .../bbox/assigners/hungarian_assigner_3d.py | 0 .../core/bbox/coders/__init__.py | 0 .../core/bbox/coders/nms_free_coder.py | 0 .../core/bbox/match_costs/__init__.py | 0 .../core/bbox/match_costs/match_cost.py | 0 .../projects/mmdet3d_plugin/core/bbox/util.py | 0 .../core/evaluation/__init__.py | 0 .../core/evaluation/eval_hooks.py | 0 .../core/evaluation/kitti2waymo.py | 0 .../mmdet3d_plugin/datasets/__init__.py | 0 .../mmdet3d_plugin/datasets/builder.py | 0 .../datasets/nuscenes_dataset.py | 0 .../datasets/nuscenes_mono_dataset.py | 0 .../mmdet3d_plugin/datasets/nuscnes_eval.py | 0 .../datasets/pipelines/__init__.py | 0 .../datasets/pipelines/formating.py | 0 .../datasets/pipelines/loading.py | 0 .../datasets/pipelines/transform_3d.py | 0 .../datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/samplers/group_sampler.py | 0 .../datasets/samplers/sampler.py | 0 .../models/backbones/__init__.py | 0 .../mmdet3d_plugin/models/backbones/vovnet.py | 0 .../mmdet3d_plugin/models/hooks/__init__.py | 0 .../mmdet3d_plugin/models/hooks/hooks.py | 0 .../mmdet3d_plugin/models/opt/__init__.py | 0 .../mmdet3d_plugin/models/opt/adamw.py | 0 .../mmdet3d_plugin/models/utils/__init__.py | 0 .../mmdet3d_plugin/models/utils/bricks.py | 0 .../mmdet3d_plugin/models/utils/grid_mask.py | 0 .../models/utils/position_embedding.py | 0 .../mmdet3d_plugin/models/utils/visual.py | 0 .../pytorch/tools/analysis_tools/__init__.py | 0 .../tools/analysis_tools/analyze_logs.py | 0 .../pytorch/tools/analysis_tools/benchmark.py | 0 .../tools/analysis_tools/get_params.py | 0 .../pytorch/tools/analysis_tools/visual.py | 0 .../BEVFormer/pytorch/tools/create_data.py | 0 .../pytorch/tools/data_converter/__init__.py | 0 .../data_converter/create_gt_database.py | 0 .../tools/data_converter/indoor_converter.py | 0 .../tools/data_converter/kitti_converter.py | 0 .../tools/data_converter/kitti_data_utils.py | 0 .../tools/data_converter/lyft_converter.py | 0 .../tools/data_converter/lyft_data_fixer.py | 0 .../tools/data_converter/nuimage_converter.py | 0 .../data_converter/nuscenes_converter.py | 0 .../tools/data_converter/s3dis_data_utils.py | 0 .../data_converter/scannet_data_utils.py | 0 .../data_converter/sunrgbd_data_utils.py | 0 .../tools/data_converter/waymo_converter.py | 0 .../BEVFormer/pytorch/tools/dist_test.sh | 0 .../BEVFormer/pytorch/tools/dist_train.sh | 0 .../pytorch/tools/fp16/dist_train.sh | 0 .../BEVFormer/pytorch/tools/fp16/train.py | 0 .../pytorch/tools/misc/browse_dataset.py | 0 .../pytorch/tools/misc/fuse_conv_bn.py | 0 .../pytorch/tools/misc/print_config.py | 0 .../pytorch/tools/misc/visualize_results.py | 0 .../convert_votenet_checkpoints.py | 0 .../tools/model_converters/publish_model.py | 0 .../tools/model_converters/regnet2mmdet.py | 0 .../BEVFormer/pytorch/tools/test.py | 0 .../BEVFormer/pytorch/tools/train.py | 0 .../pointpillars/pytorch/.gitignore | 0 .../pointpillars/pytorch/README.md | 0 .../pointpillars/pytorch/__init__.py | 0 .../pointpillars/pytorch/dataset/__init__.py | 0 .../pointpillars/pytorch/dataset/data_aug.py | 0 .../pytorch/dataset/dataloader.py | 0 .../pointpillars/pytorch/dataset/kitti.py | 0 .../pointpillars/pytorch/evaluate.py | 0 .../pytorch/figures/img_3dbbox_000134.png | Bin .../pytorch/figures/pc_pred_000134.png | Bin .../pointpillars/pytorch/loss/__init__.py | 0 .../pointpillars/pytorch/loss/loss.py | 0 .../pointpillars/pytorch/misc/log.md | 0 .../pointpillars/pytorch/misc/vis_data_gt.py | 0 .../pointpillars/pytorch/model/__init__.py | 0 .../pointpillars/pytorch/model/anchors.py | 0 .../pytorch/model/pointpillars.py | 0 .../pointpillars/pytorch/ops/__init__.py | 0 .../pointpillars/pytorch/ops/iou3d/iou3d.cpp | 0 .../pytorch/ops/iou3d/iou3d_kernel.cu | 0 .../pointpillars/pytorch/ops/iou3d_module.py | 0 .../pointpillars/pytorch/ops/setup.py | 0 .../pointpillars/pytorch/ops/voxel_module.py | 0 .../pytorch/ops/voxelization/voxelization.cpp | 0 .../pytorch/ops/voxelization/voxelization.h | 0 .../ops/voxelization/voxelization_cpu.cpp | 0 .../ops/voxelization/voxelization_cuda.cu | 0 .../pointpillars/pytorch/pre_process_kitti.py | 0 .../pointpillars/pytorch/requirements.txt | 0 cv/3d_detection/pointpillars/pytorch/test.py | 0 cv/3d_detection/pointpillars/pytorch/train.py | 0 .../pointpillars/pytorch/utils/__init__.py | 0 .../pointpillars/pytorch/utils/io.py | 0 .../pointpillars/pytorch/utils/process.py | 0 .../pointpillars/pytorch/utils/viewpoint.json | 0 .../pointpillars/pytorch/utils/vis_o3d.py | 0 cv/classification/densenet/pytorch/.gitignore | 0 cv/classification/densenet/pytorch/README.md | 0 .../densenet/pytorch/__init__.py | 0 .../densenet/pytorch/common_utils/__init__.py | 0 .../densenet/pytorch/common_utils/dist.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../densenet/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../densenet/pytorch/dataloader/__init__.py | 0 .../pytorch/dataloader/classification.py | 0 .../pytorch/dataloader/dali_classification.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../utils/presets_classification.py | 0 cv/classification/densenet/pytorch/train.py | 0 cv/classification/densenet/pytorch/utils_.py | 0 .../dpn107/pytorch/train_dpn107_amp_dist.sh | 0 .../dpn92/pytorch/train_dpn92_amp_dist.sh | 0 .../train_eca_mobilenet_v2_amp_dist.sh | 0 .../pytorch/train_eca_resnet152_amp_dist.sh | 0 .../efficientb4/pytorch/.gitignore | 0 .../efficientb4/pytorch/README.md | 0 .../efficientb4/pytorch/__init__.py | 0 .../pytorch/common_utils/__init__.py | 0 .../efficientb4/pytorch/common_utils/dist.py | 0 .../efficientb4/pytorch/common_utils/loss.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../efficientb4/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../pytorch/dataloader/__init__.py | 0 .../pytorch/dataloader/classification.py | 0 .../pytorch/dataloader/dali_classification.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../utils/presets_classification.py | 0 .../efficientb4/pytorch/train.py | 0 .../efficientb4/pytorch/utils.py | 0 .../googlenet/pytorch/.gitignore | 0 cv/classification/googlenet/pytorch/README.md | 0 .../googlenet/pytorch/__init__.py | 0 .../pytorch/common_utils/__init__.py | 0 .../googlenet/pytorch/common_utils/dist.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../googlenet/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../googlenet/pytorch/dataloader/__init__.py | 0 .../pytorch/dataloader/classification.py | 0 .../pytorch/dataloader/dali_classification.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../utils/presets_classification.py | 0 cv/classification/googlenet/pytorch/train.py | 0 cv/classification/googlenet/pytorch/utils_.py | 0 .../pytorch/train_inception_v3_amp_dist.sh | 0 .../pytorch/train_inceptionv4_amp_dist.sh | 0 cv/classification/lenet/pytorch/.gitignore | 0 cv/classification/lenet/pytorch/README.md | 0 cv/classification/lenet/pytorch/__init__.py | 0 .../lenet/pytorch/common_utils/__init__.py | 0 .../lenet/pytorch/common_utils/dist.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../lenet/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../lenet/pytorch/dataloader/__init__.py | 0 .../pytorch/dataloader/classification.py | 0 .../pytorch/dataloader/dali_classification.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../utils/presets_classification.py | 0 cv/classification/lenet/pytorch/train.py | 0 cv/classification/lenet/pytorch/utils_.py | 0 .../pytorch/train_mobilenet_v2_amp_dist.sh | 0 .../train_mobilenet_v3_large_amp_dist.sh | 0 cv/classification/repvgg/pytorch/LICENSE | 0 cv/classification/repvgg/pytorch/README.md | 0 .../repvgg/pytorch/data/__init__.py | 0 .../repvgg/pytorch/data/build.py | 0 .../pytorch/data/cached_image_folder.py | 0 .../repvgg/pytorch/data/lmdb_dataset.py | 0 .../repvgg/pytorch/data/samplers.py | 0 .../repvgg/pytorch/data/zipreader.py | 0 .../repvgg/pytorch/example_pspnet.py | 0 .../pytorch/jizhi_submit_train_repvgg.py | 0 cv/classification/repvgg/pytorch/main.py | 0 .../pytorch/quantization/quant_qat_train.py | 0 .../pytorch/quantization/repvgg_quantized.py | 0 cv/classification/repvgg/pytorch/repvgg.py | 0 .../repvgg/pytorch/repvggplus.py | 0 .../repvgg/pytorch/repvggplus_custom_L2.py | 0 cv/classification/repvgg/pytorch/se_block.py | 0 .../repvgg/pytorch/tools/convert.py | 0 .../repvgg/pytorch/tools/insert_bn.py | 0 .../repvgg/pytorch/tools/verify.py | 0 .../repvgg/pytorch/train/config.py | 0 .../repvgg/pytorch/train/cutout.py | 0 .../repvgg/pytorch/train/logger.py | 0 .../repvgg/pytorch/train/lr_scheduler.py | 0 .../repvgg/pytorch/train/optimizer.py | 0 .../repvgg/pytorch/train/randaug.py | 0 cv/classification/repvgg/pytorch/utils.py | 0 .../pytorch/train_resnest101_amp_dist.sh | 0 .../pytorch/train_resnest14_amp_dist.sh | 0 .../pytorch/train_resnest269_amp_dist.sh | 0 .../pytorch/train_resnest50_amp_dist.sh | 0 .../pytorch/train_resnet101_amp_dist.sh | 0 .../pytorch/train_resnet152_amp_dist.sh | 0 .../pytorch/train_resnet18_amp_dist.sh | 0 .../train_resnext101_32x8d_amp_dist.sh | 0 .../pytorch/train_resnext50_32x4d_amp_dist.sh | 0 .../train_seresnext101_32x4d_amp_dist.sh | 0 .../train_shufflenet_v2_x2_0_amp_dist.sh | 0 cv/classification/vgg/pytorch/.gitignore | 0 .../vgg/pytorch/train_vgg16_amp_dist.sh | 0 .../train_wide_resnet101_2_amp_dist.sh | 0 cv/classification/xception/pytorch/.gitignore | 0 cv/classification/xception/pytorch/README.md | 0 .../xception/pytorch/__init__.py | 0 .../xception/pytorch/common_utils/__init__.py | 0 .../xception/pytorch/common_utils/dist.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../xception/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../xception/pytorch/dataloader/__init__.py | 0 .../pytorch/dataloader/classification.py | 0 .../pytorch/dataloader/dali_classification.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../utils/presets_classification.py | 0 cv/classification/xception/pytorch/train.py | 0 cv/classification/xception/pytorch/utils_.py | 0 cv/detection/autoassign/pytorch/.gitignore | 0 cv/detection/autoassign/pytorch/LICENSE | 0 cv/detection/autoassign/pytorch/README.md | 0 .../_base_/datasets/cityscapes_detection.py | 0 .../_base_/datasets/cityscapes_instance.py | 0 .../configs/_base_/datasets/coco_detection.py | 0 .../configs/_base_/datasets/coco_instance.py | 0 .../_base_/datasets/coco_instance_semantic.py | 0 .../configs/_base_/datasets/coco_panoptic.py | 0 .../configs/_base_/datasets/deepfashion.py | 0 .../_base_/datasets/lvis_v0.5_instance.py | 0 .../_base_/datasets/lvis_v1_instance.py | 0 .../_base_/datasets/openimages_detection.py | 0 .../configs/_base_/datasets/voc0712.py | 0 .../configs/_base_/datasets/wider_face.py | 0 .../pytorch/configs/_base_/default_runtime.py | 0 .../models/cascade_mask_rcnn_r50_fpn.py | 0 .../_base_/models/cascade_rcnn_r50_fpn.py | 0 .../_base_/models/fast_rcnn_r50_fpn.py | 0 .../_base_/models/faster_rcnn_r50_caffe_c4.py | 0 .../models/faster_rcnn_r50_caffe_dc5.py | 0 .../_base_/models/faster_rcnn_r50_fpn.py | 0 .../_base_/models/mask_rcnn_r50_caffe_c4.py | 0 .../_base_/models/mask_rcnn_r50_fpn.py | 0 .../_base_/models/retinanet_r50_fpn.py | 0 .../configs/_base_/models/rpn_r50_caffe_c4.py | 0 .../configs/_base_/models/rpn_r50_fpn.py | 0 .../pytorch/configs/_base_/models/ssd300.py | 0 .../configs/_base_/schedules/schedule_1x.py | 0 .../configs/_base_/schedules/schedule_20e.py | 0 .../configs/_base_/schedules/schedule_2x.py | 0 .../pytorch/configs/autoassign/README.md | 0 .../autoassign_r50_fpn_8x2_1x_coco.py | 0 .../pytorch/configs/autoassign/metafile.yml | 0 cv/detection/autoassign/pytorch/dist_train.sh | 0 .../autoassign/pytorch/docker/Dockerfile | 0 .../pytorch/docker/serve/Dockerfile | 0 .../pytorch/docker/serve/config.properties | 0 .../pytorch/docker/serve/entrypoint.sh | 0 .../autoassign/pytorch/mmcv/__init__.py | 0 .../autoassign/pytorch/mmcv/cnn/__init__.py | 0 .../autoassign/pytorch/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../pytorch/mmcv/cnn/bricks/norm.py | 0 .../pytorch/mmcv/cnn/bricks/padding.py | 0 .../pytorch/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/cnn/bricks/registry.py | 0 .../pytorch/mmcv/cnn/bricks/scale.py | 0 .../pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../autoassign/pytorch/mmcv/cnn/builder.py | 0 .../autoassign/pytorch/mmcv/cnn/resnet.py | 0 .../pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../autoassign/pytorch/mmcv/cnn/vgg.py | 0 .../pytorch/mmcv/engine/__init__.py | 0 .../autoassign/pytorch/mmcv/engine/test.py | 0 .../pytorch/mmcv/fileio/__init__.py | 0 .../pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../autoassign/pytorch/mmcv/fileio/io.py | 0 .../autoassign/pytorch/mmcv/fileio/parse.py | 0 .../autoassign/pytorch/mmcv/image/__init__.py | 0 .../pytorch/mmcv/image/colorspace.py | 0 .../pytorch/mmcv/image/geometric.py | 0 .../autoassign/pytorch/mmcv/image/io.py | 0 .../autoassign/pytorch/mmcv/image/misc.py | 0 .../pytorch/mmcv/image/photometric.py | 0 .../pytorch/mmcv/model_zoo/deprecated.json | 0 .../pytorch/mmcv/model_zoo/mmcls.json | 0 .../pytorch/mmcv/model_zoo/open_mmlab.json | 0 .../autoassign/pytorch/mmcv/ops/__init__.py | 0 .../pytorch/mmcv/ops/csrc/README.md | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../ops/csrc/common/cuda/nms_cuda_kernel.cuh | 0 .../ops/csrc/common/cuda/nms_rotated_cuda.cuh | 0 .../common/cuda/roi_align_cuda_kernel.cuh | 0 .../csrc/common/cuda/roi_pool_cuda_kernel.cuh | 0 .../cuda/sigmoid_focal_loss_cuda_kernel.cuh | 0 .../cuda/softmax_focal_loss_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../ops/csrc/pytorch/cuda/focal_loss_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_align_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_pool_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/focal_loss.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/nms.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../mmcv/ops/csrc/pytorch/roi_align.cpp | 0 .../mmcv/ops/csrc/pytorch/roi_align_cpu.cpp | 0 .../mmcv/ops/csrc/pytorch/roi_pool.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../pytorch/mmcv/ops/deprecated_wrappers.py | 0 .../autoassign/pytorch/mmcv/ops/focal_loss.py | 0 .../autoassign/pytorch/mmcv/ops/info.py | 0 .../autoassign/pytorch/mmcv/ops/nms.py | 0 .../pytorch/mmcv/ops/point_sample.py | 0 .../autoassign/pytorch/mmcv/ops/roi_align.py | 0 .../autoassign/pytorch/mmcv/ops/roi_pool.py | 0 .../autoassign/pytorch/mmcv/ops/sync_bn.py | 0 .../pytorch/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/parallel/_functions.py | 0 .../pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../autoassign/pytorch/mmcv/parallel/utils.py | 0 .../pytorch/mmcv/runner/__init__.py | 0 .../pytorch/mmcv/runner/base_module.py | 0 .../pytorch/mmcv/runner/base_runner.py | 0 .../autoassign/pytorch/mmcv/runner/builder.py | 0 .../pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../pytorch/mmcv/runner/priority.py | 0 .../autoassign/pytorch/mmcv/runner/utils.py | 0 .../autoassign/pytorch/mmcv/utils/__init__.py | 0 .../autoassign/pytorch/mmcv/utils/config.py | 0 .../autoassign/pytorch/mmcv/utils/env.py | 0 .../pytorch/mmcv/utils/ext_loader.py | 0 .../autoassign/pytorch/mmcv/utils/logging.py | 0 .../autoassign/pytorch/mmcv/utils/misc.py | 0 .../pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../autoassign/pytorch/mmcv/utils/path.py | 0 .../pytorch/mmcv/utils/progressbar.py | 0 .../autoassign/pytorch/mmcv/utils/registry.py | 0 .../autoassign/pytorch/mmcv/utils/testing.py | 0 .../autoassign/pytorch/mmcv/utils/timer.py | 0 .../autoassign/pytorch/mmcv/utils/trace.py | 0 .../pytorch/mmcv/utils/version_utils.py | 0 .../autoassign/pytorch/mmcv/version.py | 0 .../autoassign/pytorch/mmdet/__init__.py | 0 .../autoassign/pytorch/mmdet/apis/__init__.py | 0 .../pytorch/mmdet/apis/inference.py | 0 .../autoassign/pytorch/mmdet/apis/test.py | 0 .../autoassign/pytorch/mmdet/apis/train.py | 0 .../autoassign/pytorch/mmdet/core/__init__.py | 0 .../pytorch/mmdet/core/anchor/__init__.py | 0 .../mmdet/core/anchor/anchor_generator.py | 0 .../pytorch/mmdet/core/anchor/builder.py | 0 .../mmdet/core/anchor/point_generator.py | 0 .../pytorch/mmdet/core/anchor/utils.py | 0 .../pytorch/mmdet/core/bbox/__init__.py | 0 .../mmdet/core/bbox/assigners/__init__.py | 0 .../bbox/assigners/approx_max_iou_assigner.py | 0 .../core/bbox/assigners/assign_result.py | 0 .../core/bbox/assigners/atss_assigner.py | 0 .../core/bbox/assigners/base_assigner.py | 0 .../bbox/assigners/center_region_assigner.py | 0 .../core/bbox/assigners/grid_assigner.py | 0 .../core/bbox/assigners/hungarian_assigner.py | 0 .../bbox/assigners/mask_hungarian_assigner.py | 0 .../core/bbox/assigners/max_iou_assigner.py | 0 .../core/bbox/assigners/point_assigner.py | 0 .../core/bbox/assigners/region_assigner.py | 0 .../core/bbox/assigners/sim_ota_assigner.py | 0 .../bbox/assigners/task_aligned_assigner.py | 0 .../core/bbox/assigners/uniform_assigner.py | 0 .../pytorch/mmdet/core/bbox/builder.py | 0 .../pytorch/mmdet/core/bbox/coder/__init__.py | 0 .../mmdet/core/bbox/coder/base_bbox_coder.py | 0 .../core/bbox/coder/bucketing_bbox_coder.py | 0 .../core/bbox/coder/delta_xywh_bbox_coder.py | 0 .../bbox/coder/distance_point_bbox_coder.py | 0 .../coder/legacy_delta_xywh_bbox_coder.py | 0 .../core/bbox/coder/pseudo_bbox_coder.py | 0 .../mmdet/core/bbox/coder/tblr_bbox_coder.py | 0 .../mmdet/core/bbox/coder/yolo_bbox_coder.py | 0 .../pytorch/mmdet/core/bbox/demodata.py | 0 .../core/bbox/iou_calculators/__init__.py | 0 .../core/bbox/iou_calculators/builder.py | 0 .../bbox/iou_calculators/iou2d_calculator.py | 0 .../mmdet/core/bbox/match_costs/__init__.py | 0 .../mmdet/core/bbox/match_costs/builder.py | 0 .../mmdet/core/bbox/match_costs/match_cost.py | 0 .../mmdet/core/bbox/samplers/__init__.py | 0 .../mmdet/core/bbox/samplers/base_sampler.py | 0 .../core/bbox/samplers/combined_sampler.py | 0 .../samplers/instance_balanced_pos_sampler.py | 0 .../bbox/samplers/iou_balanced_neg_sampler.py | 0 .../core/bbox/samplers/mask_pseudo_sampler.py | 0 .../bbox/samplers/mask_sampling_result.py | 0 .../mmdet/core/bbox/samplers/ohem_sampler.py | 0 .../core/bbox/samplers/pseudo_sampler.py | 0 .../core/bbox/samplers/random_sampler.py | 0 .../core/bbox/samplers/sampling_result.py | 0 .../core/bbox/samplers/score_hlr_sampler.py | 0 .../pytorch/mmdet/core/bbox/transforms.py | 0 .../mmdet/core/data_structures/__init__.py | 0 .../core/data_structures/general_data.py | 0 .../core/data_structures/instance_data.py | 0 .../pytorch/mmdet/core/evaluation/__init__.py | 0 .../mmdet/core/evaluation/bbox_overlaps.py | 0 .../mmdet/core/evaluation/class_names.py | 0 .../mmdet/core/evaluation/eval_hooks.py | 0 .../pytorch/mmdet/core/evaluation/mean_ap.py | 0 .../mmdet/core/evaluation/panoptic_utils.py | 0 .../pytorch/mmdet/core/evaluation/recall.py | 0 .../pytorch/mmdet/core/export/__init__.py | 0 .../mmdet/core/export/model_wrappers.py | 0 .../pytorch/mmdet/core/export/onnx_helper.py | 0 .../pytorch/mmdet/core/export/pytorch2onnx.py | 0 .../pytorch/mmdet/core/hook/__init__.py | 0 .../pytorch/mmdet/core/hook/checkloss_hook.py | 0 .../autoassign/pytorch/mmdet/core/hook/ema.py | 0 .../mmdet/core/hook/memory_profiler_hook.py | 0 .../mmdet/core/hook/set_epoch_info_hook.py | 0 .../pytorch/mmdet/core/hook/sync_norm_hook.py | 0 .../mmdet/core/hook/sync_random_size_hook.py | 0 .../mmdet/core/hook/wandblogger_hook.py | 0 .../mmdet/core/hook/yolox_lrupdater_hook.py | 0 .../mmdet/core/hook/yolox_mode_switch_hook.py | 0 .../pytorch/mmdet/core/mask/__init__.py | 0 .../pytorch/mmdet/core/mask/mask_target.py | 0 .../pytorch/mmdet/core/mask/structures.py | 0 .../pytorch/mmdet/core/mask/utils.py | 0 .../pytorch/mmdet/core/optimizers/__init__.py | 0 .../pytorch/mmdet/core/optimizers/builder.py | 0 .../layer_decay_optimizer_constructor.py | 0 .../mmdet/core/post_processing/__init__.py | 0 .../mmdet/core/post_processing/bbox_nms.py | 0 .../mmdet/core/post_processing/matrix_nms.py | 0 .../mmdet/core/post_processing/merge_augs.py | 0 .../pytorch/mmdet/core/utils/__init__.py | 0 .../pytorch/mmdet/core/utils/dist_utils.py | 0 .../pytorch/mmdet/core/utils/misc.py | 0 .../mmdet/core/visualization/__init__.py | 0 .../pytorch/mmdet/core/visualization/image.py | 0 .../mmdet/core/visualization/palette.py | 0 .../pytorch/mmdet/datasets/__init__.py | 0 .../mmdet/datasets/api_wrappers/__init__.py | 0 .../mmdet/datasets/api_wrappers/coco_api.py | 0 .../api_wrappers/panoptic_evaluation.py | 0 .../pytorch/mmdet/datasets/builder.py | 0 .../autoassign/pytorch/mmdet/datasets/coco.py | 0 .../pytorch/mmdet/datasets/custom.py | 0 .../mmdet/datasets/dataset_wrappers.py | 0 .../mmdet/datasets/pipelines/__init__.py | 0 .../mmdet/datasets/pipelines/compose.py | 0 .../mmdet/datasets/pipelines/formating.py | 0 .../mmdet/datasets/pipelines/formatting.py | 0 .../mmdet/datasets/pipelines/loading.py | 0 .../mmdet/datasets/pipelines/test_time_aug.py | 0 .../mmdet/datasets/pipelines/transforms.py | 0 .../mmdet/datasets/samplers/__init__.py | 0 .../datasets/samplers/class_aware_sampler.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../mmdet/datasets/samplers/group_sampler.py | 0 .../datasets/samplers/infinite_sampler.py | 0 .../pytorch/mmdet/datasets/utils.py | 0 .../pytorch/mmdet/models/__init__.py | 0 .../mmdet/models/backbones/__init__.py | 0 .../pytorch/mmdet/models/backbones/resnet.py | 0 .../pytorch/mmdet/models/builder.py | 0 .../mmdet/models/dense_heads/__init__.py | 0 .../models/dense_heads/anchor_free_head.py | 0 .../mmdet/models/dense_heads/anchor_head.py | 0 .../mmdet/models/dense_heads/atss_head.py | 0 .../models/dense_heads/autoassign_head.py | 0 .../models/dense_heads/base_dense_head.py | 0 .../models/dense_heads/dense_test_mixins.py | 0 .../mmdet/models/dense_heads/fcos_head.py | 0 .../mmdet/models/dense_heads/paa_head.py | 0 .../mmdet/models/detectors/__init__.py | 0 .../mmdet/models/detectors/autoassign.py | 0 .../pytorch/mmdet/models/detectors/base.py | 0 .../mmdet/models/detectors/single_stage.py | 0 .../pytorch/mmdet/models/losses/__init__.py | 0 .../pytorch/mmdet/models/losses/accuracy.py | 0 .../mmdet/models/losses/cross_entropy_loss.py | 0 .../pytorch/mmdet/models/losses/focal_loss.py | 0 .../pytorch/mmdet/models/losses/iou_loss.py | 0 .../pytorch/mmdet/models/losses/utils.py | 0 .../pytorch/mmdet/models/necks/__init__.py | 0 .../pytorch/mmdet/models/necks/fpn.py | 0 .../pytorch/mmdet/models/utils/__init__.py | 0 .../mmdet/models/utils/brick_wrappers.py | 0 .../pytorch/mmdet/models/utils/builder.py | 0 .../mmdet/models/utils/ckpt_convert.py | 0 .../mmdet/models/utils/conv_upsample.py | 0 .../pytorch/mmdet/models/utils/csp_layer.py | 0 .../mmdet/models/utils/gaussian_target.py | 0 .../mmdet/models/utils/inverted_residual.py | 0 .../mmdet/models/utils/make_divisible.py | 0 .../pytorch/mmdet/models/utils/misc.py | 0 .../mmdet/models/utils/normed_predictor.py | 0 .../models/utils/panoptic_gt_processing.py | 0 .../mmdet/models/utils/point_sample.py | 0 .../mmdet/models/utils/positional_encoding.py | 0 .../pytorch/mmdet/models/utils/res_layer.py | 0 .../pytorch/mmdet/models/utils/se_layer.py | 0 .../pytorch/mmdet/utils/__init__.py | 0 .../pytorch/mmdet/utils/collect_env.py | 0 .../pytorch/mmdet/utils/compat_config.py | 0 .../pytorch/mmdet/utils/contextmanagers.py | 0 .../autoassign/pytorch/mmdet/utils/logger.py | 0 .../autoassign/pytorch/mmdet/utils/memory.py | 0 .../autoassign/pytorch/mmdet/utils/misc.py | 0 .../pytorch/mmdet/utils/profiling.py | 0 .../pytorch/mmdet/utils/replace_cfg_vals.py | 0 .../pytorch/mmdet/utils/setup_env.py | 0 .../pytorch/mmdet/utils/split_batch.py | 0 .../pytorch/mmdet/utils/util_distribution.py | 0 .../pytorch/mmdet/utils/util_mixins.py | 0 .../pytorch/mmdet/utils/util_random.py | 0 .../autoassign/pytorch/mmdet/version.py | 0 cv/detection/autoassign/pytorch/pytest.ini | 0 .../autoassign/pytorch/requirements.txt | 0 cv/detection/autoassign/pytorch/setup.py | 0 cv/detection/autoassign/pytorch/train.py | 0 .../src/lib/detectors/base_detector.py | 0 .../pytorch/src/lib/detectors/ctdet.py | 0 .../pytorch/src/lib/detectors/ddd.py | 0 .../pytorch/src/lib/detectors/exdet.py | 0 .../pytorch/src/lib/detectors/multi_pose.py | 0 .../centernet/pytorch/src/lib/opts.py | 0 .../pytorch/src/lib/trains/base_trainer.py | 0 .../centernet/pytorch/src/lib/trains/ctdet.py | 0 .../centernet/pytorch/src/lib/trains/ddd.py | 0 .../centernet/pytorch/src/lib/trains/exdet.py | 0 .../pytorch/src/lib/trains/multi_pose.py | 0 .../pytorch/src/lib/utils/__init__.py | 0 .../centernet/pytorch/src/lib/utils/image.py | 0 cv/detection/centernet/pytorch/src/main.py | 0 cv/detection/centernet/pytorch/src/test.py | 0 .../kitti_eval/evaluate_object_3d_offline | Bin .../centernet/pytorch/src/tools/reval.py | 0 cv/detection/fcos/pytorch/LICENSE | 0 cv/detection/fcos/pytorch/README.md | 0 .../e2e_faster_rcnn_R_101_FPN_1x_caffe2.yaml | 0 .../e2e_faster_rcnn_R_50_C4_1x_caffe2.yaml | 0 .../e2e_faster_rcnn_R_50_FPN_1x_caffe2.yaml | 0 ...faster_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml | 0 .../e2e_keypoint_rcnn_R_50_FPN_1x_caffe2.yaml | 0 .../e2e_mask_rcnn_R_101_FPN_1x_caffe2.yaml | 0 .../e2e_mask_rcnn_R_50_C4_1x_caffe2.yaml | 0 .../e2e_mask_rcnn_R_50_FPN_1x_caffe2.yaml | 0 ...cnn_X-152-32x8d-FPN-IN5k_1.44x_caffe2.yaml | 0 ...e_mask_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml | 0 ...e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml | 0 .../e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml | 0 .../configs/e2e_faster_rcnn_R_101_FPN_1x.yaml | 0 .../configs/e2e_faster_rcnn_R_50_C4_1x.yaml | 0 .../configs/e2e_faster_rcnn_R_50_FPN_1x.yaml | 0 .../e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml | 0 .../configs/e2e_faster_rcnn_fbnet.yaml | 0 .../configs/e2e_faster_rcnn_fbnet_600.yaml | 0 .../e2e_faster_rcnn_fbnet_chamv1a_600.yaml | 0 .../e2e_keypoint_rcnn_R_50_FPN_1x.yaml | 0 .../configs/e2e_mask_rcnn_R_101_FPN_1x.yaml | 0 .../configs/e2e_mask_rcnn_R_50_C4_1x.yaml | 0 .../configs/e2e_mask_rcnn_R_50_FPN_1x.yaml | 0 .../e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml | 0 .../pytorch/configs/e2e_mask_rcnn_fbnet.yaml | 0 .../configs/e2e_mask_rcnn_fbnet_600.yaml | 0 .../e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml | 0 ...2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml | 0 .../configs/fcos/fcos_R_101_FPN_2x.yaml | 0 .../configs/fcos/fcos_R_50_FPN_1x.yaml | 0 .../configs/fcos/fcos_X_101_32x8d_FPN_2x.yaml | 0 .../configs/fcos/fcos_X_101_64x4d_FPN_2x.yaml | 0 .../fcos/fcos_bn_bs16_MNV2_FPN_1x.yaml | 0 .../configs/fcos/fcos_imprv_R_101_FPN_1x.yaml | 0 .../configs/fcos/fcos_imprv_R_101_FPN_2x.yaml | 0 .../configs/fcos/fcos_imprv_R_50_FPN_1x.yaml | 0 .../fcos/fcos_imprv_X_101_32x8d_FPN_2x.yaml | 0 .../fcos/fcos_imprv_X_101_64x4d_FPN_2x.yaml | 0 .../fcos/fcos_imprv_dcnv2_R_101_FPN_1x.yaml | 0 .../fcos/fcos_imprv_dcnv2_R_101_FPN_2x.yaml | 0 .../fcos/fcos_imprv_dcnv2_R_50_FPN_1x.yaml | 0 .../fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml | 0 .../fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml | 0 .../fcos/fcos_syncbn_bs32_MNV2_FPN_1x.yaml | 0 .../fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml | 0 .../fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml | 0 .../fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml | 0 .../pytorch/configs/gn_baselines/README.md | 0 .../e2e_faster_rcnn_R_50_FPN_1x_gn.yaml | 0 ...e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml | 0 .../e2e_mask_rcnn_R_50_FPN_1x_gn.yaml | 0 ...e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml | 0 ...cratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml | 0 ...e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml | 0 .../scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml | 0 ...e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml | 0 .../e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml | 0 .../e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml | 0 .../e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml | 0 .../e2e_faster_rcnn_R_50_C4_quick.yaml | 0 .../e2e_faster_rcnn_R_50_FPN_quick.yaml | 0 ...e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml | 0 .../e2e_keypoint_rcnn_R_50_FPN_quick.yaml | 0 .../e2e_mask_rcnn_R_50_C4_quick.yaml | 0 .../e2e_mask_rcnn_R_50_FPN_quick.yaml | 0 .../e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml | 0 .../quick_schedules/rpn_R_50_C4_quick.yaml | 0 .../quick_schedules/rpn_R_50_FPN_quick.yaml | 0 .../retinanet/retinanet_R-101-FPN_1x.yaml | 0 .../retinanet/retinanet_R-101-FPN_P5_1x.yaml | 0 .../retinanet/retinanet_R-50-FPN_1x.yaml | 0 .../retinanet_R-50-FPN_1x_quick.yaml | 0 .../retinanet/retinanet_R-50-FPN_P5_1x.yaml | 0 .../retinanet_X_101_32x8d_FPN_1x.yaml | 0 .../pytorch/configs/rpn_R_101_FPN_1x.yaml | 0 .../fcos/pytorch/configs/rpn_R_50_C4_1x.yaml | 0 .../fcos/pytorch/configs/rpn_R_50_FPN_1x.yaml | 0 .../configs/rpn_X_101_32x8d_FPN_1x.yaml | 0 cv/detection/fcos/pytorch/demo/README.md | 0 .../demo/demo_e2e_mask_rcnn_R_50_FPN_1x.png | Bin .../demo_e2e_mask_rcnn_X_101_32x8d_FPN_1x.png | Bin cv/detection/fcos/pytorch/demo/fcos_demo.py | 0 .../demo/images/COCO_val2014_000000000885.jpg | Bin .../demo/images/COCO_val2014_000000001000.jpg | Bin .../demo/images/COCO_val2014_000000005477.jpg | Bin .../demo/images/COCO_val2014_000000007281.jpg | Bin .../demo/images/COCO_val2014_000000012639.jpg | Bin .../demo/images/COCO_val2014_000000033759.jpg | Bin .../demo/images/COCO_val2014_000000039769.jpg | Bin .../demo/images/COCO_val2014_000000050896.jpg | Bin .../demo/images/COCO_val2014_000000053505.jpg | Bin .../demo/images/COCO_val2014_000000128654.jpg | Bin .../demo/images/COCO_val2014_000000463842.jpg | Bin .../demo/images/COCO_val2014_000000479030.jpg | Bin cv/detection/fcos/pytorch/demo/predictor.py | 0 cv/detection/fcos/pytorch/demo/webcam.py | 0 cv/detection/fcos/pytorch/docker/Dockerfile | 0 .../pytorch/docker/docker-jupyter/Dockerfile | 0 .../docker-jupyter/jupyter_notebook_config.py | 0 cv/detection/fcos/pytorch/fcos/__init__.py | 0 cv/detection/fcos/pytorch/fcos/bin/fcos | 0 cv/detection/fcos/pytorch/fcos/configs | 1 - .../fcos/configs/fcos_R_101_FPN_2x.yaml | 28 + .../fcos/configs/fcos_R_50_FPN_1x.yaml | 35 + .../fcos/configs/fcos_X_101_32x8d_FPN_2x.yaml | 31 + .../fcos/configs/fcos_X_101_64x4d_FPN_2x.yaml | 31 + .../configs/fcos_bn_bs16_MNV2_FPN_1x.yaml | 30 + .../fcos/configs/fcos_imprv_R_101_FPN_1x.yaml | 38 + .../fcos/configs/fcos_imprv_R_101_FPN_2x.yaml | 38 + .../fcos/configs/fcos_imprv_R_50_FPN_1x.yaml | 39 + .../fcos_imprv_X_101_32x8d_FPN_2x.yaml | 41 + .../fcos_imprv_X_101_64x4d_FPN_2x.yaml | 41 + .../fcos_imprv_dcnv2_R_101_FPN_1x.yaml | 44 + .../fcos_imprv_dcnv2_R_101_FPN_2x.yaml | 44 + .../configs/fcos_imprv_dcnv2_R_50_FPN_1x.yaml | 44 + .../fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml | 46 + .../fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml | 53 + .../configs/fcos_syncbn_bs32_MNV2_FPN_1x.yaml | 30 + .../fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml | 30 + .../fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml | 30 + .../fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml | 30 + cv/detection/fcos/pytorch/fcos/fcos.py | 0 cv/detection/fcos/pytorch/fcos_core/README.md | 0 .../fcos/pytorch/fcos_core/__init__.py | 0 .../fcos/pytorch/fcos_core/config/__init__.py | 0 .../fcos/pytorch/fcos_core/config/defaults.py | 0 .../pytorch/fcos_core/config/paths_catalog.py | 0 .../fcos/pytorch/fcos_core/csrc/ROIAlign.h | 0 .../fcos/pytorch/fcos_core/csrc/ROIPool.h | 0 .../pytorch/fcos_core/csrc/SigmoidFocalLoss.h | 0 .../fcos_core/csrc/cpu/ROIAlign_cpu.cpp | 0 .../pytorch/fcos_core/csrc/cpu/nms_cpu.cpp | 0 .../fcos/pytorch/fcos_core/csrc/cpu/vision.h | 0 .../fcos_core/csrc/cuda/ROIAlign_cuda.cu | 0 .../fcos_core/csrc/cuda/ROIPool_cuda.cu | 0 .../csrc/cuda/SigmoidFocalLoss_cuda.cu | 0 .../fcos_core/csrc/cuda/deform_conv_cuda.cu | 0 .../csrc/cuda/deform_conv_kernel_cuda.cu | 0 .../fcos_core/csrc/cuda/deform_pool_cuda.cu | 0 .../csrc/cuda/deform_pool_kernel_cuda.cu | 0 .../pytorch/fcos_core/csrc/cuda/ml_nms.cu | 0 .../fcos/pytorch/fcos_core/csrc/cuda/nms.cu | 0 .../fcos/pytorch/fcos_core/csrc/cuda/vision.h | 0 .../fcos/pytorch/fcos_core/csrc/deform_conv.h | 0 .../fcos/pytorch/fcos_core/csrc/deform_pool.h | 0 .../fcos/pytorch/fcos_core/csrc/ml_nms.h | 0 .../fcos/pytorch/fcos_core/csrc/nms.h | 0 .../fcos/pytorch/fcos_core/csrc/vision.cpp | 0 .../fcos/pytorch/fcos_core/data/README.md | 0 .../fcos/pytorch/fcos_core/data/__init__.py | 0 .../fcos/pytorch/fcos_core/data/build.py | 0 .../pytorch/fcos_core/data/collate_batch.py | 0 .../fcos_core/data/datasets/__init__.py | 0 .../pytorch/fcos_core/data/datasets/coco.py | 0 .../fcos_core/data/datasets/concat_dataset.py | 0 .../data/datasets/evaluation/__init__.py | 0 .../data/datasets/evaluation/coco/__init__.py | 0 .../datasets/evaluation/coco/coco_eval.py | 0 .../data/datasets/evaluation/voc/__init__.py | 0 .../data/datasets/evaluation/voc/voc_eval.py | 0 .../fcos_core/data/datasets/list_dataset.py | 0 .../pytorch/fcos_core/data/datasets/voc.py | 0 .../fcos_core/data/samplers/__init__.py | 0 .../fcos_core/data/samplers/distributed.py | 0 .../data/samplers/grouped_batch_sampler.py | 0 .../samplers/iteration_based_batch_sampler.py | 0 .../fcos_core/data/transforms/__init__.py | 0 .../fcos_core/data/transforms/build.py | 0 .../fcos_core/data/transforms/transforms.py | 0 .../fcos/pytorch/fcos_core/engine/__init__.py | 0 .../fcos/pytorch/fcos_core/engine/bbox_aug.py | 0 .../pytorch/fcos_core/engine/inference.py | 0 .../fcos/pytorch/fcos_core/engine/trainer.py | 0 .../fcos/pytorch/fcos_core/layers/__init__.py | 0 .../fcos/pytorch/fcos_core/layers/_utils.py | 0 .../pytorch/fcos_core/layers/batch_norm.py | 0 .../pytorch/fcos_core/layers/dcn/__init__.py | 0 .../fcos_core/layers/dcn/deform_conv_func.py | 0 .../layers/dcn/deform_conv_module.py | 0 .../fcos_core/layers/dcn/deform_pool_func.py | 0 .../layers/dcn/deform_pool_module.py | 0 .../fcos/pytorch/fcos_core/layers/iou_loss.py | 0 .../fcos/pytorch/fcos_core/layers/misc.py | 0 .../fcos/pytorch/fcos_core/layers/nms.py | 0 .../pytorch/fcos_core/layers/roi_align.py | 0 .../fcos/pytorch/fcos_core/layers/roi_pool.py | 0 .../fcos/pytorch/fcos_core/layers/scale.py | 0 .../fcos_core/layers/sigmoid_focal_loss.py | 0 .../fcos_core/layers/smooth_l1_loss.py | 0 .../pytorch/fcos_core/modeling/__init__.py | 0 .../fcos_core/modeling/backbone/__init__.py | 0 .../fcos_core/modeling/backbone/backbone.py | 0 .../fcos_core/modeling/backbone/fbnet.py | 0 .../modeling/backbone/fbnet_builder.py | 0 .../modeling/backbone/fbnet_modeldef.py | 0 .../fcos_core/modeling/backbone/fpn.py | 0 .../fcos_core/modeling/backbone/mobilenet.py | 0 .../fcos_core/modeling/backbone/resnet.py | 0 .../balanced_positive_negative_sampler.py | 0 .../pytorch/fcos_core/modeling/box_coder.py | 0 .../fcos_core/modeling/detector/__init__.py | 0 .../fcos_core/modeling/detector/detectors.py | 0 .../modeling/detector/generalized_rcnn.py | 0 .../pytorch/fcos_core/modeling/make_layers.py | 0 .../pytorch/fcos_core/modeling/matcher.py | 0 .../pytorch/fcos_core/modeling/poolers.py | 0 .../pytorch/fcos_core/modeling/registry.py | 0 .../fcos_core/modeling/roi_heads/__init__.py | 0 .../modeling/roi_heads/box_head/__init__.py | 0 .../modeling/roi_heads/box_head/box_head.py | 0 .../modeling/roi_heads/box_head/inference.py | 0 .../modeling/roi_heads/box_head/loss.py | 0 .../box_head/roi_box_feature_extractors.py | 0 .../roi_heads/box_head/roi_box_predictors.py | 0 .../roi_heads/keypoint_head/__init__.py | 0 .../roi_heads/keypoint_head/inference.py | 0 .../roi_heads/keypoint_head/keypoint_head.py | 0 .../modeling/roi_heads/keypoint_head/loss.py | 0 .../roi_keypoint_feature_extractors.py | 0 .../keypoint_head/roi_keypoint_predictors.py | 0 .../modeling/roi_heads/mask_head/__init__.py | 0 .../modeling/roi_heads/mask_head/inference.py | 0 .../modeling/roi_heads/mask_head/loss.py | 0 .../modeling/roi_heads/mask_head/mask_head.py | 0 .../mask_head/roi_mask_feature_extractors.py | 0 .../mask_head/roi_mask_predictors.py | 0 .../fcos_core/modeling/roi_heads/roi_heads.py | 0 .../fcos_core/modeling/rpn/__init__.py | 0 .../modeling/rpn/anchor_generator.py | 0 .../fcos_core/modeling/rpn/fcos/__init__.py | 0 .../fcos_core/modeling/rpn/fcos/fcos.py | 0 .../fcos_core/modeling/rpn/fcos/inference.py | 0 .../fcos_core/modeling/rpn/fcos/loss.py | 0 .../fcos_core/modeling/rpn/inference.py | 0 .../pytorch/fcos_core/modeling/rpn/loss.py | 0 .../modeling/rpn/retinanet/__init__.py | 0 .../modeling/rpn/retinanet/inference.py | 0 .../fcos_core/modeling/rpn/retinanet/loss.py | 0 .../modeling/rpn/retinanet/retinanet.py | 0 .../pytorch/fcos_core/modeling/rpn/rpn.py | 0 .../pytorch/fcos_core/modeling/rpn/utils.py | 0 .../fcos/pytorch/fcos_core/modeling/utils.py | 0 .../fcos/pytorch/fcos_core/solver/__init__.py | 0 .../fcos/pytorch/fcos_core/solver/build.py | 0 .../pytorch/fcos_core/solver/lr_scheduler.py | 0 .../pytorch/fcos_core/structures/__init__.py | 0 .../fcos_core/structures/bounding_box.py | 0 .../fcos_core/structures/boxlist_ops.py | 0 .../fcos_core/structures/image_list.py | 0 .../pytorch/fcos_core/structures/keypoint.py | 0 .../fcos_core/structures/segmentation_mask.py | 0 .../fcos/pytorch/fcos_core/utils/README.md | 0 .../fcos/pytorch/fcos_core/utils/__init__.py | 0 .../fcos_core/utils/c2_model_loading.py | 0 .../pytorch/fcos_core/utils/checkpoint.py | 0 .../pytorch/fcos_core/utils/collect_env.py | 0 .../fcos/pytorch/fcos_core/utils/comm.py | 0 .../fcos/pytorch/fcos_core/utils/cv2_util.py | 0 .../fcos/pytorch/fcos_core/utils/env.py | 0 .../fcos/pytorch/fcos_core/utils/imports.py | 0 .../fcos/pytorch/fcos_core/utils/logger.py | 0 .../pytorch/fcos_core/utils/metric_logger.py | 0 .../pytorch/fcos_core/utils/miscellaneous.py | 0 .../fcos_core/utils/model_serialization.py | 0 .../fcos/pytorch/fcos_core/utils/model_zoo.py | 0 .../fcos/pytorch/fcos_core/utils/registry.py | 0 .../fcos/pytorch/fcos_core/utils/timer.py | 0 .../fcos/pytorch/onnx/export_model_to_onnx.py | 0 .../fcos/pytorch/onnx/test_fcos_onnx_model.py | 0 cv/detection/fcos/pytorch/requirements.txt | 0 cv/detection/fcos/pytorch/setup.py | 0 cv/detection/fcos/pytorch/tests/checkpoint.py | 0 .../fcos/pytorch/tests/env_tests/env.py | 0 .../fcos/pytorch/tests/test_backbones.py | 0 .../fcos/pytorch/tests/test_box_coder.py | 0 .../fcos/pytorch/tests/test_configs.py | 0 .../fcos/pytorch/tests/test_data_samplers.py | 0 .../fcos/pytorch/tests/test_detectors.py | 0 cv/detection/fcos/pytorch/tests/test_fbnet.py | 0 .../pytorch/tests/test_feature_extractors.py | 0 .../fcos/pytorch/tests/test_metric_logger.py | 0 cv/detection/fcos/pytorch/tests/test_nms.py | 0 .../fcos/pytorch/tests/test_predictors.py | 0 .../fcos/pytorch/tests/test_rpn_heads.py | 0 .../pytorch/tests/test_segmentation_mask.py | 0 cv/detection/fcos/pytorch/tests/utils.py | 0 .../cityscapes/convert_cityscapes_to_coco.py | 0 .../instances2dict_with_polygons.py | 0 .../pytorch/tools/remove_solver_states.py | 0 cv/detection/fcos/pytorch/tools/test_net.py | 0 cv/detection/fcos/pytorch/tools/train_net.py | 0 cv/detection/pvanet/pytorch/README.md | 0 cv/detection/pvanet/pytorch/__init__.py | 0 cv/detection/pvanet/pytorch/_utils.py | 0 cv/detection/pvanet/pytorch/coco_eval.py | 0 .../pvanet/pytorch/common_utils/__init__.py | 0 .../pvanet/pytorch/common_utils/dist.py | 0 .../pytorch/common_utils/metric_logger.py | 0 .../pvanet/pytorch/common_utils/misc.py | 0 .../pytorch/common_utils/smooth_value.py | 0 .../pvanet/pytorch/dataloader/__init__.py | 0 .../pvanet/pytorch/dataloader/detection.py | 0 .../pytorch/dataloader/utils/__init__.py | 0 .../pytorch/dataloader/utils/coco_utils.py | 0 .../pytorch/dataloader/utils/functional.py | 0 .../dataloader/utils/functional_pil.py | 0 .../dataloader/utils/functional_tensor.py | 0 .../pytorch/dataloader/utils/pascal_voc.py | 0 .../dataloader/utils/presets_detection.py | 0 .../dataloader/utils/presets_segmentation.py | 0 .../dataloader/utils/transforms_det.py | 0 cv/detection/pvanet/pytorch/engine.py | 0 .../pvanet/pytorch/group_by_aspect_ratio.py | 0 cv/detection/pvanet/pytorch/model/__init__.py | 0 cv/detection/pvanet/pytorch/model/_utils.py | 0 .../pvanet/pytorch/model/anchor_utils.py | 0 .../pvanet/pytorch/model/det_utils.py | 0 .../pvanet/pytorch/model/generalized_rcnn.py | 0 .../pvanet/pytorch/model/image_list.py | 0 .../pvanet/pytorch/model/model_main.py | 0 .../pvanet/pytorch/model/model_utils.py | 0 .../pvanet/pytorch/model/ops/__init__.py | 0 .../pvanet/pytorch/model/ops/_box_convert.py | 0 cv/detection/pvanet/pytorch/model/ops/_ops.py | 0 .../pvanet/pytorch/model/ops/_utils.py | 0 .../pvanet/pytorch/model/ops/boxes.py | 0 .../model/ops/feature_pyramid_network.py | 0 .../pvanet/pytorch/model/ops/focal_loss.py | 0 cv/detection/pvanet/pytorch/model/ops/misc.py | 0 .../pvanet/pytorch/model/ops/poolers.py | 0 .../pvanet/pytorch/model/ops/roi_align.py | 0 .../pvanet/pytorch/model/ops/roi_pool.py | 0 .../pytorch/model/ops/smooth_l1_loss.py | 0 cv/detection/pvanet/pytorch/model/pvanet.py | 0 .../pvanet/pytorch/model/roi_heads.py | 0 cv/detection/pvanet/pytorch/model/rpn.py | 0 .../pvanet/pytorch/model/transform.py | 0 .../pvanet/pytorch/model/weight_init.py | 0 cv/detection/pvanet/pytorch/train.py | 0 .../pvanet/pytorch/train_pvanet_dist.sh | 0 cv/detection/ssd/MindSpore/Dockerfile | 0 cv/detection/ssd/MindSpore/README.md | 0 .../MindSpore/ascend310_infer/CMakeLists.txt | 0 .../ssd/MindSpore/ascend310_infer/aipp.cfg | 0 .../ssd/MindSpore/ascend310_infer/build.sh | 0 .../ssd/MindSpore/ascend310_infer/inc/utils.h | 0 .../ssd/MindSpore/ascend310_infer/src/main.cc | 0 .../MindSpore/ascend310_infer/src/utils.cc | 0 .../ssd/MindSpore/config/ssd300_config.yaml | 0 .../MindSpore/config/ssd300_config_gpu.yaml | 0 .../ssd_mobilenet_v1_300_config_gpu.yaml | 0 .../config/ssd_mobilenet_v1_fpn_config.yaml | 0 .../ssd_mobilenet_v1_fpn_config_gpu.yaml | 0 .../config/ssd_resnet50_fpn_config.yaml | 0 .../config/ssd_resnet50_fpn_config_gpu.yaml | 0 .../MindSpore/config/ssd_vgg16_config.yaml | 0 .../config/ssd_vgg16_config_gpu.yaml | 0 cv/detection/ssd/MindSpore/eval.py | 0 cv/detection/ssd/MindSpore/eval_onnx.py | 0 cv/detection/ssd/MindSpore/export.py | 0 .../ssd/MindSpore/mindspore_hub_conf.py | 0 cv/detection/ssd/MindSpore/postprocess.py | 0 cv/detection/ssd/MindSpore/requirements.txt | 0 .../MindSpore/scripts/run_distribute_train.sh | 0 .../scripts/run_distribute_train_gpu.sh | 0 .../ssd/MindSpore/scripts/run_eval.sh | 0 .../ssd/MindSpore/scripts/run_eval_gpu.sh | 0 .../ssd/MindSpore/scripts/run_eval_onnx.sh | 0 .../ssd/MindSpore/scripts/run_infer_310.sh | 0 .../MindSpore/scripts/run_standalone_train.sh | 0 .../scripts/run_standalone_train_gpu.sh | 0 cv/detection/ssd/MindSpore/src/__init__.py | 0 .../ssd/MindSpore/src/anchor_generator.py | 0 cv/detection/ssd/MindSpore/src/box_utils.py | 0 cv/detection/ssd/MindSpore/src/dataset.py | 0 .../ssd/MindSpore/src/eval_callback.py | 0 cv/detection/ssd/MindSpore/src/eval_utils.py | 0 cv/detection/ssd/MindSpore/src/fpn.py | 0 cv/detection/ssd/MindSpore/src/init_params.py | 0 cv/detection/ssd/MindSpore/src/lr_schedule.py | 0 .../ssd/MindSpore/src/mobilenet_v1.py | 0 .../ssd/MindSpore/src/model_utils/config.py | 0 .../src/model_utils/device_adapter.py | 0 .../src/model_utils/local_adapter.py | 0 .../src/model_utils/moxing_adapter.py | 0 cv/detection/ssd/MindSpore/src/resnet.py | 0 cv/detection/ssd/MindSpore/src/ssd.py | 0 cv/detection/ssd/MindSpore/src/vgg16.py | 0 cv/detection/ssd/MindSpore/train.py | 0 cv/detection/yolof/pytorch/.gitignore | 0 cv/detection/yolof/pytorch/LICENSE | 0 cv/detection/yolof/pytorch/README.md | 0 .../configs/_base_/datasets/coco_detection.py | 0 .../pytorch/configs/_base_/default_runtime.py | 0 .../configs/_base_/schedules/schedule_1x.py | 0 .../yolof/pytorch/configs/yolof/README.md | 0 .../yolof/pytorch/configs/yolof/metafile.yml | 0 .../configs/yolof/yolof_r50_c5_8x8_1x_coco.py | 0 .../yolof/yolof_r50_c5_8x8_iter-1x_coco.py | 0 cv/detection/yolof/pytorch/mmcv/__init__.py | 0 .../yolof/pytorch/mmcv/cnn/__init__.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/conv.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/norm.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/padding.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/plugin.py | 0 .../yolof/pytorch/mmcv/cnn/bricks/registry.py | 0 .../yolof/pytorch/mmcv/cnn/builder.py | 0 cv/detection/yolof/pytorch/mmcv/cnn/resnet.py | 0 .../yolof/pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../yolof/pytorch/mmcv/engine/__init__.py | 0 .../yolof/pytorch/mmcv/engine/test.py | 0 .../yolof/pytorch/mmcv/fileio/__init__.py | 0 .../yolof/pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 cv/detection/yolof/pytorch/mmcv/fileio/io.py | 0 .../yolof/pytorch/mmcv/fileio/parse.py | 0 .../yolof/pytorch/mmcv/image/__init__.py | 0 .../yolof/pytorch/mmcv/image/colorspace.py | 0 .../yolof/pytorch/mmcv/image/geometric.py | 0 cv/detection/yolof/pytorch/mmcv/image/io.py | 0 cv/detection/yolof/pytorch/mmcv/image/misc.py | 0 .../yolof/pytorch/mmcv/image/photometric.py | 0 .../pytorch/mmcv/model_zoo/deprecated.json | 0 .../yolof/pytorch/mmcv/model_zoo/mmcls.json | 0 .../yolof/pytorch/mmcv/ops/__init__.py | 0 .../yolof/pytorch/mmcv/ops/csrc/README.md | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../ops/csrc/common/cuda/nms_cuda_kernel.cuh | 0 .../cuda/sigmoid_focal_loss_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../ops/csrc/pytorch/cuda/focal_loss_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/focal_loss.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/nms.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../yolof/pytorch/mmcv/ops/focal_loss.py | 0 cv/detection/yolof/pytorch/mmcv/ops/info.py | 0 cv/detection/yolof/pytorch/mmcv/ops/nms.py | 0 .../yolof/pytorch/mmcv/parallel/__init__.py | 0 .../yolof/pytorch/mmcv/parallel/_functions.py | 0 .../yolof/pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../yolof/pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../yolof/pytorch/mmcv/parallel/utils.py | 0 .../yolof/pytorch/mmcv/runner/__init__.py | 0 .../yolof/pytorch/mmcv/runner/base_module.py | 0 .../yolof/pytorch/mmcv/runner/base_runner.py | 0 .../yolof/pytorch/mmcv/runner/builder.py | 0 .../yolof/pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../yolof/pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../yolof/pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../yolof/pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../yolof/pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../yolof/pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../yolof/pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../yolof/pytorch/mmcv/runner/priority.py | 0 .../yolof/pytorch/mmcv/runner/utils.py | 0 .../yolof/pytorch/mmcv/utils/__init__.py | 0 .../yolof/pytorch/mmcv/utils/config.py | 0 .../yolof/pytorch/mmcv/utils/ext_loader.py | 0 .../yolof/pytorch/mmcv/utils/logging.py | 0 cv/detection/yolof/pytorch/mmcv/utils/misc.py | 0 cv/detection/yolof/pytorch/mmcv/utils/path.py | 0 .../yolof/pytorch/mmcv/utils/progressbar.py | 0 .../yolof/pytorch/mmcv/utils/registry.py | 0 .../yolof/pytorch/mmcv/utils/testing.py | 0 .../yolof/pytorch/mmcv/utils/timer.py | 0 .../yolof/pytorch/mmcv/utils/version_utils.py | 0 cv/detection/yolof/pytorch/mmcv/version.py | 0 cv/detection/yolof/pytorch/mmdet/__init__.py | 0 .../yolof/pytorch/mmdet/apis/__init__.py | 0 cv/detection/yolof/pytorch/mmdet/apis/test.py | 0 .../yolof/pytorch/mmdet/apis/train.py | 0 .../yolof/pytorch/mmdet/core/__init__.py | 0 .../pytorch/mmdet/core/anchor/__init__.py | 0 .../mmdet/core/anchor/anchor_generator.py | 0 .../pytorch/mmdet/core/anchor/builder.py | 0 .../yolof/pytorch/mmdet/core/anchor/utils.py | 0 .../yolof/pytorch/mmdet/core/bbox/__init__.py | 0 .../mmdet/core/bbox/assigners/__init__.py | 0 .../core/bbox/assigners/assign_result.py | 0 .../core/bbox/assigners/base_assigner.py | 0 .../core/bbox/assigners/uniform_assigner.py | 0 .../yolof/pytorch/mmdet/core/bbox/builder.py | 0 .../pytorch/mmdet/core/bbox/coder/__init__.py | 0 .../mmdet/core/bbox/coder/base_bbox_coder.py | 0 .../core/bbox/coder/delta_xywh_bbox_coder.py | 0 .../core/bbox/iou_calculators/__init__.py | 0 .../core/bbox/iou_calculators/builder.py | 0 .../bbox/iou_calculators/iou2d_calculator.py | 0 .../mmdet/core/bbox/samplers/__init__.py | 0 .../mmdet/core/bbox/samplers/base_sampler.py | 0 .../core/bbox/samplers/pseudo_sampler.py | 0 .../core/bbox/samplers/sampling_result.py | 0 .../pytorch/mmdet/core/bbox/transforms.py | 0 .../pytorch/mmdet/core/evaluation/__init__.py | 0 .../mmdet/core/evaluation/bbox_overlaps.py | 0 .../mmdet/core/evaluation/class_names.py | 0 .../mmdet/core/evaluation/eval_hooks.py | 0 .../pytorch/mmdet/core/evaluation/mean_ap.py | 0 .../mmdet/core/evaluation/panoptic_utils.py | 0 .../pytorch/mmdet/core/evaluation/recall.py | 0 .../pytorch/mmdet/core/optimizers/__init__.py | 0 .../pytorch/mmdet/core/optimizers/builder.py | 0 .../layer_decay_optimizer_constructor.py | 0 .../mmdet/core/post_processing/__init__.py | 0 .../mmdet/core/post_processing/bbox_nms.py | 0 .../mmdet/core/post_processing/matrix_nms.py | 0 .../mmdet/core/post_processing/merge_augs.py | 0 .../pytorch/mmdet/core/utils/__init__.py | 0 .../pytorch/mmdet/core/utils/dist_utils.py | 0 .../yolof/pytorch/mmdet/core/utils/misc.py | 0 .../yolof/pytorch/mmdet/datasets/__init__.py | 0 .../mmdet/datasets/api_wrappers/__init__.py | 0 .../mmdet/datasets/api_wrappers/coco_api.py | 0 .../api_wrappers/panoptic_evaluation.py | 0 .../yolof/pytorch/mmdet/datasets/builder.py | 0 .../yolof/pytorch/mmdet/datasets/coco.py | 0 .../yolof/pytorch/mmdet/datasets/custom.py | 0 .../mmdet/datasets/dataset_wrappers.py | 0 .../mmdet/datasets/pipelines/__init__.py | 0 .../mmdet/datasets/pipelines/auto_augment.py | 0 .../mmdet/datasets/pipelines/compose.py | 0 .../mmdet/datasets/pipelines/formating.py | 0 .../mmdet/datasets/pipelines/formatting.py | 0 .../mmdet/datasets/pipelines/instaboost.py | 0 .../mmdet/datasets/pipelines/loading.py | 0 .../mmdet/datasets/pipelines/test_time_aug.py | 0 .../mmdet/datasets/pipelines/transforms.py | 0 .../mmdet/datasets/samplers/__init__.py | 0 .../datasets/samplers/class_aware_sampler.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../mmdet/datasets/samplers/group_sampler.py | 0 .../datasets/samplers/infinite_sampler.py | 0 .../yolof/pytorch/mmdet/datasets/utils.py | 0 .../yolof/pytorch/mmdet/models/__init__.py | 0 .../mmdet/models/backbones/__init__.py | 0 .../pytorch/mmdet/models/backbones/resnet.py | 0 .../yolof/pytorch/mmdet/models/builder.py | 0 .../mmdet/models/dense_heads/__init__.py | 0 .../mmdet/models/dense_heads/anchor_head.py | 0 .../models/dense_heads/base_dense_head.py | 0 .../models/dense_heads/dense_test_mixins.py | 0 .../mmdet/models/dense_heads/yolof_head.py | 0 .../mmdet/models/detectors/__init__.py | 0 .../pytorch/mmdet/models/detectors/base.py | 0 .../mmdet/models/detectors/single_stage.py | 0 .../pytorch/mmdet/models/detectors/yolof.py | 0 .../pytorch/mmdet/models/losses/__init__.py | 0 .../pytorch/mmdet/models/losses/accuracy.py | 0 .../pytorch/mmdet/models/losses/focal_loss.py | 0 .../pytorch/mmdet/models/losses/iou_loss.py | 0 .../pytorch/mmdet/models/losses/utils.py | 0 .../pytorch/mmdet/models/necks/__init__.py | 0 .../mmdet/models/necks/dilated_encoder.py | 0 .../pytorch/mmdet/models/utils/__init__.py | 0 .../pytorch/mmdet/models/utils/res_layer.py | 0 .../yolof/pytorch/mmdet/utils/__init__.py | 0 .../yolof/pytorch/mmdet/utils/collect_env.py | 0 .../pytorch/mmdet/utils/compat_config.py | 0 .../pytorch/mmdet/utils/contextmanagers.py | 0 .../yolof/pytorch/mmdet/utils/logger.py | 0 .../yolof/pytorch/mmdet/utils/memory.py | 0 .../yolof/pytorch/mmdet/utils/misc.py | 0 .../pytorch/mmdet/utils/replace_cfg_vals.py | 0 .../yolof/pytorch/mmdet/utils/setup_env.py | 0 .../yolof/pytorch/mmdet/utils/split_batch.py | 0 .../pytorch/mmdet/utils/util_distribution.py | 0 cv/detection/yolof/pytorch/mmdet/version.py | 0 cv/detection/yolof/pytorch/requirements.txt | 0 cv/detection/yolof/pytorch/setup.cfg | 0 cv/detection/yolof/pytorch/setup.py | 0 cv/detection/yolof/pytorch/train.py | 0 cv/detection/yolof/pytorch/train.sh | 0 cv/detection/yolof/pytorch/train_dist.sh | 0 cv/detection/yolov3/pytorch/README.md | 0 cv/detection/yolov3/pytorch/data/coco.names | 0 .../yolov3/pytorch/data/custom/classes.names | 0 .../pytorch/data/custom/images/train.jpg | Bin .../pytorch/data/custom/labels/train.txt | 0 .../yolov3/pytorch/data/custom/train.txt | 0 .../yolov3/pytorch/data/custom/valid.txt | 0 .../yolov3/pytorch/data/get_coco_dataset.sh | 0 cv/detection/yolov3/pytorch/data/voc.names | 0 .../yolov3/pytorch/data/voc/train.txt | 0 .../yolov3/pytorch/data/voc/valid.txt | 0 .../yolact/pytorch/external/DCNv2/make.sh | 0 cv/ocr/dbnet/pytorch/.gitignore | 0 cv/ocr/dbnet/pytorch/CITATION.cff | 0 cv/ocr/dbnet/pytorch/EGG-INFO/PKG-INFO | 0 cv/ocr/dbnet/pytorch/EGG-INFO/SOURCES.txt | 0 .../pytorch/EGG-INFO/dependency_links.txt | 0 cv/ocr/dbnet/pytorch/EGG-INFO/not-zip-safe | 0 cv/ocr/dbnet/pytorch/EGG-INFO/requires.txt | 0 cv/ocr/dbnet/pytorch/EGG-INFO/top_level.txt | 0 cv/ocr/dbnet/pytorch/LICENSE | 0 cv/ocr/dbnet/pytorch/README.md | 0 .../pytorch/configs/_base_/default_runtime.py | 0 .../configs/_base_/det_datasets/icdar2015.py | 0 .../det_models/dbnet_mobilenetv3_fpnc.py | 0 .../_base_/det_models/dbnet_r18_fpnc.py | 0 .../_base_/det_models/dbnet_r50dcnv2_fpnc.py | 0 .../_base_/det_pipelines/dbnet_pipeline.py | 0 .../_base_/schedules/schedule_adam_1200e.py | 0 .../_base_/schedules/schedule_sgd_1200e.py | 0 .../pytorch/configs/textdet/dbnet/README.md | 0 .../dbnet_mobilenetv3_fpnc_1200e_icdar2015.py | 0 .../dbnet/dbnet_r18_fpnc_1200e_icdar2015.py | 0 .../dbnet_r50dcnv2_fpnc_1200e_icdar2015.py | 0 .../configs/textdet/dbnet/metafile.yml | 0 cv/ocr/dbnet/pytorch/dbnet/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet/apis/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet/apis/inference.py | 0 cv/ocr/dbnet/pytorch/dbnet/apis/test.py | 0 cv/ocr/dbnet/pytorch/dbnet/apis/train.py | 0 cv/ocr/dbnet/pytorch/dbnet/apis/utils.py | 0 cv/ocr/dbnet/pytorch/dbnet/core/__init__.py | 0 .../pytorch/dbnet/core/evaluation/__init__.py | 0 .../pytorch/dbnet/core/evaluation/hmean.py | 0 .../dbnet/core/evaluation/hmean_ic13.py | 0 .../dbnet/core/evaluation/hmean_iou.py | 0 .../pytorch/dbnet/core/evaluation/utils.py | 0 cv/ocr/dbnet/pytorch/dbnet/core/mask.py | 0 cv/ocr/dbnet/pytorch/dbnet/core/visualize.py | 0 .../dbnet/pytorch/dbnet/datasets/__init__.py | 0 .../pytorch/dbnet/datasets/base_dataset.py | 0 .../dbnet/pytorch/dbnet/datasets/builder.py | 0 .../pytorch/dbnet/datasets/icdar_dataset.py | 0 .../dbnet/datasets/pipelines/__init__.py | 0 .../dbnet/datasets/pipelines/box_utils.py | 0 .../pytorch/dbnet/datasets/pipelines/crop.py | 0 .../pipelines/custom_format_bundle.py | 0 .../datasets/pipelines/dbnet_transforms.py | 0 .../dbnet/datasets/pipelines/loading.py | 0 .../pipelines/textdet_targets/__init__.py | 0 .../textdet_targets/base_textdet_targets.py | 0 .../textdet_targets/dbnet_targets.py | 0 .../datasets/pipelines/transform_wrappers.py | 0 .../dbnet/datasets/pipelines/transforms.py | 0 .../dbnet/datasets/text_det_dataset.py | 0 .../dbnet/datasets/uniform_concat_dataset.py | 0 .../pytorch/dbnet/datasets/utils/__init__.py | 0 .../pytorch/dbnet/datasets/utils/backend.py | 0 .../pytorch/dbnet/datasets/utils/loader.py | 0 .../pytorch/dbnet/datasets/utils/parser.py | 0 cv/ocr/dbnet/pytorch/dbnet/models/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet/models/builder.py | 0 .../pytorch/dbnet/models/common/__init__.py | 0 .../dbnet/models/common/backbones/__init__.py | 0 .../dbnet/models/common/backbones/unet.py | 0 .../dbnet/models/common/detectors/__init__.py | 0 .../models/common/detectors/single_stage.py | 0 .../dbnet/models/common/losses/__init__.py | 0 .../dbnet/models/common/losses/dice_loss.py | 0 .../dbnet/models/common/losses/focal_loss.py | 0 .../pytorch/dbnet/models/textdet/__init__.py | 0 .../models/textdet/dense_heads/__init__.py | 0 .../models/textdet/dense_heads/db_head.py | 0 .../models/textdet/dense_heads/head_mixin.py | 0 .../models/textdet/detectors/__init__.py | 0 .../dbnet/models/textdet/detectors/dbnet.py | 0 .../detectors/single_stage_text_detector.py | 0 .../textdet/detectors/text_detector_mixin.py | 0 .../dbnet/models/textdet/losses/__init__.py | 0 .../dbnet/models/textdet/losses/db_loss.py | 0 .../dbnet/models/textdet/necks/__init__.py | 0 .../dbnet/models/textdet/necks/fpn_cat.py | 0 .../models/textdet/postprocess/__init__.py | 0 .../textdet/postprocess/base_postprocessor.py | 0 .../textdet/postprocess/db_postprocessor.py | 0 .../dbnet/models/textdet/postprocess/utils.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/box_util.py | 0 .../pytorch/dbnet/utils/check_argument.py | 0 .../dbnet/pytorch/dbnet/utils/collect_env.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/fileio.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/lmdb_util.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/logger.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/model.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/ocr.py | 0 cv/ocr/dbnet/pytorch/dbnet/utils/setup_env.py | 0 .../dbnet/pytorch/dbnet/utils/string_util.py | 0 cv/ocr/dbnet/pytorch/dbnet/version.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/__init__.py | 0 .../pytorch/dbnet_cv/cnn/bricks/__init__.py | 0 .../pytorch/dbnet_cv/cnn/bricks/activation.py | 0 .../dbnet/pytorch/dbnet_cv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../dbnet_cv/cnn/bricks/conv_module.py | 0 .../dbnet/pytorch/dbnet_cv/cnn/bricks/drop.py | 0 .../pytorch/dbnet_cv/cnn/bricks/hsigmoid.py | 0 .../pytorch/dbnet_cv/cnn/bricks/hswish.py | 0 .../dbnet/pytorch/dbnet_cv/cnn/bricks/norm.py | 0 .../pytorch/dbnet_cv/cnn/bricks/padding.py | 0 .../pytorch/dbnet_cv/cnn/bricks/plugin.py | 0 .../pytorch/dbnet_cv/cnn/bricks/registry.py | 0 .../pytorch/dbnet_cv/cnn/bricks/upsample.py | 0 .../pytorch/dbnet_cv/cnn/bricks/wrappers.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/builder.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/resnet.py | 0 .../pytorch/dbnet_cv/cnn/utils/__init__.py | 0 .../dbnet_cv/cnn/utils/flops_counter.py | 0 .../dbnet_cv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/dbnet_cv/cnn/utils/sync_bn.py | 0 .../pytorch/dbnet_cv/cnn/utils/weight_init.py | 0 .../dbnet/pytorch/dbnet_cv/engine/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/engine/test.py | 0 .../dbnet/pytorch/dbnet_cv/fileio/__init__.py | 0 .../pytorch/dbnet_cv/fileio/file_client.py | 0 .../dbnet_cv/fileio/handlers/__init__.py | 0 .../pytorch/dbnet_cv/fileio/handlers/base.py | 0 .../dbnet_cv/fileio/handlers/json_handler.py | 0 .../fileio/handlers/pickle_handler.py | 0 .../dbnet_cv/fileio/handlers/yaml_handler.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/io.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/parse.py | 0 .../dbnet/pytorch/dbnet_cv/image/__init__.py | 0 .../pytorch/dbnet_cv/image/colorspace.py | 0 .../dbnet/pytorch/dbnet_cv/image/geometric.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/image/io.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/image/misc.py | 0 .../pytorch/dbnet_cv/image/photometric.py | 0 .../dbnet_cv/model_zoo/deprecated.json | 0 .../pytorch/dbnet_cv/model_zoo/mmcls.json | 0 .../dbnet_cv/model_zoo/open_mmlab.json | 0 .../dbnet_cv/model_zoo/torchvision_0.12.json | 0 cv/ocr/dbnet/pytorch/dbnet_cv/ops/__init__.py | 0 .../dbnet/pytorch/dbnet_cv/ops/csrc/README.md | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../common/cuda/deform_conv_cuda_kernel.cuh | 0 .../cuda/deform_roi_pool_cuda_kernel.cuh | 0 .../modulated_deform_conv_cuda_kernel.cuh | 0 .../cuda/ms_deform_attn_cuda_kernel.cuh | 0 .../common/cuda/roi_align_cuda_kernel.cuh | 0 .../csrc/common/cuda/roi_pool_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../csrc/common/pytorch_device_registry.hpp | 0 .../ops/csrc/pytorch/cuda/cudabind.cpp | 0 .../ops/csrc/pytorch/cuda/deform_conv_cuda.cu | 0 .../csrc/pytorch/cuda/deform_roi_pool_cuda.cu | 0 .../cuda/modulated_deform_conv_cuda.cu | 0 .../csrc/pytorch/cuda/ms_deform_attn_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_align_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_pool_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../dbnet_cv/ops/csrc/pytorch/deform_conv.cpp | 0 .../ops/csrc/pytorch/deform_roi_pool.cpp | 0 .../dbnet_cv/ops/csrc/pytorch/info.cpp | 0 .../csrc/pytorch/modulated_deform_conv.cpp | 0 .../ops/csrc/pytorch/ms_deform_attn.cpp | 0 .../dbnet_cv/ops/csrc/pytorch/pybind.cpp | 0 .../dbnet_cv/ops/csrc/pytorch/roi_align.cpp | 0 .../dbnet_cv/ops/csrc/pytorch/roi_pool.cpp | 0 .../dbnet_cv/ops/csrc/pytorch/sync_bn.cpp | 0 .../dbnet/pytorch/dbnet_cv/ops/deform_conv.py | 0 .../pytorch/dbnet_cv/ops/deform_roi_pool.py | 0 .../dbnet_cv/ops/deprecated_wrappers.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/ops/info.py | 0 .../dbnet_cv/ops/modulated_deform_conv.py | 0 .../dbnet_cv/ops/multi_scale_deform_attn.py | 0 .../dbnet/pytorch/dbnet_cv/ops/roi_align.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_pool.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/ops/sync_bn.py | 0 .../pytorch/dbnet_cv/parallel/__init__.py | 0 .../pytorch/dbnet_cv/parallel/_functions.py | 0 .../pytorch/dbnet_cv/parallel/collate.py | 0 .../dbnet_cv/parallel/data_container.py | 0 .../dbnet_cv/parallel/data_parallel.py | 0 .../pytorch/dbnet_cv/parallel/distributed.py | 0 .../parallel/distributed_deprecated.py | 0 .../pytorch/dbnet_cv/parallel/registry.py | 0 .../dbnet_cv/parallel/scatter_gather.py | 0 .../dbnet/pytorch/dbnet_cv/parallel/utils.py | 0 .../dbnet/pytorch/dbnet_cv/runner/__init__.py | 0 .../pytorch/dbnet_cv/runner/base_module.py | 0 .../pytorch/dbnet_cv/runner/base_runner.py | 0 .../dbnet/pytorch/dbnet_cv/runner/builder.py | 0 .../pytorch/dbnet_cv/runner/checkpoint.py | 0 .../dbnet_cv/runner/default_constructor.py | 0 .../pytorch/dbnet_cv/runner/dist_utils.py | 0 .../dbnet_cv/runner/epoch_based_runner.py | 0 .../pytorch/dbnet_cv/runner/fp16_utils.py | 0 .../pytorch/dbnet_cv/runner/hooks/__init__.py | 0 .../dbnet_cv/runner/hooks/checkpoint.py | 0 .../pytorch/dbnet_cv/runner/hooks/closure.py | 0 .../pytorch/dbnet_cv/runner/hooks/ema.py | 0 .../dbnet_cv/runner/hooks/evaluation.py | 0 .../pytorch/dbnet_cv/runner/hooks/hook.py | 0 .../dbnet_cv/runner/hooks/iter_timer.py | 0 .../dbnet_cv/runner/hooks/logger/__init__.py | 0 .../dbnet_cv/runner/hooks/logger/base.py | 0 .../dbnet_cv/runner/hooks/logger/clearml.py | 0 .../dbnet_cv/runner/hooks/logger/dvclive.py | 0 .../dbnet_cv/runner/hooks/logger/mlflow.py | 0 .../dbnet_cv/runner/hooks/logger/neptune.py | 0 .../dbnet_cv/runner/hooks/logger/pavi.py | 0 .../dbnet_cv/runner/hooks/logger/segmind.py | 0 .../runner/hooks/logger/tensorboard.py | 0 .../dbnet_cv/runner/hooks/logger/text.py | 0 .../dbnet_cv/runner/hooks/logger/wandb.py | 0 .../dbnet_cv/runner/hooks/lr_updater.py | 0 .../pytorch/dbnet_cv/runner/hooks/memory.py | 0 .../dbnet_cv/runner/hooks/momentum_updater.py | 0 .../dbnet_cv/runner/hooks/optimizer.py | 0 .../pytorch/dbnet_cv/runner/hooks/profiler.py | 0 .../dbnet_cv/runner/hooks/sampler_seed.py | 0 .../dbnet_cv/runner/hooks/sync_buffer.py | 0 .../dbnet_cv/runner/iter_based_runner.py | 0 .../pytorch/dbnet_cv/runner/log_buffer.py | 0 .../dbnet_cv/runner/optimizer/__init__.py | 0 .../dbnet_cv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../dbnet/pytorch/dbnet_cv/runner/priority.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/runner/utils.py | 0 .../dbnet/pytorch/dbnet_cv/utils/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/config.py | 0 .../pytorch/dbnet_cv/utils/device_type.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/env.py | 0 .../pytorch/dbnet_cv/utils/ext_loader.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/hub.py | 0 .../dbnet/pytorch/dbnet_cv/utils/logging.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/misc.py | 0 .../pytorch/dbnet_cv/utils/parrots_jit.py | 0 .../pytorch/dbnet_cv/utils/parrots_wrapper.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/path.py | 0 .../pytorch/dbnet_cv/utils/progressbar.py | 0 .../dbnet/pytorch/dbnet_cv/utils/registry.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/seed.py | 0 .../dbnet/pytorch/dbnet_cv/utils/testing.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/timer.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/utils/trace.py | 0 .../pytorch/dbnet_cv/utils/version_utils.py | 0 cv/ocr/dbnet/pytorch/dbnet_cv/version.py | 0 cv/ocr/dbnet/pytorch/dbnet_det/__init__.py | 0 .../dbnet/pytorch/dbnet_det/apis/__init__.py | 0 cv/ocr/dbnet/pytorch/dbnet_det/apis/test.py | 0 .../dbnet/pytorch/dbnet_det/core/__init__.py | 0 .../pytorch/dbnet_det/core/bbox/__init__.py | 0 .../pytorch/dbnet_det/core/bbox/transforms.py | 0 .../dbnet_det/core/evaluation/__init__.py | 0 .../core/evaluation/bbox_overlaps.py | 0 .../dbnet_det/core/evaluation/class_names.py | 0 .../dbnet_det/core/evaluation/eval_hooks.py | 0 .../dbnet_det/core/evaluation/mean_ap.py | 0 .../core/evaluation/panoptic_utils.py | 0 .../dbnet_det/core/evaluation/recall.py | 0 .../pytorch/dbnet_det/core/mask/__init__.py | 0 .../pytorch/dbnet_det/core/mask/structures.py | 0 .../pytorch/dbnet_det/core/mask/utils.py | 0 .../pytorch/dbnet_det/core/utils/__init__.py | 0 .../dbnet_det/core/utils/dist_utils.py | 0 .../pytorch/dbnet_det/core/utils/misc.py | 0 .../dbnet_det/core/visualization/__init__.py | 0 .../dbnet_det/core/visualization/image.py | 0 .../dbnet_det/core/visualization/palette.py | 0 .../pytorch/dbnet_det/datasets/__init__.py | 0 .../datasets/api_wrappers/__init__.py | 0 .../datasets/api_wrappers/coco_api.py | 0 .../api_wrappers/panoptic_evaluation.py | 0 .../pytorch/dbnet_det/datasets/builder.py | 0 .../dbnet/pytorch/dbnet_det/datasets/coco.py | 0 .../pytorch/dbnet_det/datasets/custom.py | 0 .../dbnet_det/datasets/dataset_wrappers.py | 0 .../dbnet_det/datasets/pipelines/__init__.py | 0 .../dbnet_det/datasets/pipelines/compose.py | 0 .../datasets/pipelines/formatting.py | 0 .../dbnet_det/datasets/pipelines/loading.py | 0 .../datasets/pipelines/test_time_aug.py | 0 .../datasets/pipelines/transforms.py | 0 .../dbnet_det/datasets/samplers/__init__.py | 0 .../datasets/samplers/class_aware_sampler.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/samplers/group_sampler.py | 0 .../datasets/samplers/infinite_sampler.py | 0 .../dbnet/pytorch/dbnet_det/datasets/utils.py | 0 .../pytorch/dbnet_det/models/__init__.py | 0 .../dbnet_det/models/backbones/__init__.py | 0 .../models/backbones/mobilenet_v3.py | 0 .../dbnet_det/models/backbones/resnet.py | 0 .../dbnet/pytorch/dbnet_det/models/builder.py | 0 .../dbnet_det/models/detectors/__init__.py | 0 .../dbnet_det/models/detectors/base.py | 0 .../models/detectors/single_stage.py | 0 .../dbnet_det/models/utils/__init__.py | 0 .../models/utils/inverted_residual.py | 0 .../dbnet_det/models/utils/make_divisible.py | 0 .../dbnet_det/models/utils/res_layer.py | 0 .../dbnet_det/models/utils/se_layer.py | 0 .../dbnet/pytorch/dbnet_det/utils/__init__.py | 0 .../dbnet_det/utils/inverted_residual.py | 0 .../dbnet/pytorch/dbnet_det/utils/logger.py | 0 .../pytorch/dbnet_det/utils/profiling.py | 0 .../dbnet_det/utils/util_distribution.py | 0 cv/ocr/dbnet/pytorch/dbnet_det/version.py | 0 cv/ocr/dbnet/pytorch/dist_train.sh | 0 cv/ocr/dbnet/pytorch/requirements.txt | 0 cv/ocr/dbnet/pytorch/setup.py | 0 cv/ocr/dbnet/pytorch/tools/analyze_logs.py | 0 .../pytorch/tools/benchmark_processing.py | 0 .../dbnet/pytorch/tools/misc/print_config.py | 0 cv/ocr/dbnet/pytorch/tools/publish_model.py | 0 cv/ocr/dbnet/pytorch/train.py | 0 cv/ocr/sar/pytorch/README.md | 0 cv/ocr/sar/pytorch/apis/__init__.py | 0 cv/ocr/sar/pytorch/apis/train.py | 0 cv/ocr/sar/pytorch/apis/utils.py | 0 cv/ocr/sar/pytorch/basic_utils/__init__.py | 0 cv/ocr/sar/pytorch/basic_utils/box_util.py | 0 .../sar/pytorch/basic_utils/check_argument.py | 0 .../pytorch/basic_utils/data_convert_util.py | 0 cv/ocr/sar/pytorch/basic_utils/env.py | 0 cv/ocr/sar/pytorch/basic_utils/fileio.py | 0 cv/ocr/sar/pytorch/basic_utils/img_util.py | 0 cv/ocr/sar/pytorch/basic_utils/lmdb_util.py | 0 cv/ocr/sar/pytorch/basic_utils/logger.py | 0 cv/ocr/sar/pytorch/basic_utils/model.py | 0 cv/ocr/sar/pytorch/basic_utils/setup_env.py | 0 cv/ocr/sar/pytorch/basic_utils/string_util.py | 0 .../configs/_base_/datasets/MJ_train.py | 0 .../datasets/ST_MJ_alphanumeric_train.py | 0 .../configs/_base_/datasets/ST_MJ_train.py | 0 .../_base_/datasets/ST_SA_MJ_real_train.py | 0 .../_base_/datasets/ST_charbox_train.py | 0 .../configs/_base_/datasets/Sample_test.py | 0 .../configs/_base_/datasets/Sample_train.py | 0 .../configs/_base_/datasets/academic_test.py | 0 .../configs/_base_/datasets/seg_toy_data.py | 0 .../configs/_base_/datasets/toy_data.py | 0 .../pytorch/configs/_base_/default_runtime.py | 0 .../sar/pytorch/configs/_base_/models/sar.py | 0 .../configs/_base_/pipelines/sar_pipeline.py | 0 .../sar/pytorch/configs/_base_/runtime_10e.py | 0 .../_base_/schedules/schedule_adadelta_18e.py | 0 .../_base_/schedules/schedule_adadelta_5e.py | 0 .../_base_/schedules/schedule_adam_600e.py | 0 .../schedules/schedule_adam_step_20e.py | 0 .../_base_/schedules/schedule_adam_step_5e.py | 0 .../schedules/schedule_adam_step_600e.py | 0 .../_base_/schedules/schedule_adam_step_6e.py | 0 .../_base_/schedules/schedule_sgd_1200e.py | 0 .../_base_/schedules/schedule_sgd_1500e.py | 0 .../_base_/schedules/schedule_sgd_160e.py | 0 .../_base_/schedules/schedule_sgd_600e.py | 0 cv/ocr/sar/pytorch/configs/metafile.yml | 0 .../sar_r31_parallel_decoder_academic.py | 0 .../sar_r31_sequential_decoder_academic.py | 0 cv/ocr/sar/pytorch/core/__init__.py | 0 .../sar/pytorch/core/evaluation/__init__.py | 0 .../sar/pytorch/core/evaluation/ocr_metric.py | 0 cv/ocr/sar/pytorch/core/evaluation/utils.py | 0 cv/ocr/sar/pytorch/core/mask.py | 0 cv/ocr/sar/pytorch/core/visualize.py | 0 cv/ocr/sar/pytorch/csrc/.gitignore | 0 cv/ocr/sar/pytorch/csrc/build.sh | 0 cv/ocr/sar/pytorch/csrc/clean.sh | 0 cv/ocr/sar/pytorch/csrc/install.sh | 0 cv/ocr/sar/pytorch/csrc/sar/__init__.py | 0 cv/ocr/sar/pytorch/csrc/sar/cnn/__init__.py | 0 .../pytorch/csrc/sar/cnn/bricks/__init__.py | 0 .../pytorch/csrc/sar/cnn/bricks/activation.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/conv.py | 0 .../sar/cnn/bricks/conv2d_adaptive_padding.py | 0 .../csrc/sar/cnn/bricks/conv_module.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/drop.py | 0 .../pytorch/csrc/sar/cnn/bricks/hsigmoid.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/hswish.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/norm.py | 0 .../pytorch/csrc/sar/cnn/bricks/padding.py | 0 .../pytorch/csrc/sar/cnn/bricks/registry.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/scale.py | 0 .../sar/pytorch/csrc/sar/cnn/bricks/swish.py | 0 .../csrc/sar/cnn/bricks/transformer.py | 0 .../pytorch/csrc/sar/cnn/bricks/wrappers.py | 0 cv/ocr/sar/pytorch/csrc/sar/cnn/builder.py | 0 .../pytorch/csrc/sar/cnn/utils/__init__.py | 0 .../csrc/sar/cnn/utils/fuse_conv_bn.py | 0 .../sar/pytorch/csrc/sar/cnn/utils/sync_bn.py | 0 .../pytorch/csrc/sar/cnn/utils/weight_init.py | 0 cv/ocr/sar/pytorch/csrc/sar/ops/__init__.py | 0 .../csrc/sar/ops/assign_score_withk.py | 0 cv/ocr/sar/pytorch/csrc/sar/ops/bbox.py | 0 .../sar/pytorch/csrc/sar/ops/csrc/README.md | 0 .../cuda/assign_score_withk_cuda_kernel.cuh | 0 .../common/cuda/bbox_overlaps_cuda_kernel.cuh | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../common/cuda/roi_align_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../ops/csrc/pytorch/assign_score_withk.cpp | 0 .../sar/ops/csrc/pytorch/bbox_overlaps.cpp | 0 .../pytorch/cuda/assign_score_withk_cuda.cu | 0 .../csrc/pytorch/cuda/bbox_overlaps_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_align_cuda.cu | 0 .../sar/ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../csrc/sar/ops/csrc/pytorch/info.cpp | 0 .../csrc/sar/ops/csrc/pytorch/pybind.cpp | 0 .../csrc/sar/ops/csrc/pytorch/roi_align.cpp | 0 .../sar/ops/csrc/pytorch/roi_align_cpu.cpp | 0 .../csrc/sar/ops/csrc/pytorch/sync_bn.cpp | 0 cv/ocr/sar/pytorch/csrc/sar/ops/info.py | 0 cv/ocr/sar/pytorch/csrc/sar/ops/roi_align.py | 0 cv/ocr/sar/pytorch/csrc/sar/ops/sync_bn.py | 0 .../sar/pytorch/csrc/sar/runner/__init__.py | 0 .../pytorch/csrc/sar/runner/base_module.py | 0 .../sar/pytorch/csrc/sar/runner/dist_utils.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/__init__.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/config.py | 0 .../sar/pytorch/csrc/sar/utils/ext_loader.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/logging.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/misc.py | 0 .../pytorch/csrc/sar/utils/parrots_wrapper.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/path.py | 0 cv/ocr/sar/pytorch/csrc/sar/utils/registry.py | 0 .../pytorch/csrc/sar/utils/version_utils.py | 0 cv/ocr/sar/pytorch/csrc/setup.py | 0 cv/ocr/sar/pytorch/datasets_/__init__.py | 0 cv/ocr/sar/pytorch/datasets_/base_dataset.py | 0 cv/ocr/sar/pytorch/datasets_/builder.py | 0 cv/ocr/sar/pytorch/datasets_/ocr_dataset.py | 0 .../pytorch/datasets_/pipelines/__init__.py | 0 .../pytorch/datasets_/pipelines/box_utils.py | 0 .../sar/pytorch/datasets_/pipelines/crop.py | 0 .../pipelines/custom_format_bundle.py | 0 .../pytorch/datasets_/pipelines/loading.py | 0 .../datasets_/pipelines/ocr_transforms.py | 0 .../datasets_/pipelines/test_time_aug.py | 0 .../datasets_/pipelines/transform_wrappers.py | 0 .../pytorch/datasets_/pipelines/transforms.py | 0 .../datasets_/uniform_concat_dataset.py | 0 .../sar/pytorch/datasets_/utils/__init__.py | 0 cv/ocr/sar/pytorch/datasets_/utils/loader.py | 0 cv/ocr/sar/pytorch/datasets_/utils/parser.py | 0 cv/ocr/sar/pytorch/dist_train.sh | 0 cv/ocr/sar/pytorch/models/__init__.py | 0 .../sar/pytorch/models/backbones/__init__.py | 0 .../pytorch/models/backbones/resnet31_ocr.py | 0 cv/ocr/sar/pytorch/models/builder.py | 0 .../sar/pytorch/models/convertors/__init__.py | 0 cv/ocr/sar/pytorch/models/convertors/attn.py | 0 cv/ocr/sar/pytorch/models/convertors/base.py | 0 .../sar/pytorch/models/decoders/__init__.py | 0 .../pytorch/models/decoders/base_decoder.py | 0 .../pytorch/models/decoders/sar_decoder.py | 0 .../models/decoders/sar_decoder_with_bs.py | 0 .../sar/pytorch/models/encoders/__init__.py | 0 .../pytorch/models/encoders/base_encoder.py | 0 .../pytorch/models/encoders/sar_encoder.py | 0 cv/ocr/sar/pytorch/models/layers/__init__.py | 0 .../sar/pytorch/models/layers/conv_layer.py | 0 cv/ocr/sar/pytorch/models/layers/resnet.py | 0 cv/ocr/sar/pytorch/models/losses/__init__.py | 0 cv/ocr/sar/pytorch/models/losses/ce_loss.py | 0 .../sar/pytorch/models/recognizer/__init__.py | 0 cv/ocr/sar/pytorch/models/recognizer/base.py | 0 .../recognizer/encode_decode_recognizer.py | 0 cv/ocr/sar/pytorch/models/recognizer/sar.py | 0 cv/ocr/sar/pytorch/ocrcv/__init__.py | 0 cv/ocr/sar/pytorch/ocrcv/engine/__init__.py | 0 cv/ocr/sar/pytorch/ocrcv/engine/test.py | 0 cv/ocr/sar/pytorch/ocrcv/fileio/__init__.py | 0 .../sar/pytorch/ocrcv/fileio/file_client.py | 0 .../pytorch/ocrcv/fileio/handlers/__init__.py | 0 .../sar/pytorch/ocrcv/fileio/handlers/base.py | 0 .../ocrcv/fileio/handlers/json_handler.py | 0 .../ocrcv/fileio/handlers/pickle_handler.py | 0 .../ocrcv/fileio/handlers/yaml_handler.py | 0 cv/ocr/sar/pytorch/ocrcv/fileio/io.py | 0 cv/ocr/sar/pytorch/ocrcv/fileio/parse.py | 0 cv/ocr/sar/pytorch/ocrcv/image/__init__.py | 0 cv/ocr/sar/pytorch/ocrcv/image/colorspace.py | 0 cv/ocr/sar/pytorch/ocrcv/image/geometric.py | 0 cv/ocr/sar/pytorch/ocrcv/image/io.py | 0 cv/ocr/sar/pytorch/ocrcv/image/misc.py | 0 cv/ocr/sar/pytorch/ocrcv/image/photometric.py | 0 cv/ocr/sar/pytorch/ocrcv/parallel/__init__.py | 0 .../sar/pytorch/ocrcv/parallel/_functions.py | 0 cv/ocr/sar/pytorch/ocrcv/parallel/collate.py | 0 .../pytorch/ocrcv/parallel/data_container.py | 0 .../pytorch/ocrcv/parallel/data_parallel.py | 0 .../sar/pytorch/ocrcv/parallel/distributed.py | 0 .../ocrcv/parallel/distributed_deprecated.py | 0 cv/ocr/sar/pytorch/ocrcv/parallel/registry.py | 0 .../pytorch/ocrcv/parallel/scatter_gather.py | 0 cv/ocr/sar/pytorch/ocrcv/parallel/utils.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/__init__.py | 0 .../sar/pytorch/ocrcv/runner/base_module.py | 0 .../sar/pytorch/ocrcv/runner/base_runner.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/builder.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/checkpoint.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/dist_utils.py | 0 .../ocrcv/runner/epoch_based_runner.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/fp16_utils.py | 0 .../pytorch/ocrcv/runner/hooks/__init__.py | 0 .../pytorch/ocrcv/runner/hooks/checkpoint.py | 0 .../sar/pytorch/ocrcv/runner/hooks/closure.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/hooks/ema.py | 0 .../pytorch/ocrcv/runner/hooks/evaluation.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/hooks/hook.py | 0 .../pytorch/ocrcv/runner/hooks/iter_timer.py | 0 .../ocrcv/runner/hooks/logger/__init__.py | 0 .../pytorch/ocrcv/runner/hooks/logger/base.py | 0 .../ocrcv/runner/hooks/logger/dvclive.py | 0 .../ocrcv/runner/hooks/logger/mlflow.py | 0 .../ocrcv/runner/hooks/logger/neptune.py | 0 .../pytorch/ocrcv/runner/hooks/logger/pavi.py | 0 .../ocrcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/ocrcv/runner/hooks/logger/text.py | 0 .../ocrcv/runner/hooks/logger/wandb.py | 0 .../pytorch/ocrcv/runner/hooks/lr_updater.py | 0 .../sar/pytorch/ocrcv/runner/hooks/memory.py | 0 .../ocrcv/runner/hooks/momentum_updater.py | 0 .../pytorch/ocrcv/runner/hooks/optimizer.py | 0 .../pytorch/ocrcv/runner/hooks/profiler.py | 0 .../ocrcv/runner/hooks/sampler_seed.py | 0 .../pytorch/ocrcv/runner/hooks/sync_buffer.py | 0 .../pytorch/ocrcv/runner/iter_based_runner.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/log_buffer.py | 0 .../ocrcv/runner/optimizer/__init__.py | 0 .../pytorch/ocrcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/priority.py | 0 cv/ocr/sar/pytorch/ocrcv/runner/utils.py | 0 .../sar/pytorch/ocrcv/runner/weight_init.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/__init__.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/config.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/ext_loader.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/logging.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/misc.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/parrots_jit.py | 0 .../pytorch/ocrcv/utils/parrots_wrapper.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/path.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/progressbar.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/registry.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/testing.py | 0 cv/ocr/sar/pytorch/ocrcv/utils/timer.py | 0 .../sar/pytorch/ocrcv/utils/version_utils.py | 0 cv/ocr/sar/pytorch/ocrdet/__init__.py | 0 cv/ocr/sar/pytorch/ocrdet/core/__init__.py | 0 .../sar/pytorch/ocrdet/core/bbox/__init__.py | 0 .../ocrdet/core/bbox/assigners/__init__.py | 0 .../core/bbox/assigners/assign_result.py | 0 .../sar/pytorch/ocrdet/core/bbox/builder.py | 0 .../sar/pytorch/ocrdet/core/bbox/demodata.py | 0 .../core/bbox/iou_calculators/__init__.py | 0 .../bbox/iou_calculators/iou2d_calculator.py | 0 .../ocrdet/core/bbox/samplers/__init__.py | 0 .../ocrdet/core/bbox/samplers/base_sampler.py | 0 .../core/bbox/samplers/random_sampler.py | 0 .../core/bbox/samplers/sampling_result.py | 0 .../pytorch/ocrdet/core/bbox/transforms.py | 0 .../ocrdet/core/evaluation/__init__.py | 0 .../ocrdet/core/evaluation/bbox_overlaps.py | 0 .../ocrdet/core/evaluation/eval_hooks.py | 0 .../sar/pytorch/ocrdet/core/mask/__init__.py | 0 .../pytorch/ocrdet/core/mask/structures.py | 0 .../sar/pytorch/ocrdet/datasets/__init__.py | 0 .../ocrdet/datasets/api_wrappers/__init__.py | 0 .../ocrdet/datasets/api_wrappers/coco_api.py | 0 cv/ocr/sar/pytorch/ocrdet/datasets/builder.py | 0 .../ocrdet/datasets/dataset_wrappers.py | 0 .../ocrdet/datasets/pipelines/__init__.py | 0 .../ocrdet/datasets/pipelines/auto_augment.py | 0 .../ocrdet/datasets/pipelines/compose.py | 0 .../ocrdet/datasets/pipelines/formating.py | 0 .../ocrdet/datasets/pipelines/instaboost.py | 0 .../ocrdet/datasets/pipelines/loading.py | 0 .../datasets/pipelines/test_time_aug.py | 0 .../ocrdet/datasets/pipelines/transforms.py | 0 .../ocrdet/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../ocrdet/datasets/samplers/group_sampler.py | 0 .../datasets/samplers/infinite_sampler.py | 0 cv/ocr/sar/pytorch/ocrdet/datasets/utils.py | 0 cv/ocr/sar/pytorch/ocrdet/models/__init__.py | 0 cv/ocr/sar/pytorch/ocrdet/models/builder.py | 0 .../ocrdet/models/detectors/__init__.py | 0 .../pytorch/ocrdet/models/detectors/base.py | 0 .../ocrdet/models/detectors/single_stage.py | 0 .../pytorch/ocrdet/models/utils/__init__.py | 0 .../ocrdet/models/utils/transformer.py | 0 cv/ocr/sar/pytorch/ocrdet/utils/__init__.py | 0 .../sar/pytorch/ocrdet/utils/util_mixins.py | 0 .../sar/pytorch/ocrdet/utils/util_random.py | 0 cv/ocr/sar/pytorch/openvino_converter.py | 0 cv/ocr/sar/pytorch/requirements.txt | 0 cv/ocr/sar/pytorch/seg_synthtext_converter.py | 0 cv/ocr/sar/pytorch/svt_converter.py | 0 cv/ocr/sar/pytorch/synthtext_converter.py | 0 cv/ocr/sar/pytorch/textocr_converter.py | 0 cv/ocr/sar/pytorch/totaltext_converter.py | 0 cv/ocr/sar/pytorch/train.py | 0 cv/ocr/sar/pytorch/txt2lmdb.py | 0 cv/ocr/satrn/pytorch/base/.gitignore | 0 cv/ocr/satrn/pytorch/base/README.md | 0 cv/ocr/satrn/pytorch/base/apis/__init__.py | 0 cv/ocr/satrn/pytorch/base/apis/train.py | 0 cv/ocr/satrn/pytorch/base/apis/utils.py | 0 .../pytorch/base/basic_utils/__init__.py | 0 .../pytorch/base/basic_utils/box_util.py | 0 .../base/basic_utils/check_argument.py | 0 .../base/basic_utils/data_convert_util.py | 0 cv/ocr/satrn/pytorch/base/basic_utils/env.py | 0 .../satrn/pytorch/base/basic_utils/fileio.py | 0 .../pytorch/base/basic_utils/img_util.py | 0 .../pytorch/base/basic_utils/lmdb_util.py | 0 .../satrn/pytorch/base/basic_utils/logger.py | 0 .../satrn/pytorch/base/basic_utils/model.py | 0 .../pytorch/base/basic_utils/setup_env.py | 0 .../pytorch/base/basic_utils/string_util.py | 0 .../base/configs/_base_/default_runtime.py | 0 .../base/configs/_base_/runtime_10e.py | 0 .../_base_/schedules/schedule_adadelta_18e.py | 0 .../_base_/schedules/schedule_adadelta_5e.py | 0 .../_base_/schedules/schedule_adam_600e.py | 0 .../schedules/schedule_adam_step_20e.py | 0 .../_base_/schedules/schedule_adam_step_5e.py | 0 .../schedules/schedule_adam_step_600e.py | 0 .../_base_/schedules/schedule_adam_step_6e.py | 0 .../_base_/schedules/schedule_sgd_1200e.py | 0 .../_base_/schedules/schedule_sgd_1500e.py | 0 .../_base_/schedules/schedule_sgd_160e.py | 0 .../_base_/schedules/schedule_sgd_600e.py | 0 .../datasets_/ST_MJ_alphanumeric_train.py | 0 .../base/configs/datasets_/ST_MJ_train.py | 0 .../configs/datasets_/ST_SA_MJ_real_train.py | 0 .../base/configs/datasets_/Sample_test.py | 0 .../base/configs/datasets_/Sample_train.py | 0 .../base/configs/datasets_/academic_test.py | 0 .../pytorch/base/configs/models/satrn.py | 0 .../base/configs/models/satrn_academic.py | 0 .../configs/models/satrn_academic_sample.py | 0 .../base/configs/models/satrn_small.py | 0 .../base/configs/models/satrn_small_sample.py | 0 .../base/configs/pipelines/satrn_pipeline.py | 0 cv/ocr/satrn/pytorch/base/core/__init__.py | 0 .../pytorch/base/core/evaluation/__init__.py | 0 .../base/core/evaluation/ocr_metric.py | 0 .../pytorch/base/core/evaluation/utils.py | 0 cv/ocr/satrn/pytorch/base/core/mask.py | 0 cv/ocr/satrn/pytorch/base/core/visualize.py | 0 cv/ocr/satrn/pytorch/base/csrc/.gitignore | 0 cv/ocr/satrn/pytorch/base/csrc/build.sh | 0 cv/ocr/satrn/pytorch/base/csrc/clean.sh | 0 cv/ocr/satrn/pytorch/base/csrc/install.sh | 0 .../satrn/pytorch/base/csrc/satrn/__init__.py | 0 .../pytorch/base/csrc/satrn/cnn/__init__.py | 0 .../base/csrc/satrn/cnn/bricks/__init__.py | 0 .../base/csrc/satrn/cnn/bricks/activation.py | 0 .../base/csrc/satrn/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../base/csrc/satrn/cnn/bricks/conv_module.py | 0 .../base/csrc/satrn/cnn/bricks/drop.py | 0 .../base/csrc/satrn/cnn/bricks/hsigmoid.py | 0 .../base/csrc/satrn/cnn/bricks/hswish.py | 0 .../base/csrc/satrn/cnn/bricks/norm.py | 0 .../base/csrc/satrn/cnn/bricks/padding.py | 0 .../base/csrc/satrn/cnn/bricks/registry.py | 0 .../base/csrc/satrn/cnn/bricks/scale.py | 0 .../base/csrc/satrn/cnn/bricks/swish.py | 0 .../base/csrc/satrn/cnn/bricks/transformer.py | 0 .../base/csrc/satrn/cnn/bricks/wrappers.py | 0 .../pytorch/base/csrc/satrn/cnn/builder.py | 0 .../base/csrc/satrn/cnn/utils/__init__.py | 0 .../base/csrc/satrn/cnn/utils/fuse_conv_bn.py | 0 .../base/csrc/satrn/cnn/utils/sync_bn.py | 0 .../base/csrc/satrn/cnn/utils/weight_init.py | 0 .../pytorch/base/csrc/satrn/ops/__init__.py | 0 .../base/csrc/satrn/ops/assign_score_withk.py | 0 .../satrn/pytorch/base/csrc/satrn/ops/bbox.py | 0 .../base/csrc/satrn/ops/csrc/README.md | 0 .../cuda/assign_score_withk_cuda_kernel.cuh | 0 .../common/cuda/bbox_overlaps_cuda_kernel.cuh | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../common/cuda/roi_align_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../ops/csrc/pytorch/assign_score_withk.cpp | 0 .../satrn/ops/csrc/pytorch/bbox_overlaps.cpp | 0 .../pytorch/cuda/assign_score_withk_cuda.cu | 0 .../csrc/pytorch/cuda/bbox_overlaps_cuda.cu | 0 .../ops/csrc/pytorch/cuda/roi_align_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../base/csrc/satrn/ops/csrc/pytorch/info.cpp | 0 .../csrc/satrn/ops/csrc/pytorch/pybind.cpp | 0 .../csrc/satrn/ops/csrc/pytorch/roi_align.cpp | 0 .../satrn/ops/csrc/pytorch/roi_align_cpu.cpp | 0 .../csrc/satrn/ops/csrc/pytorch/sync_bn.cpp | 0 .../satrn/pytorch/base/csrc/satrn/ops/info.py | 0 .../pytorch/base/csrc/satrn/ops/roi_align.py | 0 .../pytorch/base/csrc/satrn/ops/sync_bn.py | 0 .../base/csrc/satrn/runner/__init__.py | 0 .../base/csrc/satrn/runner/base_module.py | 0 .../base/csrc/satrn/runner/dist_utils.py | 0 .../pytorch/base/csrc/satrn/utils/__init__.py | 0 .../pytorch/base/csrc/satrn/utils/config.py | 0 .../base/csrc/satrn/utils/ext_loader.py | 0 .../pytorch/base/csrc/satrn/utils/logging.py | 0 .../pytorch/base/csrc/satrn/utils/misc.py | 0 .../base/csrc/satrn/utils/parrots_wrapper.py | 0 .../pytorch/base/csrc/satrn/utils/path.py | 0 .../pytorch/base/csrc/satrn/utils/registry.py | 0 .../base/csrc/satrn/utils/version_utils.py | 0 cv/ocr/satrn/pytorch/base/csrc/setup.py | 0 .../satrn/pytorch/base/datasets_/__init__.py | 0 .../pytorch/base/datasets_/base_dataset.py | 0 .../satrn/pytorch/base/datasets_/builder.py | 0 .../pytorch/base/datasets_/ocr_dataset.py | 0 .../base/datasets_/pipelines/__init__.py | 0 .../base/datasets_/pipelines/box_utils.py | 0 .../pytorch/base/datasets_/pipelines/crop.py | 0 .../pipelines/custom_format_bundle.py | 0 .../base/datasets_/pipelines/loading.py | 0 .../datasets_/pipelines/ocr_transforms.py | 0 .../base/datasets_/pipelines/test_time_aug.py | 0 .../datasets_/pipelines/transform_wrappers.py | 0 .../base/datasets_/pipelines/transforms.py | 0 .../base/datasets_/uniform_concat_dataset.py | 0 .../pytorch/base/datasets_/utils/__init__.py | 0 .../pytorch/base/datasets_/utils/loader.py | 0 .../pytorch/base/datasets_/utils/parser.py | 0 cv/ocr/satrn/pytorch/base/dist_train.sh | 0 cv/ocr/satrn/pytorch/base/models/__init__.py | 0 .../pytorch/base/models/backbones/__init__.py | 0 .../base/models/backbones/shallow_cnn.py | 0 cv/ocr/satrn/pytorch/base/models/builder.py | 0 .../pytorch/base/models/common/__init__.py | 0 .../base/models/common/detectors/__init__.py | 0 .../models/common/detectors/single_stage.py | 0 .../base/models/common/layers/__init__.py | 0 .../common/layers/transformer_layers.py | 0 .../base/models/common/losses/__init__.py | 0 .../base/models/common/losses/dice_loss.py | 0 .../base/models/common/losses/focal_loss.py | 0 .../base/models/common/modules/__init__.py | 0 .../common/modules/transformer_module.py | 0 .../base/models/convertors/__init__.py | 0 .../pytorch/base/models/convertors/attn.py | 0 .../pytorch/base/models/convertors/base.py | 0 .../pytorch/base/models/decoders/__init__.py | 0 .../base/models/decoders/base_decoder.py | 0 .../base/models/decoders/nrtr_decoder.py | 0 .../models/decoders/transformer_decoder.py | 0 .../pytorch/base/models/encoders/__init__.py | 0 .../base/models/encoders/base_encoder.py | 0 .../base/models/encoders/satrn_encoder.py | 0 .../pytorch/base/models/layers/__init__.py | 0 .../pytorch/base/models/layers/conv_layer.py | 0 .../layers/dot_product_attention_layer.py | 0 .../pytorch/base/models/layers/lstm_layer.py | 0 .../models/layers/position_aware_layer.py | 0 .../layers/robust_scanner_fusion_layer.py | 0 .../base/models/layers/transformer_layer.py | 0 .../pytorch/base/models/losses/__init__.py | 0 .../pytorch/base/models/losses/ce_loss.py | 0 .../base/models/recognizer/__init__.py | 0 .../pytorch/base/models/recognizer/base.py | 0 .../recognizer/encode_decode_recognizer.py | 0 .../pytorch/base/models/recognizer/satrn.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/__init__.py | 0 .../pytorch/base/ocrcv/engine/__init__.py | 0 .../satrn/pytorch/base/ocrcv/engine/test.py | 0 .../pytorch/base/ocrcv/fileio/__init__.py | 0 .../pytorch/base/ocrcv/fileio/file_client.py | 0 .../base/ocrcv/fileio/handlers/__init__.py | 0 .../base/ocrcv/fileio/handlers/base.py | 0 .../ocrcv/fileio/handlers/json_handler.py | 0 .../ocrcv/fileio/handlers/pickle_handler.py | 0 .../ocrcv/fileio/handlers/yaml_handler.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/fileio/io.py | 0 .../satrn/pytorch/base/ocrcv/fileio/parse.py | 0 .../pytorch/base/ocrcv/image/__init__.py | 0 .../pytorch/base/ocrcv/image/colorspace.py | 0 .../pytorch/base/ocrcv/image/geometric.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/image/io.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/image/misc.py | 0 .../pytorch/base/ocrcv/image/photometric.py | 0 .../pytorch/base/ocrcv/parallel/__init__.py | 0 .../pytorch/base/ocrcv/parallel/_functions.py | 0 .../pytorch/base/ocrcv/parallel/collate.py | 0 .../base/ocrcv/parallel/data_container.py | 0 .../base/ocrcv/parallel/data_parallel.py | 0 .../base/ocrcv/parallel/distributed.py | 0 .../ocrcv/parallel/distributed_deprecated.py | 0 .../pytorch/base/ocrcv/parallel/registry.py | 0 .../base/ocrcv/parallel/scatter_gather.py | 0 .../pytorch/base/ocrcv/parallel/utils.py | 0 .../pytorch/base/ocrcv/runner/__init__.py | 0 .../pytorch/base/ocrcv/runner/base_module.py | 0 .../pytorch/base/ocrcv/runner/base_runner.py | 0 .../pytorch/base/ocrcv/runner/builder.py | 0 .../pytorch/base/ocrcv/runner/checkpoint.py | 0 .../pytorch/base/ocrcv/runner/dist_utils.py | 0 .../base/ocrcv/runner/epoch_based_runner.py | 0 .../pytorch/base/ocrcv/runner/fp16_utils.py | 0 .../base/ocrcv/runner/hooks/__init__.py | 0 .../base/ocrcv/runner/hooks/checkpoint.py | 0 .../base/ocrcv/runner/hooks/closure.py | 0 .../pytorch/base/ocrcv/runner/hooks/ema.py | 0 .../base/ocrcv/runner/hooks/evaluation.py | 0 .../pytorch/base/ocrcv/runner/hooks/hook.py | 0 .../base/ocrcv/runner/hooks/iter_timer.py | 0 .../ocrcv/runner/hooks/logger/__init__.py | 0 .../base/ocrcv/runner/hooks/logger/base.py | 0 .../base/ocrcv/runner/hooks/logger/dvclive.py | 0 .../base/ocrcv/runner/hooks/logger/mlflow.py | 0 .../base/ocrcv/runner/hooks/logger/neptune.py | 0 .../base/ocrcv/runner/hooks/logger/pavi.py | 0 .../ocrcv/runner/hooks/logger/tensorboard.py | 0 .../base/ocrcv/runner/hooks/logger/text.py | 0 .../base/ocrcv/runner/hooks/logger/wandb.py | 0 .../base/ocrcv/runner/hooks/lr_updater.py | 0 .../pytorch/base/ocrcv/runner/hooks/memory.py | 0 .../ocrcv/runner/hooks/momentum_updater.py | 0 .../base/ocrcv/runner/hooks/optimizer.py | 0 .../base/ocrcv/runner/hooks/profiler.py | 0 .../base/ocrcv/runner/hooks/sampler_seed.py | 0 .../base/ocrcv/runner/hooks/sync_buffer.py | 0 .../base/ocrcv/runner/iter_based_runner.py | 0 .../pytorch/base/ocrcv/runner/log_buffer.py | 0 .../base/ocrcv/runner/optimizer/__init__.py | 0 .../base/ocrcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../pytorch/base/ocrcv/runner/priority.py | 0 .../satrn/pytorch/base/ocrcv/runner/utils.py | 0 .../pytorch/base/ocrcv/runner/weight_init.py | 0 .../pytorch/base/ocrcv/utils/__init__.py | 0 .../satrn/pytorch/base/ocrcv/utils/config.py | 0 .../pytorch/base/ocrcv/utils/ext_loader.py | 0 .../satrn/pytorch/base/ocrcv/utils/logging.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/utils/misc.py | 0 .../pytorch/base/ocrcv/utils/parrots_jit.py | 0 .../base/ocrcv/utils/parrots_wrapper.py | 0 cv/ocr/satrn/pytorch/base/ocrcv/utils/path.py | 0 .../pytorch/base/ocrcv/utils/progressbar.py | 0 .../pytorch/base/ocrcv/utils/registry.py | 0 .../satrn/pytorch/base/ocrcv/utils/testing.py | 0 .../satrn/pytorch/base/ocrcv/utils/timer.py | 0 .../pytorch/base/ocrcv/utils/version_utils.py | 0 cv/ocr/satrn/pytorch/base/ocrdet/__init__.py | 0 .../pytorch/base/ocrdet/apis/__init__.py | 0 cv/ocr/satrn/pytorch/base/ocrdet/apis/test.py | 0 .../pytorch/base/ocrdet/core/__init__.py | 0 .../pytorch/base/ocrdet/core/bbox/__init__.py | 0 .../ocrdet/core/bbox/assigners/__init__.py | 0 .../core/bbox/assigners/assign_result.py | 0 .../pytorch/base/ocrdet/core/bbox/builder.py | 0 .../pytorch/base/ocrdet/core/bbox/demodata.py | 0 .../core/bbox/iou_calculators/__init__.py | 0 .../bbox/iou_calculators/iou2d_calculator.py | 0 .../ocrdet/core/bbox/samplers/__init__.py | 0 .../ocrdet/core/bbox/samplers/base_sampler.py | 0 .../core/bbox/samplers/random_sampler.py | 0 .../core/bbox/samplers/sampling_result.py | 0 .../base/ocrdet/core/bbox/transforms.py | 0 .../base/ocrdet/core/evaluation/__init__.py | 0 .../ocrdet/core/evaluation/bbox_overlaps.py | 0 .../base/ocrdet/core/evaluation/eval_hooks.py | 0 .../pytorch/base/ocrdet/core/mask/__init__.py | 0 .../base/ocrdet/core/mask/structures.py | 0 .../pytorch/base/ocrdet/core/mask/utils.py | 0 .../pytorch/base/ocrdet/datasets_/__init__.py | 0 .../ocrdet/datasets_/api_wrappers/__init__.py | 0 .../ocrdet/datasets_/api_wrappers/coco_api.py | 0 .../pytorch/base/ocrdet/datasets_/builder.py | 0 .../base/ocrdet/datasets_/dataset_wrappers.py | 0 .../ocrdet/datasets_/pipelines/__init__.py | 0 .../datasets_/pipelines/auto_augment.py | 0 .../ocrdet/datasets_/pipelines/compose.py | 0 .../ocrdet/datasets_/pipelines/formating.py | 0 .../ocrdet/datasets_/pipelines/instaboost.py | 0 .../ocrdet/datasets_/pipelines/loading.py | 0 .../datasets_/pipelines/test_time_aug.py | 0 .../ocrdet/datasets_/pipelines/transforms.py | 0 .../ocrdet/datasets_/samplers/__init__.py | 0 .../datasets_/samplers/distributed_sampler.py | 0 .../datasets_/samplers/group_sampler.py | 0 .../datasets_/samplers/infinite_sampler.py | 0 .../pytorch/base/ocrdet/datasets_/utils.py | 0 .../pytorch/base/ocrdet/models/__init__.py | 0 .../pytorch/base/ocrdet/models/builder.py | 0 .../base/ocrdet/models/detectors/__init__.py | 0 .../base/ocrdet/models/detectors/base.py | 0 .../ocrdet/models/detectors/single_stage.py | 0 .../base/ocrdet/models/utils/__init__.py | 0 .../base/ocrdet/models/utils/transformer.py | 0 .../pytorch/base/ocrdet/utils/__init__.py | 0 .../pytorch/base/ocrdet/utils/util_mixins.py | 0 .../pytorch/base/ocrdet/utils/util_random.py | 0 .../satrn/pytorch/base/openvino_converter.py | 0 cv/ocr/satrn/pytorch/base/requirements.txt | 0 .../pytorch/base/seg_synthtext_converter.py | 0 cv/ocr/satrn/pytorch/base/svt_converter.py | 0 .../satrn/pytorch/base/synthtext_converter.py | 0 .../satrn/pytorch/base/textocr_converter.py | 0 .../satrn/pytorch/base/totaltext_converter.py | 0 cv/ocr/satrn/pytorch/base/train.py | 0 cv/ocr/satrn/pytorch/base/txt2lmdb.py | 0 .../Point-BERT/pytorch/datasets/io.py | 0 .../pytorch/extensions/emd/__init__.py | 0 .../pytorch/extensions/emd/cuda/emd.cpp | 0 .../Point-BERT/pytorch/extensions/emd/emd.py | 0 .../pytorch/extensions/emd/setup.py | 0 .../Point-BERT/pytorch/segmentation/data | 1 - .../modelnet40_shape_names.txt | 40 + .../modelnet40_test.txt | 2468 + .../modelnet40_train.txt | 9843 ++++ .../data/ScanObjectNN_shape_names.txt | 15 + .../data/ShapeNet55-34/ShapeNet-55/test.txt | 10518 ++++ .../data/ShapeNet55-34/ShapeNet-55/train.txt | 41952 ++++++++++++++++ .../data/shapenet_synset_dict.json | 1 + .../pytorch/mmcv/device/ipu/__init__.py | 0 .../pytorch/mmcv/device/ipu/dataloader.py | 0 .../device/ipu/hierarchical_data_manager.py | 0 .../pytorch/mmcv/device/ipu/hook_wrapper.py | 0 .../pytorch/mmcv/device/ipu/model_wrapper.py | 0 .../apcnet/pytorch/mmcv/device/ipu/runner.py | 0 .../apcnet/pytorch/mmcv/device/ipu/utils.py | 0 .../apcnet/pytorch/tools/slurm_test.sh | 0 .../apcnet/pytorch/tools/slurm_train.sh | 0 .../apcnet/pytorch/train.sh | 0 .../apcnet/pytorch/train_dist.sh | 0 .../deeplabv3/MindSpore/Dockerfile | 0 .../deeplabv3/MindSpore/README.md | 0 .../MindSpore/ascend310_infer/CMakeLists.txt | 0 .../MindSpore/ascend310_infer/build.sh | 0 .../ascend310_infer/fusion_switch.cfg | 0 .../MindSpore/ascend310_infer/inc/utils.h | 0 .../MindSpore/ascend310_infer/src/main.cc | 0 .../MindSpore/ascend310_infer/src/utils.cc | 0 .../deeplabv3/MindSpore/default_config.yaml | 0 .../deeplabv3/MindSpore/eval.py | 0 .../deeplabv3/MindSpore/eval_onnx.py | 0 .../deeplabv3/MindSpore/export.py | 0 .../deeplabv3/MindSpore/infer/Dockerfile | 0 .../MindSpore/infer/convert/convert_om.sh | 0 .../MindSpore/infer/convert/fusion_switch.cfg | 0 .../MindSpore/infer/data/config/deeplabv3.cfg | 0 .../infer/data/config/deeplabv3.pipeline | 0 .../MindSpore/infer/docker_start_infer.sh | 0 .../MindSpore/infer/mxbase/CMakeLists.txt | 0 .../deeplabv3/MindSpore/infer/mxbase/build.sh | 0 .../MindSpore/infer/mxbase/src/DeeplabV3.cpp | 0 .../MindSpore/infer/mxbase/src/DeeplabV3.h | 0 .../MindSpore/infer/mxbase/src/main.cpp | 0 .../MindSpore/infer/requirements.txt | 0 .../infer/sdk/get_dataset_colormap.py | 0 .../deeplabv3/MindSpore/infer/sdk/main.py | 0 .../deeplabv3/MindSpore/infer/sdk/run.sh | 0 .../MindSpore/infer/util/get_vocval_lst.py | 0 .../deeplabv3/MindSpore/mindspore_hub_conf.py | 0 .../MindSpore/model_utils/__init__.py | 0 .../deeplabv3/MindSpore/model_utils/config.py | 0 .../MindSpore/model_utils/device_adapter.py | 0 .../MindSpore/model_utils/local_adapter.py | 0 .../MindSpore/model_utils/moxing_adapter.py | 0 .../MindSpore/modelarts/train_start.py | 0 .../deeplabv3/MindSpore/postprocess.py | 0 .../deeplabv3/MindSpore/requirements.txt | 0 .../deeplabv3/MindSpore/scripts/build_data.sh | 0 .../MindSpore/scripts/docker_start.sh | 0 .../scripts/run_distribute_train_s16_r1.sh | 0 .../scripts/run_distribute_train_s8_r1.sh | 0 .../scripts/run_distribute_train_s8_r2.sh | 0 .../MindSpore/scripts/run_eval_onnx.sh | 0 .../MindSpore/scripts/run_eval_s16.sh | 0 .../MindSpore/scripts/run_eval_s16_gpu.sh | 0 .../MindSpore/scripts/run_eval_s8.sh | 0 .../scripts/run_eval_s8_multiscale.sh | 0 .../scripts/run_eval_s8_multiscale_flip.sh | 0 .../MindSpore/scripts/run_infer_310.sh | 0 .../MindSpore/scripts/run_standalone_train.sh | 0 .../scripts/run_standalone_train_cpu.sh | 0 .../scripts/run_standalone_train_gpu.sh | 0 .../deeplabv3/MindSpore/src/__init__.py | 0 .../deeplabv3/MindSpore/src/data/__init__.py | 0 .../MindSpore/src/data/build_seg_data.py | 0 .../deeplabv3/MindSpore/src/data/dataset.py | 0 .../MindSpore/src/data/get_dataset_lst.py | 0 .../deeplabv3/MindSpore/src/loss/__init__.py | 0 .../deeplabv3/MindSpore/src/loss/loss.py | 0 .../deeplabv3/MindSpore/src/nets/__init__.py | 0 .../MindSpore/src/nets/deeplab_v3/__init__.py | 0 .../src/nets/deeplab_v3/deeplab_v3.py | 0 .../MindSpore/src/nets/net_factory.py | 0 .../deeplabv3/MindSpore/src/tools/__init__.py | 0 .../src/tools/get_multicards_json.py | 0 .../deeplabv3/MindSpore/src/utils/__init__.py | 0 .../MindSpore/src/utils/learning_rates.py | 0 .../deeplabv3/MindSpore/train.py | 0 .../gcnet/pytorch/.gitignore | 0 .../gcnet/pytorch/CITATION.cff | 0 .../gcnet/pytorch/LICENSE | 0 .../gcnet/pytorch/README.md | 0 .../configs/_base_/datasets/cityscapes.py | 0 .../_base_/datasets/cityscapes_769x769.py | 0 .../pytorch/configs/_base_/default_runtime.py | 0 .../configs/_base_/models/gcnet_r50-d8.py | 0 .../configs/_base_/schedules/schedule_40k.py | 0 .../gcnet/pytorch/configs/gcnet/README.md | 0 .../gcnet_r50-d8_769x769_40k_cityscapes.py | 0 .../gcnet/pytorch/dist_train.sh | 0 .../gcnet/pytorch/mmcv/__init__.py | 0 .../gcnet/pytorch/mmcv/cnn/__init__.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/conv.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/norm.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/padding.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/plugin.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/registry.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/scale.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/upsample.py | 0 .../gcnet/pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../gcnet/pytorch/mmcv/cnn/builder.py | 0 .../gcnet/pytorch/mmcv/cnn/resnet.py | 0 .../gcnet/pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../gcnet/pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../gcnet/pytorch/mmcv/engine/__init__.py | 0 .../gcnet/pytorch/mmcv/engine/test.py | 0 .../gcnet/pytorch/mmcv/fileio/__init__.py | 0 .../gcnet/pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../gcnet/pytorch/mmcv/fileio/io.py | 0 .../gcnet/pytorch/mmcv/fileio/parse.py | 0 .../gcnet/pytorch/mmcv/image/__init__.py | 0 .../gcnet/pytorch/mmcv/image/colorspace.py | 0 .../gcnet/pytorch/mmcv/image/geometric.py | 0 .../gcnet/pytorch/mmcv/image/io.py | 0 .../gcnet/pytorch/mmcv/image/misc.py | 0 .../gcnet/pytorch/mmcv/image/photometric.py | 0 .../gcnet/pytorch/mmcv/ops/__init__.py | 0 .../gcnet/pytorch/mmcv/ops/csrc/README.md | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../cuda/sigmoid_focal_loss_cuda_kernel.cuh | 0 .../cuda/softmax_focal_loss_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../ops/csrc/pytorch/cuda/focal_loss_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../mmcv/ops/csrc/pytorch/focal_loss.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../pytorch/mmcv/ops/deprecated_wrappers.py | 0 .../gcnet/pytorch/mmcv/ops/focal_loss.py | 0 .../gcnet/pytorch/mmcv/ops/info.py | 0 .../gcnet/pytorch/mmcv/ops/sync_bn.py | 0 .../gcnet/pytorch/mmcv/parallel/__init__.py | 0 .../gcnet/pytorch/mmcv/parallel/_functions.py | 0 .../gcnet/pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../gcnet/pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../gcnet/pytorch/mmcv/parallel/utils.py | 0 .../gcnet/pytorch/mmcv/runner/__init__.py | 0 .../gcnet/pytorch/mmcv/runner/base_module.py | 0 .../gcnet/pytorch/mmcv/runner/base_runner.py | 0 .../gcnet/pytorch/mmcv/runner/builder.py | 0 .../gcnet/pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../gcnet/pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../gcnet/pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../gcnet/pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../gcnet/pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../gcnet/pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../gcnet/pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../gcnet/pytorch/mmcv/runner/priority.py | 0 .../gcnet/pytorch/mmcv/runner/utils.py | 0 .../gcnet/pytorch/mmcv/utils/__init__.py | 0 .../gcnet/pytorch/mmcv/utils/config.py | 0 .../gcnet/pytorch/mmcv/utils/env.py | 0 .../gcnet/pytorch/mmcv/utils/ext_loader.py | 0 .../gcnet/pytorch/mmcv/utils/logging.py | 0 .../gcnet/pytorch/mmcv/utils/misc.py | 0 .../gcnet/pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../gcnet/pytorch/mmcv/utils/path.py | 0 .../gcnet/pytorch/mmcv/utils/progressbar.py | 0 .../gcnet/pytorch/mmcv/utils/registry.py | 0 .../gcnet/pytorch/mmcv/utils/testing.py | 0 .../gcnet/pytorch/mmcv/utils/timer.py | 0 .../gcnet/pytorch/mmcv/utils/trace.py | 0 .../gcnet/pytorch/mmcv/utils/version_utils.py | 0 .../gcnet/pytorch/mmcv/version.py | 0 .../gcnet/pytorch/mmseg/__init__.py | 0 .../gcnet/pytorch/mmseg/apis/__init__.py | 0 .../gcnet/pytorch/mmseg/apis/inference.py | 0 .../gcnet/pytorch/mmseg/apis/test.py | 0 .../gcnet/pytorch/mmseg/apis/train.py | 0 .../gcnet/pytorch/mmseg/core/__init__.py | 0 .../pytorch/mmseg/core/evaluation/__init__.py | 0 .../mmseg/core/evaluation/class_names.py | 0 .../mmseg/core/evaluation/eval_hooks.py | 0 .../pytorch/mmseg/core/evaluation/metrics.py | 0 .../gcnet/pytorch/mmseg/core/seg/__init__.py | 0 .../gcnet/pytorch/mmseg/core/seg/builder.py | 0 .../mmseg/core/seg/sampler/__init__.py | 0 .../core/seg/sampler/base_pixel_sampler.py | 0 .../core/seg/sampler/ohem_pixel_sampler.py | 0 .../pytorch/mmseg/core/utils/__init__.py | 0 .../gcnet/pytorch/mmseg/core/utils/misc.py | 0 .../gcnet/pytorch/mmseg/datasets/__init__.py | 0 .../gcnet/pytorch/mmseg/datasets/builder.py | 0 .../pytorch/mmseg/datasets/cityscapes.py | 0 .../gcnet/pytorch/mmseg/datasets/custom.py | 0 .../mmseg/datasets/dataset_wrappers.py | 0 .../mmseg/datasets/pipelines/__init__.py | 0 .../mmseg/datasets/pipelines/compose.py | 0 .../mmseg/datasets/pipelines/formating.py | 0 .../mmseg/datasets/pipelines/formatting.py | 0 .../mmseg/datasets/pipelines/loading.py | 0 .../mmseg/datasets/pipelines/test_time_aug.py | 0 .../mmseg/datasets/pipelines/transforms.py | 0 .../gcnet/pytorch/mmseg/models/__init__.py | 0 .../mmseg/models/backbones/__init__.py | 0 .../pytorch/mmseg/models/backbones/resnet.py | 0 .../gcnet/pytorch/mmseg/models/builder.py | 0 .../mmseg/models/decode_heads/__init__.py | 0 .../mmseg/models/decode_heads/decode_head.py | 0 .../mmseg/models/decode_heads/fcn_head.py | 0 .../mmseg/models/decode_heads/gc_head.py | 0 .../pytorch/mmseg/models/losses/__init__.py | 0 .../pytorch/mmseg/models/losses/accuracy.py | 0 .../mmseg/models/losses/cross_entropy_loss.py | 0 .../pytorch/mmseg/models/losses/utils.py | 0 .../pytorch/mmseg/models/necks/__init__.py | 0 .../gcnet/pytorch/mmseg/models/necks/fpn.py | 0 .../pytorch/mmseg/models/necks/ic_neck.py | 0 .../gcnet/pytorch/mmseg/models/necks/jpu.py | 0 .../pytorch/mmseg/models/necks/mla_neck.py | 0 .../mmseg/models/necks/multilevel_neck.py | 0 .../mmseg/models/segmentors/__init__.py | 0 .../pytorch/mmseg/models/segmentors/base.py | 0 .../models/segmentors/encoder_decoder.py | 0 .../pytorch/mmseg/models/utils/__init__.py | 0 .../gcnet/pytorch/mmseg/models/utils/embed.py | 0 .../mmseg/models/utils/inverted_residual.py | 0 .../mmseg/models/utils/make_divisible.py | 0 .../pytorch/mmseg/models/utils/res_layer.py | 0 .../pytorch/mmseg/models/utils/se_layer.py | 0 .../models/utils/self_attention_block.py | 0 .../mmseg/models/utils/shape_convert.py | 0 .../mmseg/models/utils/up_conv_block.py | 0 .../gcnet/pytorch/mmseg/ops/__init__.py | 0 .../gcnet/pytorch/mmseg/ops/encoding.py | 0 .../gcnet/pytorch/mmseg/ops/wrappers.py | 0 .../gcnet/pytorch/mmseg/utils/__init__.py | 0 .../gcnet/pytorch/mmseg/utils/collect_env.py | 0 .../gcnet/pytorch/mmseg/utils/logger.py | 0 .../gcnet/pytorch/mmseg/version.py | 0 .../gcnet/pytorch/requirements.txt | 0 .../gcnet/pytorch/requirements/docs.txt | 0 .../gcnet/pytorch/requirements/mminstall.txt | 0 .../gcnet/pytorch/requirements/optional.txt | 0 .../pytorch/requirements/readthedocs.txt | 0 .../gcnet/pytorch/requirements/runtime.txt | 0 .../gcnet/pytorch/requirements/tests.txt | 0 .../gcnet/pytorch/run_train.sh | 0 .../gcnet/pytorch/setup.py | 0 .../gcnet/pytorch/tools/analyze_logs.py | 0 .../gcnet/pytorch/tools/benchmark.py | 0 .../tools/convert_datasets/cityscapes.py | 0 .../gcnet/pytorch/tools/get_flops.py | 0 .../gcnet/pytorch/tools/print_config.py | 0 .../gcnet/pytorch/tools/test.py | 0 .../gcnet/pytorch/train.py | 0 .../basicVSR++/pytorch/.gitignore | 0 .../basicVSR++/pytorch/LICENSE | 0 .../basicVSR++/pytorch/README.md | 0 .../basicVSR++/pytorch/build_env.sh | 0 .../basicvsr_plusplus_c64n7_8x1_600k_reds4.py | 0 .../basicVSR++/pytorch/dist_train.sh | 0 .../basicVSR++/pytorch/docker/Dockerfile | 0 .../basicVSR++/pytorch/docker/README.md | 0 .../basicVSR++/pytorch/mmcv/__init__.py | 0 .../pytorch/mmcv/arraymisc/__init__.py | 0 .../pytorch/mmcv/arraymisc/quantization.py | 0 .../basicVSR++/pytorch/mmcv/cnn/__init__.py | 0 .../basicVSR++/pytorch/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../pytorch/mmcv/cnn/bricks/norm.py | 0 .../pytorch/mmcv/cnn/bricks/padding.py | 0 .../pytorch/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/cnn/bricks/registry.py | 0 .../pytorch/mmcv/cnn/bricks/scale.py | 0 .../pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../basicVSR++/pytorch/mmcv/cnn/builder.py | 0 .../basicVSR++/pytorch/mmcv/cnn/resnet.py | 0 .../pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../basicVSR++/pytorch/mmcv/cnn/vgg.py | 0 .../pytorch/mmcv/engine/__init__.py | 0 .../basicVSR++/pytorch/mmcv/engine/test.py | 0 .../pytorch/mmcv/fileio/__init__.py | 0 .../pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../basicVSR++/pytorch/mmcv/fileio/io.py | 0 .../basicVSR++/pytorch/mmcv/fileio/parse.py | 0 .../basicVSR++/pytorch/mmcv/image/__init__.py | 0 .../pytorch/mmcv/image/colorspace.py | 0 .../pytorch/mmcv/image/geometric.py | 0 .../basicVSR++/pytorch/mmcv/image/io.py | 0 .../basicVSR++/pytorch/mmcv/image/misc.py | 0 .../pytorch/mmcv/image/photometric.py | 0 .../basicVSR++/pytorch/mmcv/ops/__init__.py | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../modulated_deform_conv_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../cuda/modulated_deform_conv_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../csrc/pytorch/modulated_deform_conv.cpp | 0 .../pytorch/modulated_deform_conv_cpu.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../pytorch/mmcv/ops/deprecated_wrappers.py | 0 .../basicVSR++/pytorch/mmcv/ops/info.py | 0 .../pytorch/mmcv/ops/modulated_deform_conv.py | 0 .../basicVSR++/pytorch/mmcv/ops/sync_bn.py | 0 .../pytorch/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/parallel/_functions.py | 0 .../pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../basicVSR++/pytorch/mmcv/parallel/utils.py | 0 .../pytorch/mmcv/runner/__init__.py | 0 .../pytorch/mmcv/runner/base_module.py | 0 .../pytorch/mmcv/runner/base_runner.py | 0 .../basicVSR++/pytorch/mmcv/runner/builder.py | 0 .../pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../pytorch/mmcv/runner/priority.py | 0 .../basicVSR++/pytorch/mmcv/runner/utils.py | 0 .../basicVSR++/pytorch/mmcv/utils/__init__.py | 0 .../basicVSR++/pytorch/mmcv/utils/config.py | 0 .../basicVSR++/pytorch/mmcv/utils/env.py | 0 .../pytorch/mmcv/utils/ext_loader.py | 0 .../basicVSR++/pytorch/mmcv/utils/logging.py | 0 .../basicVSR++/pytorch/mmcv/utils/misc.py | 0 .../pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../basicVSR++/pytorch/mmcv/utils/path.py | 0 .../pytorch/mmcv/utils/progressbar.py | 0 .../basicVSR++/pytorch/mmcv/utils/registry.py | 0 .../basicVSR++/pytorch/mmcv/utils/testing.py | 0 .../basicVSR++/pytorch/mmcv/utils/timer.py | 0 .../basicVSR++/pytorch/mmcv/utils/trace.py | 0 .../pytorch/mmcv/utils/version_utils.py | 0 .../basicVSR++/pytorch/mmcv/version.py | 0 .../basicVSR++/pytorch/mmedit/__init__.py | 0 .../pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/generation_inference.py | 0 .../mmedit/apis/inpainting_inference.py | 0 .../pytorch/mmedit/apis/matting_inference.py | 0 .../mmedit/apis/restoration_face_inference.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../apis/restoration_video_inference.py | 0 .../basicVSR++/pytorch/mmedit/apis/test.py | 0 .../basicVSR++/pytorch/mmedit/apis/train.py | 0 .../apis/video_interpolation_inference.py | 0 .../pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../pytorch/mmedit/core/hooks/ema.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../basicVSR++/pytorch/mmedit/core/mask.py | 0 .../basicVSR++/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../pytorch/mmedit/core/utils/__init__.py | 0 .../pytorch/mmedit/core/utils/dist_utils.py | 0 .../pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../pytorch/mmedit/datasets/builder.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../pytorch/mmedit/datasets/pipelines/crop.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../datasets/pipelines/matlab_like_resize.py | 0 .../datasets/pipelines/normalization.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/sr_reds_multiple_gt_dataset.py | 0 .../pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../backbones/sr_backbones/basicvsr_net.py | 0 .../backbones/sr_backbones/basicvsr_pp.py | 0 .../basicVSR++/pytorch/mmedit/models/base.py | 0 .../pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../pytorch/mmedit/models/common/aspp.py | 0 .../models/common/contextual_attention.py | 0 .../pytorch/mmedit/models/common/conv.py | 0 .../mmedit/models/common/downsample.py | 0 .../pytorch/mmedit/models/common/ensemble.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/gated_conv_module.py | 0 .../mmedit/models/common/gca_module.py | 0 .../models/common/generation_model_utils.py | 0 .../mmedit/models/common/img_normalize.py | 0 .../mmedit/models/common/linear_module.py | 0 .../mmedit/models/common/mask_conv_module.py | 0 .../mmedit/models/common/model_utils.py | 0 .../mmedit/models/common/partial_conv.py | 0 .../models/common/separable_conv_module.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../mmedit/models/restorers/basicvsr.py | 0 .../pytorch/mmedit/utils/__init__.py | 0 .../basicVSR++/pytorch/mmedit/utils/cli.py | 0 .../pytorch/mmedit/utils/collect_env.py | 0 .../basicVSR++/pytorch/mmedit/utils/logger.py | 0 .../pytorch/mmedit/utils/setup_env.py | 0 .../basicVSR++/pytorch/mmedit/version.py | 0 .../basicVSR++/pytorch/requirements.txt | 0 .../basicVSR++/pytorch/setup.py | 0 .../basicVSR++/pytorch/train.py | 0 .../basicVSR/pytorch/.gitignore | 0 cv/super_resolution/basicVSR/pytorch/LICENSE | 0 .../basicVSR/pytorch/README.md | 0 .../basicVSR/pytorch/build_env.sh | 0 .../configs/basicvsr/basicvsr_reds4.py | 0 .../pytorch/configs/iconvsr/iconvsr_reds4.py | 0 .../basicVSR/pytorch/dist_train.sh | 0 .../basicVSR/pytorch/docker/Dockerfile | 0 .../basicVSR/pytorch/docker/README.md | 0 .../basicVSR/pytorch/mmcv/__init__.py | 0 .../pytorch/mmcv/arraymisc/__init__.py | 0 .../pytorch/mmcv/arraymisc/quantization.py | 0 .../basicVSR/pytorch/mmcv/cnn/__init__.py | 0 .../basicVSR/pytorch/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../basicVSR/pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../basicVSR/pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../basicVSR/pytorch/mmcv/cnn/bricks/norm.py | 0 .../pytorch/mmcv/cnn/bricks/padding.py | 0 .../pytorch/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/cnn/bricks/registry.py | 0 .../basicVSR/pytorch/mmcv/cnn/bricks/scale.py | 0 .../basicVSR/pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../basicVSR/pytorch/mmcv/cnn/builder.py | 0 .../basicVSR/pytorch/mmcv/cnn/resnet.py | 0 .../pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../basicVSR/pytorch/mmcv/cnn/vgg.py | 0 .../basicVSR/pytorch/mmcv/engine/__init__.py | 0 .../basicVSR/pytorch/mmcv/engine/test.py | 0 .../basicVSR/pytorch/mmcv/fileio/__init__.py | 0 .../pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../basicVSR/pytorch/mmcv/fileio/io.py | 0 .../basicVSR/pytorch/mmcv/fileio/parse.py | 0 .../basicVSR/pytorch/mmcv/image/__init__.py | 0 .../basicVSR/pytorch/mmcv/image/colorspace.py | 0 .../basicVSR/pytorch/mmcv/image/geometric.py | 0 .../basicVSR/pytorch/mmcv/image/io.py | 0 .../basicVSR/pytorch/mmcv/image/misc.py | 0 .../pytorch/mmcv/image/photometric.py | 0 .../basicVSR/pytorch/mmcv/ops/__init__.py | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../modulated_deform_conv_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../cuda/modulated_deform_conv_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../csrc/pytorch/modulated_deform_conv.cpp | 0 .../pytorch/modulated_deform_conv_cpu.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../pytorch/mmcv/ops/deprecated_wrappers.py | 0 .../basicVSR/pytorch/mmcv/ops/info.py | 0 .../pytorch/mmcv/ops/modulated_deform_conv.py | 0 .../basicVSR/pytorch/mmcv/ops/sync_bn.py | 0 .../pytorch/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/parallel/_functions.py | 0 .../basicVSR/pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../basicVSR/pytorch/mmcv/parallel/utils.py | 0 .../basicVSR/pytorch/mmcv/runner/__init__.py | 0 .../pytorch/mmcv/runner/base_module.py | 0 .../pytorch/mmcv/runner/base_runner.py | 0 .../basicVSR/pytorch/mmcv/runner/builder.py | 0 .../pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../basicVSR/pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../basicVSR/pytorch/mmcv/runner/priority.py | 0 .../basicVSR/pytorch/mmcv/runner/utils.py | 0 .../basicVSR/pytorch/mmcv/utils/__init__.py | 0 .../basicVSR/pytorch/mmcv/utils/config.py | 0 .../basicVSR/pytorch/mmcv/utils/env.py | 0 .../basicVSR/pytorch/mmcv/utils/ext_loader.py | 0 .../basicVSR/pytorch/mmcv/utils/logging.py | 0 .../basicVSR/pytorch/mmcv/utils/misc.py | 0 .../pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../basicVSR/pytorch/mmcv/utils/path.py | 0 .../pytorch/mmcv/utils/progressbar.py | 0 .../basicVSR/pytorch/mmcv/utils/registry.py | 0 .../basicVSR/pytorch/mmcv/utils/testing.py | 0 .../basicVSR/pytorch/mmcv/utils/timer.py | 0 .../basicVSR/pytorch/mmcv/utils/trace.py | 0 .../pytorch/mmcv/utils/version_utils.py | 0 .../basicVSR/pytorch/mmcv/version.py | 0 .../basicVSR/pytorch/mmedit/__init__.py | 0 .../basicVSR/pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/generation_inference.py | 0 .../mmedit/apis/inpainting_inference.py | 0 .../pytorch/mmedit/apis/matting_inference.py | 0 .../mmedit/apis/restoration_face_inference.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../apis/restoration_video_inference.py | 0 .../basicVSR/pytorch/mmedit/apis/test.py | 0 .../basicVSR/pytorch/mmedit/apis/train.py | 0 .../apis/video_interpolation_inference.py | 0 .../basicVSR/pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../basicVSR/pytorch/mmedit/core/hooks/ema.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../basicVSR/pytorch/mmedit/core/mask.py | 0 .../basicVSR/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../pytorch/mmedit/core/utils/__init__.py | 0 .../pytorch/mmedit/core/utils/dist_utils.py | 0 .../pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../pytorch/mmedit/datasets/builder.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../pytorch/mmedit/datasets/pipelines/crop.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../datasets/pipelines/matlab_like_resize.py | 0 .../datasets/pipelines/normalization.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/sr_reds_multiple_gt_dataset.py | 0 .../pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../backbones/sr_backbones/basicvsr_net.py | 0 .../models/backbones/sr_backbones/edvr_net.py | 0 .../models/backbones/sr_backbones/iconvsr.py | 0 .../basicVSR/pytorch/mmedit/models/base.py | 0 .../basicVSR/pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../pytorch/mmedit/models/common/aspp.py | 0 .../models/common/contextual_attention.py | 0 .../pytorch/mmedit/models/common/conv.py | 0 .../mmedit/models/common/downsample.py | 0 .../pytorch/mmedit/models/common/ensemble.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/gated_conv_module.py | 0 .../mmedit/models/common/gca_module.py | 0 .../models/common/generation_model_utils.py | 0 .../mmedit/models/common/img_normalize.py | 0 .../mmedit/models/common/linear_module.py | 0 .../mmedit/models/common/mask_conv_module.py | 0 .../mmedit/models/common/model_utils.py | 0 .../mmedit/models/common/partial_conv.py | 0 .../models/common/separable_conv_module.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../mmedit/models/restorers/basicvsr.py | 0 .../basicVSR/pytorch/mmedit/utils/__init__.py | 0 .../basicVSR/pytorch/mmedit/utils/cli.py | 0 .../pytorch/mmedit/utils/collect_env.py | 0 .../basicVSR/pytorch/mmedit/utils/logger.py | 0 .../pytorch/mmedit/utils/setup_env.py | 0 .../basicVSR/pytorch/mmedit/version.py | 0 .../basicVSR/pytorch/requirements.txt | 0 cv/super_resolution/basicVSR/pytorch/setup.py | 0 cv/super_resolution/basicVSR/pytorch/train.py | 0 cv/super_resolution/esrgan/pytorch/.gitignore | 0 cv/super_resolution/esrgan/pytorch/LICENSE | 0 cv/super_resolution/esrgan/pytorch/README.md | 0 .../esrgan_psnr_x4c64b23g32_g1_1000k_div2k.py | 0 .../esrgan/pytorch/dist_train.sh | 0 .../esrgan/pytorch/docker/Dockerfile | 0 .../esrgan/pytorch/docker/README.md | 0 .../esrgan/pytorch/get_div2k_anno.py | 0 .../esrgan/pytorch/mmcv/__init__.py | 0 .../esrgan/pytorch/mmcv/cnn/__init__.py | 0 .../esrgan/pytorch/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/norm.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/padding.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/cnn/bricks/registry.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/scale.py | 0 .../esrgan/pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../esrgan/pytorch/mmcv/cnn/builder.py | 0 .../esrgan/pytorch/mmcv/cnn/resnet.py | 0 .../esrgan/pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../esrgan/pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../esrgan/pytorch/mmcv/cnn/vgg.py | 0 .../esrgan/pytorch/mmcv/engine/__init__.py | 0 .../esrgan/pytorch/mmcv/engine/test.py | 0 .../esrgan/pytorch/mmcv/fileio/__init__.py | 0 .../esrgan/pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../esrgan/pytorch/mmcv/fileio/io.py | 0 .../esrgan/pytorch/mmcv/fileio/parse.py | 0 .../esrgan/pytorch/mmcv/image/__init__.py | 0 .../esrgan/pytorch/mmcv/image/colorspace.py | 0 .../esrgan/pytorch/mmcv/image/geometric.py | 0 .../esrgan/pytorch/mmcv/image/io.py | 0 .../esrgan/pytorch/mmcv/image/misc.py | 0 .../esrgan/pytorch/mmcv/image/photometric.py | 0 .../esrgan/pytorch/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/parallel/_functions.py | 0 .../esrgan/pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../esrgan/pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../esrgan/pytorch/mmcv/parallel/utils.py | 0 .../esrgan/pytorch/mmcv/runner/__init__.py | 0 .../esrgan/pytorch/mmcv/runner/base_module.py | 0 .../esrgan/pytorch/mmcv/runner/base_runner.py | 0 .../esrgan/pytorch/mmcv/runner/builder.py | 0 .../esrgan/pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../esrgan/pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../esrgan/pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../esrgan/pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../esrgan/pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../esrgan/pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../esrgan/pytorch/mmcv/runner/priority.py | 0 .../esrgan/pytorch/mmcv/runner/utils.py | 0 .../esrgan/pytorch/mmcv/utils/__init__.py | 0 .../esrgan/pytorch/mmcv/utils/config.py | 0 .../esrgan/pytorch/mmcv/utils/env.py | 0 .../esrgan/pytorch/mmcv/utils/ext_loader.py | 0 .../esrgan/pytorch/mmcv/utils/logging.py | 0 .../esrgan/pytorch/mmcv/utils/misc.py | 0 .../esrgan/pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../esrgan/pytorch/mmcv/utils/path.py | 0 .../esrgan/pytorch/mmcv/utils/progressbar.py | 0 .../esrgan/pytorch/mmcv/utils/registry.py | 0 .../esrgan/pytorch/mmcv/utils/testing.py | 0 .../esrgan/pytorch/mmcv/utils/timer.py | 0 .../esrgan/pytorch/mmcv/utils/trace.py | 0 .../pytorch/mmcv/utils/version_utils.py | 0 .../esrgan/pytorch/mmcv/version.py | 0 .../esrgan/pytorch/mmedit/__init__.py | 0 .../esrgan/pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/generation_inference.py | 0 .../mmedit/apis/inpainting_inference.py | 0 .../pytorch/mmedit/apis/matting_inference.py | 0 .../mmedit/apis/restoration_face_inference.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../apis/restoration_video_inference.py | 0 .../esrgan/pytorch/mmedit/apis/test.py | 0 .../esrgan/pytorch/mmedit/apis/train.py | 0 .../apis/video_interpolation_inference.py | 0 .../esrgan/pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../esrgan/pytorch/mmedit/core/hooks/ema.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../esrgan/pytorch/mmedit/core/mask.py | 0 .../esrgan/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../pytorch/mmedit/core/utils/__init__.py | 0 .../pytorch/mmedit/core/utils/dist_utils.py | 0 .../pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../esrgan/pytorch/mmedit/datasets/builder.py | 0 .../pytorch/mmedit/datasets/comp1k_dataset.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../pytorch/mmedit/datasets/pipelines/crop.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../datasets/pipelines/matlab_like_resize.py | 0 .../datasets/pipelines/normalization.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../mmedit/datasets/sr_annotation_dataset.py | 0 .../mmedit/datasets/sr_folder_dataset.py | 0 .../esrgan/pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../models/backbones/sr_backbones/rrdb_net.py | 0 .../esrgan/pytorch/mmedit/models/base.py | 0 .../esrgan/pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../pytorch/mmedit/models/common/aspp.py | 0 .../models/common/contextual_attention.py | 0 .../pytorch/mmedit/models/common/conv.py | 0 .../mmedit/models/common/downsample.py | 0 .../pytorch/mmedit/models/common/ensemble.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/gated_conv_module.py | 0 .../mmedit/models/common/gca_module.py | 0 .../models/common/generation_model_utils.py | 0 .../mmedit/models/common/img_normalize.py | 0 .../mmedit/models/common/linear_module.py | 0 .../mmedit/models/common/mask_conv_module.py | 0 .../mmedit/models/common/model_utils.py | 0 .../mmedit/models/common/partial_conv.py | 0 .../models/common/separable_conv_module.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../mmedit/models/components/__init__.py | 0 .../components/discriminators/__init__.py | 0 .../components/discriminators/modified_vgg.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../pytorch/mmedit/models/losses/gan_loss.py | 0 .../mmedit/models/losses/perceptual_loss.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../esrgan/pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../pytorch/mmedit/models/restorers/esrgan.py | 0 .../pytorch/mmedit/models/restorers/srgan.py | 0 .../esrgan/pytorch/mmedit/utils/__init__.py | 0 .../esrgan/pytorch/mmedit/utils/cli.py | 0 .../pytorch/mmedit/utils/collect_env.py | 0 .../esrgan/pytorch/mmedit/utils/logger.py | 0 .../esrgan/pytorch/mmedit/utils/setup_env.py | 0 .../esrgan/pytorch/mmedit/version.py | 0 .../esrgan/pytorch/requirements.txt | 0 cv/super_resolution/esrgan/pytorch/train.py | 0 cv/super_resolution/liif/pytorch/.gitignore | 0 cv/super_resolution/liif/pytorch/LICENSE | 0 cv/super_resolution/liif/pytorch/README.md | 0 .../pytorch/configs/restorers/liif/README.md | 0 .../configs/restorers/liif/README_zh-CN.md | 0 .../liif_edsr_norm_c64b16_g1_1000k_div2k.py | 0 ...iif_rdn_norm_x2-4_c64b16_g1_1000k_div2k.py | 0 .../configs/restorers/liif/metafile.yml | 0 cv/super_resolution/liif/pytorch/dist_test.sh | 0 .../liif/pytorch/dist_train.sh | 0 .../liif/pytorch/docker/Dockerfile | 0 .../liif/pytorch/docker/README.md | 0 .../liif/pytorch/mmcv/device/ipu/__init__.py | 0 .../pytorch/mmcv/device/ipu/dataloader.py | 0 .../device/ipu/hierarchical_data_manager.py | 0 .../pytorch/mmcv/device/ipu/hook_wrapper.py | 0 .../pytorch/mmcv/device/ipu/model_wrapper.py | 0 .../liif/pytorch/mmcv/device/ipu/runner.py | 0 .../liif/pytorch/mmcv/device/ipu/utils.py | 0 .../liif/pytorch/mmedit/__init__.py | 0 .../liif/pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/generation_inference.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../liif/pytorch/mmedit/apis/test.py | 0 .../liif/pytorch/mmedit/apis/train.py | 0 .../liif/pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../liif/pytorch/mmedit/core/hooks/ema.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../liif/pytorch/mmedit/core/mask.py | 0 .../liif/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../pytorch/mmedit/core/utils/__init__.py | 0 .../pytorch/mmedit/core/utils/dist_utils.py | 0 .../liif/pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../liif/pytorch/mmedit/datasets/builder.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../datasets/pipelines/generate_assistant.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../datasets/pipelines/normalization.py | 0 .../pipelines/random_down_sampling.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../liif/pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../mmedit/datasets/sr_folder_dataset.py | 0 .../mmedit/datasets/sr_folder_gt_dataset.py | 0 .../liif/pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../models/backbones/sr_backbones/liif_net.py | 0 .../liif/pytorch/mmedit/models/base.py | 0 .../liif/pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../liif/pytorch/mmedit/models/common/aspp.py | 0 .../models/common/contextual_attention.py | 0 .../liif/pytorch/mmedit/models/common/conv.py | 0 .../mmedit/models/common/downsample.py | 0 .../pytorch/mmedit/models/common/ensemble.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/gated_conv_module.py | 0 .../mmedit/models/common/gca_module.py | 0 .../models/common/generation_model_utils.py | 0 .../mmedit/models/common/img_normalize.py | 0 .../mmedit/models/common/linear_module.py | 0 .../mmedit/models/common/mask_conv_module.py | 0 .../mmedit/models/common/model_utils.py | 0 .../mmedit/models/common/partial_conv.py | 0 .../models/common/separable_conv_module.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../mmedit/models/components/__init__.py | 0 .../models/components/refiners/__init__.py | 0 .../models/components/refiners/mlp_refiner.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../liif/pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../pytorch/mmedit/models/restorers/liif.py | 0 .../liif/pytorch/mmedit/utils/__init__.py | 0 .../liif/pytorch/mmedit/utils/cli.py | 0 .../liif/pytorch/mmedit/utils/collect_env.py | 0 .../liif/pytorch/mmedit/utils/logger.py | 0 .../liif/pytorch/mmedit/utils/setup_env.py | 0 .../liif/pytorch/mmedit/version.py | 0 .../liif/pytorch/requirements.txt | 0 cv/super_resolution/liif/pytorch/test.py | 0 cv/super_resolution/liif/pytorch/train.py | 0 .../real_basicVSR/pytorch/.gitignore | 0 .../real_basicVSR/pytorch/LICENSE | 0 .../real_basicVSR/pytorch/README.md | 0 .../real_basicVSR/pytorch/build_env.sh | 0 ...basicvsr_c64b20_1x30x8_lr5e-5_150k_reds.py | 0 ...sr_wogan_c64b20_2x30x8_lr1e-4_300k_reds.py | 0 .../real_basicVSR/pytorch/crop_sub_images.py | 0 .../real_basicVSR/pytorch/dist_train.sh | 0 .../real_basicVSR/pytorch/docker/Dockerfile | 0 .../real_basicVSR/pytorch/docker/README.md | 0 .../real_basicVSR/pytorch/mmcv/__init__.py | 0 .../pytorch/mmcv/arraymisc/__init__.py | 0 .../pytorch/mmcv/arraymisc/quantization.py | 0 .../pytorch/mmcv/cnn/__init__.py | 0 .../real_basicVSR/pytorch/mmcv/cnn/alexnet.py | 0 .../pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../pytorch/mmcv/cnn/bricks/norm.py | 0 .../pytorch/mmcv/cnn/bricks/padding.py | 0 .../pytorch/mmcv/cnn/bricks/plugin.py | 0 .../pytorch/mmcv/cnn/bricks/registry.py | 0 .../pytorch/mmcv/cnn/bricks/scale.py | 0 .../pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../pytorch/mmcv/cnn/bricks/upsample.py | 0 .../pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../real_basicVSR/pytorch/mmcv/cnn/builder.py | 0 .../real_basicVSR/pytorch/mmcv/cnn/resnet.py | 0 .../pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../real_basicVSR/pytorch/mmcv/cnn/vgg.py | 0 .../pytorch/mmcv/engine/__init__.py | 0 .../real_basicVSR/pytorch/mmcv/engine/test.py | 0 .../pytorch/mmcv/fileio/__init__.py | 0 .../pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../real_basicVSR/pytorch/mmcv/fileio/io.py | 0 .../pytorch/mmcv/fileio/parse.py | 0 .../pytorch/mmcv/image/__init__.py | 0 .../pytorch/mmcv/image/colorspace.py | 0 .../pytorch/mmcv/image/geometric.py | 0 .../real_basicVSR/pytorch/mmcv/image/io.py | 0 .../real_basicVSR/pytorch/mmcv/image/misc.py | 0 .../pytorch/mmcv/image/photometric.py | 0 .../pytorch/mmcv/ops/__init__.py | 0 .../csrc/common/cuda/common_cuda_helper.hpp | 0 .../modulated_deform_conv_cuda_kernel.cuh | 0 .../csrc/common/cuda/sync_bn_cuda_kernel.cuh | 0 .../ops/csrc/common/pytorch_cpp_helper.hpp | 0 .../ops/csrc/common/pytorch_cuda_helper.hpp | 0 .../cuda/modulated_deform_conv_cuda.cu | 0 .../ops/csrc/pytorch/cuda/sync_bn_cuda.cu | 0 .../pytorch/mmcv/ops/csrc/pytorch/info.cpp | 0 .../csrc/pytorch/modulated_deform_conv.cpp | 0 .../pytorch/modulated_deform_conv_cpu.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/pybind.cpp | 0 .../pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp | 0 .../pytorch/mmcv/ops/deprecated_wrappers.py | 0 .../real_basicVSR/pytorch/mmcv/ops/info.py | 0 .../pytorch/mmcv/ops/modulated_deform_conv.py | 0 .../real_basicVSR/pytorch/mmcv/ops/sync_bn.py | 0 .../pytorch/mmcv/parallel/__init__.py | 0 .../pytorch/mmcv/parallel/_functions.py | 0 .../pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../pytorch/mmcv/parallel/utils.py | 0 .../pytorch/mmcv/runner/__init__.py | 0 .../pytorch/mmcv/runner/base_module.py | 0 .../pytorch/mmcv/runner/base_runner.py | 0 .../pytorch/mmcv/runner/builder.py | 0 .../pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../pytorch/mmcv/runner/priority.py | 0 .../pytorch/mmcv/runner/utils.py | 0 .../pytorch/mmcv/utils/__init__.py | 0 .../pytorch/mmcv/utils/config.py | 0 .../real_basicVSR/pytorch/mmcv/utils/env.py | 0 .../pytorch/mmcv/utils/ext_loader.py | 0 .../pytorch/mmcv/utils/logging.py | 0 .../real_basicVSR/pytorch/mmcv/utils/misc.py | 0 .../pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../real_basicVSR/pytorch/mmcv/utils/path.py | 0 .../pytorch/mmcv/utils/progressbar.py | 0 .../pytorch/mmcv/utils/registry.py | 0 .../pytorch/mmcv/utils/testing.py | 0 .../real_basicVSR/pytorch/mmcv/utils/timer.py | 0 .../real_basicVSR/pytorch/mmcv/utils/trace.py | 0 .../pytorch/mmcv/utils/version_utils.py | 0 .../real_basicVSR/pytorch/mmcv/version.py | 0 .../real_basicVSR/pytorch/mmedit/__init__.py | 0 .../pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/generation_inference.py | 0 .../mmedit/apis/inpainting_inference.py | 0 .../pytorch/mmedit/apis/matting_inference.py | 0 .../mmedit/apis/restoration_face_inference.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../apis/restoration_video_inference.py | 0 .../real_basicVSR/pytorch/mmedit/apis/test.py | 0 .../pytorch/mmedit/apis/train.py | 0 .../apis/video_interpolation_inference.py | 0 .../pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../pytorch/mmedit/core/hooks/ema.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../real_basicVSR/pytorch/mmedit/core/mask.py | 0 .../real_basicVSR/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../pytorch/mmedit/core/utils/__init__.py | 0 .../pytorch/mmedit/core/utils/dist_utils.py | 0 .../pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../pytorch/mmedit/datasets/builder.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/blur_kernels.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../pytorch/mmedit/datasets/pipelines/crop.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../datasets/pipelines/matlab_like_resize.py | 0 .../datasets/pipelines/normalization.py | 0 .../datasets/pipelines/random_degradations.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/sr_folder_multiple_gt_dataset.py | 0 .../pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../backbones/sr_backbones/basicvsr_net.py | 0 .../sr_backbones/real_basicvsr_net.py | 0 .../pytorch/mmedit/models/base.py | 0 .../pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../pytorch/mmedit/models/common/aspp.py | 0 .../models/common/contextual_attention.py | 0 .../pytorch/mmedit/models/common/conv.py | 0 .../mmedit/models/common/downsample.py | 0 .../pytorch/mmedit/models/common/ensemble.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/gated_conv_module.py | 0 .../mmedit/models/common/gca_module.py | 0 .../models/common/generation_model_utils.py | 0 .../mmedit/models/common/img_normalize.py | 0 .../mmedit/models/common/linear_module.py | 0 .../mmedit/models/common/mask_conv_module.py | 0 .../mmedit/models/common/model_utils.py | 0 .../mmedit/models/common/partial_conv.py | 0 .../models/common/separable_conv_module.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../mmedit/models/components/__init__.py | 0 .../components/discriminators/__init__.py | 0 .../components/discriminators/unet_disc.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../pytorch/mmedit/models/losses/gan_loss.py | 0 .../mmedit/models/losses/perceptual_loss.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../mmedit/models/restorers/real_basicvsr.py | 0 .../mmedit/models/restorers/real_esrgan.py | 0 .../pytorch/mmedit/models/restorers/srgan.py | 0 .../pytorch/mmedit/utils/__init__.py | 0 .../real_basicVSR/pytorch/mmedit/utils/cli.py | 0 .../pytorch/mmedit/utils/collect_env.py | 0 .../pytorch/mmedit/utils/logger.py | 0 .../pytorch/mmedit/utils/setup_env.py | 0 .../real_basicVSR/pytorch/mmedit/version.py | 0 .../real_basicVSR/pytorch/requirements.txt | 0 .../real_basicVSR/pytorch/setup.py | 0 .../real_basicVSR/pytorch/train.py | 0 cv/super_resolution/ttsr/pytorch/.gitignore | 0 cv/super_resolution/ttsr/pytorch/LICENSE | 0 cv/super_resolution/ttsr/pytorch/README.md | 0 .../ttsr/pytorch/checkpoints/args.txt | 0 .../ttsr/pytorch/checkpoints/train.log | 0 .../ttsr/pytorch/dataset/cufed.py | 0 .../ttsr/pytorch/dataset/dataloader.py | 0 cv/super_resolution/ttsr/pytorch/eval.sh | 0 .../ttsr/pytorch/loss/discriminator.py | 0 cv/super_resolution/ttsr/pytorch/loss/loss.py | 0 cv/super_resolution/ttsr/pytorch/main.py | 0 cv/super_resolution/ttsr/pytorch/model/LTE.py | 0 .../ttsr/pytorch/model/MainNet.py | 0 .../ttsr/pytorch/model/SearchTransfer.py | 0 .../ttsr/pytorch/model/TTSR.py | 0 .../ttsr/pytorch/model/Vgg19.py | 0 cv/super_resolution/ttsr/pytorch/option.py | 0 .../ttsr/pytorch/requirements.txt | 0 cv/super_resolution/ttsr/pytorch/test.sh | 0 .../ttsr/pytorch/test/demo/lr/0.png | Bin .../ttsr/pytorch/test/demo/ref/0.png | Bin cv/super_resolution/ttsr/pytorch/train.sh | 0 cv/super_resolution/ttsr/pytorch/trainer.py | 0 cv/super_resolution/ttsr/pytorch/utils.py | 0 cv/super_resolution/ttvsr/pytorch/LICENSE | 0 cv/super_resolution/ttvsr/pytorch/README.md | 0 .../ttvsr/pytorch/configs/TTVSR_reds4.py | 0 .../ttvsr/pytorch/dist_train.sh | 0 .../ttvsr/pytorch/mmcv/__init__.py | 0 .../ttvsr/pytorch/mmcv/cnn/__init__.py | 0 .../ttvsr/pytorch/mmcv/cnn/alexnet.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/__init__.py | 0 .../pytorch/mmcv/cnn/bricks/activation.py | 0 .../pytorch/mmcv/cnn/bricks/context_block.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/conv.py | 0 .../cnn/bricks/conv2d_adaptive_padding.py | 0 .../pytorch/mmcv/cnn/bricks/conv_module.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/conv_ws.py | 0 .../bricks/depthwise_separable_conv_module.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/drop.py | 0 .../mmcv/cnn/bricks/generalized_attention.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/hsigmoid.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/hswish.py | 0 .../pytorch/mmcv/cnn/bricks/non_local.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/norm.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/padding.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/plugin.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/registry.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/scale.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/swish.py | 0 .../pytorch/mmcv/cnn/bricks/transformer.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/upsample.py | 0 .../ttvsr/pytorch/mmcv/cnn/bricks/wrappers.py | 0 .../ttvsr/pytorch/mmcv/cnn/builder.py | 0 .../ttvsr/pytorch/mmcv/cnn/resnet.py | 0 .../ttvsr/pytorch/mmcv/cnn/utils/__init__.py | 0 .../pytorch/mmcv/cnn/utils/flops_counter.py | 0 .../pytorch/mmcv/cnn/utils/fuse_conv_bn.py | 0 .../ttvsr/pytorch/mmcv/cnn/utils/sync_bn.py | 0 .../pytorch/mmcv/cnn/utils/weight_init.py | 0 .../ttvsr/pytorch/mmcv/cnn/vgg.py | 0 .../ttvsr/pytorch/mmcv/engine/__init__.py | 0 .../ttvsr/pytorch/mmcv/engine/test.py | 0 .../ttvsr/pytorch/mmcv/fileio/__init__.py | 0 .../ttvsr/pytorch/mmcv/fileio/file_client.py | 0 .../pytorch/mmcv/fileio/handlers/__init__.py | 0 .../pytorch/mmcv/fileio/handlers/base.py | 0 .../mmcv/fileio/handlers/json_handler.py | 0 .../mmcv/fileio/handlers/pickle_handler.py | 0 .../mmcv/fileio/handlers/yaml_handler.py | 0 .../ttvsr/pytorch/mmcv/fileio/io.py | 0 .../ttvsr/pytorch/mmcv/fileio/parse.py | 0 .../ttvsr/pytorch/mmcv/image/__init__.py | 0 .../ttvsr/pytorch/mmcv/image/colorspace.py | 0 .../ttvsr/pytorch/mmcv/image/geometric.py | 0 .../ttvsr/pytorch/mmcv/image/io.py | 0 .../ttvsr/pytorch/mmcv/image/misc.py | 0 .../ttvsr/pytorch/mmcv/image/photometric.py | 0 .../ttvsr/pytorch/mmcv/parallel/__init__.py | 0 .../ttvsr/pytorch/mmcv/parallel/_functions.py | 0 .../ttvsr/pytorch/mmcv/parallel/collate.py | 0 .../pytorch/mmcv/parallel/data_container.py | 0 .../pytorch/mmcv/parallel/data_parallel.py | 0 .../pytorch/mmcv/parallel/distributed.py | 0 .../mmcv/parallel/distributed_deprecated.py | 0 .../ttvsr/pytorch/mmcv/parallel/registry.py | 0 .../pytorch/mmcv/parallel/scatter_gather.py | 0 .../ttvsr/pytorch/mmcv/parallel/utils.py | 0 .../ttvsr/pytorch/mmcv/runner/__init__.py | 0 .../ttvsr/pytorch/mmcv/runner/base_module.py | 0 .../ttvsr/pytorch/mmcv/runner/base_runner.py | 0 .../ttvsr/pytorch/mmcv/runner/builder.py | 0 .../ttvsr/pytorch/mmcv/runner/checkpoint.py | 0 .../mmcv/runner/default_constructor.py | 0 .../ttvsr/pytorch/mmcv/runner/dist_utils.py | 0 .../pytorch/mmcv/runner/epoch_based_runner.py | 0 .../ttvsr/pytorch/mmcv/runner/fp16_utils.py | 0 .../pytorch/mmcv/runner/hooks/__init__.py | 0 .../pytorch/mmcv/runner/hooks/checkpoint.py | 0 .../pytorch/mmcv/runner/hooks/closure.py | 0 .../ttvsr/pytorch/mmcv/runner/hooks/ema.py | 0 .../pytorch/mmcv/runner/hooks/evaluation.py | 0 .../ttvsr/pytorch/mmcv/runner/hooks/hook.py | 0 .../pytorch/mmcv/runner/hooks/iter_timer.py | 0 .../mmcv/runner/hooks/logger/__init__.py | 0 .../pytorch/mmcv/runner/hooks/logger/base.py | 0 .../mmcv/runner/hooks/logger/dvclive.py | 0 .../mmcv/runner/hooks/logger/mlflow.py | 0 .../mmcv/runner/hooks/logger/neptune.py | 0 .../pytorch/mmcv/runner/hooks/logger/pavi.py | 0 .../mmcv/runner/hooks/logger/tensorboard.py | 0 .../pytorch/mmcv/runner/hooks/logger/text.py | 0 .../pytorch/mmcv/runner/hooks/logger/wandb.py | 0 .../pytorch/mmcv/runner/hooks/lr_updater.py | 0 .../ttvsr/pytorch/mmcv/runner/hooks/memory.py | 0 .../mmcv/runner/hooks/momentum_updater.py | 0 .../pytorch/mmcv/runner/hooks/optimizer.py | 0 .../pytorch/mmcv/runner/hooks/profiler.py | 0 .../pytorch/mmcv/runner/hooks/sampler_seed.py | 0 .../pytorch/mmcv/runner/hooks/sync_buffer.py | 0 .../pytorch/mmcv/runner/iter_based_runner.py | 0 .../ttvsr/pytorch/mmcv/runner/log_buffer.py | 0 .../pytorch/mmcv/runner/optimizer/__init__.py | 0 .../pytorch/mmcv/runner/optimizer/builder.py | 0 .../runner/optimizer/default_constructor.py | 0 .../ttvsr/pytorch/mmcv/runner/priority.py | 0 .../ttvsr/pytorch/mmcv/runner/utils.py | 0 .../ttvsr/pytorch/mmcv/utils/__init__.py | 0 .../ttvsr/pytorch/mmcv/utils/config.py | 0 .../ttvsr/pytorch/mmcv/utils/env.py | 0 .../ttvsr/pytorch/mmcv/utils/ext_loader.py | 0 .../ttvsr/pytorch/mmcv/utils/logging.py | 0 .../ttvsr/pytorch/mmcv/utils/misc.py | 0 .../ttvsr/pytorch/mmcv/utils/parrots_jit.py | 0 .../pytorch/mmcv/utils/parrots_wrapper.py | 0 .../ttvsr/pytorch/mmcv/utils/path.py | 0 .../ttvsr/pytorch/mmcv/utils/progressbar.py | 0 .../ttvsr/pytorch/mmcv/utils/registry.py | 0 .../ttvsr/pytorch/mmcv/utils/testing.py | 0 .../ttvsr/pytorch/mmcv/utils/timer.py | 0 .../ttvsr/pytorch/mmcv/utils/trace.py | 0 .../ttvsr/pytorch/mmcv/utils/version_utils.py | 0 .../ttvsr/pytorch/mmcv/version.py | 0 .../ttvsr/pytorch/mmedit/__init__.py | 0 .../ttvsr/pytorch/mmedit/apis/__init__.py | 0 .../mmedit/apis/restoration_inference.py | 0 .../apis/restoration_video_inference.py | 0 .../ttvsr/pytorch/mmedit/apis/test.py | 0 .../ttvsr/pytorch/mmedit/apis/train.py | 0 .../ttvsr/pytorch/mmedit/core/__init__.py | 0 .../mmedit/core/distributed_wrapper.py | 0 .../mmedit/core/evaluation/__init__.py | 0 .../mmedit/core/evaluation/eval_hooks.py | 0 .../mmedit/core/evaluation/metric_utils.py | 0 .../pytorch/mmedit/core/evaluation/metrics.py | 0 .../core/evaluation/niqe_pris_params.npz | Bin .../pytorch/mmedit/core/export/__init__.py | 0 .../pytorch/mmedit/core/export/wrappers.py | 0 .../pytorch/mmedit/core/hooks/__init__.py | 0 .../mmedit/core/hooks/visualization.py | 0 .../ttvsr/pytorch/mmedit/core/mask.py | 0 .../ttvsr/pytorch/mmedit/core/misc.py | 0 .../pytorch/mmedit/core/optimizer/__init__.py | 0 .../pytorch/mmedit/core/optimizer/builder.py | 0 .../pytorch/mmedit/core/scheduler/__init__.py | 0 .../mmedit/core/scheduler/lr_updater.py | 0 .../ttvsr/pytorch/mmedit/datasets/__init__.py | 0 .../pytorch/mmedit/datasets/base_dataset.py | 0 .../mmedit/datasets/base_sr_dataset.py | 0 .../ttvsr/pytorch/mmedit/datasets/builder.py | 0 .../mmedit/datasets/dataset_wrappers.py | 0 .../mmedit/datasets/pipelines/__init__.py | 0 .../mmedit/datasets/pipelines/augmentation.py | 0 .../mmedit/datasets/pipelines/compose.py | 0 .../pytorch/mmedit/datasets/pipelines/crop.py | 0 .../mmedit/datasets/pipelines/formating.py | 0 .../datasets/pipelines/generate_assistant.py | 0 .../mmedit/datasets/pipelines/loading.py | 0 .../mmedit/datasets/pipelines/matting_aug.py | 0 .../datasets/pipelines/normalization.py | 0 .../pipelines/random_down_sampling.py | 0 .../mmedit/datasets/pipelines/utils.py | 0 .../ttvsr/pytorch/mmedit/datasets/registry.py | 0 .../mmedit/datasets/samplers/__init__.py | 0 .../datasets/samplers/distributed_sampler.py | 0 .../datasets/sr_folder_multiple_gt_dataset.py | 0 .../datasets/sr_reds_multiple_gt_dataset.py | 0 .../mmedit/datasets/sr_vimeo90k_dataset.py | 0 .../sr_vimeo90k_multiple_gt_dataset.py | 0 .../ttvsr/pytorch/mmedit/models/__init__.py | 0 .../mmedit/models/backbones/__init__.py | 0 .../models/backbones/sr_backbones/__init__.py | 0 .../models/backbones/sr_backbones/ttvsrnet.py | 0 .../ttvsr/pytorch/mmedit/models/base.py | 0 .../ttvsr/pytorch/mmedit/models/builder.py | 0 .../pytorch/mmedit/models/common/__init__.py | 0 .../pytorch/mmedit/models/common/flow_warp.py | 0 .../mmedit/models/common/sr_backbone_utils.py | 0 .../pytorch/mmedit/models/common/upsample.py | 0 .../pytorch/mmedit/models/losses/__init__.py | 0 .../mmedit/models/losses/pixelwise_loss.py | 0 .../pytorch/mmedit/models/losses/utils.py | 0 .../ttvsr/pytorch/mmedit/models/registry.py | 0 .../mmedit/models/restorers/__init__.py | 0 .../mmedit/models/restorers/basic_restorer.py | 0 .../pytorch/mmedit/models/restorers/ttvsr.py | 0 .../ttvsr/pytorch/mmedit/utils/__init__.py | 0 .../ttvsr/pytorch/mmedit/utils/collect_env.py | 0 .../ttvsr/pytorch/mmedit/utils/logger.py | 0 .../ttvsr/pytorch/mmedit/version.py | 0 .../ttvsr/pytorch/requirements.txt | 0 cv/super_resolution/ttvsr/pytorch/setup.py | 0 .../ttvsr/pytorch/tools/dist_test.sh | 0 .../ttvsr/pytorch/tools/slurm_test.sh | 0 .../ttvsr/pytorch/tools/slurm_train.sh | 0 .../ttvsr/pytorch/tools/test.py | 0 cv/super_resolution/ttvsr/pytorch/train.py | 0 fairseq-tools/README_bart.md | 51 + fairseq-tools/README_convolutional.md | 51 + fairseq-tools/README_environment.md | 13 + fairseq-tools/README_roberta.md | 51 + fairseq-tools/README_transformer.md | 57 + .../fairseq/.github/ISSUE_TEMPLATE.md | 3 + .../.github/ISSUE_TEMPLATE/bug_report.md | 43 + .../.github/ISSUE_TEMPLATE/documentation.md | 15 + .../.github/ISSUE_TEMPLATE/feature_request.md | 24 + .../.github/ISSUE_TEMPLATE/how-to-question.md | 33 + .../fairseq/.github/PULL_REQUEST_TEMPLATE.md | 16 + .../fairseq/.github/workflows/build.yml | 50 + .../.github/workflows/build_wheels.yml | 41 + fairseq-tools/fairseq/.gitignore | 132 + fairseq-tools/fairseq/.gitmodules | 4 + fairseq-tools/fairseq/CODE_OF_CONDUCT.md | 77 + fairseq-tools/fairseq/CONTRIBUTING.md | 28 + fairseq-tools/fairseq/LICENSE | 21 + fairseq-tools/fairseq/bart.py | 40 + fairseq-tools/fairseq/bart.sh | 49 + fairseq-tools/fairseq/config/config.yaml | 7 + .../fairseq/config/config_eval_lm.yaml | 7 + .../config/criterion/adaptive_loss.yaml | 3 + .../config/criterion/cross_entropy.yaml | 3 + .../fairseq/config/lr_scheduler/cosine.yaml | 7 + .../config/lr_scheduler/inverse_sqrt.yaml | 3 + .../fairseq/config/model/transformer_lm.yaml | 36 + .../model/transformer_lm_baevski_gbw.yaml | 36 + .../model/transformer_lm_baevski_wiki103.yaml | 36 + .../config/model/transformer_lm_big.yaml | 36 + .../config/model/transformer_lm_gbw.yaml | 36 + .../config/model/transformer_lm_gpt.yaml | 36 + .../config/model/transformer_lm_gpt2_big.yaml | 36 + .../model/transformer_lm_gpt2_medium.yaml | 36 + .../model/transformer_lm_gpt2_small.yaml | 36 + .../config/model/transformer_lm_wiki103.yaml | 36 + .../fairseq/config/optimizer/adam.yaml | 5 + .../fairseq/config/optimizer/nag.yaml | 3 + .../fairseq/config/params/eval_lm_params.yaml | 105 + .../config/params/training_params.yaml | 95 + .../config/task/language_modeling.yaml | 10 + fairseq-tools/fairseq/docs/Makefile | 20 + .../fairseq/docs/_static/theme_overrides.css | 9 + .../fairseq/docs/command_line_tools.rst | 85 + fairseq-tools/fairseq/docs/conf.py | 133 + fairseq-tools/fairseq/docs/criterions.rst | 31 + fairseq-tools/fairseq/docs/data.rst | 58 + fairseq-tools/fairseq/docs/docutils.conf | 2 + fairseq-tools/fairseq/docs/fairseq.gif | Bin 0 -> 2664833 bytes fairseq-tools/fairseq/docs/fairseq_logo.png | Bin 0 -> 73036 bytes .../fairseq/docs/getting_started.rst | 206 + .../fairseq/docs/hydra_integration.md | 113 + fairseq-tools/fairseq/docs/index.rst | 49 + fairseq-tools/fairseq/docs/lr_scheduler.rst | 34 + fairseq-tools/fairseq/docs/make.bat | 36 + fairseq-tools/fairseq/docs/models.rst | 104 + fairseq-tools/fairseq/docs/modules.rst | 9 + fairseq-tools/fairseq/docs/optim.rst | 38 + fairseq-tools/fairseq/docs/overview.rst | 74 + fairseq-tools/fairseq/docs/requirements.txt | 2 + fairseq-tools/fairseq/docs/tasks.rst | 61 + .../docs/tutorial_classifying_names.rst | 415 + .../fairseq/docs/tutorial_simple_lstm.rst | 518 + fairseq-tools/fairseq/examples/.gitignore | 2 + fairseq-tools/fairseq/examples/__init__.py | 8 + .../examples/backtranslation/README.md | 297 + .../backtranslation/deduplicate_lines.py | 41 + .../backtranslation/extract_bt_data.py | 72 + .../backtranslation/prepare-de-monolingual.sh | 98 + .../backtranslation/prepare-wmt18en2de.sh | 135 + .../examples/backtranslation/sacrebleu.sh | 37 + .../backtranslation/tokenized_bleu.sh | 46 + .../fairseq/examples/bart/README.glue.md | 99 + fairseq-tools/fairseq/examples/bart/README.md | 218 + .../examples/bart/README.summarization.md | 121 + .../fairseq/examples/byte_level_bpe/README.md | 88 + .../examples/byte_level_bpe/get_bitext.py | 254 + .../examples/byte_level_bpe/get_data.sh | 47 + .../byte_level_bpe/gru_transformer.py | 107 + .../fairseq/examples/camembert/README.md | 75 + .../examples/constrained_decoding/README.md | 123 + .../constrained_decoding/normalize.py | 27 + .../examples/constrained_decoding/tok.py | 34 + .../fairseq/examples/conv_seq2seq/README.md | 25 + .../fairseq/examples/criss/README.md | 51 + .../download_and_preprocess_flores_test.sh | 64 + .../criss/download_and_preprocess_tatoeba.sh | 37 + .../fairseq/examples/criss/mining/mine.py | 233 + .../examples/criss/mining/mine_example.sh | 103 + .../fairseq/examples/criss/save_encoder.py | 213 + .../sentence_retrieval/encoder_analysis.py | 92 + .../sentence_retrieval_tatoeba.sh | 59 + .../examples/criss/unsupervised_mt/eval.sh | 37 + .../cross_lingual_language_model/README.md | 77 + .../joint_alignment_translation/README.md | 89 + ...t18en2de_no_norm_no_escape_no_agressive.sh | 118 + .../language_model/README.adaptive_inputs.md | 39 + .../examples/language_model/README.conv.md | 40 + .../fairseq/examples/language_model/README.md | 123 + .../language_model/prepare-wikitext-103.sh | 33 + .../fairseq/examples/latent_depth/README.md | 77 + .../latent_depth/latent_depth_src/__init__.py | 9 + .../latent_depth_src/loss/__init__.py | 0 .../latent_depth_src/loss/latent_depth.py | 99 + .../latent_depth_src/models/__init__.py | 0 .../models/latent_multilingual_transformer.py | 59 + .../models/latent_transformer.py | 146 + .../latent_depth_src/modules/__init__.py | 0 .../latent_depth_src/modules/latent_layers.py | 86 + .../multilingual_translation_latent_depth.py | 194 + .../fairseq/examples/layerdrop/README.md | 154 + .../fairseq/examples/linformer/README.md | 22 + .../linformer/linformer_src/__init__.py | 6 + .../linformer_src/models/__init__.py | 0 .../linformer_src/models/linformer_roberta.py | 134 + .../linformer_src/modules/__init__.py | 0 .../modules/linformer_sentence_encoder.py | 169 + .../linformer_sentence_encoder_layer.py | 84 + .../modules/multihead_linear_attention.py | 485 + .../fairseq/examples/m2m_100/README.md | 209 + .../examples/m2m_100/install_dependecies.sh | 78 + .../m2m_100/process_data/clean_histogram.py | 52 + .../m2m_100/process_data/dedup_data.py | 91 + .../process_data/remove_too_much_punc.py | 36 + fairseq-tools/fairseq/examples/m2m_100/tok.sh | 83 + .../examples/m2m_100/tokenizers/README.md | 18 + .../examples/m2m_100/tokenizers/seg_ja.sh | 11 + .../examples/m2m_100/tokenizers/seg_ko.sh | 12 + .../m2m_100/tokenizers/thirdparty/.gitignore | 12 + .../m2m_100/tokenizers/tokenize_indic.py | 23 + .../m2m_100/tokenizers/tokenize_thai.py | 13 + .../m2m_100/tokenizers/tokenize_zh.py | 14 + .../m2m_100/tokenizers/tokenizer_ar.sh | 27 + .../fairseq/examples/mbart/README.md | 123 + .../fairseq/examples/megatron_11b/README.md | 161 + .../fairseq/examples/megatron_11b/detok.py | 32 + .../fairseq/examples/multilingual/README.md | 124 + .../finetune_multilingual_model.sh | 27 + .../multilingual/multilingual_fairseq_gen.sh | 21 + .../multilingual/train_multilingual_model.sh | 23 + .../fairseq/examples/noisychannel/README.md | 72 + .../fairseq/examples/noisychannel/__init__.py | 6 + .../fairseq/examples/noisychannel/rerank.py | 422 + .../examples/noisychannel/rerank_generate.py | 397 + .../examples/noisychannel/rerank_options.py | 149 + .../examples/noisychannel/rerank_score_bw.py | 143 + .../examples/noisychannel/rerank_score_lm.py | 81 + .../examples/noisychannel/rerank_tune.py | 102 + .../examples/noisychannel/rerank_utils.py | 850 + .../nonautoregressive_translation/README.md | 146 + .../nonautoregressive_translation/scripts.md | 179 + .../fairseq/examples/paraphraser/README.md | 46 + .../examples/paraphraser/paraphrase.py | 85 + .../pay_less_attention_paper/README.md | 176 + .../examples/pointer_generator/README.md | 82 + .../examples/pointer_generator/README.xsum.md | 180 + .../pointer_generator_src/__init__.py | 6 + .../pointer_generator_src/transformer_pg.py | 468 + .../examples/pointer_generator/postprocess.py | 96 + .../examples/pointer_generator/preprocess.py | 102 + .../fairseq/examples/quant_noise/README.md | 298 + .../transformer_quantization_config.yaml | 33 + .../roberta/README.custom_classification.md | 168 + .../fairseq/examples/roberta/README.glue.md | 99 + .../fairseq/examples/roberta/README.md | 296 + .../examples/roberta/README.pretraining.md | 98 + .../fairseq/examples/roberta/README.race.md | 68 + .../examples/roberta/commonsense_qa/README.md | 99 + .../roberta/commonsense_qa/__init__.py | 6 + .../commonsense_qa/commonsense_qa_task.py | 190 + .../commonsense_qa/download_cqa_data.sh | 14 + .../roberta/multiprocessing_bpe_encoder.py | 130 + .../examples/roberta/preprocess_GLUE_tasks.sh | 185 + .../examples/roberta/preprocess_RACE.py | 102 + .../examples/roberta/preprocess_RACE.sh | 59 + .../fairseq/examples/roberta/wsc/README.md | 125 + .../fairseq/examples/roberta/wsc/__init__.py | 7 + .../examples/roberta/wsc/wsc_criterion.py | 167 + .../fairseq/examples/roberta/wsc/wsc_task.py | 401 + .../fairseq/examples/roberta/wsc/wsc_utils.py | 241 + fairseq-tools/fairseq/examples/rxf/README.md | 52 + .../fairseq/examples/rxf/__init__.py | 6 + .../fairseq/examples/rxf/rxf_src/__init__.py | 6 + .../label_smoothed_cross_entropy_r3f.py | 157 + .../rxf/rxf_src/sentence_prediction_r3f.py | 170 + .../fairseq/examples/scaling_nmt/README.md | 114 + .../simultaneous_translation/README.md | 106 + .../simultaneous_translation/__init__.py | 6 + .../criterions/__init__.py | 15 + ...moothed_cross_entropy_latency_augmented.py | 73 + .../simultaneous_translation/docs/baseline.md | 178 + .../docs/evaluation.md | 115 + .../simultaneous_translation/eval/__init__.py | 4 + .../eval/agents/__init__.py | 24 + .../eval/agents/agent.py | 67 + .../eval/agents/simul_trans_agent.py | 167 + .../eval/agents/simul_trans_text_agent.py | 81 + .../eval/agents/word_splitter.py | 91 + .../simultaneous_translation/eval/client.py | 100 + .../eval/eval_latency.py | 78 + .../simultaneous_translation/eval/evaluate.py | 81 + .../eval/scorers/__init__.py | 19 + .../eval/scorers/scorer.py | 175 + .../eval/scorers/text_scorer.py | 41 + .../simultaneous_translation/eval/server.py | 89 + .../models/__init__.py | 15 + .../models/transformer_monotonic_attention.py | 322 + .../modules/__init__.py | 24 + .../modules/monotonic_multihead_attention.py | 622 + .../modules/monotonic_transformer_layer.py | 48 + .../utils/__init__.py | 14 + .../utils/functions.py | 149 + .../simultaneous_translation/utils/latency.py | 451 + .../examples/speech_recognition/README.md | 106 + .../examples/speech_recognition/__init__.py | 1 + .../speech_recognition/criterions/ASG_loss.py | 170 + .../speech_recognition/criterions/__init__.py | 17 + .../criterions/cross_entropy_acc.py | 130 + .../speech_recognition/data/__init__.py | 11 + .../speech_recognition/data/asr_dataset.py | 122 + .../speech_recognition/data/collaters.py | 131 + .../speech_recognition/data/data_utils.py | 100 + .../speech_recognition/data/replabels.py | 70 + .../datasets/asr_prep_json.py | 125 + .../datasets/prepare-librispeech.sh | 88 + .../examples/speech_recognition/infer.py | 464 + .../speech_recognition/models/__init__.py | 8 + .../models/vggtransformer.py | 1019 + .../models/w2l_conv_glu_enc.py | 177 + .../speech_recognition/tasks/__init__.py | 8 + .../tasks/speech_recognition.py | 157 + .../speech_recognition/utils/wer_utils.py | 381 + .../speech_recognition/w2l_decoder.py | 435 + .../fairseq/examples/speech_to_text/README.md | 216 + .../examples/speech_to_text/data_utils.py | 262 + .../speech_to_text/prep_covost_data.py | 294 + .../speech_to_text/prep_librispeech_data.py | 119 + .../speech_to_text/prep_mustc_data.py | 200 + .../fairseq/examples/stories/README.md | 66 + .../examples/translation/prepare-iwslt14.sh | 116 + .../prepare-iwslt17-multilingual.sh | 133 + .../translation/prepare-wmt14en2de.sh | 143 + .../translation/prepare-wmt14en2fr.sh | 136 + .../examples/translation_moe/README.md | 89 + .../fairseq/examples/translation_moe/score.py | 197 + .../translation_moe_src/__init__.py | 6 + .../translation_moe_src/logsumexp_moe.py | 26 + .../mean_pool_gating_network.py | 50 + .../translation_moe_src/translation_moe.py | 239 + .../unsupervised_quality_estimation/README.md | 126 + .../aggregate_scores.py | 41 + .../unsupervised_quality_estimation/meteor.py | 109 + .../repeat_lines.py | 28 + .../fairseq/examples/wav2vec/README.md | 260 + .../fairseq/examples/wav2vec/libri_labels.py | 56 + .../examples/wav2vec/vq-wav2vec_featurize.py | 253 + .../examples/wav2vec/wav2vec_featurize.py | 251 + .../examples/wav2vec/wav2vec_manifest.py | 76 + .../fairseq/examples/wmt19/README.md | 85 + fairseq-tools/fairseq/examples/xlmr/README.md | 123 + fairseq-tools/fairseq/fairseq/__init__.py | 30 + .../fairseq/fairseq/benchmark/__init__.py | 7 + .../fairseq/fairseq/benchmark/dummy_lm.py | 119 + .../fairseq/benchmark/dummy_masked_lm.py | 127 + .../fairseq/fairseq/benchmark/dummy_model.py | 96 + .../fairseq/fairseq/benchmark/dummy_mt.py | 119 + fairseq-tools/fairseq/fairseq/binarizer.py | 105 + .../fairseq/fairseq/checkpoint_utils.py | 573 + .../fairseq/fairseq/clib/libbleu/libbleu.cpp | 141 + .../fairseq/fairseq/clib/libbleu/module.cpp | 37 + .../fairseq/fairseq/clib/libnat/edit_dist.cpp | 231 + .../fairseq/clib/libnat_cuda/binding.cpp | 60 + .../fairseq/clib/libnat_cuda/edit_dist.cu | 332 + .../fairseq/clib/libnat_cuda/edit_dist.h | 25 + .../fairseq/fairseq/criterions/__init__.py | 38 + .../fairseq/criterions/adaptive_loss.py | 123 + .../fairseq/criterions/composite_loss.py | 100 + .../fairseq/criterions/cross_entropy.py | 90 + .../fairseq/fairseq/criterions/ctc.py | 253 + .../fairseq/criterions/fairseq_criterion.py | 119 + .../label_smoothed_cross_entropy.py | 160 + ...l_smoothed_cross_entropy_with_alignment.py | 125 + .../fairseq/criterions/legacy_masked_lm.py | 177 + .../fairseq/fairseq/criterions/masked_lm.py | 91 + .../fairseq/fairseq/criterions/nat_loss.py | 180 + .../fairseq/criterions/sentence_prediction.py | 99 + .../fairseq/criterions/sentence_ranking.py | 120 + .../fairseq/criterions/wav2vec_criterion.py | 184 + .../fairseq/fairseq/data/__init__.py | 124 + .../fairseq/data/add_target_dataset.py | 70 + .../fairseq/data/append_token_dataset.py | 41 + .../fairseq/fairseq/data/audio/__init__.py | 0 .../fairseq/fairseq/data/audio/audio_utils.py | 85 + .../data/audio/feature_transforms/__init__.py | 82 + .../audio/feature_transforms/global_cmvn.py | 25 + .../audio/feature_transforms/specaugment.py | 131 + .../feature_transforms/utterance_cmvn.py | 40 + .../fairseq/data/audio/raw_audio_dataset.py | 178 + .../data/audio/speech_to_text_dataset.py | 528 + .../fairseq/data/backtranslation_dataset.py | 165 + .../fairseq/data/base_wrapper_dataset.py | 78 + .../fairseq/data/bucket_pad_length_dataset.py | 76 + .../fairseq/fairseq/data/colorize_dataset.py | 25 + .../fairseq/fairseq/data/concat_dataset.py | 124 + .../fairseq/data/concat_sentences_dataset.py | 54 + .../fairseq/fairseq/data/data_utils.py | 499 + .../fairseq/fairseq/data/data_utils_fast.pyx | 123 + .../fairseq/fairseq/data/denoising_dataset.py | 436 + .../fairseq/fairseq/data/dictionary.py | 387 + .../fairseq/fairseq/data/encoders/__init__.py | 29 + .../fairseq/fairseq/data/encoders/byte_bpe.py | 45 + .../fairseq/data/encoders/byte_utils.py | 51 + .../fairseq/fairseq/data/encoders/bytes.py | 34 + .../fairseq/data/encoders/characters.py | 30 + .../fairseq/fairseq/data/encoders/fastbpe.py | 35 + .../fairseq/fairseq/data/encoders/gpt2_bpe.py | 47 + .../fairseq/data/encoders/gpt2_bpe_utils.py | 140 + .../fairseq/data/encoders/hf_bert_bpe.py | 48 + .../fairseq/data/encoders/hf_byte_bpe.py | 43 + .../fairseq/data/encoders/moses_tokenizer.py | 51 + .../fairseq/data/encoders/nltk_tokenizer.py | 23 + .../data/encoders/sentencepiece_bpe.py | 45 + .../fairseq/data/encoders/space_tokenizer.py | 20 + .../fairseq/data/encoders/subword_nmt_bpe.py | 54 + .../fairseq/fairseq/data/encoders/utils.py | 30 + .../fairseq/fairseq/data/fairseq_dataset.py | 191 + .../fairseq/fairseq/data/fasta_dataset.py | 107 + .../fairseq/fairseq/data/id_dataset.py | 19 + .../fairseq/fairseq/data/indexed_dataset.py | 561 + .../fairseq/fairseq/data/iterators.py | 594 + .../fairseq/data/language_pair_dataset.py | 469 + .../fairseq/fairseq/data/legacy/__init__.py | 16 + .../fairseq/data/legacy/block_pair_dataset.py | 311 + .../fairseq/data/legacy/masked_lm_dataset.py | 303 + .../data/legacy/masked_lm_dictionary.py | 60 + .../fairseq/fairseq/data/list_dataset.py | 32 + .../fairseq/data/lm_context_window_dataset.py | 79 + .../fairseq/fairseq/data/lru_cache_dataset.py | 21 + .../fairseq/data/mask_tokens_dataset.py | 178 + .../fairseq/data/monolingual_dataset.py | 230 + .../fairseq/data/multi_corpus_dataset.py | 159 + .../data/multi_corpus_sampled_dataset.py | 145 + .../fairseq/data/multilingual/__init__.py | 4 + .../multilingual/multilingual_data_manager.py | 1042 + .../data/multilingual/multilingual_utils.py | 63 + .../multilingual/sampled_multi_dataset.py | 458 + .../sampled_multi_epoch_dataset.py | 199 + .../data/multilingual/sampling_method.py | 78 + .../fairseq/data/nested_dictionary_dataset.py | 125 + fairseq-tools/fairseq/fairseq/data/noising.py | 333 + .../fairseq/data/num_samples_dataset.py | 17 + .../fairseq/fairseq/data/numel_dataset.py | 31 + .../fairseq/data/offset_tokens_dataset.py | 15 + .../fairseq/fairseq/data/pad_dataset.py | 28 + .../fairseq/fairseq/data/plasma_utils.py | 91 + .../fairseq/fairseq/data/prepend_dataset.py | 28 + .../fairseq/data/prepend_token_dataset.py | 41 + .../fairseq/fairseq/data/raw_label_dataset.py | 23 + .../fairseq/fairseq/data/replace_dataset.py | 36 + .../fairseq/data/resampling_dataset.py | 140 + .../fairseq/fairseq/data/roll_dataset.py | 18 + .../fairseq/data/round_robin_zip_datasets.py | 117 + .../fairseq/fairseq/data/shorten_dataset.py | 78 + .../fairseq/fairseq/data/sort_dataset.py | 21 + .../fairseq/data/strip_token_dataset.py | 20 + .../fairseq/fairseq/data/subsample_dataset.py | 72 + .../fairseq/data/token_block_dataset.py | 168 + .../fairseq/data/token_block_utils_fast.pyx | 187 + .../fairseq/data/transform_eos_dataset.py | 120 + .../data/transform_eos_lang_pair_dataset.py | 108 + .../fairseq/fairseq/dataclass/__init__.py | 9 + .../fairseq/fairseq/dataclass/constants.py | 13 + .../fairseq/fairseq/dataclass/data_class.py | 773 + .../fairseq/fairseq/dataclass/utils.py | 221 + .../fairseq/fairseq/distributed_utils.py | 446 + fairseq-tools/fairseq/fairseq/file_io.py | 116 + fairseq-tools/fairseq/fairseq/file_utils.py | 353 + fairseq-tools/fairseq/fairseq/hub_utils.py | 294 + .../fairseq/incremental_decoding_utils.py | 51 + .../fairseq/iterative_refinement_generator.py | 359 + .../legacy_distributed_data_parallel.py | 171 + .../fairseq/fairseq/logging/__init__.py | 0 .../fairseq/fairseq/logging/meters.py | 291 + .../fairseq/fairseq/logging/metrics.py | 288 + .../fairseq/fairseq/logging/progress_bar.py | 355 + .../fairseq/model_parallel/__init__.py | 6 + .../model_parallel/criterions/__init__.py | 14 + .../vocab_parallel_cross_entropy.py | 87 + .../model_parallel/megatron_trainer.py | 66 + .../fairseq/model_parallel/models/__init__.py | 20 + .../pipeline_parallel_transformer/__init__.py | 6 + .../pipeline_parallel_transformer/layers.py | 600 + .../pipeline_parallel_transformer/model.py | 721 + .../model_parallel/models/roberta/__init__.py | 6 + .../model_parallel/models/roberta/model.py | 287 + .../model_parallel/models/transformer.py | 116 + .../model_parallel/models/transformer_lm.py | 170 + .../model_parallel/modules/__init__.py | 23 + .../modules/multihead_attention.py | 352 + .../modules/transformer_layer.py | 78 + .../modules/transformer_sentence_encoder.py | 59 + .../transformer_sentence_encoder_layer.py | 77 + .../fairseq/fairseq/models/__init__.py | 188 + .../fairseq/fairseq/models/bart/__init__.py | 7 + .../fairseq/models/bart/hub_interface.py | 201 + .../fairseq/fairseq/models/bart/model.py | 371 + .../fairseq/models/composite_encoder.py | 57 + .../models/distributed_fairseq_model.py | 103 + .../fairseq/fairseq/models/fairseq_decoder.py | 90 + .../fairseq/fairseq/models/fairseq_encoder.py | 92 + .../models/fairseq_incremental_decoder.py | 118 + .../fairseq/fairseq/models/fairseq_model.py | 554 + fairseq-tools/fairseq/fairseq/models/fconv.py | 756 + .../fairseq/fairseq/models/fconv_lm.py | 135 + .../fairseq/fairseq/models/fconv_self_att.py | 674 + .../fairseq/models/huggingface/__init__.py | 20 + .../fairseq/models/huggingface/hf_gpt2.py | 168 + .../fairseq/fairseq/models/lightconv.py | 1018 + .../fairseq/fairseq/models/lightconv_lm.py | 306 + fairseq-tools/fairseq/fairseq/models/lstm.py | 753 + .../fairseq/fairseq/models/lstm_lm.py | 142 + .../fairseq/fairseq/models/masked_lm.py | 403 + .../fairseq/fairseq/models/model_utils.py | 92 + .../models/multilingual_transformer.py | 228 + .../fairseq/fairseq/models/nat/__init__.py | 13 + .../fairseq/models/nat/cmlm_transformer.py | 162 + .../fairseq/models/nat/fairseq_nat_model.py | 159 + .../models/nat/insertion_transformer.py | 280 + ...iterative_nonautoregressive_transformer.py | 228 + .../models/nat/levenshtein_transformer.py | 502 + .../fairseq/models/nat/levenshtein_utils.py | 293 + .../fairseq/models/nat/nat_crf_transformer.py | 121 + .../models/nat/nonautoregressive_ensembles.py | 254 + .../nat/nonautoregressive_transformer.py | 440 + .../fairseq/models/roberta/__init__.py | 9 + .../fairseq/models/roberta/alignment_utils.py | 118 + .../fairseq/models/roberta/hub_interface.py | 235 + .../fairseq/fairseq/models/roberta/model.py | 524 + .../fairseq/models/roberta/model_camembert.py | 50 + .../fairseq/models/roberta/model_xlmr.py | 44 + .../fairseq/models/speech_to_text/__init__.py | 7 + .../fairseq/models/speech_to_text/berard.py | 606 + .../models/speech_to_text/s2t_transformer.py | 473 + .../fairseq/fairseq/models/transformer.py | 1018 + .../fairseq/models/transformer_align.py | 93 + .../models/transformer_from_pretrained_xlm.py | 152 + .../fairseq/fairseq/models/transformer_lm.py | 393 + .../fairseq/models/wav2vec/__init__.py | 8 + .../fairseq/fairseq/models/wav2vec/wav2vec.py | 735 + .../fairseq/models/wav2vec/wav2vec2.py | 1029 + .../fairseq/models/wav2vec/wav2vec2_asr.py | 675 + .../fairseq/fairseq/modules/__init__.py | 76 + .../fairseq/fairseq/modules/adaptive_input.py | 80 + .../fairseq/modules/adaptive_softmax.py | 268 + .../fairseq/fairseq/modules/beamable_mm.py | 49 + .../modules/character_token_embedder.py | 214 + .../fairseq/fairseq/modules/conv_tbc.py | 42 + .../fairseq/fairseq/modules/cross_entropy.py | 59 + .../fairseq/fairseq/modules/cuda_utils.cu | 203 + .../downsampled_multihead_attention.py | 316 + .../fairseq/modules/dynamic_convolution.py | 304 + .../fairseq/modules/dynamic_crf_layer.py | 189 + .../modules/dynamicconv_layer/__init__.py | 6 + .../dynamicconv_layer/cuda_function_gen.py | 223 + .../dynamicconv_layer/dynamicconv_cuda.cpp | 56 + .../dynamicconv_layer/dynamicconv_cuda.cuh | 51 + .../dynamicconv_cuda_kernel.cu | 168 + .../dynamicconv_layer/dynamicconv_layer.py | 227 + .../dynamicconv_layer/dynamiconv_cpu.cpp | 35 + .../modules/dynamicconv_layer/setup.py | 23 + .../fairseq/modules/fairseq_dropout.py | 51 + .../fairseq/modules/fp32_group_norm.py | 25 + fairseq-tools/fairseq/fairseq/modules/gelu.py | 25 + .../fairseq/fairseq/modules/grad_multiply.py | 18 + .../modules/gumbel_vector_quantizer.py | 199 + .../modules/kmeans_vector_quantizer.py | 127 + .../fairseq/fairseq/modules/layer_drop.py | 44 + .../fairseq/fairseq/modules/layer_norm.py | 50 + .../modules/learned_positional_embedding.py | 61 + .../modules/lightconv_layer/__init__.py | 6 + .../lightconv_layer/cuda_function_gen.py | 289 + .../lightconv_layer/lightconv_cuda.cpp | 54 + .../lightconv_layer/lightconv_cuda.cuh | 83 + .../lightconv_layer/lightconv_cuda_kernel.cu | 375 + .../lightconv_layer/lightconv_layer.py | 137 + .../fairseq/modules/lightconv_layer/setup.py | 23 + .../modules/lightweight_convolution.py | 310 + .../fairseq/modules/linearized_convolution.py | 104 + .../fairseq/modules/multihead_attention.py | 488 + .../fairseq/modules/positional_embedding.py | 35 + .../fairseq/fairseq/modules/quant_noise.py | 107 + .../fairseq/modules/quantization/__init__.py | 0 .../modules/quantization/pq/__init__.py | 6 + .../fairseq/modules/quantization/pq/em.py | 211 + .../quantization/pq/modules/__init__.py | 8 + .../modules/quantization/pq/modules/qconv.py | 115 + .../modules/quantization/pq/modules/qemb.py | 107 + .../quantization/pq/modules/qlinear.py | 71 + .../fairseq/modules/quantization/pq/pq.py | 128 + .../fairseq/modules/quantization/pq/utils.py | 337 + .../quantization/quantization_options.py | 44 + .../modules/quantization/scalar/__init__.py | 6 + .../quantization/scalar/modules/__init__.py | 9 + .../quantization/scalar/modules/qact.py | 88 + .../quantization/scalar/modules/qconv.py | 149 + .../quantization/scalar/modules/qemb.py | 147 + .../quantization/scalar/modules/qlinear.py | 113 + .../modules/quantization/scalar/ops.py | 49 + .../modules/quantization/scalar/utils.py | 77 + .../fairseq/fairseq/modules/same_pad.py | 18 + .../fairseq/fairseq/modules/scalar_bias.py | 31 + .../sinusoidal_positional_embedding.py | 105 + .../modules/sparse_multihead_attention.py | 140 + .../sparse_transformer_sentence_encoder.py | 96 + ...arse_transformer_sentence_encoder_layer.py | 51 + .../fairseq/modules/transformer_layer.py | 423 + .../modules/transformer_sentence_encoder.py | 286 + .../transformer_sentence_encoder_layer.py | 134 + .../fairseq/fairseq/modules/transpose_last.py | 20 + .../fairseq/fairseq/modules/unfold.py | 19 + .../fairseq/fairseq/modules/vggblock.py | 116 + fairseq-tools/fairseq/fairseq/nan_detector.py | 108 + .../fairseq/fairseq/optim/__init__.py | 52 + .../fairseq/fairseq/optim/adadelta.py | 47 + .../fairseq/fairseq/optim/adafactor.py | 268 + .../fairseq/fairseq/optim/adagrad.py | 40 + fairseq-tools/fairseq/fairseq/optim/adam.py | 223 + fairseq-tools/fairseq/fairseq/optim/adamax.py | 172 + fairseq-tools/fairseq/fairseq/optim/bmuf.py | 231 + .../fairseq/optim/dynamic_loss_scaler.py | 70 + .../fairseq/optim/fairseq_optimizer.py | 150 + .../fairseq/fairseq/optim/fp16_optimizer.py | 491 + .../fairseq/fairseq/optim/fused_adam.py | 348 + .../fairseq/fairseq/optim/fused_lamb.py | 51 + .../fairseq/optim/lr_scheduler/__init__.py | 38 + .../optim/lr_scheduler/cosine_lr_scheduler.py | 145 + .../lr_scheduler/fairseq_lr_scheduler.py | 60 + .../optim/lr_scheduler/fixed_schedule.py | 69 + .../inverse_square_root_schedule.py | 85 + .../lr_scheduler/polynomial_decay_schedule.py | 81 + .../lr_scheduler/reduce_lr_on_plateau.py | 115 + .../lr_scheduler/tri_stage_lr_scheduler.py | 165 + .../lr_scheduler/triangular_lr_scheduler.py | 74 + fairseq-tools/fairseq/fairseq/optim/nag.py | 108 + fairseq-tools/fairseq/fairseq/optim/sgd.py | 43 + fairseq-tools/fairseq/fairseq/optim/shard.py | 41 + fairseq-tools/fairseq/fairseq/options.py | 441 + fairseq-tools/fairseq/fairseq/pdb.py | 47 + .../fairseq/fairseq/quantization_utils.py | 142 + fairseq-tools/fairseq/fairseq/registry.py | 106 + .../fairseq/fairseq/scoring/__init__.py | 61 + fairseq-tools/fairseq/fairseq/scoring/bleu.py | 157 + fairseq-tools/fairseq/fairseq/scoring/chrf.py | 27 + .../fairseq/fairseq/scoring/tokenizer.py | 65 + fairseq-tools/fairseq/fairseq/scoring/wer.py | 55 + fairseq-tools/fairseq/fairseq/search.py | 814 + .../fairseq/fairseq/sequence_generator.py | 1008 + .../fairseq/fairseq/sequence_scorer.py | 153 + .../fairseq/fairseq/tasks/__init__.py | 106 + .../fairseq/tasks/audio_pretraining.py | 146 + .../fairseq/fairseq/tasks/cross_lingual_lm.py | 191 + .../fairseq/fairseq/tasks/denoising.py | 210 + .../fairseq/fairseq/tasks/fairseq_task.py | 566 + .../fairseq/tasks/language_modeling.py | 327 + .../fairseq/fairseq/tasks/legacy_masked_lm.py | 152 + .../fairseq/fairseq/tasks/masked_lm.py | 247 + .../fairseq/tasks/multilingual_denoising.py | 254 + .../fairseq/tasks/multilingual_masked_lm.py | 338 + .../fairseq/tasks/multilingual_translation.py | 449 + .../tasks/semisupervised_translation.py | 485 + .../fairseq/tasks/sentence_prediction.py | 281 + .../fairseq/fairseq/tasks/sentence_ranking.py | 219 + .../fairseq/fairseq/tasks/speech_to_text.py | 143 + .../fairseq/fairseq/tasks/translation.py | 448 + .../tasks/translation_from_pretrained_bart.py | 132 + .../tasks/translation_from_pretrained_xlm.py | 31 + .../fairseq/fairseq/tasks/translation_lev.py | 189 + .../tasks/translation_multi_simple_epoch.py | 414 + .../fairseq/token_generation_constraints.py | 506 + fairseq-tools/fairseq/fairseq/tokenizer.py | 15 + fairseq-tools/fairseq/fairseq/trainer.py | 1141 + fairseq-tools/fairseq/fairseq/utils.py | 701 + fairseq-tools/fairseq/fairseq_cli/__init__.py | 0 fairseq-tools/fairseq/fairseq_cli/eval_lm.py | 279 + fairseq-tools/fairseq/fairseq_cli/generate.py | 383 + .../fairseq/fairseq_cli/interactive.py | 311 + .../fairseq/fairseq_cli/preprocess.py | 398 + fairseq-tools/fairseq/fairseq_cli/score.py | 96 + fairseq-tools/fairseq/fairseq_cli/train.py | 356 + fairseq-tools/fairseq/fairseq_cli/validate.py | 134 + fairseq-tools/fairseq/hubconf.py | 69 + fairseq-tools/fairseq/pyproject.toml | 3 + fairseq-tools/fairseq/roberta.py | 40 + fairseq-tools/fairseq/roberta.sh | 46 + fairseq-tools/fairseq/scripts/__init__.py | 0 .../fairseq/scripts/average_checkpoints.py | 158 + .../fairseq/scripts/build_sym_alignment.py | 97 + .../fairseq/scripts/compare_namespaces.py | 46 + .../fairseq/scripts/compound_split_bleu.sh | 20 + .../fairseq/scripts/constraints/extract.py | 92 + .../fairseq/scripts/constraints/validate.py | 34 + .../fairseq/scripts/convert_dictionary.lua | 34 + .../fairseq/scripts/convert_model.lua | 108 + fairseq-tools/fairseq/scripts/count_docs.py | 58 + .../fairseq/scripts/read_binarized.py | 48 + fairseq-tools/fairseq/scripts/rm_pt.py | 141 + fairseq-tools/fairseq/scripts/sacrebleu.sh | 27 + fairseq-tools/fairseq/scripts/shard_docs.py | 54 + .../fairseq/scripts/split_train_valid_docs.py | 86 + fairseq-tools/fairseq/scripts/spm_decode.py | 53 + fairseq-tools/fairseq/scripts/spm_encode.py | 119 + fairseq-tools/fairseq/scripts/spm_train.py | 16 + fairseq-tools/fairseq/setup.py | 217 + fairseq-tools/fairseq/tests/__init__.py | 0 fairseq-tools/fairseq/tests/gpu/__init__.py | 0 .../fairseq/tests/gpu/test_binaries_gpu.py | 305 + .../gpu/transformer_quantization_config.yaml | 28 + .../tests/speech_recognition/__init__.py | 0 .../tests/speech_recognition/asr_test_base.py | 558 + .../speech_recognition/test_collaters.py | 58 + .../speech_recognition/test_cross_entropy.py | 37 + .../speech_recognition/test_data_utils.py | 62 + .../speech_recognition/test_vggtransformer.py | 135 + .../fairseq/tests/test_average_checkpoints.py | 134 + .../tests/test_backtranslation_dataset.py | 123 + fairseq-tools/fairseq/tests/test_binaries.py | 1571 + fairseq-tools/fairseq/tests/test_bmuf.py | 172 + .../tests/test_character_token_embedder.py | 48 + .../fairseq/tests/test_concat_dataset.py | 58 + .../fairseq/tests/test_constraints.py | 269 + fairseq-tools/fairseq/tests/test_convtbc.py | 54 + .../fairseq/tests/test_dictionary.py | 116 + fairseq-tools/fairseq/tests/test_export.py | 108 + fairseq-tools/fairseq/tests/test_file_io.py | 47 + .../fairseq/tests/test_fp16_optimizer.py | 98 + .../fairseq/tests/test_inference_dropout.py | 66 + fairseq-tools/fairseq/tests/test_iterators.py | 123 + .../fairseq/tests/test_label_smoothing.py | 123 + .../fairseq/tests/test_lstm_jitable.py | 115 + .../tests/test_memory_efficient_fp16.py | 66 + fairseq-tools/fairseq/tests/test_metrics.py | 77 + .../test_multi_corpus_sampled_dataset.py | 95 + .../fairseq/tests/test_multihead_attention.py | 61 + fairseq-tools/fairseq/tests/test_noising.py | 530 + .../fairseq/tests/test_reproducibility.py | 138 + .../fairseq/tests/test_resampling_dataset.py | 103 + .../fairseq/tests/test_sequence_generator.py | 647 + .../fairseq/tests/test_sequence_scorer.py | 120 + .../tests/test_sparse_multihead_attention.py | 114 + .../fairseq/tests/test_token_block_dataset.py | 79 + fairseq-tools/fairseq/tests/test_train.py | 228 + fairseq-tools/fairseq/tests/test_utils.py | 114 + fairseq-tools/fairseq/tests/utils.py | 608 + fairseq-tools/fairseq/train.py | 14 + gnn/GCN/README.md | 0 gnn/GCN/ascend310_infer/CMakeLists.txt | 0 gnn/GCN/ascend310_infer/build.sh | 0 gnn/GCN/ascend310_infer/inc/utils.h | 0 gnn/GCN/ascend310_infer/src/main.cc | 0 gnn/GCN/ascend310_infer/src/utils.cc | 0 gnn/GCN/default_config.yaml | 0 gnn/GCN/eval.py | 0 gnn/GCN/export.py | 0 gnn/GCN/mindspore_hub_conf.py | 0 gnn/GCN/model_utils/__init__.py | 0 gnn/GCN/model_utils/config.py | 0 gnn/GCN/model_utils/device_adapter.py | 0 gnn/GCN/model_utils/local_adapter.py | 0 gnn/GCN/model_utils/moxing_adapter.py | 0 gnn/GCN/postprocess.py | 0 gnn/GCN/preprocess.py | 0 gnn/GCN/requirements.txt | 0 gnn/GCN/scripts/run_distribute_train_gpu.sh | 0 gnn/GCN/scripts/run_eval_gpu.sh | 0 gnn/GCN/scripts/run_infer_310.sh | 0 gnn/GCN/scripts/run_process_data.sh | 0 gnn/GCN/scripts/run_train.sh | 0 gnn/GCN/scripts/run_train_gpu.sh | 0 gnn/GCN/scripts/train_gcn_1p.sh | 0 gnn/GCN/src/config.py | 0 gnn/GCN/src/dataset.py | 0 gnn/GCN/src/eval_callback.py | 0 gnn/GCN/src/gcn.py | 0 gnn/GCN/src/metrics.py | 0 gnn/GCN/t-SNE_visualization_on_Cora.gif | Bin gnn/GCN/train.py | 0 .../stable-diffusion/training/IMG/multi.png | Bin .../stable-diffusion/training/IMG/pokemon.png | Bin .../stable-diffusion/training/IMG/single.png | Bin .../stable-diffusion/training/README.md | 0 .../training/requirements.txt | 0 .../stable-diffusion/training/test.py | 0 .../training/train_text_to_image.py | 0 .../data_preprocessing/utils/wordpiece.py | 0 .../cpm/pytorch/base/BaseDockerfile | 0 .../cpm/pytorch/base/bind_pyt.py | 0 .../pytorch/base/cleanup_image_container.sh | 0 .../cpm/pytorch/base/config/__init__.py | 0 .../cpm/pytorch/base/config/_base.py | 0 .../cpm/pytorch/base/config/config_manager.py | 0 .../cpm/pytorch/base/config/mutable_params.py | 0 .../base/data_preprocessing/change_mp.py | 0 .../preprocess_stc_finetune.py | 0 .../cpm/pytorch/base/dataloaders/__init__.py | 0 .../bpe_3w_new/chinese_vocab.model | Bin .../bpe_3w_new/chinese_vocab.vocab | 0 .../base/dataloaders/bpe_3w_new/vocab.json | 0 .../pytorch/base/dataloaders/dataloader.py | 0 .../cpm/pytorch/base/dataloaders/samplers.py | 0 .../base/dataloaders/tokenization_gpt2.py | 0 .../cpm/pytorch/base/model/__init__.py | 0 .../cpm/pytorch/base/model/fp16/__init__.py | 0 .../cpm/pytorch/base/model/fp16/fp16.py | 0 .../cpm/pytorch/base/model/fp16/fp16util.py | 0 .../pytorch/base/model/fp16/loss_scaler.py | 0 .../cpm/pytorch/base/model/layers/__init__.py | 0 .../cpm/pytorch/base/model/layers/layers.py | 0 .../cpm/pytorch/base/model/losses/__init__.py | 0 .../base/model/losses/cross_entropy.py | 0 .../cpm/pytorch/base/model/models/__init__.py | 0 .../pytorch/base/model/models/checkpoint.py | 0 .../base/model/models/gpt2_modeling.py | 0 .../pytorch/base/model/models/transformer.py | 0 .../cpm/pytorch/base/optimizers/__init__.py | 0 .../cpm/pytorch/base/optimizers/factory.py | 0 .../cpm/pytorch/base/prepare.py | 0 .../cpm/pytorch/base/requirements.txt | 0 .../cpm/pytorch/base/run_pretraining.py | 0 .../cpm/pytorch/base/run_training.sh | 0 .../cpm/pytorch/base/run_with_docker.sh | 0 .../cpm/pytorch/base/schedulers/__init__.py | 0 .../cpm/pytorch/base/schedulers/factory.py | 0 .../pytorch/base/schedulers/learning_rates.py | 0 .../cpm/pytorch/base/setup.py | 0 .../cpm/pytorch/base/train/__init__.py | 0 .../cpm/pytorch/base/train/evaluator.py | 0 .../cpm/pytorch/base/train/event/__init__.py | 0 .../cpm/pytorch/base/train/event/base.py | 0 .../pytorch/base/train/event/base_adapter.py | 0 .../cpm/pytorch/base/train/event/compose.py | 0 .../cpm/pytorch/base/train/event/log.py | 0 .../cpm/pytorch/base/train/metrics.py | 0 .../cpm/pytorch/base/train/trainer.py | 0 .../cpm/pytorch/base/train/training_state.py | 0 .../cpm/pytorch/base/utils/__init__.py | 0 .../cpm/pytorch/base/utils/check.py | 0 .../cpm/pytorch/base/utils/dist.py | 0 .../cpm/pytorch/base/utils/logging.py | 0 .../cpm/pytorch/base/utils/paths.py | 0 .../iluvatar/cpm/config/config_V100x1x1.py | 0 .../iluvatar/cpm/config/config_V100x1x8.py | 0 .../iluvatar/cpm/config/config_V100x2x8.py | 0 .../iluvatar/cpm/config/config_common.py | 0 .../pytorch/iluvatar/cpm/config/converter.py | 0 .../iluvatar/cpm/config/layers/__init__.py | 0 .../iluvatar/cpm/config/layers/attention.py | 0 .../layers/fast_self_multihead_attn_func.py | 0 .../iluvatar/cpm/config/layers/layernorm.py | 0 .../cpm/config/layers/self_multihead_attn.py | 0 .../config/layers/self_multihead_attn_func.py | 0 .../iluvatar/cpm/config/optimizers_adam.py | 0 .../iluvatar/cpm/config/training_event.py | 0 .../cpm/pytorch/iluvatar/cpm/csrc/dropout.h | 0 .../cpm/csrc/fast_self_multihead_attn_func.py | 0 .../pytorch/iluvatar/cpm/csrc/layer_norm.h | 0 .../cpm/pytorch/iluvatar/cpm/csrc/philox.h | 0 .../iluvatar/cpm/csrc/self_multihead_attn.py | 0 .../cpm/csrc/self_multihead_attn_bias.cpp | 0 .../cpm/csrc/self_multihead_attn_bias_cuda.cu | 0 .../cpm/csrc/self_multihead_attn_func.py | 0 .../cpm/pytorch/iluvatar/cpm/csrc/setup.py | 0 .../cpm/pytorch/iluvatar/cpm/csrc/softmax.h | 0 .../iluvatar/cpm/csrc/strided_batched_gemm.h | 0 .../pytorch/iluvatar/cpm/packages/files.txt | 0 .../iluvatar/docker_image/gen_docker_image.sh | 0 .../pytorch/iluvatar/docker_image/install.sh | 0 nlp/language_model/bert/pytorch/NOTICE | 0 nlp/language_model/bert/pytorch/bind.sh | 0 nlp/language_model/bert/pytorch/bmm1.py | 0 nlp/language_model/bert/pytorch/bmm2.py | 0 .../bert/pytorch/cleanup_scripts/clean.sh | 0 .../create_pretraining_data_wrapper.sh | 0 .../extract_test_set_articles.py | 0 .../cleanup_scripts/parallel_create_hdf5.sh | 0 .../pytorch/cleanup_scripts/process_wiki.sh | 0 .../bert/pytorch/data_scripts/clean.sh | 0 .../create_pretraining_data_wrapper.sh | 0 .../data_scripts/parallel_create_hdf5.sh | 0 .../bert/pytorch/data_scripts/process_wiki.sh | 0 nlp/language_model/bert/pytorch/init.sh | 0 .../bert/pytorch/input_preprocessing/clean.sh | 0 .../create_pretraining_data_wrapper.sh | 0 .../parallel_create_hdf5.sh | 0 .../input_preprocessing/process_wiki.sh | 0 .../bert/pytorch/mhalib/mha_funcs.cu | 0 .../bert/pytorch/mhalib/setup.py | 0 .../mlperf-logging/scripts/pack_submission.sh | 0 .../scripts/verify_for_v0.7_training.sh | 0 .../scripts/verify_for_v1.0_hpc.sh | 0 .../scripts/verify_for_v1.0_training.sh | 0 .../scripts/verify_for_v1.1_training.sh | 0 .../scripts/verify_for_v2.0_training.sh | 0 nlp/language_model/bert/pytorch/padding.py | 0 nlp/language_model/bert/pytorch/softmax.py | 0 nlp/ner/bert/pytorch/run.sh | 0 nlp/ner/bert/pytorch/run_dist.sh | 0 nlp/ner/bert/pytorch/run_ner.py | 0 .../ncf/pytorch/download_dataset.sh | 0 .../ncf/pytorch/ncf_16.py | 0 .../ncf/pytorch/ncf_32.py | 0 .../ncf/pytorch/run_train_fp16.sh | 0 .../ncf/pytorch/run_train_fp32.sh | 0 .../pytorch/scripts/dot_based_interact/run.sh | 0 .../conformer/pytorch/README.md | 0 .../pytorch/conf/train_conformer.yaml | 0 .../pytorch/local/aishell_data_prep.sh | 0 .../pytorch/local/aishell_train_lms.sh | 0 .../pytorch/local/download_and_untar.sh | 0 .../conformer/pytorch/run.sh | 0 .../conformer/pytorch/tools/compute-wer.py | 0 .../pytorch/tools/compute_cmvn_stats.py | 0 .../conformer/pytorch/tools/filter_scp.pl | 0 .../conformer/pytorch/tools/make_raw_list.py | 0 .../conformer/pytorch/tools/parse_options.sh | 0 .../conformer/pytorch/tools/text2token.py | 0 .../conformer/pytorch/wenet/bin/recognize.py | 0 .../conformer/pytorch/wenet/bin/train.py | 0 .../pytorch/wenet/dataset/dataset.py | 0 .../pytorch/wenet/transformer/convolution.py | 0 .../rnnt/pytorch/install.sh | 0 .../rnnt/pytorch/requirements.txt | 0 .../rnnt/pytorch/scripts/docker/Dockerfile | 0 .../rnnt/pytorch/scripts/docker/build.sh | 0 .../rnnt/pytorch/scripts/docker/launch.sh | 0 .../pytorch/scripts/download_librispeech.sh | 0 .../rnnt/pytorch/scripts/inference.sh | 0 .../pytorch/scripts/preprocess_librispeech.sh | 0 .../rnnt/pytorch/scripts/train_rnnt_1x1.sh | 0 .../rnnt/pytorch/scripts/train_rnnt_1x4.sh | 0 .../rnnt/pytorch/scripts/train_rnnt_1x8.sh | 0 .../tacotron2/pytorch/demo.wav | Bin .../ljs_audio_text_test_filelist.txt | 0 .../ljs_audio_text_train_filelist.txt | 0 .../filelists/ljs_audio_text_val_filelist.txt | 0 .../tacotron2/pytorch/waveglow/README.md | 0 .../tacotron2/pytorch/waveglow/config.json | 0 .../pytorch/waveglow/waveglow_logo.png | Bin .../egs/arctic/voc1/local/data_download.sh | 0 .../egs/arctic/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/arctic/voc1/run.sh | 0 .../ParallelWaveGAN/egs/arctic/voc1/utils | 1 - .../egs/arctic/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/arctic/voc1/utils/make_subset_data.sh | 52 + .../egs/arctic/voc1/utils/parse_options.sh | 97 + .../egs/arctic/voc1/utils/queue.pl | 624 + .../egs/arctic/voc1/utils/run.pl | 282 + .../egs/arctic/voc1/utils/slurm.pl | 627 + .../egs/arctic/voc1/utils/split_data.sh | 104 + .../egs/arctic/voc1/utils/split_scp.pl | 246 + .../egs/arctic/voc1/utils/ssh.pl | 219 + .../egs/arctic/voc1/utils/stdout.pl | 282 + .../egs/csmsc/voc1/local/data_download.sh | 0 .../egs/csmsc/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/csmsc/voc1/run.sh | 0 .../ParallelWaveGAN/egs/csmsc/voc1/utils | 1 - .../egs/csmsc/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/csmsc/voc1/utils/make_subset_data.sh | 52 + .../egs/csmsc/voc1/utils/parse_options.sh | 97 + .../egs/csmsc/voc1/utils/queue.pl | 624 + .../egs/csmsc/voc1/utils/run.pl | 282 + .../egs/csmsc/voc1/utils/slurm.pl | 627 + .../egs/csmsc/voc1/utils/split_data.sh | 104 + .../egs/csmsc/voc1/utils/split_scp.pl | 246 + .../egs/csmsc/voc1/utils/ssh.pl | 219 + .../egs/csmsc/voc1/utils/stdout.pl | 282 + .../egs/jnas/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/jnas/voc1/run.sh | 0 .../ParallelWaveGAN/egs/jnas/voc1/utils | 1 - .../egs/jnas/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/jnas/voc1/utils/make_subset_data.sh | 52 + .../egs/jnas/voc1/utils/parse_options.sh | 97 + .../egs/jnas/voc1/utils/queue.pl | 624 + .../egs/jnas/voc1/utils/run.pl | 282 + .../egs/jnas/voc1/utils/slurm.pl | 627 + .../egs/jnas/voc1/utils/split_data.sh | 104 + .../egs/jnas/voc1/utils/split_scp.pl | 246 + .../egs/jnas/voc1/utils/ssh.pl | 219 + .../egs/jnas/voc1/utils/stdout.pl | 282 + .../egs/jsss/voc1/local/data_download.sh | 0 .../egs/jsss/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/jsss/voc1/run.sh | 0 .../ParallelWaveGAN/egs/jsss/voc1/utils | 1 - .../egs/jsss/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/jsss/voc1/utils/make_subset_data.sh | 52 + .../egs/jsss/voc1/utils/parse_options.sh | 97 + .../egs/jsss/voc1/utils/queue.pl | 624 + .../egs/jsss/voc1/utils/run.pl | 282 + .../egs/jsss/voc1/utils/slurm.pl | 627 + .../egs/jsss/voc1/utils/split_data.sh | 104 + .../egs/jsss/voc1/utils/split_scp.pl | 246 + .../egs/jsss/voc1/utils/ssh.pl | 219 + .../egs/jsss/voc1/utils/stdout.pl | 282 + .../egs/jsut/voc1/local/data_download.sh | 0 .../egs/jsut/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/jsut/voc1/run.sh | 0 .../ParallelWaveGAN/egs/jsut/voc1/utils | 1 - .../egs/jsut/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/jsut/voc1/utils/make_subset_data.sh | 52 + .../egs/jsut/voc1/utils/parse_options.sh | 97 + .../egs/jsut/voc1/utils/queue.pl | 624 + .../egs/jsut/voc1/utils/run.pl | 282 + .../egs/jsut/voc1/utils/slurm.pl | 627 + .../egs/jsut/voc1/utils/split_data.sh | 104 + .../egs/jsut/voc1/utils/split_scp.pl | 246 + .../egs/jsut/voc1/utils/ssh.pl | 219 + .../egs/jsut/voc1/utils/stdout.pl | 282 + .../egs/libritts/voc1/local/data_download.sh | 0 .../egs/libritts/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/libritts/voc1/run.sh | 0 .../ParallelWaveGAN/egs/libritts/voc1/utils | 1 - .../egs/libritts/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../libritts/voc1/utils/make_subset_data.sh | 52 + .../egs/libritts/voc1/utils/parse_options.sh | 97 + .../egs/libritts/voc1/utils/queue.pl | 624 + .../egs/libritts/voc1/utils/run.pl | 282 + .../egs/libritts/voc1/utils/slurm.pl | 627 + .../egs/libritts/voc1/utils/split_data.sh | 104 + .../egs/libritts/voc1/utils/split_scp.pl | 246 + .../egs/libritts/voc1/utils/ssh.pl | 219 + .../egs/libritts/voc1/utils/stdout.pl | 282 + .../egs/ljspeech/voc1/local/data_download.sh | 0 .../egs/ljspeech/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/ljspeech/voc1/run.sh | 0 .../ParallelWaveGAN/egs/ljspeech/voc1/utils | 1 - .../egs/ljspeech/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../ljspeech/voc1/utils/make_subset_data.sh | 52 + .../egs/ljspeech/voc1/utils/parse_options.sh | 97 + .../egs/ljspeech/voc1/utils/queue.pl | 624 + .../egs/ljspeech/voc1/utils/run.pl | 282 + .../egs/ljspeech/voc1/utils/slurm.pl | 627 + .../egs/ljspeech/voc1/utils/split_data.sh | 104 + .../egs/ljspeech/voc1/utils/split_scp.pl | 246 + .../egs/ljspeech/voc1/utils/ssh.pl | 219 + .../egs/ljspeech/voc1/utils/stdout.pl | 282 + .../voc1/local/data_download.sh | 0 .../speech_commands/voc1/local/data_prep.sh | 0 .../egs/speech_commands/voc1/run.sh | 0 .../egs/speech_commands/voc1/utils | 1 - .../voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../voc1/utils/make_subset_data.sh | 52 + .../voc1/utils/parse_options.sh | 97 + .../egs/speech_commands/voc1/utils/queue.pl | 624 + .../egs/speech_commands/voc1/utils/run.pl | 282 + .../egs/speech_commands/voc1/utils/slurm.pl | 627 + .../speech_commands/voc1/utils/split_data.sh | 104 + .../speech_commands/voc1/utils/split_scp.pl | 246 + .../egs/speech_commands/voc1/utils/ssh.pl | 219 + .../egs/speech_commands/voc1/utils/stdout.pl | 282 + .../voc1/local/data_prep.sh | 0 .../egs/template_multi_spk/voc1/run.sh | 0 .../egs/template_multi_spk/voc1/utils | 1 - .../voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../voc1/utils/make_subset_data.sh | 52 + .../voc1/utils/parse_options.sh | 97 + .../template_multi_spk/voc1/utils/queue.pl | 624 + .../egs/template_multi_spk/voc1/utils/run.pl | 282 + .../template_multi_spk/voc1/utils/slurm.pl | 627 + .../voc1/utils/split_data.sh | 104 + .../voc1/utils/split_scp.pl | 246 + .../egs/template_multi_spk/voc1/utils/ssh.pl | 219 + .../template_multi_spk/voc1/utils/stdout.pl | 282 + .../voc1/local/data_prep.sh | 0 .../egs/template_single_spk/voc1/run.sh | 0 .../egs/template_single_spk/voc1/utils | 1 - .../voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../voc1/utils/make_subset_data.sh | 52 + .../voc1/utils/parse_options.sh | 97 + .../template_single_spk/voc1/utils/queue.pl | 624 + .../egs/template_single_spk/voc1/utils/run.pl | 282 + .../template_single_spk/voc1/utils/slurm.pl | 627 + .../voc1/utils/split_data.sh | 104 + .../voc1/utils/split_scp.pl | 246 + .../egs/template_single_spk/voc1/utils/ssh.pl | 219 + .../template_single_spk/voc1/utils/stdout.pl | 282 + .../egs/vctk/voc1/local/data_download.sh | 0 .../egs/vctk/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/vctk/voc1/run.sh | 0 .../ParallelWaveGAN/egs/vctk/voc1/utils | 1 - .../egs/vctk/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/vctk/voc1/utils/make_subset_data.sh | 52 + .../egs/vctk/voc1/utils/parse_options.sh | 97 + .../egs/vctk/voc1/utils/queue.pl | 624 + .../egs/vctk/voc1/utils/run.pl | 282 + .../egs/vctk/voc1/utils/slurm.pl | 627 + .../egs/vctk/voc1/utils/split_data.sh | 104 + .../egs/vctk/voc1/utils/split_scp.pl | 246 + .../egs/vctk/voc1/utils/ssh.pl | 219 + .../egs/vctk/voc1/utils/stdout.pl | 282 + .../egs/yesno/voc1/local/data_download.sh | 0 .../egs/yesno/voc1/local/data_prep.sh | 0 .../ParallelWaveGAN/egs/yesno/voc1/run.sh | 0 .../ParallelWaveGAN/egs/yesno/voc1/utils | 1 - .../egs/yesno/voc1/utils/combine_data.sh | 57 + .../voc1/utils/download_from_google_drive.sh | 51 + .../egs/yesno/voc1/utils/make_subset_data.sh | 52 + .../egs/yesno/voc1/utils/parse_options.sh | 97 + .../egs/yesno/voc1/utils/queue.pl | 624 + .../egs/yesno/voc1/utils/run.pl | 282 + .../egs/yesno/voc1/utils/slurm.pl | 627 + .../egs/yesno/voc1/utils/split_data.sh | 104 + .../egs/yesno/voc1/utils/split_scp.pl | 246 + .../egs/yesno/voc1/utils/ssh.pl | 219 + .../egs/yesno/voc1/utils/stdout.pl | 282 + .../bin/compute_statistics.py | 0 .../parallel_wavegan/bin/decode.py | 0 .../parallel_wavegan/bin/normalize.py | 0 .../parallel_wavegan/bin/preprocess.py | 0 .../parallel_wavegan/bin/train.py | 0 .../ParallelWaveGAN/utils/combine_data.sh | 0 .../utils/download_from_google_drive.sh | 0 .../ParallelWaveGAN/utils/make_subset_data.sh | 0 .../ParallelWaveGAN/utils/parse_options.sh | 0 .../pytorch/ParallelWaveGAN/utils/queue.pl | 0 .../pytorch/ParallelWaveGAN/utils/run.pl | 0 .../pytorch/ParallelWaveGAN/utils/slurm.pl | 0 .../ParallelWaveGAN/utils/split_data.sh | 0 .../ParallelWaveGAN/utils/split_scp.pl | 0 .../pytorch/ParallelWaveGAN/utils/ssh.pl | 0 .../pytorch/ParallelWaveGAN/utils/stdout.pl | 0 .../waveglow/pytorch/config.json | 0 .../waveglow/pytorch/tacotron2/README.md | 0 .../waveglow/pytorch/tacotron2/demo.wav | Bin .../ljs_audio_text_test_filelist.txt | 0 .../ljs_audio_text_train_filelist.txt | 0 .../filelists/ljs_audio_text_val_filelist.txt | 0 .../waveglow/pytorch/waveglow_logo.png | Bin 5891 files changed, 201479 insertions(+), 17 deletions(-) mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_gui_nerf.sh mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_gui_nerf_clip.sh mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_gui_tensoRF.sh mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_nerf.sh mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_sdf.sh mode change 100755 => 100644 3d-reconstruction/hashnerf/scripts/run_tensoRF.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/LICENSE mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/README.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/.pre-commit-config.yaml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/.readthedocs.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/CITATION.cff mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/LICENSE mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/build_mmcv.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/clean_mmcv.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/install_mmcv.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/quantization.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/dataloader.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hierarchical_data_manager.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hook_wrapper.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/model_wrapper.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/runner.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/_functions.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/data_parallel.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/distributed.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/scatter_gather.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/test.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/io.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/parse.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/colorspace.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/geometric.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/io.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/misc.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/photometric.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/deprecated.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/mmcls.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/open_mmlab.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/torchvision_0.12.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/info.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/symbolic_helper.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/symbolic.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/active_rotated_filter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/assign_score_withk.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/ball_query.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/bbox.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/border_align.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/box_iou_rotated.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/carafe.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/cc_attention.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/chamfer_distance.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/contour_expand.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/convex_iou.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/corner_pool.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/correlation.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/README.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/box_iou_rotated_utils.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/active_rotated_filter_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ball_query_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/border_align_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/box_iou_rotated_cuda.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_naive_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/chamfer_distance_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/convex_iou_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/correlation_cuda.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/diff_iou_rotated_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/furthest_point_sample_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/gather_points_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/group_points_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/iou3d_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/knn_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/masked_conv2d_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/min_area_polygons_cuda.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/parrots_cudawarpfunction.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_boxes_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_polygons_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/psamask_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/riroi_align_rotated_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_rotated_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roiaware_pool3d_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roipoint_pool3d_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/rotated_feature_align_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/scatter_points_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_interpolate_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_nn_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/tin_shift_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/voxelization_cuda_kernel.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/bbox_overlaps_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/common_mlu_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/focal_loss_sigmoid_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/nms_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_utils.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_utils.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/tin_shift_mlu_kernel.mlu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cpp_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cuda_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_device_registry.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_mlu_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/corner_pool.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/corner_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/gridSample.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/modulated_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/onnxruntime_register.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/reduce_ops.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/rotated_feature_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/soft_nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/deform_conv.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/grid_sample.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/modulated_deform_conv.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/nms.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_register.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_session_options_config_keys.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/ort_mmcv_utils.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/reduce_ops.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align_rotated.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/rotated_feature_align.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/soft_nms.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query._parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/cudabind.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_leakyrelu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/info.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_parrots.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_pytorch.h mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/active_rotated_filter.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/assign_score_withk.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ball_query.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/bbox_overlaps.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/border_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/box_iou_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe_naive.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/chamfer_distance.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/contour_expand.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/convex_iou.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/correlation.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/active_rotated_filter.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/box_iou_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/modulated_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/pixel_group.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/points_in_boxes.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/psamask.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/rotated_feature_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/voxelization.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/active_rotated_filter_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ball_query_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/border_align_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/box_iou_rotated_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_naive_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/chamfer_distance_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/convex_iou.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/correlation_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/cudabind.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/diff_iou_rotated_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/furthest_point_sample_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/fused_bias_leakyrelu_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/gather_points_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/group_points_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/iou3d_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/knn_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/masked_conv2d_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/min_area_polygons.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_rotated_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_boxes_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_polygons_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/psamask_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/riroi_align_rotated_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_rotated_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roiaware_pool3d_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roipoint_pool3d_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/rotated_feature_align_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/scatter_points_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_interpolate_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_nn_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/tin_shift_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/upfirdn2d_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/voxelization_cuda.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_roi_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/diff_iou_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/focal_loss.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/furthest_point_sample.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_bias_leakyrelu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_spconv_ops.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/gather_points.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/group_points.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/iou3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/knn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/masked_conv2d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/min_area_polygons.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/bbox_overlaps_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/focal_loss_sigmoid_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/nms_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/psamask_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_rotated_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/tin_shift_mlu.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ms_deform_attn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pixel_group.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_boxes.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_polygons.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/psamask.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/riroi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align_rotated.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roiaware_pool3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roipoint_pool3d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/rotated_feature_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/scatter_points.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_interpolate.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_nn.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/tin_shift.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/upfirdn2d.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/voxelization.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cuda_helper.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_instance_norm.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_plugin.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd.cpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd_kernel.cu mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_corner_pool.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cuda_helper.cuh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cummaxmin.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_deform_conv.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_grid_sampler.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_instance_norm.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_modulated_deform_conv.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_nms.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin_helper.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_roi_align.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_scatternd.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_serialize.hpp mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_conv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_roi_pool.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/diff_iou_rotated.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/focal_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/furthest_point_sample.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/fused_bias_leakyrelu.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/gather_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/group_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/info.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/iou3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/knn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/masked_conv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/merge_cells.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/min_area_polygons.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/modulated_deform_conv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/multi_scale_deform_attn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/nms.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/pixel_group.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/point_sample.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_boxes.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_polygons.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_sampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/psa_mask.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/riroi_align_rotated.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align_rotated.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_pool.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roiaware_pool3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roipoint_pool3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/rotated_feature_align.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/saconv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/scatter_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_interpolate.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_nn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/tin_shift.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/upfirdn2d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/voxelize.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/collate.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/registry.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/clearml.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/segmind.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/priority.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/init_plugins.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/preprocess.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/tensorrt_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/config.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/device_type.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/env.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/hub.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/logging.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/misc.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/path.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/registry.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/seed.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/testing.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/timer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/trace.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/version.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/io.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/optflow.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/processing.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/color.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/image.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/optflow.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmcv/setup.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CODE_OF_CONDUCT.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CONTRIBUTING.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/config.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/error-report.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/feature_request.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/general_questions.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/reimplementation_questions.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/pull_request_template.md mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/build.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/deploy.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/lint.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/test_mim.yml mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/CITATION.cff mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/LICENSE delete mode 120000 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/configs delete mode 120000 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/model-index.yml delete mode 120000 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/analyze_logs.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/benchmark.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/get_flops.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.sh create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/__init__.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/create_gt_database.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/indoor_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_data_utils.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_data_fixer.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuimage_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuscenes_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/s3dis_data_utils.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/scannet_data_utils.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/sunrgbd_data_utils.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/waymo_converter.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d2torchserve.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d_handler.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/test_torchserver.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_test.sh create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_train.sh create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/browse_dataset.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/fuse_conv_bn.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/print_config.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/visualize_results.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_h3dnet_checkpoints.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_votenet_checkpoints.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/publish_model.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/regnet2mmdet.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_test.sh create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_train.sh create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/test.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/train.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.py create mode 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/inference.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/test.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/train.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/anchor_3d_generator.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/box_np_ops.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/anchor_free_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/centerpoint_bbox_coders.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/delta_xyzwhlr_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/fcos3d_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/groupfree3d_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/monoflex_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/partial_bin_based_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/pgd_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/point_xyzwhlr_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/smoke_bbox_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/iou3d_calculator.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/iou_neg_piecewise_sampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/base_box3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/box_3d_mode.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/cam_box3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/coord_3d_mode.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/depth_box3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/lidar_box3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/transforms.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/indoor_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/instance_seg_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/rotate_iou.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/lyft_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/evaluate_semantic_instance.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/util_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/seg_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/prediction_kitti_to_waymo.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/base_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/cam_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/depth_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/lidar_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/box3d_nms.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/merge_augs.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/array_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/gaussian.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/image_vis.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/open3d_vis.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/show_result.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/voxel_generator.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d_seg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti2d_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_mono_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/lyft_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_mono_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/compose.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/data_augment_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/dbsampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/formating.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/loading.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/transforms_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/s3dis_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/scannet_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/semantickitti_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/sunrgbd_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/waymo_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/base_pointnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dgcnn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dla.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/mink_resnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/multi_backbone.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/nostem_regnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_msg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_ssg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/second.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/decode_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/dgcnn_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/paconv_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/pointnet2_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor_free_mono3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_conv_bbox_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_mono3d_dense_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/centerpoint_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcaf3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcos_mono3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/free_anchor3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/groupfree3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/monoflex_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/parta2_rpn_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/pgd_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/point_rpn_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/shape_aware_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/smoke_mono3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/ssd_3d_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/train_mixins.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/vote_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/base.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/centerpoint.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/dynamic_voxelnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/fcos_mono3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/groupfree3dnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/h3dnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvotenet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvoxelnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mink_single_stage.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_faster_rcnn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_two_stage.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/parta2.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/point_rcnn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/sassd.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage_mono3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/smoke_mono3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/ssd3dnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/two_stage.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/votenet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/voxelnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/coord_transform.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/point_fusion.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/vote_fusion.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/axis_aligned_iou_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/chamfer_distance.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/multibin_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/paconv_regularization_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/rotated_iou_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/uncertain_smooth_l1_loss.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/pillar_scatter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_encoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_unet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/edge_fusion_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/transformer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/vote_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/dla_neck.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/imvoxel_neck.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/pointnet2_fp_neck.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/second_fpn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/view_transformer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/base_3droi_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/h3d_bbox_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/parta2_bbox_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/point_rcnn_bbox_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/h3d_roi_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/pointwise_semantic_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/primitive_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/part_aggregation_roi_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/point_rcnn_roi_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roiaware_extractor.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roipoint_extractor.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/base.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/encoder_decoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/clip_sigmoid.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/edge_indices.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/gen_keypoints.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/handle_objs.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/mlp.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/pillar_encoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/voxel_encoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fa_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fp_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_gf_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/norm.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/paconv.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/paconv_sa_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_fp_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_sa_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/sparse_block.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/write_spconv2.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/collect_env.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/compat_cfg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/logger.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/misc.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/setup_env.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/version.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/build.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/docs.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/mminstall.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/optional.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/readthedocs.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/runtime.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/tests.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.cfg mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/a.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_dbinfos_train.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_gt_database/0_Pedestrian_0.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.coco.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_train.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results2d.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000000.png mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000007.png mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne/000000.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne_reduced/000000.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886501000046.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886701083686.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos_val.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/sample_results.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/maps/map_raster_palo_alto.png mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/attribute.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/calibrated_sensor.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/category.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/ego_pose.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/instance.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/log.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/map.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_annotation.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_data.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/scene.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sensor.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/visibility.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/val.txt mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/mono3d_sample_results.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_info.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_infos_mono3d.coco.json mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/CAM_BACK_LEFT/n015-2018-07-18-11-07-57+0800__CAM_BACK_LEFT__1531883530447423.jpg mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470948018.pcd.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n008-2018-09-18-12-07-26-0400__LIDAR_TOP__1537287083900561.pcd.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470898274.pcd.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/features_for_fps_distance.npy mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/fps_idx.npy mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/instance_mask/Area_1_office_2.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/points/Area_1_office_2.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/s3dis_infos.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/semantic_mask/Area_1_office_2.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/instance_mask/scene0000_00.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/points/scene0000_00.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/scannet_infos.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/semantic_mask/scene0000_00.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/semantickitti_infos.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/labels/000000.label mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/velodyne/000000.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/points/000001.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_infos.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_trainval/image/000001.jpg mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/0000000.png mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/1000000.png mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/0000000.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/1000000.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_dbinfos_train.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_gt_database/0_Car_0.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_train.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_val.pkl mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/gt.bin mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/validation/val.tfrecord mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_dataset_wrappers.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_mono_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_lyft_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscene_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscenes_mono_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_s3dis_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_scannet_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_semantickitti_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_sunrgbd_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_waymo_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_data_augment_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_test_augment_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_transforms_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_pipeline.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_sample.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_images_from_multi_views.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_points_from_multi_sweeps.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_loading.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_outdoor_pipeline.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_indoor_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_instance_seg_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_kitti_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_losses.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_seg_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_backbones.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_dgcnn_modules.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_middle_encoders.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_modules.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_ops.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_pointnet_modules.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_sparse_unet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_vote_module.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_detectors.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_forward.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_fusion_coord_trans.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_point_fusion.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_vote_fusion.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_dgcnn_decode_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_heads.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_paconv_decode_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_parta2_bbox_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_pointnet2_decode_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_roi_extractors.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_semantic_heads.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_fpn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_necks.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_segmentors.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_encoders.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_generator.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_apis.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_config.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_samples/parta2_roihead_inputs.npz mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_anchors.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_assigners.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_bbox_coders.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box_np_ops.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_compat_cfg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_coord_3d_mode.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_merge_augs.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_nms.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_points.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_samplers.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_setup_env.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/analyze_logs.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/benchmark.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/get_flops.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/create_gt_database.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/indoor_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_data_fixer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuimage_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuscenes_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/s3dis_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/scannet_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/sunrgbd_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/waymo_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d2torchserve.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d_handler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/test_torchserver.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_test.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_train.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/browse_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/fuse_conv_bn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/print_config.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/visualize_results.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_h3dnet_checkpoints.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_votenet_checkpoints.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/publish_model.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/regnet2mmdet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_test.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_train.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/test.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/train.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/coco_instance.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-3class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-car.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/lyft-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nuim_instance.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-mono3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/range100_lyft-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis-3d-5class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis_seg-3d-13class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet-3d-18class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet_seg-3d-20class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/sunrgbd-3d-10class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-3class.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-car.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/3dssd.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_01voxel_second_secfpn_nus.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_02pillar_second_secfpn_nus.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/fcos3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/groupfree3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/h3dnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_lyft.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_nus.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_range100_lyft.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_kitti.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_waymo.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_kitti.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_waymo.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/imvotenet_image.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/mask_rcnn_r50_fpn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_cuda_ssg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_ssg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/parta2.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_msg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_ssg.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/votenet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cosine.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_20e.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_40e.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/mmdet_schedule_1x.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_2x.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_3x.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_150e.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_200e.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_50e.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_base.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_small.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_tiny.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer_fp16/bevformer_tiny_fp16.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_lyft-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_nus-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_waymo-3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/mmdet_train.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/test.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/train.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer_fp16.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/custom_hooks.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/custom_base_transformer_layer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/decoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/encoder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/multi_scale_deformable_attn_function.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/spatial_cross_attention.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/temporal_self_attention.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/transformer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/util.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/kitti2waymo.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/builder.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_mono_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscnes_eval.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/formating.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/loading.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/transform_3d.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/group_sampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/sampler.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/vovnet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/hooks.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/adamw.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/bricks.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/grid_mask.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/position_embedding.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/visual.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/analyze_logs.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/benchmark.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/get_params.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/visual.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/create_data.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/__init__.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/create_gt_database.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/indoor_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_data_fixer.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuimage_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuscenes_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/s3dis_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/scannet_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/sunrgbd_data_utils.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/data_converter/waymo_converter.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/dist_test.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/dist_train.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/fp16/dist_train.sh mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/fp16/train.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/misc/browse_dataset.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/misc/fuse_conv_bn.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/misc/print_config.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/misc/visualize_results.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/model_converters/convert_votenet_checkpoints.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/model_converters/publish_model.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/model_converters/regnet2mmdet.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/test.py mode change 100755 => 100644 cv/3d_detection/BEVFormer/pytorch/tools/train.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/.gitignore mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/README.md mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/dataset/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/dataset/data_aug.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/dataset/dataloader.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/dataset/kitti.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/evaluate.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/figures/img_3dbbox_000134.png mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/figures/pc_pred_000134.png mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/loss/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/loss/loss.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/misc/log.md mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/misc/vis_data_gt.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/model/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/model/anchors.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/model/pointpillars.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d.cpp mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d_kernel.cu mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/iou3d_module.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/setup.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/voxel_module.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.cpp mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.h mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cpu.cpp mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cuda.cu mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/pre_process_kitti.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/requirements.txt mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/test.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/train.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/utils/__init__.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/utils/io.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/utils/process.py mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/utils/viewpoint.json mode change 100755 => 100644 cv/3d_detection/pointpillars/pytorch/utils/vis_o3d.py mode change 100755 => 100644 cv/classification/densenet/pytorch/.gitignore mode change 100755 => 100644 cv/classification/densenet/pytorch/README.md mode change 100755 => 100644 cv/classification/densenet/pytorch/__init__.py mode change 100755 => 100644 cv/classification/densenet/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/classification/densenet/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/classification/densenet/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/classification/densenet/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/classification/densenet/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/classification/densenet/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/classification/densenet/pytorch/dataloader/classification.py mode change 100755 => 100644 cv/classification/densenet/pytorch/dataloader/dali_classification.py mode change 100755 => 100644 cv/classification/densenet/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/classification/densenet/pytorch/dataloader/utils/presets_classification.py mode change 100755 => 100644 cv/classification/densenet/pytorch/train.py mode change 100755 => 100644 cv/classification/densenet/pytorch/utils_.py mode change 100755 => 100644 cv/classification/dpn107/pytorch/train_dpn107_amp_dist.sh mode change 100755 => 100644 cv/classification/dpn92/pytorch/train_dpn92_amp_dist.sh mode change 100755 => 100644 cv/classification/eca_mobilenet_v2/pytorch/train_eca_mobilenet_v2_amp_dist.sh mode change 100755 => 100644 cv/classification/eca_resnet152/pytorch/train_eca_resnet152_amp_dist.sh mode change 100755 => 100644 cv/classification/efficientb4/pytorch/.gitignore mode change 100755 => 100644 cv/classification/efficientb4/pytorch/README.md mode change 100755 => 100644 cv/classification/efficientb4/pytorch/__init__.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/loss.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/dataloader/classification.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/dataloader/dali_classification.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/dataloader/utils/presets_classification.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/train.py mode change 100755 => 100644 cv/classification/efficientb4/pytorch/utils.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/.gitignore mode change 100755 => 100644 cv/classification/googlenet/pytorch/README.md mode change 100755 => 100644 cv/classification/googlenet/pytorch/__init__.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/dataloader/classification.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/dataloader/dali_classification.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/dataloader/utils/presets_classification.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/train.py mode change 100755 => 100644 cv/classification/googlenet/pytorch/utils_.py mode change 100755 => 100644 cv/classification/inceptionv3/pytorch/train_inception_v3_amp_dist.sh mode change 100755 => 100644 cv/classification/inceptionv4/pytorch/train_inceptionv4_amp_dist.sh mode change 100755 => 100644 cv/classification/lenet/pytorch/.gitignore mode change 100755 => 100644 cv/classification/lenet/pytorch/README.md mode change 100755 => 100644 cv/classification/lenet/pytorch/__init__.py mode change 100755 => 100644 cv/classification/lenet/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/classification/lenet/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/classification/lenet/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/classification/lenet/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/classification/lenet/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/classification/lenet/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/classification/lenet/pytorch/dataloader/classification.py mode change 100755 => 100644 cv/classification/lenet/pytorch/dataloader/dali_classification.py mode change 100755 => 100644 cv/classification/lenet/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/classification/lenet/pytorch/dataloader/utils/presets_classification.py mode change 100755 => 100644 cv/classification/lenet/pytorch/train.py mode change 100755 => 100644 cv/classification/lenet/pytorch/utils_.py mode change 100755 => 100644 cv/classification/mobilenetv2/pytorch/train_mobilenet_v2_amp_dist.sh mode change 100755 => 100644 cv/classification/mobilenetv3/pytorch/train_mobilenet_v3_large_amp_dist.sh mode change 100755 => 100644 cv/classification/repvgg/pytorch/LICENSE mode change 100755 => 100644 cv/classification/repvgg/pytorch/README.md mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/__init__.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/build.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/cached_image_folder.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/lmdb_dataset.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/samplers.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/data/zipreader.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/example_pspnet.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/jizhi_submit_train_repvgg.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/main.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/quantization/quant_qat_train.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/quantization/repvgg_quantized.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/repvgg.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/repvggplus.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/repvggplus_custom_L2.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/se_block.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/tools/convert.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/tools/insert_bn.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/tools/verify.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/config.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/cutout.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/logger.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/lr_scheduler.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/optimizer.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/train/randaug.py mode change 100755 => 100644 cv/classification/repvgg/pytorch/utils.py mode change 100755 => 100644 cv/classification/resnest101/pytorch/train_resnest101_amp_dist.sh mode change 100755 => 100644 cv/classification/resnest14/pytorch/train_resnest14_amp_dist.sh mode change 100755 => 100644 cv/classification/resnest269/pytorch/train_resnest269_amp_dist.sh mode change 100755 => 100644 cv/classification/resnest50/pytorch/train_resnest50_amp_dist.sh mode change 100755 => 100644 cv/classification/resnet101/pytorch/train_resnet101_amp_dist.sh mode change 100755 => 100644 cv/classification/resnet152/pytorch/train_resnet152_amp_dist.sh mode change 100755 => 100644 cv/classification/resnet18/pytorch/train_resnet18_amp_dist.sh mode change 100755 => 100644 cv/classification/resnext101_32x8d/pytorch/train_resnext101_32x8d_amp_dist.sh mode change 100755 => 100644 cv/classification/resnext50_32x4d/pytorch/train_resnext50_32x4d_amp_dist.sh mode change 100755 => 100644 cv/classification/seresnext/pytorch/train_seresnext101_32x4d_amp_dist.sh mode change 100755 => 100644 cv/classification/shufflenetv2/pytorch/train_shufflenet_v2_x2_0_amp_dist.sh mode change 100755 => 100644 cv/classification/vgg/pytorch/.gitignore mode change 100755 => 100644 cv/classification/vgg/pytorch/train_vgg16_amp_dist.sh mode change 100755 => 100644 cv/classification/wide_resnet101_2/pytorch/train_wide_resnet101_2_amp_dist.sh mode change 100755 => 100644 cv/classification/xception/pytorch/.gitignore mode change 100755 => 100644 cv/classification/xception/pytorch/README.md mode change 100755 => 100644 cv/classification/xception/pytorch/__init__.py mode change 100755 => 100644 cv/classification/xception/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/classification/xception/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/classification/xception/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/classification/xception/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/classification/xception/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/classification/xception/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/classification/xception/pytorch/dataloader/classification.py mode change 100755 => 100644 cv/classification/xception/pytorch/dataloader/dali_classification.py mode change 100755 => 100644 cv/classification/xception/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/classification/xception/pytorch/dataloader/utils/presets_classification.py mode change 100755 => 100644 cv/classification/xception/pytorch/train.py mode change 100755 => 100644 cv/classification/xception/pytorch/utils_.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/.gitignore mode change 100755 => 100644 cv/detection/autoassign/pytorch/LICENSE mode change 100755 => 100644 cv/detection/autoassign/pytorch/README.md mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_detection.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_instance.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_detection.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance_semantic.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_panoptic.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/deepfashion.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v0.5_instance.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v1_instance.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/openimages_detection.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/voc0712.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/datasets/wider_face.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/cascade_rcnn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/fast_rcnn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_c4.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_dc5.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_caffe_c4.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/retinanet_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_caffe_c4.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/models/ssd300.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_1x.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_20e.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_2x.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/autoassign/README.md mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/autoassign/autoassign_r50_fpn_8x2_1x_coco.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/configs/autoassign/metafile.yml mode change 100755 => 100644 cv/detection/autoassign/pytorch/dist_train.sh mode change 100755 => 100644 cv/detection/autoassign/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/detection/autoassign/pytorch/docker/serve/Dockerfile mode change 100755 => 100644 cv/detection/autoassign/pytorch/docker/serve/config.properties mode change 100755 => 100644 cv/detection/autoassign/pytorch/docker/serve/entrypoint.sh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/model_zoo/deprecated.json mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/model_zoo/mmcls.json mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/model_zoo/open_mmlab.json mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/README.md mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/nms.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align_cpu.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_pool.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/focal_loss.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/nms.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/point_sample.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/roi_align.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/roi_pool.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmcv/version.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/apis/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/apis/inference.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/apis/test.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/apis/train.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/anchor/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/anchor/anchor_generator.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/anchor/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/anchor/point_generator.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/anchor/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/approx_max_iou_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/assign_result.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/atss_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/base_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/center_region_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/grid_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/hungarian_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/mask_hungarian_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/max_iou_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/point_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/region_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/sim_ota_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/task_aligned_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/bucketing_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/distance_point_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/legacy_delta_xywh_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/pseudo_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/tblr_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/yolo_bbox_coder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/demodata.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/match_cost.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/base_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/combined_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/instance_balanced_pos_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/iou_balanced_neg_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_pseudo_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_sampling_result.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/ohem_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/random_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/sampling_result.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/score_hlr_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/bbox/transforms.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/data_structures/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/data_structures/general_data.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/data_structures/instance_data.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/bbox_overlaps.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/class_names.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/mean_ap.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/panoptic_utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/evaluation/recall.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/export/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/export/model_wrappers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/export/onnx_helper.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/export/pytorch2onnx.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/checkloss_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/ema.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/memory_profiler_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/set_epoch_info_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/sync_norm_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/sync_random_size_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/wandblogger_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_lrupdater_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_mode_switch_hook.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/mask/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/mask/mask_target.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/mask/structures.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/mask/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/optimizers/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/optimizers/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/post_processing/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/post_processing/bbox_nms.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/post_processing/matrix_nms.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/post_processing/merge_augs.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/utils/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/utils/dist_utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/utils/misc.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/visualization/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/visualization/image.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/core/visualization/palette.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/coco_api.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/coco.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/custom.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/compose.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formating.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formatting.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/loading.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/samplers/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/samplers/class_aware_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/samplers/group_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/samplers/infinite_sampler.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/datasets/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/backbones/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/backbones/resnet.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_free_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/atss_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/autoassign_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/base_dense_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/dense_test_mixins.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/fcos_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/dense_heads/paa_head.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/detectors/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/detectors/autoassign.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/detectors/base.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/detectors/single_stage.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/accuracy.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/cross_entropy_loss.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/focal_loss.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/iou_loss.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/losses/utils.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/necks/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/necks/fpn.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/brick_wrappers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/builder.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/ckpt_convert.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/conv_upsample.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/csp_layer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/gaussian_target.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/inverted_residual.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/make_divisible.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/misc.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/normed_predictor.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/panoptic_gt_processing.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/point_sample.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/positional_encoding.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/res_layer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/models/utils/se_layer.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/__init__.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/collect_env.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/compat_config.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/contextmanagers.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/logger.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/memory.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/misc.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/profiling.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/replace_cfg_vals.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/setup_env.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/split_batch.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/util_distribution.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/util_mixins.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/utils/util_random.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/mmdet/version.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/pytest.ini mode change 100755 => 100644 cv/detection/autoassign/pytorch/requirements.txt mode change 100755 => 100644 cv/detection/autoassign/pytorch/setup.py mode change 100755 => 100644 cv/detection/autoassign/pytorch/train.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/detectors/base_detector.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/detectors/ctdet.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/detectors/ddd.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/detectors/exdet.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/detectors/multi_pose.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/opts.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/trains/base_trainer.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/trains/ctdet.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/trains/ddd.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/trains/exdet.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/trains/multi_pose.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/utils/__init__.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/lib/utils/image.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/main.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/test.py mode change 100755 => 100644 cv/detection/centernet/pytorch/src/tools/kitti_eval/evaluate_object_3d_offline mode change 100755 => 100644 cv/detection/centernet/pytorch/src/tools/reval.py mode change 100755 => 100644 cv/detection/fcos/pytorch/LICENSE mode change 100755 => 100644 cv/detection/fcos/pytorch/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_101_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_C4_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_keypoint_rcnn_R_50_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_101_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_C4_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X-152-32x8d-FPN-IN5k_1.44x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/cityscapes/e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/cityscapes/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_101_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_C4_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_600.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_chamv1a_600.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_keypoint_rcnn_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_101_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_C4_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_600.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_R_101_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_32x8d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_64x4d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_bn_bs16_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_32x8d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_64x4d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_1x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_1x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/pascal_voc/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_C4_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_keypoint_rcnn_R_50_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_C4_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_C4_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_FPN_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_P5_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x_quick.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_P5_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/retinanet/retinanet_X_101_32x8d_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/rpn_R_101_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/rpn_R_50_C4_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/rpn_R_50_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/configs/rpn_X_101_32x8d_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_R_50_FPN_1x.png mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_X_101_32x8d_FPN_1x.png mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/fcos_demo.py mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000000885.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000001000.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000005477.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000007281.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000012639.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000033759.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000039769.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000050896.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000053505.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000128654.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000463842.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000479030.jpg mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/predictor.py mode change 100755 => 100644 cv/detection/fcos/pytorch/demo/webcam.py mode change 100755 => 100644 cv/detection/fcos/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/detection/fcos/pytorch/docker/docker-jupyter/Dockerfile mode change 100755 => 100644 cv/detection/fcos/pytorch/docker/docker-jupyter/jupyter_notebook_config.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos/bin/fcos delete mode 120000 cv/detection/fcos/pytorch/fcos/configs create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_R_101_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_R_50_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_32x8d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_64x4d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_bn_bs16_MNV2_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_50_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_32x8d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_64x4d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_50_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_MNV2_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml create mode 100644 cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos/fcos.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/config/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/config/defaults.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/config/paths_catalog.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/ROIAlign.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/ROIPool.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/SigmoidFocalLoss.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cpu/ROIAlign_cpu.cpp mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cpu/nms_cpu.cpp mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cpu/vision.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIAlign_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIPool_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/SigmoidFocalLoss_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_kernel_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_kernel_cuda.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ml_nms.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/nms.cu mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/cuda/vision.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/deform_conv.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/deform_pool.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/ml_nms.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/nms.h mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/csrc/vision.cpp mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/build.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/collate_batch.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/coco.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/concat_dataset.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/coco_eval.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/voc_eval.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/list_dataset.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/datasets/voc.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/samplers/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/samplers/distributed.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/samplers/grouped_batch_sampler.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/samplers/iteration_based_batch_sampler.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/transforms/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/transforms/build.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/data/transforms/transforms.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/engine/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/engine/bbox_aug.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/engine/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/engine/trainer.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/_utils.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/batch_norm.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/dcn/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_func.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_module.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_func.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_module.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/iou_loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/misc.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/nms.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/roi_align.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/roi_pool.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/scale.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/sigmoid_focal_loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/layers/smooth_l1_loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/backbone.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_builder.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_modeldef.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fpn.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/mobilenet.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/backbone/resnet.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/balanced_positive_negative_sampler.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/box_coder.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/detector/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/detector/detectors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/detector/generalized_rcnn.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/make_layers.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/matcher.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/poolers.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/registry.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/box_head.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_feature_extractors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_predictors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/keypoint_head.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_feature_extractors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_predictors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/mask_head.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_feature_extractors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_predictors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/roi_heads.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/anchor_generator.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/fcos.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/inference.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/loss.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/retinanet.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/rpn.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/rpn/utils.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/modeling/utils.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/solver/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/solver/build.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/solver/lr_scheduler.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/bounding_box.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/boxlist_ops.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/image_list.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/keypoint.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/structures/segmentation_mask.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/README.md mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/__init__.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/c2_model_loading.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/checkpoint.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/collect_env.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/comm.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/cv2_util.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/env.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/imports.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/logger.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/metric_logger.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/miscellaneous.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/model_serialization.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/model_zoo.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/registry.py mode change 100755 => 100644 cv/detection/fcos/pytorch/fcos_core/utils/timer.py mode change 100755 => 100644 cv/detection/fcos/pytorch/onnx/export_model_to_onnx.py mode change 100755 => 100644 cv/detection/fcos/pytorch/onnx/test_fcos_onnx_model.py mode change 100755 => 100644 cv/detection/fcos/pytorch/requirements.txt mode change 100755 => 100644 cv/detection/fcos/pytorch/setup.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/checkpoint.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/env_tests/env.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_backbones.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_box_coder.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_configs.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_data_samplers.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_detectors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_fbnet.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_feature_extractors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_metric_logger.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_nms.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_predictors.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_rpn_heads.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/test_segmentation_mask.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tests/utils.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tools/cityscapes/convert_cityscapes_to_coco.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tools/cityscapes/instances2dict_with_polygons.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tools/remove_solver_states.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tools/test_net.py mode change 100755 => 100644 cv/detection/fcos/pytorch/tools/train_net.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/README.md mode change 100755 => 100644 cv/detection/pvanet/pytorch/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/coco_eval.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/common_utils/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/common_utils/dist.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/common_utils/metric_logger.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/common_utils/misc.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/common_utils/smooth_value.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/detection.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/coco_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/functional.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/functional_pil.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/functional_tensor.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/pascal_voc.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/presets_detection.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/presets_segmentation.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/dataloader/utils/transforms_det.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/engine.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/group_by_aspect_ratio.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/anchor_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/det_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/generalized_rcnn.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/image_list.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/model_main.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/model_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/__init__.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/_box_convert.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/_ops.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/_utils.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/boxes.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/feature_pyramid_network.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/focal_loss.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/misc.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/poolers.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/roi_align.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/roi_pool.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/ops/smooth_l1_loss.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/pvanet.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/roi_heads.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/rpn.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/transform.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/model/weight_init.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/train.py mode change 100755 => 100644 cv/detection/pvanet/pytorch/train_pvanet_dist.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/Dockerfile mode change 100755 => 100644 cv/detection/ssd/MindSpore/README.md mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/CMakeLists.txt mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/aipp.cfg mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/build.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/inc/utils.h mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/src/main.cc mode change 100755 => 100644 cv/detection/ssd/MindSpore/ascend310_infer/src/utils.cc mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd300_config.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd300_config_gpu.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_300_config_gpu.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config_gpu.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config_gpu.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_vgg16_config.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/config/ssd_vgg16_config_gpu.yaml mode change 100755 => 100644 cv/detection/ssd/MindSpore/eval.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/eval_onnx.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/export.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/mindspore_hub_conf.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/postprocess.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/requirements.txt mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_distribute_train.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_distribute_train_gpu.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_eval.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_eval_gpu.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_eval_onnx.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_infer_310.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_standalone_train.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/scripts/run_standalone_train_gpu.sh mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/__init__.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/anchor_generator.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/box_utils.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/dataset.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/eval_callback.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/eval_utils.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/fpn.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/init_params.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/lr_schedule.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/mobilenet_v1.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/model_utils/config.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/model_utils/device_adapter.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/model_utils/local_adapter.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/model_utils/moxing_adapter.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/resnet.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/ssd.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/src/vgg16.py mode change 100755 => 100644 cv/detection/ssd/MindSpore/train.py mode change 100755 => 100644 cv/detection/yolof/pytorch/.gitignore mode change 100755 => 100644 cv/detection/yolof/pytorch/LICENSE mode change 100755 => 100644 cv/detection/yolof/pytorch/README.md mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/_base_/datasets/coco_detection.py mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/_base_/schedules/schedule_1x.py mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/yolof/README.md mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/yolof/metafile.yml mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_1x_coco.py mode change 100755 => 100644 cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_iter-1x_coco.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/model_zoo/deprecated.json mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/model_zoo/mmcls.json mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/README.md mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/nms.cpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/focal_loss.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/ops/nms.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmcv/version.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/apis/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/apis/test.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/apis/train.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/anchor/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/anchor/anchor_generator.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/anchor/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/anchor/utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/assign_result.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/base_assigner.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/coder/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/base_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/sampling_result.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/bbox/transforms.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/bbox_overlaps.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/class_names.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/mean_ap.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/panoptic_utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/evaluation/recall.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/optimizers/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/optimizers/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/post_processing/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/post_processing/bbox_nms.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/post_processing/matrix_nms.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/post_processing/merge_augs.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/utils/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/utils/dist_utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/core/utils/misc.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/coco_api.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/coco.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/custom.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/auto_augment.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/compose.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formating.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formatting.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/instaboost.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/loading.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/samplers/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/samplers/class_aware_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/samplers/group_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/samplers/infinite_sampler.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/datasets/utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/backbones/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/backbones/resnet.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/builder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/dense_heads/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/dense_heads/anchor_head.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/dense_heads/base_dense_head.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/dense_heads/dense_test_mixins.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/dense_heads/yolof_head.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/detectors/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/detectors/base.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/detectors/single_stage.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/detectors/yolof.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/losses/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/losses/accuracy.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/losses/focal_loss.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/losses/iou_loss.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/losses/utils.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/necks/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/necks/dilated_encoder.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/utils/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/models/utils/res_layer.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/__init__.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/collect_env.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/compat_config.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/contextmanagers.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/logger.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/memory.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/misc.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/replace_cfg_vals.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/setup_env.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/split_batch.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/utils/util_distribution.py mode change 100755 => 100644 cv/detection/yolof/pytorch/mmdet/version.py mode change 100755 => 100644 cv/detection/yolof/pytorch/requirements.txt mode change 100755 => 100644 cv/detection/yolof/pytorch/setup.cfg mode change 100755 => 100644 cv/detection/yolof/pytorch/setup.py mode change 100755 => 100644 cv/detection/yolof/pytorch/train.py mode change 100755 => 100644 cv/detection/yolof/pytorch/train.sh mode change 100755 => 100644 cv/detection/yolof/pytorch/train_dist.sh mode change 100755 => 100644 cv/detection/yolov3/pytorch/README.md mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/coco.names mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/custom/classes.names mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/custom/images/train.jpg mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/custom/labels/train.txt mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/custom/train.txt mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/custom/valid.txt mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/get_coco_dataset.sh mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/voc.names mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/voc/train.txt mode change 100755 => 100644 cv/detection/yolov3/pytorch/data/voc/valid.txt mode change 100755 => 100644 cv/instance_segmentation/yolact/pytorch/external/DCNv2/make.sh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/.gitignore mode change 100755 => 100644 cv/ocr/dbnet/pytorch/CITATION.cff mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/PKG-INFO mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/SOURCES.txt mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/dependency_links.txt mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/not-zip-safe mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/requires.txt mode change 100755 => 100644 cv/ocr/dbnet/pytorch/EGG-INFO/top_level.txt mode change 100755 => 100644 cv/ocr/dbnet/pytorch/LICENSE mode change 100755 => 100644 cv/ocr/dbnet/pytorch/README.md mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/det_datasets/icdar2015.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_mobilenetv3_fpnc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r18_fpnc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r50dcnv2_fpnc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/det_pipelines/dbnet_pipeline.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_adam_1200e.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/textdet/dbnet/README.md mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_mobilenetv3_fpnc_1200e_icdar2015.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r18_fpnc_1200e_icdar2015.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r50dcnv2_fpnc_1200e_icdar2015.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/configs/textdet/dbnet/metafile.yml mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/apis/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/apis/inference.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/apis/test.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/apis/train.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/apis/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_ic13.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_iou.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/evaluation/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/mask.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/core/visualize.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/base_dataset.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/icdar_dataset.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/box_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/crop.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/custom_format_bundle.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/dbnet_transforms.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/loading.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/base_textdet_targets.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/dbnet_targets.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transform_wrappers.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/text_det_dataset.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/uniform_concat_dataset.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/utils/backend.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/utils/loader.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/datasets/utils/parser.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/unet.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/single_stage.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/losses/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/losses/dice_loss.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/common/losses/focal_loss.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/db_head.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/head_mixin.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/dbnet.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/single_stage_text_detector.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/text_detector_mixin.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/db_loss.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/fpn_cat.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/base_postprocessor.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/db_postprocessor.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/box_util.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/check_argument.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/collect_env.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/fileio.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/lmdb_util.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/logger.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/model.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/ocr.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/setup_env.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/utils/string_util.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet/version.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/activation.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/drop.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/norm.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/padding.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/registry.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/resnet.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/engine/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/engine/test.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/file_client.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/base.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/io.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/fileio/parse.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/colorspace.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/geometric.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/io.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/misc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/image/photometric.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/deprecated.json mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/mmcls.json mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/open_mmlab.json mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/torchvision_0.12.json mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/README.md mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_device_registry.hpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/cudabind.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_align_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_conv.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_roi_pool.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/modulated_deform_conv.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/ms_deform_attn.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_align.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_pool.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_conv.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_roi_pool.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/info.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/modulated_deform_conv.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/multi_scale_deform_attn.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_align.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_pool.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/ops/sync_bn.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/_functions.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/collate.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_container.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_parallel.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/registry.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/scatter_gather.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/parallel/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_module.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_runner.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/checkpoint.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/default_constructor.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/dist_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/fp16_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/closure.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/ema.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/hook.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/clearml.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/segmind.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/memory.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/profiler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/iter_based_runner.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/log_buffer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/priority.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/runner/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/config.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/device_type.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/env.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/ext_loader.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/hub.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/logging.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/misc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_jit.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/path.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/progressbar.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/registry.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/seed.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/testing.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/timer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/trace.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/utils/version_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_cv/version.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/apis/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/apis/test.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/transforms.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/bbox_overlaps.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/class_names.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/mean_ap.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/panoptic_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/recall.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/mask/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/mask/structures.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/mask/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/utils/dist_utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/utils/misc.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/image.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/palette.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/coco_api.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/panoptic_evaluation.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/coco.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/custom.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/compose.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/formatting.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/loading.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/class_aware_sampler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/group_sampler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/infinite_sampler.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/datasets/utils.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/mobilenet_v3.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/resnet.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/builder.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/base.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/single_stage.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/utils/inverted_residual.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/utils/make_divisible.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/utils/res_layer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/models/utils/se_layer.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/utils/__init__.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/utils/inverted_residual.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/utils/logger.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/utils/profiling.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/utils/util_distribution.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dbnet_det/version.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/dist_train.sh mode change 100755 => 100644 cv/ocr/dbnet/pytorch/requirements.txt mode change 100755 => 100644 cv/ocr/dbnet/pytorch/setup.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/tools/analyze_logs.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/tools/benchmark_processing.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/tools/misc/print_config.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/tools/publish_model.py mode change 100755 => 100644 cv/ocr/dbnet/pytorch/train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/README.md mode change 100755 => 100644 cv/ocr/sar/pytorch/apis/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/apis/train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/apis/utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/box_util.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/check_argument.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/data_convert_util.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/env.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/fileio.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/img_util.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/lmdb_util.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/logger.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/model.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/setup_env.py mode change 100755 => 100644 cv/ocr/sar/pytorch/basic_utils/string_util.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/MJ_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_alphanumeric_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/ST_SA_MJ_real_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/ST_charbox_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_test.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/academic_test.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/seg_toy_data.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/datasets/toy_data.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/models/sar.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/pipelines/sar_pipeline.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/runtime_10e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_18e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_5e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_600e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_20e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_5e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_600e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_6e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1500e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_160e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_600e.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/metafile.yml mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/sar_r31_parallel_decoder_academic.py mode change 100755 => 100644 cv/ocr/sar/pytorch/configs/sar_r31_sequential_decoder_academic.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/evaluation/ocr_metric.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/evaluation/utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/mask.py mode change 100755 => 100644 cv/ocr/sar/pytorch/core/visualize.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/.gitignore mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/build.sh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/clean.sh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/install.sh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/activation.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/drop.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hswish.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/norm.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/padding.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/registry.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/scale.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/swish.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/transformer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/cnn/utils/weight_init.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/assign_score_withk.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/bbox.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/README.md mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/assign_score_withk.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/bbox_overlaps.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/roi_align_cuda.cu mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align_cpu.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/info.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/roi_align.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/ops/sync_bn.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/runner/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/runner/base_module.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/runner/dist_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/config.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/ext_loader.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/logging.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/misc.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/parrots_wrapper.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/path.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/registry.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/sar/utils/version_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/csrc/setup.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/base_dataset.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/ocr_dataset.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/box_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/crop.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/custom_format_bundle.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/loading.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/ocr_transforms.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/test_time_aug.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/transform_wrappers.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/uniform_concat_dataset.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/utils/loader.py mode change 100755 => 100644 cv/ocr/sar/pytorch/datasets_/utils/parser.py mode change 100755 => 100644 cv/ocr/sar/pytorch/dist_train.sh mode change 100755 => 100644 cv/ocr/sar/pytorch/models/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/backbones/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/backbones/resnet31_ocr.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/convertors/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/convertors/attn.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/convertors/base.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/decoders/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/decoders/base_decoder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/decoders/sar_decoder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/decoders/sar_decoder_with_bs.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/encoders/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/encoders/base_encoder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/encoders/sar_encoder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/layers/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/layers/conv_layer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/layers/resnet.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/losses/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/losses/ce_loss.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/recognizer/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/recognizer/base.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/recognizer/encode_decode_recognizer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/models/recognizer/sar.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/engine/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/engine/test.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/file_client.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/handlers/base.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/io.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/fileio/parse.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/colorspace.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/geometric.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/io.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/misc.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/image/photometric.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/_functions.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/collate.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/data_container.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/data_parallel.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/distributed.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/registry.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/parallel/utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/base_module.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/base_runner.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/checkpoint.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/dist_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/fp16_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/closure.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/ema.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/hook.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/memory.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/log_buffer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/priority.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/runner/weight_init.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/config.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/ext_loader.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/logging.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/misc.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/parrots_jit.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/path.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/progressbar.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/registry.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/testing.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/timer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrcv/utils/version_utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/assign_result.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/demodata.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/base_sampler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/random_sampler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/sampling_result.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/bbox/transforms.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/evaluation/bbox_overlaps.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/mask/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/core/mask/structures.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/coco_api.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/auto_augment.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/compose.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/formating.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/instaboost.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/loading.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/samplers/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/samplers/group_sampler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/samplers/infinite_sampler.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/datasets/utils.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/builder.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/detectors/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/detectors/base.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/detectors/single_stage.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/models/utils/transformer.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/utils/__init__.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/utils/util_mixins.py mode change 100755 => 100644 cv/ocr/sar/pytorch/ocrdet/utils/util_random.py mode change 100755 => 100644 cv/ocr/sar/pytorch/openvino_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/requirements.txt mode change 100755 => 100644 cv/ocr/sar/pytorch/seg_synthtext_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/svt_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/synthtext_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/textocr_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/totaltext_converter.py mode change 100755 => 100644 cv/ocr/sar/pytorch/train.py mode change 100755 => 100644 cv/ocr/sar/pytorch/txt2lmdb.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/.gitignore mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/README.md mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/apis/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/apis/train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/apis/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/box_util.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/check_argument.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/data_convert_util.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/env.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/fileio.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/img_util.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/lmdb_util.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/logger.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/model.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/setup_env.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/basic_utils/string_util.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/runtime_10e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_18e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_5e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_600e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_20e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_5e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_600e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_6e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1200e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1500e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_160e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_600e.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_alphanumeric_train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/ST_SA_MJ_real_train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_test.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/datasets_/academic_test.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/models/satrn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/models/satrn_academic.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/models/satrn_academic_sample.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/models/satrn_small.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/models/satrn_small_sample.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/configs/pipelines/satrn_pipeline.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/evaluation/ocr_metric.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/evaluation/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/mask.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/core/visualize.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/.gitignore mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/build.sh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/clean.sh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/install.sh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/activation.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/drop.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hswish.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/norm.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/padding.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/registry.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/scale.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/swish.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/transformer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/weight_init.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/assign_score_withk.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/bbox.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/README.md mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/assign_score_withk.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/bbox_overlaps.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/roi_align_cuda.cu mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align_cpu.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/info.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/roi_align.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/ops/sync_bn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/runner/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/runner/base_module.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/runner/dist_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/config.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/ext_loader.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/logging.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/misc.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/parrots_wrapper.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/path.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/registry.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/satrn/utils/version_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/csrc/setup.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/base_dataset.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/ocr_dataset.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/box_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/crop.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/custom_format_bundle.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/loading.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/ocr_transforms.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/test_time_aug.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/transform_wrappers.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/uniform_concat_dataset.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/utils/loader.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/datasets_/utils/parser.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/dist_train.sh mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/backbones/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/backbones/shallow_cnn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/detectors/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/detectors/single_stage.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/layers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/layers/transformer_layers.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/losses/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/losses/dice_loss.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/losses/focal_loss.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/modules/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/common/modules/transformer_module.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/convertors/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/convertors/attn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/convertors/base.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/decoders/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/decoders/base_decoder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/decoders/nrtr_decoder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/decoders/transformer_decoder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/encoders/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/encoders/base_encoder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/encoders/satrn_encoder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/conv_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/dot_product_attention_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/lstm_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/position_aware_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/robust_scanner_fusion_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/layers/transformer_layer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/losses/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/losses/ce_loss.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/recognizer/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/recognizer/base.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/recognizer/encode_decode_recognizer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/models/recognizer/satrn.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/engine/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/engine/test.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/file_client.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/base.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/io.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/fileio/parse.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/colorspace.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/geometric.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/io.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/misc.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/image/photometric.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/_functions.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/collate.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_container.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_parallel.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/registry.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/parallel/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/base_module.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/base_runner.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/checkpoint.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/dist_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/fp16_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/closure.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/ema.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/hook.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/memory.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/log_buffer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/priority.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/runner/weight_init.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/config.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/ext_loader.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/logging.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/misc.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_jit.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/path.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/progressbar.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/registry.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/testing.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/timer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrcv/utils/version_utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/apis/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/apis/test.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/assign_result.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/demodata.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/base_sampler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/random_sampler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/sampling_result.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/transforms.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/bbox_overlaps.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/mask/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/mask/structures.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/core/mask/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/coco_api.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/dataset_wrappers.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/auto_augment.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/compose.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/formating.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/instaboost.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/loading.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/test_time_aug.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/transforms.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/distributed_sampler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/group_sampler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/infinite_sampler.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/datasets_/utils.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/builder.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/base.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/single_stage.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/models/utils/transformer.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/utils/__init__.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/utils/util_mixins.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/ocrdet/utils/util_random.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/openvino_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/requirements.txt mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/seg_synthtext_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/svt_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/synthtext_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/textocr_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/totaltext_converter.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/train.py mode change 100755 => 100644 cv/ocr/satrn/pytorch/base/txt2lmdb.py mode change 100755 => 100644 cv/point_cloud/Point-BERT/pytorch/datasets/io.py mode change 100755 => 100644 cv/point_cloud/Point-BERT/pytorch/extensions/emd/__init__.py mode change 100755 => 100644 cv/point_cloud/Point-BERT/pytorch/extensions/emd/cuda/emd.cpp mode change 100755 => 100644 cv/point_cloud/Point-BERT/pytorch/extensions/emd/emd.py mode change 100755 => 100644 cv/point_cloud/Point-BERT/pytorch/extensions/emd/setup.py delete mode 120000 cv/point_cloud/Point-BERT/pytorch/segmentation/data create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_shape_names.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_test.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_train.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ScanObjectNN_shape_names.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/test.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/train.txt create mode 100644 cv/point_cloud/Point-BERT/pytorch/segmentation/data/shapenet_synset_dict.json mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/dataloader.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hierarchical_data_manager.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hook_wrapper.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/model_wrapper.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/runner.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/utils.py mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/tools/slurm_test.sh mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/tools/slurm_train.sh mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/train.sh mode change 100755 => 100644 cv/semantic_segmentation/apcnet/pytorch/train_dist.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/Dockerfile mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/README.md mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/CMakeLists.txt mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/build.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/fusion_switch.cfg mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/inc/utils.h mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/main.cc mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/utils.cc mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/default_config.yaml mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/eval.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/eval_onnx.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/export.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/Dockerfile mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/convert_om.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/fusion_switch.cfg mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.cfg mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.pipeline mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/docker_start_infer.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/CMakeLists.txt mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/build.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.cpp mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.h mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/main.cpp mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/requirements.txt mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/get_dataset_colormap.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/main.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/run.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/infer/util/get_vocval_lst.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/mindspore_hub_conf.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/config.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/device_adapter.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/local_adapter.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/moxing_adapter.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/modelarts/train_start.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/postprocess.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/requirements.txt mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/build_data.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/docker_start.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s16_r1.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r1.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r2.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_onnx.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16_gpu.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale_flip.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_infer_310.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_cpu.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_gpu.sh mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/data/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/data/build_seg_data.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/data/dataset.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/data/get_dataset_lst.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/loss.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/deeplab_v3.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/net_factory.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/get_multicards_json.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/learning_rates.py mode change 100755 => 100644 cv/semantic_segmentation/deeplabv3/MindSpore/train.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/.gitignore mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/CITATION.cff mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/LICENSE mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/README.md mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes_769x769.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/_base_/default_runtime.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/_base_/models/gcnet_r50-d8.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/_base_/schedules/schedule_40k.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/README.md mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/gcnet_r50-d8_769x769_40k_cityscapes.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/dist_train.sh mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/README.md mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/focal_loss.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmcv/version.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/inference.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/test.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/train.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/class_names.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/metrics.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/base_pixel_sampler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/ohem_pixel_sampler.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/misc.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/cityscapes.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/custom.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/compose.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formating.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formatting.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/loading.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/test_time_aug.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/transforms.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/resnet.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/builder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/decode_head.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/fcn_head.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/gc_head.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/accuracy.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/cross_entropy_loss.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/utils.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/fpn.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/ic_neck.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/jpu.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/mla_neck.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/multilevel_neck.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/base.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/encoder_decoder.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/embed.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/inverted_residual.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/make_divisible.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/res_layer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/se_layer.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/self_attention_block.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/shape_convert.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/up_conv_block.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/encoding.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/wrappers.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/__init__.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/collect_env.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/logger.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/mmseg/version.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/docs.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/mminstall.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/optional.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/readthedocs.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/runtime.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/requirements/tests.txt mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/run_train.sh mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/setup.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/analyze_logs.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/benchmark.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/convert_datasets/cityscapes.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/get_flops.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/print_config.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/tools/test.py mode change 100755 => 100644 cv/semantic_segmentation/gcnet/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/build_env.sh mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/configs/basicvsr_plusplus/basicvsr_plusplus_c64n7_8x1_600k_reds4.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/docker/README.md mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/quantization.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/modulated_deform_conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmcv/version.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/generation_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/inpainting_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/matting_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_face_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_video_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/apis/video_interpolation_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/dist_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/crop.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_pp.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/aspp.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/contextual_attention.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/downsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/ensemble.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gated_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gca_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/generation_model_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/img_normalize.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/linear_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/mask_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/model_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/partial_conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basicvsr.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/utils/cli.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/utils/setup_env.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/setup.py mode change 100755 => 100644 cv/super_resolution/basicVSR++/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/build_env.sh mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/configs/basicvsr/basicvsr_reds4.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/configs/iconvsr/iconvsr_reds4.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/docker/README.md mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/quantization.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmcv/version.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/generation_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/inpainting_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/matting_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_face_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_video_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/dist_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/crop.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/edvr_net.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/iconvsr.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/aspp.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/contextual_attention.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/downsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/ensemble.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gated_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gca_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/generation_model_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/img_normalize.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/linear_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/mask_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/model_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/partial_conv.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basicvsr.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/utils/cli.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/utils/setup_env.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/setup.py mode change 100755 => 100644 cv/super_resolution/basicVSR/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/configs/esrgan_psnr_x4c64b23g32_g1_1000k_div2k.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/docker/README.md mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/get_div2k_anno.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmcv/version.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/generation_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/inpainting_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/matting_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_face_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_video_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/apis/video_interpolation_inference.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/core/utils/dist_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/comp1k_dataset.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/crop.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_annotation_dataset.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_folder_dataset.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/rrdb_net.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/aspp.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/contextual_attention.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/conv.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/downsample.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/ensemble.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/gated_conv_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/gca_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/generation_model_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/img_normalize.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/linear_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/mask_conv_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/model_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/partial_conv.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/components/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/modified_vgg.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/losses/gan_loss.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/losses/perceptual_loss.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/esrgan.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/srgan.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/utils/cli.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/utils/setup_env.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/esrgan/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/liif/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/liif/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/liif/pytorch/configs/restorers/liif/README.md mode change 100755 => 100644 cv/super_resolution/liif/pytorch/configs/restorers/liif/README_zh-CN.md mode change 100755 => 100644 cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_edsr_norm_c64b16_g1_1000k_div2k.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_rdn_norm_x2-4_c64b16_g1_1000k_div2k.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/configs/restorers/liif/metafile.yml mode change 100755 => 100644 cv/super_resolution/liif/pytorch/dist_test.sh mode change 100755 => 100644 cv/super_resolution/liif/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/liif/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/super_resolution/liif/pytorch/docker/README.md mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/dataloader.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/hierarchical_data_manager.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/hook_wrapper.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/model_wrapper.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/runner.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmcv/device/ipu/utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/apis/generation_inference.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/core/utils/dist_utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/generate_assistant.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/random_down_sampling.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_dataset.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/liif_net.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/aspp.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/contextual_attention.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/conv.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/downsample.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/ensemble.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/gated_conv_module.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/gca_module.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/generation_model_utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/img_normalize.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/linear_module.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/mask_conv_module.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/model_utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/partial_conv.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/components/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/mlp_refiner.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/models/restorers/liif.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/utils/cli.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/utils/setup_env.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/liif/pytorch/test.py mode change 100755 => 100644 cv/super_resolution/liif/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/build_env.sh mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_c64b20_1x30x8_lr5e-5_150k_reds.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_wogan_c64b20_2x30x8_lr1e-4_300k_reds.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/crop_sub_images.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/docker/Dockerfile mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/docker/README.md mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/quantization.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/info.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/sync_bn.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmcv/version.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/generation_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/inpainting_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/matting_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_face_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_video_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/dist_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/blur_kernels.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/crop.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/random_degradations.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/real_basicvsr_net.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/aspp.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/contextual_attention.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/conv.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/downsample.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/ensemble.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gated_conv_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gca_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/generation_model_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/img_normalize.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/linear_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/mask_conv_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/model_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/partial_conv.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/unet_disc.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/gan_loss.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/perceptual_loss.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_basicvsr.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_esrgan.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/srgan.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/cli.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/setup_env.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/setup.py mode change 100755 => 100644 cv/super_resolution/real_basicVSR/pytorch/train.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/.gitignore mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/checkpoints/args.txt mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/checkpoints/train.log mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/dataset/cufed.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/dataset/dataloader.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/eval.sh mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/loss/discriminator.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/loss/loss.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/main.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/model/LTE.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/model/MainNet.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/model/SearchTransfer.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/model/TTSR.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/model/Vgg19.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/option.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/test.sh mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/test/demo/lr/0.png mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/test/demo/ref/0.png mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/train.sh mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/trainer.py mode change 100755 => 100644 cv/super_resolution/ttsr/pytorch/utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/LICENSE mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/README.md mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/configs/TTVSR_reds4.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/dist_train.sh mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/alexnet.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/activation.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/context_block.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_module.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_ws.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/drop.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/generalized_attention.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hsigmoid.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hswish.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/non_local.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/norm.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/padding.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/plugin.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/registry.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/scale.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/swish.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/transformer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/upsample.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/wrappers.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/resnet.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/flops_counter.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/fuse_conv_bn.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/sync_bn.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/weight_init.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/cnn/vgg.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/engine/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/engine/test.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/file_client.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/base.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/json_handler.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/pickle_handler.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/yaml_handler.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/io.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/fileio/parse.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/colorspace.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/geometric.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/io.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/misc.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/image/photometric.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/_functions.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/collate.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_container.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_parallel.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed_deprecated.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/registry.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/scatter_gather.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/parallel/utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_module.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_runner.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/checkpoint.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/default_constructor.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/dist_utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/epoch_based_runner.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/fp16_utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/checkpoint.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/closure.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/ema.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/evaluation.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/hook.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/iter_timer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/base.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/dvclive.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/mlflow.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/neptune.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/pavi.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/tensorboard.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/text.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/wandb.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/lr_updater.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/memory.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/momentum_updater.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/optimizer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/profiler.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sampler_seed.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sync_buffer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/iter_based_runner.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/log_buffer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/default_constructor.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/priority.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/runner/utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/config.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/env.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/ext_loader.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/logging.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/misc.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_jit.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_wrapper.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/path.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/progressbar.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/registry.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/testing.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/timer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/trace.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/utils/version_utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmcv/version.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/apis/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_inference.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_video_inference.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/apis/test.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/apis/train.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/distributed_wrapper.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/eval_hooks.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metric_utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metrics.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/niqe_pris_params.npz mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/export/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/export/wrappers.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/visualization.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/mask.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/misc.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/lr_updater.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_sr_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/dataset_wrappers.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/augmentation.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/compose.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/crop.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/formating.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/generate_assistant.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/loading.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/matting_aug.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/normalization.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/random_down_sampling.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/registry.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/distributed_sampler.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_multiple_gt_dataset.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/ttvsrnet.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/base.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/builder.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/common/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/common/flow_warp.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/common/sr_backbone_utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/common/upsample.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/pixelwise_loss.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/utils.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/registry.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/basic_restorer.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/ttvsr.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/utils/__init__.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/utils/collect_env.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/utils/logger.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/mmedit/version.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/requirements.txt mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/setup.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/tools/dist_test.sh mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/tools/slurm_test.sh mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/tools/slurm_train.sh mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/tools/test.py mode change 100755 => 100644 cv/super_resolution/ttvsr/pytorch/train.py create mode 100644 fairseq-tools/README_bart.md create mode 100644 fairseq-tools/README_convolutional.md create mode 100644 fairseq-tools/README_environment.md create mode 100644 fairseq-tools/README_roberta.md create mode 100644 fairseq-tools/README_transformer.md create mode 100644 fairseq-tools/fairseq/.github/ISSUE_TEMPLATE.md create mode 100644 fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/bug_report.md create mode 100644 fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/documentation.md create mode 100644 fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/feature_request.md create mode 100644 fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/how-to-question.md create mode 100644 fairseq-tools/fairseq/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 fairseq-tools/fairseq/.github/workflows/build.yml create mode 100644 fairseq-tools/fairseq/.github/workflows/build_wheels.yml create mode 100644 fairseq-tools/fairseq/.gitignore create mode 100644 fairseq-tools/fairseq/.gitmodules create mode 100644 fairseq-tools/fairseq/CODE_OF_CONDUCT.md create mode 100644 fairseq-tools/fairseq/CONTRIBUTING.md create mode 100644 fairseq-tools/fairseq/LICENSE create mode 100644 fairseq-tools/fairseq/bart.py create mode 100644 fairseq-tools/fairseq/bart.sh create mode 100644 fairseq-tools/fairseq/config/config.yaml create mode 100644 fairseq-tools/fairseq/config/config_eval_lm.yaml create mode 100644 fairseq-tools/fairseq/config/criterion/adaptive_loss.yaml create mode 100644 fairseq-tools/fairseq/config/criterion/cross_entropy.yaml create mode 100644 fairseq-tools/fairseq/config/lr_scheduler/cosine.yaml create mode 100644 fairseq-tools/fairseq/config/lr_scheduler/inverse_sqrt.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_baevski_gbw.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_baevski_wiki103.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_big.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_gbw.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_gpt.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_gpt2_big.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_gpt2_medium.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_gpt2_small.yaml create mode 100644 fairseq-tools/fairseq/config/model/transformer_lm_wiki103.yaml create mode 100644 fairseq-tools/fairseq/config/optimizer/adam.yaml create mode 100644 fairseq-tools/fairseq/config/optimizer/nag.yaml create mode 100644 fairseq-tools/fairseq/config/params/eval_lm_params.yaml create mode 100644 fairseq-tools/fairseq/config/params/training_params.yaml create mode 100644 fairseq-tools/fairseq/config/task/language_modeling.yaml create mode 100644 fairseq-tools/fairseq/docs/Makefile create mode 100644 fairseq-tools/fairseq/docs/_static/theme_overrides.css create mode 100644 fairseq-tools/fairseq/docs/command_line_tools.rst create mode 100644 fairseq-tools/fairseq/docs/conf.py create mode 100644 fairseq-tools/fairseq/docs/criterions.rst create mode 100644 fairseq-tools/fairseq/docs/data.rst create mode 100644 fairseq-tools/fairseq/docs/docutils.conf create mode 100644 fairseq-tools/fairseq/docs/fairseq.gif create mode 100644 fairseq-tools/fairseq/docs/fairseq_logo.png create mode 100644 fairseq-tools/fairseq/docs/getting_started.rst create mode 100644 fairseq-tools/fairseq/docs/hydra_integration.md create mode 100644 fairseq-tools/fairseq/docs/index.rst create mode 100644 fairseq-tools/fairseq/docs/lr_scheduler.rst create mode 100644 fairseq-tools/fairseq/docs/make.bat create mode 100644 fairseq-tools/fairseq/docs/models.rst create mode 100644 fairseq-tools/fairseq/docs/modules.rst create mode 100644 fairseq-tools/fairseq/docs/optim.rst create mode 100644 fairseq-tools/fairseq/docs/overview.rst create mode 100644 fairseq-tools/fairseq/docs/requirements.txt create mode 100644 fairseq-tools/fairseq/docs/tasks.rst create mode 100644 fairseq-tools/fairseq/docs/tutorial_classifying_names.rst create mode 100644 fairseq-tools/fairseq/docs/tutorial_simple_lstm.rst create mode 100644 fairseq-tools/fairseq/examples/.gitignore create mode 100644 fairseq-tools/fairseq/examples/__init__.py create mode 100644 fairseq-tools/fairseq/examples/backtranslation/README.md create mode 100644 fairseq-tools/fairseq/examples/backtranslation/deduplicate_lines.py create mode 100644 fairseq-tools/fairseq/examples/backtranslation/extract_bt_data.py create mode 100644 fairseq-tools/fairseq/examples/backtranslation/prepare-de-monolingual.sh create mode 100644 fairseq-tools/fairseq/examples/backtranslation/prepare-wmt18en2de.sh create mode 100644 fairseq-tools/fairseq/examples/backtranslation/sacrebleu.sh create mode 100644 fairseq-tools/fairseq/examples/backtranslation/tokenized_bleu.sh create mode 100644 fairseq-tools/fairseq/examples/bart/README.glue.md create mode 100644 fairseq-tools/fairseq/examples/bart/README.md create mode 100644 fairseq-tools/fairseq/examples/bart/README.summarization.md create mode 100644 fairseq-tools/fairseq/examples/byte_level_bpe/README.md create mode 100644 fairseq-tools/fairseq/examples/byte_level_bpe/get_bitext.py create mode 100644 fairseq-tools/fairseq/examples/byte_level_bpe/get_data.sh create mode 100644 fairseq-tools/fairseq/examples/byte_level_bpe/gru_transformer.py create mode 100644 fairseq-tools/fairseq/examples/camembert/README.md create mode 100644 fairseq-tools/fairseq/examples/constrained_decoding/README.md create mode 100644 fairseq-tools/fairseq/examples/constrained_decoding/normalize.py create mode 100644 fairseq-tools/fairseq/examples/constrained_decoding/tok.py create mode 100644 fairseq-tools/fairseq/examples/conv_seq2seq/README.md create mode 100644 fairseq-tools/fairseq/examples/criss/README.md create mode 100644 fairseq-tools/fairseq/examples/criss/download_and_preprocess_flores_test.sh create mode 100644 fairseq-tools/fairseq/examples/criss/download_and_preprocess_tatoeba.sh create mode 100644 fairseq-tools/fairseq/examples/criss/mining/mine.py create mode 100644 fairseq-tools/fairseq/examples/criss/mining/mine_example.sh create mode 100644 fairseq-tools/fairseq/examples/criss/save_encoder.py create mode 100644 fairseq-tools/fairseq/examples/criss/sentence_retrieval/encoder_analysis.py create mode 100644 fairseq-tools/fairseq/examples/criss/sentence_retrieval/sentence_retrieval_tatoeba.sh create mode 100644 fairseq-tools/fairseq/examples/criss/unsupervised_mt/eval.sh create mode 100644 fairseq-tools/fairseq/examples/cross_lingual_language_model/README.md create mode 100644 fairseq-tools/fairseq/examples/joint_alignment_translation/README.md create mode 100644 fairseq-tools/fairseq/examples/joint_alignment_translation/prepare-wmt18en2de_no_norm_no_escape_no_agressive.sh create mode 100644 fairseq-tools/fairseq/examples/language_model/README.adaptive_inputs.md create mode 100644 fairseq-tools/fairseq/examples/language_model/README.conv.md create mode 100644 fairseq-tools/fairseq/examples/language_model/README.md create mode 100644 fairseq-tools/fairseq/examples/language_model/prepare-wikitext-103.sh create mode 100644 fairseq-tools/fairseq/examples/latent_depth/README.md create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/__init__.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/__init__.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/latent_depth.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/__init__.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_multilingual_transformer.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_transformer.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/__init__.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/latent_layers.py create mode 100644 fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/multilingual_translation_latent_depth.py create mode 100644 fairseq-tools/fairseq/examples/layerdrop/README.md create mode 100644 fairseq-tools/fairseq/examples/linformer/README.md create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/__init__.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/models/__init__.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/models/linformer_roberta.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/modules/__init__.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder_layer.py create mode 100644 fairseq-tools/fairseq/examples/linformer/linformer_src/modules/multihead_linear_attention.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/README.md create mode 100644 fairseq-tools/fairseq/examples/m2m_100/install_dependecies.sh create mode 100644 fairseq-tools/fairseq/examples/m2m_100/process_data/clean_histogram.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/process_data/dedup_data.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/process_data/remove_too_much_punc.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tok.sh create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/README.md create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ja.sh create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ko.sh create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/thirdparty/.gitignore create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_indic.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_thai.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_zh.py create mode 100644 fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenizer_ar.sh create mode 100644 fairseq-tools/fairseq/examples/mbart/README.md create mode 100644 fairseq-tools/fairseq/examples/megatron_11b/README.md create mode 100644 fairseq-tools/fairseq/examples/megatron_11b/detok.py create mode 100644 fairseq-tools/fairseq/examples/multilingual/README.md create mode 100644 fairseq-tools/fairseq/examples/multilingual/finetune_multilingual_model.sh create mode 100644 fairseq-tools/fairseq/examples/multilingual/multilingual_fairseq_gen.sh create mode 100644 fairseq-tools/fairseq/examples/multilingual/train_multilingual_model.sh create mode 100644 fairseq-tools/fairseq/examples/noisychannel/README.md create mode 100644 fairseq-tools/fairseq/examples/noisychannel/__init__.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_generate.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_options.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_score_bw.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_score_lm.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_tune.py create mode 100644 fairseq-tools/fairseq/examples/noisychannel/rerank_utils.py create mode 100644 fairseq-tools/fairseq/examples/nonautoregressive_translation/README.md create mode 100644 fairseq-tools/fairseq/examples/nonautoregressive_translation/scripts.md create mode 100644 fairseq-tools/fairseq/examples/paraphraser/README.md create mode 100644 fairseq-tools/fairseq/examples/paraphraser/paraphrase.py create mode 100644 fairseq-tools/fairseq/examples/pay_less_attention_paper/README.md create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/README.md create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/README.xsum.md create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/__init__.py create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/transformer_pg.py create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/postprocess.py create mode 100644 fairseq-tools/fairseq/examples/pointer_generator/preprocess.py create mode 100644 fairseq-tools/fairseq/examples/quant_noise/README.md create mode 100644 fairseq-tools/fairseq/examples/quant_noise/transformer_quantization_config.yaml create mode 100644 fairseq-tools/fairseq/examples/roberta/README.custom_classification.md create mode 100644 fairseq-tools/fairseq/examples/roberta/README.glue.md create mode 100644 fairseq-tools/fairseq/examples/roberta/README.md create mode 100644 fairseq-tools/fairseq/examples/roberta/README.pretraining.md create mode 100644 fairseq-tools/fairseq/examples/roberta/README.race.md create mode 100644 fairseq-tools/fairseq/examples/roberta/commonsense_qa/README.md create mode 100644 fairseq-tools/fairseq/examples/roberta/commonsense_qa/__init__.py create mode 100644 fairseq-tools/fairseq/examples/roberta/commonsense_qa/commonsense_qa_task.py create mode 100644 fairseq-tools/fairseq/examples/roberta/commonsense_qa/download_cqa_data.sh create mode 100644 fairseq-tools/fairseq/examples/roberta/multiprocessing_bpe_encoder.py create mode 100644 fairseq-tools/fairseq/examples/roberta/preprocess_GLUE_tasks.sh create mode 100644 fairseq-tools/fairseq/examples/roberta/preprocess_RACE.py create mode 100644 fairseq-tools/fairseq/examples/roberta/preprocess_RACE.sh create mode 100644 fairseq-tools/fairseq/examples/roberta/wsc/README.md create mode 100644 fairseq-tools/fairseq/examples/roberta/wsc/__init__.py create mode 100644 fairseq-tools/fairseq/examples/roberta/wsc/wsc_criterion.py create mode 100644 fairseq-tools/fairseq/examples/roberta/wsc/wsc_task.py create mode 100644 fairseq-tools/fairseq/examples/roberta/wsc/wsc_utils.py create mode 100644 fairseq-tools/fairseq/examples/rxf/README.md create mode 100644 fairseq-tools/fairseq/examples/rxf/__init__.py create mode 100644 fairseq-tools/fairseq/examples/rxf/rxf_src/__init__.py create mode 100644 fairseq-tools/fairseq/examples/rxf/rxf_src/label_smoothed_cross_entropy_r3f.py create mode 100644 fairseq-tools/fairseq/examples/rxf/rxf_src/sentence_prediction_r3f.py create mode 100644 fairseq-tools/fairseq/examples/scaling_nmt/README.md create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/README.md create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/criterions/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/criterions/label_smoothed_cross_entropy_latency_augmented.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/docs/baseline.md create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/docs/evaluation.md create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/agent.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_agent.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_text_agent.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/word_splitter.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/client.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/eval_latency.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/evaluate.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/scorer.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/text_scorer.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/eval/server.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/models/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/models/transformer_monotonic_attention.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/modules/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_multihead_attention.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_transformer_layer.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/utils/__init__.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/utils/functions.py create mode 100644 fairseq-tools/fairseq/examples/simultaneous_translation/utils/latency.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/README.md create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/__init__.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/criterions/ASG_loss.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/criterions/__init__.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/criterions/cross_entropy_acc.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/data/__init__.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/data/asr_dataset.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/data/collaters.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/data/data_utils.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/data/replabels.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/datasets/asr_prep_json.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/datasets/prepare-librispeech.sh create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/infer.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/models/__init__.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/models/vggtransformer.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/models/w2l_conv_glu_enc.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/tasks/__init__.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/tasks/speech_recognition.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/utils/wer_utils.py create mode 100644 fairseq-tools/fairseq/examples/speech_recognition/w2l_decoder.py create mode 100644 fairseq-tools/fairseq/examples/speech_to_text/README.md create mode 100644 fairseq-tools/fairseq/examples/speech_to_text/data_utils.py create mode 100644 fairseq-tools/fairseq/examples/speech_to_text/prep_covost_data.py create mode 100644 fairseq-tools/fairseq/examples/speech_to_text/prep_librispeech_data.py create mode 100644 fairseq-tools/fairseq/examples/speech_to_text/prep_mustc_data.py create mode 100644 fairseq-tools/fairseq/examples/stories/README.md create mode 100644 fairseq-tools/fairseq/examples/translation/prepare-iwslt14.sh create mode 100644 fairseq-tools/fairseq/examples/translation/prepare-iwslt17-multilingual.sh create mode 100644 fairseq-tools/fairseq/examples/translation/prepare-wmt14en2de.sh create mode 100644 fairseq-tools/fairseq/examples/translation/prepare-wmt14en2fr.sh create mode 100644 fairseq-tools/fairseq/examples/translation_moe/README.md create mode 100644 fairseq-tools/fairseq/examples/translation_moe/score.py create mode 100644 fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/__init__.py create mode 100644 fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/logsumexp_moe.py create mode 100644 fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/mean_pool_gating_network.py create mode 100644 fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/translation_moe.py create mode 100644 fairseq-tools/fairseq/examples/unsupervised_quality_estimation/README.md create mode 100644 fairseq-tools/fairseq/examples/unsupervised_quality_estimation/aggregate_scores.py create mode 100644 fairseq-tools/fairseq/examples/unsupervised_quality_estimation/meteor.py create mode 100644 fairseq-tools/fairseq/examples/unsupervised_quality_estimation/repeat_lines.py create mode 100644 fairseq-tools/fairseq/examples/wav2vec/README.md create mode 100644 fairseq-tools/fairseq/examples/wav2vec/libri_labels.py create mode 100644 fairseq-tools/fairseq/examples/wav2vec/vq-wav2vec_featurize.py create mode 100644 fairseq-tools/fairseq/examples/wav2vec/wav2vec_featurize.py create mode 100644 fairseq-tools/fairseq/examples/wav2vec/wav2vec_manifest.py create mode 100644 fairseq-tools/fairseq/examples/wmt19/README.md create mode 100644 fairseq-tools/fairseq/examples/xlmr/README.md create mode 100644 fairseq-tools/fairseq/fairseq/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/benchmark/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/benchmark/dummy_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/benchmark/dummy_masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/benchmark/dummy_model.py create mode 100644 fairseq-tools/fairseq/fairseq/benchmark/dummy_mt.py create mode 100644 fairseq-tools/fairseq/fairseq/binarizer.py create mode 100644 fairseq-tools/fairseq/fairseq/checkpoint_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/clib/libbleu/libbleu.cpp create mode 100644 fairseq-tools/fairseq/fairseq/clib/libbleu/module.cpp create mode 100644 fairseq-tools/fairseq/fairseq/clib/libnat/edit_dist.cpp create mode 100644 fairseq-tools/fairseq/fairseq/clib/libnat_cuda/binding.cpp create mode 100644 fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.cu create mode 100644 fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.h create mode 100644 fairseq-tools/fairseq/fairseq/criterions/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/adaptive_loss.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/composite_loss.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/cross_entropy.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/ctc.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/fairseq_criterion.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy_with_alignment.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/legacy_masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/nat_loss.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/sentence_prediction.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/sentence_ranking.py create mode 100644 fairseq-tools/fairseq/fairseq/criterions/wav2vec_criterion.py create mode 100644 fairseq-tools/fairseq/fairseq/data/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/add_target_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/append_token_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/audio_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/global_cmvn.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/specaugment.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/utterance_cmvn.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/raw_audio_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/audio/speech_to_text_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/backtranslation_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/base_wrapper_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/bucket_pad_length_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/colorize_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/concat_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/concat_sentences_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/data_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/data_utils_fast.pyx create mode 100644 fairseq-tools/fairseq/fairseq/data/denoising_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/dictionary.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/byte_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/byte_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/bytes.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/characters.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/fastbpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/hf_bert_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/hf_byte_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/moses_tokenizer.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/nltk_tokenizer.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/sentencepiece_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/space_tokenizer.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/subword_nmt_bpe.py create mode 100644 fairseq-tools/fairseq/fairseq/data/encoders/utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/fairseq_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/fasta_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/id_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/indexed_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/iterators.py create mode 100644 fairseq-tools/fairseq/fairseq/data/language_pair_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/legacy/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/legacy/block_pair_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dictionary.py create mode 100644 fairseq-tools/fairseq/fairseq/data/list_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/lm_context_window_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/lru_cache_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/mask_tokens_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/monolingual_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multi_corpus_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multi_corpus_sampled_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_data_manager.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_epoch_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/multilingual/sampling_method.py create mode 100644 fairseq-tools/fairseq/fairseq/data/nested_dictionary_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/noising.py create mode 100644 fairseq-tools/fairseq/fairseq/data/num_samples_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/numel_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/offset_tokens_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/pad_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/plasma_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/data/prepend_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/prepend_token_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/raw_label_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/replace_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/resampling_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/roll_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/round_robin_zip_datasets.py create mode 100644 fairseq-tools/fairseq/fairseq/data/shorten_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/sort_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/strip_token_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/subsample_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/token_block_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/token_block_utils_fast.pyx create mode 100644 fairseq-tools/fairseq/fairseq/data/transform_eos_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/data/transform_eos_lang_pair_dataset.py create mode 100644 fairseq-tools/fairseq/fairseq/dataclass/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/dataclass/constants.py create mode 100644 fairseq-tools/fairseq/fairseq/dataclass/data_class.py create mode 100644 fairseq-tools/fairseq/fairseq/dataclass/utils.py create mode 100644 fairseq-tools/fairseq/fairseq/distributed_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/file_io.py create mode 100644 fairseq-tools/fairseq/fairseq/file_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/hub_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/incremental_decoding_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/iterative_refinement_generator.py create mode 100644 fairseq-tools/fairseq/fairseq/legacy_distributed_data_parallel.py create mode 100644 fairseq-tools/fairseq/fairseq/logging/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/logging/meters.py create mode 100644 fairseq-tools/fairseq/fairseq/logging/metrics.py create mode 100644 fairseq-tools/fairseq/fairseq/logging/progress_bar.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/criterions/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/criterions/vocab_parallel_cross_entropy.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/megatron_trainer.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/layers.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/model.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/model.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/models/transformer_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/modules/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/modules/multihead_attention.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder.py create mode 100644 fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/bart/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/bart/hub_interface.py create mode 100644 fairseq-tools/fairseq/fairseq/models/bart/model.py create mode 100644 fairseq-tools/fairseq/fairseq/models/composite_encoder.py create mode 100644 fairseq-tools/fairseq/fairseq/models/distributed_fairseq_model.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fairseq_decoder.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fairseq_encoder.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fairseq_incremental_decoder.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fairseq_model.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fconv.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fconv_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/fconv_self_att.py create mode 100644 fairseq-tools/fairseq/fairseq/models/huggingface/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/huggingface/hf_gpt2.py create mode 100644 fairseq-tools/fairseq/fairseq/models/lightconv.py create mode 100644 fairseq-tools/fairseq/fairseq/models/lightconv_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/lstm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/lstm_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/model_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/models/multilingual_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/cmlm_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/fairseq_nat_model.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/insertion_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/iterative_nonautoregressive_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/levenshtein_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/levenshtein_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/nat_crf_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_ensembles.py create mode 100644 fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/alignment_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/hub_interface.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/model.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/model_camembert.py create mode 100644 fairseq-tools/fairseq/fairseq/models/roberta/model_xlmr.py create mode 100644 fairseq-tools/fairseq/fairseq/models/speech_to_text/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/speech_to_text/berard.py create mode 100644 fairseq-tools/fairseq/fairseq/models/speech_to_text/s2t_transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/transformer.py create mode 100644 fairseq-tools/fairseq/fairseq/models/transformer_align.py create mode 100644 fairseq-tools/fairseq/fairseq/models/transformer_from_pretrained_xlm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/transformer_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/models/wav2vec/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec.py create mode 100644 fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2.py create mode 100644 fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2_asr.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/adaptive_input.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/adaptive_softmax.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/beamable_mm.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/character_token_embedder.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/conv_tbc.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/cross_entropy.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/cuda_utils.cu create mode 100644 fairseq-tools/fairseq/fairseq/modules/downsampled_multihead_attention.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamic_convolution.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamic_crf_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/cuda_function_gen.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cpp create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cuh create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda_kernel.cu create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamiconv_cpu.cpp create mode 100644 fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/setup.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/fairseq_dropout.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/fp32_group_norm.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/gelu.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/grad_multiply.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/gumbel_vector_quantizer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/kmeans_vector_quantizer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/layer_drop.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/layer_norm.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/learned_positional_embedding.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/cuda_function_gen.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cpp create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cuh create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda_kernel.cu create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightconv_layer/setup.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/lightweight_convolution.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/linearized_convolution.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/multihead_attention.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/positional_embedding.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quant_noise.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/em.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qconv.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qemb.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qlinear.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/pq.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/pq/utils.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/quantization_options.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qact.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qconv.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qemb.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qlinear.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/ops.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/quantization/scalar/utils.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/same_pad.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/scalar_bias.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/sinusoidal_positional_embedding.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/sparse_multihead_attention.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/transformer_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder_layer.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/transpose_last.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/unfold.py create mode 100644 fairseq-tools/fairseq/fairseq/modules/vggblock.py create mode 100644 fairseq-tools/fairseq/fairseq/nan_detector.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/adadelta.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/adafactor.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/adagrad.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/adam.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/adamax.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/bmuf.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/dynamic_loss_scaler.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/fairseq_optimizer.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/fp16_optimizer.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/fused_adam.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/fused_lamb.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/cosine_lr_scheduler.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fairseq_lr_scheduler.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fixed_schedule.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/inverse_square_root_schedule.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/polynomial_decay_schedule.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/reduce_lr_on_plateau.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/tri_stage_lr_scheduler.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/lr_scheduler/triangular_lr_scheduler.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/nag.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/sgd.py create mode 100644 fairseq-tools/fairseq/fairseq/optim/shard.py create mode 100644 fairseq-tools/fairseq/fairseq/options.py create mode 100644 fairseq-tools/fairseq/fairseq/pdb.py create mode 100644 fairseq-tools/fairseq/fairseq/quantization_utils.py create mode 100644 fairseq-tools/fairseq/fairseq/registry.py create mode 100644 fairseq-tools/fairseq/fairseq/scoring/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/scoring/bleu.py create mode 100644 fairseq-tools/fairseq/fairseq/scoring/chrf.py create mode 100644 fairseq-tools/fairseq/fairseq/scoring/tokenizer.py create mode 100644 fairseq-tools/fairseq/fairseq/scoring/wer.py create mode 100644 fairseq-tools/fairseq/fairseq/search.py create mode 100644 fairseq-tools/fairseq/fairseq/sequence_generator.py create mode 100644 fairseq-tools/fairseq/fairseq/sequence_scorer.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/audio_pretraining.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/cross_lingual_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/denoising.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/fairseq_task.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/language_modeling.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/legacy_masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/multilingual_denoising.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/multilingual_masked_lm.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/multilingual_translation.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/semisupervised_translation.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/sentence_prediction.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/sentence_ranking.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/speech_to_text.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/translation.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_bart.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_xlm.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/translation_lev.py create mode 100644 fairseq-tools/fairseq/fairseq/tasks/translation_multi_simple_epoch.py create mode 100644 fairseq-tools/fairseq/fairseq/token_generation_constraints.py create mode 100644 fairseq-tools/fairseq/fairseq/tokenizer.py create mode 100644 fairseq-tools/fairseq/fairseq/trainer.py create mode 100644 fairseq-tools/fairseq/fairseq/utils.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/__init__.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/eval_lm.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/generate.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/interactive.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/preprocess.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/score.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/train.py create mode 100644 fairseq-tools/fairseq/fairseq_cli/validate.py create mode 100644 fairseq-tools/fairseq/hubconf.py create mode 100644 fairseq-tools/fairseq/pyproject.toml create mode 100644 fairseq-tools/fairseq/roberta.py create mode 100644 fairseq-tools/fairseq/roberta.sh create mode 100644 fairseq-tools/fairseq/scripts/__init__.py create mode 100644 fairseq-tools/fairseq/scripts/average_checkpoints.py create mode 100644 fairseq-tools/fairseq/scripts/build_sym_alignment.py create mode 100644 fairseq-tools/fairseq/scripts/compare_namespaces.py create mode 100644 fairseq-tools/fairseq/scripts/compound_split_bleu.sh create mode 100644 fairseq-tools/fairseq/scripts/constraints/extract.py create mode 100644 fairseq-tools/fairseq/scripts/constraints/validate.py create mode 100644 fairseq-tools/fairseq/scripts/convert_dictionary.lua create mode 100644 fairseq-tools/fairseq/scripts/convert_model.lua create mode 100644 fairseq-tools/fairseq/scripts/count_docs.py create mode 100644 fairseq-tools/fairseq/scripts/read_binarized.py create mode 100644 fairseq-tools/fairseq/scripts/rm_pt.py create mode 100644 fairseq-tools/fairseq/scripts/sacrebleu.sh create mode 100644 fairseq-tools/fairseq/scripts/shard_docs.py create mode 100644 fairseq-tools/fairseq/scripts/split_train_valid_docs.py create mode 100644 fairseq-tools/fairseq/scripts/spm_decode.py create mode 100644 fairseq-tools/fairseq/scripts/spm_encode.py create mode 100644 fairseq-tools/fairseq/scripts/spm_train.py create mode 100644 fairseq-tools/fairseq/setup.py create mode 100644 fairseq-tools/fairseq/tests/__init__.py create mode 100644 fairseq-tools/fairseq/tests/gpu/__init__.py create mode 100644 fairseq-tools/fairseq/tests/gpu/test_binaries_gpu.py create mode 100644 fairseq-tools/fairseq/tests/gpu/transformer_quantization_config.yaml create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/__init__.py create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/asr_test_base.py create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/test_collaters.py create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/test_cross_entropy.py create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/test_data_utils.py create mode 100644 fairseq-tools/fairseq/tests/speech_recognition/test_vggtransformer.py create mode 100644 fairseq-tools/fairseq/tests/test_average_checkpoints.py create mode 100644 fairseq-tools/fairseq/tests/test_backtranslation_dataset.py create mode 100644 fairseq-tools/fairseq/tests/test_binaries.py create mode 100644 fairseq-tools/fairseq/tests/test_bmuf.py create mode 100644 fairseq-tools/fairseq/tests/test_character_token_embedder.py create mode 100644 fairseq-tools/fairseq/tests/test_concat_dataset.py create mode 100644 fairseq-tools/fairseq/tests/test_constraints.py create mode 100644 fairseq-tools/fairseq/tests/test_convtbc.py create mode 100644 fairseq-tools/fairseq/tests/test_dictionary.py create mode 100644 fairseq-tools/fairseq/tests/test_export.py create mode 100644 fairseq-tools/fairseq/tests/test_file_io.py create mode 100644 fairseq-tools/fairseq/tests/test_fp16_optimizer.py create mode 100644 fairseq-tools/fairseq/tests/test_inference_dropout.py create mode 100644 fairseq-tools/fairseq/tests/test_iterators.py create mode 100644 fairseq-tools/fairseq/tests/test_label_smoothing.py create mode 100644 fairseq-tools/fairseq/tests/test_lstm_jitable.py create mode 100644 fairseq-tools/fairseq/tests/test_memory_efficient_fp16.py create mode 100644 fairseq-tools/fairseq/tests/test_metrics.py create mode 100644 fairseq-tools/fairseq/tests/test_multi_corpus_sampled_dataset.py create mode 100644 fairseq-tools/fairseq/tests/test_multihead_attention.py create mode 100644 fairseq-tools/fairseq/tests/test_noising.py create mode 100644 fairseq-tools/fairseq/tests/test_reproducibility.py create mode 100644 fairseq-tools/fairseq/tests/test_resampling_dataset.py create mode 100644 fairseq-tools/fairseq/tests/test_sequence_generator.py create mode 100644 fairseq-tools/fairseq/tests/test_sequence_scorer.py create mode 100644 fairseq-tools/fairseq/tests/test_sparse_multihead_attention.py create mode 100644 fairseq-tools/fairseq/tests/test_token_block_dataset.py create mode 100644 fairseq-tools/fairseq/tests/test_train.py create mode 100644 fairseq-tools/fairseq/tests/test_utils.py create mode 100644 fairseq-tools/fairseq/tests/utils.py create mode 100644 fairseq-tools/fairseq/train.py mode change 100755 => 100644 gnn/GCN/README.md mode change 100755 => 100644 gnn/GCN/ascend310_infer/CMakeLists.txt mode change 100755 => 100644 gnn/GCN/ascend310_infer/build.sh mode change 100755 => 100644 gnn/GCN/ascend310_infer/inc/utils.h mode change 100755 => 100644 gnn/GCN/ascend310_infer/src/main.cc mode change 100755 => 100644 gnn/GCN/ascend310_infer/src/utils.cc mode change 100755 => 100644 gnn/GCN/default_config.yaml mode change 100755 => 100644 gnn/GCN/eval.py mode change 100755 => 100644 gnn/GCN/export.py mode change 100755 => 100644 gnn/GCN/mindspore_hub_conf.py mode change 100755 => 100644 gnn/GCN/model_utils/__init__.py mode change 100755 => 100644 gnn/GCN/model_utils/config.py mode change 100755 => 100644 gnn/GCN/model_utils/device_adapter.py mode change 100755 => 100644 gnn/GCN/model_utils/local_adapter.py mode change 100755 => 100644 gnn/GCN/model_utils/moxing_adapter.py mode change 100755 => 100644 gnn/GCN/postprocess.py mode change 100755 => 100644 gnn/GCN/preprocess.py mode change 100755 => 100644 gnn/GCN/requirements.txt mode change 100755 => 100644 gnn/GCN/scripts/run_distribute_train_gpu.sh mode change 100755 => 100644 gnn/GCN/scripts/run_eval_gpu.sh mode change 100755 => 100644 gnn/GCN/scripts/run_infer_310.sh mode change 100755 => 100644 gnn/GCN/scripts/run_process_data.sh mode change 100755 => 100644 gnn/GCN/scripts/run_train.sh mode change 100755 => 100644 gnn/GCN/scripts/run_train_gpu.sh mode change 100755 => 100644 gnn/GCN/scripts/train_gcn_1p.sh mode change 100755 => 100644 gnn/GCN/src/config.py mode change 100755 => 100644 gnn/GCN/src/dataset.py mode change 100755 => 100644 gnn/GCN/src/eval_callback.py mode change 100755 => 100644 gnn/GCN/src/gcn.py mode change 100755 => 100644 gnn/GCN/src/metrics.py mode change 100755 => 100644 gnn/GCN/t-SNE_visualization_on_Cora.gif mode change 100755 => 100644 gnn/GCN/train.py mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/IMG/multi.png mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/IMG/pokemon.png mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/IMG/single.png mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/README.md mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/requirements.txt mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/test.py mode change 100755 => 100644 multimodal/diffusion/stable-diffusion/training/train_text_to_image.py mode change 100755 => 100644 nlp/cloze_test/glm/pytorch/GLMForMultiTokenCloze/base/data_preprocessing/utils/wordpiece.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/BaseDockerfile mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/bind_pyt.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/cleanup_image_container.sh mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/config/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/config/_base.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/config/config_manager.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/config/mutable_params.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/change_mp.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/preprocess_stc_finetune.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.model mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.vocab mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/vocab.json mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/dataloader.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/samplers.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/dataloaders/tokenization_gpt2.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/fp16/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16util.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/fp16/loss_scaler.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/layers/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/layers/layers.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/losses/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/losses/cross_entropy.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/models/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/models/checkpoint.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/models/gpt2_modeling.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/model/models/transformer.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/optimizers/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/optimizers/factory.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/prepare.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/requirements.txt mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/run_pretraining.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/run_training.sh mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/run_with_docker.sh mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/schedulers/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/schedulers/factory.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/schedulers/learning_rates.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/setup.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/evaluator.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/event/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/event/base.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/event/base_adapter.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/event/compose.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/event/log.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/metrics.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/trainer.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/train/training_state.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/utils/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/utils/check.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/utils/dist.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/utils/logging.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/base/utils/paths.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x1.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x8.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x2x8.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_common.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/converter.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/__init__.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/attention.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/fast_self_multihead_attn_func.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/layernorm.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn_func.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/optimizers_adam.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/training_event.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/dropout.h mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/fast_self_multihead_attn_func.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/layer_norm.h mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/philox.h mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias.cpp mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias_cuda.cu mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_func.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/setup.py mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/softmax.h mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/strided_batched_gemm.h mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/packages/files.txt mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/gen_docker_image.sh mode change 100755 => 100644 nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/install.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/NOTICE mode change 100755 => 100644 nlp/language_model/bert/pytorch/bind.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/bmm1.py mode change 100755 => 100644 nlp/language_model/bert/pytorch/bmm2.py mode change 100755 => 100644 nlp/language_model/bert/pytorch/cleanup_scripts/clean.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/cleanup_scripts/create_pretraining_data_wrapper.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/cleanup_scripts/extract_test_set_articles.py mode change 100755 => 100644 nlp/language_model/bert/pytorch/cleanup_scripts/parallel_create_hdf5.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/cleanup_scripts/process_wiki.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/data_scripts/clean.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/data_scripts/create_pretraining_data_wrapper.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/data_scripts/parallel_create_hdf5.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/data_scripts/process_wiki.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/init.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/input_preprocessing/clean.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/input_preprocessing/create_pretraining_data_wrapper.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/input_preprocessing/parallel_create_hdf5.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/input_preprocessing/process_wiki.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mhalib/mha_funcs.cu mode change 100755 => 100644 nlp/language_model/bert/pytorch/mhalib/setup.py mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/pack_submission.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v0.7_training.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_hpc.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_training.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.1_training.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v2.0_training.sh mode change 100755 => 100644 nlp/language_model/bert/pytorch/padding.py mode change 100755 => 100644 nlp/language_model/bert/pytorch/softmax.py mode change 100755 => 100644 nlp/ner/bert/pytorch/run.sh mode change 100755 => 100644 nlp/ner/bert/pytorch/run_dist.sh mode change 100755 => 100644 nlp/ner/bert/pytorch/run_ner.py mode change 100755 => 100644 recommendation/collaborative_filtering/ncf/pytorch/download_dataset.sh mode change 100755 => 100644 recommendation/collaborative_filtering/ncf/pytorch/ncf_16.py mode change 100755 => 100644 recommendation/collaborative_filtering/ncf/pytorch/ncf_32.py mode change 100755 => 100644 recommendation/collaborative_filtering/ncf/pytorch/run_train_fp16.sh mode change 100755 => 100644 recommendation/collaborative_filtering/ncf/pytorch/run_train_fp32.sh mode change 100755 => 100644 recommendation/ctr/dlrm/pytorch/scripts/dot_based_interact/run.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/README.md mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/conf/train_conformer.yaml mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/local/aishell_data_prep.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/local/aishell_train_lms.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/local/download_and_untar.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/run.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/compute-wer.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/compute_cmvn_stats.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/filter_scp.pl mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/make_raw_list.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/parse_options.sh mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/tools/text2token.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/wenet/bin/recognize.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/wenet/bin/train.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/wenet/dataset/dataset.py mode change 100755 => 100644 speech/speech_recognition/conformer/pytorch/wenet/transformer/convolution.py mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/install.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/requirements.txt mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/docker/Dockerfile mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/docker/build.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/docker/launch.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/download_librispeech.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/inference.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/preprocess_librispeech.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x1.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x4.sh mode change 100755 => 100644 speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x8.sh mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/demo.wav mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_test_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_train_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_val_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/waveglow/README.md mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/waveglow/config.json mode change 100755 => 100644 speech/speech_synthesis/tacotron2/pytorch/waveglow/waveglow_logo.png mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_download.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_prep.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/run.sh delete mode 120000 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/combine_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/download_from_google_drive.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/make_subset_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/parse_options.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/queue.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/run.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/slurm.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_data.sh create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_scp.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/ssh.pl create mode 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/compute_statistics.py mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/decode.py mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/normalize.py mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/preprocess.py mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/train.py mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/combine_data.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/download_from_google_drive.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/make_subset_data.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/parse_options.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/queue.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/run.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/slurm.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_data.sh mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_scp.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/ssh.pl mode change 100755 => 100644 speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/stdout.pl mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/config.json mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/tacotron2/README.md mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/tacotron2/demo.wav mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_test_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_train_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_val_filelist.txt mode change 100755 => 100644 speech/speech_synthesis/waveglow/pytorch/waveglow_logo.png diff --git a/3d-reconstruction/hashnerf/scripts/run_gui_nerf.sh b/3d-reconstruction/hashnerf/scripts/run_gui_nerf.sh old mode 100755 new mode 100644 diff --git a/3d-reconstruction/hashnerf/scripts/run_gui_nerf_clip.sh b/3d-reconstruction/hashnerf/scripts/run_gui_nerf_clip.sh old mode 100755 new mode 100644 diff --git a/3d-reconstruction/hashnerf/scripts/run_gui_tensoRF.sh b/3d-reconstruction/hashnerf/scripts/run_gui_tensoRF.sh old mode 100755 new mode 100644 diff --git a/3d-reconstruction/hashnerf/scripts/run_nerf.sh b/3d-reconstruction/hashnerf/scripts/run_nerf.sh old mode 100755 new mode 100644 diff --git a/3d-reconstruction/hashnerf/scripts/run_sdf.sh b/3d-reconstruction/hashnerf/scripts/run_sdf.sh old mode 100755 new mode 100644 diff --git a/3d-reconstruction/hashnerf/scripts/run_tensoRF.sh b/3d-reconstruction/hashnerf/scripts/run_tensoRF.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/LICENSE b/cv/3d_detection/BEVFormer/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/README.md b/cv/3d_detection/BEVFormer/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/.pre-commit-config.yaml b/cv/3d_detection/BEVFormer/pytorch/mmcv/.pre-commit-config.yaml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/.readthedocs.yml b/cv/3d_detection/BEVFormer/pytorch/mmcv/.readthedocs.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/CITATION.cff b/cv/3d_detection/BEVFormer/pytorch/mmcv/CITATION.cff old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/LICENSE b/cv/3d_detection/BEVFormer/pytorch/mmcv/LICENSE old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/build_mmcv.sh b/cv/3d_detection/BEVFormer/pytorch/mmcv/build_mmcv.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/clean_mmcv.sh b/cv/3d_detection/BEVFormer/pytorch/mmcv/clean_mmcv.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/install_mmcv.sh b/cv/3d_detection/BEVFormer/pytorch/mmcv/install_mmcv.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/quantization.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/arraymisc/quantization.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/alexnet.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/activation.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/context_block.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_module.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_ws.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/drop.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/generalized_attention.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hsigmoid.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hswish.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/non_local.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/norm.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/padding.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/plugin.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/registry.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/scale.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/swish.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/transformer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/upsample.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/wrappers.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/resnet.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/flops_counter.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/fuse_conv_bn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/sync_bn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/weight_init.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/vgg.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/dataloader.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/dataloader.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hierarchical_data_manager.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hierarchical_data_manager.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hook_wrapper.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/hook_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/model_wrapper.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/model_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/runner.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/runner.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/ipu/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/_functions.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/_functions.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/data_parallel.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/distributed.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/distributed.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/scatter_gather.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/device/mlu/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/test.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/file_client.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/base.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/json_handler.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/pickle_handler.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/yaml_handler.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/io.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/parse.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/colorspace.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/geometric.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/io.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/misc.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/photometric.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/deprecated.json b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/deprecated.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/mmcls.json b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/mmcls.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/open_mmlab.json b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/open_mmlab.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/torchvision_0.12.json b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/model_zoo/torchvision_0.12.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/info.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/info.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/symbolic_helper.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/onnx_utils/symbolic_helper.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/symbolic.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/onnx/symbolic.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/active_rotated_filter.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/active_rotated_filter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/assign_score_withk.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/assign_score_withk.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/ball_query.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/ball_query.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/bbox.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/bbox.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/border_align.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/border_align.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/box_iou_rotated.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/box_iou_rotated.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/carafe.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/carafe.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/cc_attention.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/cc_attention.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/chamfer_distance.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/chamfer_distance.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/contour_expand.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/contour_expand.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/convex_iou.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/convex_iou.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/corner_pool.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/corner_pool.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/correlation.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/correlation.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/README.md b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/box_iou_rotated_utils.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/box_iou_rotated_utils.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/active_rotated_filter_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/active_rotated_filter_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ball_query_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ball_query_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/border_align_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/border_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/box_iou_rotated_cuda.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/box_iou_rotated_cuda.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_naive_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/carafe_naive_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/chamfer_distance_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/chamfer_distance_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/convex_iou_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/convex_iou_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/correlation_cuda.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/correlation_cuda.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/diff_iou_rotated_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/diff_iou_rotated_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/furthest_point_sample_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/furthest_point_sample_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/gather_points_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/gather_points_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/group_points_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/group_points_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/iou3d_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/iou3d_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/knn_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/knn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/masked_conv2d_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/masked_conv2d_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/min_area_polygons_cuda.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/min_area_polygons_cuda.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/parrots_cudawarpfunction.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/parrots_cudawarpfunction.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_boxes_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_boxes_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_polygons_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/points_in_polygons_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/psamask_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/psamask_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/riroi_align_rotated_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/riroi_align_rotated_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_rotated_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_align_rotated_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roiaware_pool3d_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roiaware_pool3d_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roipoint_pool3d_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/roipoint_pool3d_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/rotated_feature_align_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/rotated_feature_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/scatter_points_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/scatter_points_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_interpolate_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_interpolate_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_nn_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/three_nn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/tin_shift_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/tin_shift_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/voxelization_cuda_kernel.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/cuda/voxelization_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/bbox_overlaps_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/bbox_overlaps_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/common_mlu_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/common_mlu_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/focal_loss_sigmoid_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/focal_loss_sigmoid_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/nms_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/nms_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_utils.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/psamask_utils.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_utils.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/roi_align_rotated_utils.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/tin_shift_mlu_kernel.mlu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/mlu/tin_shift_mlu_kernel.mlu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cpp_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cuda_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/parrots_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_device_registry.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_device_registry.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_mlu_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/common/pytorch_mlu_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/corner_pool.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/corner_pool.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/corner_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/corner_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/gridSample.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/gridSample.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/modulated_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/onnxruntime_register.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/onnxruntime_register.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/reduce_ops.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/reduce_ops.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/roi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/rotated_feature_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/rotated_feature_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/soft_nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/cpu/soft_nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/deform_conv.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/deform_conv.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/grid_sample.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/grid_sample.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/modulated_deform_conv.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/modulated_deform_conv.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/nms.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/nms.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_register.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_register.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_session_options_config_keys.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/onnxruntime_session_options_config_keys.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/ort_mmcv_utils.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/ort_mmcv_utils.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/reduce_ops.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/reduce_ops.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align_rotated.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/roi_align_rotated.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/rotated_feature_align.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/rotated_feature_align.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/soft_nms.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/onnxruntime/soft_nms.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/active_rotated_filter_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/assign_score_withk_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query._parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query._parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ball_query_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/bbox_overlaps_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/border_align_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/box_iou_rotated_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_naive_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/carafe_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/contour_expand_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/convex_iou_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/correlation_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/cudabind.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/cudabind.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_conv_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/deform_roi_pool_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/diff_iou_rotated_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/focal_loss_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/furthest_point_sample_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_leakyrelu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_leakyrelu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/fused_bias_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/gather_points_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/group_points_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/info.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/info.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/iou3d_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/knn_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/masked_conv2d_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/min_area_polygons_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/modulated_deform_conv_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/ms_deform_attn_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/nms_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/pixel_group_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_boxes_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/points_in_polygons_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/psamask_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/riroi_align_rotated_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_align_rotated_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roi_pool_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roiaware_pool3d_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/roipoint_pool3d_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/rotated_feature_align_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/sync_bn_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_interpolate_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/three_nn_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/tin_shift_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/upfirdn2d_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_parrots.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_parrots.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_pytorch.h b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/parrots/voxelization_pytorch.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/active_rotated_filter.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/active_rotated_filter.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/assign_score_withk.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/assign_score_withk.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ball_query.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ball_query.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/bbox_overlaps.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/bbox_overlaps.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/border_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/border_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/box_iou_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/box_iou_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe_naive.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/carafe_naive.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/chamfer_distance.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/chamfer_distance.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/contour_expand.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/contour_expand.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/convex_iou.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/convex_iou.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/correlation.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/correlation.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/active_rotated_filter.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/active_rotated_filter.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/box_iou_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/box_iou_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/modulated_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/nms_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/pixel_group.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/pixel_group.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/points_in_boxes.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/points_in_boxes.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/psamask.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/psamask.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/roi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/rotated_feature_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/rotated_feature_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/voxelization.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cpu/voxelization.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/active_rotated_filter_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/active_rotated_filter_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ball_query_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ball_query_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/border_align_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/border_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/box_iou_rotated_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/box_iou_rotated_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_naive_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/carafe_naive_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/chamfer_distance_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/chamfer_distance_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/convex_iou.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/convex_iou.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/correlation_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/correlation_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/cudabind.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/cudabind.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/diff_iou_rotated_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/diff_iou_rotated_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/furthest_point_sample_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/furthest_point_sample_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/fused_bias_leakyrelu_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/fused_bias_leakyrelu_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/gather_points_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/gather_points_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/group_points_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/group_points_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/iou3d_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/iou3d_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/knn_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/knn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/masked_conv2d_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/masked_conv2d_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/min_area_polygons.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/min_area_polygons.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_rotated_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/nms_rotated_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_boxes_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_boxes_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_polygons_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/points_in_polygons_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/psamask_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/psamask_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/riroi_align_rotated_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/riroi_align_rotated_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_rotated_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_align_rotated_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roiaware_pool3d_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roiaware_pool3d_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roipoint_pool3d_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/roipoint_pool3d_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/rotated_feature_align_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/rotated_feature_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/scatter_points_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/scatter_points_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_interpolate_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_interpolate_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_nn_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/three_nn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/tin_shift_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/tin_shift_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/upfirdn2d_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/upfirdn2d_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/voxelization_cuda.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/cuda/voxelization_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_roi_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/deform_roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/diff_iou_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/diff_iou_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/focal_loss.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/focal_loss.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/furthest_point_sample.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/furthest_point_sample.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_bias_leakyrelu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_bias_leakyrelu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_spconv_ops.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/fused_spconv_ops.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/gather_points.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/gather_points.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/group_points.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/group_points.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/info.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/iou3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/iou3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/knn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/knn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/masked_conv2d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/masked_conv2d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/min_area_polygons.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/min_area_polygons.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/bbox_overlaps_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/bbox_overlaps_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/focal_loss_sigmoid_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/focal_loss_sigmoid_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/nms_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/nms_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/psamask_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/psamask_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_rotated_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/roi_align_rotated_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/tin_shift_mlu.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/mlu/tin_shift_mlu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ms_deform_attn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/ms_deform_attn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/nms_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pixel_group.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pixel_group.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_boxes.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_boxes.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_polygons.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/points_in_polygons.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/psamask.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/psamask.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/riroi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/riroi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align_rotated.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_align_rotated.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roiaware_pool3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roiaware_pool3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roipoint_pool3d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/roipoint_pool3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/rotated_feature_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/rotated_feature_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/scatter_points.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/scatter_points.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_interpolate.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_interpolate.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_nn.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/three_nn.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/tin_shift.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/tin_shift.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/upfirdn2d.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/upfirdn2d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/voxelization.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/pytorch/voxelization.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_corner_pool_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cuda_helper.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cuda_helper.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_cummaxmin_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_deform_conv_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_grid_sampler_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_instance_norm.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_instance_norm.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_modulated_deform_conv_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_nms_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_plugin.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_plugin.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_roi_align_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd.cpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd_kernel.cu b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/plugins/trt_scatternd_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_corner_pool.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_corner_pool.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cuda_helper.cuh b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cuda_helper.cuh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cummaxmin.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_cummaxmin.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_deform_conv.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_deform_conv.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_grid_sampler.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_grid_sampler.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_instance_norm.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_instance_norm.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_modulated_deform_conv.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_modulated_deform_conv.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_nms.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_nms.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin_helper.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_plugin_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_roi_align.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_roi_align.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_scatternd.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_scatternd.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_serialize.hpp b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/csrc/tensorrt/trt_serialize.hpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_conv.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_roi_pool.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deform_roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deprecated_wrappers.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/diff_iou_rotated.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/diff_iou_rotated.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/focal_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/furthest_point_sample.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/furthest_point_sample.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/fused_bias_leakyrelu.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/fused_bias_leakyrelu.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/gather_points.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/gather_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/group_points.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/group_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/info.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/iou3d.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/iou3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/knn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/knn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/masked_conv.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/masked_conv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/merge_cells.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/merge_cells.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/min_area_polygons.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/min_area_polygons.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/modulated_deform_conv.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/modulated_deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/multi_scale_deform_attn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/multi_scale_deform_attn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/nms.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/nms.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/pixel_group.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/pixel_group.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/point_sample.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/point_sample.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_boxes.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_boxes.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_polygons.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_in_polygons.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_sampler.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/points_sampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/psa_mask.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/psa_mask.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/riroi_align_rotated.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/riroi_align_rotated.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align_rotated.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_align_rotated.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_pool.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roiaware_pool3d.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roiaware_pool3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roipoint_pool3d.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/roipoint_pool3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/rotated_feature_align.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/rotated_feature_align.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/saconv.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/saconv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/scatter_points.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/scatter_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/sync_bn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_interpolate.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_interpolate.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_nn.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/three_nn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/tin_shift.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/tin_shift.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/upfirdn2d.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/upfirdn2d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/voxelize.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/ops/voxelize.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/_functions.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/collate.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_container.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_parallel.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed_deprecated.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/registry.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/scatter_gather.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_module.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_runner.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/checkpoint.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/default_constructor.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/dist_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/epoch_based_runner.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/fp16_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/checkpoint.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/closure.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/ema.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/evaluation.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/hook.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/iter_timer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/base.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/clearml.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/clearml.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/dvclive.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/mlflow.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/neptune.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/pavi.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/segmind.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/segmind.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/tensorboard.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/text.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/wandb.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/lr_updater.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/memory.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/momentum_updater.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/optimizer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/profiler.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sampler_seed.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sync_buffer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/iter_based_runner.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/log_buffer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/default_constructor.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/priority.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/init_plugins.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/init_plugins.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/preprocess.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/preprocess.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/tensorrt_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/tensorrt/tensorrt_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/config.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/device_type.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/device_type.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/env.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/ext_loader.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/hub.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/hub.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/logging.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/misc.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_jit.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_wrapper.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/path.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/progressbar.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/registry.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/seed.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/seed.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/testing.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/timer.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/trace.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/version_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/version.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/io.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/io.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/optflow.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/optflow.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/processing.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/video/processing.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/color.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/color.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/image.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/image.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/optflow.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/mmcv/visualization/optflow.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmcv/setup.py b/cv/3d_detection/BEVFormer/pytorch/mmcv/setup.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CODE_OF_CONDUCT.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CODE_OF_CONDUCT.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CONTRIBUTING.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/CONTRIBUTING.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/config.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/config.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/error-report.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/error-report.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/feature_request.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/feature_request.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/general_questions.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/general_questions.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/reimplementation_questions.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/ISSUE_TEMPLATE/reimplementation_questions.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/pull_request_template.md b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/pull_request_template.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/build.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/build.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/deploy.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/deploy.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/lint.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/lint.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/test_mim.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/.github/workflows/test_mim.yml old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/CITATION.cff b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/CITATION.cff old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/LICENSE b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/LICENSE old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/configs b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/configs deleted file mode 120000 index 5992d109..00000000 --- a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/configs +++ /dev/null @@ -1 +0,0 @@ -../../configs \ No newline at end of file diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/model-index.yml b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/model-index.yml deleted file mode 120000 index a18c0b38..00000000 --- a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/model-index.yml +++ /dev/null @@ -1 +0,0 @@ -../../model-index.yml \ No newline at end of file diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools deleted file mode 120000 index 31941e94..00000000 --- a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools +++ /dev/null @@ -1 +0,0 @@ -../../tools \ No newline at end of file diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/analyze_logs.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/analyze_logs.py new file mode 100644 index 00000000..18858466 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/analyze_logs.py @@ -0,0 +1,202 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import json +from collections import defaultdict + +import numpy as np +import seaborn as sns +from matplotlib import pyplot as plt + + +def cal_train_time(log_dicts, args): + for i, log_dict in enumerate(log_dicts): + print(f'{"-" * 5}Analyze train time of {args.json_logs[i]}{"-" * 5}') + all_times = [] + for epoch in log_dict.keys(): + if args.include_outliers: + all_times.append(log_dict[epoch]['time']) + else: + all_times.append(log_dict[epoch]['time'][1:]) + all_times = np.array(all_times) + epoch_ave_time = all_times.mean(-1) + slowest_epoch = epoch_ave_time.argmax() + fastest_epoch = epoch_ave_time.argmin() + std_over_epoch = epoch_ave_time.std() + print(f'slowest epoch {slowest_epoch + 1}, ' + f'average time is {epoch_ave_time[slowest_epoch]:.4f}') + print(f'fastest epoch {fastest_epoch + 1}, ' + f'average time is {epoch_ave_time[fastest_epoch]:.4f}') + print(f'time std over epochs is {std_over_epoch:.4f}') + print(f'average iter time: {np.mean(all_times):.4f} s/iter') + print() + + +def plot_curve(log_dicts, args): + if args.backend is not None: + plt.switch_backend(args.backend) + sns.set_style(args.style) + # if legend is None, use {filename}_{key} as legend + legend = args.legend + if legend is None: + legend = [] + for json_log in args.json_logs: + for metric in args.keys: + legend.append(f'{json_log}_{metric}') + assert len(legend) == (len(args.json_logs) * len(args.keys)) + metrics = args.keys + + num_metrics = len(metrics) + for i, log_dict in enumerate(log_dicts): + epochs = list(log_dict.keys()) + for j, metric in enumerate(metrics): + print(f'plot curve of {args.json_logs[i]}, metric is {metric}') + if metric not in log_dict[epochs[args.interval - 1]]: + raise KeyError( + f'{args.json_logs[i]} does not contain metric {metric}') + + if args.mode == 'eval': + if min(epochs) == args.interval: + x0 = args.interval + else: + # if current training is resumed from previous checkpoint + # we lost information in early epochs + # `xs` should start according to `min(epochs)` + if min(epochs) % args.interval == 0: + x0 = min(epochs) + else: + # find the first epoch that do eval + x0 = min(epochs) + args.interval - \ + min(epochs) % args.interval + xs = np.arange(x0, max(epochs) + 1, args.interval) + ys = [] + for epoch in epochs[args.interval - 1::args.interval]: + ys += log_dict[epoch][metric] + + # if training is aborted before eval of the last epoch + # `xs` and `ys` will have different length and cause an error + # check if `ys[-1]` is empty here + if not log_dict[epoch][metric]: + xs = xs[:-1] + + ax = plt.gca() + ax.set_xticks(xs) + plt.xlabel('epoch') + plt.plot(xs, ys, label=legend[i * num_metrics + j], marker='o') + else: + xs = [] + ys = [] + num_iters_per_epoch = \ + log_dict[epochs[args.interval-1]]['iter'][-1] + for epoch in epochs[args.interval - 1::args.interval]: + iters = log_dict[epoch]['iter'] + if log_dict[epoch]['mode'][-1] == 'val': + iters = iters[:-1] + xs.append( + np.array(iters) + (epoch - 1) * num_iters_per_epoch) + ys.append(np.array(log_dict[epoch][metric][:len(iters)])) + xs = np.concatenate(xs) + ys = np.concatenate(ys) + plt.xlabel('iter') + plt.plot( + xs, ys, label=legend[i * num_metrics + j], linewidth=0.5) + plt.legend() + if args.title is not None: + plt.title(args.title) + if args.out is None: + plt.show() + else: + print(f'save curve to: {args.out}') + plt.savefig(args.out) + plt.cla() + + +def add_plot_parser(subparsers): + parser_plt = subparsers.add_parser( + 'plot_curve', help='parser for plotting curves') + parser_plt.add_argument( + 'json_logs', + type=str, + nargs='+', + help='path of train log in json format') + parser_plt.add_argument( + '--keys', + type=str, + nargs='+', + default=['mAP_0.25'], + help='the metric that you want to plot') + parser_plt.add_argument('--title', type=str, help='title of figure') + parser_plt.add_argument( + '--legend', + type=str, + nargs='+', + default=None, + help='legend of each plot') + parser_plt.add_argument( + '--backend', type=str, default=None, help='backend of plt') + parser_plt.add_argument( + '--style', type=str, default='dark', help='style of plt') + parser_plt.add_argument('--out', type=str, default=None) + parser_plt.add_argument('--mode', type=str, default='train') + parser_plt.add_argument('--interval', type=int, default=1) + + +def add_time_parser(subparsers): + parser_time = subparsers.add_parser( + 'cal_train_time', + help='parser for computing the average time per training iteration') + parser_time.add_argument( + 'json_logs', + type=str, + nargs='+', + help='path of train log in json format') + parser_time.add_argument( + '--include-outliers', + action='store_true', + help='include the first value of every epoch when computing ' + 'the average time') + + +def parse_args(): + parser = argparse.ArgumentParser(description='Analyze Json Log') + # currently only support plot curve and calculate average train time + subparsers = parser.add_subparsers(dest='task', help='task parser') + add_plot_parser(subparsers) + add_time_parser(subparsers) + args = parser.parse_args() + return args + + +def load_json_logs(json_logs): + # load and convert json_logs to log_dict, key is epoch, value is a sub dict + # keys of sub dict is different metrics, e.g. memory, bbox_mAP + # value of sub dict is a list of corresponding values of all iterations + log_dicts = [dict() for _ in json_logs] + for json_log, log_dict in zip(json_logs, log_dicts): + with open(json_log, 'r') as log_file: + for line in log_file: + log = json.loads(line.strip()) + # skip lines without `epoch` field + if 'epoch' not in log: + continue + epoch = log.pop('epoch') + if epoch not in log_dict: + log_dict[epoch] = defaultdict(list) + for k, v in log.items(): + log_dict[epoch][k].append(v) + return log_dicts + + +def main(): + args = parse_args() + + json_logs = args.json_logs + for json_log in json_logs: + assert json_log.endswith('.json') + + log_dicts = load_json_logs(json_logs) + + eval(args.task)(log_dicts, args) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/benchmark.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/benchmark.py new file mode 100644 index 00000000..b31c9f09 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/benchmark.py @@ -0,0 +1,96 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import time + +import torch +from mmcv import Config +from mmcv.parallel import MMDataParallel +from mmcv.runner import load_checkpoint, wrap_fp16_model + +from mmdet3d.datasets import build_dataloader, build_dataset +from mmdet3d.models import build_detector +from tools.misc.fuse_conv_bn import fuse_module + + +def parse_args(): + parser = argparse.ArgumentParser(description='MMDet benchmark a model') + parser.add_argument('config', help='test config file path') + parser.add_argument('checkpoint', help='checkpoint file') + parser.add_argument('--samples', default=2000, help='samples to benchmark') + parser.add_argument( + '--log-interval', default=50, help='interval of logging') + parser.add_argument( + '--fuse-conv-bn', + action='store_true', + help='Whether to fuse conv and bn, this will slightly increase' + 'the inference speed') + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + + cfg = Config.fromfile(args.config) + # set cudnn_benchmark + if cfg.get('cudnn_benchmark', False): + torch.backends.cudnn.benchmark = True + cfg.model.pretrained = None + cfg.data.test.test_mode = True + + # build the dataloader + # TODO: support multiple images per gpu (only minor changes are needed) + dataset = build_dataset(cfg.data.test) + data_loader = build_dataloader( + dataset, + samples_per_gpu=1, + workers_per_gpu=cfg.data.workers_per_gpu, + dist=False, + shuffle=False) + + # build the model and load checkpoint + cfg.model.train_cfg = None + model = build_detector(cfg.model, test_cfg=cfg.get('test_cfg')) + fp16_cfg = cfg.get('fp16', None) + if fp16_cfg is not None: + wrap_fp16_model(model) + load_checkpoint(model, args.checkpoint, map_location='cpu') + if args.fuse_conv_bn: + model = fuse_module(model) + + model = MMDataParallel(model, device_ids=[0]) + + model.eval() + + # the first several iterations may be very slow so skip them + num_warmup = 5 + pure_inf_time = 0 + + # benchmark with several samples and take the average + for i, data in enumerate(data_loader): + + torch.cuda.synchronize() + start_time = time.perf_counter() + + with torch.no_grad(): + model(return_loss=False, rescale=True, **data) + + torch.cuda.synchronize() + elapsed = time.perf_counter() - start_time + + if i >= num_warmup: + pure_inf_time += elapsed + if (i + 1) % args.log_interval == 0: + fps = (i + 1 - num_warmup) / pure_inf_time + print(f'Done image [{i + 1:<3}/ {args.samples}], ' + f'fps: {fps:.1f} img / s') + + if (i + 1) == args.samples: + pure_inf_time += elapsed + fps = (i + 1 - num_warmup) / pure_inf_time + print(f'Overall fps: {fps:.1f} img / s') + break + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/get_flops.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/get_flops.py new file mode 100644 index 00000000..f45ed80f --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/analysis_tools/get_flops.py @@ -0,0 +1,92 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse + +import torch +from mmcv import Config, DictAction + +from mmdet3d.models import build_model + +try: + from mmcv.cnn import get_model_complexity_info +except ImportError: + raise ImportError('Please upgrade mmcv to >0.6.2') + + +def parse_args(): + parser = argparse.ArgumentParser(description='Train a detector') + parser.add_argument('config', help='train config file path') + parser.add_argument( + '--shape', + type=int, + nargs='+', + default=[40000, 4], + help='input point cloud size') + parser.add_argument( + '--modality', + type=str, + default='point', + choices=['point', 'image', 'multi'], + help='input data modality') + parser.add_argument( + '--cfg-options', + nargs='+', + action=DictAction, + help='override some settings in the used config, the key-value pair ' + 'in xxx=yyy format will be merged into config file. If the value to ' + 'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' + 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' + 'Note that the quotation marks are necessary and that no white space ' + 'is allowed.') + args = parser.parse_args() + return args + + +def main(): + + args = parse_args() + + if args.modality == 'point': + assert len(args.shape) == 2, 'invalid input shape' + input_shape = tuple(args.shape) + elif args.modality == 'image': + if len(args.shape) == 1: + input_shape = (3, args.shape[0], args.shape[0]) + elif len(args.shape) == 2: + input_shape = (3, ) + tuple(args.shape) + else: + raise ValueError('invalid input shape') + elif args.modality == 'multi': + raise NotImplementedError( + 'FLOPs counter is currently not supported for models with ' + 'multi-modality input') + + cfg = Config.fromfile(args.config) + if args.cfg_options is not None: + cfg.merge_from_dict(args.cfg_options) + + model = build_model( + cfg.model, + train_cfg=cfg.get('train_cfg'), + test_cfg=cfg.get('test_cfg')) + if torch.cuda.is_available(): + model.cuda() + model.eval() + + if hasattr(model, 'forward_dummy'): + model.forward = model.forward_dummy + else: + raise NotImplementedError( + 'FLOPs counter is currently not supported for {}'.format( + model.__class__.__name__)) + + flops, params = get_model_complexity_info(model, input_shape) + split_line = '=' * 30 + print(f'{split_line}\nInput shape: {input_shape}\n' + f'Flops: {flops}\nParams: {params}\n{split_line}') + print('!!!Please be cautious if you use the results in papers. ' + 'You may need to check if all ops are supported and verify that the ' + 'flops computation is correct.') + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.py new file mode 100644 index 00000000..32337d1a --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.py @@ -0,0 +1,313 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +from os import path as osp + +from tools.data_converter import indoor_converter as indoor +from tools.data_converter import kitti_converter as kitti +from tools.data_converter import lyft_converter as lyft_converter +from tools.data_converter import nuscenes_converter as nuscenes_converter +from tools.data_converter.create_gt_database import ( + GTDatabaseCreater, create_groundtruth_database) + + +def kitti_data_prep(root_path, + info_prefix, + version, + out_dir, + with_plane=False): + """Prepare data related to Kitti dataset. + + Related data consists of '.pkl' files recording basic infos, + 2D annotations and groundtruth database. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + version (str): Dataset version. + out_dir (str): Output directory of the groundtruth database info. + with_plane (bool, optional): Whether to use plane information. + Default: False. + """ + kitti.create_kitti_info_file(root_path, info_prefix, with_plane) + kitti.create_reduced_point_cloud(root_path, info_prefix) + + info_train_path = osp.join(root_path, f'{info_prefix}_infos_train.pkl') + info_val_path = osp.join(root_path, f'{info_prefix}_infos_val.pkl') + info_trainval_path = osp.join(root_path, + f'{info_prefix}_infos_trainval.pkl') + info_test_path = osp.join(root_path, f'{info_prefix}_infos_test.pkl') + kitti.export_2d_annotation(root_path, info_train_path) + kitti.export_2d_annotation(root_path, info_val_path) + kitti.export_2d_annotation(root_path, info_trainval_path) + kitti.export_2d_annotation(root_path, info_test_path) + + create_groundtruth_database( + 'KittiDataset', + root_path, + info_prefix, + f'{out_dir}/{info_prefix}_infos_train.pkl', + relative_path=False, + mask_anno_path='instances_train.json', + with_mask=(version == 'mask')) + + +def nuscenes_data_prep(root_path, + info_prefix, + version, + dataset_name, + out_dir, + max_sweeps=10): + """Prepare data related to nuScenes dataset. + + Related data consists of '.pkl' files recording basic infos, + 2D annotations and groundtruth database. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + version (str): Dataset version. + dataset_name (str): The dataset class name. + out_dir (str): Output directory of the groundtruth database info. + max_sweeps (int, optional): Number of input consecutive frames. + Default: 10 + """ + nuscenes_converter.create_nuscenes_infos( + root_path, info_prefix, version=version, max_sweeps=max_sweeps) + + if version == 'v1.0-test': + info_test_path = osp.join(root_path, f'{info_prefix}_infos_test.pkl') + nuscenes_converter.export_2d_annotation( + root_path, info_test_path, version=version) + return + + info_train_path = osp.join(root_path, f'{info_prefix}_infos_train.pkl') + info_val_path = osp.join(root_path, f'{info_prefix}_infos_val.pkl') + nuscenes_converter.export_2d_annotation( + root_path, info_train_path, version=version) + nuscenes_converter.export_2d_annotation( + root_path, info_val_path, version=version) + create_groundtruth_database(dataset_name, root_path, info_prefix, + f'{out_dir}/{info_prefix}_infos_train.pkl') + + +def lyft_data_prep(root_path, info_prefix, version, max_sweeps=10): + """Prepare data related to Lyft dataset. + + Related data consists of '.pkl' files recording basic infos. + Although the ground truth database and 2D annotations are not used in + Lyft, it can also be generated like nuScenes. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + version (str): Dataset version. + max_sweeps (int, optional): Number of input consecutive frames. + Defaults to 10. + """ + lyft_converter.create_lyft_infos( + root_path, info_prefix, version=version, max_sweeps=max_sweeps) + + +def scannet_data_prep(root_path, info_prefix, out_dir, workers): + """Prepare the info file for scannet dataset. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + out_dir (str): Output directory of the generated info file. + workers (int): Number of threads to be used. + """ + indoor.create_indoor_info_file( + root_path, info_prefix, out_dir, workers=workers) + + +def s3dis_data_prep(root_path, info_prefix, out_dir, workers): + """Prepare the info file for s3dis dataset. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + out_dir (str): Output directory of the generated info file. + workers (int): Number of threads to be used. + """ + indoor.create_indoor_info_file( + root_path, info_prefix, out_dir, workers=workers) + + +def sunrgbd_data_prep(root_path, info_prefix, out_dir, workers, num_points): + """Prepare the info file for sunrgbd dataset. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + out_dir (str): Output directory of the generated info file. + workers (int): Number of threads to be used. + """ + indoor.create_indoor_info_file( + root_path, + info_prefix, + out_dir, + workers=workers, + num_points=num_points) + + +def waymo_data_prep(root_path, + info_prefix, + version, + out_dir, + workers, + max_sweeps=5): + """Prepare the info file for waymo dataset. + + Args: + root_path (str): Path of dataset root. + info_prefix (str): The prefix of info filenames. + out_dir (str): Output directory of the generated info file. + workers (int): Number of threads to be used. + max_sweeps (int, optional): Number of input consecutive frames. + Default: 5. Here we store pose information of these frames + for later use. + """ + from tools.data_converter import waymo_converter as waymo + + splits = ['training', 'validation', 'testing'] + for i, split in enumerate(splits): + load_dir = osp.join(root_path, 'waymo_format', split) + if split == 'validation': + save_dir = osp.join(out_dir, 'kitti_format', 'training') + else: + save_dir = osp.join(out_dir, 'kitti_format', split) + converter = waymo.Waymo2KITTI( + load_dir, + save_dir, + prefix=str(i), + workers=workers, + test_mode=(split == 'testing')) + converter.convert() + # Generate waymo infos + out_dir = osp.join(out_dir, 'kitti_format') + kitti.create_waymo_info_file( + out_dir, info_prefix, max_sweeps=max_sweeps, workers=workers) + GTDatabaseCreater( + 'WaymoDataset', + out_dir, + info_prefix, + f'{out_dir}/{info_prefix}_infos_train.pkl', + relative_path=False, + with_mask=False, + num_worker=workers).create() + + +parser = argparse.ArgumentParser(description='Data converter arg parser') +parser.add_argument('dataset', metavar='kitti', help='name of the dataset') +parser.add_argument( + '--root-path', + type=str, + default='./data/kitti', + help='specify the root path of dataset') +parser.add_argument( + '--version', + type=str, + default='v1.0', + required=False, + help='specify the dataset version, no need for kitti') +parser.add_argument( + '--max-sweeps', + type=int, + default=10, + required=False, + help='specify sweeps of lidar per example') +parser.add_argument( + '--with-plane', + action='store_true', + help='Whether to use plane information for kitti.') +parser.add_argument( + '--num-points', + type=int, + default=-1, + help='Number of points to sample for indoor datasets.') +parser.add_argument( + '--out-dir', + type=str, + default='./data/kitti', + required=False, + help='name of info pkl') +parser.add_argument('--extra-tag', type=str, default='kitti') +parser.add_argument( + '--workers', type=int, default=4, help='number of threads to be used') +args = parser.parse_args() + +if __name__ == '__main__': + if args.dataset == 'kitti': + kitti_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=args.version, + out_dir=args.out_dir, + with_plane=args.with_plane) + elif args.dataset == 'nuscenes' and args.version != 'v1.0-mini': + train_version = f'{args.version}-trainval' + nuscenes_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=train_version, + dataset_name='NuScenesDataset', + out_dir=args.out_dir, + max_sweeps=args.max_sweeps) + test_version = f'{args.version}-test' + nuscenes_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=test_version, + dataset_name='NuScenesDataset', + out_dir=args.out_dir, + max_sweeps=args.max_sweeps) + elif args.dataset == 'nuscenes' and args.version == 'v1.0-mini': + train_version = f'{args.version}' + nuscenes_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=train_version, + dataset_name='NuScenesDataset', + out_dir=args.out_dir, + max_sweeps=args.max_sweeps) + elif args.dataset == 'lyft': + train_version = f'{args.version}-train' + lyft_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=train_version, + max_sweeps=args.max_sweeps) + test_version = f'{args.version}-test' + lyft_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=test_version, + max_sweeps=args.max_sweeps) + elif args.dataset == 'waymo': + waymo_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + version=args.version, + out_dir=args.out_dir, + workers=args.workers, + max_sweeps=args.max_sweeps) + elif args.dataset == 'scannet': + scannet_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + out_dir=args.out_dir, + workers=args.workers) + elif args.dataset == 's3dis': + s3dis_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + out_dir=args.out_dir, + workers=args.workers) + elif args.dataset == 'sunrgbd': + sunrgbd_data_prep( + root_path=args.root_path, + info_prefix=args.extra_tag, + num_points=args.num_points, + out_dir=args.out_dir, + workers=args.workers) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.sh new file mode 100644 index 00000000..9a57852f --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/create_data.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -x +export PYTHONPATH=`pwd`:$PYTHONPATH + +PARTITION=$1 +JOB_NAME=$2 +DATASET=$3 +GPUS=${GPUS:-1} +GPUS_PER_NODE=${GPUS_PER_NODE:-1} +SRUN_ARGS=${SRUN_ARGS:-""} +JOB_NAME=create_data + +srun -p ${PARTITION} \ + --job-name=${JOB_NAME} \ + --gres=gpu:${GPUS_PER_NODE} \ + --ntasks=${GPUS} \ + --ntasks-per-node=${GPUS_PER_NODE} \ + --kill-on-bad-exit=1 \ + ${SRUN_ARGS} \ + python -u tools/create_data.py ${DATASET} \ + --root-path ./data/${DATASET} \ + --out-dir ./data/${DATASET} \ + --extra-tag ${DATASET} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/__init__.py new file mode 100644 index 00000000..ef101fec --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/__init__.py @@ -0,0 +1 @@ +# Copyright (c) OpenMMLab. All rights reserved. diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/create_gt_database.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/create_gt_database.py new file mode 100644 index 00000000..210f0e88 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/create_gt_database.py @@ -0,0 +1,624 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import pickle +from os import path as osp + +import mmcv +import numpy as np +from mmcv import track_iter_progress +from mmcv.ops import roi_align +from pycocotools import mask as maskUtils +from pycocotools.coco import COCO + +from mmdet3d.core.bbox import box_np_ops as box_np_ops +from mmdet3d.datasets import build_dataset +from mmdet.core.evaluation.bbox_overlaps import bbox_overlaps + + +def _poly2mask(mask_ann, img_h, img_w): + if isinstance(mask_ann, list): + # polygon -- a single object might consist of multiple parts + # we merge all parts into one mask rle code + rles = maskUtils.frPyObjects(mask_ann, img_h, img_w) + rle = maskUtils.merge(rles) + elif isinstance(mask_ann['counts'], list): + # uncompressed RLE + rle = maskUtils.frPyObjects(mask_ann, img_h, img_w) + else: + # rle + rle = mask_ann + mask = maskUtils.decode(rle) + return mask + + +def _parse_coco_ann_info(ann_info): + gt_bboxes = [] + gt_labels = [] + gt_bboxes_ignore = [] + gt_masks_ann = [] + + for i, ann in enumerate(ann_info): + if ann.get('ignore', False): + continue + x1, y1, w, h = ann['bbox'] + if ann['area'] <= 0: + continue + bbox = [x1, y1, x1 + w, y1 + h] + if ann.get('iscrowd', False): + gt_bboxes_ignore.append(bbox) + else: + gt_bboxes.append(bbox) + gt_masks_ann.append(ann['segmentation']) + + if gt_bboxes: + gt_bboxes = np.array(gt_bboxes, dtype=np.float32) + gt_labels = np.array(gt_labels, dtype=np.int64) + else: + gt_bboxes = np.zeros((0, 4), dtype=np.float32) + gt_labels = np.array([], dtype=np.int64) + + if gt_bboxes_ignore: + gt_bboxes_ignore = np.array(gt_bboxes_ignore, dtype=np.float32) + else: + gt_bboxes_ignore = np.zeros((0, 4), dtype=np.float32) + + ann = dict( + bboxes=gt_bboxes, bboxes_ignore=gt_bboxes_ignore, masks=gt_masks_ann) + + return ann + + +def crop_image_patch_v2(pos_proposals, pos_assigned_gt_inds, gt_masks): + import torch + from torch.nn.modules.utils import _pair + device = pos_proposals.device + num_pos = pos_proposals.size(0) + fake_inds = ( + torch.arange(num_pos, + device=device).to(dtype=pos_proposals.dtype)[:, None]) + rois = torch.cat([fake_inds, pos_proposals], dim=1) # Nx5 + mask_size = _pair(28) + rois = rois.to(device=device) + gt_masks_th = ( + torch.from_numpy(gt_masks).to(device).index_select( + 0, pos_assigned_gt_inds).to(dtype=rois.dtype)) + # Use RoIAlign could apparently accelerate the training (~0.1s/iter) + targets = ( + roi_align(gt_masks_th, rois, mask_size[::-1], 1.0, 0, True).squeeze(1)) + return targets + + +def crop_image_patch(pos_proposals, gt_masks, pos_assigned_gt_inds, org_img): + num_pos = pos_proposals.shape[0] + masks = [] + img_patches = [] + for i in range(num_pos): + gt_mask = gt_masks[pos_assigned_gt_inds[i]] + bbox = pos_proposals[i, :].astype(np.int32) + x1, y1, x2, y2 = bbox + w = np.maximum(x2 - x1 + 1, 1) + h = np.maximum(y2 - y1 + 1, 1) + + mask_patch = gt_mask[y1:y1 + h, x1:x1 + w] + masked_img = gt_mask[..., None] * org_img + img_patch = masked_img[y1:y1 + h, x1:x1 + w] + + img_patches.append(img_patch) + masks.append(mask_patch) + return img_patches, masks + + +def create_groundtruth_database(dataset_class_name, + data_path, + info_prefix, + info_path=None, + mask_anno_path=None, + used_classes=None, + database_save_path=None, + db_info_save_path=None, + relative_path=True, + add_rgb=False, + lidar_only=False, + bev_only=False, + coors_range=None, + with_mask=False): + """Given the raw data, generate the ground truth database. + + Args: + dataset_class_name (str): Name of the input dataset. + data_path (str): Path of the data. + info_prefix (str): Prefix of the info file. + info_path (str, optional): Path of the info file. + Default: None. + mask_anno_path (str, optional): Path of the mask_anno. + Default: None. + used_classes (list[str], optional): Classes have been used. + Default: None. + database_save_path (str, optional): Path to save database. + Default: None. + db_info_save_path (str, optional): Path to save db_info. + Default: None. + relative_path (bool, optional): Whether to use relative path. + Default: True. + with_mask (bool, optional): Whether to use mask. + Default: False. + """ + print(f'Create GT Database of {dataset_class_name}') + dataset_cfg = dict( + type=dataset_class_name, data_root=data_path, ann_file=info_path) + if dataset_class_name == 'KittiDataset': + file_client_args = dict(backend='disk') + dataset_cfg.update( + test_mode=False, + split='training', + modality=dict( + use_lidar=True, + use_depth=False, + use_lidar_intensity=True, + use_camera=with_mask, + ), + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=4, + use_dim=4, + file_client_args=file_client_args), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True, + file_client_args=file_client_args) + ]) + + elif dataset_class_name == 'NuScenesDataset': + dataset_cfg.update( + use_valid_flag=True, + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=5, + use_dim=5), + dict( + type='LoadPointsFromMultiSweeps', + sweeps_num=10, + use_dim=[0, 1, 2, 3, 4], + pad_empty_sweeps=True, + remove_close=True), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True) + ]) + + elif dataset_class_name == 'WaymoDataset': + file_client_args = dict(backend='disk') + dataset_cfg.update( + test_mode=False, + split='training', + modality=dict( + use_lidar=True, + use_depth=False, + use_lidar_intensity=True, + use_camera=False, + ), + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=6, + use_dim=6, + file_client_args=file_client_args), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True, + file_client_args=file_client_args) + ]) + + dataset = build_dataset(dataset_cfg) + + if database_save_path is None: + database_save_path = osp.join(data_path, f'{info_prefix}_gt_database') + if db_info_save_path is None: + db_info_save_path = osp.join(data_path, + f'{info_prefix}_dbinfos_train.pkl') + mmcv.mkdir_or_exist(database_save_path) + all_db_infos = dict() + if with_mask: + coco = COCO(osp.join(data_path, mask_anno_path)) + imgIds = coco.getImgIds() + file2id = dict() + for i in imgIds: + info = coco.loadImgs([i])[0] + file2id.update({info['file_name']: i}) + + group_counter = 0 + for j in track_iter_progress(list(range(len(dataset)))): + input_dict = dataset.get_data_info(j) + dataset.pre_pipeline(input_dict) + example = dataset.pipeline(input_dict) + annos = example['ann_info'] + image_idx = example['sample_idx'] + points = example['points'].tensor.numpy() + gt_boxes_3d = annos['gt_bboxes_3d'].tensor.numpy() + names = annos['gt_names'] + group_dict = dict() + if 'group_ids' in annos: + group_ids = annos['group_ids'] + else: + group_ids = np.arange(gt_boxes_3d.shape[0], dtype=np.int64) + difficulty = np.zeros(gt_boxes_3d.shape[0], dtype=np.int32) + if 'difficulty' in annos: + difficulty = annos['difficulty'] + + num_obj = gt_boxes_3d.shape[0] + point_indices = box_np_ops.points_in_rbbox(points, gt_boxes_3d) + + if with_mask: + # prepare masks + gt_boxes = annos['gt_bboxes'] + img_path = osp.split(example['img_info']['filename'])[-1] + if img_path not in file2id.keys(): + print(f'skip image {img_path} for empty mask') + continue + img_id = file2id[img_path] + kins_annIds = coco.getAnnIds(imgIds=img_id) + kins_raw_info = coco.loadAnns(kins_annIds) + kins_ann_info = _parse_coco_ann_info(kins_raw_info) + h, w = annos['img_shape'][:2] + gt_masks = [ + _poly2mask(mask, h, w) for mask in kins_ann_info['masks'] + ] + # get mask inds based on iou mapping + bbox_iou = bbox_overlaps(kins_ann_info['bboxes'], gt_boxes) + mask_inds = bbox_iou.argmax(axis=0) + valid_inds = (bbox_iou.max(axis=0) > 0.5) + + # mask the image + # use more precise crop when it is ready + # object_img_patches = np.ascontiguousarray( + # np.stack(object_img_patches, axis=0).transpose(0, 3, 1, 2)) + # crop image patches using roi_align + # object_img_patches = crop_image_patch_v2( + # torch.Tensor(gt_boxes), + # torch.Tensor(mask_inds).long(), object_img_patches) + object_img_patches, object_masks = crop_image_patch( + gt_boxes, gt_masks, mask_inds, annos['img']) + + for i in range(num_obj): + filename = f'{image_idx}_{names[i]}_{i}.bin' + abs_filepath = osp.join(database_save_path, filename) + rel_filepath = osp.join(f'{info_prefix}_gt_database', filename) + + # save point clouds and image patches for each object + gt_points = points[point_indices[:, i]] + gt_points[:, :3] -= gt_boxes_3d[i, :3] + + if with_mask: + if object_masks[i].sum() == 0 or not valid_inds[i]: + # Skip object for empty or invalid mask + continue + img_patch_path = abs_filepath + '.png' + mask_patch_path = abs_filepath + '.mask.png' + mmcv.imwrite(object_img_patches[i], img_patch_path) + mmcv.imwrite(object_masks[i], mask_patch_path) + + with open(abs_filepath, 'w') as f: + gt_points.tofile(f) + + if (used_classes is None) or names[i] in used_classes: + db_info = { + 'name': names[i], + 'path': rel_filepath, + 'image_idx': image_idx, + 'gt_idx': i, + 'box3d_lidar': gt_boxes_3d[i], + 'num_points_in_gt': gt_points.shape[0], + 'difficulty': difficulty[i], + } + local_group_id = group_ids[i] + # if local_group_id >= 0: + if local_group_id not in group_dict: + group_dict[local_group_id] = group_counter + group_counter += 1 + db_info['group_id'] = group_dict[local_group_id] + if 'score' in annos: + db_info['score'] = annos['score'][i] + if with_mask: + db_info.update({'box2d_camera': gt_boxes[i]}) + if names[i] in all_db_infos: + all_db_infos[names[i]].append(db_info) + else: + all_db_infos[names[i]] = [db_info] + + for k, v in all_db_infos.items(): + print(f'load {len(v)} {k} database infos') + + with open(db_info_save_path, 'wb') as f: + pickle.dump(all_db_infos, f) + + +class GTDatabaseCreater: + """Given the raw data, generate the ground truth database. This is the + parallel version. For serialized version, please refer to + `create_groundtruth_database` + + Args: + dataset_class_name (str): Name of the input dataset. + data_path (str): Path of the data. + info_prefix (str): Prefix of the info file. + info_path (str, optional): Path of the info file. + Default: None. + mask_anno_path (str, optional): Path of the mask_anno. + Default: None. + used_classes (list[str], optional): Classes have been used. + Default: None. + database_save_path (str, optional): Path to save database. + Default: None. + db_info_save_path (str, optional): Path to save db_info. + Default: None. + relative_path (bool, optional): Whether to use relative path. + Default: True. + with_mask (bool, optional): Whether to use mask. + Default: False. + num_worker (int, optional): the number of parallel workers to use. + Default: 8. + """ + + def __init__(self, + dataset_class_name, + data_path, + info_prefix, + info_path=None, + mask_anno_path=None, + used_classes=None, + database_save_path=None, + db_info_save_path=None, + relative_path=True, + add_rgb=False, + lidar_only=False, + bev_only=False, + coors_range=None, + with_mask=False, + num_worker=8) -> None: + self.dataset_class_name = dataset_class_name + self.data_path = data_path + self.info_prefix = info_prefix + self.info_path = info_path + self.mask_anno_path = mask_anno_path + self.used_classes = used_classes + self.database_save_path = database_save_path + self.db_info_save_path = db_info_save_path + self.relative_path = relative_path + self.add_rgb = add_rgb + self.lidar_only = lidar_only + self.bev_only = bev_only + self.coors_range = coors_range + self.with_mask = with_mask + self.num_worker = num_worker + self.pipeline = None + + def create_single(self, input_dict): + group_counter = 0 + single_db_infos = dict() + example = self.pipeline(input_dict) + annos = example['ann_info'] + image_idx = example['sample_idx'] + points = example['points'].tensor.numpy() + gt_boxes_3d = annos['gt_bboxes_3d'].tensor.numpy() + names = annos['gt_names'] + group_dict = dict() + if 'group_ids' in annos: + group_ids = annos['group_ids'] + else: + group_ids = np.arange(gt_boxes_3d.shape[0], dtype=np.int64) + difficulty = np.zeros(gt_boxes_3d.shape[0], dtype=np.int32) + if 'difficulty' in annos: + difficulty = annos['difficulty'] + + num_obj = gt_boxes_3d.shape[0] + point_indices = box_np_ops.points_in_rbbox(points, gt_boxes_3d) + + if self.with_mask: + # prepare masks + gt_boxes = annos['gt_bboxes'] + img_path = osp.split(example['img_info']['filename'])[-1] + if img_path not in self.file2id.keys(): + print(f'skip image {img_path} for empty mask') + return single_db_infos + img_id = self.file2id[img_path] + kins_annIds = self.coco.getAnnIds(imgIds=img_id) + kins_raw_info = self.coco.loadAnns(kins_annIds) + kins_ann_info = _parse_coco_ann_info(kins_raw_info) + h, w = annos['img_shape'][:2] + gt_masks = [ + _poly2mask(mask, h, w) for mask in kins_ann_info['masks'] + ] + # get mask inds based on iou mapping + bbox_iou = bbox_overlaps(kins_ann_info['bboxes'], gt_boxes) + mask_inds = bbox_iou.argmax(axis=0) + valid_inds = (bbox_iou.max(axis=0) > 0.5) + + # mask the image + # use more precise crop when it is ready + # object_img_patches = np.ascontiguousarray( + # np.stack(object_img_patches, axis=0).transpose(0, 3, 1, 2)) + # crop image patches using roi_align + # object_img_patches = crop_image_patch_v2( + # torch.Tensor(gt_boxes), + # torch.Tensor(mask_inds).long(), object_img_patches) + object_img_patches, object_masks = crop_image_patch( + gt_boxes, gt_masks, mask_inds, annos['img']) + + for i in range(num_obj): + filename = f'{image_idx}_{names[i]}_{i}.bin' + abs_filepath = osp.join(self.database_save_path, filename) + rel_filepath = osp.join(f'{self.info_prefix}_gt_database', + filename) + + # save point clouds and image patches for each object + gt_points = points[point_indices[:, i]] + gt_points[:, :3] -= gt_boxes_3d[i, :3] + + if self.with_mask: + if object_masks[i].sum() == 0 or not valid_inds[i]: + # Skip object for empty or invalid mask + continue + img_patch_path = abs_filepath + '.png' + mask_patch_path = abs_filepath + '.mask.png' + mmcv.imwrite(object_img_patches[i], img_patch_path) + mmcv.imwrite(object_masks[i], mask_patch_path) + + with open(abs_filepath, 'w') as f: + gt_points.tofile(f) + + if (self.used_classes is None) or names[i] in self.used_classes: + db_info = { + 'name': names[i], + 'path': rel_filepath, + 'image_idx': image_idx, + 'gt_idx': i, + 'box3d_lidar': gt_boxes_3d[i], + 'num_points_in_gt': gt_points.shape[0], + 'difficulty': difficulty[i], + } + local_group_id = group_ids[i] + # if local_group_id >= 0: + if local_group_id not in group_dict: + group_dict[local_group_id] = group_counter + group_counter += 1 + db_info['group_id'] = group_dict[local_group_id] + if 'score' in annos: + db_info['score'] = annos['score'][i] + if self.with_mask: + db_info.update({'box2d_camera': gt_boxes[i]}) + if names[i] in single_db_infos: + single_db_infos[names[i]].append(db_info) + else: + single_db_infos[names[i]] = [db_info] + + return single_db_infos + + def create(self): + print(f'Create GT Database of {self.dataset_class_name}') + dataset_cfg = dict( + type=self.dataset_class_name, + data_root=self.data_path, + ann_file=self.info_path) + if self.dataset_class_name == 'KittiDataset': + file_client_args = dict(backend='disk') + dataset_cfg.update( + test_mode=False, + split='training', + modality=dict( + use_lidar=True, + use_depth=False, + use_lidar_intensity=True, + use_camera=self.with_mask, + ), + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=4, + use_dim=4, + file_client_args=file_client_args), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True, + file_client_args=file_client_args) + ]) + + elif self.dataset_class_name == 'NuScenesDataset': + dataset_cfg.update( + use_valid_flag=True, + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=5, + use_dim=5), + dict( + type='LoadPointsFromMultiSweeps', + sweeps_num=10, + use_dim=[0, 1, 2, 3, 4], + pad_empty_sweeps=True, + remove_close=True), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True) + ]) + + elif self.dataset_class_name == 'WaymoDataset': + file_client_args = dict(backend='disk') + dataset_cfg.update( + test_mode=False, + split='training', + modality=dict( + use_lidar=True, + use_depth=False, + use_lidar_intensity=True, + use_camera=False, + ), + pipeline=[ + dict( + type='LoadPointsFromFile', + coord_type='LIDAR', + load_dim=6, + use_dim=6, + file_client_args=file_client_args), + dict( + type='LoadAnnotations3D', + with_bbox_3d=True, + with_label_3d=True, + file_client_args=file_client_args) + ]) + + dataset = build_dataset(dataset_cfg) + self.pipeline = dataset.pipeline + if self.database_save_path is None: + self.database_save_path = osp.join( + self.data_path, f'{self.info_prefix}_gt_database') + if self.db_info_save_path is None: + self.db_info_save_path = osp.join( + self.data_path, f'{self.info_prefix}_dbinfos_train.pkl') + mmcv.mkdir_or_exist(self.database_save_path) + if self.with_mask: + self.coco = COCO(osp.join(self.data_path, self.mask_anno_path)) + imgIds = self.coco.getImgIds() + self.file2id = dict() + for i in imgIds: + info = self.coco.loadImgs([i])[0] + self.file2id.update({info['file_name']: i}) + + def loop_dataset(i): + input_dict = dataset.get_data_info(i) + dataset.pre_pipeline(input_dict) + return input_dict + + multi_db_infos = mmcv.track_parallel_progress( + self.create_single, ((loop_dataset(i) + for i in range(len(dataset))), len(dataset)), + self.num_worker) + print('Make global unique group id') + group_counter_offset = 0 + all_db_infos = dict() + for single_db_infos in track_iter_progress(multi_db_infos): + group_id = -1 + for name, name_db_infos in single_db_infos.items(): + for db_info in name_db_infos: + group_id = max(group_id, db_info['group_id']) + db_info['group_id'] += group_counter_offset + if name not in all_db_infos: + all_db_infos[name] = [] + all_db_infos[name].extend(name_db_infos) + group_counter_offset += (group_id + 1) + + for k, v in all_db_infos.items(): + print(f'load {len(v)} {k} database infos') + + with open(self.db_info_save_path, 'wb') as f: + pickle.dump(all_db_infos, f) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/indoor_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/indoor_converter.py new file mode 100644 index 00000000..ee6c0387 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/indoor_converter.py @@ -0,0 +1,121 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import os + +import mmcv +import numpy as np + +from tools.data_converter.s3dis_data_utils import S3DISData, S3DISSegData +from tools.data_converter.scannet_data_utils import ScanNetData, ScanNetSegData +from tools.data_converter.sunrgbd_data_utils import SUNRGBDData + + +def create_indoor_info_file(data_path, + pkl_prefix='sunrgbd', + save_path=None, + workers=4, + **kwargs): + """Create indoor information file. + + Get information of the raw data and save it to the pkl file. + + Args: + data_path (str): Path of the data. + pkl_prefix (str, optional): Prefix of the pkl to be saved. + Default: 'sunrgbd'. + save_path (str, optional): Path of the pkl to be saved. Default: None. + workers (int, optional): Number of threads to be used. Default: 4. + kwargs (dict): Additional parameters for dataset-specific Data class. + May include `use_v1` for SUN RGB-D and `num_points`. + """ + assert os.path.exists(data_path) + assert pkl_prefix in ['sunrgbd', 'scannet', 's3dis'], \ + f'unsupported indoor dataset {pkl_prefix}' + save_path = data_path if save_path is None else save_path + assert os.path.exists(save_path) + + # generate infos for both detection and segmentation task + if pkl_prefix in ['sunrgbd', 'scannet']: + train_filename = os.path.join(save_path, + f'{pkl_prefix}_infos_train.pkl') + val_filename = os.path.join(save_path, f'{pkl_prefix}_infos_val.pkl') + if pkl_prefix == 'sunrgbd': + # SUN RGB-D has a train-val split + num_points = kwargs.get('num_points', -1) + use_v1 = kwargs.get('use_v1', False) + train_dataset = SUNRGBDData( + root_path=data_path, + split='train', + use_v1=use_v1, + num_points=num_points) + val_dataset = SUNRGBDData( + root_path=data_path, + split='val', + use_v1=use_v1, + num_points=num_points) + else: + # ScanNet has a train-val-test split + train_dataset = ScanNetData(root_path=data_path, split='train') + val_dataset = ScanNetData(root_path=data_path, split='val') + test_dataset = ScanNetData(root_path=data_path, split='test') + test_filename = os.path.join(save_path, + f'{pkl_prefix}_infos_test.pkl') + + infos_train = train_dataset.get_infos( + num_workers=workers, has_label=True) + mmcv.dump(infos_train, train_filename, 'pkl') + print(f'{pkl_prefix} info train file is saved to {train_filename}') + + infos_val = val_dataset.get_infos(num_workers=workers, has_label=True) + mmcv.dump(infos_val, val_filename, 'pkl') + print(f'{pkl_prefix} info val file is saved to {val_filename}') + + if pkl_prefix == 'scannet': + infos_test = test_dataset.get_infos( + num_workers=workers, has_label=False) + mmcv.dump(infos_test, test_filename, 'pkl') + print(f'{pkl_prefix} info test file is saved to {test_filename}') + + # generate infos for the semantic segmentation task + # e.g. re-sampled scene indexes and label weights + # scene indexes are used to re-sample rooms with different number of points + # label weights are used to balance classes with different number of points + if pkl_prefix == 'scannet': + # label weight computation function is adopted from + # https://github.com/charlesq34/pointnet2/blob/master/scannet/scannet_dataset.py#L24 + num_points = kwargs.get('num_points', 8192) + train_dataset = ScanNetSegData( + data_root=data_path, + ann_file=train_filename, + split='train', + num_points=num_points, + label_weight_func=lambda x: 1.0 / np.log(1.2 + x)) + # TODO: do we need to generate on val set? + val_dataset = ScanNetSegData( + data_root=data_path, + ann_file=val_filename, + split='val', + num_points=num_points, + label_weight_func=lambda x: 1.0 / np.log(1.2 + x)) + # no need to generate for test set + train_dataset.get_seg_infos() + val_dataset.get_seg_infos() + elif pkl_prefix == 's3dis': + # S3DIS doesn't have a fixed train-val split + # it has 6 areas instead, so we generate info file for each of them + # in training, we will use dataset to wrap different areas + splits = [f'Area_{i}' for i in [1, 2, 3, 4, 5, 6]] + for split in splits: + dataset = S3DISData(root_path=data_path, split=split) + info = dataset.get_infos(num_workers=workers, has_label=True) + filename = os.path.join(save_path, + f'{pkl_prefix}_infos_{split}.pkl') + mmcv.dump(info, filename, 'pkl') + print(f'{pkl_prefix} info {split} file is saved to {filename}') + num_points = kwargs.get('num_points', 4096) + seg_dataset = S3DISSegData( + data_root=data_path, + ann_file=filename, + split=split, + num_points=num_points, + label_weight_func=lambda x: 1.0 / np.log(1.2 + x)) + seg_dataset.get_seg_infos() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_converter.py new file mode 100644 index 00000000..2db461d4 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_converter.py @@ -0,0 +1,624 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from collections import OrderedDict +from pathlib import Path + +import mmcv +import numpy as np +from nuscenes.utils.geometry_utils import view_points + +from mmdet3d.core.bbox import box_np_ops, points_cam2img +from .kitti_data_utils import WaymoInfoGatherer, get_kitti_image_info +from .nuscenes_converter import post_process_coords + +kitti_categories = ('Pedestrian', 'Cyclist', 'Car') + + +def convert_to_kitti_info_version2(info): + """convert kitti info v1 to v2 if possible. + + Args: + info (dict): Info of the input kitti data. + - image (dict): image info + - calib (dict): calibration info + - point_cloud (dict): point cloud info + """ + if 'image' not in info or 'calib' not in info or 'point_cloud' not in info: + info['image'] = { + 'image_shape': info['img_shape'], + 'image_idx': info['image_idx'], + 'image_path': info['img_path'], + } + info['calib'] = { + 'R0_rect': info['calib/R0_rect'], + 'Tr_velo_to_cam': info['calib/Tr_velo_to_cam'], + 'P2': info['calib/P2'], + } + info['point_cloud'] = { + 'velodyne_path': info['velodyne_path'], + } + + +def _read_imageset_file(path): + with open(path, 'r') as f: + lines = f.readlines() + return [int(line) for line in lines] + + +class _NumPointsInGTCalculater: + """Calculate the number of points inside the ground truth box. This is the + parallel version. For the serialized version, please refer to + `_calculate_num_points_in_gt`. + + Args: + data_path (str): Path of the data. + relative_path (bool): Whether to use relative path. + remove_outside (bool, optional): Whether to remove points which are + outside of image. Default: True. + num_features (int, optional): Number of features per point. + Default: False. + num_worker (int, optional): the number of parallel workers to use. + Default: 8. + """ + + def __init__(self, + data_path, + relative_path, + remove_outside=True, + num_features=4, + num_worker=8) -> None: + self.data_path = data_path + self.relative_path = relative_path + self.remove_outside = remove_outside + self.num_features = num_features + self.num_worker = num_worker + + def calculate_single(self, info): + pc_info = info['point_cloud'] + image_info = info['image'] + calib = info['calib'] + if self.relative_path: + v_path = str(Path(self.data_path) / pc_info['velodyne_path']) + else: + v_path = pc_info['velodyne_path'] + points_v = np.fromfile( + v_path, dtype=np.float32, + count=-1).reshape([-1, self.num_features]) + rect = calib['R0_rect'] + Trv2c = calib['Tr_velo_to_cam'] + P2 = calib['P2'] + if self.remove_outside: + points_v = box_np_ops.remove_outside_points( + points_v, rect, Trv2c, P2, image_info['image_shape']) + annos = info['annos'] + num_obj = len([n for n in annos['name'] if n != 'DontCare']) + dims = annos['dimensions'][:num_obj] + loc = annos['location'][:num_obj] + rots = annos['rotation_y'][:num_obj] + gt_boxes_camera = np.concatenate([loc, dims, rots[..., np.newaxis]], + axis=1) + gt_boxes_lidar = box_np_ops.box_camera_to_lidar( + gt_boxes_camera, rect, Trv2c) + indices = box_np_ops.points_in_rbbox(points_v[:, :3], gt_boxes_lidar) + num_points_in_gt = indices.sum(0) + num_ignored = len(annos['dimensions']) - num_obj + num_points_in_gt = np.concatenate( + [num_points_in_gt, -np.ones([num_ignored])]) + annos['num_points_in_gt'] = num_points_in_gt.astype(np.int32) + return info + + def calculate(self, infos): + ret_infos = mmcv.track_parallel_progress(self.calculate_single, infos, + self.num_worker) + for i, ret_info in enumerate(ret_infos): + infos[i] = ret_info + + +def _calculate_num_points_in_gt(data_path, + infos, + relative_path, + remove_outside=True, + num_features=4): + for info in mmcv.track_iter_progress(infos): + pc_info = info['point_cloud'] + image_info = info['image'] + calib = info['calib'] + if relative_path: + v_path = str(Path(data_path) / pc_info['velodyne_path']) + else: + v_path = pc_info['velodyne_path'] + points_v = np.fromfile( + v_path, dtype=np.float32, count=-1).reshape([-1, num_features]) + rect = calib['R0_rect'] + Trv2c = calib['Tr_velo_to_cam'] + P2 = calib['P2'] + if remove_outside: + points_v = box_np_ops.remove_outside_points( + points_v, rect, Trv2c, P2, image_info['image_shape']) + + # points_v = points_v[points_v[:, 0] > 0] + annos = info['annos'] + num_obj = len([n for n in annos['name'] if n != 'DontCare']) + # annos = kitti.filter_kitti_anno(annos, ['DontCare']) + dims = annos['dimensions'][:num_obj] + loc = annos['location'][:num_obj] + rots = annos['rotation_y'][:num_obj] + gt_boxes_camera = np.concatenate([loc, dims, rots[..., np.newaxis]], + axis=1) + gt_boxes_lidar = box_np_ops.box_camera_to_lidar( + gt_boxes_camera, rect, Trv2c) + indices = box_np_ops.points_in_rbbox(points_v[:, :3], gt_boxes_lidar) + num_points_in_gt = indices.sum(0) + num_ignored = len(annos['dimensions']) - num_obj + num_points_in_gt = np.concatenate( + [num_points_in_gt, -np.ones([num_ignored])]) + annos['num_points_in_gt'] = num_points_in_gt.astype(np.int32) + + +def create_kitti_info_file(data_path, + pkl_prefix='kitti', + with_plane=False, + save_path=None, + relative_path=True): + """Create info file of KITTI dataset. + + Given the raw data, generate its related info file in pkl format. + + Args: + data_path (str): Path of the data root. + pkl_prefix (str, optional): Prefix of the info file to be generated. + Default: 'kitti'. + with_plane (bool, optional): Whether to use plane information. + Default: False. + save_path (str, optional): Path to save the info file. + Default: None. + relative_path (bool, optional): Whether to use relative path. + Default: True. + """ + imageset_folder = Path(data_path) / 'ImageSets' + train_img_ids = _read_imageset_file(str(imageset_folder / 'train.txt')) + val_img_ids = _read_imageset_file(str(imageset_folder / 'val.txt')) + test_img_ids = _read_imageset_file(str(imageset_folder / 'test.txt')) + + print('Generate info. this may take several minutes.') + if save_path is None: + save_path = Path(data_path) + else: + save_path = Path(save_path) + kitti_infos_train = get_kitti_image_info( + data_path, + training=True, + velodyne=True, + calib=True, + with_plane=with_plane, + image_ids=train_img_ids, + relative_path=relative_path) + _calculate_num_points_in_gt(data_path, kitti_infos_train, relative_path) + filename = save_path / f'{pkl_prefix}_infos_train.pkl' + print(f'Kitti info train file is saved to {filename}') + mmcv.dump(kitti_infos_train, filename) + kitti_infos_val = get_kitti_image_info( + data_path, + training=True, + velodyne=True, + calib=True, + with_plane=with_plane, + image_ids=val_img_ids, + relative_path=relative_path) + _calculate_num_points_in_gt(data_path, kitti_infos_val, relative_path) + filename = save_path / f'{pkl_prefix}_infos_val.pkl' + print(f'Kitti info val file is saved to {filename}') + mmcv.dump(kitti_infos_val, filename) + filename = save_path / f'{pkl_prefix}_infos_trainval.pkl' + print(f'Kitti info trainval file is saved to {filename}') + mmcv.dump(kitti_infos_train + kitti_infos_val, filename) + + kitti_infos_test = get_kitti_image_info( + data_path, + training=False, + label_info=False, + velodyne=True, + calib=True, + with_plane=False, + image_ids=test_img_ids, + relative_path=relative_path) + filename = save_path / f'{pkl_prefix}_infos_test.pkl' + print(f'Kitti info test file is saved to {filename}') + mmcv.dump(kitti_infos_test, filename) + + +def create_waymo_info_file(data_path, + pkl_prefix='waymo', + save_path=None, + relative_path=True, + max_sweeps=5, + workers=8): + """Create info file of waymo dataset. + + Given the raw data, generate its related info file in pkl format. + + Args: + data_path (str): Path of the data root. + pkl_prefix (str, optional): Prefix of the info file to be generated. + Default: 'waymo'. + save_path (str, optional): Path to save the info file. + Default: None. + relative_path (bool, optional): Whether to use relative path. + Default: True. + max_sweeps (int, optional): Max sweeps before the detection frame + to be used. Default: 5. + """ + imageset_folder = Path(data_path) / 'ImageSets' + train_img_ids = _read_imageset_file(str(imageset_folder / 'train.txt')) + val_img_ids = _read_imageset_file(str(imageset_folder / 'val.txt')) + test_img_ids = _read_imageset_file(str(imageset_folder / 'test.txt')) + + print('Generate info. this may take several minutes.') + if save_path is None: + save_path = Path(data_path) + else: + save_path = Path(save_path) + waymo_infos_gatherer_trainval = WaymoInfoGatherer( + data_path, + training=True, + velodyne=True, + calib=True, + pose=True, + relative_path=relative_path, + max_sweeps=max_sweeps, + num_worker=workers) + waymo_infos_gatherer_test = WaymoInfoGatherer( + data_path, + training=False, + label_info=False, + velodyne=True, + calib=True, + pose=True, + relative_path=relative_path, + max_sweeps=max_sweeps, + num_worker=workers) + num_points_in_gt_calculater = _NumPointsInGTCalculater( + data_path, + relative_path, + num_features=6, + remove_outside=False, + num_worker=workers) + + waymo_infos_train = waymo_infos_gatherer_trainval.gather(train_img_ids) + num_points_in_gt_calculater.calculate(waymo_infos_train) + filename = save_path / f'{pkl_prefix}_infos_train.pkl' + print(f'Waymo info train file is saved to {filename}') + mmcv.dump(waymo_infos_train, filename) + waymo_infos_val = waymo_infos_gatherer_trainval.gather(val_img_ids) + num_points_in_gt_calculater.calculate(waymo_infos_val) + filename = save_path / f'{pkl_prefix}_infos_val.pkl' + print(f'Waymo info val file is saved to {filename}') + mmcv.dump(waymo_infos_val, filename) + filename = save_path / f'{pkl_prefix}_infos_trainval.pkl' + print(f'Waymo info trainval file is saved to {filename}') + mmcv.dump(waymo_infos_train + waymo_infos_val, filename) + waymo_infos_test = waymo_infos_gatherer_test.gather(test_img_ids) + filename = save_path / f'{pkl_prefix}_infos_test.pkl' + print(f'Waymo info test file is saved to {filename}') + mmcv.dump(waymo_infos_test, filename) + + +def _create_reduced_point_cloud(data_path, + info_path, + save_path=None, + back=False, + num_features=4, + front_camera_id=2): + """Create reduced point clouds for given info. + + Args: + data_path (str): Path of original data. + info_path (str): Path of data info. + save_path (str, optional): Path to save reduced point cloud + data. Default: None. + back (bool, optional): Whether to flip the points to back. + Default: False. + num_features (int, optional): Number of point features. Default: 4. + front_camera_id (int, optional): The referenced/front camera ID. + Default: 2. + """ + kitti_infos = mmcv.load(info_path) + + for info in mmcv.track_iter_progress(kitti_infos): + pc_info = info['point_cloud'] + image_info = info['image'] + calib = info['calib'] + + v_path = pc_info['velodyne_path'] + v_path = Path(data_path) / v_path + points_v = np.fromfile( + str(v_path), dtype=np.float32, + count=-1).reshape([-1, num_features]) + rect = calib['R0_rect'] + if front_camera_id == 2: + P2 = calib['P2'] + else: + P2 = calib[f'P{str(front_camera_id)}'] + Trv2c = calib['Tr_velo_to_cam'] + # first remove z < 0 points + # keep = points_v[:, -1] > 0 + # points_v = points_v[keep] + # then remove outside. + if back: + points_v[:, 0] = -points_v[:, 0] + points_v = box_np_ops.remove_outside_points(points_v, rect, Trv2c, P2, + image_info['image_shape']) + if save_path is None: + save_dir = v_path.parent.parent / (v_path.parent.stem + '_reduced') + if not save_dir.exists(): + save_dir.mkdir() + save_filename = save_dir / v_path.name + # save_filename = str(v_path) + '_reduced' + if back: + save_filename += '_back' + else: + save_filename = str(Path(save_path) / v_path.name) + if back: + save_filename += '_back' + with open(save_filename, 'w') as f: + points_v.tofile(f) + + +def create_reduced_point_cloud(data_path, + pkl_prefix, + train_info_path=None, + val_info_path=None, + test_info_path=None, + save_path=None, + with_back=False): + """Create reduced point clouds for training/validation/testing. + + Args: + data_path (str): Path of original data. + pkl_prefix (str): Prefix of info files. + train_info_path (str, optional): Path of training set info. + Default: None. + val_info_path (str, optional): Path of validation set info. + Default: None. + test_info_path (str, optional): Path of test set info. + Default: None. + save_path (str, optional): Path to save reduced point cloud data. + Default: None. + with_back (bool, optional): Whether to flip the points to back. + Default: False. + """ + if train_info_path is None: + train_info_path = Path(data_path) / f'{pkl_prefix}_infos_train.pkl' + if val_info_path is None: + val_info_path = Path(data_path) / f'{pkl_prefix}_infos_val.pkl' + if test_info_path is None: + test_info_path = Path(data_path) / f'{pkl_prefix}_infos_test.pkl' + + print('create reduced point cloud for training set') + _create_reduced_point_cloud(data_path, train_info_path, save_path) + print('create reduced point cloud for validation set') + _create_reduced_point_cloud(data_path, val_info_path, save_path) + print('create reduced point cloud for testing set') + _create_reduced_point_cloud(data_path, test_info_path, save_path) + if with_back: + _create_reduced_point_cloud( + data_path, train_info_path, save_path, back=True) + _create_reduced_point_cloud( + data_path, val_info_path, save_path, back=True) + _create_reduced_point_cloud( + data_path, test_info_path, save_path, back=True) + + +def export_2d_annotation(root_path, info_path, mono3d=True): + """Export 2d annotation from the info file and raw data. + + Args: + root_path (str): Root path of the raw data. + info_path (str): Path of the info file. + mono3d (bool, optional): Whether to export mono3d annotation. + Default: True. + """ + # get bbox annotations for camera + kitti_infos = mmcv.load(info_path) + cat2Ids = [ + dict(id=kitti_categories.index(cat_name), name=cat_name) + for cat_name in kitti_categories + ] + coco_ann_id = 0 + coco_2d_dict = dict(annotations=[], images=[], categories=cat2Ids) + from os import path as osp + for info in mmcv.track_iter_progress(kitti_infos): + coco_infos = get_2d_boxes(info, occluded=[0, 1, 2, 3], mono3d=mono3d) + (height, width, + _) = mmcv.imread(osp.join(root_path, + info['image']['image_path'])).shape + coco_2d_dict['images'].append( + dict( + file_name=info['image']['image_path'], + id=info['image']['image_idx'], + Tri2v=info['calib']['Tr_imu_to_velo'], + Trv2c=info['calib']['Tr_velo_to_cam'], + rect=info['calib']['R0_rect'], + cam_intrinsic=info['calib']['P2'], + width=width, + height=height)) + for coco_info in coco_infos: + if coco_info is None: + continue + # add an empty key for coco format + coco_info['segmentation'] = [] + coco_info['id'] = coco_ann_id + coco_2d_dict['annotations'].append(coco_info) + coco_ann_id += 1 + if mono3d: + json_prefix = f'{info_path[:-4]}_mono3d' + else: + json_prefix = f'{info_path[:-4]}' + mmcv.dump(coco_2d_dict, f'{json_prefix}.coco.json') + + +def get_2d_boxes(info, occluded, mono3d=True): + """Get the 2D annotation records for a given info. + + Args: + info: Information of the given sample data. + occluded: Integer (0, 1, 2, 3) indicating occlusion state: + 0 = fully visible, 1 = partly occluded, 2 = largely occluded, + 3 = unknown, -1 = DontCare + mono3d (bool): Whether to get boxes with mono3d annotation. + + Return: + list[dict]: List of 2D annotation record that belongs to the input + `sample_data_token`. + """ + # Get calibration information + P2 = info['calib']['P2'] + + repro_recs = [] + # if no annotations in info (test dataset), then return + if 'annos' not in info: + return repro_recs + + # Get all the annotation with the specified visibilties. + ann_dicts = info['annos'] + mask = [(ocld in occluded) for ocld in ann_dicts['occluded']] + for k in ann_dicts.keys(): + ann_dicts[k] = ann_dicts[k][mask] + + # convert dict of list to list of dict + ann_recs = [] + for i in range(len(ann_dicts['occluded'])): + ann_rec = {} + for k in ann_dicts.keys(): + ann_rec[k] = ann_dicts[k][i] + ann_recs.append(ann_rec) + + for ann_idx, ann_rec in enumerate(ann_recs): + # Augment sample_annotation with token information. + ann_rec['sample_annotation_token'] = \ + f"{info['image']['image_idx']}.{ann_idx}" + ann_rec['sample_data_token'] = info['image']['image_idx'] + sample_data_token = info['image']['image_idx'] + + loc = ann_rec['location'][np.newaxis, :] + dim = ann_rec['dimensions'][np.newaxis, :] + rot = ann_rec['rotation_y'][np.newaxis, np.newaxis] + # transform the center from [0.5, 1.0, 0.5] to [0.5, 0.5, 0.5] + dst = np.array([0.5, 0.5, 0.5]) + src = np.array([0.5, 1.0, 0.5]) + loc = loc + dim * (dst - src) + offset = (info['calib']['P2'][0, 3] - info['calib']['P0'][0, 3]) \ + / info['calib']['P2'][0, 0] + loc_3d = np.copy(loc) + loc_3d[0, 0] += offset + gt_bbox_3d = np.concatenate([loc, dim, rot], axis=1).astype(np.float32) + + # Filter out the corners that are not in front of the calibrated + # sensor. + corners_3d = box_np_ops.center_to_corner_box3d( + gt_bbox_3d[:, :3], + gt_bbox_3d[:, 3:6], + gt_bbox_3d[:, 6], [0.5, 0.5, 0.5], + axis=1) + corners_3d = corners_3d[0].T # (1, 8, 3) -> (3, 8) + in_front = np.argwhere(corners_3d[2, :] > 0).flatten() + corners_3d = corners_3d[:, in_front] + + # Project 3d box to 2d. + camera_intrinsic = P2 + corner_coords = view_points(corners_3d, camera_intrinsic, + True).T[:, :2].tolist() + + # Keep only corners that fall within the image. + final_coords = post_process_coords(corner_coords) + + # Skip if the convex hull of the re-projected corners + # does not intersect the image canvas. + if final_coords is None: + continue + else: + min_x, min_y, max_x, max_y = final_coords + + # Generate dictionary record to be included in the .json file. + repro_rec = generate_record(ann_rec, min_x, min_y, max_x, max_y, + sample_data_token, + info['image']['image_path']) + + # If mono3d=True, add 3D annotations in camera coordinates + if mono3d and (repro_rec is not None): + repro_rec['bbox_cam3d'] = np.concatenate( + [loc_3d, dim, rot], + axis=1).astype(np.float32).squeeze().tolist() + repro_rec['velo_cam3d'] = -1 # no velocity in KITTI + + center3d = np.array(loc).reshape([1, 3]) + center2d = points_cam2img( + center3d, camera_intrinsic, with_depth=True) + repro_rec['center2d'] = center2d.squeeze().tolist() + # normalized center2D + depth + # samples with depth < 0 will be removed + if repro_rec['center2d'][2] <= 0: + continue + + repro_rec['attribute_name'] = -1 # no attribute in KITTI + repro_rec['attribute_id'] = -1 + + repro_recs.append(repro_rec) + + return repro_recs + + +def generate_record(ann_rec, x1, y1, x2, y2, sample_data_token, filename): + """Generate one 2D annotation record given various information on top of + the 2D bounding box coordinates. + + Args: + ann_rec (dict): Original 3d annotation record. + x1 (float): Minimum value of the x coordinate. + y1 (float): Minimum value of the y coordinate. + x2 (float): Maximum value of the x coordinate. + y2 (float): Maximum value of the y coordinate. + sample_data_token (str): Sample data token. + filename (str):The corresponding image file where the annotation + is present. + + Returns: + dict: A sample 2D annotation record. + - file_name (str): file name + - image_id (str): sample data token + - area (float): 2d box area + - category_name (str): category name + - category_id (int): category id + - bbox (list[float]): left x, top y, x_size, y_size of 2d box + - iscrowd (int): whether the area is crowd + """ + repro_rec = OrderedDict() + repro_rec['sample_data_token'] = sample_data_token + coco_rec = dict() + + key_mapping = { + 'name': 'category_name', + 'num_points_in_gt': 'num_lidar_pts', + 'sample_annotation_token': 'sample_annotation_token', + 'sample_data_token': 'sample_data_token', + } + + for key, value in ann_rec.items(): + if key in key_mapping.keys(): + repro_rec[key_mapping[key]] = value + + repro_rec['bbox_corners'] = [x1, y1, x2, y2] + repro_rec['filename'] = filename + + coco_rec['file_name'] = filename + coco_rec['image_id'] = sample_data_token + coco_rec['area'] = (y2 - y1) * (x2 - x1) + + if repro_rec['category_name'] not in kitti_categories: + return None + cat_name = repro_rec['category_name'] + coco_rec['category_name'] = cat_name + coco_rec['category_id'] = kitti_categories.index(cat_name) + coco_rec['bbox'] = [x1, y1, x2 - x1, y2 - y1] + coco_rec['iscrowd'] = 0 + + return coco_rec diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_data_utils.py new file mode 100644 index 00000000..cae84cc6 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/kitti_data_utils.py @@ -0,0 +1,619 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from collections import OrderedDict +from concurrent import futures as futures +from os import path as osp +from pathlib import Path + +import mmcv +import numpy as np +from PIL import Image +from skimage import io + + +def get_image_index_str(img_idx, use_prefix_id=False): + if use_prefix_id: + return '{:07d}'.format(img_idx) + else: + return '{:06d}'.format(img_idx) + + +def get_kitti_info_path(idx, + prefix, + info_type='image_2', + file_tail='.png', + training=True, + relative_path=True, + exist_check=True, + use_prefix_id=False): + img_idx_str = get_image_index_str(idx, use_prefix_id) + img_idx_str += file_tail + prefix = Path(prefix) + if training: + file_path = Path('training') / info_type / img_idx_str + else: + file_path = Path('testing') / info_type / img_idx_str + if exist_check and not (prefix / file_path).exists(): + raise ValueError('file not exist: {}'.format(file_path)) + if relative_path: + return str(file_path) + else: + return str(prefix / file_path) + + +def get_image_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + info_type='image_2', + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, info_type, '.png', training, + relative_path, exist_check, use_prefix_id) + + +def get_label_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + info_type='label_2', + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, info_type, '.txt', training, + relative_path, exist_check, use_prefix_id) + + +def get_plane_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + info_type='planes', + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, info_type, '.txt', training, + relative_path, exist_check, use_prefix_id) + + +def get_velodyne_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, 'velodyne', '.bin', training, + relative_path, exist_check, use_prefix_id) + + +def get_calib_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, 'calib', '.txt', training, + relative_path, exist_check, use_prefix_id) + + +def get_pose_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, 'pose', '.txt', training, + relative_path, exist_check, use_prefix_id) + + +def get_timestamp_path(idx, + prefix, + training=True, + relative_path=True, + exist_check=True, + use_prefix_id=False): + return get_kitti_info_path(idx, prefix, 'timestamp', '.txt', training, + relative_path, exist_check, use_prefix_id) + + +def get_label_anno(label_path): + annotations = {} + annotations.update({ + 'name': [], + 'truncated': [], + 'occluded': [], + 'alpha': [], + 'bbox': [], + 'dimensions': [], + 'location': [], + 'rotation_y': [] + }) + with open(label_path, 'r') as f: + lines = f.readlines() + # if len(lines) == 0 or len(lines[0]) < 15: + # content = [] + # else: + content = [line.strip().split(' ') for line in lines] + num_objects = len([x[0] for x in content if x[0] != 'DontCare']) + annotations['name'] = np.array([x[0] for x in content]) + num_gt = len(annotations['name']) + annotations['truncated'] = np.array([float(x[1]) for x in content]) + annotations['occluded'] = np.array([int(x[2]) for x in content]) + annotations['alpha'] = np.array([float(x[3]) for x in content]) + annotations['bbox'] = np.array([[float(info) for info in x[4:8]] + for x in content]).reshape(-1, 4) + # dimensions will convert hwl format to standard lhw(camera) format. + annotations['dimensions'] = np.array([[float(info) for info in x[8:11]] + for x in content + ]).reshape(-1, 3)[:, [2, 0, 1]] + annotations['location'] = np.array([[float(info) for info in x[11:14]] + for x in content]).reshape(-1, 3) + annotations['rotation_y'] = np.array([float(x[14]) + for x in content]).reshape(-1) + if len(content) != 0 and len(content[0]) == 16: # have score + annotations['score'] = np.array([float(x[15]) for x in content]) + else: + annotations['score'] = np.zeros((annotations['bbox'].shape[0], )) + index = list(range(num_objects)) + [-1] * (num_gt - num_objects) + annotations['index'] = np.array(index, dtype=np.int32) + annotations['group_ids'] = np.arange(num_gt, dtype=np.int32) + return annotations + + +def _extend_matrix(mat): + mat = np.concatenate([mat, np.array([[0., 0., 0., 1.]])], axis=0) + return mat + + +def get_kitti_image_info(path, + training=True, + label_info=True, + velodyne=False, + calib=False, + with_plane=False, + image_ids=7481, + extend_matrix=True, + num_worker=8, + relative_path=True, + with_imageshape=True): + """ + KITTI annotation format version 2: + { + [optional]points: [N, 3+] point cloud + [optional, for kitti]image: { + image_idx: ... + image_path: ... + image_shape: ... + } + point_cloud: { + num_features: 4 + velodyne_path: ... + } + [optional, for kitti]calib: { + R0_rect: ... + Tr_velo_to_cam: ... + P2: ... + } + annos: { + location: [num_gt, 3] array + dimensions: [num_gt, 3] array + rotation_y: [num_gt] angle array + name: [num_gt] ground truth name array + [optional]difficulty: kitti difficulty + [optional]group_ids: used for multi-part object + } + } + """ + root_path = Path(path) + if not isinstance(image_ids, list): + image_ids = list(range(image_ids)) + + def map_func(idx): + info = {} + pc_info = {'num_features': 4} + calib_info = {} + + image_info = {'image_idx': idx} + annotations = None + if velodyne: + pc_info['velodyne_path'] = get_velodyne_path( + idx, path, training, relative_path) + image_info['image_path'] = get_image_path(idx, path, training, + relative_path) + if with_imageshape: + img_path = image_info['image_path'] + if relative_path: + img_path = str(root_path / img_path) + image_info['image_shape'] = np.array( + io.imread(img_path).shape[:2], dtype=np.int32) + if label_info: + label_path = get_label_path(idx, path, training, relative_path) + if relative_path: + label_path = str(root_path / label_path) + annotations = get_label_anno(label_path) + info['image'] = image_info + info['point_cloud'] = pc_info + if calib: + calib_path = get_calib_path( + idx, path, training, relative_path=False) + with open(calib_path, 'r') as f: + lines = f.readlines() + P0 = np.array([float(info) for info in lines[0].split(' ')[1:13] + ]).reshape([3, 4]) + P1 = np.array([float(info) for info in lines[1].split(' ')[1:13] + ]).reshape([3, 4]) + P2 = np.array([float(info) for info in lines[2].split(' ')[1:13] + ]).reshape([3, 4]) + P3 = np.array([float(info) for info in lines[3].split(' ')[1:13] + ]).reshape([3, 4]) + if extend_matrix: + P0 = _extend_matrix(P0) + P1 = _extend_matrix(P1) + P2 = _extend_matrix(P2) + P3 = _extend_matrix(P3) + R0_rect = np.array([ + float(info) for info in lines[4].split(' ')[1:10] + ]).reshape([3, 3]) + if extend_matrix: + rect_4x4 = np.zeros([4, 4], dtype=R0_rect.dtype) + rect_4x4[3, 3] = 1. + rect_4x4[:3, :3] = R0_rect + else: + rect_4x4 = R0_rect + + Tr_velo_to_cam = np.array([ + float(info) for info in lines[5].split(' ')[1:13] + ]).reshape([3, 4]) + Tr_imu_to_velo = np.array([ + float(info) for info in lines[6].split(' ')[1:13] + ]).reshape([3, 4]) + if extend_matrix: + Tr_velo_to_cam = _extend_matrix(Tr_velo_to_cam) + Tr_imu_to_velo = _extend_matrix(Tr_imu_to_velo) + calib_info['P0'] = P0 + calib_info['P1'] = P1 + calib_info['P2'] = P2 + calib_info['P3'] = P3 + calib_info['R0_rect'] = rect_4x4 + calib_info['Tr_velo_to_cam'] = Tr_velo_to_cam + calib_info['Tr_imu_to_velo'] = Tr_imu_to_velo + info['calib'] = calib_info + + if with_plane: + plane_path = get_plane_path(idx, path, training, relative_path) + if relative_path: + plane_path = str(root_path / plane_path) + lines = mmcv.list_from_file(plane_path) + info['plane'] = np.array([float(i) for i in lines[3].split()]) + + if annotations is not None: + info['annos'] = annotations + add_difficulty_to_annos(info) + return info + + with futures.ThreadPoolExecutor(num_worker) as executor: + image_infos = executor.map(map_func, image_ids) + + return list(image_infos) + + +class WaymoInfoGatherer: + """ + Parallel version of waymo dataset information gathering. + Waymo annotation format version like KITTI: + { + [optional]points: [N, 3+] point cloud + [optional, for kitti]image: { + image_idx: ... + image_path: ... + image_shape: ... + } + point_cloud: { + num_features: 6 + velodyne_path: ... + } + [optional, for kitti]calib: { + R0_rect: ... + Tr_velo_to_cam0: ... + P0: ... + } + annos: { + location: [num_gt, 3] array + dimensions: [num_gt, 3] array + rotation_y: [num_gt] angle array + name: [num_gt] ground truth name array + [optional]difficulty: kitti difficulty + [optional]group_ids: used for multi-part object + } + } + """ + + def __init__(self, + path, + training=True, + label_info=True, + velodyne=False, + calib=False, + pose=False, + extend_matrix=True, + num_worker=8, + relative_path=True, + with_imageshape=True, + max_sweeps=5) -> None: + self.path = path + self.training = training + self.label_info = label_info + self.velodyne = velodyne + self.calib = calib + self.pose = pose + self.extend_matrix = extend_matrix + self.num_worker = num_worker + self.relative_path = relative_path + self.with_imageshape = with_imageshape + self.max_sweeps = max_sweeps + + def gather_single(self, idx): + root_path = Path(self.path) + info = {} + pc_info = {'num_features': 6} + calib_info = {} + + image_info = {'image_idx': idx} + annotations = None + if self.velodyne: + pc_info['velodyne_path'] = get_velodyne_path( + idx, + self.path, + self.training, + self.relative_path, + use_prefix_id=True) + with open( + get_timestamp_path( + idx, + self.path, + self.training, + relative_path=False, + use_prefix_id=True)) as f: + info['timestamp'] = np.int64(f.read()) + image_info['image_path'] = get_image_path( + idx, + self.path, + self.training, + self.relative_path, + info_type='image_0', + use_prefix_id=True) + if self.with_imageshape: + img_path = image_info['image_path'] + if self.relative_path: + img_path = str(root_path / img_path) + # io using PIL is significantly faster than skimage + w, h = Image.open(img_path).size + image_info['image_shape'] = np.array((h, w), dtype=np.int32) + if self.label_info: + label_path = get_label_path( + idx, + self.path, + self.training, + self.relative_path, + info_type='label_all', + use_prefix_id=True) + if self.relative_path: + label_path = str(root_path / label_path) + annotations = get_label_anno(label_path) + info['image'] = image_info + info['point_cloud'] = pc_info + if self.calib: + calib_path = get_calib_path( + idx, + self.path, + self.training, + relative_path=False, + use_prefix_id=True) + with open(calib_path, 'r') as f: + lines = f.readlines() + P0 = np.array([float(info) for info in lines[0].split(' ')[1:13] + ]).reshape([3, 4]) + P1 = np.array([float(info) for info in lines[1].split(' ')[1:13] + ]).reshape([3, 4]) + P2 = np.array([float(info) for info in lines[2].split(' ')[1:13] + ]).reshape([3, 4]) + P3 = np.array([float(info) for info in lines[3].split(' ')[1:13] + ]).reshape([3, 4]) + P4 = np.array([float(info) for info in lines[4].split(' ')[1:13] + ]).reshape([3, 4]) + if self.extend_matrix: + P0 = _extend_matrix(P0) + P1 = _extend_matrix(P1) + P2 = _extend_matrix(P2) + P3 = _extend_matrix(P3) + P4 = _extend_matrix(P4) + R0_rect = np.array([ + float(info) for info in lines[5].split(' ')[1:10] + ]).reshape([3, 3]) + if self.extend_matrix: + rect_4x4 = np.zeros([4, 4], dtype=R0_rect.dtype) + rect_4x4[3, 3] = 1. + rect_4x4[:3, :3] = R0_rect + else: + rect_4x4 = R0_rect + + Tr_velo_to_cam = np.array([ + float(info) for info in lines[6].split(' ')[1:13] + ]).reshape([3, 4]) + if self.extend_matrix: + Tr_velo_to_cam = _extend_matrix(Tr_velo_to_cam) + calib_info['P0'] = P0 + calib_info['P1'] = P1 + calib_info['P2'] = P2 + calib_info['P3'] = P3 + calib_info['P4'] = P4 + calib_info['R0_rect'] = rect_4x4 + calib_info['Tr_velo_to_cam'] = Tr_velo_to_cam + info['calib'] = calib_info + if self.pose: + pose_path = get_pose_path( + idx, + self.path, + self.training, + relative_path=False, + use_prefix_id=True) + info['pose'] = np.loadtxt(pose_path) + + if annotations is not None: + info['annos'] = annotations + info['annos']['camera_id'] = info['annos'].pop('score') + add_difficulty_to_annos(info) + + sweeps = [] + prev_idx = idx + while len(sweeps) < self.max_sweeps: + prev_info = {} + prev_idx -= 1 + prev_info['velodyne_path'] = get_velodyne_path( + prev_idx, + self.path, + self.training, + self.relative_path, + exist_check=False, + use_prefix_id=True) + if_prev_exists = osp.exists( + Path(self.path) / prev_info['velodyne_path']) + if if_prev_exists: + with open( + get_timestamp_path( + prev_idx, + self.path, + self.training, + relative_path=False, + use_prefix_id=True)) as f: + prev_info['timestamp'] = np.int64(f.read()) + prev_pose_path = get_pose_path( + prev_idx, + self.path, + self.training, + relative_path=False, + use_prefix_id=True) + prev_info['pose'] = np.loadtxt(prev_pose_path) + sweeps.append(prev_info) + else: + break + info['sweeps'] = sweeps + + return info + + def gather(self, image_ids): + if not isinstance(image_ids, list): + image_ids = list(range(image_ids)) + image_infos = mmcv.track_parallel_progress(self.gather_single, + image_ids, self.num_worker) + return list(image_infos) + + +def kitti_anno_to_label_file(annos, folder): + folder = Path(folder) + for anno in annos: + image_idx = anno['metadata']['image_idx'] + label_lines = [] + for j in range(anno['bbox'].shape[0]): + label_dict = { + 'name': anno['name'][j], + 'alpha': anno['alpha'][j], + 'bbox': anno['bbox'][j], + 'location': anno['location'][j], + 'dimensions': anno['dimensions'][j], + 'rotation_y': anno['rotation_y'][j], + 'score': anno['score'][j], + } + label_line = kitti_result_line(label_dict) + label_lines.append(label_line) + label_file = folder / f'{get_image_index_str(image_idx)}.txt' + label_str = '\n'.join(label_lines) + with open(label_file, 'w') as f: + f.write(label_str) + + +def add_difficulty_to_annos(info): + min_height = [40, 25, + 25] # minimum height for evaluated groundtruth/detections + max_occlusion = [ + 0, 1, 2 + ] # maximum occlusion level of the groundtruth used for evaluation + max_trunc = [ + 0.15, 0.3, 0.5 + ] # maximum truncation level of the groundtruth used for evaluation + annos = info['annos'] + dims = annos['dimensions'] # lhw format + bbox = annos['bbox'] + height = bbox[:, 3] - bbox[:, 1] + occlusion = annos['occluded'] + truncation = annos['truncated'] + diff = [] + easy_mask = np.ones((len(dims), ), dtype=np.bool) + moderate_mask = np.ones((len(dims), ), dtype=np.bool) + hard_mask = np.ones((len(dims), ), dtype=np.bool) + i = 0 + for h, o, t in zip(height, occlusion, truncation): + if o > max_occlusion[0] or h <= min_height[0] or t > max_trunc[0]: + easy_mask[i] = False + if o > max_occlusion[1] or h <= min_height[1] or t > max_trunc[1]: + moderate_mask[i] = False + if o > max_occlusion[2] or h <= min_height[2] or t > max_trunc[2]: + hard_mask[i] = False + i += 1 + is_easy = easy_mask + is_moderate = np.logical_xor(easy_mask, moderate_mask) + is_hard = np.logical_xor(hard_mask, moderate_mask) + + for i in range(len(dims)): + if is_easy[i]: + diff.append(0) + elif is_moderate[i]: + diff.append(1) + elif is_hard[i]: + diff.append(2) + else: + diff.append(-1) + annos['difficulty'] = np.array(diff, np.int32) + return diff + + +def kitti_result_line(result_dict, precision=4): + prec_float = '{' + ':.{}f'.format(precision) + '}' + res_line = [] + all_field_default = OrderedDict([ + ('name', None), + ('truncated', -1), + ('occluded', -1), + ('alpha', -10), + ('bbox', None), + ('dimensions', [-1, -1, -1]), + ('location', [-1000, -1000, -1000]), + ('rotation_y', -10), + ('score', 0.0), + ]) + res_dict = [(key, None) for key, val in all_field_default.items()] + res_dict = OrderedDict(res_dict) + for key, val in result_dict.items(): + if all_field_default[key] is None and val is None: + raise ValueError('you must specify a value for {}'.format(key)) + res_dict[key] = val + + for key, val in res_dict.items(): + if key == 'name': + res_line.append(val) + elif key in ['truncated', 'alpha', 'rotation_y', 'score']: + if val is None: + res_line.append(str(all_field_default[key])) + else: + res_line.append(prec_float.format(val)) + elif key == 'occluded': + if val is None: + res_line.append(str(all_field_default[key])) + else: + res_line.append('{}'.format(val)) + elif key in ['bbox', 'dimensions', 'location']: + if val is None: + res_line += [str(v) for v in all_field_default[key]] + else: + res_line += [prec_float.format(v) for v in val] + else: + raise ValueError('unknown key. supported key:{}'.format( + res_dict.keys())) + return ' '.join(res_line) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_converter.py new file mode 100644 index 00000000..c6a89d0d --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_converter.py @@ -0,0 +1,271 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import os +from logging import warning +from os import path as osp + +import mmcv +import numpy as np +from lyft_dataset_sdk.lyftdataset import LyftDataset as Lyft +from pyquaternion import Quaternion + +from mmdet3d.datasets import LyftDataset +from .nuscenes_converter import (get_2d_boxes, get_available_scenes, + obtain_sensor2top) + +lyft_categories = ('car', 'truck', 'bus', 'emergency_vehicle', 'other_vehicle', + 'motorcycle', 'bicycle', 'pedestrian', 'animal') + + +def create_lyft_infos(root_path, + info_prefix, + version='v1.01-train', + max_sweeps=10): + """Create info file of lyft dataset. + + Given the raw data, generate its related info file in pkl format. + + Args: + root_path (str): Path of the data root. + info_prefix (str): Prefix of the info file to be generated. + version (str, optional): Version of the data. + Default: 'v1.01-train'. + max_sweeps (int, optional): Max number of sweeps. + Default: 10. + """ + lyft = Lyft( + data_path=osp.join(root_path, version), + json_path=osp.join(root_path, version, version), + verbose=True) + available_vers = ['v1.01-train', 'v1.01-test'] + assert version in available_vers + if version == 'v1.01-train': + train_scenes = mmcv.list_from_file('data/lyft/train.txt') + val_scenes = mmcv.list_from_file('data/lyft/val.txt') + elif version == 'v1.01-test': + train_scenes = mmcv.list_from_file('data/lyft/test.txt') + val_scenes = [] + else: + raise ValueError('unknown') + + # filter existing scenes. + available_scenes = get_available_scenes(lyft) + available_scene_names = [s['name'] for s in available_scenes] + train_scenes = list( + filter(lambda x: x in available_scene_names, train_scenes)) + val_scenes = list(filter(lambda x: x in available_scene_names, val_scenes)) + train_scenes = set([ + available_scenes[available_scene_names.index(s)]['token'] + for s in train_scenes + ]) + val_scenes = set([ + available_scenes[available_scene_names.index(s)]['token'] + for s in val_scenes + ]) + + test = 'test' in version + if test: + print(f'test scene: {len(train_scenes)}') + else: + print(f'train scene: {len(train_scenes)}, \ + val scene: {len(val_scenes)}') + train_lyft_infos, val_lyft_infos = _fill_trainval_infos( + lyft, train_scenes, val_scenes, test, max_sweeps=max_sweeps) + + metadata = dict(version=version) + if test: + print(f'test sample: {len(train_lyft_infos)}') + data = dict(infos=train_lyft_infos, metadata=metadata) + info_name = f'{info_prefix}_infos_test' + info_path = osp.join(root_path, f'{info_name}.pkl') + mmcv.dump(data, info_path) + else: + print(f'train sample: {len(train_lyft_infos)}, \ + val sample: {len(val_lyft_infos)}') + data = dict(infos=train_lyft_infos, metadata=metadata) + train_info_name = f'{info_prefix}_infos_train' + info_path = osp.join(root_path, f'{train_info_name}.pkl') + mmcv.dump(data, info_path) + data['infos'] = val_lyft_infos + val_info_name = f'{info_prefix}_infos_val' + info_val_path = osp.join(root_path, f'{val_info_name}.pkl') + mmcv.dump(data, info_val_path) + + +def _fill_trainval_infos(lyft, + train_scenes, + val_scenes, + test=False, + max_sweeps=10): + """Generate the train/val infos from the raw data. + + Args: + lyft (:obj:`LyftDataset`): Dataset class in the Lyft dataset. + train_scenes (list[str]): Basic information of training scenes. + val_scenes (list[str]): Basic information of validation scenes. + test (bool, optional): Whether use the test mode. In the test mode, no + annotations can be accessed. Default: False. + max_sweeps (int, optional): Max number of sweeps. Default: 10. + + Returns: + tuple[list[dict]]: Information of training set and + validation set that will be saved to the info file. + """ + train_lyft_infos = [] + val_lyft_infos = [] + + for sample in mmcv.track_iter_progress(lyft.sample): + lidar_token = sample['data']['LIDAR_TOP'] + sd_rec = lyft.get('sample_data', sample['data']['LIDAR_TOP']) + cs_record = lyft.get('calibrated_sensor', + sd_rec['calibrated_sensor_token']) + pose_record = lyft.get('ego_pose', sd_rec['ego_pose_token']) + abs_lidar_path, boxes, _ = lyft.get_sample_data(lidar_token) + # nuScenes devkit returns more convenient relative paths while + # lyft devkit returns absolute paths + abs_lidar_path = str(abs_lidar_path) # absolute path + lidar_path = abs_lidar_path.split(f'{os.getcwd()}/')[-1] + # relative path + + mmcv.check_file_exist(lidar_path) + + info = { + 'lidar_path': lidar_path, + 'token': sample['token'], + 'sweeps': [], + 'cams': dict(), + 'lidar2ego_translation': cs_record['translation'], + 'lidar2ego_rotation': cs_record['rotation'], + 'ego2global_translation': pose_record['translation'], + 'ego2global_rotation': pose_record['rotation'], + 'timestamp': sample['timestamp'], + } + + l2e_r = info['lidar2ego_rotation'] + l2e_t = info['lidar2ego_translation'] + e2g_r = info['ego2global_rotation'] + e2g_t = info['ego2global_translation'] + l2e_r_mat = Quaternion(l2e_r).rotation_matrix + e2g_r_mat = Quaternion(e2g_r).rotation_matrix + + # obtain 6 image's information per frame + camera_types = [ + 'CAM_FRONT', + 'CAM_FRONT_RIGHT', + 'CAM_FRONT_LEFT', + 'CAM_BACK', + 'CAM_BACK_LEFT', + 'CAM_BACK_RIGHT', + ] + for cam in camera_types: + cam_token = sample['data'][cam] + cam_path, _, cam_intrinsic = lyft.get_sample_data(cam_token) + cam_info = obtain_sensor2top(lyft, cam_token, l2e_t, l2e_r_mat, + e2g_t, e2g_r_mat, cam) + cam_info.update(cam_intrinsic=cam_intrinsic) + info['cams'].update({cam: cam_info}) + + # obtain sweeps for a single key-frame + sd_rec = lyft.get('sample_data', sample['data']['LIDAR_TOP']) + sweeps = [] + while len(sweeps) < max_sweeps: + if not sd_rec['prev'] == '': + sweep = obtain_sensor2top(lyft, sd_rec['prev'], l2e_t, + l2e_r_mat, e2g_t, e2g_r_mat, 'lidar') + sweeps.append(sweep) + sd_rec = lyft.get('sample_data', sd_rec['prev']) + else: + break + info['sweeps'] = sweeps + # obtain annotation + if not test: + annotations = [ + lyft.get('sample_annotation', token) + for token in sample['anns'] + ] + locs = np.array([b.center for b in boxes]).reshape(-1, 3) + dims = np.array([b.wlh for b in boxes]).reshape(-1, 3) + rots = np.array([b.orientation.yaw_pitch_roll[0] + for b in boxes]).reshape(-1, 1) + + names = [b.name for b in boxes] + for i in range(len(names)): + if names[i] in LyftDataset.NameMapping: + names[i] = LyftDataset.NameMapping[names[i]] + names = np.array(names) + + # we need to convert box size to + # the format of our lidar coordinate system + # which is x_size, y_size, z_size (corresponding to l, w, h) + gt_boxes = np.concatenate([locs, dims[:, [1, 0, 2]], rots], axis=1) + assert len(gt_boxes) == len( + annotations), f'{len(gt_boxes)}, {len(annotations)}' + info['gt_boxes'] = gt_boxes + info['gt_names'] = names + info['num_lidar_pts'] = np.array( + [a['num_lidar_pts'] for a in annotations]) + info['num_radar_pts'] = np.array( + [a['num_radar_pts'] for a in annotations]) + + if sample['scene_token'] in train_scenes: + train_lyft_infos.append(info) + else: + val_lyft_infos.append(info) + + return train_lyft_infos, val_lyft_infos + + +def export_2d_annotation(root_path, info_path, version): + """Export 2d annotation from the info file and raw data. + + Args: + root_path (str): Root path of the raw data. + info_path (str): Path of the info file. + version (str): Dataset version. + """ + warning.warn('DeprecationWarning: 2D annotations are not used on the ' + 'Lyft dataset. The function export_2d_annotation will be ' + 'deprecated.') + # get bbox annotations for camera + camera_types = [ + 'CAM_FRONT', + 'CAM_FRONT_RIGHT', + 'CAM_FRONT_LEFT', + 'CAM_BACK', + 'CAM_BACK_LEFT', + 'CAM_BACK_RIGHT', + ] + lyft_infos = mmcv.load(info_path)['infos'] + lyft = Lyft( + data_path=osp.join(root_path, version), + json_path=osp.join(root_path, version, version), + verbose=True) + # info_2d_list = [] + cat2Ids = [ + dict(id=lyft_categories.index(cat_name), name=cat_name) + for cat_name in lyft_categories + ] + coco_ann_id = 0 + coco_2d_dict = dict(annotations=[], images=[], categories=cat2Ids) + for info in mmcv.track_iter_progress(lyft_infos): + for cam in camera_types: + cam_info = info['cams'][cam] + coco_infos = get_2d_boxes( + lyft, + cam_info['sample_data_token'], + visibilities=['', '1', '2', '3', '4']) + (height, width, _) = mmcv.imread(cam_info['data_path']).shape + coco_2d_dict['images'].append( + dict( + file_name=cam_info['data_path'], + id=cam_info['sample_data_token'], + width=width, + height=height)) + for coco_info in coco_infos: + if coco_info is None: + continue + # add an empty key for coco format + coco_info['segmentation'] = [] + coco_info['id'] = coco_ann_id + coco_2d_dict['annotations'].append(coco_info) + coco_ann_id += 1 + mmcv.dump(coco_2d_dict, f'{info_path[:-4]}.coco.json') diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_data_fixer.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_data_fixer.py new file mode 100644 index 00000000..55103515 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/lyft_data_fixer.py @@ -0,0 +1,39 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import os + +import numpy as np + + +def fix_lyft(root_folder='./data/lyft', version='v1.01'): + # refer to https://www.kaggle.com/c/3d-object-detection-for-autonomous-vehicles/discussion/110000 # noqa + lidar_path = 'lidar/host-a011_lidar1_1233090652702363606.bin' + root_folder = os.path.join(root_folder, f'{version}-train') + lidar_path = os.path.join(root_folder, lidar_path) + assert os.path.isfile(lidar_path), f'Please download the complete Lyft ' \ + f'dataset and make sure {lidar_path} is present.' + points = np.fromfile(lidar_path, dtype=np.float32, count=-1) + try: + points.reshape([-1, 5]) + print(f'This fix is not required for version {version}.') + except ValueError: + new_points = np.array(list(points) + [100.0, 1.0], dtype='float32') + new_points.tofile(lidar_path) + print(f'Appended 100.0 and 1.0 to the end of {lidar_path}.') + + +parser = argparse.ArgumentParser(description='Lyft dataset fixer arg parser') +parser.add_argument( + '--root-folder', + type=str, + default='./data/lyft', + help='specify the root path of Lyft dataset') +parser.add_argument( + '--version', + type=str, + default='v1.01', + help='specify Lyft dataset version') +args = parser.parse_args() + +if __name__ == '__main__': + fix_lyft(root_folder=args.root_folder, version=args.version) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuimage_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuimage_converter.py new file mode 100644 index 00000000..a46015a1 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuimage_converter.py @@ -0,0 +1,226 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import base64 +from os import path as osp + +import mmcv +import numpy as np +from nuimages import NuImages +from nuimages.utils.utils import mask_decode, name_to_index_mapping + +nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle', + 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', + 'barrier') + +NAME_MAPPING = { + 'movable_object.barrier': 'barrier', + 'vehicle.bicycle': 'bicycle', + 'vehicle.bus.bendy': 'bus', + 'vehicle.bus.rigid': 'bus', + 'vehicle.car': 'car', + 'vehicle.construction': 'construction_vehicle', + 'vehicle.motorcycle': 'motorcycle', + 'human.pedestrian.adult': 'pedestrian', + 'human.pedestrian.child': 'pedestrian', + 'human.pedestrian.construction_worker': 'pedestrian', + 'human.pedestrian.police_officer': 'pedestrian', + 'movable_object.trafficcone': 'traffic_cone', + 'vehicle.trailer': 'trailer', + 'vehicle.truck': 'truck', +} + + +def parse_args(): + parser = argparse.ArgumentParser(description='Data converter arg parser') + parser.add_argument( + '--data-root', + type=str, + default='./data/nuimages', + help='specify the root path of dataset') + parser.add_argument( + '--version', + type=str, + nargs='+', + default=['v1.0-mini'], + required=False, + help='specify the dataset version') + parser.add_argument( + '--out-dir', + type=str, + default='./data/nuimages/annotations/', + required=False, + help='path to save the exported json') + parser.add_argument( + '--nproc', + type=int, + default=4, + required=False, + help='workers to process semantic masks') + parser.add_argument('--extra-tag', type=str, default='nuimages') + args = parser.parse_args() + return args + + +def get_img_annos(nuim, img_info, cat2id, out_dir, data_root, seg_root): + """Get semantic segmentation map for an image. + + Args: + nuim (obj:`NuImages`): NuImages dataset object + img_info (dict): Meta information of img + + Returns: + np.ndarray: Semantic segmentation map of the image + """ + sd_token = img_info['token'] + image_id = img_info['id'] + name_to_index = name_to_index_mapping(nuim.category) + + # Get image data. + width, height = img_info['width'], img_info['height'] + semseg_mask = np.zeros((height, width)).astype('uint8') + + # Load stuff / surface regions. + surface_anns = [ + o for o in nuim.surface_ann if o['sample_data_token'] == sd_token + ] + + # Draw stuff / surface regions. + for ann in surface_anns: + # Get color and mask. + category_token = ann['category_token'] + category_name = nuim.get('category', category_token)['name'] + if ann['mask'] is None: + continue + mask = mask_decode(ann['mask']) + + # Draw mask for semantic segmentation. + semseg_mask[mask == 1] = name_to_index[category_name] + + # Load object instances. + object_anns = [ + o for o in nuim.object_ann if o['sample_data_token'] == sd_token + ] + + # Sort by token to ensure that objects always appear in the + # instance mask in the same order. + object_anns = sorted(object_anns, key=lambda k: k['token']) + + # Draw object instances. + # The 0 index is reserved for background; thus, the instances + # should start from index 1. + annotations = [] + for i, ann in enumerate(object_anns, start=1): + # Get color, box, mask and name. + category_token = ann['category_token'] + category_name = nuim.get('category', category_token)['name'] + if ann['mask'] is None: + continue + mask = mask_decode(ann['mask']) + + # Draw masks for semantic segmentation and instance segmentation. + semseg_mask[mask == 1] = name_to_index[category_name] + + if category_name in NAME_MAPPING: + cat_name = NAME_MAPPING[category_name] + cat_id = cat2id[cat_name] + + x_min, y_min, x_max, y_max = ann['bbox'] + # encode calibrated instance mask + mask_anno = dict() + mask_anno['counts'] = base64.b64decode( + ann['mask']['counts']).decode() + mask_anno['size'] = ann['mask']['size'] + + data_anno = dict( + image_id=image_id, + category_id=cat_id, + bbox=[x_min, y_min, x_max - x_min, y_max - y_min], + area=(x_max - x_min) * (y_max - y_min), + segmentation=mask_anno, + iscrowd=0) + annotations.append(data_anno) + + # after process, save semantic masks + img_filename = img_info['file_name'] + seg_filename = img_filename.replace('jpg', 'png') + seg_filename = osp.join(seg_root, seg_filename) + mmcv.imwrite(semseg_mask, seg_filename) + return annotations, np.max(semseg_mask) + + +def export_nuim_to_coco(nuim, data_root, out_dir, extra_tag, version, nproc): + print('Process category information') + categories = [] + categories = [ + dict(id=nus_categories.index(cat_name), name=cat_name) + for cat_name in nus_categories + ] + cat2id = {k_v['name']: k_v['id'] for k_v in categories} + + images = [] + print('Process image meta information...') + for sample_info in mmcv.track_iter_progress(nuim.sample_data): + if sample_info['is_key_frame']: + img_idx = len(images) + images.append( + dict( + id=img_idx, + token=sample_info['token'], + file_name=sample_info['filename'], + width=sample_info['width'], + height=sample_info['height'])) + + seg_root = f'{out_dir}semantic_masks' + mmcv.mkdir_or_exist(seg_root) + mmcv.mkdir_or_exist(osp.join(data_root, 'calibrated')) + + global process_img_anno + + def process_img_anno(img_info): + single_img_annos, max_cls_id = get_img_annos(nuim, img_info, cat2id, + out_dir, data_root, + seg_root) + return single_img_annos, max_cls_id + + print('Process img annotations...') + if nproc > 1: + outputs = mmcv.track_parallel_progress( + process_img_anno, images, nproc=nproc) + else: + outputs = [] + for img_info in mmcv.track_iter_progress(images): + outputs.append(process_img_anno(img_info)) + + # Determine the index of object annotation + print('Process annotation information...') + annotations = [] + max_cls_ids = [] + for single_img_annos, max_cls_id in outputs: + max_cls_ids.append(max_cls_id) + for img_anno in single_img_annos: + img_anno.update(id=len(annotations)) + annotations.append(img_anno) + + max_cls_id = max(max_cls_ids) + print(f'Max ID of class in the semantic map: {max_cls_id}') + + coco_format_json = dict( + images=images, annotations=annotations, categories=categories) + + mmcv.mkdir_or_exist(out_dir) + out_file = osp.join(out_dir, f'{extra_tag}_{version}.json') + print(f'Annotation dumped to {out_file}') + mmcv.dump(coco_format_json, out_file) + + +def main(): + args = parse_args() + for version in args.version: + nuim = NuImages( + dataroot=args.data_root, version=version, verbose=True, lazy=True) + export_nuim_to_coco(nuim, args.data_root, args.out_dir, args.extra_tag, + version, args.nproc) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuscenes_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuscenes_converter.py new file mode 100644 index 00000000..c6140fcc --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/nuscenes_converter.py @@ -0,0 +1,628 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import os +from collections import OrderedDict +from os import path as osp +from typing import List, Tuple, Union + +import mmcv +import numpy as np +from nuscenes.nuscenes import NuScenes +from nuscenes.utils.geometry_utils import view_points +from pyquaternion import Quaternion +from shapely.geometry import MultiPoint, box + +from mmdet3d.core.bbox import points_cam2img +from mmdet3d.datasets import NuScenesDataset + +nus_categories = ('car', 'truck', 'trailer', 'bus', 'construction_vehicle', + 'bicycle', 'motorcycle', 'pedestrian', 'traffic_cone', + 'barrier') + +nus_attributes = ('cycle.with_rider', 'cycle.without_rider', + 'pedestrian.moving', 'pedestrian.standing', + 'pedestrian.sitting_lying_down', 'vehicle.moving', + 'vehicle.parked', 'vehicle.stopped', 'None') + + +def create_nuscenes_infos(root_path, + info_prefix, + version='v1.0-trainval', + max_sweeps=10): + """Create info file of nuscene dataset. + + Given the raw data, generate its related info file in pkl format. + + Args: + root_path (str): Path of the data root. + info_prefix (str): Prefix of the info file to be generated. + version (str, optional): Version of the data. + Default: 'v1.0-trainval'. + max_sweeps (int, optional): Max number of sweeps. + Default: 10. + """ + from nuscenes.nuscenes import NuScenes + nusc = NuScenes(version=version, dataroot=root_path, verbose=True) + from nuscenes.utils import splits + available_vers = ['v1.0-trainval', 'v1.0-test', 'v1.0-mini'] + assert version in available_vers + if version == 'v1.0-trainval': + train_scenes = splits.train + val_scenes = splits.val + elif version == 'v1.0-test': + train_scenes = splits.test + val_scenes = [] + elif version == 'v1.0-mini': + train_scenes = splits.mini_train + val_scenes = splits.mini_val + else: + raise ValueError('unknown') + + # filter existing scenes. + available_scenes = get_available_scenes(nusc) + available_scene_names = [s['name'] for s in available_scenes] + train_scenes = list( + filter(lambda x: x in available_scene_names, train_scenes)) + val_scenes = list(filter(lambda x: x in available_scene_names, val_scenes)) + train_scenes = set([ + available_scenes[available_scene_names.index(s)]['token'] + for s in train_scenes + ]) + val_scenes = set([ + available_scenes[available_scene_names.index(s)]['token'] + for s in val_scenes + ]) + + test = 'test' in version + if test: + print('test scene: {}'.format(len(train_scenes))) + else: + print('train scene: {}, val scene: {}'.format( + len(train_scenes), len(val_scenes))) + train_nusc_infos, val_nusc_infos = _fill_trainval_infos( + nusc, train_scenes, val_scenes, test, max_sweeps=max_sweeps) + + metadata = dict(version=version) + if test: + print('test sample: {}'.format(len(train_nusc_infos))) + data = dict(infos=train_nusc_infos, metadata=metadata) + info_path = osp.join(root_path, + '{}_infos_test.pkl'.format(info_prefix)) + mmcv.dump(data, info_path) + else: + print('train sample: {}, val sample: {}'.format( + len(train_nusc_infos), len(val_nusc_infos))) + data = dict(infos=train_nusc_infos, metadata=metadata) + info_path = osp.join(root_path, + '{}_infos_train.pkl'.format(info_prefix)) + mmcv.dump(data, info_path) + data['infos'] = val_nusc_infos + info_val_path = osp.join(root_path, + '{}_infos_val.pkl'.format(info_prefix)) + mmcv.dump(data, info_val_path) + + +def get_available_scenes(nusc): + """Get available scenes from the input nuscenes class. + + Given the raw data, get the information of available scenes for + further info generation. + + Args: + nusc (class): Dataset class in the nuScenes dataset. + + Returns: + available_scenes (list[dict]): List of basic information for the + available scenes. + """ + available_scenes = [] + print('total scene num: {}'.format(len(nusc.scene))) + for scene in nusc.scene: + scene_token = scene['token'] + scene_rec = nusc.get('scene', scene_token) + sample_rec = nusc.get('sample', scene_rec['first_sample_token']) + sd_rec = nusc.get('sample_data', sample_rec['data']['LIDAR_TOP']) + has_more_frames = True + scene_not_exist = False + while has_more_frames: + lidar_path, boxes, _ = nusc.get_sample_data(sd_rec['token']) + lidar_path = str(lidar_path) + if os.getcwd() in lidar_path: + # path from lyftdataset is absolute path + lidar_path = lidar_path.split(f'{os.getcwd()}/')[-1] + # relative path + if not mmcv.is_filepath(lidar_path): + scene_not_exist = True + break + else: + break + if scene_not_exist: + continue + available_scenes.append(scene) + print('exist scene num: {}'.format(len(available_scenes))) + return available_scenes + + +def _fill_trainval_infos(nusc, + train_scenes, + val_scenes, + test=False, + max_sweeps=10): + """Generate the train/val infos from the raw data. + + Args: + nusc (:obj:`NuScenes`): Dataset class in the nuScenes dataset. + train_scenes (list[str]): Basic information of training scenes. + val_scenes (list[str]): Basic information of validation scenes. + test (bool, optional): Whether use the test mode. In test mode, no + annotations can be accessed. Default: False. + max_sweeps (int, optional): Max number of sweeps. Default: 10. + + Returns: + tuple[list[dict]]: Information of training set and validation set + that will be saved to the info file. + """ + train_nusc_infos = [] + val_nusc_infos = [] + + for sample in mmcv.track_iter_progress(nusc.sample): + lidar_token = sample['data']['LIDAR_TOP'] + sd_rec = nusc.get('sample_data', sample['data']['LIDAR_TOP']) + cs_record = nusc.get('calibrated_sensor', + sd_rec['calibrated_sensor_token']) + pose_record = nusc.get('ego_pose', sd_rec['ego_pose_token']) + lidar_path, boxes, _ = nusc.get_sample_data(lidar_token) + + mmcv.check_file_exist(lidar_path) + + info = { + 'lidar_path': lidar_path, + 'token': sample['token'], + 'sweeps': [], + 'cams': dict(), + 'lidar2ego_translation': cs_record['translation'], + 'lidar2ego_rotation': cs_record['rotation'], + 'ego2global_translation': pose_record['translation'], + 'ego2global_rotation': pose_record['rotation'], + 'timestamp': sample['timestamp'], + } + + l2e_r = info['lidar2ego_rotation'] + l2e_t = info['lidar2ego_translation'] + e2g_r = info['ego2global_rotation'] + e2g_t = info['ego2global_translation'] + l2e_r_mat = Quaternion(l2e_r).rotation_matrix + e2g_r_mat = Quaternion(e2g_r).rotation_matrix + + # obtain 6 image's information per frame + camera_types = [ + 'CAM_FRONT', + 'CAM_FRONT_RIGHT', + 'CAM_FRONT_LEFT', + 'CAM_BACK', + 'CAM_BACK_LEFT', + 'CAM_BACK_RIGHT', + ] + for cam in camera_types: + cam_token = sample['data'][cam] + cam_path, _, cam_intrinsic = nusc.get_sample_data(cam_token) + cam_info = obtain_sensor2top(nusc, cam_token, l2e_t, l2e_r_mat, + e2g_t, e2g_r_mat, cam) + cam_info.update(cam_intrinsic=cam_intrinsic) + info['cams'].update({cam: cam_info}) + + # obtain sweeps for a single key-frame + sd_rec = nusc.get('sample_data', sample['data']['LIDAR_TOP']) + sweeps = [] + while len(sweeps) < max_sweeps: + if not sd_rec['prev'] == '': + sweep = obtain_sensor2top(nusc, sd_rec['prev'], l2e_t, + l2e_r_mat, e2g_t, e2g_r_mat, 'lidar') + sweeps.append(sweep) + sd_rec = nusc.get('sample_data', sd_rec['prev']) + else: + break + info['sweeps'] = sweeps + # obtain annotation + if not test: + annotations = [ + nusc.get('sample_annotation', token) + for token in sample['anns'] + ] + locs = np.array([b.center for b in boxes]).reshape(-1, 3) + dims = np.array([b.wlh for b in boxes]).reshape(-1, 3) + rots = np.array([b.orientation.yaw_pitch_roll[0] + for b in boxes]).reshape(-1, 1) + velocity = np.array( + [nusc.box_velocity(token)[:2] for token in sample['anns']]) + valid_flag = np.array( + [(anno['num_lidar_pts'] + anno['num_radar_pts']) > 0 + for anno in annotations], + dtype=bool).reshape(-1) + # convert velo from global to lidar + for i in range(len(boxes)): + velo = np.array([*velocity[i], 0.0]) + velo = velo @ np.linalg.inv(e2g_r_mat).T @ np.linalg.inv( + l2e_r_mat).T + velocity[i] = velo[:2] + + names = [b.name for b in boxes] + for i in range(len(names)): + if names[i] in NuScenesDataset.NameMapping: + names[i] = NuScenesDataset.NameMapping[names[i]] + names = np.array(names) + # we need to convert box size to + # the format of our lidar coordinate system + # which is x_size, y_size, z_size (corresponding to l, w, h) + gt_boxes = np.concatenate([locs, dims[:, [1, 0, 2]], rots], axis=1) + assert len(gt_boxes) == len( + annotations), f'{len(gt_boxes)}, {len(annotations)}' + info['gt_boxes'] = gt_boxes + info['gt_names'] = names + info['gt_velocity'] = velocity.reshape(-1, 2) + info['num_lidar_pts'] = np.array( + [a['num_lidar_pts'] for a in annotations]) + info['num_radar_pts'] = np.array( + [a['num_radar_pts'] for a in annotations]) + info['valid_flag'] = valid_flag + + if sample['scene_token'] in train_scenes: + train_nusc_infos.append(info) + else: + val_nusc_infos.append(info) + + return train_nusc_infos, val_nusc_infos + + +def obtain_sensor2top(nusc, + sensor_token, + l2e_t, + l2e_r_mat, + e2g_t, + e2g_r_mat, + sensor_type='lidar'): + """Obtain the info with RT matric from general sensor to Top LiDAR. + + Args: + nusc (class): Dataset class in the nuScenes dataset. + sensor_token (str): Sample data token corresponding to the + specific sensor type. + l2e_t (np.ndarray): Translation from lidar to ego in shape (1, 3). + l2e_r_mat (np.ndarray): Rotation matrix from lidar to ego + in shape (3, 3). + e2g_t (np.ndarray): Translation from ego to global in shape (1, 3). + e2g_r_mat (np.ndarray): Rotation matrix from ego to global + in shape (3, 3). + sensor_type (str, optional): Sensor to calibrate. Default: 'lidar'. + + Returns: + sweep (dict): Sweep information after transformation. + """ + sd_rec = nusc.get('sample_data', sensor_token) + cs_record = nusc.get('calibrated_sensor', + sd_rec['calibrated_sensor_token']) + pose_record = nusc.get('ego_pose', sd_rec['ego_pose_token']) + data_path = str(nusc.get_sample_data_path(sd_rec['token'])) + if os.getcwd() in data_path: # path from lyftdataset is absolute path + data_path = data_path.split(f'{os.getcwd()}/')[-1] # relative path + sweep = { + 'data_path': data_path, + 'type': sensor_type, + 'sample_data_token': sd_rec['token'], + 'sensor2ego_translation': cs_record['translation'], + 'sensor2ego_rotation': cs_record['rotation'], + 'ego2global_translation': pose_record['translation'], + 'ego2global_rotation': pose_record['rotation'], + 'timestamp': sd_rec['timestamp'] + } + l2e_r_s = sweep['sensor2ego_rotation'] + l2e_t_s = sweep['sensor2ego_translation'] + e2g_r_s = sweep['ego2global_rotation'] + e2g_t_s = sweep['ego2global_translation'] + + # obtain the RT from sensor to Top LiDAR + # sweep->ego->global->ego'->lidar + l2e_r_s_mat = Quaternion(l2e_r_s).rotation_matrix + e2g_r_s_mat = Quaternion(e2g_r_s).rotation_matrix + R = (l2e_r_s_mat.T @ e2g_r_s_mat.T) @ ( + np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) + T = (l2e_t_s @ e2g_r_s_mat.T + e2g_t_s) @ ( + np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T) + T -= e2g_t @ (np.linalg.inv(e2g_r_mat).T @ np.linalg.inv(l2e_r_mat).T + ) + l2e_t @ np.linalg.inv(l2e_r_mat).T + sweep['sensor2lidar_rotation'] = R.T # points @ R.T + T + sweep['sensor2lidar_translation'] = T + return sweep + + +def export_2d_annotation(root_path, info_path, version, mono3d=True): + """Export 2d annotation from the info file and raw data. + + Args: + root_path (str): Root path of the raw data. + info_path (str): Path of the info file. + version (str): Dataset version. + mono3d (bool, optional): Whether to export mono3d annotation. + Default: True. + """ + # get bbox annotations for camera + camera_types = [ + 'CAM_FRONT', + 'CAM_FRONT_RIGHT', + 'CAM_FRONT_LEFT', + 'CAM_BACK', + 'CAM_BACK_LEFT', + 'CAM_BACK_RIGHT', + ] + nusc_infos = mmcv.load(info_path)['infos'] + nusc = NuScenes(version=version, dataroot=root_path, verbose=True) + # info_2d_list = [] + cat2Ids = [ + dict(id=nus_categories.index(cat_name), name=cat_name) + for cat_name in nus_categories + ] + coco_ann_id = 0 + coco_2d_dict = dict(annotations=[], images=[], categories=cat2Ids) + for info in mmcv.track_iter_progress(nusc_infos): + for cam in camera_types: + cam_info = info['cams'][cam] + coco_infos = get_2d_boxes( + nusc, + cam_info['sample_data_token'], + visibilities=['', '1', '2', '3', '4'], + mono3d=mono3d) + (height, width, _) = mmcv.imread(cam_info['data_path']).shape + coco_2d_dict['images'].append( + dict( + file_name=cam_info['data_path'].split('data/nuscenes/') + [-1], + id=cam_info['sample_data_token'], + token=info['token'], + cam2ego_rotation=cam_info['sensor2ego_rotation'], + cam2ego_translation=cam_info['sensor2ego_translation'], + ego2global_rotation=info['ego2global_rotation'], + ego2global_translation=info['ego2global_translation'], + cam_intrinsic=cam_info['cam_intrinsic'], + width=width, + height=height)) + for coco_info in coco_infos: + if coco_info is None: + continue + # add an empty key for coco format + coco_info['segmentation'] = [] + coco_info['id'] = coco_ann_id + coco_2d_dict['annotations'].append(coco_info) + coco_ann_id += 1 + if mono3d: + json_prefix = f'{info_path[:-4]}_mono3d' + else: + json_prefix = f'{info_path[:-4]}' + mmcv.dump(coco_2d_dict, f'{json_prefix}.coco.json') + + +def get_2d_boxes(nusc, + sample_data_token: str, + visibilities: List[str], + mono3d=True): + """Get the 2D annotation records for a given `sample_data_token`. + + Args: + sample_data_token (str): Sample data token belonging to a camera + keyframe. + visibilities (list[str]): Visibility filter. + mono3d (bool): Whether to get boxes with mono3d annotation. + + Return: + list[dict]: List of 2D annotation record that belongs to the input + `sample_data_token`. + """ + + # Get the sample data and the sample corresponding to that sample data. + sd_rec = nusc.get('sample_data', sample_data_token) + + assert sd_rec[ + 'sensor_modality'] == 'camera', 'Error: get_2d_boxes only works' \ + ' for camera sample_data!' + if not sd_rec['is_key_frame']: + raise ValueError( + 'The 2D re-projections are available only for keyframes.') + + s_rec = nusc.get('sample', sd_rec['sample_token']) + + # Get the calibrated sensor and ego pose + # record to get the transformation matrices. + cs_rec = nusc.get('calibrated_sensor', sd_rec['calibrated_sensor_token']) + pose_rec = nusc.get('ego_pose', sd_rec['ego_pose_token']) + camera_intrinsic = np.array(cs_rec['camera_intrinsic']) + + # Get all the annotation with the specified visibilties. + ann_recs = [ + nusc.get('sample_annotation', token) for token in s_rec['anns'] + ] + ann_recs = [ + ann_rec for ann_rec in ann_recs + if (ann_rec['visibility_token'] in visibilities) + ] + + repro_recs = [] + + for ann_rec in ann_recs: + # Augment sample_annotation with token information. + ann_rec['sample_annotation_token'] = ann_rec['token'] + ann_rec['sample_data_token'] = sample_data_token + + # Get the box in global coordinates. + box = nusc.get_box(ann_rec['token']) + + # Move them to the ego-pose frame. + box.translate(-np.array(pose_rec['translation'])) + box.rotate(Quaternion(pose_rec['rotation']).inverse) + + # Move them to the calibrated sensor frame. + box.translate(-np.array(cs_rec['translation'])) + box.rotate(Quaternion(cs_rec['rotation']).inverse) + + # Filter out the corners that are not in front of the calibrated + # sensor. + corners_3d = box.corners() + in_front = np.argwhere(corners_3d[2, :] > 0).flatten() + corners_3d = corners_3d[:, in_front] + + # Project 3d box to 2d. + corner_coords = view_points(corners_3d, camera_intrinsic, + True).T[:, :2].tolist() + + # Keep only corners that fall within the image. + final_coords = post_process_coords(corner_coords) + + # Skip if the convex hull of the re-projected corners + # does not intersect the image canvas. + if final_coords is None: + continue + else: + min_x, min_y, max_x, max_y = final_coords + + # Generate dictionary record to be included in the .json file. + repro_rec = generate_record(ann_rec, min_x, min_y, max_x, max_y, + sample_data_token, sd_rec['filename']) + + # If mono3d=True, add 3D annotations in camera coordinates + if mono3d and (repro_rec is not None): + loc = box.center.tolist() + + dim = box.wlh + dim[[0, 1, 2]] = dim[[1, 2, 0]] # convert wlh to our lhw + dim = dim.tolist() + + rot = box.orientation.yaw_pitch_roll[0] + rot = [-rot] # convert the rot to our cam coordinate + + global_velo2d = nusc.box_velocity(box.token)[:2] + global_velo3d = np.array([*global_velo2d, 0.0]) + e2g_r_mat = Quaternion(pose_rec['rotation']).rotation_matrix + c2e_r_mat = Quaternion(cs_rec['rotation']).rotation_matrix + cam_velo3d = global_velo3d @ np.linalg.inv( + e2g_r_mat).T @ np.linalg.inv(c2e_r_mat).T + velo = cam_velo3d[0::2].tolist() + + repro_rec['bbox_cam3d'] = loc + dim + rot + repro_rec['velo_cam3d'] = velo + + center3d = np.array(loc).reshape([1, 3]) + center2d = points_cam2img( + center3d, camera_intrinsic, with_depth=True) + repro_rec['center2d'] = center2d.squeeze().tolist() + # normalized center2D + depth + # if samples with depth < 0 will be removed + if repro_rec['center2d'][2] <= 0: + continue + + ann_token = nusc.get('sample_annotation', + box.token)['attribute_tokens'] + if len(ann_token) == 0: + attr_name = 'None' + else: + attr_name = nusc.get('attribute', ann_token[0])['name'] + attr_id = nus_attributes.index(attr_name) + repro_rec['attribute_name'] = attr_name + repro_rec['attribute_id'] = attr_id + + repro_recs.append(repro_rec) + + return repro_recs + + +def post_process_coords( + corner_coords: List, imsize: Tuple[int, int] = (1600, 900) +) -> Union[Tuple[float, float, float, float], None]: + """Get the intersection of the convex hull of the reprojected bbox corners + and the image canvas, return None if no intersection. + + Args: + corner_coords (list[int]): Corner coordinates of reprojected + bounding box. + imsize (tuple[int]): Size of the image canvas. + + Return: + tuple [float]: Intersection of the convex hull of the 2D box + corners and the image canvas. + """ + polygon_from_2d_box = MultiPoint(corner_coords).convex_hull + img_canvas = box(0, 0, imsize[0], imsize[1]) + + if polygon_from_2d_box.intersects(img_canvas): + img_intersection = polygon_from_2d_box.intersection(img_canvas) + intersection_coords = np.array( + [coord for coord in img_intersection.exterior.coords]) + + min_x = min(intersection_coords[:, 0]) + min_y = min(intersection_coords[:, 1]) + max_x = max(intersection_coords[:, 0]) + max_y = max(intersection_coords[:, 1]) + + return min_x, min_y, max_x, max_y + else: + return None + + +def generate_record(ann_rec: dict, x1: float, y1: float, x2: float, y2: float, + sample_data_token: str, filename: str) -> OrderedDict: + """Generate one 2D annotation record given various information on top of + the 2D bounding box coordinates. + + Args: + ann_rec (dict): Original 3d annotation record. + x1 (float): Minimum value of the x coordinate. + y1 (float): Minimum value of the y coordinate. + x2 (float): Maximum value of the x coordinate. + y2 (float): Maximum value of the y coordinate. + sample_data_token (str): Sample data token. + filename (str):The corresponding image file where the annotation + is present. + + Returns: + dict: A sample 2D annotation record. + - file_name (str): file name + - image_id (str): sample data token + - area (float): 2d box area + - category_name (str): category name + - category_id (int): category id + - bbox (list[float]): left x, top y, dx, dy of 2d box + - iscrowd (int): whether the area is crowd + """ + repro_rec = OrderedDict() + repro_rec['sample_data_token'] = sample_data_token + coco_rec = dict() + + relevant_keys = [ + 'attribute_tokens', + 'category_name', + 'instance_token', + 'next', + 'num_lidar_pts', + 'num_radar_pts', + 'prev', + 'sample_annotation_token', + 'sample_data_token', + 'visibility_token', + ] + + for key, value in ann_rec.items(): + if key in relevant_keys: + repro_rec[key] = value + + repro_rec['bbox_corners'] = [x1, y1, x2, y2] + repro_rec['filename'] = filename + + coco_rec['file_name'] = filename + coco_rec['image_id'] = sample_data_token + coco_rec['area'] = (y2 - y1) * (x2 - x1) + + if repro_rec['category_name'] not in NuScenesDataset.NameMapping: + return None + cat_name = NuScenesDataset.NameMapping[repro_rec['category_name']] + coco_rec['category_name'] = cat_name + coco_rec['category_id'] = nus_categories.index(cat_name) + coco_rec['bbox'] = [x1, y1, x2 - x1, y2 - y1] + coco_rec['iscrowd'] = 0 + + return coco_rec diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/s3dis_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/s3dis_data_utils.py new file mode 100644 index 00000000..48f37882 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/s3dis_data_utils.py @@ -0,0 +1,245 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import os +from concurrent import futures as futures +from os import path as osp + +import mmcv +import numpy as np + + +class S3DISData(object): + """S3DIS data. + + Generate s3dis infos for s3dis_converter. + + Args: + root_path (str): Root path of the raw data. + split (str, optional): Set split type of the data. Default: 'Area_1'. + """ + + def __init__(self, root_path, split='Area_1'): + self.root_dir = root_path + self.split = split + self.data_dir = osp.join(root_path, + 'Stanford3dDataset_v1.2_Aligned_Version') + + # Following `GSDN `_, use 5 furniture + # classes for detection: table, chair, sofa, bookcase, board. + self.cat_ids = np.array([7, 8, 9, 10, 11]) + self.cat_ids2class = { + cat_id: i + for i, cat_id in enumerate(list(self.cat_ids)) + } + + assert split in [ + 'Area_1', 'Area_2', 'Area_3', 'Area_4', 'Area_5', 'Area_6' + ] + self.sample_id_list = os.listdir(osp.join(self.data_dir, + split)) # conferenceRoom_1 + for sample_id in self.sample_id_list: + if os.path.isfile(osp.join(self.data_dir, split, sample_id)): + self.sample_id_list.remove(sample_id) + + def __len__(self): + return len(self.sample_id_list) + + def get_infos(self, num_workers=4, has_label=True, sample_id_list=None): + """Get data infos. + + This method gets information from the raw data. + + Args: + num_workers (int, optional): Number of threads to be used. + Default: 4. + has_label (bool, optional): Whether the data has label. + Default: True. + sample_id_list (list[int], optional): Index list of the sample. + Default: None. + + Returns: + infos (list[dict]): Information of the raw data. + """ + + def process_single_scene(sample_idx): + print(f'{self.split} sample_idx: {sample_idx}') + info = dict() + pc_info = { + 'num_features': 6, + 'lidar_idx': f'{self.split}_{sample_idx}' + } + info['point_cloud'] = pc_info + pts_filename = osp.join(self.root_dir, 's3dis_data', + f'{self.split}_{sample_idx}_point.npy') + pts_instance_mask_path = osp.join( + self.root_dir, 's3dis_data', + f'{self.split}_{sample_idx}_ins_label.npy') + pts_semantic_mask_path = osp.join( + self.root_dir, 's3dis_data', + f'{self.split}_{sample_idx}_sem_label.npy') + + points = np.load(pts_filename).astype(np.float32) + pts_instance_mask = np.load(pts_instance_mask_path).astype(np.int) + pts_semantic_mask = np.load(pts_semantic_mask_path).astype(np.int) + + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'points')) + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'instance_mask')) + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'semantic_mask')) + + points.tofile( + osp.join(self.root_dir, 'points', + f'{self.split}_{sample_idx}.bin')) + pts_instance_mask.tofile( + osp.join(self.root_dir, 'instance_mask', + f'{self.split}_{sample_idx}.bin')) + pts_semantic_mask.tofile( + osp.join(self.root_dir, 'semantic_mask', + f'{self.split}_{sample_idx}.bin')) + + info['pts_path'] = osp.join('points', + f'{self.split}_{sample_idx}.bin') + info['pts_instance_mask_path'] = osp.join( + 'instance_mask', f'{self.split}_{sample_idx}.bin') + info['pts_semantic_mask_path'] = osp.join( + 'semantic_mask', f'{self.split}_{sample_idx}.bin') + info['annos'] = self.get_bboxes(points, pts_instance_mask, + pts_semantic_mask) + + return info + + sample_id_list = sample_id_list if sample_id_list is not None \ + else self.sample_id_list + with futures.ThreadPoolExecutor(num_workers) as executor: + infos = executor.map(process_single_scene, sample_id_list) + return list(infos) + + def get_bboxes(self, points, pts_instance_mask, pts_semantic_mask): + """Convert instance masks to axis-aligned bounding boxes. + + Args: + points (np.array): Scene points of shape (n, 6). + pts_instance_mask (np.ndarray): Instance labels of shape (n,). + pts_semantic_mask (np.ndarray): Semantic labels of shape (n,). + + Returns: + dict: A dict containing detection infos with following keys: + + - gt_boxes_upright_depth (np.ndarray): Bounding boxes + of shape (n, 6) + - class (np.ndarray): Box labels of shape (n,) + - gt_num (int): Number of boxes. + """ + bboxes, labels = [], [] + for i in range(1, pts_instance_mask.max() + 1): + ids = pts_instance_mask == i + # check if all instance points have same semantic label + assert pts_semantic_mask[ids].min() == pts_semantic_mask[ids].max() + label = pts_semantic_mask[ids][0] + # keep only furniture objects + if label in self.cat_ids2class: + labels.append(self.cat_ids2class[pts_semantic_mask[ids][0]]) + pts = points[:, :3][ids] + min_pts = pts.min(axis=0) + max_pts = pts.max(axis=0) + locations = (min_pts + max_pts) / 2 + dimensions = max_pts - min_pts + bboxes.append(np.concatenate((locations, dimensions))) + annotation = dict() + # follow ScanNet and SUN RGB-D keys + annotation['gt_boxes_upright_depth'] = np.array(bboxes) + annotation['class'] = np.array(labels) + annotation['gt_num'] = len(labels) + return annotation + + +class S3DISSegData(object): + """S3DIS dataset used to generate infos for semantic segmentation task. + + Args: + data_root (str): Root path of the raw data. + ann_file (str): The generated scannet infos. + split (str, optional): Set split type of the data. Default: 'train'. + num_points (int, optional): Number of points in each data input. + Default: 8192. + label_weight_func (function, optional): Function to compute the + label weight. Default: None. + """ + + def __init__(self, + data_root, + ann_file, + split='Area_1', + num_points=4096, + label_weight_func=None): + self.data_root = data_root + self.data_infos = mmcv.load(ann_file) + self.split = split + self.num_points = num_points + + self.all_ids = np.arange(13) # all possible ids + self.cat_ids = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12]) # used for seg task + self.ignore_index = len(self.cat_ids) + + self.cat_id2class = np.ones((self.all_ids.shape[0],), dtype=np.int) * \ + self.ignore_index + for i, cat_id in enumerate(self.cat_ids): + self.cat_id2class[cat_id] = i + + # label weighting function is taken from + # https://github.com/charlesq34/pointnet2/blob/master/scannet/scannet_dataset.py#L24 + self.label_weight_func = (lambda x: 1.0 / np.log(1.2 + x)) if \ + label_weight_func is None else label_weight_func + + def get_seg_infos(self): + scene_idxs, label_weight = self.get_scene_idxs_and_label_weight() + save_folder = osp.join(self.data_root, 'seg_info') + mmcv.mkdir_or_exist(save_folder) + np.save( + osp.join(save_folder, f'{self.split}_resampled_scene_idxs.npy'), + scene_idxs) + np.save( + osp.join(save_folder, f'{self.split}_label_weight.npy'), + label_weight) + print(f'{self.split} resampled scene index and label weight saved') + + def _convert_to_label(self, mask): + """Convert class_id in loaded segmentation mask to label.""" + if isinstance(mask, str): + if mask.endswith('npy'): + mask = np.load(mask) + else: + mask = np.fromfile(mask, dtype=np.int64) + label = self.cat_id2class[mask] + return label + + def get_scene_idxs_and_label_weight(self): + """Compute scene_idxs for data sampling and label weight for loss + calculation. + + We sample more times for scenes with more points. Label_weight is + inversely proportional to number of class points. + """ + num_classes = len(self.cat_ids) + num_point_all = [] + label_weight = np.zeros((num_classes + 1, )) # ignore_index + for data_info in self.data_infos: + label = self._convert_to_label( + osp.join(self.data_root, data_info['pts_semantic_mask_path'])) + num_point_all.append(label.shape[0]) + class_count, _ = np.histogram(label, range(num_classes + 2)) + label_weight += class_count + + # repeat scene_idx for num_scene_point // num_sample_point times + sample_prob = np.array(num_point_all) / float(np.sum(num_point_all)) + num_iter = int(np.sum(num_point_all) / float(self.num_points)) + scene_idxs = [] + for idx in range(len(self.data_infos)): + scene_idxs.extend([idx] * int(round(sample_prob[idx] * num_iter))) + scene_idxs = np.array(scene_idxs).astype(np.int32) + + # calculate label weight, adopted from PointNet++ + label_weight = label_weight[:-1].astype(np.float32) + label_weight = label_weight / label_weight.sum() + label_weight = self.label_weight_func(label_weight).astype(np.float32) + + return scene_idxs, label_weight diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/scannet_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/scannet_data_utils.py new file mode 100644 index 00000000..085d401c --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/scannet_data_utils.py @@ -0,0 +1,297 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import os +from concurrent import futures as futures +from os import path as osp + +import mmcv +import numpy as np + + +class ScanNetData(object): + """ScanNet data. + + Generate scannet infos for scannet_converter. + + Args: + root_path (str): Root path of the raw data. + split (str, optional): Set split type of the data. Default: 'train'. + """ + + def __init__(self, root_path, split='train'): + self.root_dir = root_path + self.split = split + self.split_dir = osp.join(root_path) + self.classes = [ + 'cabinet', 'bed', 'chair', 'sofa', 'table', 'door', 'window', + 'bookshelf', 'picture', 'counter', 'desk', 'curtain', + 'refrigerator', 'showercurtrain', 'toilet', 'sink', 'bathtub', + 'garbagebin' + ] + self.cat2label = {cat: self.classes.index(cat) for cat in self.classes} + self.label2cat = {self.cat2label[t]: t for t in self.cat2label} + self.cat_ids = np.array( + [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34, 36, 39]) + self.cat_ids2class = { + nyu40id: i + for i, nyu40id in enumerate(list(self.cat_ids)) + } + assert split in ['train', 'val', 'test'] + split_file = osp.join(self.root_dir, 'meta_data', + f'scannetv2_{split}.txt') + mmcv.check_file_exist(split_file) + self.sample_id_list = mmcv.list_from_file(split_file) + self.test_mode = (split == 'test') + + def __len__(self): + return len(self.sample_id_list) + + def get_aligned_box_label(self, idx): + box_file = osp.join(self.root_dir, 'scannet_instance_data', + f'{idx}_aligned_bbox.npy') + mmcv.check_file_exist(box_file) + return np.load(box_file) + + def get_unaligned_box_label(self, idx): + box_file = osp.join(self.root_dir, 'scannet_instance_data', + f'{idx}_unaligned_bbox.npy') + mmcv.check_file_exist(box_file) + return np.load(box_file) + + def get_axis_align_matrix(self, idx): + matrix_file = osp.join(self.root_dir, 'scannet_instance_data', + f'{idx}_axis_align_matrix.npy') + mmcv.check_file_exist(matrix_file) + return np.load(matrix_file) + + def get_images(self, idx): + paths = [] + path = osp.join(self.root_dir, 'posed_images', idx) + for file in sorted(os.listdir(path)): + if file.endswith('.jpg'): + paths.append(osp.join('posed_images', idx, file)) + return paths + + def get_extrinsics(self, idx): + extrinsics = [] + path = osp.join(self.root_dir, 'posed_images', idx) + for file in sorted(os.listdir(path)): + if file.endswith('.txt') and not file == 'intrinsic.txt': + extrinsics.append(np.loadtxt(osp.join(path, file))) + return extrinsics + + def get_intrinsics(self, idx): + matrix_file = osp.join(self.root_dir, 'posed_images', idx, + 'intrinsic.txt') + mmcv.check_file_exist(matrix_file) + return np.loadtxt(matrix_file) + + def get_infos(self, num_workers=4, has_label=True, sample_id_list=None): + """Get data infos. + + This method gets information from the raw data. + + Args: + num_workers (int, optional): Number of threads to be used. + Default: 4. + has_label (bool, optional): Whether the data has label. + Default: True. + sample_id_list (list[int], optional): Index list of the sample. + Default: None. + + Returns: + infos (list[dict]): Information of the raw data. + """ + + def process_single_scene(sample_idx): + print(f'{self.split} sample_idx: {sample_idx}') + info = dict() + pc_info = {'num_features': 6, 'lidar_idx': sample_idx} + info['point_cloud'] = pc_info + pts_filename = osp.join(self.root_dir, 'scannet_instance_data', + f'{sample_idx}_vert.npy') + points = np.load(pts_filename) + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'points')) + points.tofile( + osp.join(self.root_dir, 'points', f'{sample_idx}.bin')) + info['pts_path'] = osp.join('points', f'{sample_idx}.bin') + + # update with RGB image paths if exist + if os.path.exists(osp.join(self.root_dir, 'posed_images')): + info['intrinsics'] = self.get_intrinsics(sample_idx) + all_extrinsics = self.get_extrinsics(sample_idx) + all_img_paths = self.get_images(sample_idx) + # some poses in ScanNet are invalid + extrinsics, img_paths = [], [] + for extrinsic, img_path in zip(all_extrinsics, all_img_paths): + if np.all(np.isfinite(extrinsic)): + img_paths.append(img_path) + extrinsics.append(extrinsic) + info['extrinsics'] = extrinsics + info['img_paths'] = img_paths + + if not self.test_mode: + pts_instance_mask_path = osp.join( + self.root_dir, 'scannet_instance_data', + f'{sample_idx}_ins_label.npy') + pts_semantic_mask_path = osp.join( + self.root_dir, 'scannet_instance_data', + f'{sample_idx}_sem_label.npy') + + pts_instance_mask = np.load(pts_instance_mask_path).astype( + np.int64) + pts_semantic_mask = np.load(pts_semantic_mask_path).astype( + np.int64) + + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'instance_mask')) + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'semantic_mask')) + + pts_instance_mask.tofile( + osp.join(self.root_dir, 'instance_mask', + f'{sample_idx}.bin')) + pts_semantic_mask.tofile( + osp.join(self.root_dir, 'semantic_mask', + f'{sample_idx}.bin')) + + info['pts_instance_mask_path'] = osp.join( + 'instance_mask', f'{sample_idx}.bin') + info['pts_semantic_mask_path'] = osp.join( + 'semantic_mask', f'{sample_idx}.bin') + + if has_label: + annotations = {} + # box is of shape [k, 6 + class] + aligned_box_label = self.get_aligned_box_label(sample_idx) + unaligned_box_label = self.get_unaligned_box_label(sample_idx) + annotations['gt_num'] = aligned_box_label.shape[0] + if annotations['gt_num'] != 0: + aligned_box = aligned_box_label[:, :-1] # k, 6 + unaligned_box = unaligned_box_label[:, :-1] + classes = aligned_box_label[:, -1] # k + annotations['name'] = np.array([ + self.label2cat[self.cat_ids2class[classes[i]]] + for i in range(annotations['gt_num']) + ]) + # default names are given to aligned bbox for compatibility + # we also save unaligned bbox info with marked names + annotations['location'] = aligned_box[:, :3] + annotations['dimensions'] = aligned_box[:, 3:6] + annotations['gt_boxes_upright_depth'] = aligned_box + annotations['unaligned_location'] = unaligned_box[:, :3] + annotations['unaligned_dimensions'] = unaligned_box[:, 3:6] + annotations[ + 'unaligned_gt_boxes_upright_depth'] = unaligned_box + annotations['index'] = np.arange( + annotations['gt_num'], dtype=np.int32) + annotations['class'] = np.array([ + self.cat_ids2class[classes[i]] + for i in range(annotations['gt_num']) + ]) + axis_align_matrix = self.get_axis_align_matrix(sample_idx) + annotations['axis_align_matrix'] = axis_align_matrix # 4x4 + info['annos'] = annotations + return info + + sample_id_list = sample_id_list if sample_id_list is not None \ + else self.sample_id_list + with futures.ThreadPoolExecutor(num_workers) as executor: + infos = executor.map(process_single_scene, sample_id_list) + return list(infos) + + +class ScanNetSegData(object): + """ScanNet dataset used to generate infos for semantic segmentation task. + + Args: + data_root (str): Root path of the raw data. + ann_file (str): The generated scannet infos. + split (str, optional): Set split type of the data. Default: 'train'. + num_points (int, optional): Number of points in each data input. + Default: 8192. + label_weight_func (function, optional): Function to compute the + label weight. Default: None. + """ + + def __init__(self, + data_root, + ann_file, + split='train', + num_points=8192, + label_weight_func=None): + self.data_root = data_root + self.data_infos = mmcv.load(ann_file) + self.split = split + assert split in ['train', 'val', 'test'] + self.num_points = num_points + + self.all_ids = np.arange(41) # all possible ids + self.cat_ids = np.array([ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 24, 28, 33, 34, 36, + 39 + ]) # used for seg task + self.ignore_index = len(self.cat_ids) + + self.cat_id2class = np.ones((self.all_ids.shape[0],), dtype=np.int) * \ + self.ignore_index + for i, cat_id in enumerate(self.cat_ids): + self.cat_id2class[cat_id] = i + + # label weighting function is taken from + # https://github.com/charlesq34/pointnet2/blob/master/scannet/scannet_dataset.py#L24 + self.label_weight_func = (lambda x: 1.0 / np.log(1.2 + x)) if \ + label_weight_func is None else label_weight_func + + def get_seg_infos(self): + if self.split == 'test': + return + scene_idxs, label_weight = self.get_scene_idxs_and_label_weight() + save_folder = osp.join(self.data_root, 'seg_info') + mmcv.mkdir_or_exist(save_folder) + np.save( + osp.join(save_folder, f'{self.split}_resampled_scene_idxs.npy'), + scene_idxs) + np.save( + osp.join(save_folder, f'{self.split}_label_weight.npy'), + label_weight) + print(f'{self.split} resampled scene index and label weight saved') + + def _convert_to_label(self, mask): + """Convert class_id in loaded segmentation mask to label.""" + if isinstance(mask, str): + if mask.endswith('npy'): + mask = np.load(mask) + else: + mask = np.fromfile(mask, dtype=np.int64) + label = self.cat_id2class[mask] + return label + + def get_scene_idxs_and_label_weight(self): + """Compute scene_idxs for data sampling and label weight for loss + calculation. + + We sample more times for scenes with more points. Label_weight is + inversely proportional to number of class points. + """ + num_classes = len(self.cat_ids) + num_point_all = [] + label_weight = np.zeros((num_classes + 1, )) # ignore_index + for data_info in self.data_infos: + label = self._convert_to_label( + osp.join(self.data_root, data_info['pts_semantic_mask_path'])) + num_point_all.append(label.shape[0]) + class_count, _ = np.histogram(label, range(num_classes + 2)) + label_weight += class_count + + # repeat scene_idx for num_scene_point // num_sample_point times + sample_prob = np.array(num_point_all) / float(np.sum(num_point_all)) + num_iter = int(np.sum(num_point_all) / float(self.num_points)) + scene_idxs = [] + for idx in range(len(self.data_infos)): + scene_idxs.extend([idx] * int(round(sample_prob[idx] * num_iter))) + scene_idxs = np.array(scene_idxs).astype(np.int32) + + # calculate label weight, adopted from PointNet++ + label_weight = label_weight[:-1].astype(np.float32) + label_weight = label_weight / label_weight.sum() + label_weight = self.label_weight_func(label_weight).astype(np.float32) + + return scene_idxs, label_weight diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/sunrgbd_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/sunrgbd_data_utils.py new file mode 100644 index 00000000..af3a5ed4 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/sunrgbd_data_utils.py @@ -0,0 +1,223 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from concurrent import futures as futures +from os import path as osp + +import mmcv +import numpy as np +from scipy import io as sio + + +def random_sampling(points, num_points, replace=None): + """Random sampling. + + Sampling point cloud to a certain number of points. + + Args: + points (ndarray): Point cloud. + num_points (int): The number of samples. + replace (bool): Whether the sample is with or without replacement. + + Returns: + points (ndarray): Point cloud after sampling. + """ + if num_points < 0: + return points + if replace is None: + replace = (points.shape[0] < num_points) + choices = np.random.choice(points.shape[0], num_points, replace=replace) + return points[choices] + + +class SUNRGBDInstance(object): + + def __init__(self, line): + data = line.split(' ') + data[1:] = [float(x) for x in data[1:]] + self.classname = data[0] + self.xmin = data[1] + self.ymin = data[2] + self.xmax = data[1] + data[3] + self.ymax = data[2] + data[4] + self.box2d = np.array([self.xmin, self.ymin, self.xmax, self.ymax]) + self.centroid = np.array([data[5], data[6], data[7]]) + self.width = data[8] + self.length = data[9] + self.height = data[10] + # data[9] is x_size (length), data[8] is y_size (width), data[10] is + # z_size (height) in our depth coordinate system, + # l corresponds to the size along the x axis + self.size = np.array([data[9], data[8], data[10]]) * 2 + self.orientation = np.zeros((3, )) + self.orientation[0] = data[11] + self.orientation[1] = data[12] + self.heading_angle = np.arctan2(self.orientation[1], + self.orientation[0]) + self.box3d = np.concatenate( + [self.centroid, self.size, self.heading_angle[None]]) + + +class SUNRGBDData(object): + """SUNRGBD data. + + Generate scannet infos for sunrgbd_converter. + + Args: + root_path (str): Root path of the raw data. + split (str, optional): Set split type of the data. Default: 'train'. + use_v1 (bool, optional): Whether to use v1. Default: False. + num_points (int, optional): Number of points to sample. Set to -1 + to utilize all points. Defaults to -1. + """ + + def __init__(self, root_path, split='train', use_v1=False, num_points=-1): + self.root_dir = root_path + self.split = split + self.split_dir = osp.join(root_path, 'sunrgbd_trainval') + self.num_points = num_points + self.classes = [ + 'bed', 'table', 'sofa', 'chair', 'toilet', 'desk', 'dresser', + 'night_stand', 'bookshelf', 'bathtub' + ] + self.cat2label = {cat: self.classes.index(cat) for cat in self.classes} + self.label2cat = { + label: self.classes[label] + for label in range(len(self.classes)) + } + assert split in ['train', 'val', 'test'] + split_file = osp.join(self.split_dir, f'{split}_data_idx.txt') + mmcv.check_file_exist(split_file) + self.sample_id_list = map(int, mmcv.list_from_file(split_file)) + self.image_dir = osp.join(self.split_dir, 'image') + self.calib_dir = osp.join(self.split_dir, 'calib') + self.depth_dir = osp.join(self.split_dir, 'depth') + if use_v1: + self.label_dir = osp.join(self.split_dir, 'label_v1') + else: + self.label_dir = osp.join(self.split_dir, 'label') + + def __len__(self): + return len(self.sample_id_list) + + def get_image(self, idx): + img_filename = osp.join(self.image_dir, f'{idx:06d}.jpg') + return mmcv.imread(img_filename) + + def get_image_shape(self, idx): + image = self.get_image(idx) + return np.array(image.shape[:2], dtype=np.int32) + + def get_depth(self, idx): + depth_filename = osp.join(self.depth_dir, f'{idx:06d}.mat') + depth = sio.loadmat(depth_filename)['instance'] + return depth + + def get_calibration(self, idx): + calib_filepath = osp.join(self.calib_dir, f'{idx:06d}.txt') + lines = [line.rstrip() for line in open(calib_filepath)] + Rt = np.array([float(x) for x in lines[0].split(' ')]) + Rt = np.reshape(Rt, (3, 3), order='F').astype(np.float32) + K = np.array([float(x) for x in lines[1].split(' ')]) + K = np.reshape(K, (3, 3), order='F').astype(np.float32) + return K, Rt + + def get_label_objects(self, idx): + label_filename = osp.join(self.label_dir, f'{idx:06d}.txt') + lines = [line.rstrip() for line in open(label_filename)] + objects = [SUNRGBDInstance(line) for line in lines] + return objects + + def get_infos(self, num_workers=4, has_label=True, sample_id_list=None): + """Get data infos. + + This method gets information from the raw data. + + Args: + num_workers (int, optional): Number of threads to be used. + Default: 4. + has_label (bool, optional): Whether the data has label. + Default: True. + sample_id_list (list[int], optional): Index list of the sample. + Default: None. + + Returns: + infos (list[dict]): Information of the raw data. + """ + + def process_single_scene(sample_idx): + print(f'{self.split} sample_idx: {sample_idx}') + # convert depth to points + pc_upright_depth = self.get_depth(sample_idx) + pc_upright_depth_subsampled = random_sampling( + pc_upright_depth, self.num_points) + + info = dict() + pc_info = {'num_features': 6, 'lidar_idx': sample_idx} + info['point_cloud'] = pc_info + + mmcv.mkdir_or_exist(osp.join(self.root_dir, 'points')) + pc_upright_depth_subsampled.tofile( + osp.join(self.root_dir, 'points', f'{sample_idx:06d}.bin')) + + info['pts_path'] = osp.join('points', f'{sample_idx:06d}.bin') + img_path = osp.join('image', f'{sample_idx:06d}.jpg') + image_info = { + 'image_idx': sample_idx, + 'image_shape': self.get_image_shape(sample_idx), + 'image_path': img_path + } + info['image'] = image_info + + K, Rt = self.get_calibration(sample_idx) + calib_info = {'K': K, 'Rt': Rt} + info['calib'] = calib_info + + if has_label: + obj_list = self.get_label_objects(sample_idx) + annotations = {} + annotations['gt_num'] = len([ + obj.classname for obj in obj_list + if obj.classname in self.cat2label.keys() + ]) + if annotations['gt_num'] != 0: + annotations['name'] = np.array([ + obj.classname for obj in obj_list + if obj.classname in self.cat2label.keys() + ]) + annotations['bbox'] = np.concatenate([ + obj.box2d.reshape(1, 4) for obj in obj_list + if obj.classname in self.cat2label.keys() + ], + axis=0) + annotations['location'] = np.concatenate([ + obj.centroid.reshape(1, 3) for obj in obj_list + if obj.classname in self.cat2label.keys() + ], + axis=0) + annotations['dimensions'] = 2 * np.array([ + [obj.length, obj.width, obj.height] for obj in obj_list + if obj.classname in self.cat2label.keys() + ]) # lwh (depth) format + annotations['rotation_y'] = np.array([ + obj.heading_angle for obj in obj_list + if obj.classname in self.cat2label.keys() + ]) + annotations['index'] = np.arange( + len(obj_list), dtype=np.int32) + annotations['class'] = np.array([ + self.cat2label[obj.classname] for obj in obj_list + if obj.classname in self.cat2label.keys() + ]) + annotations['gt_boxes_upright_depth'] = np.stack( + [ + obj.box3d for obj in obj_list + if obj.classname in self.cat2label.keys() + ], + axis=0) # (K,8) + info['annos'] = annotations + return info + + sample_id_list = sample_id_list if \ + sample_id_list is not None else self.sample_id_list + with futures.ThreadPoolExecutor(num_workers) as executor: + infos = executor.map(process_single_scene, sample_id_list) + return list(infos) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/waymo_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/waymo_converter.py new file mode 100644 index 00000000..f991514b --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/data_converter/waymo_converter.py @@ -0,0 +1,556 @@ +# Copyright (c) OpenMMLab. All rights reserved. +r"""Adapted from `Waymo to KITTI converter + `_. +""" + +try: + from waymo_open_dataset import dataset_pb2 +except ImportError: + raise ImportError( + 'Please run "pip install waymo-open-dataset-tf-2-1-0==1.2.0" ' + 'to install the official devkit first.') + +from glob import glob +from os.path import join + +import mmcv +import numpy as np +import tensorflow as tf +from waymo_open_dataset.utils import range_image_utils, transform_utils +from waymo_open_dataset.utils.frame_utils import \ + parse_range_image_and_camera_projection + + +class Waymo2KITTI(object): + """Waymo to KITTI converter. + + This class serves as the converter to change the waymo raw data to KITTI + format. + + Args: + load_dir (str): Directory to load waymo raw data. + save_dir (str): Directory to save data in KITTI format. + prefix (str): Prefix of filename. In general, 0 for training, 1 for + validation and 2 for testing. + workers (int, optional): Number of workers for the parallel process. + test_mode (bool, optional): Whether in the test_mode. Default: False. + """ + + def __init__(self, + load_dir, + save_dir, + prefix, + workers=64, + test_mode=False): + self.filter_empty_3dboxes = True + self.filter_no_label_zone_points = True + + self.selected_waymo_classes = ['VEHICLE', 'PEDESTRIAN', 'CYCLIST'] + + # Only data collected in specific locations will be converted + # If set None, this filter is disabled + # Available options: location_sf (main dataset) + self.selected_waymo_locations = None + self.save_track_id = False + + # turn on eager execution for older tensorflow versions + if int(tf.__version__.split('.')[0]) < 2: + tf.enable_eager_execution() + + self.lidar_list = [ + '_FRONT', '_FRONT_RIGHT', '_FRONT_LEFT', '_SIDE_RIGHT', + '_SIDE_LEFT' + ] + self.type_list = [ + 'UNKNOWN', 'VEHICLE', 'PEDESTRIAN', 'SIGN', 'CYCLIST' + ] + self.waymo_to_kitti_class_map = { + 'UNKNOWN': 'DontCare', + 'PEDESTRIAN': 'Pedestrian', + 'VEHICLE': 'Car', + 'CYCLIST': 'Cyclist', + 'SIGN': 'Sign' # not in kitti + } + + self.load_dir = load_dir + self.save_dir = save_dir + self.prefix = prefix + self.workers = int(workers) + self.test_mode = test_mode + + self.tfrecord_pathnames = sorted( + glob(join(self.load_dir, '*.tfrecord'))) + + self.label_save_dir = f'{self.save_dir}/label_' + self.label_all_save_dir = f'{self.save_dir}/label_all' + self.image_save_dir = f'{self.save_dir}/image_' + self.calib_save_dir = f'{self.save_dir}/calib' + self.point_cloud_save_dir = f'{self.save_dir}/velodyne' + self.pose_save_dir = f'{self.save_dir}/pose' + self.timestamp_save_dir = f'{self.save_dir}/timestamp' + + self.create_folder() + + def convert(self): + """Convert action.""" + print('Start converting ...') + mmcv.track_parallel_progress(self.convert_one, range(len(self)), + self.workers) + print('\nFinished ...') + + def convert_one(self, file_idx): + """Convert action for single file. + + Args: + file_idx (int): Index of the file to be converted. + """ + pathname = self.tfrecord_pathnames[file_idx] + dataset = tf.data.TFRecordDataset(pathname, compression_type='') + + for frame_idx, data in enumerate(dataset): + + frame = dataset_pb2.Frame() + frame.ParseFromString(bytearray(data.numpy())) + if (self.selected_waymo_locations is not None + and frame.context.stats.location + not in self.selected_waymo_locations): + continue + + self.save_image(frame, file_idx, frame_idx) + self.save_calib(frame, file_idx, frame_idx) + self.save_lidar(frame, file_idx, frame_idx) + self.save_pose(frame, file_idx, frame_idx) + self.save_timestamp(frame, file_idx, frame_idx) + + if not self.test_mode: + self.save_label(frame, file_idx, frame_idx) + + def __len__(self): + """Length of the filename list.""" + return len(self.tfrecord_pathnames) + + def save_image(self, frame, file_idx, frame_idx): + """Parse and save the images in png format. + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + for img in frame.images: + img_path = f'{self.image_save_dir}{str(img.name - 1)}/' + \ + f'{self.prefix}{str(file_idx).zfill(3)}' + \ + f'{str(frame_idx).zfill(3)}.png' + img = mmcv.imfrombytes(img.image) + mmcv.imwrite(img, img_path) + + def save_calib(self, frame, file_idx, frame_idx): + """Parse and save the calibration data. + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + # waymo front camera to kitti reference camera + T_front_cam_to_ref = np.array([[0.0, -1.0, 0.0], [0.0, 0.0, -1.0], + [1.0, 0.0, 0.0]]) + camera_calibs = [] + R0_rect = [f'{i:e}' for i in np.eye(3).flatten()] + Tr_velo_to_cams = [] + calib_context = '' + + for camera in frame.context.camera_calibrations: + # extrinsic parameters + T_cam_to_vehicle = np.array(camera.extrinsic.transform).reshape( + 4, 4) + T_vehicle_to_cam = np.linalg.inv(T_cam_to_vehicle) + Tr_velo_to_cam = \ + self.cart_to_homo(T_front_cam_to_ref) @ T_vehicle_to_cam + if camera.name == 1: # FRONT = 1, see dataset.proto for details + self.T_velo_to_front_cam = Tr_velo_to_cam.copy() + Tr_velo_to_cam = Tr_velo_to_cam[:3, :].reshape((12, )) + Tr_velo_to_cams.append([f'{i:e}' for i in Tr_velo_to_cam]) + + # intrinsic parameters + camera_calib = np.zeros((3, 4)) + camera_calib[0, 0] = camera.intrinsic[0] + camera_calib[1, 1] = camera.intrinsic[1] + camera_calib[0, 2] = camera.intrinsic[2] + camera_calib[1, 2] = camera.intrinsic[3] + camera_calib[2, 2] = 1 + camera_calib = list(camera_calib.reshape(12)) + camera_calib = [f'{i:e}' for i in camera_calib] + camera_calibs.append(camera_calib) + + # all camera ids are saved as id-1 in the result because + # camera 0 is unknown in the proto + for i in range(5): + calib_context += 'P' + str(i) + ': ' + \ + ' '.join(camera_calibs[i]) + '\n' + calib_context += 'R0_rect' + ': ' + ' '.join(R0_rect) + '\n' + for i in range(5): + calib_context += 'Tr_velo_to_cam_' + str(i) + ': ' + \ + ' '.join(Tr_velo_to_cams[i]) + '\n' + + with open( + f'{self.calib_save_dir}/{self.prefix}' + + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.txt', + 'w+') as fp_calib: + fp_calib.write(calib_context) + fp_calib.close() + + def save_lidar(self, frame, file_idx, frame_idx): + """Parse and save the lidar data in psd format. + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + range_images, camera_projections, range_image_top_pose = \ + parse_range_image_and_camera_projection(frame) + + # First return + points_0, cp_points_0, intensity_0, elongation_0, mask_indices_0 = \ + self.convert_range_image_to_point_cloud( + frame, + range_images, + camera_projections, + range_image_top_pose, + ri_index=0 + ) + points_0 = np.concatenate(points_0, axis=0) + intensity_0 = np.concatenate(intensity_0, axis=0) + elongation_0 = np.concatenate(elongation_0, axis=0) + mask_indices_0 = np.concatenate(mask_indices_0, axis=0) + + # Second return + points_1, cp_points_1, intensity_1, elongation_1, mask_indices_1 = \ + self.convert_range_image_to_point_cloud( + frame, + range_images, + camera_projections, + range_image_top_pose, + ri_index=1 + ) + points_1 = np.concatenate(points_1, axis=0) + intensity_1 = np.concatenate(intensity_1, axis=0) + elongation_1 = np.concatenate(elongation_1, axis=0) + mask_indices_1 = np.concatenate(mask_indices_1, axis=0) + + points = np.concatenate([points_0, points_1], axis=0) + intensity = np.concatenate([intensity_0, intensity_1], axis=0) + elongation = np.concatenate([elongation_0, elongation_1], axis=0) + mask_indices = np.concatenate([mask_indices_0, mask_indices_1], axis=0) + + # timestamp = frame.timestamp_micros * np.ones_like(intensity) + + # concatenate x,y,z, intensity, elongation, timestamp (6-dim) + point_cloud = np.column_stack( + (points, intensity, elongation, mask_indices)) + + pc_path = f'{self.point_cloud_save_dir}/{self.prefix}' + \ + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.bin' + point_cloud.astype(np.float32).tofile(pc_path) + + def save_label(self, frame, file_idx, frame_idx): + """Parse and save the label data in txt format. + The relation between waymo and kitti coordinates is noteworthy: + 1. x, y, z correspond to l, w, h (waymo) -> l, h, w (kitti) + 2. x-y-z: front-left-up (waymo) -> right-down-front(kitti) + 3. bbox origin at volumetric center (waymo) -> bottom center (kitti) + 4. rotation: +x around y-axis (kitti) -> +x around z-axis (waymo) + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + fp_label_all = open( + f'{self.label_all_save_dir}/{self.prefix}' + + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.txt', 'w+') + id_to_bbox = dict() + id_to_name = dict() + for labels in frame.projected_lidar_labels: + name = labels.name + for label in labels.labels: + # TODO: need a workaround as bbox may not belong to front cam + bbox = [ + label.box.center_x - label.box.length / 2, + label.box.center_y - label.box.width / 2, + label.box.center_x + label.box.length / 2, + label.box.center_y + label.box.width / 2 + ] + id_to_bbox[label.id] = bbox + id_to_name[label.id] = name - 1 + + for obj in frame.laser_labels: + bounding_box = None + name = None + id = obj.id + for lidar in self.lidar_list: + if id + lidar in id_to_bbox: + bounding_box = id_to_bbox.get(id + lidar) + name = str(id_to_name.get(id + lidar)) + break + + if bounding_box is None or name is None: + name = '0' + bounding_box = (0, 0, 0, 0) + + my_type = self.type_list[obj.type] + + if my_type not in self.selected_waymo_classes: + continue + + if self.filter_empty_3dboxes and obj.num_lidar_points_in_box < 1: + continue + + my_type = self.waymo_to_kitti_class_map[my_type] + + height = obj.box.height + width = obj.box.width + length = obj.box.length + + x = obj.box.center_x + y = obj.box.center_y + z = obj.box.center_z - height / 2 + + # project bounding box to the virtual reference frame + pt_ref = self.T_velo_to_front_cam @ \ + np.array([x, y, z, 1]).reshape((4, 1)) + x, y, z, _ = pt_ref.flatten().tolist() + + rotation_y = -obj.box.heading - np.pi / 2 + track_id = obj.id + + # not available + truncated = 0 + occluded = 0 + alpha = -10 + + line = my_type + \ + ' {} {} {} {} {} {} {} {} {} {} {} {} {} {}\n'.format( + round(truncated, 2), occluded, round(alpha, 2), + round(bounding_box[0], 2), round(bounding_box[1], 2), + round(bounding_box[2], 2), round(bounding_box[3], 2), + round(height, 2), round(width, 2), round(length, 2), + round(x, 2), round(y, 2), round(z, 2), + round(rotation_y, 2)) + + if self.save_track_id: + line_all = line[:-1] + ' ' + name + ' ' + track_id + '\n' + else: + line_all = line[:-1] + ' ' + name + '\n' + + fp_label = open( + f'{self.label_save_dir}{name}/{self.prefix}' + + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.txt', 'a') + fp_label.write(line) + fp_label.close() + + fp_label_all.write(line_all) + + fp_label_all.close() + + def save_pose(self, frame, file_idx, frame_idx): + """Parse and save the pose data. + + Note that SDC's own pose is not included in the regular training + of KITTI dataset. KITTI raw dataset contains ego motion files + but are not often used. Pose is important for algorithms that + take advantage of the temporal information. + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + pose = np.array(frame.pose.transform).reshape(4, 4) + np.savetxt( + join(f'{self.pose_save_dir}/{self.prefix}' + + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.txt'), + pose) + + def save_timestamp(self, frame, file_idx, frame_idx): + """Save the timestamp data in a separate file instead of the + pointcloud. + + Note that SDC's own pose is not included in the regular training + of KITTI dataset. KITTI raw dataset contains ego motion files + but are not often used. Pose is important for algorithms that + take advantage of the temporal information. + + Args: + frame (:obj:`Frame`): Open dataset frame proto. + file_idx (int): Current file index. + frame_idx (int): Current frame index. + """ + with open( + join(f'{self.timestamp_save_dir}/{self.prefix}' + + f'{str(file_idx).zfill(3)}{str(frame_idx).zfill(3)}.txt'), + 'w') as f: + f.write(str(frame.timestamp_micros)) + + def create_folder(self): + """Create folder for data preprocessing.""" + if not self.test_mode: + dir_list1 = [ + self.label_all_save_dir, self.calib_save_dir, + self.point_cloud_save_dir, self.pose_save_dir, + self.timestamp_save_dir + ] + dir_list2 = [self.label_save_dir, self.image_save_dir] + else: + dir_list1 = [ + self.calib_save_dir, self.point_cloud_save_dir, + self.pose_save_dir, self.timestamp_save_dir + ] + dir_list2 = [self.image_save_dir] + for d in dir_list1: + mmcv.mkdir_or_exist(d) + for d in dir_list2: + for i in range(5): + mmcv.mkdir_or_exist(f'{d}{str(i)}') + + def convert_range_image_to_point_cloud(self, + frame, + range_images, + camera_projections, + range_image_top_pose, + ri_index=0): + """Convert range images to point cloud. + + Args: + frame (:obj:`Frame`): Open dataset frame. + range_images (dict): Mapping from laser_name to list of two + range images corresponding with two returns. + camera_projections (dict): Mapping from laser_name to list of two + camera projections corresponding with two returns. + range_image_top_pose (:obj:`Transform`): Range image pixel pose for + top lidar. + ri_index (int, optional): 0 for the first return, + 1 for the second return. Default: 0. + + Returns: + tuple[list[np.ndarray]]: (List of points with shape [N, 3], + camera projections of points with shape [N, 6], intensity + with shape [N, 1], elongation with shape [N, 1], points' + position in the depth map (element offset if points come from + the main lidar otherwise -1) with shape[N, 1]). All the + lists have the length of lidar numbers (5). + """ + calibrations = sorted( + frame.context.laser_calibrations, key=lambda c: c.name) + points = [] + cp_points = [] + intensity = [] + elongation = [] + mask_indices = [] + + frame_pose = tf.convert_to_tensor( + value=np.reshape(np.array(frame.pose.transform), [4, 4])) + # [H, W, 6] + range_image_top_pose_tensor = tf.reshape( + tf.convert_to_tensor(value=range_image_top_pose.data), + range_image_top_pose.shape.dims) + # [H, W, 3, 3] + range_image_top_pose_tensor_rotation = \ + transform_utils.get_rotation_matrix( + range_image_top_pose_tensor[..., 0], + range_image_top_pose_tensor[..., 1], + range_image_top_pose_tensor[..., 2]) + range_image_top_pose_tensor_translation = \ + range_image_top_pose_tensor[..., 3:] + range_image_top_pose_tensor = transform_utils.get_transform( + range_image_top_pose_tensor_rotation, + range_image_top_pose_tensor_translation) + for c in calibrations: + range_image = range_images[c.name][ri_index] + if len(c.beam_inclinations) == 0: + beam_inclinations = range_image_utils.compute_inclination( + tf.constant( + [c.beam_inclination_min, c.beam_inclination_max]), + height=range_image.shape.dims[0]) + else: + beam_inclinations = tf.constant(c.beam_inclinations) + + beam_inclinations = tf.reverse(beam_inclinations, axis=[-1]) + extrinsic = np.reshape(np.array(c.extrinsic.transform), [4, 4]) + + range_image_tensor = tf.reshape( + tf.convert_to_tensor(value=range_image.data), + range_image.shape.dims) + pixel_pose_local = None + frame_pose_local = None + if c.name == dataset_pb2.LaserName.TOP: + pixel_pose_local = range_image_top_pose_tensor + pixel_pose_local = tf.expand_dims(pixel_pose_local, axis=0) + frame_pose_local = tf.expand_dims(frame_pose, axis=0) + range_image_mask = range_image_tensor[..., 0] > 0 + + if self.filter_no_label_zone_points: + nlz_mask = range_image_tensor[..., 3] != 1.0 # 1.0: in NLZ + range_image_mask = range_image_mask & nlz_mask + + range_image_cartesian = \ + range_image_utils.extract_point_cloud_from_range_image( + tf.expand_dims(range_image_tensor[..., 0], axis=0), + tf.expand_dims(extrinsic, axis=0), + tf.expand_dims(tf.convert_to_tensor( + value=beam_inclinations), axis=0), + pixel_pose=pixel_pose_local, + frame_pose=frame_pose_local) + + mask_index = tf.where(range_image_mask) + + range_image_cartesian = tf.squeeze(range_image_cartesian, axis=0) + points_tensor = tf.gather_nd(range_image_cartesian, mask_index) + + cp = camera_projections[c.name][ri_index] + cp_tensor = tf.reshape( + tf.convert_to_tensor(value=cp.data), cp.shape.dims) + cp_points_tensor = tf.gather_nd(cp_tensor, mask_index) + points.append(points_tensor.numpy()) + cp_points.append(cp_points_tensor.numpy()) + + intensity_tensor = tf.gather_nd(range_image_tensor[..., 1], + mask_index) + intensity.append(intensity_tensor.numpy()) + + elongation_tensor = tf.gather_nd(range_image_tensor[..., 2], + mask_index) + elongation.append(elongation_tensor.numpy()) + if c.name == 1: + mask_index = (ri_index * range_image_mask.shape[0] + + mask_index[:, 0] + ) * range_image_mask.shape[1] + mask_index[:, 1] + mask_index = mask_index.numpy().astype(elongation[-1].dtype) + else: + mask_index = np.full_like(elongation[-1], -1) + + mask_indices.append(mask_index) + + return points, cp_points, intensity, elongation, mask_indices + + def cart_to_homo(self, mat): + """Convert transformation matrix in Cartesian coordinates to + homogeneous format. + + Args: + mat (np.ndarray): Transformation matrix in Cartesian. + The input matrix shape is 3x3 or 3x4. + + Returns: + np.ndarray: Transformation matrix in homogeneous format. + The matrix shape is 4x4. + """ + ret = np.eye(4) + if mat.shape == (3, 3): + ret[:3, :3] = mat + elif mat.shape == (3, 4): + ret[:3, :] = mat + else: + raise ValueError(mat.shape) + return ret diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d2torchserve.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d2torchserve.py new file mode 100644 index 00000000..df7e6084 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d2torchserve.py @@ -0,0 +1,111 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from argparse import ArgumentParser, Namespace +from pathlib import Path +from tempfile import TemporaryDirectory + +import mmcv + +try: + from model_archiver.model_packaging import package_model + from model_archiver.model_packaging_utils import ModelExportUtils +except ImportError: + package_model = None + + +def mmdet3d2torchserve( + config_file: str, + checkpoint_file: str, + output_folder: str, + model_name: str, + model_version: str = '1.0', + force: bool = False, +): + """Converts MMDetection3D model (config + checkpoint) to TorchServe `.mar`. + + Args: + config_file (str): + In MMDetection3D config format. + The contents vary for each task repository. + checkpoint_file (str): + In MMDetection3D checkpoint format. + The contents vary for each task repository. + output_folder (str): + Folder where `{model_name}.mar` will be created. + The file created will be in TorchServe archive format. + model_name (str): + If not None, used for naming the `{model_name}.mar` file + that will be created under `output_folder`. + If None, `{Path(checkpoint_file).stem}` will be used. + model_version (str, optional): + Model's version. Default: '1.0'. + force (bool, optional): + If True, if there is an existing `{model_name}.mar` + file under `output_folder` it will be overwritten. + Default: False. + """ + mmcv.mkdir_or_exist(output_folder) + + config = mmcv.Config.fromfile(config_file) + + with TemporaryDirectory() as tmpdir: + config.dump(f'{tmpdir}/config.py') + + args = Namespace( + **{ + 'model_file': f'{tmpdir}/config.py', + 'serialized_file': checkpoint_file, + 'handler': f'{Path(__file__).parent}/mmdet3d_handler.py', + 'model_name': model_name or Path(checkpoint_file).stem, + 'version': model_version, + 'export_path': output_folder, + 'force': force, + 'requirements_file': None, + 'extra_files': None, + 'runtime': 'python', + 'archive_format': 'default' + }) + manifest = ModelExportUtils.generate_manifest_json(args) + package_model(args, manifest) + + +def parse_args(): + parser = ArgumentParser( + description='Convert MMDetection models to TorchServe `.mar` format.') + parser.add_argument('config', type=str, help='config file path') + parser.add_argument('checkpoint', type=str, help='checkpoint file path') + parser.add_argument( + '--output-folder', + type=str, + required=True, + help='Folder where `{model_name}.mar` will be created.') + parser.add_argument( + '--model-name', + type=str, + default=None, + help='If not None, used for naming the `{model_name}.mar`' + 'file that will be created under `output_folder`.' + 'If None, `{Path(checkpoint_file).stem}` will be used.') + parser.add_argument( + '--model-version', + type=str, + default='1.0', + help='Number used for versioning.') + parser.add_argument( + '-f', + '--force', + action='store_true', + help='overwrite the existing `{model_name}.mar`') + args = parser.parse_args() + + return args + + +if __name__ == '__main__': + args = parse_args() + + if package_model is None: + raise ImportError('`torch-model-archiver` is required.' + 'Try: pip install torch-model-archiver') + + mmdet3d2torchserve(args.config, args.checkpoint, args.output_folder, + args.model_name, args.model_version, args.force) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d_handler.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d_handler.py new file mode 100644 index 00000000..8b526cdf --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/mmdet3d_handler.py @@ -0,0 +1,120 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import base64 +import os + +import numpy as np +import torch +from ts.torch_handler.base_handler import BaseHandler + +from mmdet3d.apis import inference_detector, init_model +from mmdet3d.core.points import get_points_type + + +class MMdet3dHandler(BaseHandler): + """MMDetection3D Handler used in TorchServe. + + Handler to load models in MMDetection3D, and it will process data to get + predicted results. For now, it only supports SECOND. + """ + threshold = 0.5 + load_dim = 4 + use_dim = [0, 1, 2, 3] + coord_type = 'LIDAR' + attribute_dims = None + + def initialize(self, context): + """Initialize function loads the model in MMDetection3D. + + Args: + context (context): It is a JSON Object containing information + pertaining to the model artifacts parameters. + """ + properties = context.system_properties + self.map_location = 'cuda' if torch.cuda.is_available() else 'cpu' + self.device = torch.device(self.map_location + ':' + + str(properties.get('gpu_id')) if torch.cuda. + is_available() else self.map_location) + self.manifest = context.manifest + + model_dir = properties.get('model_dir') + serialized_file = self.manifest['model']['serializedFile'] + checkpoint = os.path.join(model_dir, serialized_file) + self.config_file = os.path.join(model_dir, 'config.py') + self.model = init_model(self.config_file, checkpoint, self.device) + self.initialized = True + + def preprocess(self, data): + """Preprocess function converts data into LiDARPoints class. + + Args: + data (List): Input data from the request. + + Returns: + `LiDARPoints` : The preprocess function returns the input + point cloud data as LiDARPoints class. + """ + for row in data: + # Compat layer: normally the envelope should just return the data + # directly, but older versions of Torchserve didn't have envelope. + pts = row.get('data') or row.get('body') + if isinstance(pts, str): + pts = base64.b64decode(pts) + + points = np.frombuffer(pts, dtype=np.float32) + points = points.reshape(-1, self.load_dim) + points = points[:, self.use_dim] + points_class = get_points_type(self.coord_type) + points = points_class( + points, + points_dim=points.shape[-1], + attribute_dims=self.attribute_dims) + + return points + + def inference(self, data): + """Inference Function. + + This function is used to make a prediction call on the + given input request. + + Args: + data (`LiDARPoints`): LiDARPoints class passed to make + the inference request. + + Returns: + List(dict) : The predicted result is returned in this function. + """ + results, _ = inference_detector(self.model, data) + return results + + def postprocess(self, data): + """Postprocess function. + + This function makes use of the output from the inference and + converts it into a torchserve supported response output. + + Args: + data (List[dict]): The data received from the prediction + output of the model. + + Returns: + List: The post process function returns a list of the predicted + output. + """ + output = [] + for pts_index, result in enumerate(data): + output.append([]) + if 'pts_bbox' in result.keys(): + pred_bboxes = result['pts_bbox']['boxes_3d'].tensor.numpy() + pred_scores = result['pts_bbox']['scores_3d'].numpy() + else: + pred_bboxes = result['boxes_3d'].tensor.numpy() + pred_scores = result['scores_3d'].numpy() + + index = pred_scores > self.threshold + bbox_coords = pred_bboxes[index].tolist() + score = pred_scores[index].tolist() + + output[pts_index].append({'3dbbox': bbox_coords, 'score': score}) + + return output diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/test_torchserver.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/test_torchserver.py new file mode 100644 index 00000000..613f9e4f --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/deployment/test_torchserver.py @@ -0,0 +1,56 @@ +from argparse import ArgumentParser + +import numpy as np +import requests + +from mmdet3d.apis import inference_detector, init_model + + +def parse_args(): + parser = ArgumentParser() + parser.add_argument('pcd', help='Point cloud file') + parser.add_argument('config', help='Config file') + parser.add_argument('checkpoint', help='Checkpoint file') + parser.add_argument('model_name', help='The model name in the server') + parser.add_argument( + '--inference-addr', + default='127.0.0.1:8080', + help='Address and port of the inference server') + parser.add_argument( + '--device', default='cuda:0', help='Device used for inference') + parser.add_argument( + '--score-thr', type=float, default=0.5, help='3d bbox score threshold') + args = parser.parse_args() + return args + + +def parse_result(input): + bbox = input[0]['3dbbox'] + result = np.array(bbox) + return result + + +def main(args): + # build the model from a config file and a checkpoint file + model = init_model(args.config, args.checkpoint, device=args.device) + # test a single point cloud file + model_result, _ = inference_detector(model, args.pcd) + # filter the 3d bboxes whose scores > 0.5 + if 'pts_bbox' in model_result[0].keys(): + pred_bboxes = model_result[0]['pts_bbox']['boxes_3d'].tensor.numpy() + pred_scores = model_result[0]['pts_bbox']['scores_3d'].numpy() + else: + pred_bboxes = model_result[0]['boxes_3d'].tensor.numpy() + pred_scores = model_result[0]['scores_3d'].numpy() + model_result = pred_bboxes[pred_scores > 0.5] + + url = 'http://' + args.inference_addr + '/predictions/' + args.model_name + with open(args.pcd, 'rb') as points: + response = requests.post(url, points) + server_result = parse_result(response.json()) + assert np.allclose(model_result, server_result) + + +if __name__ == '__main__': + args = parse_args() + main(args) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_test.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_test.sh new file mode 100644 index 00000000..dea131b4 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_test.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +CONFIG=$1 +CHECKPOINT=$2 +GPUS=$3 +NNODES=${NNODES:-1} +NODE_RANK=${NODE_RANK:-0} +PORT=${PORT:-29500} +MASTER_ADDR=${MASTER_ADDR:-"127.0.0.1"} + +PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ +python -m torch.distributed.launch \ + --nnodes=$NNODES \ + --node_rank=$NODE_RANK \ + --master_addr=$MASTER_ADDR \ + --nproc_per_node=$GPUS \ + --master_port=$PORT \ + $(dirname "$0")/test.py \ + $CONFIG \ + $CHECKPOINT \ + --launcher pytorch \ + ${@:4} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_train.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_train.sh new file mode 100644 index 00000000..aa71bf4a --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/dist_train.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +CONFIG=$1 +GPUS=$2 +NNODES=${NNODES:-1} +NODE_RANK=${NODE_RANK:-0} +PORT=${PORT:-29500} +MASTER_ADDR=${MASTER_ADDR:-"127.0.0.1"} + +PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ +python -m torch.distributed.launch \ + --nnodes=$NNODES \ + --node_rank=$NODE_RANK \ + --master_addr=$MASTER_ADDR \ + --nproc_per_node=$GPUS \ + --master_port=$PORT \ + $(dirname "$0")/train.py \ + $CONFIG \ + --seed 0 \ + --launcher pytorch ${@:3} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/browse_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/browse_dataset.py new file mode 100644 index 00000000..e4451b12 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/browse_dataset.py @@ -0,0 +1,232 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import warnings +from os import path as osp +from pathlib import Path + +import mmcv +import numpy as np +from mmcv import Config, DictAction, mkdir_or_exist + +from mmdet3d.core.bbox import (Box3DMode, CameraInstance3DBoxes, Coord3DMode, + DepthInstance3DBoxes, LiDARInstance3DBoxes) +from mmdet3d.core.visualizer import (show_multi_modality_result, show_result, + show_seg_result) +from mmdet3d.datasets import build_dataset + + +def parse_args(): + parser = argparse.ArgumentParser(description='Browse a dataset') + parser.add_argument('config', help='train config file path') + parser.add_argument( + '--skip-type', + type=str, + nargs='+', + default=['Normalize'], + help='skip some useless pipeline') + parser.add_argument( + '--output-dir', + default=None, + type=str, + help='If there is no display interface, you can save it') + parser.add_argument( + '--task', + type=str, + choices=['det', 'seg', 'multi_modality-det', 'mono-det'], + help='Determine the visualization method depending on the task.') + parser.add_argument( + '--aug', + action='store_true', + help='Whether to visualize augmented datasets or original dataset.') + parser.add_argument( + '--online', + action='store_true', + help='Whether to perform online visualization. Note that you often ' + 'need a monitor to do so.') + parser.add_argument( + '--cfg-options', + nargs='+', + action=DictAction, + help='override some settings in the used config, the key-value pair ' + 'in xxx=yyy format will be merged into config file. If the value to ' + 'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' + 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' + 'Note that the quotation marks are necessary and that no white space ' + 'is allowed.') + args = parser.parse_args() + return args + + +def build_data_cfg(config_path, skip_type, aug, cfg_options): + """Build data config for loading visualization data.""" + + cfg = Config.fromfile(config_path) + if cfg_options is not None: + cfg.merge_from_dict(cfg_options) + # extract inner dataset of `RepeatDataset` as `cfg.data.train` + # so we don't need to worry about it later + if cfg.data.train['type'] == 'RepeatDataset': + cfg.data.train = cfg.data.train.dataset + # use only first dataset for `ConcatDataset` + if cfg.data.train['type'] == 'ConcatDataset': + cfg.data.train = cfg.data.train.datasets[0] + train_data_cfg = cfg.data.train + + if aug: + show_pipeline = cfg.train_pipeline + else: + show_pipeline = cfg.eval_pipeline + for i in range(len(cfg.train_pipeline)): + if cfg.train_pipeline[i]['type'] == 'LoadAnnotations3D': + show_pipeline.insert(i, cfg.train_pipeline[i]) + # Collect points as well as labels + if cfg.train_pipeline[i]['type'] == 'Collect3D': + if show_pipeline[-1]['type'] == 'Collect3D': + show_pipeline[-1] = cfg.train_pipeline[i] + else: + show_pipeline.append(cfg.train_pipeline[i]) + + train_data_cfg['pipeline'] = [ + x for x in show_pipeline if x['type'] not in skip_type + ] + + return cfg + + +def to_depth_mode(points, bboxes): + """Convert points and bboxes to Depth Coord and Depth Box mode.""" + if points is not None: + points = Coord3DMode.convert_point(points.copy(), Coord3DMode.LIDAR, + Coord3DMode.DEPTH) + if bboxes is not None: + bboxes = Box3DMode.convert(bboxes.clone(), Box3DMode.LIDAR, + Box3DMode.DEPTH) + return points, bboxes + + +def show_det_data(input, out_dir, show=False): + """Visualize 3D point cloud and 3D bboxes.""" + img_metas = input['img_metas']._data + points = input['points']._data.numpy() + gt_bboxes = input['gt_bboxes_3d']._data.tensor + if img_metas['box_mode_3d'] != Box3DMode.DEPTH: + points, gt_bboxes = to_depth_mode(points, gt_bboxes) + filename = osp.splitext(osp.basename(img_metas['pts_filename']))[0] + show_result( + points, + gt_bboxes.clone(), + None, + out_dir, + filename, + show=show, + snapshot=True) + + +def show_seg_data(input, out_dir, show=False): + """Visualize 3D point cloud and segmentation mask.""" + img_metas = input['img_metas']._data + points = input['points']._data.numpy() + gt_seg = input['pts_semantic_mask']._data.numpy() + filename = osp.splitext(osp.basename(img_metas['pts_filename']))[0] + show_seg_result( + points, + gt_seg.copy(), + None, + out_dir, + filename, + np.array(img_metas['PALETTE']), + img_metas['ignore_index'], + show=show, + snapshot=True) + + +def show_proj_bbox_img(input, out_dir, show=False, is_nus_mono=False): + """Visualize 3D bboxes on 2D image by projection.""" + gt_bboxes = input['gt_bboxes_3d']._data + img_metas = input['img_metas']._data + img = input['img']._data.numpy() + # need to transpose channel to first dim + img = img.transpose(1, 2, 0) + # no 3D gt bboxes, just show img + if gt_bboxes.tensor.shape[0] == 0: + gt_bboxes = None + filename = Path(img_metas['filename']).name + if isinstance(gt_bboxes, DepthInstance3DBoxes): + show_multi_modality_result( + img, + gt_bboxes, + None, + None, + out_dir, + filename, + box_mode='depth', + img_metas=img_metas, + show=show) + elif isinstance(gt_bboxes, LiDARInstance3DBoxes): + show_multi_modality_result( + img, + gt_bboxes, + None, + img_metas['lidar2img'], + out_dir, + filename, + box_mode='lidar', + img_metas=img_metas, + show=show) + elif isinstance(gt_bboxes, CameraInstance3DBoxes): + show_multi_modality_result( + img, + gt_bboxes, + None, + img_metas['cam2img'], + out_dir, + filename, + box_mode='camera', + img_metas=img_metas, + show=show) + else: + # can't project, just show img + warnings.warn( + f'unrecognized gt box type {type(gt_bboxes)}, only show image') + show_multi_modality_result( + img, None, None, None, out_dir, filename, show=show) + + +def main(): + args = parse_args() + + if args.output_dir is not None: + mkdir_or_exist(args.output_dir) + + cfg = build_data_cfg(args.config, args.skip_type, args.aug, + args.cfg_options) + try: + dataset = build_dataset( + cfg.data.train, default_args=dict(filter_empty_gt=False)) + except TypeError: # seg dataset doesn't have `filter_empty_gt` key + dataset = build_dataset(cfg.data.train) + + dataset_type = cfg.dataset_type + # configure visualization mode + vis_task = args.task # 'det', 'seg', 'multi_modality-det', 'mono-det' + progress_bar = mmcv.ProgressBar(len(dataset)) + + for input in dataset: + if vis_task in ['det', 'multi_modality-det']: + # show 3D bboxes on 3D point clouds + show_det_data(input, args.output_dir, show=args.online) + if vis_task in ['multi_modality-det', 'mono-det']: + # project 3D bboxes to 2D image + show_proj_bbox_img( + input, + args.output_dir, + show=args.online, + is_nus_mono=(dataset_type == 'NuScenesMonoDataset')) + elif vis_task in ['seg']: + # show 3D segmentation mask on 3D point clouds + show_seg_data(input, args.output_dir, show=args.online) + progress_bar.update() + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/fuse_conv_bn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/fuse_conv_bn.py new file mode 100644 index 00000000..9aff4029 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/fuse_conv_bn.py @@ -0,0 +1,68 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse + +import torch +from mmcv.runner import save_checkpoint +from torch import nn as nn + +from mmdet3d.apis import init_model + + +def fuse_conv_bn(conv, bn): + """During inference, the functionary of batch norm layers is turned off but + only the mean and var alone channels are used, which exposes the chance to + fuse it with the preceding conv layers to save computations and simplify + network structures.""" + conv_w = conv.weight + conv_b = conv.bias if conv.bias is not None else torch.zeros_like( + bn.running_mean) + + factor = bn.weight / torch.sqrt(bn.running_var + bn.eps) + conv.weight = nn.Parameter(conv_w * + factor.reshape([conv.out_channels, 1, 1, 1])) + conv.bias = nn.Parameter((conv_b - bn.running_mean) * factor + bn.bias) + return conv + + +def fuse_module(m): + last_conv = None + last_conv_name = None + + for name, child in m.named_children(): + if isinstance(child, (nn.BatchNorm2d, nn.SyncBatchNorm)): + if last_conv is None: # only fuse BN that is after Conv + continue + fused_conv = fuse_conv_bn(last_conv, child) + m._modules[last_conv_name] = fused_conv + # To reduce changes, set BN as Identity instead of deleting it. + m._modules[name] = nn.Identity() + last_conv = None + elif isinstance(child, nn.Conv2d): + last_conv = child + last_conv_name = name + else: + fuse_module(child) + return m + + +def parse_args(): + parser = argparse.ArgumentParser( + description='fuse Conv and BN layers in a model') + parser.add_argument('config', help='config file path') + parser.add_argument('checkpoint', help='checkpoint file path') + parser.add_argument('out', help='output path of the converted model') + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + # build the model from a config file and a checkpoint file + model = init_model(args.config, args.checkpoint) + # fuse conv and bn layers of the model + fused_model = fuse_module(model) + save_checkpoint(fused_model, args.out) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/print_config.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/print_config.py new file mode 100644 index 00000000..c3538ef5 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/print_config.py @@ -0,0 +1,27 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse + +from mmcv import Config, DictAction + + +def parse_args(): + parser = argparse.ArgumentParser(description='Print the whole config') + parser.add_argument('config', help='config file path') + parser.add_argument( + '--options', nargs='+', action=DictAction, help='arguments in dict') + args = parser.parse_args() + + return args + + +def main(): + args = parse_args() + + cfg = Config.fromfile(args.config) + if args.options is not None: + cfg.merge_from_dict(args.options) + print(f'Config:\n{cfg.pretty_text}') + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/visualize_results.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/visualize_results.py new file mode 100644 index 00000000..c59445f6 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/misc/visualize_results.py @@ -0,0 +1,50 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse + +import mmcv +from mmcv import Config + +from mmdet3d.datasets import build_dataset + + +def parse_args(): + parser = argparse.ArgumentParser( + description='MMDet3D visualize the results') + parser.add_argument('config', help='test config file path') + parser.add_argument('--result', help='results file in pickle format') + parser.add_argument( + '--show-dir', help='directory where visualize results will be saved') + args = parser.parse_args() + + return args + + +def main(): + args = parse_args() + + if args.result is not None and \ + not args.result.endswith(('.pkl', '.pickle')): + raise ValueError('The results file must be a pkl file.') + + cfg = Config.fromfile(args.config) + cfg.data.test.test_mode = True + + # build the dataset + dataset = build_dataset(cfg.data.test) + results = mmcv.load(args.result) + + if getattr(dataset, 'show', None) is not None: + # data loading pipeline for showing + eval_pipeline = cfg.get('eval_pipeline', {}) + if eval_pipeline: + dataset.show(results, args.show_dir, pipeline=eval_pipeline) + else: + dataset.show(results, args.show_dir) # use default pipeline + else: + raise NotImplementedError( + 'Show is not implemented for dataset {}!'.format( + type(dataset).__name__)) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_h3dnet_checkpoints.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_h3dnet_checkpoints.py new file mode 100644 index 00000000..2ede340a --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_h3dnet_checkpoints.py @@ -0,0 +1,177 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import tempfile + +import torch +from mmcv import Config +from mmcv.runner import load_state_dict + +from mmdet3d.models import build_detector + + +def parse_args(): + parser = argparse.ArgumentParser( + description='MMDet3D upgrade model version(before v0.6.0) of H3DNet') + parser.add_argument('checkpoint', help='checkpoint file') + parser.add_argument('--out', help='path of the output checkpoint file') + args = parser.parse_args() + return args + + +def parse_config(config_strings): + """Parse config from strings. + + Args: + config_strings (string): strings of model config. + + Returns: + Config: model config + """ + temp_file = tempfile.NamedTemporaryFile() + config_path = f'{temp_file.name}.py' + with open(config_path, 'w') as f: + f.write(config_strings) + + config = Config.fromfile(config_path) + + # Update backbone config + if 'pool_mod' in config.model.backbone.backbones: + config.model.backbone.backbones.pop('pool_mod') + + if 'sa_cfg' not in config.model.backbone: + config.model.backbone['sa_cfg'] = dict( + type='PointSAModule', + pool_mod='max', + use_xyz=True, + normalize_xyz=True) + + if 'type' not in config.model.rpn_head.vote_aggregation_cfg: + config.model.rpn_head.vote_aggregation_cfg['type'] = 'PointSAModule' + + # Update rpn_head config + if 'pred_layer_cfg' not in config.model.rpn_head: + config.model.rpn_head['pred_layer_cfg'] = dict( + in_channels=128, shared_conv_channels=(128, 128), bias=True) + + if 'feat_channels' in config.model.rpn_head: + config.model.rpn_head.pop('feat_channels') + + if 'vote_moudule_cfg' in config.model.rpn_head: + config.model.rpn_head['vote_module_cfg'] = config.model.rpn_head.pop( + 'vote_moudule_cfg') + + if config.model.rpn_head.vote_aggregation_cfg.use_xyz: + config.model.rpn_head.vote_aggregation_cfg.mlp_channels[0] -= 3 + + for cfg in config.model.roi_head.primitive_list: + cfg['vote_module_cfg'] = cfg.pop('vote_moudule_cfg') + cfg.vote_aggregation_cfg.mlp_channels[0] -= 3 + if 'type' not in cfg.vote_aggregation_cfg: + cfg.vote_aggregation_cfg['type'] = 'PointSAModule' + + if 'type' not in config.model.roi_head.bbox_head.suface_matching_cfg: + config.model.roi_head.bbox_head.suface_matching_cfg[ + 'type'] = 'PointSAModule' + + if config.model.roi_head.bbox_head.suface_matching_cfg.use_xyz: + config.model.roi_head.bbox_head.suface_matching_cfg.mlp_channels[ + 0] -= 3 + + if 'type' not in config.model.roi_head.bbox_head.line_matching_cfg: + config.model.roi_head.bbox_head.line_matching_cfg[ + 'type'] = 'PointSAModule' + + if config.model.roi_head.bbox_head.line_matching_cfg.use_xyz: + config.model.roi_head.bbox_head.line_matching_cfg.mlp_channels[0] -= 3 + + if 'proposal_module_cfg' in config.model.roi_head.bbox_head: + config.model.roi_head.bbox_head.pop('proposal_module_cfg') + + temp_file.close() + + return config + + +def main(): + """Convert keys in checkpoints for VoteNet. + + There can be some breaking changes during the development of mmdetection3d, + and this tool is used for upgrading checkpoints trained with old versions + (before v0.6.0) to the latest one. + """ + args = parse_args() + checkpoint = torch.load(args.checkpoint) + cfg = parse_config(checkpoint['meta']['config']) + # Build the model and load checkpoint + model = build_detector( + cfg.model, + train_cfg=cfg.get('train_cfg'), + test_cfg=cfg.get('test_cfg')) + orig_ckpt = checkpoint['state_dict'] + converted_ckpt = orig_ckpt.copy() + + if cfg['dataset_type'] == 'ScanNetDataset': + NUM_CLASSES = 18 + elif cfg['dataset_type'] == 'SUNRGBDDataset': + NUM_CLASSES = 10 + else: + raise NotImplementedError + + RENAME_PREFIX = { + 'rpn_head.conv_pred.0': 'rpn_head.conv_pred.shared_convs.layer0', + 'rpn_head.conv_pred.1': 'rpn_head.conv_pred.shared_convs.layer1' + } + + DEL_KEYS = [ + 'rpn_head.conv_pred.0.bn.num_batches_tracked', + 'rpn_head.conv_pred.1.bn.num_batches_tracked' + ] + + EXTRACT_KEYS = { + 'rpn_head.conv_pred.conv_cls.weight': + ('rpn_head.conv_pred.conv_out.weight', [(0, 2), (-NUM_CLASSES, -1)]), + 'rpn_head.conv_pred.conv_cls.bias': + ('rpn_head.conv_pred.conv_out.bias', [(0, 2), (-NUM_CLASSES, -1)]), + 'rpn_head.conv_pred.conv_reg.weight': + ('rpn_head.conv_pred.conv_out.weight', [(2, -NUM_CLASSES)]), + 'rpn_head.conv_pred.conv_reg.bias': + ('rpn_head.conv_pred.conv_out.bias', [(2, -NUM_CLASSES)]) + } + + # Delete some useless keys + for key in DEL_KEYS: + converted_ckpt.pop(key) + + # Rename keys with specific prefix + RENAME_KEYS = dict() + for old_key in converted_ckpt.keys(): + for rename_prefix in RENAME_PREFIX.keys(): + if rename_prefix in old_key: + new_key = old_key.replace(rename_prefix, + RENAME_PREFIX[rename_prefix]) + RENAME_KEYS[new_key] = old_key + for new_key, old_key in RENAME_KEYS.items(): + converted_ckpt[new_key] = converted_ckpt.pop(old_key) + + # Extract weights and rename the keys + for new_key, (old_key, indices) in EXTRACT_KEYS.items(): + cur_layers = orig_ckpt[old_key] + converted_layers = [] + for (start, end) in indices: + if end != -1: + converted_layers.append(cur_layers[start:end]) + else: + converted_layers.append(cur_layers[start:]) + converted_layers = torch.cat(converted_layers, 0) + converted_ckpt[new_key] = converted_layers + if old_key in converted_ckpt.keys(): + converted_ckpt.pop(old_key) + + # Check the converted checkpoint by loading to the model + load_state_dict(model, converted_ckpt, strict=True) + checkpoint['state_dict'] = converted_ckpt + torch.save(checkpoint, args.out) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_votenet_checkpoints.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_votenet_checkpoints.py new file mode 100644 index 00000000..7264e319 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/convert_votenet_checkpoints.py @@ -0,0 +1,153 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import tempfile + +import torch +from mmcv import Config +from mmcv.runner import load_state_dict + +from mmdet3d.models import build_detector + + +def parse_args(): + parser = argparse.ArgumentParser( + description='MMDet3D upgrade model version(before v0.6.0) of VoteNet') + parser.add_argument('checkpoint', help='checkpoint file') + parser.add_argument('--out', help='path of the output checkpoint file') + args = parser.parse_args() + return args + + +def parse_config(config_strings): + """Parse config from strings. + + Args: + config_strings (string): strings of model config. + + Returns: + Config: model config + """ + temp_file = tempfile.NamedTemporaryFile() + config_path = f'{temp_file.name}.py' + with open(config_path, 'w') as f: + f.write(config_strings) + + config = Config.fromfile(config_path) + + # Update backbone config + if 'pool_mod' in config.model.backbone: + config.model.backbone.pop('pool_mod') + + if 'sa_cfg' not in config.model.backbone: + config.model.backbone['sa_cfg'] = dict( + type='PointSAModule', + pool_mod='max', + use_xyz=True, + normalize_xyz=True) + + if 'type' not in config.model.bbox_head.vote_aggregation_cfg: + config.model.bbox_head.vote_aggregation_cfg['type'] = 'PointSAModule' + + # Update bbox_head config + if 'pred_layer_cfg' not in config.model.bbox_head: + config.model.bbox_head['pred_layer_cfg'] = dict( + in_channels=128, shared_conv_channels=(128, 128), bias=True) + + if 'feat_channels' in config.model.bbox_head: + config.model.bbox_head.pop('feat_channels') + + if 'vote_moudule_cfg' in config.model.bbox_head: + config.model.bbox_head['vote_module_cfg'] = config.model.bbox_head.pop( + 'vote_moudule_cfg') + + if config.model.bbox_head.vote_aggregation_cfg.use_xyz: + config.model.bbox_head.vote_aggregation_cfg.mlp_channels[0] -= 3 + + temp_file.close() + + return config + + +def main(): + """Convert keys in checkpoints for VoteNet. + + There can be some breaking changes during the development of mmdetection3d, + and this tool is used for upgrading checkpoints trained with old versions + (before v0.6.0) to the latest one. + """ + args = parse_args() + checkpoint = torch.load(args.checkpoint) + cfg = parse_config(checkpoint['meta']['config']) + # Build the model and load checkpoint + model = build_detector( + cfg.model, + train_cfg=cfg.get('train_cfg'), + test_cfg=cfg.get('test_cfg')) + orig_ckpt = checkpoint['state_dict'] + converted_ckpt = orig_ckpt.copy() + + if cfg['dataset_type'] == 'ScanNetDataset': + NUM_CLASSES = 18 + elif cfg['dataset_type'] == 'SUNRGBDDataset': + NUM_CLASSES = 10 + else: + raise NotImplementedError + + RENAME_PREFIX = { + 'bbox_head.conv_pred.0': 'bbox_head.conv_pred.shared_convs.layer0', + 'bbox_head.conv_pred.1': 'bbox_head.conv_pred.shared_convs.layer1' + } + + DEL_KEYS = [ + 'bbox_head.conv_pred.0.bn.num_batches_tracked', + 'bbox_head.conv_pred.1.bn.num_batches_tracked' + ] + + EXTRACT_KEYS = { + 'bbox_head.conv_pred.conv_cls.weight': + ('bbox_head.conv_pred.conv_out.weight', [(0, 2), (-NUM_CLASSES, -1)]), + 'bbox_head.conv_pred.conv_cls.bias': + ('bbox_head.conv_pred.conv_out.bias', [(0, 2), (-NUM_CLASSES, -1)]), + 'bbox_head.conv_pred.conv_reg.weight': + ('bbox_head.conv_pred.conv_out.weight', [(2, -NUM_CLASSES)]), + 'bbox_head.conv_pred.conv_reg.bias': + ('bbox_head.conv_pred.conv_out.bias', [(2, -NUM_CLASSES)]) + } + + # Delete some useless keys + for key in DEL_KEYS: + converted_ckpt.pop(key) + + # Rename keys with specific prefix + RENAME_KEYS = dict() + for old_key in converted_ckpt.keys(): + for rename_prefix in RENAME_PREFIX.keys(): + if rename_prefix in old_key: + new_key = old_key.replace(rename_prefix, + RENAME_PREFIX[rename_prefix]) + RENAME_KEYS[new_key] = old_key + for new_key, old_key in RENAME_KEYS.items(): + converted_ckpt[new_key] = converted_ckpt.pop(old_key) + + # Extract weights and rename the keys + for new_key, (old_key, indices) in EXTRACT_KEYS.items(): + cur_layers = orig_ckpt[old_key] + converted_layers = [] + for (start, end) in indices: + if end != -1: + converted_layers.append(cur_layers[start:end]) + else: + converted_layers.append(cur_layers[start:]) + converted_layers = torch.cat(converted_layers, 0) + converted_ckpt[new_key] = converted_layers + if old_key in converted_ckpt.keys(): + converted_ckpt.pop(old_key) + + # Check the converted checkpoint by loading to the model + load_state_dict(model, converted_ckpt, strict=True) + checkpoint['state_dict'] = converted_ckpt + torch.save(checkpoint, args.out) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/publish_model.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/publish_model.py new file mode 100644 index 00000000..e2660578 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/publish_model.py @@ -0,0 +1,36 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import subprocess + +import torch + + +def parse_args(): + parser = argparse.ArgumentParser( + description='Process a checkpoint to be published') + parser.add_argument('in_file', help='input checkpoint filename') + parser.add_argument('out_file', help='output checkpoint filename') + args = parser.parse_args() + return args + + +def process_checkpoint(in_file, out_file): + checkpoint = torch.load(in_file, map_location='cpu') + # remove optimizer for smaller file size + if 'optimizer' in checkpoint: + del checkpoint['optimizer'] + # if it is necessary to remove some sensitive data in checkpoint['meta'], + # add the code here. + torch.save(checkpoint, out_file) + sha = subprocess.check_output(['sha256sum', out_file]).decode() + final_file = out_file.rstrip('.pth') + '-{}.pth'.format(sha[:8]) + subprocess.Popen(['mv', out_file, final_file]) + + +def main(): + args = parse_args() + process_checkpoint(args.in_file, args.out_file) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/regnet2mmdet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/regnet2mmdet.py new file mode 100644 index 00000000..fbf8c8f3 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/model_converters/regnet2mmdet.py @@ -0,0 +1,90 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +from collections import OrderedDict + +import torch + + +def convert_stem(model_key, model_weight, state_dict, converted_names): + new_key = model_key.replace('stem.conv', 'conv1') + new_key = new_key.replace('stem.bn', 'bn1') + state_dict[new_key] = model_weight + converted_names.add(model_key) + print(f'Convert {model_key} to {new_key}') + + +def convert_head(model_key, model_weight, state_dict, converted_names): + new_key = model_key.replace('head.fc', 'fc') + state_dict[new_key] = model_weight + converted_names.add(model_key) + print(f'Convert {model_key} to {new_key}') + + +def convert_reslayer(model_key, model_weight, state_dict, converted_names): + split_keys = model_key.split('.') + layer, block, module = split_keys[:3] + block_id = int(block[1:]) + layer_name = f'layer{int(layer[1:])}' + block_name = f'{block_id - 1}' + + if block_id == 1 and module == 'bn': + new_key = f'{layer_name}.{block_name}.downsample.1.{split_keys[-1]}' + elif block_id == 1 and module == 'proj': + new_key = f'{layer_name}.{block_name}.downsample.0.{split_keys[-1]}' + elif module == 'f': + if split_keys[3] == 'a_bn': + module_name = 'bn1' + elif split_keys[3] == 'b_bn': + module_name = 'bn2' + elif split_keys[3] == 'c_bn': + module_name = 'bn3' + elif split_keys[3] == 'a': + module_name = 'conv1' + elif split_keys[3] == 'b': + module_name = 'conv2' + elif split_keys[3] == 'c': + module_name = 'conv3' + new_key = f'{layer_name}.{block_name}.{module_name}.{split_keys[-1]}' + else: + raise ValueError(f'Unsupported conversion of key {model_key}') + print(f'Convert {model_key} to {new_key}') + state_dict[new_key] = model_weight + converted_names.add(model_key) + + +def convert(src, dst): + """Convert keys in pycls pretrained RegNet models to mmdet style.""" + # load caffe model + regnet_model = torch.load(src) + blobs = regnet_model['model_state'] + # convert to pytorch style + state_dict = OrderedDict() + converted_names = set() + for key, weight in blobs.items(): + if 'stem' in key: + convert_stem(key, weight, state_dict, converted_names) + elif 'head' in key: + convert_head(key, weight, state_dict, converted_names) + elif key.startswith('s'): + convert_reslayer(key, weight, state_dict, converted_names) + + # check if all layers are converted + for key in blobs: + if key not in converted_names: + print(f'not converted: {key}') + # save checkpoint + checkpoint = dict() + checkpoint['state_dict'] = state_dict + torch.save(checkpoint, dst) + + +def main(): + parser = argparse.ArgumentParser(description='Convert model keys') + parser.add_argument('src', help='src detectron model path') + parser.add_argument('dst', help='save path') + args = parser.parse_args() + convert(args.src, args.dst) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_test.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_test.sh new file mode 100644 index 00000000..6dd67e57 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_test.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -x + +PARTITION=$1 +JOB_NAME=$2 +CONFIG=$3 +CHECKPOINT=$4 +GPUS=${GPUS:-8} +GPUS_PER_NODE=${GPUS_PER_NODE:-8} +CPUS_PER_TASK=${CPUS_PER_TASK:-5} +PY_ARGS=${@:5} +SRUN_ARGS=${SRUN_ARGS:-""} + +PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ +srun -p ${PARTITION} \ + --job-name=${JOB_NAME} \ + --gres=gpu:${GPUS_PER_NODE} \ + --ntasks=${GPUS} \ + --ntasks-per-node=${GPUS_PER_NODE} \ + --cpus-per-task=${CPUS_PER_TASK} \ + --kill-on-bad-exit=1 \ + ${SRUN_ARGS} \ + python -u tools/test.py ${CONFIG} ${CHECKPOINT} --launcher="slurm" ${PY_ARGS} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_train.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_train.sh new file mode 100644 index 00000000..b3feb3d9 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/slurm_train.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +set -x + +PARTITION=$1 +JOB_NAME=$2 +CONFIG=$3 +WORK_DIR=$4 +GPUS=${GPUS:-8} +GPUS_PER_NODE=${GPUS_PER_NODE:-8} +CPUS_PER_TASK=${CPUS_PER_TASK:-5} +SRUN_ARGS=${SRUN_ARGS:-""} +PY_ARGS=${@:5} + +PYTHONPATH="$(dirname $0)/..":$PYTHONPATH \ +srun -p ${PARTITION} \ + --job-name=${JOB_NAME} \ + --gres=gpu:${GPUS_PER_NODE} \ + --ntasks=${GPUS} \ + --ntasks-per-node=${GPUS_PER_NODE} \ + --cpus-per-task=${CPUS_PER_TASK} \ + --kill-on-bad-exit=1 \ + ${SRUN_ARGS} \ + python -u tools/train.py ${CONFIG} --work-dir=${WORK_DIR} --launcher="slurm" ${PY_ARGS} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/test.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/test.py new file mode 100644 index 00000000..bd9d95f4 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/test.py @@ -0,0 +1,260 @@ +# Copyright (c) OpenMMLab. All rights reserved. +import argparse +import os +import warnings + +import mmcv +import torch +from mmcv import Config, DictAction +from mmcv.cnn import fuse_conv_bn +from mmcv.parallel import MMDataParallel, MMDistributedDataParallel +from mmcv.runner import (get_dist_info, init_dist, load_checkpoint, + wrap_fp16_model) + +import mmdet +from mmdet3d.apis import single_gpu_test +from mmdet3d.datasets import build_dataloader, build_dataset +from mmdet3d.models import build_model +from mmdet.apis import multi_gpu_test, set_random_seed +from mmdet.datasets import replace_ImageToTensor + +if mmdet.__version__ > '2.23.0': + # If mmdet version > 2.23.0, setup_multi_processes would be imported and + # used from mmdet instead of mmdet3d. + from mmdet.utils import setup_multi_processes +else: + from mmdet3d.utils import setup_multi_processes + +try: + # If mmdet version > 2.23.0, compat_cfg would be imported and + # used from mmdet instead of mmdet3d. + from mmdet.utils import compat_cfg +except ImportError: + from mmdet3d.utils import compat_cfg + + +def parse_args(): + parser = argparse.ArgumentParser( + description='MMDet test (and eval) a model') + parser.add_argument('config', help='test config file path') + parser.add_argument('checkpoint', help='checkpoint file') + parser.add_argument('--out', help='output result file in pickle format') + parser.add_argument( + '--fuse-conv-bn', + action='store_true', + help='Whether to fuse conv and bn, this will slightly increase' + 'the inference speed') + parser.add_argument( + '--gpu-ids', + type=int, + nargs='+', + help='(Deprecated, please use --gpu-id) ids of gpus to use ' + '(only applicable to non-distributed training)') + parser.add_argument( + '--gpu-id', + type=int, + default=0, + help='id of gpu to use ' + '(only applicable to non-distributed testing)') + parser.add_argument( + '--format-only', + action='store_true', + help='Format the output results without perform evaluation. It is' + 'useful when you want to format the result to a specific format and ' + 'submit it to the test server') + parser.add_argument( + '--eval', + type=str, + nargs='+', + help='evaluation metrics, which depends on the dataset, e.g., "bbox",' + ' "segm", "proposal" for COCO, and "mAP", "recall" for PASCAL VOC') + parser.add_argument('--show', action='store_true', help='show results') + parser.add_argument( + '--show-dir', help='directory where results will be saved') + parser.add_argument( + '--gpu-collect', + action='store_true', + help='whether to use gpu to collect results.') + parser.add_argument( + '--tmpdir', + help='tmp directory used for collecting results from multiple ' + 'workers, available when gpu-collect is not specified') + parser.add_argument('--seed', type=int, default=0, help='random seed') + parser.add_argument( + '--deterministic', + action='store_true', + help='whether to set deterministic options for CUDNN backend.') + parser.add_argument( + '--cfg-options', + nargs='+', + action=DictAction, + help='override some settings in the used config, the key-value pair ' + 'in xxx=yyy format will be merged into config file. If the value to ' + 'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' + 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' + 'Note that the quotation marks are necessary and that no white space ' + 'is allowed.') + parser.add_argument( + '--options', + nargs='+', + action=DictAction, + help='custom options for evaluation, the key-value pair in xxx=yyy ' + 'format will be kwargs for dataset.evaluate() function (deprecate), ' + 'change to --eval-options instead.') + parser.add_argument( + '--eval-options', + nargs='+', + action=DictAction, + help='custom options for evaluation, the key-value pair in xxx=yyy ' + 'format will be kwargs for dataset.evaluate() function') + parser.add_argument( + '--launcher', + choices=['none', 'pytorch', 'slurm', 'mpi'], + default='none', + help='job launcher') + parser.add_argument('--local_rank', type=int, default=0) + args = parser.parse_args() + if 'LOCAL_RANK' not in os.environ: + os.environ['LOCAL_RANK'] = str(args.local_rank) + + if args.options and args.eval_options: + raise ValueError( + '--options and --eval-options cannot be both specified, ' + '--options is deprecated in favor of --eval-options') + if args.options: + warnings.warn('--options is deprecated in favor of --eval-options') + args.eval_options = args.options + return args + + +def main(): + args = parse_args() + + assert args.out or args.eval or args.format_only or args.show \ + or args.show_dir, \ + ('Please specify at least one operation (save/eval/format/show the ' + 'results / save the results) with the argument "--out", "--eval"' + ', "--format-only", "--show" or "--show-dir"') + + if args.eval and args.format_only: + raise ValueError('--eval and --format_only cannot be both specified') + + if args.out is not None and not args.out.endswith(('.pkl', '.pickle')): + raise ValueError('The output file must be a pkl file.') + + cfg = Config.fromfile(args.config) + if args.cfg_options is not None: + cfg.merge_from_dict(args.cfg_options) + + cfg = compat_cfg(cfg) + + # set multi-process settings + setup_multi_processes(cfg) + + # set cudnn_benchmark + if cfg.get('cudnn_benchmark', False): + torch.backends.cudnn.benchmark = True + + cfg.model.pretrained = None + + if args.gpu_ids is not None: + cfg.gpu_ids = args.gpu_ids[0:1] + warnings.warn('`--gpu-ids` is deprecated, please use `--gpu-id`. ' + 'Because we only support single GPU mode in ' + 'non-distributed testing. Use the first GPU ' + 'in `gpu_ids` now.') + else: + cfg.gpu_ids = [args.gpu_id] + + # init distributed env first, since logger depends on the dist info. + if args.launcher == 'none': + distributed = False + else: + distributed = True + init_dist(args.launcher, **cfg.dist_params) + + test_dataloader_default_args = dict( + samples_per_gpu=1, workers_per_gpu=2, dist=distributed, shuffle=False) + + # in case the test dataset is concatenated + if isinstance(cfg.data.test, dict): + cfg.data.test.test_mode = True + if cfg.data.test_dataloader.get('samples_per_gpu', 1) > 1: + # Replace 'ImageToTensor' to 'DefaultFormatBundle' + cfg.data.test.pipeline = replace_ImageToTensor( + cfg.data.test.pipeline) + elif isinstance(cfg.data.test, list): + for ds_cfg in cfg.data.test: + ds_cfg.test_mode = True + if cfg.data.test_dataloader.get('samples_per_gpu', 1) > 1: + for ds_cfg in cfg.data.test: + ds_cfg.pipeline = replace_ImageToTensor(ds_cfg.pipeline) + + test_loader_cfg = { + **test_dataloader_default_args, + **cfg.data.get('test_dataloader', {}) + } + + # set random seeds + if args.seed is not None: + set_random_seed(args.seed, deterministic=args.deterministic) + + # build the dataloader + dataset = build_dataset(cfg.data.test) + data_loader = build_dataloader(dataset, **test_loader_cfg) + + # build the model and load checkpoint + cfg.model.train_cfg = None + model = build_model(cfg.model, test_cfg=cfg.get('test_cfg')) + fp16_cfg = cfg.get('fp16', None) + if fp16_cfg is not None: + wrap_fp16_model(model) + checkpoint = load_checkpoint(model, args.checkpoint, map_location='cpu') + if args.fuse_conv_bn: + model = fuse_conv_bn(model) + # old versions did not save class info in checkpoints, this walkaround is + # for backward compatibility + if 'CLASSES' in checkpoint.get('meta', {}): + model.CLASSES = checkpoint['meta']['CLASSES'] + else: + model.CLASSES = dataset.CLASSES + # palette for visualization in segmentation tasks + if 'PALETTE' in checkpoint.get('meta', {}): + model.PALETTE = checkpoint['meta']['PALETTE'] + elif hasattr(dataset, 'PALETTE'): + # segmentation dataset has `PALETTE` attribute + model.PALETTE = dataset.PALETTE + + if not distributed: + model = MMDataParallel(model, device_ids=cfg.gpu_ids) + outputs = single_gpu_test(model, data_loader, args.show, args.show_dir) + else: + model = MMDistributedDataParallel( + model.cuda(), + device_ids=[torch.cuda.current_device()], + broadcast_buffers=False) + outputs = multi_gpu_test(model, data_loader, args.tmpdir, + args.gpu_collect) + + rank, _ = get_dist_info() + if rank == 0: + if args.out: + print(f'\nwriting results to {args.out}') + mmcv.dump(outputs, args.out) + kwargs = {} if args.eval_options is None else args.eval_options + if args.format_only: + dataset.format_results(outputs, **kwargs) + if args.eval: + eval_kwargs = cfg.get('evaluation', {}).copy() + # hard-code way to remove EvalHook args + for key in [ + 'interval', 'tmpdir', 'start', 'gpu_collect', 'save_best', + 'rule' + ]: + eval_kwargs.pop(key, None) + eval_kwargs.update(dict(metric=args.eval, **kwargs)) + print(dataset.evaluate(outputs, **eval_kwargs)) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/train.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/train.py new file mode 100644 index 00000000..ed9c2a6b --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/train.py @@ -0,0 +1,263 @@ +# Copyright (c) OpenMMLab. All rights reserved. +from __future__ import division +import argparse +import copy +import os +import time +import warnings +from os import path as osp + +import mmcv +import torch +import torch.distributed as dist +from mmcv import Config, DictAction +from mmcv.runner import get_dist_info, init_dist + +from mmdet import __version__ as mmdet_version +from mmdet3d import __version__ as mmdet3d_version +from mmdet3d.apis import init_random_seed, train_model +from mmdet3d.datasets import build_dataset +from mmdet3d.models import build_model +from mmdet3d.utils import collect_env, get_root_logger +from mmdet.apis import set_random_seed +from mmseg import __version__ as mmseg_version + +try: + # If mmdet version > 2.20.0, setup_multi_processes would be imported and + # used from mmdet instead of mmdet3d. + from mmdet.utils import setup_multi_processes +except ImportError: + from mmdet3d.utils import setup_multi_processes + + +def parse_args(): + parser = argparse.ArgumentParser(description='Train a detector') + parser.add_argument('config', help='train config file path') + parser.add_argument('--work-dir', help='the dir to save logs and models') + parser.add_argument( + '--resume-from', help='the checkpoint file to resume from') + parser.add_argument( + '--auto-resume', + action='store_true', + help='resume from the latest checkpoint automatically') + parser.add_argument( + '--no-validate', + action='store_true', + help='whether not to evaluate the checkpoint during training') + group_gpus = parser.add_mutually_exclusive_group() + group_gpus.add_argument( + '--gpus', + type=int, + help='(Deprecated, please use --gpu-id) number of gpus to use ' + '(only applicable to non-distributed training)') + group_gpus.add_argument( + '--gpu-ids', + type=int, + nargs='+', + help='(Deprecated, please use --gpu-id) ids of gpus to use ' + '(only applicable to non-distributed training)') + group_gpus.add_argument( + '--gpu-id', + type=int, + default=0, + help='number of gpus to use ' + '(only applicable to non-distributed training)') + parser.add_argument('--seed', type=int, default=0, help='random seed') + parser.add_argument( + '--diff-seed', + action='store_true', + help='Whether or not set different seeds for different ranks') + parser.add_argument( + '--deterministic', + action='store_true', + help='whether to set deterministic options for CUDNN backend.') + parser.add_argument( + '--options', + nargs='+', + action=DictAction, + help='override some settings in the used config, the key-value pair ' + 'in xxx=yyy format will be merged into config file (deprecate), ' + 'change to --cfg-options instead.') + parser.add_argument( + '--cfg-options', + nargs='+', + action=DictAction, + help='override some settings in the used config, the key-value pair ' + 'in xxx=yyy format will be merged into config file. If the value to ' + 'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' + 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' + 'Note that the quotation marks are necessary and that no white space ' + 'is allowed.') + parser.add_argument( + '--launcher', + choices=['none', 'pytorch', 'slurm', 'mpi'], + default='none', + help='job launcher') + parser.add_argument('--local_rank', type=int, default=0) + parser.add_argument( + '--autoscale-lr', + action='store_true', + help='automatically scale lr with the number of gpus') + args = parser.parse_args() + if 'LOCAL_RANK' not in os.environ: + os.environ['LOCAL_RANK'] = str(args.local_rank) + + if args.options and args.cfg_options: + raise ValueError( + '--options and --cfg-options cannot be both specified, ' + '--options is deprecated in favor of --cfg-options') + if args.options: + warnings.warn('--options is deprecated in favor of --cfg-options') + args.cfg_options = args.options + + return args + + +def main(): + args = parse_args() + + cfg = Config.fromfile(args.config) + if args.cfg_options is not None: + cfg.merge_from_dict(args.cfg_options) + + # set multi-process settings + setup_multi_processes(cfg) + + # set cudnn_benchmark + if cfg.get('cudnn_benchmark', False): + torch.backends.cudnn.benchmark = True + + # work_dir is determined in this priority: CLI > segment in file > filename + if args.work_dir is not None: + # update configs according to CLI args if args.work_dir is not None + cfg.work_dir = args.work_dir + elif cfg.get('work_dir', None) is None: + # use config filename as default work_dir if cfg.work_dir is None + cfg.work_dir = osp.join('./work_dirs', + osp.splitext(osp.basename(args.config))[0]) + if args.resume_from is not None: + cfg.resume_from = args.resume_from + + if args.auto_resume: + cfg.auto_resume = args.auto_resume + warnings.warn('`--auto-resume` is only supported when mmdet' + 'version >= 2.20.0 for 3D detection model or' + 'mmsegmentation verision >= 0.21.0 for 3D' + 'segmentation model') + + if args.gpus is not None: + cfg.gpu_ids = range(1) + warnings.warn('`--gpus` is deprecated because we only support ' + 'single GPU mode in non-distributed training. ' + 'Use `gpus=1` now.') + if args.gpu_ids is not None: + cfg.gpu_ids = args.gpu_ids[0:1] + warnings.warn('`--gpu-ids` is deprecated, please use `--gpu-id`. ' + 'Because we only support single GPU mode in ' + 'non-distributed training. Use the first GPU ' + 'in `gpu_ids` now.') + if args.gpus is None and args.gpu_ids is None: + cfg.gpu_ids = [args.gpu_id] + + if args.autoscale_lr: + # apply the linear scaling rule (https://arxiv.org/abs/1706.02677) + cfg.optimizer['lr'] = cfg.optimizer['lr'] * len(cfg.gpu_ids) / 8 + + # init distributed env first, since logger depends on the dist info. + if args.launcher == 'none': + distributed = False + else: + distributed = True + init_dist(args.launcher, **cfg.dist_params) + # re-set gpu_ids with distributed training mode + _, world_size = get_dist_info() + cfg.gpu_ids = range(world_size) + + # create work_dir + mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir)) + # dump config + cfg.dump(osp.join(cfg.work_dir, osp.basename(args.config))) + # init the logger before other steps + timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) + log_file = osp.join(cfg.work_dir, f'{timestamp}.log') + # specify logger name, if we still use 'mmdet', the output info will be + # filtered and won't be saved in the log_file + # TODO: ugly workaround to judge whether we are training det or seg model + if cfg.model.type in ['EncoderDecoder3D']: + logger_name = 'mmseg' + else: + logger_name = 'mmdet' + logger = get_root_logger( + log_file=log_file, log_level=cfg.log_level, name=logger_name) + + # init the meta dict to record some important information such as + # environment info and seed, which will be logged + meta = dict() + # log env info + env_info_dict = collect_env() + env_info = '\n'.join([(f'{k}: {v}') for k, v in env_info_dict.items()]) + dash_line = '-' * 60 + '\n' + logger.info('Environment info:\n' + dash_line + env_info + '\n' + + dash_line) + meta['env_info'] = env_info + meta['config'] = cfg.pretty_text + + # log some basic info + logger.info(f'Distributed training: {distributed}') + logger.info(f'Config:\n{cfg.pretty_text}') + + # set random seeds + seed = init_random_seed(args.seed) + seed = seed + dist.get_rank() if args.diff_seed else seed + logger.info(f'Set random seed to {seed}, ' + f'deterministic: {args.deterministic}') + set_random_seed(seed, deterministic=args.deterministic) + cfg.seed = seed + meta['seed'] = seed + meta['exp_name'] = osp.basename(args.config) + + model = build_model( + cfg.model, + train_cfg=cfg.get('train_cfg'), + test_cfg=cfg.get('test_cfg')) + model.init_weights() + + logger.info(f'Model:\n{model}') + datasets = [build_dataset(cfg.data.train)] + if len(cfg.workflow) == 2: + val_dataset = copy.deepcopy(cfg.data.val) + # in case we use a dataset wrapper + if 'dataset' in cfg.data.train: + val_dataset.pipeline = cfg.data.train.dataset.pipeline + else: + val_dataset.pipeline = cfg.data.train.pipeline + # set test_mode=False here in deep copied config + # which do not affect AP/AR calculation later + # refer to https://mmdetection3d.readthedocs.io/en/latest/tutorials/customize_runtime.html#customize-workflow # noqa + val_dataset.test_mode = False + datasets.append(build_dataset(val_dataset)) + if cfg.checkpoint_config is not None: + # save mmdet version, config file content and class names in + # checkpoints as meta data + cfg.checkpoint_config.meta = dict( + mmdet_version=mmdet_version, + mmseg_version=mmseg_version, + mmdet3d_version=mmdet3d_version, + config=cfg.pretty_text, + CLASSES=datasets[0].CLASSES, + PALETTE=datasets[0].PALETTE # for segmentors + if hasattr(datasets[0], 'PALETTE') else None) + # add an attribute for visualization convenience + model.CLASSES = datasets[0].CLASSES + train_model( + model, + datasets, + cfg, + distributed=distributed, + validate=(not args.no_validate), + timestamp=timestamp, + meta=meta) + + +if __name__ == '__main__': + main() diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.py new file mode 100644 index 00000000..94728bcc --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.py @@ -0,0 +1,168 @@ +import argparse +import time +from os import path as osp + +import mmcv +import numpy as np + +from mmdet3d.core.bbox import limit_period + + +def update_sunrgbd_infos(root_dir, out_dir, pkl_files): + print(f'{pkl_files} will be modified because ' + f'of the refactor of the Depth coordinate system.') + if root_dir == out_dir: + print(f'Warning, you are overwriting ' + f'the original data under {root_dir}.') + time.sleep(3) + for pkl_file in pkl_files: + in_path = osp.join(root_dir, pkl_file) + print(f'Reading from input file: {in_path}.') + a = mmcv.load(in_path) + print('Start updating:') + for item in mmcv.track_iter_progress(a): + if 'rotation_y' in item['annos']: + item['annos']['rotation_y'] = -item['annos']['rotation_y'] + item['annos']['gt_boxes_upright_depth'][:, -1:] = \ + -item['annos']['gt_boxes_upright_depth'][:, -1:] + + out_path = osp.join(out_dir, pkl_file) + print(f'Writing to output file: {out_path}.') + mmcv.dump(a, out_path, 'pkl') + + +def update_outdoor_dbinfos(root_dir, out_dir, pkl_files): + print(f'{pkl_files} will be modified because ' + f'of the refactor of the LIDAR coordinate system.') + if root_dir == out_dir: + print(f'Warning, you are overwriting ' + f'the original data under {root_dir}.') + time.sleep(3) + for pkl_file in pkl_files: + in_path = osp.join(root_dir, pkl_file) + print(f'Reading from input file: {in_path}.') + a = mmcv.load(in_path) + print('Start updating:') + for k in a.keys(): + print(f'Updating samples of class {k}:') + for item in mmcv.track_iter_progress(a[k]): + boxes = item['box3d_lidar'].copy() + # swap l, w (or dx, dy) + item['box3d_lidar'][3] = boxes[4] + item['box3d_lidar'][4] = boxes[3] + # change yaw + item['box3d_lidar'][6] = -boxes[6] - np.pi / 2 + item['box3d_lidar'][6] = limit_period( + item['box3d_lidar'][6], period=np.pi * 2) + + out_path = osp.join(out_dir, pkl_file) + print(f'Writing to output file: {out_path}.') + mmcv.dump(a, out_path, 'pkl') + + +def update_nuscenes_or_lyft_infos(root_dir, out_dir, pkl_files): + + print(f'{pkl_files} will be modified because ' + f'of the refactor of the LIDAR coordinate system.') + if root_dir == out_dir: + print(f'Warning, you are overwriting ' + f'the original data under {root_dir}.') + time.sleep(3) + for pkl_file in pkl_files: + in_path = osp.join(root_dir, pkl_file) + print(f'Reading from input file: {in_path}.') + a = mmcv.load(in_path) + print('Start updating:') + for item in mmcv.track_iter_progress(a['infos']): + boxes = item['gt_boxes'].copy() + # swap l, w (or dx, dy) + item['gt_boxes'][:, 3] = boxes[:, 4] + item['gt_boxes'][:, 4] = boxes[:, 3] + # change yaw + item['gt_boxes'][:, 6] = -boxes[:, 6] - np.pi / 2 + item['gt_boxes'][:, 6] = limit_period( + item['gt_boxes'][:, 6], period=np.pi * 2) + + out_path = osp.join(out_dir, pkl_file) + print(f'Writing to output file: {out_path}.') + mmcv.dump(a, out_path, 'pkl') + + +parser = argparse.ArgumentParser(description='Arg parser for data coords ' + 'update due to coords sys refactor.') +parser.add_argument('dataset', metavar='kitti', help='name of the dataset') +parser.add_argument( + '--root-dir', + type=str, + default='./data/kitti', + help='specify the root dir of dataset') +parser.add_argument( + '--version', + type=str, + default='v1.0', + required=False, + help='specify the dataset version, no need for kitti') +parser.add_argument( + '--out-dir', + type=str, + default=None, + required=False, + help='name of info pkl') +args = parser.parse_args() + +if __name__ == '__main__': + if args.out_dir is None: + args.out_dir = args.root_dir + if args.dataset == 'kitti': + # KITTI infos is in CAM coord sys (unchanged) + # KITTI dbinfos is in LIDAR coord sys (changed) + # so we only update dbinfos + pkl_files = ['kitti_dbinfos_train.pkl'] + update_outdoor_dbinfos( + root_dir=args.root_dir, out_dir=args.out_dir, pkl_files=pkl_files) + elif args.dataset == 'nuscenes': + # nuScenes infos is in LIDAR coord sys (changed) + # nuScenes dbinfos is in LIDAR coord sys (changed) + # so we update both infos and dbinfos + pkl_files = ['nuscenes_infos_val.pkl'] + if args.version != 'v1.0-mini': + pkl_files.append('nuscenes_infos_train.pkl') + else: + pkl_files.append('nuscenes_infos_train_tiny.pkl') + update_nuscenes_or_lyft_infos( + root_dir=args.root_dir, out_dir=args.out_dir, pkl_files=pkl_files) + if args.version != 'v1.0-mini': + pkl_files = ['nuscenes_dbinfos_train.pkl'] + update_outdoor_dbinfos( + root_dir=args.root_dir, + out_dir=args.out_dir, + pkl_files=pkl_files) + elif args.dataset == 'lyft': + # Lyft infos is in LIDAR coord sys (changed) + # Lyft has no dbinfos + # so we update infos + pkl_files = ['lyft_infos_train.pkl', 'lyft_infos_val.pkl'] + update_nuscenes_or_lyft_infos( + root_dir=args.root_dir, out_dir=args.out_dir, pkl_files=pkl_files) + elif args.dataset == 'waymo': + # Waymo infos is in CAM coord sys (unchanged) + # Waymo dbinfos is in LIDAR coord sys (changed) + # so we only update dbinfos + pkl_files = ['waymo_dbinfos_train.pkl'] + update_outdoor_dbinfos( + root_dir=args.root_dir, out_dir=args.out_dir, pkl_files=pkl_files) + elif args.dataset == 'scannet': + # ScanNet infos is in DEPTH coord sys (changed) + # but bbox is without yaw + # so ScanNet is unaffected + pass + elif args.dataset == 's3dis': + # Segmentation datasets are not affected + pass + elif args.dataset == 'sunrgbd': + # SUNRGBD infos is in DEPTH coord sys (changed) + # and bbox is with yaw + # so we update infos + pkl_files = ['sunrgbd_infos_train.pkl', 'sunrgbd_infos_val.pkl'] + update_sunrgbd_infos( + root_dir=args.root_dir, out_dir=args.out_dir, pkl_files=pkl_files) diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.sh new file mode 100644 index 00000000..bd8db628 --- /dev/null +++ b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/.mim/tools/update_data_coords.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -x +export PYTHONPATH=`pwd`:$PYTHONPATH + +PARTITION=$1 +DATASET=$2 +GPUS=${GPUS:-1} +GPUS_PER_NODE=${GPUS_PER_NODE:-1} +SRUN_ARGS=${SRUN_ARGS:-""} +JOB_NAME=update_data_coords + +srun -p ${PARTITION} \ + --job-name=${JOB_NAME} \ + --gres=gpu:${GPUS_PER_NODE} \ + --ntasks=${GPUS} \ + --ntasks-per-node=${GPUS_PER_NODE} \ + --kill-on-bad-exit=1 \ + ${SRUN_ARGS} \ + python -u tools/update_data_coords.py ${DATASET} \ + --root-dir ./data/${DATASET} \ + --out-dir ./data/${DATASET} diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/inference.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/inference.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/test.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/train.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/anchor_3d_generator.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/anchor/anchor_3d_generator.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/assigners/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/box_np_ops.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/box_np_ops.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/anchor_free_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/anchor_free_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/centerpoint_bbox_coders.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/centerpoint_bbox_coders.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/delta_xyzwhlr_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/delta_xyzwhlr_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/fcos3d_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/fcos3d_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/groupfree3d_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/groupfree3d_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/monoflex_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/monoflex_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/partial_bin_based_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/partial_bin_based_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/pgd_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/pgd_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/point_xyzwhlr_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/point_xyzwhlr_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/smoke_bbox_coder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/coders/smoke_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/iou3d_calculator.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/iou_calculators/iou3d_calculator.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/iou_neg_piecewise_sampler.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/samplers/iou_neg_piecewise_sampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/base_box3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/base_box3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/box_3d_mode.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/box_3d_mode.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/cam_box3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/cam_box3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/coord_3d_mode.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/coord_3d_mode.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/depth_box3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/depth_box3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/lidar_box3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/lidar_box3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/structures/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/transforms.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/indoor_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/indoor_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/instance_seg_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/instance_seg_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/rotate_iou.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/kitti_utils/rotate_iou.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/lyft_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/lyft_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/evaluate_semantic_instance.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/evaluate_semantic_instance.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/util_3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/scannet_utils/util_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/seg_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/seg_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/prediction_kitti_to_waymo.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/evaluation/waymo_utils/prediction_kitti_to_waymo.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/base_points.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/base_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/cam_points.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/cam_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/depth_points.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/depth_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/lidar_points.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/points/lidar_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/box3d_nms.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/box3d_nms.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/merge_augs.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/post_processing/merge_augs.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/array_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/array_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/gaussian.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/utils/gaussian.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/image_vis.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/image_vis.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/open3d_vis.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/open3d_vis.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/show_result.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/visualizer/show_result.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/voxel_generator.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/core/voxel/voxel_generator.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d_seg.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/custom_3d_seg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/dataset_wrappers.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti2d_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti2d_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_mono_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/kitti_mono_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/lyft_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/lyft_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_mono_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/nuscenes_mono_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/compose.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/data_augment_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/data_augment_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/dbsampler.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/dbsampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/formating.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/loading.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/test_time_aug.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/transforms_3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/pipelines/transforms_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/s3dis_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/s3dis_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/scannet_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/scannet_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/semantickitti_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/semantickitti_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/sunrgbd_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/sunrgbd_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/waymo_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/datasets/waymo_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/base_pointnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/base_pointnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dgcnn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dgcnn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dla.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/dla.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/mink_resnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/mink_resnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/multi_backbone.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/multi_backbone.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/nostem_regnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/nostem_regnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_msg.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_msg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_ssg.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/pointnet2_sa_ssg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/second.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/backbones/second.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/decode_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/decode_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/dgcnn_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/dgcnn_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/paconv_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/paconv_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/pointnet2_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/decode_heads/pointnet2_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor_free_mono3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/anchor_free_mono3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_conv_bbox_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_conv_bbox_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_mono3d_dense_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/base_mono3d_dense_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/centerpoint_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/centerpoint_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcaf3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcaf3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcos_mono3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/fcos_mono3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/free_anchor3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/free_anchor3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/groupfree3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/groupfree3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/monoflex_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/monoflex_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/parta2_rpn_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/parta2_rpn_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/pgd_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/pgd_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/point_rpn_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/point_rpn_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/shape_aware_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/shape_aware_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/smoke_mono3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/smoke_mono3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/ssd_3d_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/ssd_3d_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/train_mixins.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/train_mixins.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/vote_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/dense_heads/vote_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/base.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/centerpoint.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/centerpoint.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/dynamic_voxelnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/dynamic_voxelnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/fcos_mono3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/fcos_mono3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/groupfree3dnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/groupfree3dnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/h3dnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/h3dnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvotenet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvotenet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvoxelnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/imvoxelnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mink_single_stage.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mink_single_stage.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_faster_rcnn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_faster_rcnn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_two_stage.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/mvx_two_stage.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/parta2.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/parta2.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/point_rcnn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/point_rcnn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/sassd.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/sassd.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage_mono3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/single_stage_mono3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/smoke_mono3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/smoke_mono3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/ssd3dnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/ssd3dnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/two_stage.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/two_stage.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/votenet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/votenet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/voxelnet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/detectors/voxelnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/coord_transform.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/coord_transform.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/point_fusion.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/point_fusion.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/vote_fusion.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/fusion_layers/vote_fusion.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/axis_aligned_iou_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/axis_aligned_iou_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/chamfer_distance.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/chamfer_distance.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/multibin_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/multibin_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/paconv_regularization_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/paconv_regularization_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/rotated_iou_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/rotated_iou_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/uncertain_smooth_l1_loss.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/losses/uncertain_smooth_l1_loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/pillar_scatter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/pillar_scatter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_encoder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_encoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_unet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/middle_encoders/sparse_unet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/edge_fusion_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/edge_fusion_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/transformer.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/transformer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/vote_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/model_utils/vote_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/dla_neck.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/dla_neck.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/imvoxel_neck.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/imvoxel_neck.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/pointnet2_fp_neck.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/pointnet2_fp_neck.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/second_fpn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/second_fpn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/view_transformer.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/necks/view_transformer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/base_3droi_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/base_3droi_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/h3d_bbox_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/h3d_bbox_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/parta2_bbox_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/parta2_bbox_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/point_rcnn_bbox_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/bbox_heads/point_rcnn_bbox_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/h3d_roi_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/h3d_roi_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/pointwise_semantic_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/pointwise_semantic_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/primitive_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/mask_heads/primitive_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/part_aggregation_roi_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/part_aggregation_roi_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/point_rcnn_roi_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/point_rcnn_roi_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roiaware_extractor.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roiaware_extractor.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roipoint_extractor.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/roi_heads/roi_extractors/single_roipoint_extractor.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/base.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/base.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/encoder_decoder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/segmentors/encoder_decoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/clip_sigmoid.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/clip_sigmoid.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/edge_indices.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/edge_indices.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/gen_keypoints.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/gen_keypoints.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/handle_objs.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/handle_objs.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/mlp.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/utils/mlp.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/pillar_encoder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/pillar_encoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/voxel_encoder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/models/voxel_encoders/voxel_encoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fa_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fa_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fp_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_fp_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_gf_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/dgcnn_modules/dgcnn_gf_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/norm.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/norm.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/paconv.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/paconv.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/paconv/utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/builder.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/paconv_sa_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/paconv_sa_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_fp_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_fp_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_sa_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/pointnet_modules/point_sa_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/sparse_block.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/sparse_block.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/write_spconv2.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/ops/spconv/overwrite_spconv/write_spconv2.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/collect_env.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/compat_cfg.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/compat_cfg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/logger.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/misc.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/setup_env.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/version.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/mmdet3d/version.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/build.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/build.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/docs.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/docs.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/mminstall.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/mminstall.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/optional.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/optional.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/readthedocs.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/readthedocs.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/runtime.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/runtime.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/tests.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/requirements/tests.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.cfg b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.cfg old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/setup.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/a.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/a.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_dbinfos_train.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_dbinfos_train.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_gt_database/0_Pedestrian_0.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_gt_database/0_Pedestrian_0.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.coco.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.coco.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_mono3d.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_train.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/kitti_infos_train.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results2d.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/mono3d_sample_results2d.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000000.png b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000000.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000007.png b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/image_2/000007.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne/000000.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne/000000.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne_reduced/000000.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/kitti/training/velodyne_reduced/000000.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886501000046.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886501000046.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886701083686.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886701083686.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lidar/host-a017_lidar1_1236118886901125926.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos_val.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/lyft_infos_val.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/sample_results.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/sample_results.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/maps/map_raster_palo_alto.png b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/maps/map_raster_palo_alto.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/attribute.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/attribute.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/calibrated_sensor.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/calibrated_sensor.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/category.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/category.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/ego_pose.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/ego_pose.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/instance.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/instance.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/log.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/log.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/map.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/map.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_annotation.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_annotation.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_data.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sample_data.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/scene.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/scene.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sensor.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/sensor.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/visibility.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/v1.01-train/v1.01-train/visibility.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/val.txt b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/lyft/val.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/mono3d_sample_results.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/mono3d_sample_results.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_info.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_info.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_infos_mono3d.coco.json b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/nus_infos_mono3d.coco.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/CAM_BACK_LEFT/n015-2018-07-18-11-07-57+0800__CAM_BACK_LEFT__1531883530447423.jpg b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/CAM_BACK_LEFT/n015-2018-07-18-11-07-57+0800__CAM_BACK_LEFT__1531883530447423.jpg old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470948018.pcd.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/samples/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470948018.pcd.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n008-2018-09-18-12-07-26-0400__LIDAR_TOP__1537287083900561.pcd.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n008-2018-09-18-12-07-26-0400__LIDAR_TOP__1537287083900561.pcd.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470898274.pcd.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/nuscenes/sweeps/LIDAR_TOP/n015-2018-08-02-17-16-37+0800__LIDAR_TOP__1533201470898274.pcd.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/features_for_fps_distance.npy b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/features_for_fps_distance.npy old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/fps_idx.npy b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/ops/fps_idx.npy old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/instance_mask/Area_1_office_2.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/instance_mask/Area_1_office_2.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/points/Area_1_office_2.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/points/Area_1_office_2.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/s3dis_infos.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/s3dis_infos.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/semantic_mask/Area_1_office_2.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/s3dis/semantic_mask/Area_1_office_2.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/instance_mask/scene0000_00.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/instance_mask/scene0000_00.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/points/scene0000_00.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/points/scene0000_00.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/scannet_infos.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/scannet_infos.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/semantic_mask/scene0000_00.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/scannet/semantic_mask/scene0000_00.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/semantickitti_infos.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/semantickitti_infos.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/labels/000000.label b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/labels/000000.label old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/velodyne/000000.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/semantickitti/sequences/00/velodyne/000000.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/points/000001.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/points/000001.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_infos.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_infos.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_trainval/image/000001.jpg b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/sunrgbd/sunrgbd_trainval/image/000001.jpg old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/0000000.png b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/0000000.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/1000000.png b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/image_0/1000000.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/0000000.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/0000000.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/1000000.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/training/velodyne/1000000.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_dbinfos_train.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_dbinfos_train.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_gt_database/0_Car_0.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_gt_database/0_Car_0.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_train.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_train.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_val.pkl b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/kitti_format/waymo_infos_val.pkl old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/gt.bin b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/gt.bin old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/validation/val.tfrecord b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/data/waymo/waymo_format/validation/val.tfrecord old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_dataset_wrappers.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_mono_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_kitti_mono_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_lyft_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_lyft_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscene_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscene_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscenes_mono_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_nuscenes_mono_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_s3dis_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_s3dis_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_scannet_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_scannet_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_semantickitti_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_semantickitti_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_sunrgbd_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_sunrgbd_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_waymo_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_datasets/test_waymo_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_data_augment_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_data_augment_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_test_augment_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_test_augment_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_transforms_3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_augmentations/test_transforms_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_pipeline.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_pipeline.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_sample.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_indoor_sample.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_images_from_multi_views.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_images_from_multi_views.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_points_from_multi_sweeps.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_load_points_from_multi_sweeps.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_loading.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_loadings/test_loading.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_outdoor_pipeline.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_data/test_pipelines/test_outdoor_pipeline.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_indoor_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_indoor_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_instance_seg_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_instance_seg_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_kitti_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_kitti_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_losses.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_losses.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_seg_eval.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_metrics/test_seg_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_backbones.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_backbones.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_dgcnn_modules.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_dgcnn_modules.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_middle_encoders.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_middle_encoders.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_modules.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_modules.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_ops.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_paconv_ops.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_pointnet_modules.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_pointnet_modules.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_sparse_unet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_sparse_unet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_vote_module.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_common_modules/test_vote_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_detectors.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_detectors.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_forward.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_forward.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_fusion_coord_trans.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_fusion_coord_trans.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_point_fusion.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_point_fusion.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_vote_fusion.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_fusion/test_vote_fusion.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_dgcnn_decode_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_dgcnn_decode_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_heads.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_heads.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_paconv_decode_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_paconv_decode_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_parta2_bbox_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_parta2_bbox_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_pointnet2_decode_head.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_pointnet2_decode_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_roi_extractors.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_roi_extractors.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_semantic_heads.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_heads/test_semantic_heads.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_fpn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_fpn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_necks.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_necks/test_necks.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_segmentors.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_segmentors.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_encoders.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_encoders.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_generator.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_models/test_voxel_encoder/test_voxel_generator.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_apis.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_apis.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_config.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_runtime/test_config.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_samples/parta2_roihead_inputs.npz b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_samples/parta2_roihead_inputs.npz old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_anchors.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_anchors.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_assigners.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_assigners.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_bbox_coders.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_bbox_coders.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box3d.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box_np_ops.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_box_np_ops.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_compat_cfg.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_compat_cfg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_coord_3d_mode.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_coord_3d_mode.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_merge_augs.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_merge_augs.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_nms.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_nms.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_points.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_points.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_samplers.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_samplers.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_setup_env.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_setup_env.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tests/test_utils/test_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/analyze_logs.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/analyze_logs.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/benchmark.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/benchmark.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/get_flops.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/analysis_tools/get_flops.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/create_data.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/__init__.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/create_gt_database.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/create_gt_database.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/indoor_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/indoor_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/kitti_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_data_fixer.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/lyft_data_fixer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuimage_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuimage_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuscenes_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/nuscenes_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/s3dis_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/s3dis_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/scannet_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/scannet_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/sunrgbd_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/sunrgbd_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/waymo_converter.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/data_converter/waymo_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d2torchserve.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d2torchserve.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d_handler.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/mmdet3d_handler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/test_torchserver.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/deployment/test_torchserver.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_test.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_test.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_train.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/browse_dataset.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/browse_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/fuse_conv_bn.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/print_config.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/print_config.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/visualize_results.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/misc/visualize_results.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_h3dnet_checkpoints.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_h3dnet_checkpoints.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_votenet_checkpoints.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/convert_votenet_checkpoints.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/publish_model.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/publish_model.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/regnet2mmdet.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/model_converters/regnet2mmdet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_test.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_test.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_train.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/slurm_train.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/test.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/train.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.py b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.sh b/cv/3d_detection/BEVFormer/pytorch/mmdetection3d/tools/update_data_coords.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/coco_instance.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/coco_instance.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-3class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-3class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-car.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/kitti-3d-car.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/lyft-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/lyft-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nuim_instance.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nuim_instance.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-mono3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/nus-mono3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/range100_lyft-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/range100_lyft-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis-3d-5class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis-3d-5class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis_seg-3d-13class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/s3dis_seg-3d-13class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet-3d-18class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet-3d-18class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet_seg-3d-20class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/scannet_seg-3d-20class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/sunrgbd-3d-10class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/sunrgbd-3d-10class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-3class.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-3class.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-car.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/datasets/waymoD5-3d-car.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/default_runtime.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/3dssd.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/3dssd.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_01voxel_second_secfpn_nus.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_01voxel_second_secfpn_nus.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_02pillar_second_secfpn_nus.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/centerpoint_02pillar_second_secfpn_nus.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/fcos3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/fcos3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/groupfree3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/groupfree3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/h3dnet.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/h3dnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_lyft.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_lyft.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_nus.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_nus.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_range100_lyft.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_fpn_range100_lyft.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_kitti.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_kitti.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_waymo.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_pointpillars_secfpn_waymo.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_kitti.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_kitti.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_waymo.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/hv_second_secfpn_waymo.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/imvotenet_image.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/imvotenet_image.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/mask_rcnn_r50_fpn.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/mask_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_cuda_ssg.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_cuda_ssg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_ssg.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/paconv_ssg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/parta2.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/parta2.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_msg.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_msg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_ssg.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/pointnet2_ssg.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/votenet.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/models/votenet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cosine.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cosine.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_20e.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_20e.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_40e.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/cyclic_40e.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/mmdet_schedule_1x.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/mmdet_schedule_1x.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_2x.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_2x.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_3x.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/schedule_3x.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_150e.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_150e.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_200e.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_200e.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_50e.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/_base_/schedules/seg_cosine_50e.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_base.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_base.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_small.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_small.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_tiny.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer/bevformer_tiny.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer_fp16/bevformer_tiny_fp16.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/bevformer_fp16/bevformer_tiny_fp16.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_lyft-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_lyft-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_nus-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_nus-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_waymo-3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/configs/datasets/custom_waymo-3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/mmdet_train.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/mmdet_train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/test.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/train.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/dense_heads/bevformer_head.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer_fp16.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/detectors/bevformer_fp16.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/custom_hooks.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/hooks/custom_hooks.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/custom_base_transformer_layer.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/custom_base_transformer_layer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/decoder.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/decoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/encoder.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/encoder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/multi_scale_deformable_attn_function.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/multi_scale_deformable_attn_function.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/spatial_cross_attention.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/spatial_cross_attention.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/temporal_self_attention.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/temporal_self_attention.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/transformer.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/modules/transformer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/bevformer/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/assigners/hungarian_assigner_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/coders/nms_free_coder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/match_costs/match_cost.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/util.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/bbox/util.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/kitti2waymo.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/core/evaluation/kitti2waymo.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/builder.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_mono_dataset.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscenes_mono_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscnes_eval.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/nuscnes_eval.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/formating.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/loading.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/transform_3d.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/pipelines/transform_3d.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/distributed_sampler.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/group_sampler.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/sampler.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/datasets/samplers/sampler.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/vovnet.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/backbones/vovnet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/hooks.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/hooks/hooks.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/adamw.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/opt/adamw.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/__init__.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/bricks.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/bricks.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/grid_mask.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/grid_mask.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/position_embedding.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/position_embedding.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/visual.py b/cv/3d_detection/BEVFormer/pytorch/projects/mmdet3d_plugin/models/utils/visual.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/__init__.py b/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/analyze_logs.py b/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/analyze_logs.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/benchmark.py b/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/benchmark.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/get_params.py b/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/get_params.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/visual.py b/cv/3d_detection/BEVFormer/pytorch/tools/analysis_tools/visual.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/create_data.py b/cv/3d_detection/BEVFormer/pytorch/tools/create_data.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/__init__.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/create_gt_database.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/create_gt_database.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/indoor_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/indoor_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/kitti_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_data_fixer.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/lyft_data_fixer.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuimage_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuimage_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuscenes_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/nuscenes_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/s3dis_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/s3dis_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/scannet_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/scannet_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/sunrgbd_data_utils.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/sunrgbd_data_utils.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/waymo_converter.py b/cv/3d_detection/BEVFormer/pytorch/tools/data_converter/waymo_converter.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/dist_test.sh b/cv/3d_detection/BEVFormer/pytorch/tools/dist_test.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/dist_train.sh b/cv/3d_detection/BEVFormer/pytorch/tools/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/fp16/dist_train.sh b/cv/3d_detection/BEVFormer/pytorch/tools/fp16/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/fp16/train.py b/cv/3d_detection/BEVFormer/pytorch/tools/fp16/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/misc/browse_dataset.py b/cv/3d_detection/BEVFormer/pytorch/tools/misc/browse_dataset.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/misc/fuse_conv_bn.py b/cv/3d_detection/BEVFormer/pytorch/tools/misc/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/misc/print_config.py b/cv/3d_detection/BEVFormer/pytorch/tools/misc/print_config.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/misc/visualize_results.py b/cv/3d_detection/BEVFormer/pytorch/tools/misc/visualize_results.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/convert_votenet_checkpoints.py b/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/convert_votenet_checkpoints.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/publish_model.py b/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/publish_model.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/regnet2mmdet.py b/cv/3d_detection/BEVFormer/pytorch/tools/model_converters/regnet2mmdet.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/test.py b/cv/3d_detection/BEVFormer/pytorch/tools/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/BEVFormer/pytorch/tools/train.py b/cv/3d_detection/BEVFormer/pytorch/tools/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/.gitignore b/cv/3d_detection/pointpillars/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/README.md b/cv/3d_detection/pointpillars/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/__init__.py b/cv/3d_detection/pointpillars/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/dataset/__init__.py b/cv/3d_detection/pointpillars/pytorch/dataset/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/dataset/data_aug.py b/cv/3d_detection/pointpillars/pytorch/dataset/data_aug.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/dataset/dataloader.py b/cv/3d_detection/pointpillars/pytorch/dataset/dataloader.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/dataset/kitti.py b/cv/3d_detection/pointpillars/pytorch/dataset/kitti.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/evaluate.py b/cv/3d_detection/pointpillars/pytorch/evaluate.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/figures/img_3dbbox_000134.png b/cv/3d_detection/pointpillars/pytorch/figures/img_3dbbox_000134.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/figures/pc_pred_000134.png b/cv/3d_detection/pointpillars/pytorch/figures/pc_pred_000134.png old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/loss/__init__.py b/cv/3d_detection/pointpillars/pytorch/loss/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/loss/loss.py b/cv/3d_detection/pointpillars/pytorch/loss/loss.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/misc/log.md b/cv/3d_detection/pointpillars/pytorch/misc/log.md old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/misc/vis_data_gt.py b/cv/3d_detection/pointpillars/pytorch/misc/vis_data_gt.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/model/__init__.py b/cv/3d_detection/pointpillars/pytorch/model/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/model/anchors.py b/cv/3d_detection/pointpillars/pytorch/model/anchors.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/model/pointpillars.py b/cv/3d_detection/pointpillars/pytorch/model/pointpillars.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/__init__.py b/cv/3d_detection/pointpillars/pytorch/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d.cpp b/cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d_kernel.cu b/cv/3d_detection/pointpillars/pytorch/ops/iou3d/iou3d_kernel.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/iou3d_module.py b/cv/3d_detection/pointpillars/pytorch/ops/iou3d_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/setup.py b/cv/3d_detection/pointpillars/pytorch/ops/setup.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/voxel_module.py b/cv/3d_detection/pointpillars/pytorch/ops/voxel_module.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.cpp b/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.h b/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization.h old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cpu.cpp b/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cuda.cu b/cv/3d_detection/pointpillars/pytorch/ops/voxelization/voxelization_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/pre_process_kitti.py b/cv/3d_detection/pointpillars/pytorch/pre_process_kitti.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/requirements.txt b/cv/3d_detection/pointpillars/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/test.py b/cv/3d_detection/pointpillars/pytorch/test.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/train.py b/cv/3d_detection/pointpillars/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/utils/__init__.py b/cv/3d_detection/pointpillars/pytorch/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/utils/io.py b/cv/3d_detection/pointpillars/pytorch/utils/io.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/utils/process.py b/cv/3d_detection/pointpillars/pytorch/utils/process.py old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/utils/viewpoint.json b/cv/3d_detection/pointpillars/pytorch/utils/viewpoint.json old mode 100755 new mode 100644 diff --git a/cv/3d_detection/pointpillars/pytorch/utils/vis_o3d.py b/cv/3d_detection/pointpillars/pytorch/utils/vis_o3d.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/.gitignore b/cv/classification/densenet/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/README.md b/cv/classification/densenet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/__init__.py b/cv/classification/densenet/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/common_utils/__init__.py b/cv/classification/densenet/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/common_utils/dist.py b/cv/classification/densenet/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/common_utils/metric_logger.py b/cv/classification/densenet/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/common_utils/misc.py b/cv/classification/densenet/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/common_utils/smooth_value.py b/cv/classification/densenet/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/dataloader/__init__.py b/cv/classification/densenet/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/dataloader/classification.py b/cv/classification/densenet/pytorch/dataloader/classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/dataloader/dali_classification.py b/cv/classification/densenet/pytorch/dataloader/dali_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/dataloader/utils/__init__.py b/cv/classification/densenet/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/dataloader/utils/presets_classification.py b/cv/classification/densenet/pytorch/dataloader/utils/presets_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/train.py b/cv/classification/densenet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/classification/densenet/pytorch/utils_.py b/cv/classification/densenet/pytorch/utils_.py old mode 100755 new mode 100644 diff --git a/cv/classification/dpn107/pytorch/train_dpn107_amp_dist.sh b/cv/classification/dpn107/pytorch/train_dpn107_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/dpn92/pytorch/train_dpn92_amp_dist.sh b/cv/classification/dpn92/pytorch/train_dpn92_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/eca_mobilenet_v2/pytorch/train_eca_mobilenet_v2_amp_dist.sh b/cv/classification/eca_mobilenet_v2/pytorch/train_eca_mobilenet_v2_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/eca_resnet152/pytorch/train_eca_resnet152_amp_dist.sh b/cv/classification/eca_resnet152/pytorch/train_eca_resnet152_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/.gitignore b/cv/classification/efficientb4/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/README.md b/cv/classification/efficientb4/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/__init__.py b/cv/classification/efficientb4/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/__init__.py b/cv/classification/efficientb4/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/dist.py b/cv/classification/efficientb4/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/loss.py b/cv/classification/efficientb4/pytorch/common_utils/loss.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/metric_logger.py b/cv/classification/efficientb4/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/misc.py b/cv/classification/efficientb4/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/common_utils/smooth_value.py b/cv/classification/efficientb4/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/dataloader/__init__.py b/cv/classification/efficientb4/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/dataloader/classification.py b/cv/classification/efficientb4/pytorch/dataloader/classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/dataloader/dali_classification.py b/cv/classification/efficientb4/pytorch/dataloader/dali_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/dataloader/utils/__init__.py b/cv/classification/efficientb4/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/dataloader/utils/presets_classification.py b/cv/classification/efficientb4/pytorch/dataloader/utils/presets_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/train.py b/cv/classification/efficientb4/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/classification/efficientb4/pytorch/utils.py b/cv/classification/efficientb4/pytorch/utils.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/.gitignore b/cv/classification/googlenet/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/README.md b/cv/classification/googlenet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/__init__.py b/cv/classification/googlenet/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/common_utils/__init__.py b/cv/classification/googlenet/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/common_utils/dist.py b/cv/classification/googlenet/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/common_utils/metric_logger.py b/cv/classification/googlenet/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/common_utils/misc.py b/cv/classification/googlenet/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/common_utils/smooth_value.py b/cv/classification/googlenet/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/dataloader/__init__.py b/cv/classification/googlenet/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/dataloader/classification.py b/cv/classification/googlenet/pytorch/dataloader/classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/dataloader/dali_classification.py b/cv/classification/googlenet/pytorch/dataloader/dali_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/dataloader/utils/__init__.py b/cv/classification/googlenet/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/dataloader/utils/presets_classification.py b/cv/classification/googlenet/pytorch/dataloader/utils/presets_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/train.py b/cv/classification/googlenet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/classification/googlenet/pytorch/utils_.py b/cv/classification/googlenet/pytorch/utils_.py old mode 100755 new mode 100644 diff --git a/cv/classification/inceptionv3/pytorch/train_inception_v3_amp_dist.sh b/cv/classification/inceptionv3/pytorch/train_inception_v3_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/inceptionv4/pytorch/train_inceptionv4_amp_dist.sh b/cv/classification/inceptionv4/pytorch/train_inceptionv4_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/.gitignore b/cv/classification/lenet/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/README.md b/cv/classification/lenet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/__init__.py b/cv/classification/lenet/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/common_utils/__init__.py b/cv/classification/lenet/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/common_utils/dist.py b/cv/classification/lenet/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/common_utils/metric_logger.py b/cv/classification/lenet/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/common_utils/misc.py b/cv/classification/lenet/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/common_utils/smooth_value.py b/cv/classification/lenet/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/dataloader/__init__.py b/cv/classification/lenet/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/dataloader/classification.py b/cv/classification/lenet/pytorch/dataloader/classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/dataloader/dali_classification.py b/cv/classification/lenet/pytorch/dataloader/dali_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/dataloader/utils/__init__.py b/cv/classification/lenet/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/dataloader/utils/presets_classification.py b/cv/classification/lenet/pytorch/dataloader/utils/presets_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/train.py b/cv/classification/lenet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/classification/lenet/pytorch/utils_.py b/cv/classification/lenet/pytorch/utils_.py old mode 100755 new mode 100644 diff --git a/cv/classification/mobilenetv2/pytorch/train_mobilenet_v2_amp_dist.sh b/cv/classification/mobilenetv2/pytorch/train_mobilenet_v2_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/mobilenetv3/pytorch/train_mobilenet_v3_large_amp_dist.sh b/cv/classification/mobilenetv3/pytorch/train_mobilenet_v3_large_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/LICENSE b/cv/classification/repvgg/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/README.md b/cv/classification/repvgg/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/__init__.py b/cv/classification/repvgg/pytorch/data/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/build.py b/cv/classification/repvgg/pytorch/data/build.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/cached_image_folder.py b/cv/classification/repvgg/pytorch/data/cached_image_folder.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/lmdb_dataset.py b/cv/classification/repvgg/pytorch/data/lmdb_dataset.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/samplers.py b/cv/classification/repvgg/pytorch/data/samplers.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/data/zipreader.py b/cv/classification/repvgg/pytorch/data/zipreader.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/example_pspnet.py b/cv/classification/repvgg/pytorch/example_pspnet.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/jizhi_submit_train_repvgg.py b/cv/classification/repvgg/pytorch/jizhi_submit_train_repvgg.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/main.py b/cv/classification/repvgg/pytorch/main.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/quantization/quant_qat_train.py b/cv/classification/repvgg/pytorch/quantization/quant_qat_train.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/quantization/repvgg_quantized.py b/cv/classification/repvgg/pytorch/quantization/repvgg_quantized.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/repvgg.py b/cv/classification/repvgg/pytorch/repvgg.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/repvggplus.py b/cv/classification/repvgg/pytorch/repvggplus.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/repvggplus_custom_L2.py b/cv/classification/repvgg/pytorch/repvggplus_custom_L2.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/se_block.py b/cv/classification/repvgg/pytorch/se_block.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/tools/convert.py b/cv/classification/repvgg/pytorch/tools/convert.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/tools/insert_bn.py b/cv/classification/repvgg/pytorch/tools/insert_bn.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/tools/verify.py b/cv/classification/repvgg/pytorch/tools/verify.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/config.py b/cv/classification/repvgg/pytorch/train/config.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/cutout.py b/cv/classification/repvgg/pytorch/train/cutout.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/logger.py b/cv/classification/repvgg/pytorch/train/logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/lr_scheduler.py b/cv/classification/repvgg/pytorch/train/lr_scheduler.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/optimizer.py b/cv/classification/repvgg/pytorch/train/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/train/randaug.py b/cv/classification/repvgg/pytorch/train/randaug.py old mode 100755 new mode 100644 diff --git a/cv/classification/repvgg/pytorch/utils.py b/cv/classification/repvgg/pytorch/utils.py old mode 100755 new mode 100644 diff --git a/cv/classification/resnest101/pytorch/train_resnest101_amp_dist.sh b/cv/classification/resnest101/pytorch/train_resnest101_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnest14/pytorch/train_resnest14_amp_dist.sh b/cv/classification/resnest14/pytorch/train_resnest14_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnest269/pytorch/train_resnest269_amp_dist.sh b/cv/classification/resnest269/pytorch/train_resnest269_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnest50/pytorch/train_resnest50_amp_dist.sh b/cv/classification/resnest50/pytorch/train_resnest50_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnet101/pytorch/train_resnet101_amp_dist.sh b/cv/classification/resnet101/pytorch/train_resnet101_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnet152/pytorch/train_resnet152_amp_dist.sh b/cv/classification/resnet152/pytorch/train_resnet152_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnet18/pytorch/train_resnet18_amp_dist.sh b/cv/classification/resnet18/pytorch/train_resnet18_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnext101_32x8d/pytorch/train_resnext101_32x8d_amp_dist.sh b/cv/classification/resnext101_32x8d/pytorch/train_resnext101_32x8d_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/resnext50_32x4d/pytorch/train_resnext50_32x4d_amp_dist.sh b/cv/classification/resnext50_32x4d/pytorch/train_resnext50_32x4d_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/seresnext/pytorch/train_seresnext101_32x4d_amp_dist.sh b/cv/classification/seresnext/pytorch/train_seresnext101_32x4d_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/shufflenetv2/pytorch/train_shufflenet_v2_x2_0_amp_dist.sh b/cv/classification/shufflenetv2/pytorch/train_shufflenet_v2_x2_0_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/vgg/pytorch/.gitignore b/cv/classification/vgg/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/vgg/pytorch/train_vgg16_amp_dist.sh b/cv/classification/vgg/pytorch/train_vgg16_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/wide_resnet101_2/pytorch/train_wide_resnet101_2_amp_dist.sh b/cv/classification/wide_resnet101_2/pytorch/train_wide_resnet101_2_amp_dist.sh old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/.gitignore b/cv/classification/xception/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/README.md b/cv/classification/xception/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/__init__.py b/cv/classification/xception/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/common_utils/__init__.py b/cv/classification/xception/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/common_utils/dist.py b/cv/classification/xception/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/common_utils/metric_logger.py b/cv/classification/xception/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/common_utils/misc.py b/cv/classification/xception/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/common_utils/smooth_value.py b/cv/classification/xception/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/dataloader/__init__.py b/cv/classification/xception/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/dataloader/classification.py b/cv/classification/xception/pytorch/dataloader/classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/dataloader/dali_classification.py b/cv/classification/xception/pytorch/dataloader/dali_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/dataloader/utils/__init__.py b/cv/classification/xception/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/dataloader/utils/presets_classification.py b/cv/classification/xception/pytorch/dataloader/utils/presets_classification.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/train.py b/cv/classification/xception/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/classification/xception/pytorch/utils_.py b/cv/classification/xception/pytorch/utils_.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/.gitignore b/cv/detection/autoassign/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/LICENSE b/cv/detection/autoassign/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/README.md b/cv/detection/autoassign/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_detection.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_instance.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/cityscapes_instance.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_detection.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance_semantic.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_instance_semantic.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_panoptic.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/coco_panoptic.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/deepfashion.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/deepfashion.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v0.5_instance.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v0.5_instance.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v1_instance.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/lvis_v1_instance.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/openimages_detection.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/openimages_detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/voc0712.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/voc0712.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/datasets/wider_face.py b/cv/detection/autoassign/pytorch/configs/_base_/datasets/wider_face.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/default_runtime.py b/cv/detection/autoassign/pytorch/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/cascade_mask_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/cascade_rcnn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/cascade_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/fast_rcnn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/fast_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_c4.py b/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_c4.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_dc5.py b/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_caffe_dc5.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/faster_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_caffe_c4.py b/cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_caffe_c4.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/mask_rcnn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/retinanet_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/retinanet_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_caffe_c4.py b/cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_caffe_c4.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_fpn.py b/cv/detection/autoassign/pytorch/configs/_base_/models/rpn_r50_fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/models/ssd300.py b/cv/detection/autoassign/pytorch/configs/_base_/models/ssd300.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_1x.py b/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_1x.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_20e.py b/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_20e.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_2x.py b/cv/detection/autoassign/pytorch/configs/_base_/schedules/schedule_2x.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/autoassign/README.md b/cv/detection/autoassign/pytorch/configs/autoassign/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/autoassign/autoassign_r50_fpn_8x2_1x_coco.py b/cv/detection/autoassign/pytorch/configs/autoassign/autoassign_r50_fpn_8x2_1x_coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/configs/autoassign/metafile.yml b/cv/detection/autoassign/pytorch/configs/autoassign/metafile.yml old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/dist_train.sh b/cv/detection/autoassign/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/docker/Dockerfile b/cv/detection/autoassign/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/docker/serve/Dockerfile b/cv/detection/autoassign/pytorch/docker/serve/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/docker/serve/config.properties b/cv/detection/autoassign/pytorch/docker/serve/config.properties old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/docker/serve/entrypoint.sh b/cv/detection/autoassign/pytorch/docker/serve/entrypoint.sh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/__init__.py b/cv/detection/autoassign/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/__init__.py b/cv/detection/autoassign/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/alexnet.py b/cv/detection/autoassign/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/__init__.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/activation.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/context_block.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/drop.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hswish.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/non_local.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/norm.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/padding.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/plugin.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/registry.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/scale.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/swish.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/transformer.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/upsample.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/detection/autoassign/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/builder.py b/cv/detection/autoassign/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/resnet.py b/cv/detection/autoassign/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/utils/__init__.py b/cv/detection/autoassign/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/detection/autoassign/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/detection/autoassign/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/detection/autoassign/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/utils/weight_init.py b/cv/detection/autoassign/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/cnn/vgg.py b/cv/detection/autoassign/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/engine/__init__.py b/cv/detection/autoassign/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/engine/test.py b/cv/detection/autoassign/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/__init__.py b/cv/detection/autoassign/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/file_client.py b/cv/detection/autoassign/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/__init__.py b/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/base.py b/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/detection/autoassign/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/io.py b/cv/detection/autoassign/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/fileio/parse.py b/cv/detection/autoassign/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/__init__.py b/cv/detection/autoassign/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/colorspace.py b/cv/detection/autoassign/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/geometric.py b/cv/detection/autoassign/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/io.py b/cv/detection/autoassign/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/misc.py b/cv/detection/autoassign/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/image/photometric.py b/cv/detection/autoassign/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/model_zoo/deprecated.json b/cv/detection/autoassign/pytorch/mmcv/model_zoo/deprecated.json old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/model_zoo/mmcls.json b/cv/detection/autoassign/pytorch/mmcv/model_zoo/mmcls.json old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/model_zoo/open_mmlab.json b/cv/detection/autoassign/pytorch/mmcv/model_zoo/open_mmlab.json old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/__init__.py b/cv/detection/autoassign/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/README.md b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/nms_rotated_cuda.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/nms.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align_cpu.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_align_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_pool.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/detection/autoassign/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/deprecated_wrappers.py b/cv/detection/autoassign/pytorch/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/focal_loss.py b/cv/detection/autoassign/pytorch/mmcv/ops/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/info.py b/cv/detection/autoassign/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/nms.py b/cv/detection/autoassign/pytorch/mmcv/ops/nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/point_sample.py b/cv/detection/autoassign/pytorch/mmcv/ops/point_sample.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/roi_align.py b/cv/detection/autoassign/pytorch/mmcv/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/roi_pool.py b/cv/detection/autoassign/pytorch/mmcv/ops/roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/ops/sync_bn.py b/cv/detection/autoassign/pytorch/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/__init__.py b/cv/detection/autoassign/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/_functions.py b/cv/detection/autoassign/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/collate.py b/cv/detection/autoassign/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/data_container.py b/cv/detection/autoassign/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/data_parallel.py b/cv/detection/autoassign/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/distributed.py b/cv/detection/autoassign/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/detection/autoassign/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/registry.py b/cv/detection/autoassign/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/scatter_gather.py b/cv/detection/autoassign/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/parallel/utils.py b/cv/detection/autoassign/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/__init__.py b/cv/detection/autoassign/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/base_module.py b/cv/detection/autoassign/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/base_runner.py b/cv/detection/autoassign/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/builder.py b/cv/detection/autoassign/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/checkpoint.py b/cv/detection/autoassign/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/default_constructor.py b/cv/detection/autoassign/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/dist_utils.py b/cv/detection/autoassign/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/epoch_based_runner.py b/cv/detection/autoassign/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/fp16_utils.py b/cv/detection/autoassign/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/__init__.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/closure.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/ema.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/evaluation.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/hook.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/base.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/text.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/memory.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/optimizer.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/profiler.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/detection/autoassign/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/iter_based_runner.py b/cv/detection/autoassign/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/log_buffer.py b/cv/detection/autoassign/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/__init__.py b/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/builder.py b/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/detection/autoassign/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/priority.py b/cv/detection/autoassign/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/runner/utils.py b/cv/detection/autoassign/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/__init__.py b/cv/detection/autoassign/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/config.py b/cv/detection/autoassign/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/env.py b/cv/detection/autoassign/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/ext_loader.py b/cv/detection/autoassign/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/logging.py b/cv/detection/autoassign/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/misc.py b/cv/detection/autoassign/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/parrots_jit.py b/cv/detection/autoassign/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/parrots_wrapper.py b/cv/detection/autoassign/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/path.py b/cv/detection/autoassign/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/progressbar.py b/cv/detection/autoassign/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/registry.py b/cv/detection/autoassign/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/testing.py b/cv/detection/autoassign/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/timer.py b/cv/detection/autoassign/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/trace.py b/cv/detection/autoassign/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/utils/version_utils.py b/cv/detection/autoassign/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmcv/version.py b/cv/detection/autoassign/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/__init__.py b/cv/detection/autoassign/pytorch/mmdet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/apis/__init__.py b/cv/detection/autoassign/pytorch/mmdet/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/apis/inference.py b/cv/detection/autoassign/pytorch/mmdet/apis/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/apis/test.py b/cv/detection/autoassign/pytorch/mmdet/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/apis/train.py b/cv/detection/autoassign/pytorch/mmdet/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/anchor/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/anchor/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/anchor/anchor_generator.py b/cv/detection/autoassign/pytorch/mmdet/core/anchor/anchor_generator.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/anchor/builder.py b/cv/detection/autoassign/pytorch/mmdet/core/anchor/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/anchor/point_generator.py b/cv/detection/autoassign/pytorch/mmdet/core/anchor/point_generator.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/anchor/utils.py b/cv/detection/autoassign/pytorch/mmdet/core/anchor/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/approx_max_iou_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/approx_max_iou_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/assign_result.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/assign_result.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/atss_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/atss_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/base_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/base_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/center_region_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/center_region_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/grid_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/grid_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/hungarian_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/hungarian_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/mask_hungarian_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/mask_hungarian_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/max_iou_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/max_iou_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/point_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/point_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/region_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/region_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/sim_ota_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/sim_ota_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/task_aligned_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/task_aligned_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/builder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/bucketing_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/bucketing_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/distance_point_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/distance_point_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/legacy_delta_xywh_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/legacy_delta_xywh_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/pseudo_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/pseudo_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/tblr_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/tblr_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/yolo_bbox_coder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/coder/yolo_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/demodata.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/demodata.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/builder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/builder.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/match_cost.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/match_costs/match_cost.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/base_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/base_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/combined_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/combined_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/instance_balanced_pos_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/instance_balanced_pos_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/iou_balanced_neg_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/iou_balanced_neg_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_pseudo_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_pseudo_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_sampling_result.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/mask_sampling_result.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/ohem_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/ohem_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/random_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/random_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/sampling_result.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/sampling_result.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/score_hlr_sampler.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/samplers/score_hlr_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/bbox/transforms.py b/cv/detection/autoassign/pytorch/mmdet/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/data_structures/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/data_structures/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/data_structures/general_data.py b/cv/detection/autoassign/pytorch/mmdet/core/data_structures/general_data.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/data_structures/instance_data.py b/cv/detection/autoassign/pytorch/mmdet/core/data_structures/instance_data.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/bbox_overlaps.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/bbox_overlaps.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/class_names.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/class_names.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/eval_hooks.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/mean_ap.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/mean_ap.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/panoptic_utils.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/panoptic_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/evaluation/recall.py b/cv/detection/autoassign/pytorch/mmdet/core/evaluation/recall.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/export/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/export/model_wrappers.py b/cv/detection/autoassign/pytorch/mmdet/core/export/model_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/export/onnx_helper.py b/cv/detection/autoassign/pytorch/mmdet/core/export/onnx_helper.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/export/pytorch2onnx.py b/cv/detection/autoassign/pytorch/mmdet/core/export/pytorch2onnx.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/checkloss_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/checkloss_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/ema.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/ema.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/memory_profiler_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/memory_profiler_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/set_epoch_info_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/set_epoch_info_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/sync_norm_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/sync_norm_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/sync_random_size_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/sync_random_size_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/wandblogger_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/wandblogger_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_lrupdater_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_lrupdater_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_mode_switch_hook.py b/cv/detection/autoassign/pytorch/mmdet/core/hook/yolox_mode_switch_hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/mask/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/mask/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/mask/mask_target.py b/cv/detection/autoassign/pytorch/mmdet/core/mask/mask_target.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/mask/structures.py b/cv/detection/autoassign/pytorch/mmdet/core/mask/structures.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/mask/utils.py b/cv/detection/autoassign/pytorch/mmdet/core/mask/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/optimizers/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/optimizers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/optimizers/builder.py b/cv/detection/autoassign/pytorch/mmdet/core/optimizers/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py b/cv/detection/autoassign/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/post_processing/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/post_processing/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/post_processing/bbox_nms.py b/cv/detection/autoassign/pytorch/mmdet/core/post_processing/bbox_nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/post_processing/matrix_nms.py b/cv/detection/autoassign/pytorch/mmdet/core/post_processing/matrix_nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/post_processing/merge_augs.py b/cv/detection/autoassign/pytorch/mmdet/core/post_processing/merge_augs.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/utils/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/utils/dist_utils.py b/cv/detection/autoassign/pytorch/mmdet/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/utils/misc.py b/cv/detection/autoassign/pytorch/mmdet/core/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/visualization/__init__.py b/cv/detection/autoassign/pytorch/mmdet/core/visualization/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/visualization/image.py b/cv/detection/autoassign/pytorch/mmdet/core/visualization/image.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/core/visualization/palette.py b/cv/detection/autoassign/pytorch/mmdet/core/visualization/palette.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/__init__.py b/cv/detection/autoassign/pytorch/mmdet/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/__init__.py b/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/coco_api.py b/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/coco_api.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py b/cv/detection/autoassign/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/builder.py b/cv/detection/autoassign/pytorch/mmdet/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/coco.py b/cv/detection/autoassign/pytorch/mmdet/datasets/coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/custom.py b/cv/detection/autoassign/pytorch/mmdet/datasets/custom.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/dataset_wrappers.py b/cv/detection/autoassign/pytorch/mmdet/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/__init__.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/compose.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formating.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formatting.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/formatting.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/loading.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/test_time_aug.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/transforms.py b/cv/detection/autoassign/pytorch/mmdet/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/__init__.py b/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/class_aware_sampler.py b/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/class_aware_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/distributed_sampler.py b/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/group_sampler.py b/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/infinite_sampler.py b/cv/detection/autoassign/pytorch/mmdet/datasets/samplers/infinite_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/datasets/utils.py b/cv/detection/autoassign/pytorch/mmdet/datasets/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/backbones/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/backbones/resnet.py b/cv/detection/autoassign/pytorch/mmdet/models/backbones/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/builder.py b/cv/detection/autoassign/pytorch/mmdet/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_free_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_free_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/anchor_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/atss_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/atss_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/autoassign_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/autoassign_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/base_dense_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/base_dense_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/dense_test_mixins.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/dense_test_mixins.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/fcos_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/fcos_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/paa_head.py b/cv/detection/autoassign/pytorch/mmdet/models/dense_heads/paa_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/detectors/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/detectors/autoassign.py b/cv/detection/autoassign/pytorch/mmdet/models/detectors/autoassign.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/detectors/base.py b/cv/detection/autoassign/pytorch/mmdet/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/detectors/single_stage.py b/cv/detection/autoassign/pytorch/mmdet/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/accuracy.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/accuracy.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/cross_entropy_loss.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/cross_entropy_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/focal_loss.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/iou_loss.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/iou_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/losses/utils.py b/cv/detection/autoassign/pytorch/mmdet/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/necks/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/necks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/necks/fpn.py b/cv/detection/autoassign/pytorch/mmdet/models/necks/fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/__init__.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/brick_wrappers.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/brick_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/builder.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/ckpt_convert.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/ckpt_convert.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/conv_upsample.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/conv_upsample.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/csp_layer.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/csp_layer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/gaussian_target.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/gaussian_target.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/inverted_residual.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/inverted_residual.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/make_divisible.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/make_divisible.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/misc.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/normed_predictor.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/normed_predictor.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/panoptic_gt_processing.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/panoptic_gt_processing.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/point_sample.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/point_sample.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/positional_encoding.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/positional_encoding.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/res_layer.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/res_layer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/models/utils/se_layer.py b/cv/detection/autoassign/pytorch/mmdet/models/utils/se_layer.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/__init__.py b/cv/detection/autoassign/pytorch/mmdet/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/collect_env.py b/cv/detection/autoassign/pytorch/mmdet/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/compat_config.py b/cv/detection/autoassign/pytorch/mmdet/utils/compat_config.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/contextmanagers.py b/cv/detection/autoassign/pytorch/mmdet/utils/contextmanagers.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/logger.py b/cv/detection/autoassign/pytorch/mmdet/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/memory.py b/cv/detection/autoassign/pytorch/mmdet/utils/memory.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/misc.py b/cv/detection/autoassign/pytorch/mmdet/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/profiling.py b/cv/detection/autoassign/pytorch/mmdet/utils/profiling.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/replace_cfg_vals.py b/cv/detection/autoassign/pytorch/mmdet/utils/replace_cfg_vals.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/setup_env.py b/cv/detection/autoassign/pytorch/mmdet/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/split_batch.py b/cv/detection/autoassign/pytorch/mmdet/utils/split_batch.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/util_distribution.py b/cv/detection/autoassign/pytorch/mmdet/utils/util_distribution.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/util_mixins.py b/cv/detection/autoassign/pytorch/mmdet/utils/util_mixins.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/utils/util_random.py b/cv/detection/autoassign/pytorch/mmdet/utils/util_random.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/mmdet/version.py b/cv/detection/autoassign/pytorch/mmdet/version.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/pytest.ini b/cv/detection/autoassign/pytorch/pytest.ini old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/requirements.txt b/cv/detection/autoassign/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/setup.py b/cv/detection/autoassign/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/detection/autoassign/pytorch/train.py b/cv/detection/autoassign/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/detectors/base_detector.py b/cv/detection/centernet/pytorch/src/lib/detectors/base_detector.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/detectors/ctdet.py b/cv/detection/centernet/pytorch/src/lib/detectors/ctdet.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/detectors/ddd.py b/cv/detection/centernet/pytorch/src/lib/detectors/ddd.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/detectors/exdet.py b/cv/detection/centernet/pytorch/src/lib/detectors/exdet.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/detectors/multi_pose.py b/cv/detection/centernet/pytorch/src/lib/detectors/multi_pose.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/opts.py b/cv/detection/centernet/pytorch/src/lib/opts.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/trains/base_trainer.py b/cv/detection/centernet/pytorch/src/lib/trains/base_trainer.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/trains/ctdet.py b/cv/detection/centernet/pytorch/src/lib/trains/ctdet.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/trains/ddd.py b/cv/detection/centernet/pytorch/src/lib/trains/ddd.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/trains/exdet.py b/cv/detection/centernet/pytorch/src/lib/trains/exdet.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/trains/multi_pose.py b/cv/detection/centernet/pytorch/src/lib/trains/multi_pose.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/utils/__init__.py b/cv/detection/centernet/pytorch/src/lib/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/lib/utils/image.py b/cv/detection/centernet/pytorch/src/lib/utils/image.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/main.py b/cv/detection/centernet/pytorch/src/main.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/test.py b/cv/detection/centernet/pytorch/src/test.py old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/tools/kitti_eval/evaluate_object_3d_offline b/cv/detection/centernet/pytorch/src/tools/kitti_eval/evaluate_object_3d_offline old mode 100755 new mode 100644 diff --git a/cv/detection/centernet/pytorch/src/tools/reval.py b/cv/detection/centernet/pytorch/src/tools/reval.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/LICENSE b/cv/detection/fcos/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/README.md b/cv/detection/fcos/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_101_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_101_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_C4_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_C4_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_R_50_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_faster_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_keypoint_rcnn_R_50_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_keypoint_rcnn_R_50_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_101_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_101_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_C4_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_C4_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_R_50_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X-152-32x8d-FPN-IN5k_1.44x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X-152-32x8d-FPN-IN5k_1.44x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml b/cv/detection/fcos/pytorch/configs/caffe2/e2e_mask_rcnn_X_101_32x8d_FPN_1x_caffe2.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/cityscapes/e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml b/cv/detection/fcos/pytorch/configs/cityscapes/e2e_faster_rcnn_R_50_FPN_1x_cocostyle.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/cityscapes/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml b/cv/detection/fcos/pytorch/configs/cityscapes/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_101_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_C4_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_C4_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_X_101_32x8d_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_600.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_600.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_chamv1a_600.yaml b/cv/detection/fcos/pytorch/configs/e2e_faster_rcnn_fbnet_chamv1a_600.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_keypoint_rcnn_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_keypoint_rcnn_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_101_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_C4_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_C4_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_X_101_32x8d_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_600.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_600.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml b/cv/detection/fcos/pytorch/configs/e2e_mask_rcnn_fbnet_xirb16d_dsmask_600.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_R_101_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_32x8d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_X_101_64x4d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_bn_bs16_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_bn_bs16_MNV2_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_101_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_32x8d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_X_101_64x4d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_101_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_MNV2_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/fcos/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/README.md b/cv/detection/fcos/pytorch/configs/gn_baselines/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_1x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_1x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_faster_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_1x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_1x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/e2e_mask_rcnn_R_50_FPN_Xconv1fc_1x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_3x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_faster_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_3x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml b/cv/detection/fcos/pytorch/configs/gn_baselines/scratch_e2e_mask_rcnn_R_50_FPN_Xconv1fc_3x_gn.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml b/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_1_gpu_voc.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml b/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_faster_rcnn_R_50_C4_1x_4_gpu_voc.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml b/cv/detection/fcos/pytorch/configs/pascal_voc/e2e_mask_rcnn_R_50_FPN_1x_cocostyle.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_C4_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_C4_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_R_50_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_faster_rcnn_X_101_32x8d_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_keypoint_rcnn_R_50_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_keypoint_rcnn_R_50_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_C4_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_C4_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_R_50_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/e2e_mask_rcnn_X_101_32x8d_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_C4_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_C4_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_FPN_quick.yaml b/cv/detection/fcos/pytorch/configs/quick_schedules/rpn_R_50_FPN_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_P5_1x.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-101-FPN_P5_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x_quick.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_1x_quick.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_P5_1x.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_R-50-FPN_P5_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/retinanet/retinanet_X_101_32x8d_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/retinanet/retinanet_X_101_32x8d_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/rpn_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/rpn_R_101_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/rpn_R_50_C4_1x.yaml b/cv/detection/fcos/pytorch/configs/rpn_R_50_C4_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/rpn_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/rpn_R_50_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/configs/rpn_X_101_32x8d_FPN_1x.yaml b/cv/detection/fcos/pytorch/configs/rpn_X_101_32x8d_FPN_1x.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/README.md b/cv/detection/fcos/pytorch/demo/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_R_50_FPN_1x.png b/cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_R_50_FPN_1x.png old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_X_101_32x8d_FPN_1x.png b/cv/detection/fcos/pytorch/demo/demo_e2e_mask_rcnn_X_101_32x8d_FPN_1x.png old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/fcos_demo.py b/cv/detection/fcos/pytorch/demo/fcos_demo.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000000885.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000000885.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000001000.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000001000.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000005477.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000005477.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000007281.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000007281.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000012639.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000012639.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000033759.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000033759.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000039769.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000039769.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000050896.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000050896.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000053505.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000053505.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000128654.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000128654.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000463842.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000463842.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000479030.jpg b/cv/detection/fcos/pytorch/demo/images/COCO_val2014_000000479030.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/predictor.py b/cv/detection/fcos/pytorch/demo/predictor.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/demo/webcam.py b/cv/detection/fcos/pytorch/demo/webcam.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/docker/Dockerfile b/cv/detection/fcos/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/docker/docker-jupyter/Dockerfile b/cv/detection/fcos/pytorch/docker/docker-jupyter/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/docker/docker-jupyter/jupyter_notebook_config.py b/cv/detection/fcos/pytorch/docker/docker-jupyter/jupyter_notebook_config.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos/__init__.py b/cv/detection/fcos/pytorch/fcos/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos/bin/fcos b/cv/detection/fcos/pytorch/fcos/bin/fcos old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos/configs b/cv/detection/fcos/pytorch/fcos/configs deleted file mode 120000 index b47cd002..00000000 --- a/cv/detection/fcos/pytorch/fcos/configs +++ /dev/null @@ -1 +0,0 @@ -../configs/fcos \ No newline at end of file diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_R_101_FPN_2x.yaml new file mode 100644 index 00000000..cb76eefd --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_R_101_FPN_2x.yaml @@ -0,0 +1,28 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" \ No newline at end of file diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_R_50_FPN_1x.yaml new file mode 100644 index 00000000..7c36c23d --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_R_50_FPN_1x.yaml @@ -0,0 +1,35 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-50-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 +DATASETS: + TRAIN: ("coco_2017_train",) + TEST: ("coco_2017_val",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" +TEST: + BBOX_AUG: + ENABLED: False + H_FLIP: True + SCALES: (400, 500, 600, 700, 900, 1000, 1100, 1200) + MAX_SIZE: 2000 + SCALE_H_FLIP: True diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_32x8d_FPN_2x.yaml new file mode 100644 index 00000000..6414382e --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_32x8d_FPN_2x.yaml @@ -0,0 +1,31 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 32 + WIDTH_PER_GROUP: 8 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_64x4d_FPN_2x.yaml new file mode 100644 index 00000000..2b4ea9ee --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_X_101_64x4d_FPN_2x.yaml @@ -0,0 +1,31 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-64x4d" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 64 + WIDTH_PER_GROUP: 4 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_bn_bs16_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_bn_bs16_MNV2_FPN_1x.yaml new file mode 100644 index 00000000..583b8267 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_bn_bs16_MNV2_FPN_1x.yaml @@ -0,0 +1,30 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "MNV2-FPN-RETINANET" + FREEZE_CONV_BODY_AT: 0 + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + USE_SYNCBN: False +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_1x.yaml new file mode 100644 index 00000000..f620399b --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_1x.yaml @@ -0,0 +1,38 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_2x.yaml new file mode 100644 index 00000000..73f61c02 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_101_FPN_2x.yaml @@ -0,0 +1,38 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" \ No newline at end of file diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_50_FPN_1x.yaml new file mode 100644 index 00000000..9cdd9897 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_R_50_FPN_1x.yaml @@ -0,0 +1,39 @@ +# FCOS with improvements +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-50-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" +DATASETS: + TRAIN: ("coco_2017_train", ) + TEST: ("coco_2017_val",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_32x8d_FPN_2x.yaml new file mode 100644 index 00000000..057d3863 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_32x8d_FPN_2x.yaml @@ -0,0 +1,41 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 32 + WIDTH_PER_GROUP: 8 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_64x4d_FPN_2x.yaml new file mode 100644 index 00000000..8d6b21dc --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_X_101_64x4d_FPN_2x.yaml @@ -0,0 +1,41 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/k3ys35075jmU1RP/download#X-101-64x4d.pkl" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 64 + WIDTH_PER_GROUP: 4 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_1x.yaml new file mode 100644 index 00000000..b193c4a1 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_1x.yaml @@ -0,0 +1,44 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + STAGE_WITH_DCN: (False, True, True, True) + WITH_MODULATED_DCN: True + DEFORMABLE_GROUPS: 1 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" + # we only use dcn in the last layer of towers + USE_DCN_IN_TOWER: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" + diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_2x.yaml new file mode 100644 index 00000000..c9ba15e6 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_101_FPN_2x.yaml @@ -0,0 +1,44 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-101" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + STAGE_WITH_DCN: (False, True, True, True) + WITH_MODULATED_DCN: True + DEFORMABLE_GROUPS: 1 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" + # we only use dcn in the last layer of towers + USE_DCN_IN_TOWER: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" + diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_50_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_50_FPN_1x.yaml new file mode 100644 index 00000000..7bedeed0 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_R_50_FPN_1x.yaml @@ -0,0 +1,44 @@ +# FCOS with improvements +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/MSRA/R-50" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-50-FPN-RETINANET" + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + STAGE_WITH_DCN: (False, True, True, True) + WITH_MODULATED_DCN: True + DEFORMABLE_GROUPS: 1 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" + # we only use dcn in the last layer of towers + USE_DCN_IN_TOWER: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml new file mode 100644 index 00000000..a8266fa2 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_32x8d_FPN_2x.yaml @@ -0,0 +1,46 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "catalog://ImageNetPretrained/FAIR/20171220/X-101-32x8d" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 32 + WIDTH_PER_GROUP: 8 + STAGE_WITH_DCN: (False, False, True, True) + WITH_MODULATED_DCN: True + DEFORMABLE_GROUPS: 1 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" + # we only use dcn in the last layer of towers + USE_DCN_IN_TOWER: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml new file mode 100644 index 00000000..0d466e8f --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_imprv_dcnv2_X_101_64x4d_FPN_2x.yaml @@ -0,0 +1,53 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/k3ys35075jmU1RP/download#X-101-64x4d.pkl" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "R-101-FPN-RETINANET" + RESNETS: + STRIDE_IN_1X1: False + BACKBONE_OUT_CHANNELS: 256 + NUM_GROUPS: 64 + WIDTH_PER_GROUP: 4 + STAGE_WITH_DCN: (False, False, True, True) + WITH_MODULATED_DCN: True + DEFORMABLE_GROUPS: 1 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + FCOS: + # normalizing the regression targets with FPN strides + NORM_REG_TARGETS: True + # positioning centerness on the regress branch. + # Please refer to https://github.com/tianzhi0549/FCOS/issues/89#issuecomment-516877042 + CENTERNESS_ON_REG: True + # using center sampling and GIoU. + # Please refer to https://github.com/yqyao/FCOS_PLUS + CENTER_SAMPLING_RADIUS: 1.5 + IOU_LOSS_TYPE: "giou" + # we only use dcn in the last layer of towers + USE_DCN_IN_TOWER: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (120000, 160000) + MAX_ITER: 180000 + IMS_PER_BATCH: 16 + WARMUP_METHOD: "constant" +TEST: + BBOX_AUG: + ENABLED: False + H_FLIP: True + SCALES: (400, 500, 600, 700, 900, 1000, 1100, 1200) + MAX_SIZE: 2000 + SCALE_H_FLIP: True diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_MNV2_FPN_1x.yaml new file mode 100644 index 00000000..de937bd4 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_MNV2_FPN_1x.yaml @@ -0,0 +1,30 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "MNV2-FPN-RETINANET" + FREEZE_CONV_BODY_AT: 0 + RESNETS: + BACKBONE_OUT_CHANNELS: 256 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + USE_SYNCBN: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 32 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml new file mode 100644 index 00000000..3a928987 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_MNV2_FPN_1x.yaml @@ -0,0 +1,30 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "MNV2-FPN-RETINANET" + FREEZE_CONV_BODY_AT: 0 + RESNETS: + BACKBONE_OUT_CHANNELS: 128 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + USE_SYNCBN: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_TRAIN: (800,) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 32 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml new file mode 100644 index 00000000..20b805ef --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs32_c128_ms_MNV2_FPN_1x.yaml @@ -0,0 +1,30 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "MNV2-FPN-RETINANET" + FREEZE_CONV_BODY_AT: 0 + RESNETS: + BACKBONE_OUT_CHANNELS: 128 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + USE_SYNCBN: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 32 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml new file mode 100644 index 00000000..29874502 --- /dev/null +++ b/cv/detection/fcos/pytorch/fcos/configs/fcos_syncbn_bs64_c128_ms_MNV2_FPN_1x.yaml @@ -0,0 +1,30 @@ +MODEL: + META_ARCHITECTURE: "GeneralizedRCNN" + WEIGHT: "https://cloudstor.aarnet.edu.au/plus/s/xtixKaxLWmbcyf7/download#mobilenet_v2-ecbe2b5.pth" + RPN_ONLY: True + FCOS_ON: True + BACKBONE: + CONV_BODY: "MNV2-FPN-RETINANET" + FREEZE_CONV_BODY_AT: 0 + RESNETS: + BACKBONE_OUT_CHANNELS: 128 + RETINANET: + USE_C5: False # FCOS uses P5 instead of C5 + USE_SYNCBN: True +DATASETS: + TRAIN: ("coco_2014_train", "coco_2014_valminusminival") + TEST: ("coco_2014_minival",) +INPUT: + MIN_SIZE_RANGE_TRAIN: (640, 800) + MAX_SIZE_TRAIN: 1333 + MIN_SIZE_TEST: 800 + MAX_SIZE_TEST: 1333 +DATALOADER: + SIZE_DIVISIBILITY: 32 +SOLVER: + BASE_LR: 0.01 + WEIGHT_DECAY: 0.0001 + STEPS: (60000, 80000) + MAX_ITER: 90000 + IMS_PER_BATCH: 64 + WARMUP_METHOD: "constant" diff --git a/cv/detection/fcos/pytorch/fcos/fcos.py b/cv/detection/fcos/pytorch/fcos/fcos.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/README.md b/cv/detection/fcos/pytorch/fcos_core/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/__init__.py b/cv/detection/fcos/pytorch/fcos_core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/config/__init__.py b/cv/detection/fcos/pytorch/fcos_core/config/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/config/defaults.py b/cv/detection/fcos/pytorch/fcos_core/config/defaults.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/config/paths_catalog.py b/cv/detection/fcos/pytorch/fcos_core/config/paths_catalog.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/ROIAlign.h b/cv/detection/fcos/pytorch/fcos_core/csrc/ROIAlign.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/ROIPool.h b/cv/detection/fcos/pytorch/fcos_core/csrc/ROIPool.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/SigmoidFocalLoss.h b/cv/detection/fcos/pytorch/fcos_core/csrc/SigmoidFocalLoss.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/ROIAlign_cpu.cpp b/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/ROIAlign_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/nms_cpu.cpp b/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/nms_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/vision.h b/cv/detection/fcos/pytorch/fcos_core/csrc/cpu/vision.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIAlign_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIAlign_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIPool_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ROIPool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/SigmoidFocalLoss_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/SigmoidFocalLoss_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_kernel_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_conv_kernel_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_kernel_cuda.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/deform_pool_kernel_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ml_nms.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/ml_nms.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/nms.cu b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/nms.cu old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/vision.h b/cv/detection/fcos/pytorch/fcos_core/csrc/cuda/vision.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/deform_conv.h b/cv/detection/fcos/pytorch/fcos_core/csrc/deform_conv.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/deform_pool.h b/cv/detection/fcos/pytorch/fcos_core/csrc/deform_pool.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/ml_nms.h b/cv/detection/fcos/pytorch/fcos_core/csrc/ml_nms.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/nms.h b/cv/detection/fcos/pytorch/fcos_core/csrc/nms.h old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/csrc/vision.cpp b/cv/detection/fcos/pytorch/fcos_core/csrc/vision.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/README.md b/cv/detection/fcos/pytorch/fcos_core/data/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/build.py b/cv/detection/fcos/pytorch/fcos_core/data/build.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/collate_batch.py b/cv/detection/fcos/pytorch/fcos_core/data/collate_batch.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/coco.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/concat_dataset.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/concat_dataset.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/coco_eval.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/coco/coco_eval.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/voc_eval.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/evaluation/voc/voc_eval.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/list_dataset.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/list_dataset.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/datasets/voc.py b/cv/detection/fcos/pytorch/fcos_core/data/datasets/voc.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/samplers/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/samplers/distributed.py b/cv/detection/fcos/pytorch/fcos_core/data/samplers/distributed.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/samplers/grouped_batch_sampler.py b/cv/detection/fcos/pytorch/fcos_core/data/samplers/grouped_batch_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/samplers/iteration_based_batch_sampler.py b/cv/detection/fcos/pytorch/fcos_core/data/samplers/iteration_based_batch_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/transforms/__init__.py b/cv/detection/fcos/pytorch/fcos_core/data/transforms/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/transforms/build.py b/cv/detection/fcos/pytorch/fcos_core/data/transforms/build.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/data/transforms/transforms.py b/cv/detection/fcos/pytorch/fcos_core/data/transforms/transforms.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/engine/__init__.py b/cv/detection/fcos/pytorch/fcos_core/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/engine/bbox_aug.py b/cv/detection/fcos/pytorch/fcos_core/engine/bbox_aug.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/engine/inference.py b/cv/detection/fcos/pytorch/fcos_core/engine/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/engine/trainer.py b/cv/detection/fcos/pytorch/fcos_core/engine/trainer.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/__init__.py b/cv/detection/fcos/pytorch/fcos_core/layers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/_utils.py b/cv/detection/fcos/pytorch/fcos_core/layers/_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/batch_norm.py b/cv/detection/fcos/pytorch/fcos_core/layers/batch_norm.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/dcn/__init__.py b/cv/detection/fcos/pytorch/fcos_core/layers/dcn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_func.py b/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_func.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_module.py b/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_func.py b/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_func.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_module.py b/cv/detection/fcos/pytorch/fcos_core/layers/dcn/deform_pool_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/iou_loss.py b/cv/detection/fcos/pytorch/fcos_core/layers/iou_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/misc.py b/cv/detection/fcos/pytorch/fcos_core/layers/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/nms.py b/cv/detection/fcos/pytorch/fcos_core/layers/nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/roi_align.py b/cv/detection/fcos/pytorch/fcos_core/layers/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/roi_pool.py b/cv/detection/fcos/pytorch/fcos_core/layers/roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/scale.py b/cv/detection/fcos/pytorch/fcos_core/layers/scale.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/sigmoid_focal_loss.py b/cv/detection/fcos/pytorch/fcos_core/layers/sigmoid_focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/layers/smooth_l1_loss.py b/cv/detection/fcos/pytorch/fcos_core/layers/smooth_l1_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/backbone.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/backbone.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_builder.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_modeldef.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fbnet_modeldef.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fpn.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/mobilenet.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/mobilenet.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/resnet.py b/cv/detection/fcos/pytorch/fcos_core/modeling/backbone/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/balanced_positive_negative_sampler.py b/cv/detection/fcos/pytorch/fcos_core/modeling/balanced_positive_negative_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/box_coder.py b/cv/detection/fcos/pytorch/fcos_core/modeling/box_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/detector/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/detector/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/detector/detectors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/detector/detectors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/detector/generalized_rcnn.py b/cv/detection/fcos/pytorch/fcos_core/modeling/detector/generalized_rcnn.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/make_layers.py b/cv/detection/fcos/pytorch/fcos_core/modeling/make_layers.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/matcher.py b/cv/detection/fcos/pytorch/fcos_core/modeling/matcher.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/poolers.py b/cv/detection/fcos/pytorch/fcos_core/modeling/poolers.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/registry.py b/cv/detection/fcos/pytorch/fcos_core/modeling/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/box_head.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/box_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_feature_extractors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_feature_extractors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_predictors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/box_head/roi_box_predictors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/keypoint_head.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/keypoint_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_feature_extractors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_feature_extractors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_predictors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/keypoint_head/roi_keypoint_predictors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/mask_head.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/mask_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_feature_extractors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_feature_extractors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_predictors.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/mask_head/roi_mask_predictors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/roi_heads.py b/cv/detection/fcos/pytorch/fcos_core/modeling/roi_heads/roi_heads.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/anchor_generator.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/anchor_generator.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/fcos.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/fcos.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/fcos/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/__init__.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/inference.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/inference.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/loss.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/retinanet.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/retinanet/retinanet.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/rpn.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/rpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/utils.py b/cv/detection/fcos/pytorch/fcos_core/modeling/rpn/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/modeling/utils.py b/cv/detection/fcos/pytorch/fcos_core/modeling/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/solver/__init__.py b/cv/detection/fcos/pytorch/fcos_core/solver/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/solver/build.py b/cv/detection/fcos/pytorch/fcos_core/solver/build.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/solver/lr_scheduler.py b/cv/detection/fcos/pytorch/fcos_core/solver/lr_scheduler.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/__init__.py b/cv/detection/fcos/pytorch/fcos_core/structures/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/bounding_box.py b/cv/detection/fcos/pytorch/fcos_core/structures/bounding_box.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/boxlist_ops.py b/cv/detection/fcos/pytorch/fcos_core/structures/boxlist_ops.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/image_list.py b/cv/detection/fcos/pytorch/fcos_core/structures/image_list.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/keypoint.py b/cv/detection/fcos/pytorch/fcos_core/structures/keypoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/structures/segmentation_mask.py b/cv/detection/fcos/pytorch/fcos_core/structures/segmentation_mask.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/README.md b/cv/detection/fcos/pytorch/fcos_core/utils/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/__init__.py b/cv/detection/fcos/pytorch/fcos_core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/c2_model_loading.py b/cv/detection/fcos/pytorch/fcos_core/utils/c2_model_loading.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/checkpoint.py b/cv/detection/fcos/pytorch/fcos_core/utils/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/collect_env.py b/cv/detection/fcos/pytorch/fcos_core/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/comm.py b/cv/detection/fcos/pytorch/fcos_core/utils/comm.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/cv2_util.py b/cv/detection/fcos/pytorch/fcos_core/utils/cv2_util.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/env.py b/cv/detection/fcos/pytorch/fcos_core/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/imports.py b/cv/detection/fcos/pytorch/fcos_core/utils/imports.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/logger.py b/cv/detection/fcos/pytorch/fcos_core/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/metric_logger.py b/cv/detection/fcos/pytorch/fcos_core/utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/miscellaneous.py b/cv/detection/fcos/pytorch/fcos_core/utils/miscellaneous.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/model_serialization.py b/cv/detection/fcos/pytorch/fcos_core/utils/model_serialization.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/model_zoo.py b/cv/detection/fcos/pytorch/fcos_core/utils/model_zoo.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/registry.py b/cv/detection/fcos/pytorch/fcos_core/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/fcos_core/utils/timer.py b/cv/detection/fcos/pytorch/fcos_core/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/onnx/export_model_to_onnx.py b/cv/detection/fcos/pytorch/onnx/export_model_to_onnx.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/onnx/test_fcos_onnx_model.py b/cv/detection/fcos/pytorch/onnx/test_fcos_onnx_model.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/requirements.txt b/cv/detection/fcos/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/setup.py b/cv/detection/fcos/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/checkpoint.py b/cv/detection/fcos/pytorch/tests/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/env_tests/env.py b/cv/detection/fcos/pytorch/tests/env_tests/env.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_backbones.py b/cv/detection/fcos/pytorch/tests/test_backbones.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_box_coder.py b/cv/detection/fcos/pytorch/tests/test_box_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_configs.py b/cv/detection/fcos/pytorch/tests/test_configs.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_data_samplers.py b/cv/detection/fcos/pytorch/tests/test_data_samplers.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_detectors.py b/cv/detection/fcos/pytorch/tests/test_detectors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_fbnet.py b/cv/detection/fcos/pytorch/tests/test_fbnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_feature_extractors.py b/cv/detection/fcos/pytorch/tests/test_feature_extractors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_metric_logger.py b/cv/detection/fcos/pytorch/tests/test_metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_nms.py b/cv/detection/fcos/pytorch/tests/test_nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_predictors.py b/cv/detection/fcos/pytorch/tests/test_predictors.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_rpn_heads.py b/cv/detection/fcos/pytorch/tests/test_rpn_heads.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/test_segmentation_mask.py b/cv/detection/fcos/pytorch/tests/test_segmentation_mask.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tests/utils.py b/cv/detection/fcos/pytorch/tests/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tools/cityscapes/convert_cityscapes_to_coco.py b/cv/detection/fcos/pytorch/tools/cityscapes/convert_cityscapes_to_coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tools/cityscapes/instances2dict_with_polygons.py b/cv/detection/fcos/pytorch/tools/cityscapes/instances2dict_with_polygons.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tools/remove_solver_states.py b/cv/detection/fcos/pytorch/tools/remove_solver_states.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tools/test_net.py b/cv/detection/fcos/pytorch/tools/test_net.py old mode 100755 new mode 100644 diff --git a/cv/detection/fcos/pytorch/tools/train_net.py b/cv/detection/fcos/pytorch/tools/train_net.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/README.md b/cv/detection/pvanet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/__init__.py b/cv/detection/pvanet/pytorch/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/_utils.py b/cv/detection/pvanet/pytorch/_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/coco_eval.py b/cv/detection/pvanet/pytorch/coco_eval.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/common_utils/__init__.py b/cv/detection/pvanet/pytorch/common_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/common_utils/dist.py b/cv/detection/pvanet/pytorch/common_utils/dist.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/common_utils/metric_logger.py b/cv/detection/pvanet/pytorch/common_utils/metric_logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/common_utils/misc.py b/cv/detection/pvanet/pytorch/common_utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/common_utils/smooth_value.py b/cv/detection/pvanet/pytorch/common_utils/smooth_value.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/__init__.py b/cv/detection/pvanet/pytorch/dataloader/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/detection.py b/cv/detection/pvanet/pytorch/dataloader/detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/__init__.py b/cv/detection/pvanet/pytorch/dataloader/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/coco_utils.py b/cv/detection/pvanet/pytorch/dataloader/utils/coco_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/functional.py b/cv/detection/pvanet/pytorch/dataloader/utils/functional.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/functional_pil.py b/cv/detection/pvanet/pytorch/dataloader/utils/functional_pil.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/functional_tensor.py b/cv/detection/pvanet/pytorch/dataloader/utils/functional_tensor.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/pascal_voc.py b/cv/detection/pvanet/pytorch/dataloader/utils/pascal_voc.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/presets_detection.py b/cv/detection/pvanet/pytorch/dataloader/utils/presets_detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/presets_segmentation.py b/cv/detection/pvanet/pytorch/dataloader/utils/presets_segmentation.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/dataloader/utils/transforms_det.py b/cv/detection/pvanet/pytorch/dataloader/utils/transforms_det.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/engine.py b/cv/detection/pvanet/pytorch/engine.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/group_by_aspect_ratio.py b/cv/detection/pvanet/pytorch/group_by_aspect_ratio.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/__init__.py b/cv/detection/pvanet/pytorch/model/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/_utils.py b/cv/detection/pvanet/pytorch/model/_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/anchor_utils.py b/cv/detection/pvanet/pytorch/model/anchor_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/det_utils.py b/cv/detection/pvanet/pytorch/model/det_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/generalized_rcnn.py b/cv/detection/pvanet/pytorch/model/generalized_rcnn.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/image_list.py b/cv/detection/pvanet/pytorch/model/image_list.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/model_main.py b/cv/detection/pvanet/pytorch/model/model_main.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/model_utils.py b/cv/detection/pvanet/pytorch/model/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/__init__.py b/cv/detection/pvanet/pytorch/model/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/_box_convert.py b/cv/detection/pvanet/pytorch/model/ops/_box_convert.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/_ops.py b/cv/detection/pvanet/pytorch/model/ops/_ops.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/_utils.py b/cv/detection/pvanet/pytorch/model/ops/_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/boxes.py b/cv/detection/pvanet/pytorch/model/ops/boxes.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/feature_pyramid_network.py b/cv/detection/pvanet/pytorch/model/ops/feature_pyramid_network.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/focal_loss.py b/cv/detection/pvanet/pytorch/model/ops/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/misc.py b/cv/detection/pvanet/pytorch/model/ops/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/poolers.py b/cv/detection/pvanet/pytorch/model/ops/poolers.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/roi_align.py b/cv/detection/pvanet/pytorch/model/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/roi_pool.py b/cv/detection/pvanet/pytorch/model/ops/roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/ops/smooth_l1_loss.py b/cv/detection/pvanet/pytorch/model/ops/smooth_l1_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/pvanet.py b/cv/detection/pvanet/pytorch/model/pvanet.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/roi_heads.py b/cv/detection/pvanet/pytorch/model/roi_heads.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/rpn.py b/cv/detection/pvanet/pytorch/model/rpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/transform.py b/cv/detection/pvanet/pytorch/model/transform.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/model/weight_init.py b/cv/detection/pvanet/pytorch/model/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/train.py b/cv/detection/pvanet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/pvanet/pytorch/train_pvanet_dist.sh b/cv/detection/pvanet/pytorch/train_pvanet_dist.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/Dockerfile b/cv/detection/ssd/MindSpore/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/README.md b/cv/detection/ssd/MindSpore/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/CMakeLists.txt b/cv/detection/ssd/MindSpore/ascend310_infer/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/aipp.cfg b/cv/detection/ssd/MindSpore/ascend310_infer/aipp.cfg old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/build.sh b/cv/detection/ssd/MindSpore/ascend310_infer/build.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/inc/utils.h b/cv/detection/ssd/MindSpore/ascend310_infer/inc/utils.h old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/src/main.cc b/cv/detection/ssd/MindSpore/ascend310_infer/src/main.cc old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/ascend310_infer/src/utils.cc b/cv/detection/ssd/MindSpore/ascend310_infer/src/utils.cc old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd300_config.yaml b/cv/detection/ssd/MindSpore/config/ssd300_config.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd300_config_gpu.yaml b/cv/detection/ssd/MindSpore/config/ssd300_config_gpu.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_300_config_gpu.yaml b/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_300_config_gpu.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config.yaml b/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config_gpu.yaml b/cv/detection/ssd/MindSpore/config/ssd_mobilenet_v1_fpn_config_gpu.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config.yaml b/cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config_gpu.yaml b/cv/detection/ssd/MindSpore/config/ssd_resnet50_fpn_config_gpu.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_vgg16_config.yaml b/cv/detection/ssd/MindSpore/config/ssd_vgg16_config.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/config/ssd_vgg16_config_gpu.yaml b/cv/detection/ssd/MindSpore/config/ssd_vgg16_config_gpu.yaml old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/eval.py b/cv/detection/ssd/MindSpore/eval.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/eval_onnx.py b/cv/detection/ssd/MindSpore/eval_onnx.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/export.py b/cv/detection/ssd/MindSpore/export.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/mindspore_hub_conf.py b/cv/detection/ssd/MindSpore/mindspore_hub_conf.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/postprocess.py b/cv/detection/ssd/MindSpore/postprocess.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/requirements.txt b/cv/detection/ssd/MindSpore/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_distribute_train.sh b/cv/detection/ssd/MindSpore/scripts/run_distribute_train.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_distribute_train_gpu.sh b/cv/detection/ssd/MindSpore/scripts/run_distribute_train_gpu.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_eval.sh b/cv/detection/ssd/MindSpore/scripts/run_eval.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_eval_gpu.sh b/cv/detection/ssd/MindSpore/scripts/run_eval_gpu.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_eval_onnx.sh b/cv/detection/ssd/MindSpore/scripts/run_eval_onnx.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_infer_310.sh b/cv/detection/ssd/MindSpore/scripts/run_infer_310.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_standalone_train.sh b/cv/detection/ssd/MindSpore/scripts/run_standalone_train.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/scripts/run_standalone_train_gpu.sh b/cv/detection/ssd/MindSpore/scripts/run_standalone_train_gpu.sh old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/__init__.py b/cv/detection/ssd/MindSpore/src/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/anchor_generator.py b/cv/detection/ssd/MindSpore/src/anchor_generator.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/box_utils.py b/cv/detection/ssd/MindSpore/src/box_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/dataset.py b/cv/detection/ssd/MindSpore/src/dataset.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/eval_callback.py b/cv/detection/ssd/MindSpore/src/eval_callback.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/eval_utils.py b/cv/detection/ssd/MindSpore/src/eval_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/fpn.py b/cv/detection/ssd/MindSpore/src/fpn.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/init_params.py b/cv/detection/ssd/MindSpore/src/init_params.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/lr_schedule.py b/cv/detection/ssd/MindSpore/src/lr_schedule.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/mobilenet_v1.py b/cv/detection/ssd/MindSpore/src/mobilenet_v1.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/model_utils/config.py b/cv/detection/ssd/MindSpore/src/model_utils/config.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/model_utils/device_adapter.py b/cv/detection/ssd/MindSpore/src/model_utils/device_adapter.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/model_utils/local_adapter.py b/cv/detection/ssd/MindSpore/src/model_utils/local_adapter.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/model_utils/moxing_adapter.py b/cv/detection/ssd/MindSpore/src/model_utils/moxing_adapter.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/resnet.py b/cv/detection/ssd/MindSpore/src/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/ssd.py b/cv/detection/ssd/MindSpore/src/ssd.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/src/vgg16.py b/cv/detection/ssd/MindSpore/src/vgg16.py old mode 100755 new mode 100644 diff --git a/cv/detection/ssd/MindSpore/train.py b/cv/detection/ssd/MindSpore/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/.gitignore b/cv/detection/yolof/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/LICENSE b/cv/detection/yolof/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/README.md b/cv/detection/yolof/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/_base_/datasets/coco_detection.py b/cv/detection/yolof/pytorch/configs/_base_/datasets/coco_detection.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/_base_/default_runtime.py b/cv/detection/yolof/pytorch/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/_base_/schedules/schedule_1x.py b/cv/detection/yolof/pytorch/configs/_base_/schedules/schedule_1x.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/yolof/README.md b/cv/detection/yolof/pytorch/configs/yolof/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/yolof/metafile.yml b/cv/detection/yolof/pytorch/configs/yolof/metafile.yml old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_1x_coco.py b/cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_1x_coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_iter-1x_coco.py b/cv/detection/yolof/pytorch/configs/yolof/yolof_r50_c5_8x8_iter-1x_coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/__init__.py b/cv/detection/yolof/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/__init__.py b/cv/detection/yolof/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/__init__.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/activation.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/norm.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/padding.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/plugin.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/bricks/registry.py b/cv/detection/yolof/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/builder.py b/cv/detection/yolof/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/resnet.py b/cv/detection/yolof/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/utils/__init__.py b/cv/detection/yolof/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/cnn/utils/weight_init.py b/cv/detection/yolof/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/engine/__init__.py b/cv/detection/yolof/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/engine/test.py b/cv/detection/yolof/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/__init__.py b/cv/detection/yolof/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/file_client.py b/cv/detection/yolof/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/handlers/__init__.py b/cv/detection/yolof/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/handlers/base.py b/cv/detection/yolof/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/detection/yolof/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/detection/yolof/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/detection/yolof/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/io.py b/cv/detection/yolof/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/fileio/parse.py b/cv/detection/yolof/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/__init__.py b/cv/detection/yolof/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/colorspace.py b/cv/detection/yolof/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/geometric.py b/cv/detection/yolof/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/io.py b/cv/detection/yolof/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/misc.py b/cv/detection/yolof/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/image/photometric.py b/cv/detection/yolof/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/model_zoo/deprecated.json b/cv/detection/yolof/pytorch/mmcv/model_zoo/deprecated.json old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/model_zoo/mmcls.json b/cv/detection/yolof/pytorch/mmcv/model_zoo/mmcls.json old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/__init__.py b/cv/detection/yolof/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/README.md b/cv/detection/yolof/pytorch/mmcv/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh b/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/nms_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh b/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/cuda/nms_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/nms.cpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/nms.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/detection/yolof/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/focal_loss.py b/cv/detection/yolof/pytorch/mmcv/ops/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/info.py b/cv/detection/yolof/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/ops/nms.py b/cv/detection/yolof/pytorch/mmcv/ops/nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/__init__.py b/cv/detection/yolof/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/_functions.py b/cv/detection/yolof/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/collate.py b/cv/detection/yolof/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/data_container.py b/cv/detection/yolof/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/data_parallel.py b/cv/detection/yolof/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/distributed.py b/cv/detection/yolof/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/detection/yolof/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/registry.py b/cv/detection/yolof/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/scatter_gather.py b/cv/detection/yolof/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/parallel/utils.py b/cv/detection/yolof/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/__init__.py b/cv/detection/yolof/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/base_module.py b/cv/detection/yolof/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/base_runner.py b/cv/detection/yolof/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/builder.py b/cv/detection/yolof/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/checkpoint.py b/cv/detection/yolof/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/default_constructor.py b/cv/detection/yolof/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/dist_utils.py b/cv/detection/yolof/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/epoch_based_runner.py b/cv/detection/yolof/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/fp16_utils.py b/cv/detection/yolof/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/__init__.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/closure.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/ema.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/evaluation.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/hook.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/base.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/text.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/memory.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/optimizer.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/profiler.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/detection/yolof/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/iter_based_runner.py b/cv/detection/yolof/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/log_buffer.py b/cv/detection/yolof/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/optimizer/__init__.py b/cv/detection/yolof/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/optimizer/builder.py b/cv/detection/yolof/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/detection/yolof/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/priority.py b/cv/detection/yolof/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/runner/utils.py b/cv/detection/yolof/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/__init__.py b/cv/detection/yolof/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/config.py b/cv/detection/yolof/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/ext_loader.py b/cv/detection/yolof/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/logging.py b/cv/detection/yolof/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/misc.py b/cv/detection/yolof/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/path.py b/cv/detection/yolof/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/progressbar.py b/cv/detection/yolof/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/registry.py b/cv/detection/yolof/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/testing.py b/cv/detection/yolof/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/timer.py b/cv/detection/yolof/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/utils/version_utils.py b/cv/detection/yolof/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmcv/version.py b/cv/detection/yolof/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/__init__.py b/cv/detection/yolof/pytorch/mmdet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/apis/__init__.py b/cv/detection/yolof/pytorch/mmdet/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/apis/test.py b/cv/detection/yolof/pytorch/mmdet/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/apis/train.py b/cv/detection/yolof/pytorch/mmdet/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/anchor/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/anchor/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/anchor/anchor_generator.py b/cv/detection/yolof/pytorch/mmdet/core/anchor/anchor_generator.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/anchor/builder.py b/cv/detection/yolof/pytorch/mmdet/core/anchor/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/anchor/utils.py b/cv/detection/yolof/pytorch/mmdet/core/anchor/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/assign_result.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/assign_result.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/base_assigner.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/base_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/assigners/uniform_assigner.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/builder.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/base_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/coder/delta_xywh_bbox_coder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/builder.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/iou_calculators/iou2d_calculator.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/base_sampler.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/base_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/pseudo_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/sampling_result.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/samplers/sampling_result.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/bbox/transforms.py b/cv/detection/yolof/pytorch/mmdet/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/bbox_overlaps.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/bbox_overlaps.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/class_names.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/class_names.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/eval_hooks.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/mean_ap.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/mean_ap.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/panoptic_utils.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/panoptic_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/evaluation/recall.py b/cv/detection/yolof/pytorch/mmdet/core/evaluation/recall.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/optimizers/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/optimizers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/optimizers/builder.py b/cv/detection/yolof/pytorch/mmdet/core/optimizers/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py b/cv/detection/yolof/pytorch/mmdet/core/optimizers/layer_decay_optimizer_constructor.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/post_processing/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/post_processing/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/post_processing/bbox_nms.py b/cv/detection/yolof/pytorch/mmdet/core/post_processing/bbox_nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/post_processing/matrix_nms.py b/cv/detection/yolof/pytorch/mmdet/core/post_processing/matrix_nms.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/post_processing/merge_augs.py b/cv/detection/yolof/pytorch/mmdet/core/post_processing/merge_augs.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/utils/__init__.py b/cv/detection/yolof/pytorch/mmdet/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/utils/dist_utils.py b/cv/detection/yolof/pytorch/mmdet/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/core/utils/misc.py b/cv/detection/yolof/pytorch/mmdet/core/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/__init__.py b/cv/detection/yolof/pytorch/mmdet/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/__init__.py b/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/coco_api.py b/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/coco_api.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py b/cv/detection/yolof/pytorch/mmdet/datasets/api_wrappers/panoptic_evaluation.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/builder.py b/cv/detection/yolof/pytorch/mmdet/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/coco.py b/cv/detection/yolof/pytorch/mmdet/datasets/coco.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/custom.py b/cv/detection/yolof/pytorch/mmdet/datasets/custom.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/dataset_wrappers.py b/cv/detection/yolof/pytorch/mmdet/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/__init__.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/auto_augment.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/auto_augment.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/compose.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formating.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formatting.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/formatting.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/instaboost.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/instaboost.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/loading.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/test_time_aug.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/transforms.py b/cv/detection/yolof/pytorch/mmdet/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/samplers/__init__.py b/cv/detection/yolof/pytorch/mmdet/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/samplers/class_aware_sampler.py b/cv/detection/yolof/pytorch/mmdet/datasets/samplers/class_aware_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/samplers/distributed_sampler.py b/cv/detection/yolof/pytorch/mmdet/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/samplers/group_sampler.py b/cv/detection/yolof/pytorch/mmdet/datasets/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/samplers/infinite_sampler.py b/cv/detection/yolof/pytorch/mmdet/datasets/samplers/infinite_sampler.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/datasets/utils.py b/cv/detection/yolof/pytorch/mmdet/datasets/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/backbones/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/backbones/resnet.py b/cv/detection/yolof/pytorch/mmdet/models/backbones/resnet.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/builder.py b/cv/detection/yolof/pytorch/mmdet/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/dense_heads/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/dense_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/dense_heads/anchor_head.py b/cv/detection/yolof/pytorch/mmdet/models/dense_heads/anchor_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/dense_heads/base_dense_head.py b/cv/detection/yolof/pytorch/mmdet/models/dense_heads/base_dense_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/dense_heads/dense_test_mixins.py b/cv/detection/yolof/pytorch/mmdet/models/dense_heads/dense_test_mixins.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/dense_heads/yolof_head.py b/cv/detection/yolof/pytorch/mmdet/models/dense_heads/yolof_head.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/detectors/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/detectors/base.py b/cv/detection/yolof/pytorch/mmdet/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/detectors/single_stage.py b/cv/detection/yolof/pytorch/mmdet/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/detectors/yolof.py b/cv/detection/yolof/pytorch/mmdet/models/detectors/yolof.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/losses/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/losses/accuracy.py b/cv/detection/yolof/pytorch/mmdet/models/losses/accuracy.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/losses/focal_loss.py b/cv/detection/yolof/pytorch/mmdet/models/losses/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/losses/iou_loss.py b/cv/detection/yolof/pytorch/mmdet/models/losses/iou_loss.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/losses/utils.py b/cv/detection/yolof/pytorch/mmdet/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/necks/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/necks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/necks/dilated_encoder.py b/cv/detection/yolof/pytorch/mmdet/models/necks/dilated_encoder.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/utils/__init__.py b/cv/detection/yolof/pytorch/mmdet/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/models/utils/res_layer.py b/cv/detection/yolof/pytorch/mmdet/models/utils/res_layer.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/__init__.py b/cv/detection/yolof/pytorch/mmdet/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/collect_env.py b/cv/detection/yolof/pytorch/mmdet/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/compat_config.py b/cv/detection/yolof/pytorch/mmdet/utils/compat_config.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/contextmanagers.py b/cv/detection/yolof/pytorch/mmdet/utils/contextmanagers.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/logger.py b/cv/detection/yolof/pytorch/mmdet/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/memory.py b/cv/detection/yolof/pytorch/mmdet/utils/memory.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/misc.py b/cv/detection/yolof/pytorch/mmdet/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/replace_cfg_vals.py b/cv/detection/yolof/pytorch/mmdet/utils/replace_cfg_vals.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/setup_env.py b/cv/detection/yolof/pytorch/mmdet/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/split_batch.py b/cv/detection/yolof/pytorch/mmdet/utils/split_batch.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/utils/util_distribution.py b/cv/detection/yolof/pytorch/mmdet/utils/util_distribution.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/mmdet/version.py b/cv/detection/yolof/pytorch/mmdet/version.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/requirements.txt b/cv/detection/yolof/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/setup.cfg b/cv/detection/yolof/pytorch/setup.cfg old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/setup.py b/cv/detection/yolof/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/train.py b/cv/detection/yolof/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/train.sh b/cv/detection/yolof/pytorch/train.sh old mode 100755 new mode 100644 diff --git a/cv/detection/yolof/pytorch/train_dist.sh b/cv/detection/yolof/pytorch/train_dist.sh old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/README.md b/cv/detection/yolov3/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/coco.names b/cv/detection/yolov3/pytorch/data/coco.names old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/custom/classes.names b/cv/detection/yolov3/pytorch/data/custom/classes.names old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/custom/images/train.jpg b/cv/detection/yolov3/pytorch/data/custom/images/train.jpg old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/custom/labels/train.txt b/cv/detection/yolov3/pytorch/data/custom/labels/train.txt old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/custom/train.txt b/cv/detection/yolov3/pytorch/data/custom/train.txt old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/custom/valid.txt b/cv/detection/yolov3/pytorch/data/custom/valid.txt old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/get_coco_dataset.sh b/cv/detection/yolov3/pytorch/data/get_coco_dataset.sh old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/voc.names b/cv/detection/yolov3/pytorch/data/voc.names old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/voc/train.txt b/cv/detection/yolov3/pytorch/data/voc/train.txt old mode 100755 new mode 100644 diff --git a/cv/detection/yolov3/pytorch/data/voc/valid.txt b/cv/detection/yolov3/pytorch/data/voc/valid.txt old mode 100755 new mode 100644 diff --git a/cv/instance_segmentation/yolact/pytorch/external/DCNv2/make.sh b/cv/instance_segmentation/yolact/pytorch/external/DCNv2/make.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/.gitignore b/cv/ocr/dbnet/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/CITATION.cff b/cv/ocr/dbnet/pytorch/CITATION.cff old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/PKG-INFO b/cv/ocr/dbnet/pytorch/EGG-INFO/PKG-INFO old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/SOURCES.txt b/cv/ocr/dbnet/pytorch/EGG-INFO/SOURCES.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/dependency_links.txt b/cv/ocr/dbnet/pytorch/EGG-INFO/dependency_links.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/not-zip-safe b/cv/ocr/dbnet/pytorch/EGG-INFO/not-zip-safe old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/requires.txt b/cv/ocr/dbnet/pytorch/EGG-INFO/requires.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/EGG-INFO/top_level.txt b/cv/ocr/dbnet/pytorch/EGG-INFO/top_level.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/LICENSE b/cv/ocr/dbnet/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/README.md b/cv/ocr/dbnet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/default_runtime.py b/cv/ocr/dbnet/pytorch/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/det_datasets/icdar2015.py b/cv/ocr/dbnet/pytorch/configs/_base_/det_datasets/icdar2015.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_mobilenetv3_fpnc.py b/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_mobilenetv3_fpnc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r18_fpnc.py b/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r18_fpnc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r50dcnv2_fpnc.py b/cv/ocr/dbnet/pytorch/configs/_base_/det_models/dbnet_r50dcnv2_fpnc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/det_pipelines/dbnet_pipeline.py b/cv/ocr/dbnet/pytorch/configs/_base_/det_pipelines/dbnet_pipeline.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_adam_1200e.py b/cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_adam_1200e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py b/cv/ocr/dbnet/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/README.md b/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_mobilenetv3_fpnc_1200e_icdar2015.py b/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_mobilenetv3_fpnc_1200e_icdar2015.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r18_fpnc_1200e_icdar2015.py b/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r18_fpnc_1200e_icdar2015.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r50dcnv2_fpnc_1200e_icdar2015.py b/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/dbnet_r50dcnv2_fpnc_1200e_icdar2015.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/metafile.yml b/cv/ocr/dbnet/pytorch/configs/textdet/dbnet/metafile.yml old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/apis/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/apis/inference.py b/cv/ocr/dbnet/pytorch/dbnet/apis/inference.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/apis/test.py b/cv/ocr/dbnet/pytorch/dbnet/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/apis/train.py b/cv/ocr/dbnet/pytorch/dbnet/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/apis/utils.py b/cv/ocr/dbnet/pytorch/dbnet/apis/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean.py b/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_ic13.py b/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_ic13.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_iou.py b/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/hmean_iou.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/utils.py b/cv/ocr/dbnet/pytorch/dbnet/core/evaluation/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/mask.py b/cv/ocr/dbnet/pytorch/dbnet/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/core/visualize.py b/cv/ocr/dbnet/pytorch/dbnet/core/visualize.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/base_dataset.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/builder.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/icdar_dataset.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/icdar_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/box_utils.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/box_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/crop.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/custom_format_bundle.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/custom_format_bundle.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/dbnet_transforms.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/dbnet_transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/loading.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/base_textdet_targets.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/base_textdet_targets.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/dbnet_targets.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/textdet_targets/dbnet_targets.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transform_wrappers.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transform_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transforms.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/text_det_dataset.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/text_det_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/uniform_concat_dataset.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/uniform_concat_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/backend.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/backend.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/loader.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/parser.py b/cv/ocr/dbnet/pytorch/dbnet/datasets/utils/parser.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/builder.py b/cv/ocr/dbnet/pytorch/dbnet/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/unet.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/backbones/unet.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/single_stage.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/dice_loss.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/dice_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/focal_loss.py b/cv/ocr/dbnet/pytorch/dbnet/models/common/losses/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/db_head.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/db_head.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/head_mixin.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/dense_heads/head_mixin.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/dbnet.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/dbnet.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/single_stage_text_detector.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/single_stage_text_detector.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/text_detector_mixin.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/detectors/text_detector_mixin.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/db_loss.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/losses/db_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/fpn_cat.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/necks/fpn_cat.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/base_postprocessor.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/base_postprocessor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/db_postprocessor.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/db_postprocessor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/utils.py b/cv/ocr/dbnet/pytorch/dbnet/models/textdet/postprocess/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/box_util.py b/cv/ocr/dbnet/pytorch/dbnet/utils/box_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/check_argument.py b/cv/ocr/dbnet/pytorch/dbnet/utils/check_argument.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/collect_env.py b/cv/ocr/dbnet/pytorch/dbnet/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/fileio.py b/cv/ocr/dbnet/pytorch/dbnet/utils/fileio.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/lmdb_util.py b/cv/ocr/dbnet/pytorch/dbnet/utils/lmdb_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/logger.py b/cv/ocr/dbnet/pytorch/dbnet/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/model.py b/cv/ocr/dbnet/pytorch/dbnet/utils/model.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/ocr.py b/cv/ocr/dbnet/pytorch/dbnet/utils/ocr.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/setup_env.py b/cv/ocr/dbnet/pytorch/dbnet/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/utils/string_util.py b/cv/ocr/dbnet/pytorch/dbnet/utils/string_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet/version.py b/cv/ocr/dbnet/pytorch/dbnet/version.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/activation.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv2d_adaptive_padding.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv_module.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/drop.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hsigmoid.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hswish.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/norm.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/padding.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/plugin.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/registry.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/upsample.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/wrappers.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/builder.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/resnet.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/flops_counter.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/fuse_conv_bn.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/sync_bn.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/weight_init.py b/cv/ocr/dbnet/pytorch/dbnet_cv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/engine/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/engine/test.py b/cv/ocr/dbnet/pytorch/dbnet_cv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/file_client.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/base.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/json_handler.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/pickle_handler.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/yaml_handler.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/io.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/parse.py b/cv/ocr/dbnet/pytorch/dbnet_cv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/colorspace.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/geometric.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/io.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/misc.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/image/photometric.py b/cv/ocr/dbnet/pytorch/dbnet_cv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/deprecated.json b/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/deprecated.json old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/mmcls.json b/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/mmcls.json old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/open_mmlab.json b/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/open_mmlab.json old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/torchvision_0.12.json b/cv/ocr/dbnet/pytorch/dbnet_cv/model_zoo/torchvision_0.12.json old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/README.md b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/deform_roi_pool_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/ms_deform_attn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/roi_pool_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_device_registry.hpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/common/pytorch_device_registry.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/cudabind.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/cudabind.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/deform_roi_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/ms_deform_attn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_align_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/roi_pool_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_conv.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_roi_pool.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/deform_roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/info.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/modulated_deform_conv.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/ms_deform_attn.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/ms_deform_attn.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/pybind.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_align.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_pool.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/roi_pool.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/sync_bn.cpp b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_conv.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_roi_pool.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deform_roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deprecated_wrappers.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/info.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/modulated_deform_conv.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/modulated_deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/multi_scale_deform_attn.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/multi_scale_deform_attn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_align.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_pool.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/roi_pool.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/ops/sync_bn.py b/cv/ocr/dbnet/pytorch/dbnet_cv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/_functions.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/collate.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_container.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_parallel.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed_deprecated.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/registry.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/scatter_gather.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/utils.py b/cv/ocr/dbnet/pytorch/dbnet_cv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_module.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_runner.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/builder.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/checkpoint.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/default_constructor.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/dist_utils.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/epoch_based_runner.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/fp16_utils.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/checkpoint.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/closure.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/ema.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/evaluation.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/hook.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/iter_timer.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/base.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/clearml.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/clearml.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/dvclive.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/mlflow.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/neptune.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/pavi.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/segmind.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/segmind.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/tensorboard.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/text.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/wandb.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/lr_updater.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/memory.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/momentum_updater.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/optimizer.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/profiler.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sampler_seed.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sync_buffer.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/iter_based_runner.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/log_buffer.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/builder.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/default_constructor.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/priority.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/runner/utils.py b/cv/ocr/dbnet/pytorch/dbnet_cv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/config.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/device_type.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/device_type.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/env.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/ext_loader.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/hub.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/hub.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/logging.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/misc.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_jit.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_wrapper.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/path.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/progressbar.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/registry.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/seed.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/seed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/testing.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/timer.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/trace.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/utils/version_utils.py b/cv/ocr/dbnet/pytorch/dbnet_cv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_cv/version.py b/cv/ocr/dbnet/pytorch/dbnet_cv/version.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/apis/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/apis/test.py b/cv/ocr/dbnet/pytorch/dbnet_det/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/transforms.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/bbox_overlaps.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/bbox_overlaps.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/class_names.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/class_names.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/eval_hooks.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/mean_ap.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/mean_ap.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/panoptic_utils.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/panoptic_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/recall.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/evaluation/recall.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/structures.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/structures.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/utils.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/mask/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/dist_utils.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/misc.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/image.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/image.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/palette.py b/cv/ocr/dbnet/pytorch/dbnet_det/core/visualization/palette.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/coco_api.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/coco_api.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/panoptic_evaluation.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/api_wrappers/panoptic_evaluation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/builder.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/coco.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/coco.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/custom.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/custom.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/dataset_wrappers.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/compose.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/formatting.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/formatting.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/loading.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/test_time_aug.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/transforms.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/class_aware_sampler.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/class_aware_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/distributed_sampler.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/group_sampler.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/infinite_sampler.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/samplers/infinite_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/datasets/utils.py b/cv/ocr/dbnet/pytorch/dbnet_det/datasets/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/mobilenet_v3.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/mobilenet_v3.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/resnet.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/backbones/resnet.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/builder.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/base.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/single_stage.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/inverted_residual.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/inverted_residual.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/make_divisible.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/make_divisible.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/res_layer.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/res_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/se_layer.py b/cv/ocr/dbnet/pytorch/dbnet_det/models/utils/se_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/utils/__init__.py b/cv/ocr/dbnet/pytorch/dbnet_det/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/utils/inverted_residual.py b/cv/ocr/dbnet/pytorch/dbnet_det/utils/inverted_residual.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/utils/logger.py b/cv/ocr/dbnet/pytorch/dbnet_det/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/utils/profiling.py b/cv/ocr/dbnet/pytorch/dbnet_det/utils/profiling.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/utils/util_distribution.py b/cv/ocr/dbnet/pytorch/dbnet_det/utils/util_distribution.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dbnet_det/version.py b/cv/ocr/dbnet/pytorch/dbnet_det/version.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/dist_train.sh b/cv/ocr/dbnet/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/requirements.txt b/cv/ocr/dbnet/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/setup.py b/cv/ocr/dbnet/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/tools/analyze_logs.py b/cv/ocr/dbnet/pytorch/tools/analyze_logs.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/tools/benchmark_processing.py b/cv/ocr/dbnet/pytorch/tools/benchmark_processing.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/tools/misc/print_config.py b/cv/ocr/dbnet/pytorch/tools/misc/print_config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/tools/publish_model.py b/cv/ocr/dbnet/pytorch/tools/publish_model.py old mode 100755 new mode 100644 diff --git a/cv/ocr/dbnet/pytorch/train.py b/cv/ocr/dbnet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/README.md b/cv/ocr/sar/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/apis/__init__.py b/cv/ocr/sar/pytorch/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/apis/train.py b/cv/ocr/sar/pytorch/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/apis/utils.py b/cv/ocr/sar/pytorch/apis/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/__init__.py b/cv/ocr/sar/pytorch/basic_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/box_util.py b/cv/ocr/sar/pytorch/basic_utils/box_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/check_argument.py b/cv/ocr/sar/pytorch/basic_utils/check_argument.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/data_convert_util.py b/cv/ocr/sar/pytorch/basic_utils/data_convert_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/env.py b/cv/ocr/sar/pytorch/basic_utils/env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/fileio.py b/cv/ocr/sar/pytorch/basic_utils/fileio.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/img_util.py b/cv/ocr/sar/pytorch/basic_utils/img_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/lmdb_util.py b/cv/ocr/sar/pytorch/basic_utils/lmdb_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/logger.py b/cv/ocr/sar/pytorch/basic_utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/model.py b/cv/ocr/sar/pytorch/basic_utils/model.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/setup_env.py b/cv/ocr/sar/pytorch/basic_utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/basic_utils/string_util.py b/cv/ocr/sar/pytorch/basic_utils/string_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/MJ_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/MJ_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_alphanumeric_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_alphanumeric_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_MJ_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_SA_MJ_real_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_SA_MJ_real_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_charbox_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/ST_charbox_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_test.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_train.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/Sample_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/academic_test.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/academic_test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/seg_toy_data.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/seg_toy_data.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/datasets/toy_data.py b/cv/ocr/sar/pytorch/configs/_base_/datasets/toy_data.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/default_runtime.py b/cv/ocr/sar/pytorch/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/models/sar.py b/cv/ocr/sar/pytorch/configs/_base_/models/sar.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/pipelines/sar_pipeline.py b/cv/ocr/sar/pytorch/configs/_base_/pipelines/sar_pipeline.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/runtime_10e.py b/cv/ocr/sar/pytorch/configs/_base_/runtime_10e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_18e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_18e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_5e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adadelta_5e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_600e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_20e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_20e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_5e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_5e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_600e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_6e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_adam_step_6e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1200e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1500e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_1500e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_160e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_160e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_600e.py b/cv/ocr/sar/pytorch/configs/_base_/schedules/schedule_sgd_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/metafile.yml b/cv/ocr/sar/pytorch/configs/metafile.yml old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/sar_r31_parallel_decoder_academic.py b/cv/ocr/sar/pytorch/configs/sar_r31_parallel_decoder_academic.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/configs/sar_r31_sequential_decoder_academic.py b/cv/ocr/sar/pytorch/configs/sar_r31_sequential_decoder_academic.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/__init__.py b/cv/ocr/sar/pytorch/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/evaluation/__init__.py b/cv/ocr/sar/pytorch/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/evaluation/ocr_metric.py b/cv/ocr/sar/pytorch/core/evaluation/ocr_metric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/evaluation/utils.py b/cv/ocr/sar/pytorch/core/evaluation/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/mask.py b/cv/ocr/sar/pytorch/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/core/visualize.py b/cv/ocr/sar/pytorch/core/visualize.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/.gitignore b/cv/ocr/sar/pytorch/csrc/.gitignore old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/build.sh b/cv/ocr/sar/pytorch/csrc/build.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/clean.sh b/cv/ocr/sar/pytorch/csrc/clean.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/install.sh b/cv/ocr/sar/pytorch/csrc/install.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/activation.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv2d_adaptive_padding.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv_module.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/drop.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hsigmoid.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hswish.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/norm.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/padding.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/registry.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/scale.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/swish.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/transformer.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/wrappers.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/builder.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/fuse_conv_bn.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/sync_bn.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/weight_init.py b/cv/ocr/sar/pytorch/csrc/sar/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/assign_score_withk.py b/cv/ocr/sar/pytorch/csrc/sar/ops/assign_score_withk.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/bbox.py b/cv/ocr/sar/pytorch/csrc/sar/ops/bbox.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/README.md b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/assign_score_withk.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/assign_score_withk.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/bbox_overlaps.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/bbox_overlaps.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/roi_align_cuda.cu b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/roi_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/info.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/pybind.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align_cpu.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/roi_align_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/sync_bn.cpp b/cv/ocr/sar/pytorch/csrc/sar/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/info.py b/cv/ocr/sar/pytorch/csrc/sar/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/roi_align.py b/cv/ocr/sar/pytorch/csrc/sar/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/ops/sync_bn.py b/cv/ocr/sar/pytorch/csrc/sar/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/runner/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/runner/base_module.py b/cv/ocr/sar/pytorch/csrc/sar/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/runner/dist_utils.py b/cv/ocr/sar/pytorch/csrc/sar/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/__init__.py b/cv/ocr/sar/pytorch/csrc/sar/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/config.py b/cv/ocr/sar/pytorch/csrc/sar/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/ext_loader.py b/cv/ocr/sar/pytorch/csrc/sar/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/logging.py b/cv/ocr/sar/pytorch/csrc/sar/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/misc.py b/cv/ocr/sar/pytorch/csrc/sar/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/parrots_wrapper.py b/cv/ocr/sar/pytorch/csrc/sar/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/path.py b/cv/ocr/sar/pytorch/csrc/sar/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/registry.py b/cv/ocr/sar/pytorch/csrc/sar/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/sar/utils/version_utils.py b/cv/ocr/sar/pytorch/csrc/sar/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/csrc/setup.py b/cv/ocr/sar/pytorch/csrc/setup.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/__init__.py b/cv/ocr/sar/pytorch/datasets_/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/base_dataset.py b/cv/ocr/sar/pytorch/datasets_/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/builder.py b/cv/ocr/sar/pytorch/datasets_/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/ocr_dataset.py b/cv/ocr/sar/pytorch/datasets_/ocr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/__init__.py b/cv/ocr/sar/pytorch/datasets_/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/box_utils.py b/cv/ocr/sar/pytorch/datasets_/pipelines/box_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/crop.py b/cv/ocr/sar/pytorch/datasets_/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/custom_format_bundle.py b/cv/ocr/sar/pytorch/datasets_/pipelines/custom_format_bundle.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/loading.py b/cv/ocr/sar/pytorch/datasets_/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/ocr_transforms.py b/cv/ocr/sar/pytorch/datasets_/pipelines/ocr_transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/test_time_aug.py b/cv/ocr/sar/pytorch/datasets_/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/transform_wrappers.py b/cv/ocr/sar/pytorch/datasets_/pipelines/transform_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/pipelines/transforms.py b/cv/ocr/sar/pytorch/datasets_/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/uniform_concat_dataset.py b/cv/ocr/sar/pytorch/datasets_/uniform_concat_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/utils/__init__.py b/cv/ocr/sar/pytorch/datasets_/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/utils/loader.py b/cv/ocr/sar/pytorch/datasets_/utils/loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/datasets_/utils/parser.py b/cv/ocr/sar/pytorch/datasets_/utils/parser.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/dist_train.sh b/cv/ocr/sar/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/__init__.py b/cv/ocr/sar/pytorch/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/backbones/__init__.py b/cv/ocr/sar/pytorch/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/backbones/resnet31_ocr.py b/cv/ocr/sar/pytorch/models/backbones/resnet31_ocr.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/builder.py b/cv/ocr/sar/pytorch/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/convertors/__init__.py b/cv/ocr/sar/pytorch/models/convertors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/convertors/attn.py b/cv/ocr/sar/pytorch/models/convertors/attn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/convertors/base.py b/cv/ocr/sar/pytorch/models/convertors/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/decoders/__init__.py b/cv/ocr/sar/pytorch/models/decoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/decoders/base_decoder.py b/cv/ocr/sar/pytorch/models/decoders/base_decoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/decoders/sar_decoder.py b/cv/ocr/sar/pytorch/models/decoders/sar_decoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/decoders/sar_decoder_with_bs.py b/cv/ocr/sar/pytorch/models/decoders/sar_decoder_with_bs.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/encoders/__init__.py b/cv/ocr/sar/pytorch/models/encoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/encoders/base_encoder.py b/cv/ocr/sar/pytorch/models/encoders/base_encoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/encoders/sar_encoder.py b/cv/ocr/sar/pytorch/models/encoders/sar_encoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/layers/__init__.py b/cv/ocr/sar/pytorch/models/layers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/layers/conv_layer.py b/cv/ocr/sar/pytorch/models/layers/conv_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/layers/resnet.py b/cv/ocr/sar/pytorch/models/layers/resnet.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/losses/__init__.py b/cv/ocr/sar/pytorch/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/losses/ce_loss.py b/cv/ocr/sar/pytorch/models/losses/ce_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/recognizer/__init__.py b/cv/ocr/sar/pytorch/models/recognizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/recognizer/base.py b/cv/ocr/sar/pytorch/models/recognizer/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/recognizer/encode_decode_recognizer.py b/cv/ocr/sar/pytorch/models/recognizer/encode_decode_recognizer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/models/recognizer/sar.py b/cv/ocr/sar/pytorch/models/recognizer/sar.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/__init__.py b/cv/ocr/sar/pytorch/ocrcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/engine/__init__.py b/cv/ocr/sar/pytorch/ocrcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/engine/test.py b/cv/ocr/sar/pytorch/ocrcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/__init__.py b/cv/ocr/sar/pytorch/ocrcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/file_client.py b/cv/ocr/sar/pytorch/ocrcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/__init__.py b/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/base.py b/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/json_handler.py b/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/pickle_handler.py b/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/yaml_handler.py b/cv/ocr/sar/pytorch/ocrcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/io.py b/cv/ocr/sar/pytorch/ocrcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/fileio/parse.py b/cv/ocr/sar/pytorch/ocrcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/__init__.py b/cv/ocr/sar/pytorch/ocrcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/colorspace.py b/cv/ocr/sar/pytorch/ocrcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/geometric.py b/cv/ocr/sar/pytorch/ocrcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/io.py b/cv/ocr/sar/pytorch/ocrcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/misc.py b/cv/ocr/sar/pytorch/ocrcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/image/photometric.py b/cv/ocr/sar/pytorch/ocrcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/__init__.py b/cv/ocr/sar/pytorch/ocrcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/_functions.py b/cv/ocr/sar/pytorch/ocrcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/collate.py b/cv/ocr/sar/pytorch/ocrcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/data_container.py b/cv/ocr/sar/pytorch/ocrcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/data_parallel.py b/cv/ocr/sar/pytorch/ocrcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/distributed.py b/cv/ocr/sar/pytorch/ocrcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/distributed_deprecated.py b/cv/ocr/sar/pytorch/ocrcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/registry.py b/cv/ocr/sar/pytorch/ocrcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/scatter_gather.py b/cv/ocr/sar/pytorch/ocrcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/parallel/utils.py b/cv/ocr/sar/pytorch/ocrcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/__init__.py b/cv/ocr/sar/pytorch/ocrcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/base_module.py b/cv/ocr/sar/pytorch/ocrcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/base_runner.py b/cv/ocr/sar/pytorch/ocrcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/builder.py b/cv/ocr/sar/pytorch/ocrcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/checkpoint.py b/cv/ocr/sar/pytorch/ocrcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/dist_utils.py b/cv/ocr/sar/pytorch/ocrcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/epoch_based_runner.py b/cv/ocr/sar/pytorch/ocrcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/fp16_utils.py b/cv/ocr/sar/pytorch/ocrcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/__init__.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/checkpoint.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/closure.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/ema.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/evaluation.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/hook.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/iter_timer.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/__init__.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/base.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/dvclive.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/mlflow.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/neptune.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/pavi.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/tensorboard.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/text.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/wandb.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/lr_updater.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/memory.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/momentum_updater.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/optimizer.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/profiler.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/sampler_seed.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/hooks/sync_buffer.py b/cv/ocr/sar/pytorch/ocrcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/iter_based_runner.py b/cv/ocr/sar/pytorch/ocrcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/log_buffer.py b/cv/ocr/sar/pytorch/ocrcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/__init__.py b/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/builder.py b/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/default_constructor.py b/cv/ocr/sar/pytorch/ocrcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/priority.py b/cv/ocr/sar/pytorch/ocrcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/utils.py b/cv/ocr/sar/pytorch/ocrcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/runner/weight_init.py b/cv/ocr/sar/pytorch/ocrcv/runner/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/__init__.py b/cv/ocr/sar/pytorch/ocrcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/config.py b/cv/ocr/sar/pytorch/ocrcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/ext_loader.py b/cv/ocr/sar/pytorch/ocrcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/logging.py b/cv/ocr/sar/pytorch/ocrcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/misc.py b/cv/ocr/sar/pytorch/ocrcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/parrots_jit.py b/cv/ocr/sar/pytorch/ocrcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/parrots_wrapper.py b/cv/ocr/sar/pytorch/ocrcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/path.py b/cv/ocr/sar/pytorch/ocrcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/progressbar.py b/cv/ocr/sar/pytorch/ocrcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/registry.py b/cv/ocr/sar/pytorch/ocrcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/testing.py b/cv/ocr/sar/pytorch/ocrcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/timer.py b/cv/ocr/sar/pytorch/ocrcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrcv/utils/version_utils.py b/cv/ocr/sar/pytorch/ocrcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/__init__.py b/cv/ocr/sar/pytorch/ocrdet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/assign_result.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/assigners/assign_result.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/builder.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/demodata.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/demodata.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/base_sampler.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/base_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/random_sampler.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/random_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/sampling_result.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/samplers/sampling_result.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/bbox/transforms.py b/cv/ocr/sar/pytorch/ocrdet/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/evaluation/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/evaluation/bbox_overlaps.py b/cv/ocr/sar/pytorch/ocrdet/core/evaluation/bbox_overlaps.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/evaluation/eval_hooks.py b/cv/ocr/sar/pytorch/ocrdet/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/mask/__init__.py b/cv/ocr/sar/pytorch/ocrdet/core/mask/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/core/mask/structures.py b/cv/ocr/sar/pytorch/ocrdet/core/mask/structures.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/__init__.py b/cv/ocr/sar/pytorch/ocrdet/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/__init__.py b/cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/coco_api.py b/cv/ocr/sar/pytorch/ocrdet/datasets/api_wrappers/coco_api.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/builder.py b/cv/ocr/sar/pytorch/ocrdet/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/dataset_wrappers.py b/cv/ocr/sar/pytorch/ocrdet/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/__init__.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/auto_augment.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/auto_augment.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/compose.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/formating.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/instaboost.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/instaboost.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/loading.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/test_time_aug.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/transforms.py b/cv/ocr/sar/pytorch/ocrdet/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/__init__.py b/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/distributed_sampler.py b/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/group_sampler.py b/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/infinite_sampler.py b/cv/ocr/sar/pytorch/ocrdet/datasets/samplers/infinite_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/datasets/utils.py b/cv/ocr/sar/pytorch/ocrdet/datasets/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/__init__.py b/cv/ocr/sar/pytorch/ocrdet/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/builder.py b/cv/ocr/sar/pytorch/ocrdet/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/detectors/__init__.py b/cv/ocr/sar/pytorch/ocrdet/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/detectors/base.py b/cv/ocr/sar/pytorch/ocrdet/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/detectors/single_stage.py b/cv/ocr/sar/pytorch/ocrdet/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/utils/__init__.py b/cv/ocr/sar/pytorch/ocrdet/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/models/utils/transformer.py b/cv/ocr/sar/pytorch/ocrdet/models/utils/transformer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/utils/__init__.py b/cv/ocr/sar/pytorch/ocrdet/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/utils/util_mixins.py b/cv/ocr/sar/pytorch/ocrdet/utils/util_mixins.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/ocrdet/utils/util_random.py b/cv/ocr/sar/pytorch/ocrdet/utils/util_random.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/openvino_converter.py b/cv/ocr/sar/pytorch/openvino_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/requirements.txt b/cv/ocr/sar/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/seg_synthtext_converter.py b/cv/ocr/sar/pytorch/seg_synthtext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/svt_converter.py b/cv/ocr/sar/pytorch/svt_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/synthtext_converter.py b/cv/ocr/sar/pytorch/synthtext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/textocr_converter.py b/cv/ocr/sar/pytorch/textocr_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/totaltext_converter.py b/cv/ocr/sar/pytorch/totaltext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/train.py b/cv/ocr/sar/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/sar/pytorch/txt2lmdb.py b/cv/ocr/sar/pytorch/txt2lmdb.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/.gitignore b/cv/ocr/satrn/pytorch/base/.gitignore old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/README.md b/cv/ocr/satrn/pytorch/base/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/apis/__init__.py b/cv/ocr/satrn/pytorch/base/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/apis/train.py b/cv/ocr/satrn/pytorch/base/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/apis/utils.py b/cv/ocr/satrn/pytorch/base/apis/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/__init__.py b/cv/ocr/satrn/pytorch/base/basic_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/box_util.py b/cv/ocr/satrn/pytorch/base/basic_utils/box_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/check_argument.py b/cv/ocr/satrn/pytorch/base/basic_utils/check_argument.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/data_convert_util.py b/cv/ocr/satrn/pytorch/base/basic_utils/data_convert_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/env.py b/cv/ocr/satrn/pytorch/base/basic_utils/env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/fileio.py b/cv/ocr/satrn/pytorch/base/basic_utils/fileio.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/img_util.py b/cv/ocr/satrn/pytorch/base/basic_utils/img_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/lmdb_util.py b/cv/ocr/satrn/pytorch/base/basic_utils/lmdb_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/logger.py b/cv/ocr/satrn/pytorch/base/basic_utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/model.py b/cv/ocr/satrn/pytorch/base/basic_utils/model.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/setup_env.py b/cv/ocr/satrn/pytorch/base/basic_utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/basic_utils/string_util.py b/cv/ocr/satrn/pytorch/base/basic_utils/string_util.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/default_runtime.py b/cv/ocr/satrn/pytorch/base/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/runtime_10e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/runtime_10e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_18e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_18e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_5e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adadelta_5e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_600e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_20e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_20e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_5e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_5e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_600e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_6e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_adam_step_6e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1200e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1200e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1500e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_1500e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_160e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_160e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_600e.py b/cv/ocr/satrn/pytorch/base/configs/_base_/schedules/schedule_sgd_600e.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_alphanumeric_train.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_alphanumeric_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_train.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_MJ_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_SA_MJ_real_train.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/ST_SA_MJ_real_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_test.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_train.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/Sample_train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/datasets_/academic_test.py b/cv/ocr/satrn/pytorch/base/configs/datasets_/academic_test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/models/satrn.py b/cv/ocr/satrn/pytorch/base/configs/models/satrn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/models/satrn_academic.py b/cv/ocr/satrn/pytorch/base/configs/models/satrn_academic.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/models/satrn_academic_sample.py b/cv/ocr/satrn/pytorch/base/configs/models/satrn_academic_sample.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/models/satrn_small.py b/cv/ocr/satrn/pytorch/base/configs/models/satrn_small.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/models/satrn_small_sample.py b/cv/ocr/satrn/pytorch/base/configs/models/satrn_small_sample.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/configs/pipelines/satrn_pipeline.py b/cv/ocr/satrn/pytorch/base/configs/pipelines/satrn_pipeline.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/__init__.py b/cv/ocr/satrn/pytorch/base/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/evaluation/__init__.py b/cv/ocr/satrn/pytorch/base/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/evaluation/ocr_metric.py b/cv/ocr/satrn/pytorch/base/core/evaluation/ocr_metric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/evaluation/utils.py b/cv/ocr/satrn/pytorch/base/core/evaluation/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/mask.py b/cv/ocr/satrn/pytorch/base/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/core/visualize.py b/cv/ocr/satrn/pytorch/base/core/visualize.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/.gitignore b/cv/ocr/satrn/pytorch/base/csrc/.gitignore old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/build.sh b/cv/ocr/satrn/pytorch/base/csrc/build.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/clean.sh b/cv/ocr/satrn/pytorch/base/csrc/clean.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/install.sh b/cv/ocr/satrn/pytorch/base/csrc/install.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/activation.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv2d_adaptive_padding.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv_module.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/drop.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hsigmoid.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hswish.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/norm.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/padding.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/registry.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/scale.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/swish.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/transformer.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/wrappers.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/builder.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/fuse_conv_bn.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/sync_bn.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/weight_init.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/assign_score_withk.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/assign_score_withk.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/bbox.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/bbox.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/README.md b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/assign_score_withk_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/bbox_overlaps_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/roi_align_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/assign_score_withk.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/assign_score_withk.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/bbox_overlaps.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/bbox_overlaps.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/assign_score_withk_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/bbox_overlaps_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/roi_align_cuda.cu b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/roi_align_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/info.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/pybind.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align_cpu.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/roi_align_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/sync_bn.cpp b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/info.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/roi_align.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/roi_align.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/sync_bn.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/base_module.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/dist_utils.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/__init__.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/config.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/ext_loader.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/logging.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/misc.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/parrots_wrapper.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/path.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/registry.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/version_utils.py b/cv/ocr/satrn/pytorch/base/csrc/satrn/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/csrc/setup.py b/cv/ocr/satrn/pytorch/base/csrc/setup.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/__init__.py b/cv/ocr/satrn/pytorch/base/datasets_/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/base_dataset.py b/cv/ocr/satrn/pytorch/base/datasets_/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/builder.py b/cv/ocr/satrn/pytorch/base/datasets_/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/ocr_dataset.py b/cv/ocr/satrn/pytorch/base/datasets_/ocr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/__init__.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/box_utils.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/box_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/crop.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/custom_format_bundle.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/custom_format_bundle.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/loading.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/ocr_transforms.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/ocr_transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/test_time_aug.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/transform_wrappers.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/transform_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/pipelines/transforms.py b/cv/ocr/satrn/pytorch/base/datasets_/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/uniform_concat_dataset.py b/cv/ocr/satrn/pytorch/base/datasets_/uniform_concat_dataset.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/utils/__init__.py b/cv/ocr/satrn/pytorch/base/datasets_/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/utils/loader.py b/cv/ocr/satrn/pytorch/base/datasets_/utils/loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/datasets_/utils/parser.py b/cv/ocr/satrn/pytorch/base/datasets_/utils/parser.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/dist_train.sh b/cv/ocr/satrn/pytorch/base/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/__init__.py b/cv/ocr/satrn/pytorch/base/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/backbones/__init__.py b/cv/ocr/satrn/pytorch/base/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/backbones/shallow_cnn.py b/cv/ocr/satrn/pytorch/base/models/backbones/shallow_cnn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/builder.py b/cv/ocr/satrn/pytorch/base/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/__init__.py b/cv/ocr/satrn/pytorch/base/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/detectors/__init__.py b/cv/ocr/satrn/pytorch/base/models/common/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/detectors/single_stage.py b/cv/ocr/satrn/pytorch/base/models/common/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/layers/__init__.py b/cv/ocr/satrn/pytorch/base/models/common/layers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/layers/transformer_layers.py b/cv/ocr/satrn/pytorch/base/models/common/layers/transformer_layers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/losses/__init__.py b/cv/ocr/satrn/pytorch/base/models/common/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/losses/dice_loss.py b/cv/ocr/satrn/pytorch/base/models/common/losses/dice_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/losses/focal_loss.py b/cv/ocr/satrn/pytorch/base/models/common/losses/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/modules/__init__.py b/cv/ocr/satrn/pytorch/base/models/common/modules/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/common/modules/transformer_module.py b/cv/ocr/satrn/pytorch/base/models/common/modules/transformer_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/convertors/__init__.py b/cv/ocr/satrn/pytorch/base/models/convertors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/convertors/attn.py b/cv/ocr/satrn/pytorch/base/models/convertors/attn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/convertors/base.py b/cv/ocr/satrn/pytorch/base/models/convertors/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/decoders/__init__.py b/cv/ocr/satrn/pytorch/base/models/decoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/decoders/base_decoder.py b/cv/ocr/satrn/pytorch/base/models/decoders/base_decoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/decoders/nrtr_decoder.py b/cv/ocr/satrn/pytorch/base/models/decoders/nrtr_decoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/decoders/transformer_decoder.py b/cv/ocr/satrn/pytorch/base/models/decoders/transformer_decoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/encoders/__init__.py b/cv/ocr/satrn/pytorch/base/models/encoders/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/encoders/base_encoder.py b/cv/ocr/satrn/pytorch/base/models/encoders/base_encoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/encoders/satrn_encoder.py b/cv/ocr/satrn/pytorch/base/models/encoders/satrn_encoder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/__init__.py b/cv/ocr/satrn/pytorch/base/models/layers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/conv_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/conv_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/dot_product_attention_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/dot_product_attention_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/lstm_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/lstm_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/position_aware_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/position_aware_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/robust_scanner_fusion_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/robust_scanner_fusion_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/layers/transformer_layer.py b/cv/ocr/satrn/pytorch/base/models/layers/transformer_layer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/losses/__init__.py b/cv/ocr/satrn/pytorch/base/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/losses/ce_loss.py b/cv/ocr/satrn/pytorch/base/models/losses/ce_loss.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/recognizer/__init__.py b/cv/ocr/satrn/pytorch/base/models/recognizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/recognizer/base.py b/cv/ocr/satrn/pytorch/base/models/recognizer/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/recognizer/encode_decode_recognizer.py b/cv/ocr/satrn/pytorch/base/models/recognizer/encode_decode_recognizer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/models/recognizer/satrn.py b/cv/ocr/satrn/pytorch/base/models/recognizer/satrn.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/engine/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/engine/test.py b/cv/ocr/satrn/pytorch/base/ocrcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/file_client.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/base.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/json_handler.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/pickle_handler.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/yaml_handler.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/io.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/fileio/parse.py b/cv/ocr/satrn/pytorch/base/ocrcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/colorspace.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/geometric.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/io.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/misc.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/image/photometric.py b/cv/ocr/satrn/pytorch/base/ocrcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/_functions.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/collate.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_container.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_parallel.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed_deprecated.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/registry.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/scatter_gather.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/parallel/utils.py b/cv/ocr/satrn/pytorch/base/ocrcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/base_module.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/base_runner.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/builder.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/checkpoint.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/dist_utils.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/epoch_based_runner.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/fp16_utils.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/checkpoint.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/closure.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/ema.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/evaluation.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/hook.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/iter_timer.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/base.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/dvclive.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/mlflow.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/neptune.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/pavi.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/tensorboard.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/text.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/wandb.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/lr_updater.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/memory.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/momentum_updater.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/optimizer.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/profiler.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sampler_seed.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sync_buffer.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/iter_based_runner.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/log_buffer.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/builder.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/default_constructor.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/priority.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/utils.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/runner/weight_init.py b/cv/ocr/satrn/pytorch/base/ocrcv/runner/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/__init__.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/config.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/ext_loader.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/logging.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/misc.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_jit.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_wrapper.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/path.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/progressbar.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/registry.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/testing.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/timer.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrcv/utils/version_utils.py b/cv/ocr/satrn/pytorch/base/ocrcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/apis/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/apis/test.py b/cv/ocr/satrn/pytorch/base/ocrdet/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/assign_result.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/assigners/assign_result.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/builder.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/demodata.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/demodata.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/iou_calculators/iou2d_calculator.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/base_sampler.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/base_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/random_sampler.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/random_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/sampling_result.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/samplers/sampling_result.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/transforms.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/bbox/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/bbox_overlaps.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/bbox_overlaps.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/eval_hooks.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/structures.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/structures.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/utils.py b/cv/ocr/satrn/pytorch/base/ocrdet/core/mask/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/coco_api.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/api_wrappers/coco_api.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/builder.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/dataset_wrappers.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/auto_augment.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/auto_augment.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/compose.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/formating.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/instaboost.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/instaboost.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/loading.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/test_time_aug.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/transforms.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/distributed_sampler.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/group_sampler.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/group_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/infinite_sampler.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/samplers/infinite_sampler.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/utils.py b/cv/ocr/satrn/pytorch/base/ocrdet/datasets_/utils.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/builder.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/base.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/base.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/single_stage.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/detectors/single_stage.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/utils/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/models/utils/transformer.py b/cv/ocr/satrn/pytorch/base/ocrdet/models/utils/transformer.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/utils/__init__.py b/cv/ocr/satrn/pytorch/base/ocrdet/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/utils/util_mixins.py b/cv/ocr/satrn/pytorch/base/ocrdet/utils/util_mixins.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/ocrdet/utils/util_random.py b/cv/ocr/satrn/pytorch/base/ocrdet/utils/util_random.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/openvino_converter.py b/cv/ocr/satrn/pytorch/base/openvino_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/requirements.txt b/cv/ocr/satrn/pytorch/base/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/seg_synthtext_converter.py b/cv/ocr/satrn/pytorch/base/seg_synthtext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/svt_converter.py b/cv/ocr/satrn/pytorch/base/svt_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/synthtext_converter.py b/cv/ocr/satrn/pytorch/base/synthtext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/textocr_converter.py b/cv/ocr/satrn/pytorch/base/textocr_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/totaltext_converter.py b/cv/ocr/satrn/pytorch/base/totaltext_converter.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/train.py b/cv/ocr/satrn/pytorch/base/train.py old mode 100755 new mode 100644 diff --git a/cv/ocr/satrn/pytorch/base/txt2lmdb.py b/cv/ocr/satrn/pytorch/base/txt2lmdb.py old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/datasets/io.py b/cv/point_cloud/Point-BERT/pytorch/datasets/io.py old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/extensions/emd/__init__.py b/cv/point_cloud/Point-BERT/pytorch/extensions/emd/__init__.py old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/extensions/emd/cuda/emd.cpp b/cv/point_cloud/Point-BERT/pytorch/extensions/emd/cuda/emd.cpp old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/extensions/emd/emd.py b/cv/point_cloud/Point-BERT/pytorch/extensions/emd/emd.py old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/extensions/emd/setup.py b/cv/point_cloud/Point-BERT/pytorch/extensions/emd/setup.py old mode 100755 new mode 100644 diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data b/cv/point_cloud/Point-BERT/pytorch/segmentation/data deleted file mode 120000 index 4909e06e..00000000 --- a/cv/point_cloud/Point-BERT/pytorch/segmentation/data +++ /dev/null @@ -1 +0,0 @@ -../data \ No newline at end of file diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_shape_names.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_shape_names.txt new file mode 100644 index 00000000..1b2a3971 --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_shape_names.txt @@ -0,0 +1,40 @@ +airplane +bathtub +bed +bench +bookshelf +bottle +bowl +car +chair +cone +cup +curtain +desk +door +dresser +flower_pot +glass_box +guitar +keyboard +lamp +laptop +mantel +monitor +night_stand +person +piano +plant +radio +range_hood +sink +sofa +stairs +stool +table +tent +toilet +tv_stand +vase +wardrobe +xbox diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_test.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_test.txt new file mode 100644 index 00000000..b0bc4837 --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_test.txt @@ -0,0 +1,2468 @@ +airplane_0627 +airplane_0628 +airplane_0629 +airplane_0630 +airplane_0631 +airplane_0632 +airplane_0633 +airplane_0634 +airplane_0635 +airplane_0636 +airplane_0637 +airplane_0638 +airplane_0639 +airplane_0640 +airplane_0641 +airplane_0642 +airplane_0643 +airplane_0644 +airplane_0645 +airplane_0646 +airplane_0647 +airplane_0648 +airplane_0649 +airplane_0650 +airplane_0651 +airplane_0652 +airplane_0653 +airplane_0654 +airplane_0655 +airplane_0656 +airplane_0657 +airplane_0658 +airplane_0659 +airplane_0660 +airplane_0661 +airplane_0662 +airplane_0663 +airplane_0664 +airplane_0665 +airplane_0666 +airplane_0667 +airplane_0668 +airplane_0669 +airplane_0670 +airplane_0671 +airplane_0672 +airplane_0673 +airplane_0674 +airplane_0675 +airplane_0676 +airplane_0677 +airplane_0678 +airplane_0679 +airplane_0680 +airplane_0681 +airplane_0682 +airplane_0683 +airplane_0684 +airplane_0685 +airplane_0686 +airplane_0687 +airplane_0688 +airplane_0689 +airplane_0690 +airplane_0691 +airplane_0692 +airplane_0693 +airplane_0694 +airplane_0695 +airplane_0696 +airplane_0697 +airplane_0698 +airplane_0699 +airplane_0700 +airplane_0701 +airplane_0702 +airplane_0703 +airplane_0704 +airplane_0705 +airplane_0706 +airplane_0707 +airplane_0708 +airplane_0709 +airplane_0710 +airplane_0711 +airplane_0712 +airplane_0713 +airplane_0714 +airplane_0715 +airplane_0716 +airplane_0717 +airplane_0718 +airplane_0719 +airplane_0720 +airplane_0721 +airplane_0722 +airplane_0723 +airplane_0724 +airplane_0725 +airplane_0726 +bathtub_0107 +bathtub_0108 +bathtub_0109 +bathtub_0110 +bathtub_0111 +bathtub_0112 +bathtub_0113 +bathtub_0114 +bathtub_0115 +bathtub_0116 +bathtub_0117 +bathtub_0118 +bathtub_0119 +bathtub_0120 +bathtub_0121 +bathtub_0122 +bathtub_0123 +bathtub_0124 +bathtub_0125 +bathtub_0126 +bathtub_0127 +bathtub_0128 +bathtub_0129 +bathtub_0130 +bathtub_0131 +bathtub_0132 +bathtub_0133 +bathtub_0134 +bathtub_0135 +bathtub_0136 +bathtub_0137 +bathtub_0138 +bathtub_0139 +bathtub_0140 +bathtub_0141 +bathtub_0142 +bathtub_0143 +bathtub_0144 +bathtub_0145 +bathtub_0146 +bathtub_0147 +bathtub_0148 +bathtub_0149 +bathtub_0150 +bathtub_0151 +bathtub_0152 +bathtub_0153 +bathtub_0154 +bathtub_0155 +bathtub_0156 +bed_0516 +bed_0517 +bed_0518 +bed_0519 +bed_0520 +bed_0521 +bed_0522 +bed_0523 +bed_0524 +bed_0525 +bed_0526 +bed_0527 +bed_0528 +bed_0529 +bed_0530 +bed_0531 +bed_0532 +bed_0533 +bed_0534 +bed_0535 +bed_0536 +bed_0537 +bed_0538 +bed_0539 +bed_0540 +bed_0541 +bed_0542 +bed_0543 +bed_0544 +bed_0545 +bed_0546 +bed_0547 +bed_0548 +bed_0549 +bed_0550 +bed_0551 +bed_0552 +bed_0553 +bed_0554 +bed_0555 +bed_0556 +bed_0557 +bed_0558 +bed_0559 +bed_0560 +bed_0561 +bed_0562 +bed_0563 +bed_0564 +bed_0565 +bed_0566 +bed_0567 +bed_0568 +bed_0569 +bed_0570 +bed_0571 +bed_0572 +bed_0573 +bed_0574 +bed_0575 +bed_0576 +bed_0577 +bed_0578 +bed_0579 +bed_0580 +bed_0581 +bed_0582 +bed_0583 +bed_0584 +bed_0585 +bed_0586 +bed_0587 +bed_0588 +bed_0589 +bed_0590 +bed_0591 +bed_0592 +bed_0593 +bed_0594 +bed_0595 +bed_0596 +bed_0597 +bed_0598 +bed_0599 +bed_0600 +bed_0601 +bed_0602 +bed_0603 +bed_0604 +bed_0605 +bed_0606 +bed_0607 +bed_0608 +bed_0609 +bed_0610 +bed_0611 +bed_0612 +bed_0613 +bed_0614 +bed_0615 +bench_0174 +bench_0175 +bench_0176 +bench_0177 +bench_0178 +bench_0179 +bench_0180 +bench_0181 +bench_0182 +bench_0183 +bench_0184 +bench_0185 +bench_0186 +bench_0187 +bench_0188 +bench_0189 +bench_0190 +bench_0191 +bench_0192 +bench_0193 +bookshelf_0573 +bookshelf_0574 +bookshelf_0575 +bookshelf_0576 +bookshelf_0577 +bookshelf_0578 +bookshelf_0579 +bookshelf_0580 +bookshelf_0581 +bookshelf_0582 +bookshelf_0583 +bookshelf_0584 +bookshelf_0585 +bookshelf_0586 +bookshelf_0587 +bookshelf_0588 +bookshelf_0589 +bookshelf_0590 +bookshelf_0591 +bookshelf_0592 +bookshelf_0593 +bookshelf_0594 +bookshelf_0595 +bookshelf_0596 +bookshelf_0597 +bookshelf_0598 +bookshelf_0599 +bookshelf_0600 +bookshelf_0601 +bookshelf_0602 +bookshelf_0603 +bookshelf_0604 +bookshelf_0605 +bookshelf_0606 +bookshelf_0607 +bookshelf_0608 +bookshelf_0609 +bookshelf_0610 +bookshelf_0611 +bookshelf_0612 +bookshelf_0613 +bookshelf_0614 +bookshelf_0615 +bookshelf_0616 +bookshelf_0617 +bookshelf_0618 +bookshelf_0619 +bookshelf_0620 +bookshelf_0621 +bookshelf_0622 +bookshelf_0623 +bookshelf_0624 +bookshelf_0625 +bookshelf_0626 +bookshelf_0627 +bookshelf_0628 +bookshelf_0629 +bookshelf_0630 +bookshelf_0631 +bookshelf_0632 +bookshelf_0633 +bookshelf_0634 +bookshelf_0635 +bookshelf_0636 +bookshelf_0637 +bookshelf_0638 +bookshelf_0639 +bookshelf_0640 +bookshelf_0641 +bookshelf_0642 +bookshelf_0643 +bookshelf_0644 +bookshelf_0645 +bookshelf_0646 +bookshelf_0647 +bookshelf_0648 +bookshelf_0649 +bookshelf_0650 +bookshelf_0651 +bookshelf_0652 +bookshelf_0653 +bookshelf_0654 +bookshelf_0655 +bookshelf_0656 +bookshelf_0657 +bookshelf_0658 +bookshelf_0659 +bookshelf_0660 +bookshelf_0661 +bookshelf_0662 +bookshelf_0663 +bookshelf_0664 +bookshelf_0665 +bookshelf_0666 +bookshelf_0667 +bookshelf_0668 +bookshelf_0669 +bookshelf_0670 +bookshelf_0671 +bookshelf_0672 +bottle_0336 +bottle_0337 +bottle_0338 +bottle_0339 +bottle_0340 +bottle_0341 +bottle_0342 +bottle_0343 +bottle_0344 +bottle_0345 +bottle_0346 +bottle_0347 +bottle_0348 +bottle_0349 +bottle_0350 +bottle_0351 +bottle_0352 +bottle_0353 +bottle_0354 +bottle_0355 +bottle_0356 +bottle_0357 +bottle_0358 +bottle_0359 +bottle_0360 +bottle_0361 +bottle_0362 +bottle_0363 +bottle_0364 +bottle_0365 +bottle_0366 +bottle_0367 +bottle_0368 +bottle_0369 +bottle_0370 +bottle_0371 +bottle_0372 +bottle_0373 +bottle_0374 +bottle_0375 +bottle_0376 +bottle_0377 +bottle_0378 +bottle_0379 +bottle_0380 +bottle_0381 +bottle_0382 +bottle_0383 +bottle_0384 +bottle_0385 +bottle_0386 +bottle_0387 +bottle_0388 +bottle_0389 +bottle_0390 +bottle_0391 +bottle_0392 +bottle_0393 +bottle_0394 +bottle_0395 +bottle_0396 +bottle_0397 +bottle_0398 +bottle_0399 +bottle_0400 +bottle_0401 +bottle_0402 +bottle_0403 +bottle_0404 +bottle_0405 +bottle_0406 +bottle_0407 +bottle_0408 +bottle_0409 +bottle_0410 +bottle_0411 +bottle_0412 +bottle_0413 +bottle_0414 +bottle_0415 +bottle_0416 +bottle_0417 +bottle_0418 +bottle_0419 +bottle_0420 +bottle_0421 +bottle_0422 +bottle_0423 +bottle_0424 +bottle_0425 +bottle_0426 +bottle_0427 +bottle_0428 +bottle_0429 +bottle_0430 +bottle_0431 +bottle_0432 +bottle_0433 +bottle_0434 +bottle_0435 +bowl_0065 +bowl_0066 +bowl_0067 +bowl_0068 +bowl_0069 +bowl_0070 +bowl_0071 +bowl_0072 +bowl_0073 +bowl_0074 +bowl_0075 +bowl_0076 +bowl_0077 +bowl_0078 +bowl_0079 +bowl_0080 +bowl_0081 +bowl_0082 +bowl_0083 +bowl_0084 +car_0198 +car_0199 +car_0200 +car_0201 +car_0202 +car_0203 +car_0204 +car_0205 +car_0206 +car_0207 +car_0208 +car_0209 +car_0210 +car_0211 +car_0212 +car_0213 +car_0214 +car_0215 +car_0216 +car_0217 +car_0218 +car_0219 +car_0220 +car_0221 +car_0222 +car_0223 +car_0224 +car_0225 +car_0226 +car_0227 +car_0228 +car_0229 +car_0230 +car_0231 +car_0232 +car_0233 +car_0234 +car_0235 +car_0236 +car_0237 +car_0238 +car_0239 +car_0240 +car_0241 +car_0242 +car_0243 +car_0244 +car_0245 +car_0246 +car_0247 +car_0248 +car_0249 +car_0250 +car_0251 +car_0252 +car_0253 +car_0254 +car_0255 +car_0256 +car_0257 +car_0258 +car_0259 +car_0260 +car_0261 +car_0262 +car_0263 +car_0264 +car_0265 +car_0266 +car_0267 +car_0268 +car_0269 +car_0270 +car_0271 +car_0272 +car_0273 +car_0274 +car_0275 +car_0276 +car_0277 +car_0278 +car_0279 +car_0280 +car_0281 +car_0282 +car_0283 +car_0284 +car_0285 +car_0286 +car_0287 +car_0288 +car_0289 +car_0290 +car_0291 +car_0292 +car_0293 +car_0294 +car_0295 +car_0296 +car_0297 +chair_0890 +chair_0891 +chair_0892 +chair_0893 +chair_0894 +chair_0895 +chair_0896 +chair_0897 +chair_0898 +chair_0899 +chair_0900 +chair_0901 +chair_0902 +chair_0903 +chair_0904 +chair_0905 +chair_0906 +chair_0907 +chair_0908 +chair_0909 +chair_0910 +chair_0911 +chair_0912 +chair_0913 +chair_0914 +chair_0915 +chair_0916 +chair_0917 +chair_0918 +chair_0919 +chair_0920 +chair_0921 +chair_0922 +chair_0923 +chair_0924 +chair_0925 +chair_0926 +chair_0927 +chair_0928 +chair_0929 +chair_0930 +chair_0931 +chair_0932 +chair_0933 +chair_0934 +chair_0935 +chair_0936 +chair_0937 +chair_0938 +chair_0939 +chair_0940 +chair_0941 +chair_0942 +chair_0943 +chair_0944 +chair_0945 +chair_0946 +chair_0947 +chair_0948 +chair_0949 +chair_0950 +chair_0951 +chair_0952 +chair_0953 +chair_0954 +chair_0955 +chair_0956 +chair_0957 +chair_0958 +chair_0959 +chair_0960 +chair_0961 +chair_0962 +chair_0963 +chair_0964 +chair_0965 +chair_0966 +chair_0967 +chair_0968 +chair_0969 +chair_0970 +chair_0971 +chair_0972 +chair_0973 +chair_0974 +chair_0975 +chair_0976 +chair_0977 +chair_0978 +chair_0979 +chair_0980 +chair_0981 +chair_0982 +chair_0983 +chair_0984 +chair_0985 +chair_0986 +chair_0987 +chair_0988 +chair_0989 +cone_0168 +cone_0169 +cone_0170 +cone_0171 +cone_0172 +cone_0173 +cone_0174 +cone_0175 +cone_0176 +cone_0177 +cone_0178 +cone_0179 +cone_0180 +cone_0181 +cone_0182 +cone_0183 +cone_0184 +cone_0185 +cone_0186 +cone_0187 +cup_0080 +cup_0081 +cup_0082 +cup_0083 +cup_0084 +cup_0085 +cup_0086 +cup_0087 +cup_0088 +cup_0089 +cup_0090 +cup_0091 +cup_0092 +cup_0093 +cup_0094 +cup_0095 +cup_0096 +cup_0097 +cup_0098 +cup_0099 +curtain_0139 +curtain_0140 +curtain_0141 +curtain_0142 +curtain_0143 +curtain_0144 +curtain_0145 +curtain_0146 +curtain_0147 +curtain_0148 +curtain_0149 +curtain_0150 +curtain_0151 +curtain_0152 +curtain_0153 +curtain_0154 +curtain_0155 +curtain_0156 +curtain_0157 +curtain_0158 +desk_0201 +desk_0202 +desk_0203 +desk_0204 +desk_0205 +desk_0206 +desk_0207 +desk_0208 +desk_0209 +desk_0210 +desk_0211 +desk_0212 +desk_0213 +desk_0214 +desk_0215 +desk_0216 +desk_0217 +desk_0218 +desk_0219 +desk_0220 +desk_0221 +desk_0222 +desk_0223 +desk_0224 +desk_0225 +desk_0226 +desk_0227 +desk_0228 +desk_0229 +desk_0230 +desk_0231 +desk_0232 +desk_0233 +desk_0234 +desk_0235 +desk_0236 +desk_0237 +desk_0238 +desk_0239 +desk_0240 +desk_0241 +desk_0242 +desk_0243 +desk_0244 +desk_0245 +desk_0246 +desk_0247 +desk_0248 +desk_0249 +desk_0250 +desk_0251 +desk_0252 +desk_0253 +desk_0254 +desk_0255 +desk_0256 +desk_0257 +desk_0258 +desk_0259 +desk_0260 +desk_0261 +desk_0262 +desk_0263 +desk_0264 +desk_0265 +desk_0266 +desk_0267 +desk_0268 +desk_0269 +desk_0270 +desk_0271 +desk_0272 +desk_0273 +desk_0274 +desk_0275 +desk_0276 +desk_0277 +desk_0278 +desk_0279 +desk_0280 +desk_0281 +desk_0282 +desk_0283 +desk_0284 +desk_0285 +desk_0286 +door_0110 +door_0111 +door_0112 +door_0113 +door_0114 +door_0115 +door_0116 +door_0117 +door_0118 +door_0119 +door_0120 +door_0121 +door_0122 +door_0123 +door_0124 +door_0125 +door_0126 +door_0127 +door_0128 +door_0129 +dresser_0201 +dresser_0202 +dresser_0203 +dresser_0204 +dresser_0205 +dresser_0206 +dresser_0207 +dresser_0208 +dresser_0209 +dresser_0210 +dresser_0211 +dresser_0212 +dresser_0213 +dresser_0214 +dresser_0215 +dresser_0216 +dresser_0217 +dresser_0218 +dresser_0219 +dresser_0220 +dresser_0221 +dresser_0222 +dresser_0223 +dresser_0224 +dresser_0225 +dresser_0226 +dresser_0227 +dresser_0228 +dresser_0229 +dresser_0230 +dresser_0231 +dresser_0232 +dresser_0233 +dresser_0234 +dresser_0235 +dresser_0236 +dresser_0237 +dresser_0238 +dresser_0239 +dresser_0240 +dresser_0241 +dresser_0242 +dresser_0243 +dresser_0244 +dresser_0245 +dresser_0246 +dresser_0247 +dresser_0248 +dresser_0249 +dresser_0250 +dresser_0251 +dresser_0252 +dresser_0253 +dresser_0254 +dresser_0255 +dresser_0256 +dresser_0257 +dresser_0258 +dresser_0259 +dresser_0260 +dresser_0261 +dresser_0262 +dresser_0263 +dresser_0264 +dresser_0265 +dresser_0266 +dresser_0267 +dresser_0268 +dresser_0269 +dresser_0270 +dresser_0271 +dresser_0272 +dresser_0273 +dresser_0274 +dresser_0275 +dresser_0276 +dresser_0277 +dresser_0278 +dresser_0279 +dresser_0280 +dresser_0281 +dresser_0282 +dresser_0283 +dresser_0284 +dresser_0285 +dresser_0286 +flower_pot_0150 +flower_pot_0151 +flower_pot_0152 +flower_pot_0153 +flower_pot_0154 +flower_pot_0155 +flower_pot_0156 +flower_pot_0157 +flower_pot_0158 +flower_pot_0159 +flower_pot_0160 +flower_pot_0161 +flower_pot_0162 +flower_pot_0163 +flower_pot_0164 +flower_pot_0165 +flower_pot_0166 +flower_pot_0167 +flower_pot_0168 +flower_pot_0169 +glass_box_0172 +glass_box_0173 +glass_box_0174 +glass_box_0175 +glass_box_0176 +glass_box_0177 +glass_box_0178 +glass_box_0179 +glass_box_0180 +glass_box_0181 +glass_box_0182 +glass_box_0183 +glass_box_0184 +glass_box_0185 +glass_box_0186 +glass_box_0187 +glass_box_0188 +glass_box_0189 +glass_box_0190 +glass_box_0191 +glass_box_0192 +glass_box_0193 +glass_box_0194 +glass_box_0195 +glass_box_0196 +glass_box_0197 +glass_box_0198 +glass_box_0199 +glass_box_0200 +glass_box_0201 +glass_box_0202 +glass_box_0203 +glass_box_0204 +glass_box_0205 +glass_box_0206 +glass_box_0207 +glass_box_0208 +glass_box_0209 +glass_box_0210 +glass_box_0211 +glass_box_0212 +glass_box_0213 +glass_box_0214 +glass_box_0215 +glass_box_0216 +glass_box_0217 +glass_box_0218 +glass_box_0219 +glass_box_0220 +glass_box_0221 +glass_box_0222 +glass_box_0223 +glass_box_0224 +glass_box_0225 +glass_box_0226 +glass_box_0227 +glass_box_0228 +glass_box_0229 +glass_box_0230 +glass_box_0231 +glass_box_0232 +glass_box_0233 +glass_box_0234 +glass_box_0235 +glass_box_0236 +glass_box_0237 +glass_box_0238 +glass_box_0239 +glass_box_0240 +glass_box_0241 +glass_box_0242 +glass_box_0243 +glass_box_0244 +glass_box_0245 +glass_box_0246 +glass_box_0247 +glass_box_0248 +glass_box_0249 +glass_box_0250 +glass_box_0251 +glass_box_0252 +glass_box_0253 +glass_box_0254 +glass_box_0255 +glass_box_0256 +glass_box_0257 +glass_box_0258 +glass_box_0259 +glass_box_0260 +glass_box_0261 +glass_box_0262 +glass_box_0263 +glass_box_0264 +glass_box_0265 +glass_box_0266 +glass_box_0267 +glass_box_0268 +glass_box_0269 +glass_box_0270 +glass_box_0271 +guitar_0156 +guitar_0157 +guitar_0158 +guitar_0159 +guitar_0160 +guitar_0161 +guitar_0162 +guitar_0163 +guitar_0164 +guitar_0165 +guitar_0166 +guitar_0167 +guitar_0168 +guitar_0169 +guitar_0170 +guitar_0171 +guitar_0172 +guitar_0173 +guitar_0174 +guitar_0175 +guitar_0176 +guitar_0177 +guitar_0178 +guitar_0179 +guitar_0180 +guitar_0181 +guitar_0182 +guitar_0183 +guitar_0184 +guitar_0185 +guitar_0186 +guitar_0187 +guitar_0188 +guitar_0189 +guitar_0190 +guitar_0191 +guitar_0192 +guitar_0193 +guitar_0194 +guitar_0195 +guitar_0196 +guitar_0197 +guitar_0198 +guitar_0199 +guitar_0200 +guitar_0201 +guitar_0202 +guitar_0203 +guitar_0204 +guitar_0205 +guitar_0206 +guitar_0207 +guitar_0208 +guitar_0209 +guitar_0210 +guitar_0211 +guitar_0212 +guitar_0213 +guitar_0214 +guitar_0215 +guitar_0216 +guitar_0217 +guitar_0218 +guitar_0219 +guitar_0220 +guitar_0221 +guitar_0222 +guitar_0223 +guitar_0224 +guitar_0225 +guitar_0226 +guitar_0227 +guitar_0228 +guitar_0229 +guitar_0230 +guitar_0231 +guitar_0232 +guitar_0233 +guitar_0234 +guitar_0235 +guitar_0236 +guitar_0237 +guitar_0238 +guitar_0239 +guitar_0240 +guitar_0241 +guitar_0242 +guitar_0243 +guitar_0244 +guitar_0245 +guitar_0246 +guitar_0247 +guitar_0248 +guitar_0249 +guitar_0250 +guitar_0251 +guitar_0252 +guitar_0253 +guitar_0254 +guitar_0255 +keyboard_0146 +keyboard_0147 +keyboard_0148 +keyboard_0149 +keyboard_0150 +keyboard_0151 +keyboard_0152 +keyboard_0153 +keyboard_0154 +keyboard_0155 +keyboard_0156 +keyboard_0157 +keyboard_0158 +keyboard_0159 +keyboard_0160 +keyboard_0161 +keyboard_0162 +keyboard_0163 +keyboard_0164 +keyboard_0165 +lamp_0125 +lamp_0126 +lamp_0127 +lamp_0128 +lamp_0129 +lamp_0130 +lamp_0131 +lamp_0132 +lamp_0133 +lamp_0134 +lamp_0135 +lamp_0136 +lamp_0137 +lamp_0138 +lamp_0139 +lamp_0140 +lamp_0141 +lamp_0142 +lamp_0143 +lamp_0144 +laptop_0150 +laptop_0151 +laptop_0152 +laptop_0153 +laptop_0154 +laptop_0155 +laptop_0156 +laptop_0157 +laptop_0158 +laptop_0159 +laptop_0160 +laptop_0161 +laptop_0162 +laptop_0163 +laptop_0164 +laptop_0165 +laptop_0166 +laptop_0167 +laptop_0168 +laptop_0169 +mantel_0285 +mantel_0286 +mantel_0287 +mantel_0288 +mantel_0289 +mantel_0290 +mantel_0291 +mantel_0292 +mantel_0293 +mantel_0294 +mantel_0295 +mantel_0296 +mantel_0297 +mantel_0298 +mantel_0299 +mantel_0300 +mantel_0301 +mantel_0302 +mantel_0303 +mantel_0304 +mantel_0305 +mantel_0306 +mantel_0307 +mantel_0308 +mantel_0309 +mantel_0310 +mantel_0311 +mantel_0312 +mantel_0313 +mantel_0314 +mantel_0315 +mantel_0316 +mantel_0317 +mantel_0318 +mantel_0319 +mantel_0320 +mantel_0321 +mantel_0322 +mantel_0323 +mantel_0324 +mantel_0325 +mantel_0326 +mantel_0327 +mantel_0328 +mantel_0329 +mantel_0330 +mantel_0331 +mantel_0332 +mantel_0333 +mantel_0334 +mantel_0335 +mantel_0336 +mantel_0337 +mantel_0338 +mantel_0339 +mantel_0340 +mantel_0341 +mantel_0342 +mantel_0343 +mantel_0344 +mantel_0345 +mantel_0346 +mantel_0347 +mantel_0348 +mantel_0349 +mantel_0350 +mantel_0351 +mantel_0352 +mantel_0353 +mantel_0354 +mantel_0355 +mantel_0356 +mantel_0357 +mantel_0358 +mantel_0359 +mantel_0360 +mantel_0361 +mantel_0362 +mantel_0363 +mantel_0364 +mantel_0365 +mantel_0366 +mantel_0367 +mantel_0368 +mantel_0369 +mantel_0370 +mantel_0371 +mantel_0372 +mantel_0373 +mantel_0374 +mantel_0375 +mantel_0376 +mantel_0377 +mantel_0378 +mantel_0379 +mantel_0380 +mantel_0381 +mantel_0382 +mantel_0383 +mantel_0384 +monitor_0466 +monitor_0467 +monitor_0468 +monitor_0469 +monitor_0470 +monitor_0471 +monitor_0472 +monitor_0473 +monitor_0474 +monitor_0475 +monitor_0476 +monitor_0477 +monitor_0478 +monitor_0479 +monitor_0480 +monitor_0481 +monitor_0482 +monitor_0483 +monitor_0484 +monitor_0485 +monitor_0486 +monitor_0487 +monitor_0488 +monitor_0489 +monitor_0490 +monitor_0491 +monitor_0492 +monitor_0493 +monitor_0494 +monitor_0495 +monitor_0496 +monitor_0497 +monitor_0498 +monitor_0499 +monitor_0500 +monitor_0501 +monitor_0502 +monitor_0503 +monitor_0504 +monitor_0505 +monitor_0506 +monitor_0507 +monitor_0508 +monitor_0509 +monitor_0510 +monitor_0511 +monitor_0512 +monitor_0513 +monitor_0514 +monitor_0515 +monitor_0516 +monitor_0517 +monitor_0518 +monitor_0519 +monitor_0520 +monitor_0521 +monitor_0522 +monitor_0523 +monitor_0524 +monitor_0525 +monitor_0526 +monitor_0527 +monitor_0528 +monitor_0529 +monitor_0530 +monitor_0531 +monitor_0532 +monitor_0533 +monitor_0534 +monitor_0535 +monitor_0536 +monitor_0537 +monitor_0538 +monitor_0539 +monitor_0540 +monitor_0541 +monitor_0542 +monitor_0543 +monitor_0544 +monitor_0545 +monitor_0546 +monitor_0547 +monitor_0548 +monitor_0549 +monitor_0550 +monitor_0551 +monitor_0552 +monitor_0553 +monitor_0554 +monitor_0555 +monitor_0556 +monitor_0557 +monitor_0558 +monitor_0559 +monitor_0560 +monitor_0561 +monitor_0562 +monitor_0563 +monitor_0564 +monitor_0565 +night_stand_0201 +night_stand_0202 +night_stand_0203 +night_stand_0204 +night_stand_0205 +night_stand_0206 +night_stand_0207 +night_stand_0208 +night_stand_0209 +night_stand_0210 +night_stand_0211 +night_stand_0212 +night_stand_0213 +night_stand_0214 +night_stand_0215 +night_stand_0216 +night_stand_0217 +night_stand_0218 +night_stand_0219 +night_stand_0220 +night_stand_0221 +night_stand_0222 +night_stand_0223 +night_stand_0224 +night_stand_0225 +night_stand_0226 +night_stand_0227 +night_stand_0228 +night_stand_0229 +night_stand_0230 +night_stand_0231 +night_stand_0232 +night_stand_0233 +night_stand_0234 +night_stand_0235 +night_stand_0236 +night_stand_0237 +night_stand_0238 +night_stand_0239 +night_stand_0240 +night_stand_0241 +night_stand_0242 +night_stand_0243 +night_stand_0244 +night_stand_0245 +night_stand_0246 +night_stand_0247 +night_stand_0248 +night_stand_0249 +night_stand_0250 +night_stand_0251 +night_stand_0252 +night_stand_0253 +night_stand_0254 +night_stand_0255 +night_stand_0256 +night_stand_0257 +night_stand_0258 +night_stand_0259 +night_stand_0260 +night_stand_0261 +night_stand_0262 +night_stand_0263 +night_stand_0264 +night_stand_0265 +night_stand_0266 +night_stand_0267 +night_stand_0268 +night_stand_0269 +night_stand_0270 +night_stand_0271 +night_stand_0272 +night_stand_0273 +night_stand_0274 +night_stand_0275 +night_stand_0276 +night_stand_0277 +night_stand_0278 +night_stand_0279 +night_stand_0280 +night_stand_0281 +night_stand_0282 +night_stand_0283 +night_stand_0284 +night_stand_0285 +night_stand_0286 +person_0089 +person_0090 +person_0091 +person_0092 +person_0093 +person_0094 +person_0095 +person_0096 +person_0097 +person_0098 +person_0099 +person_0100 +person_0101 +person_0102 +person_0103 +person_0104 +person_0105 +person_0106 +person_0107 +person_0108 +piano_0232 +piano_0233 +piano_0234 +piano_0235 +piano_0236 +piano_0237 +piano_0238 +piano_0239 +piano_0240 +piano_0241 +piano_0242 +piano_0243 +piano_0244 +piano_0245 +piano_0246 +piano_0247 +piano_0248 +piano_0249 +piano_0250 +piano_0251 +piano_0252 +piano_0253 +piano_0254 +piano_0255 +piano_0256 +piano_0257 +piano_0258 +piano_0259 +piano_0260 +piano_0261 +piano_0262 +piano_0263 +piano_0264 +piano_0265 +piano_0266 +piano_0267 +piano_0268 +piano_0269 +piano_0270 +piano_0271 +piano_0272 +piano_0273 +piano_0274 +piano_0275 +piano_0276 +piano_0277 +piano_0278 +piano_0279 +piano_0280 +piano_0281 +piano_0282 +piano_0283 +piano_0284 +piano_0285 +piano_0286 +piano_0287 +piano_0288 +piano_0289 +piano_0290 +piano_0291 +piano_0292 +piano_0293 +piano_0294 +piano_0295 +piano_0296 +piano_0297 +piano_0298 +piano_0299 +piano_0300 +piano_0301 +piano_0302 +piano_0303 +piano_0304 +piano_0305 +piano_0306 +piano_0307 +piano_0308 +piano_0309 +piano_0310 +piano_0311 +piano_0312 +piano_0313 +piano_0314 +piano_0315 +piano_0316 +piano_0317 +piano_0318 +piano_0319 +piano_0320 +piano_0321 +piano_0322 +piano_0323 +piano_0324 +piano_0325 +piano_0326 +piano_0327 +piano_0328 +piano_0329 +piano_0330 +piano_0331 +plant_0241 +plant_0242 +plant_0243 +plant_0244 +plant_0245 +plant_0246 +plant_0247 +plant_0248 +plant_0249 +plant_0250 +plant_0251 +plant_0252 +plant_0253 +plant_0254 +plant_0255 +plant_0256 +plant_0257 +plant_0258 +plant_0259 +plant_0260 +plant_0261 +plant_0262 +plant_0263 +plant_0264 +plant_0265 +plant_0266 +plant_0267 +plant_0268 +plant_0269 +plant_0270 +plant_0271 +plant_0272 +plant_0273 +plant_0274 +plant_0275 +plant_0276 +plant_0277 +plant_0278 +plant_0279 +plant_0280 +plant_0281 +plant_0282 +plant_0283 +plant_0284 +plant_0285 +plant_0286 +plant_0287 +plant_0288 +plant_0289 +plant_0290 +plant_0291 +plant_0292 +plant_0293 +plant_0294 +plant_0295 +plant_0296 +plant_0297 +plant_0298 +plant_0299 +plant_0300 +plant_0301 +plant_0302 +plant_0303 +plant_0304 +plant_0305 +plant_0306 +plant_0307 +plant_0308 +plant_0309 +plant_0310 +plant_0311 +plant_0312 +plant_0313 +plant_0314 +plant_0315 +plant_0316 +plant_0317 +plant_0318 +plant_0319 +plant_0320 +plant_0321 +plant_0322 +plant_0323 +plant_0324 +plant_0325 +plant_0326 +plant_0327 +plant_0328 +plant_0329 +plant_0330 +plant_0331 +plant_0332 +plant_0333 +plant_0334 +plant_0335 +plant_0336 +plant_0337 +plant_0338 +plant_0339 +plant_0340 +radio_0105 +radio_0106 +radio_0107 +radio_0108 +radio_0109 +radio_0110 +radio_0111 +radio_0112 +radio_0113 +radio_0114 +radio_0115 +radio_0116 +radio_0117 +radio_0118 +radio_0119 +radio_0120 +radio_0121 +radio_0122 +radio_0123 +radio_0124 +range_hood_0116 +range_hood_0117 +range_hood_0118 +range_hood_0119 +range_hood_0120 +range_hood_0121 +range_hood_0122 +range_hood_0123 +range_hood_0124 +range_hood_0125 +range_hood_0126 +range_hood_0127 +range_hood_0128 +range_hood_0129 +range_hood_0130 +range_hood_0131 +range_hood_0132 +range_hood_0133 +range_hood_0134 +range_hood_0135 +range_hood_0136 +range_hood_0137 +range_hood_0138 +range_hood_0139 +range_hood_0140 +range_hood_0141 +range_hood_0142 +range_hood_0143 +range_hood_0144 +range_hood_0145 +range_hood_0146 +range_hood_0147 +range_hood_0148 +range_hood_0149 +range_hood_0150 +range_hood_0151 +range_hood_0152 +range_hood_0153 +range_hood_0154 +range_hood_0155 +range_hood_0156 +range_hood_0157 +range_hood_0158 +range_hood_0159 +range_hood_0160 +range_hood_0161 +range_hood_0162 +range_hood_0163 +range_hood_0164 +range_hood_0165 +range_hood_0166 +range_hood_0167 +range_hood_0168 +range_hood_0169 +range_hood_0170 +range_hood_0171 +range_hood_0172 +range_hood_0173 +range_hood_0174 +range_hood_0175 +range_hood_0176 +range_hood_0177 +range_hood_0178 +range_hood_0179 +range_hood_0180 +range_hood_0181 +range_hood_0182 +range_hood_0183 +range_hood_0184 +range_hood_0185 +range_hood_0186 +range_hood_0187 +range_hood_0188 +range_hood_0189 +range_hood_0190 +range_hood_0191 +range_hood_0192 +range_hood_0193 +range_hood_0194 +range_hood_0195 +range_hood_0196 +range_hood_0197 +range_hood_0198 +range_hood_0199 +range_hood_0200 +range_hood_0201 +range_hood_0202 +range_hood_0203 +range_hood_0204 +range_hood_0205 +range_hood_0206 +range_hood_0207 +range_hood_0208 +range_hood_0209 +range_hood_0210 +range_hood_0211 +range_hood_0212 +range_hood_0213 +range_hood_0214 +range_hood_0215 +sink_0129 +sink_0130 +sink_0131 +sink_0132 +sink_0133 +sink_0134 +sink_0135 +sink_0136 +sink_0137 +sink_0138 +sink_0139 +sink_0140 +sink_0141 +sink_0142 +sink_0143 +sink_0144 +sink_0145 +sink_0146 +sink_0147 +sink_0148 +sofa_0681 +sofa_0682 +sofa_0683 +sofa_0684 +sofa_0685 +sofa_0686 +sofa_0687 +sofa_0688 +sofa_0689 +sofa_0690 +sofa_0691 +sofa_0692 +sofa_0693 +sofa_0694 +sofa_0695 +sofa_0696 +sofa_0697 +sofa_0698 +sofa_0699 +sofa_0700 +sofa_0701 +sofa_0702 +sofa_0703 +sofa_0704 +sofa_0705 +sofa_0706 +sofa_0707 +sofa_0708 +sofa_0709 +sofa_0710 +sofa_0711 +sofa_0712 +sofa_0713 +sofa_0714 +sofa_0715 +sofa_0716 +sofa_0717 +sofa_0718 +sofa_0719 +sofa_0720 +sofa_0721 +sofa_0722 +sofa_0723 +sofa_0724 +sofa_0725 +sofa_0726 +sofa_0727 +sofa_0728 +sofa_0729 +sofa_0730 +sofa_0731 +sofa_0732 +sofa_0733 +sofa_0734 +sofa_0735 +sofa_0736 +sofa_0737 +sofa_0738 +sofa_0739 +sofa_0740 +sofa_0741 +sofa_0742 +sofa_0743 +sofa_0744 +sofa_0745 +sofa_0746 +sofa_0747 +sofa_0748 +sofa_0749 +sofa_0750 +sofa_0751 +sofa_0752 +sofa_0753 +sofa_0754 +sofa_0755 +sofa_0756 +sofa_0757 +sofa_0758 +sofa_0759 +sofa_0760 +sofa_0761 +sofa_0762 +sofa_0763 +sofa_0764 +sofa_0765 +sofa_0766 +sofa_0767 +sofa_0768 +sofa_0769 +sofa_0770 +sofa_0771 +sofa_0772 +sofa_0773 +sofa_0774 +sofa_0775 +sofa_0776 +sofa_0777 +sofa_0778 +sofa_0779 +sofa_0780 +stairs_0125 +stairs_0126 +stairs_0127 +stairs_0128 +stairs_0129 +stairs_0130 +stairs_0131 +stairs_0132 +stairs_0133 +stairs_0134 +stairs_0135 +stairs_0136 +stairs_0137 +stairs_0138 +stairs_0139 +stairs_0140 +stairs_0141 +stairs_0142 +stairs_0143 +stairs_0144 +stool_0091 +stool_0092 +stool_0093 +stool_0094 +stool_0095 +stool_0096 +stool_0097 +stool_0098 +stool_0099 +stool_0100 +stool_0101 +stool_0102 +stool_0103 +stool_0104 +stool_0105 +stool_0106 +stool_0107 +stool_0108 +stool_0109 +stool_0110 +table_0393 +table_0394 +table_0395 +table_0396 +table_0397 +table_0398 +table_0399 +table_0400 +table_0401 +table_0402 +table_0403 +table_0404 +table_0405 +table_0406 +table_0407 +table_0408 +table_0409 +table_0410 +table_0411 +table_0412 +table_0413 +table_0414 +table_0415 +table_0416 +table_0417 +table_0418 +table_0419 +table_0420 +table_0421 +table_0422 +table_0423 +table_0424 +table_0425 +table_0426 +table_0427 +table_0428 +table_0429 +table_0430 +table_0431 +table_0432 +table_0433 +table_0434 +table_0435 +table_0436 +table_0437 +table_0438 +table_0439 +table_0440 +table_0441 +table_0442 +table_0443 +table_0444 +table_0445 +table_0446 +table_0447 +table_0448 +table_0449 +table_0450 +table_0451 +table_0452 +table_0453 +table_0454 +table_0455 +table_0456 +table_0457 +table_0458 +table_0459 +table_0460 +table_0461 +table_0462 +table_0463 +table_0464 +table_0465 +table_0466 +table_0467 +table_0468 +table_0469 +table_0470 +table_0471 +table_0472 +table_0473 +table_0474 +table_0475 +table_0476 +table_0477 +table_0478 +table_0479 +table_0480 +table_0481 +table_0482 +table_0483 +table_0484 +table_0485 +table_0486 +table_0487 +table_0488 +table_0489 +table_0490 +table_0491 +table_0492 +tent_0164 +tent_0165 +tent_0166 +tent_0167 +tent_0168 +tent_0169 +tent_0170 +tent_0171 +tent_0172 +tent_0173 +tent_0174 +tent_0175 +tent_0176 +tent_0177 +tent_0178 +tent_0179 +tent_0180 +tent_0181 +tent_0182 +tent_0183 +toilet_0345 +toilet_0346 +toilet_0347 +toilet_0348 +toilet_0349 +toilet_0350 +toilet_0351 +toilet_0352 +toilet_0353 +toilet_0354 +toilet_0355 +toilet_0356 +toilet_0357 +toilet_0358 +toilet_0359 +toilet_0360 +toilet_0361 +toilet_0362 +toilet_0363 +toilet_0364 +toilet_0365 +toilet_0366 +toilet_0367 +toilet_0368 +toilet_0369 +toilet_0370 +toilet_0371 +toilet_0372 +toilet_0373 +toilet_0374 +toilet_0375 +toilet_0376 +toilet_0377 +toilet_0378 +toilet_0379 +toilet_0380 +toilet_0381 +toilet_0382 +toilet_0383 +toilet_0384 +toilet_0385 +toilet_0386 +toilet_0387 +toilet_0388 +toilet_0389 +toilet_0390 +toilet_0391 +toilet_0392 +toilet_0393 +toilet_0394 +toilet_0395 +toilet_0396 +toilet_0397 +toilet_0398 +toilet_0399 +toilet_0400 +toilet_0401 +toilet_0402 +toilet_0403 +toilet_0404 +toilet_0405 +toilet_0406 +toilet_0407 +toilet_0408 +toilet_0409 +toilet_0410 +toilet_0411 +toilet_0412 +toilet_0413 +toilet_0414 +toilet_0415 +toilet_0416 +toilet_0417 +toilet_0418 +toilet_0419 +toilet_0420 +toilet_0421 +toilet_0422 +toilet_0423 +toilet_0424 +toilet_0425 +toilet_0426 +toilet_0427 +toilet_0428 +toilet_0429 +toilet_0430 +toilet_0431 +toilet_0432 +toilet_0433 +toilet_0434 +toilet_0435 +toilet_0436 +toilet_0437 +toilet_0438 +toilet_0439 +toilet_0440 +toilet_0441 +toilet_0442 +toilet_0443 +toilet_0444 +tv_stand_0268 +tv_stand_0269 +tv_stand_0270 +tv_stand_0271 +tv_stand_0272 +tv_stand_0273 +tv_stand_0274 +tv_stand_0275 +tv_stand_0276 +tv_stand_0277 +tv_stand_0278 +tv_stand_0279 +tv_stand_0280 +tv_stand_0281 +tv_stand_0282 +tv_stand_0283 +tv_stand_0284 +tv_stand_0285 +tv_stand_0286 +tv_stand_0287 +tv_stand_0288 +tv_stand_0289 +tv_stand_0290 +tv_stand_0291 +tv_stand_0292 +tv_stand_0293 +tv_stand_0294 +tv_stand_0295 +tv_stand_0296 +tv_stand_0297 +tv_stand_0298 +tv_stand_0299 +tv_stand_0300 +tv_stand_0301 +tv_stand_0302 +tv_stand_0303 +tv_stand_0304 +tv_stand_0305 +tv_stand_0306 +tv_stand_0307 +tv_stand_0308 +tv_stand_0309 +tv_stand_0310 +tv_stand_0311 +tv_stand_0312 +tv_stand_0313 +tv_stand_0314 +tv_stand_0315 +tv_stand_0316 +tv_stand_0317 +tv_stand_0318 +tv_stand_0319 +tv_stand_0320 +tv_stand_0321 +tv_stand_0322 +tv_stand_0323 +tv_stand_0324 +tv_stand_0325 +tv_stand_0326 +tv_stand_0327 +tv_stand_0328 +tv_stand_0329 +tv_stand_0330 +tv_stand_0331 +tv_stand_0332 +tv_stand_0333 +tv_stand_0334 +tv_stand_0335 +tv_stand_0336 +tv_stand_0337 +tv_stand_0338 +tv_stand_0339 +tv_stand_0340 +tv_stand_0341 +tv_stand_0342 +tv_stand_0343 +tv_stand_0344 +tv_stand_0345 +tv_stand_0346 +tv_stand_0347 +tv_stand_0348 +tv_stand_0349 +tv_stand_0350 +tv_stand_0351 +tv_stand_0352 +tv_stand_0353 +tv_stand_0354 +tv_stand_0355 +tv_stand_0356 +tv_stand_0357 +tv_stand_0358 +tv_stand_0359 +tv_stand_0360 +tv_stand_0361 +tv_stand_0362 +tv_stand_0363 +tv_stand_0364 +tv_stand_0365 +tv_stand_0366 +tv_stand_0367 +vase_0476 +vase_0477 +vase_0478 +vase_0479 +vase_0480 +vase_0481 +vase_0482 +vase_0483 +vase_0484 +vase_0485 +vase_0486 +vase_0487 +vase_0488 +vase_0489 +vase_0490 +vase_0491 +vase_0492 +vase_0493 +vase_0494 +vase_0495 +vase_0496 +vase_0497 +vase_0498 +vase_0499 +vase_0500 +vase_0501 +vase_0502 +vase_0503 +vase_0504 +vase_0505 +vase_0506 +vase_0507 +vase_0508 +vase_0509 +vase_0510 +vase_0511 +vase_0512 +vase_0513 +vase_0514 +vase_0515 +vase_0516 +vase_0517 +vase_0518 +vase_0519 +vase_0520 +vase_0521 +vase_0522 +vase_0523 +vase_0524 +vase_0525 +vase_0526 +vase_0527 +vase_0528 +vase_0529 +vase_0530 +vase_0531 +vase_0532 +vase_0533 +vase_0534 +vase_0535 +vase_0536 +vase_0537 +vase_0538 +vase_0539 +vase_0540 +vase_0541 +vase_0542 +vase_0543 +vase_0544 +vase_0545 +vase_0546 +vase_0547 +vase_0548 +vase_0549 +vase_0550 +vase_0551 +vase_0552 +vase_0553 +vase_0554 +vase_0555 +vase_0556 +vase_0557 +vase_0558 +vase_0559 +vase_0560 +vase_0561 +vase_0562 +vase_0563 +vase_0564 +vase_0565 +vase_0566 +vase_0567 +vase_0568 +vase_0569 +vase_0570 +vase_0571 +vase_0572 +vase_0573 +vase_0574 +vase_0575 +wardrobe_0088 +wardrobe_0089 +wardrobe_0090 +wardrobe_0091 +wardrobe_0092 +wardrobe_0093 +wardrobe_0094 +wardrobe_0095 +wardrobe_0096 +wardrobe_0097 +wardrobe_0098 +wardrobe_0099 +wardrobe_0100 +wardrobe_0101 +wardrobe_0102 +wardrobe_0103 +wardrobe_0104 +wardrobe_0105 +wardrobe_0106 +wardrobe_0107 +xbox_0104 +xbox_0105 +xbox_0106 +xbox_0107 +xbox_0108 +xbox_0109 +xbox_0110 +xbox_0111 +xbox_0112 +xbox_0113 +xbox_0114 +xbox_0115 +xbox_0116 +xbox_0117 +xbox_0118 +xbox_0119 +xbox_0120 +xbox_0121 +xbox_0122 +xbox_0123 diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_train.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_train.txt new file mode 100644 index 00000000..3a50c70a --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ModelNet/modelnet40_normal_resampled/modelnet40_train.txt @@ -0,0 +1,9843 @@ +airplane_0001 +airplane_0002 +airplane_0003 +airplane_0004 +airplane_0005 +airplane_0006 +airplane_0007 +airplane_0008 +airplane_0009 +airplane_0010 +airplane_0011 +airplane_0012 +airplane_0013 +airplane_0014 +airplane_0015 +airplane_0016 +airplane_0017 +airplane_0018 +airplane_0019 +airplane_0020 +airplane_0021 +airplane_0022 +airplane_0023 +airplane_0024 +airplane_0025 +airplane_0026 +airplane_0027 +airplane_0028 +airplane_0029 +airplane_0030 +airplane_0031 +airplane_0032 +airplane_0033 +airplane_0034 +airplane_0035 +airplane_0036 +airplane_0037 +airplane_0038 +airplane_0039 +airplane_0040 +airplane_0041 +airplane_0042 +airplane_0043 +airplane_0044 +airplane_0045 +airplane_0046 +airplane_0047 +airplane_0048 +airplane_0049 +airplane_0050 +airplane_0051 +airplane_0052 +airplane_0053 +airplane_0054 +airplane_0055 +airplane_0056 +airplane_0057 +airplane_0058 +airplane_0059 +airplane_0060 +airplane_0061 +airplane_0062 +airplane_0063 +airplane_0064 +airplane_0065 +airplane_0066 +airplane_0067 +airplane_0068 +airplane_0069 +airplane_0070 +airplane_0071 +airplane_0072 +airplane_0073 +airplane_0074 +airplane_0075 +airplane_0076 +airplane_0077 +airplane_0078 +airplane_0079 +airplane_0080 +airplane_0081 +airplane_0082 +airplane_0083 +airplane_0084 +airplane_0085 +airplane_0086 +airplane_0087 +airplane_0088 +airplane_0089 +airplane_0090 +airplane_0091 +airplane_0092 +airplane_0093 +airplane_0094 +airplane_0095 +airplane_0096 +airplane_0097 +airplane_0098 +airplane_0099 +airplane_0100 +airplane_0101 +airplane_0102 +airplane_0103 +airplane_0104 +airplane_0105 +airplane_0106 +airplane_0107 +airplane_0108 +airplane_0109 +airplane_0110 +airplane_0111 +airplane_0112 +airplane_0113 +airplane_0114 +airplane_0115 +airplane_0116 +airplane_0117 +airplane_0118 +airplane_0119 +airplane_0120 +airplane_0121 +airplane_0122 +airplane_0123 +airplane_0124 +airplane_0125 +airplane_0126 +airplane_0127 +airplane_0128 +airplane_0129 +airplane_0130 +airplane_0131 +airplane_0132 +airplane_0133 +airplane_0134 +airplane_0135 +airplane_0136 +airplane_0137 +airplane_0138 +airplane_0139 +airplane_0140 +airplane_0141 +airplane_0142 +airplane_0143 +airplane_0144 +airplane_0145 +airplane_0146 +airplane_0147 +airplane_0148 +airplane_0149 +airplane_0150 +airplane_0151 +airplane_0152 +airplane_0153 +airplane_0154 +airplane_0155 +airplane_0156 +airplane_0157 +airplane_0158 +airplane_0159 +airplane_0160 +airplane_0161 +airplane_0162 +airplane_0163 +airplane_0164 +airplane_0165 +airplane_0166 +airplane_0167 +airplane_0168 +airplane_0169 +airplane_0170 +airplane_0171 +airplane_0172 +airplane_0173 +airplane_0174 +airplane_0175 +airplane_0176 +airplane_0177 +airplane_0178 +airplane_0179 +airplane_0180 +airplane_0181 +airplane_0182 +airplane_0183 +airplane_0184 +airplane_0185 +airplane_0186 +airplane_0187 +airplane_0188 +airplane_0189 +airplane_0190 +airplane_0191 +airplane_0192 +airplane_0193 +airplane_0194 +airplane_0195 +airplane_0196 +airplane_0197 +airplane_0198 +airplane_0199 +airplane_0200 +airplane_0201 +airplane_0202 +airplane_0203 +airplane_0204 +airplane_0205 +airplane_0206 +airplane_0207 +airplane_0208 +airplane_0209 +airplane_0210 +airplane_0211 +airplane_0212 +airplane_0213 +airplane_0214 +airplane_0215 +airplane_0216 +airplane_0217 +airplane_0218 +airplane_0219 +airplane_0220 +airplane_0221 +airplane_0222 +airplane_0223 +airplane_0224 +airplane_0225 +airplane_0226 +airplane_0227 +airplane_0228 +airplane_0229 +airplane_0230 +airplane_0231 +airplane_0232 +airplane_0233 +airplane_0234 +airplane_0235 +airplane_0236 +airplane_0237 +airplane_0238 +airplane_0239 +airplane_0240 +airplane_0241 +airplane_0242 +airplane_0243 +airplane_0244 +airplane_0245 +airplane_0246 +airplane_0247 +airplane_0248 +airplane_0249 +airplane_0250 +airplane_0251 +airplane_0252 +airplane_0253 +airplane_0254 +airplane_0255 +airplane_0256 +airplane_0257 +airplane_0258 +airplane_0259 +airplane_0260 +airplane_0261 +airplane_0262 +airplane_0263 +airplane_0264 +airplane_0265 +airplane_0266 +airplane_0267 +airplane_0268 +airplane_0269 +airplane_0270 +airplane_0271 +airplane_0272 +airplane_0273 +airplane_0274 +airplane_0275 +airplane_0276 +airplane_0277 +airplane_0278 +airplane_0279 +airplane_0280 +airplane_0281 +airplane_0282 +airplane_0283 +airplane_0284 +airplane_0285 +airplane_0286 +airplane_0287 +airplane_0288 +airplane_0289 +airplane_0290 +airplane_0291 +airplane_0292 +airplane_0293 +airplane_0294 +airplane_0295 +airplane_0296 +airplane_0297 +airplane_0298 +airplane_0299 +airplane_0300 +airplane_0301 +airplane_0302 +airplane_0303 +airplane_0304 +airplane_0305 +airplane_0306 +airplane_0307 +airplane_0308 +airplane_0309 +airplane_0310 +airplane_0311 +airplane_0312 +airplane_0313 +airplane_0314 +airplane_0315 +airplane_0316 +airplane_0317 +airplane_0318 +airplane_0319 +airplane_0320 +airplane_0321 +airplane_0322 +airplane_0323 +airplane_0324 +airplane_0325 +airplane_0326 +airplane_0327 +airplane_0328 +airplane_0329 +airplane_0330 +airplane_0331 +airplane_0332 +airplane_0333 +airplane_0334 +airplane_0335 +airplane_0336 +airplane_0337 +airplane_0338 +airplane_0339 +airplane_0340 +airplane_0341 +airplane_0342 +airplane_0343 +airplane_0344 +airplane_0345 +airplane_0346 +airplane_0347 +airplane_0348 +airplane_0349 +airplane_0350 +airplane_0351 +airplane_0352 +airplane_0353 +airplane_0354 +airplane_0355 +airplane_0356 +airplane_0357 +airplane_0358 +airplane_0359 +airplane_0360 +airplane_0361 +airplane_0362 +airplane_0363 +airplane_0364 +airplane_0365 +airplane_0366 +airplane_0367 +airplane_0368 +airplane_0369 +airplane_0370 +airplane_0371 +airplane_0372 +airplane_0373 +airplane_0374 +airplane_0375 +airplane_0376 +airplane_0377 +airplane_0378 +airplane_0379 +airplane_0380 +airplane_0381 +airplane_0382 +airplane_0383 +airplane_0384 +airplane_0385 +airplane_0386 +airplane_0387 +airplane_0388 +airplane_0389 +airplane_0390 +airplane_0391 +airplane_0392 +airplane_0393 +airplane_0394 +airplane_0395 +airplane_0396 +airplane_0397 +airplane_0398 +airplane_0399 +airplane_0400 +airplane_0401 +airplane_0402 +airplane_0403 +airplane_0404 +airplane_0405 +airplane_0406 +airplane_0407 +airplane_0408 +airplane_0409 +airplane_0410 +airplane_0411 +airplane_0412 +airplane_0413 +airplane_0414 +airplane_0415 +airplane_0416 +airplane_0417 +airplane_0418 +airplane_0419 +airplane_0420 +airplane_0421 +airplane_0422 +airplane_0423 +airplane_0424 +airplane_0425 +airplane_0426 +airplane_0427 +airplane_0428 +airplane_0429 +airplane_0430 +airplane_0431 +airplane_0432 +airplane_0433 +airplane_0434 +airplane_0435 +airplane_0436 +airplane_0437 +airplane_0438 +airplane_0439 +airplane_0440 +airplane_0441 +airplane_0442 +airplane_0443 +airplane_0444 +airplane_0445 +airplane_0446 +airplane_0447 +airplane_0448 +airplane_0449 +airplane_0450 +airplane_0451 +airplane_0452 +airplane_0453 +airplane_0454 +airplane_0455 +airplane_0456 +airplane_0457 +airplane_0458 +airplane_0459 +airplane_0460 +airplane_0461 +airplane_0462 +airplane_0463 +airplane_0464 +airplane_0465 +airplane_0466 +airplane_0467 +airplane_0468 +airplane_0469 +airplane_0470 +airplane_0471 +airplane_0472 +airplane_0473 +airplane_0474 +airplane_0475 +airplane_0476 +airplane_0477 +airplane_0478 +airplane_0479 +airplane_0480 +airplane_0481 +airplane_0482 +airplane_0483 +airplane_0484 +airplane_0485 +airplane_0486 +airplane_0487 +airplane_0488 +airplane_0489 +airplane_0490 +airplane_0491 +airplane_0492 +airplane_0493 +airplane_0494 +airplane_0495 +airplane_0496 +airplane_0497 +airplane_0498 +airplane_0499 +airplane_0500 +airplane_0501 +airplane_0502 +airplane_0503 +airplane_0504 +airplane_0505 +airplane_0506 +airplane_0507 +airplane_0508 +airplane_0509 +airplane_0510 +airplane_0511 +airplane_0512 +airplane_0513 +airplane_0514 +airplane_0515 +airplane_0516 +airplane_0517 +airplane_0518 +airplane_0519 +airplane_0520 +airplane_0521 +airplane_0522 +airplane_0523 +airplane_0524 +airplane_0525 +airplane_0526 +airplane_0527 +airplane_0528 +airplane_0529 +airplane_0530 +airplane_0531 +airplane_0532 +airplane_0533 +airplane_0534 +airplane_0535 +airplane_0536 +airplane_0537 +airplane_0538 +airplane_0539 +airplane_0540 +airplane_0541 +airplane_0542 +airplane_0543 +airplane_0544 +airplane_0545 +airplane_0546 +airplane_0547 +airplane_0548 +airplane_0549 +airplane_0550 +airplane_0551 +airplane_0552 +airplane_0553 +airplane_0554 +airplane_0555 +airplane_0556 +airplane_0557 +airplane_0558 +airplane_0559 +airplane_0560 +airplane_0561 +airplane_0562 +airplane_0563 +airplane_0564 +airplane_0565 +airplane_0566 +airplane_0567 +airplane_0568 +airplane_0569 +airplane_0570 +airplane_0571 +airplane_0572 +airplane_0573 +airplane_0574 +airplane_0575 +airplane_0576 +airplane_0577 +airplane_0578 +airplane_0579 +airplane_0580 +airplane_0581 +airplane_0582 +airplane_0583 +airplane_0584 +airplane_0585 +airplane_0586 +airplane_0587 +airplane_0588 +airplane_0589 +airplane_0590 +airplane_0591 +airplane_0592 +airplane_0593 +airplane_0594 +airplane_0595 +airplane_0596 +airplane_0597 +airplane_0598 +airplane_0599 +airplane_0600 +airplane_0601 +airplane_0602 +airplane_0603 +airplane_0604 +airplane_0605 +airplane_0606 +airplane_0607 +airplane_0608 +airplane_0609 +airplane_0610 +airplane_0611 +airplane_0612 +airplane_0613 +airplane_0614 +airplane_0615 +airplane_0616 +airplane_0617 +airplane_0618 +airplane_0619 +airplane_0620 +airplane_0621 +airplane_0622 +airplane_0623 +airplane_0624 +airplane_0625 +airplane_0626 +bathtub_0001 +bathtub_0002 +bathtub_0003 +bathtub_0004 +bathtub_0005 +bathtub_0006 +bathtub_0007 +bathtub_0008 +bathtub_0009 +bathtub_0010 +bathtub_0011 +bathtub_0012 +bathtub_0013 +bathtub_0014 +bathtub_0015 +bathtub_0016 +bathtub_0017 +bathtub_0018 +bathtub_0019 +bathtub_0020 +bathtub_0021 +bathtub_0022 +bathtub_0023 +bathtub_0024 +bathtub_0025 +bathtub_0026 +bathtub_0027 +bathtub_0028 +bathtub_0029 +bathtub_0030 +bathtub_0031 +bathtub_0032 +bathtub_0033 +bathtub_0034 +bathtub_0035 +bathtub_0036 +bathtub_0037 +bathtub_0038 +bathtub_0039 +bathtub_0040 +bathtub_0041 +bathtub_0042 +bathtub_0043 +bathtub_0044 +bathtub_0045 +bathtub_0046 +bathtub_0047 +bathtub_0048 +bathtub_0049 +bathtub_0050 +bathtub_0051 +bathtub_0052 +bathtub_0053 +bathtub_0054 +bathtub_0055 +bathtub_0056 +bathtub_0057 +bathtub_0058 +bathtub_0059 +bathtub_0060 +bathtub_0061 +bathtub_0062 +bathtub_0063 +bathtub_0064 +bathtub_0065 +bathtub_0066 +bathtub_0067 +bathtub_0068 +bathtub_0069 +bathtub_0070 +bathtub_0071 +bathtub_0072 +bathtub_0073 +bathtub_0074 +bathtub_0075 +bathtub_0076 +bathtub_0077 +bathtub_0078 +bathtub_0079 +bathtub_0080 +bathtub_0081 +bathtub_0082 +bathtub_0083 +bathtub_0084 +bathtub_0085 +bathtub_0086 +bathtub_0087 +bathtub_0088 +bathtub_0089 +bathtub_0090 +bathtub_0091 +bathtub_0092 +bathtub_0093 +bathtub_0094 +bathtub_0095 +bathtub_0096 +bathtub_0097 +bathtub_0098 +bathtub_0099 +bathtub_0100 +bathtub_0101 +bathtub_0102 +bathtub_0103 +bathtub_0104 +bathtub_0105 +bathtub_0106 +bed_0001 +bed_0002 +bed_0003 +bed_0004 +bed_0005 +bed_0006 +bed_0007 +bed_0008 +bed_0009 +bed_0010 +bed_0011 +bed_0012 +bed_0013 +bed_0014 +bed_0015 +bed_0016 +bed_0017 +bed_0018 +bed_0019 +bed_0020 +bed_0021 +bed_0022 +bed_0023 +bed_0024 +bed_0025 +bed_0026 +bed_0027 +bed_0028 +bed_0029 +bed_0030 +bed_0031 +bed_0032 +bed_0033 +bed_0034 +bed_0035 +bed_0036 +bed_0037 +bed_0038 +bed_0039 +bed_0040 +bed_0041 +bed_0042 +bed_0043 +bed_0044 +bed_0045 +bed_0046 +bed_0047 +bed_0048 +bed_0049 +bed_0050 +bed_0051 +bed_0052 +bed_0053 +bed_0054 +bed_0055 +bed_0056 +bed_0057 +bed_0058 +bed_0059 +bed_0060 +bed_0061 +bed_0062 +bed_0063 +bed_0064 +bed_0065 +bed_0066 +bed_0067 +bed_0068 +bed_0069 +bed_0070 +bed_0071 +bed_0072 +bed_0073 +bed_0074 +bed_0075 +bed_0076 +bed_0077 +bed_0078 +bed_0079 +bed_0080 +bed_0081 +bed_0082 +bed_0083 +bed_0084 +bed_0085 +bed_0086 +bed_0087 +bed_0088 +bed_0089 +bed_0090 +bed_0091 +bed_0092 +bed_0093 +bed_0094 +bed_0095 +bed_0096 +bed_0097 +bed_0098 +bed_0099 +bed_0100 +bed_0101 +bed_0102 +bed_0103 +bed_0104 +bed_0105 +bed_0106 +bed_0107 +bed_0108 +bed_0109 +bed_0110 +bed_0111 +bed_0112 +bed_0113 +bed_0114 +bed_0115 +bed_0116 +bed_0117 +bed_0118 +bed_0119 +bed_0120 +bed_0121 +bed_0122 +bed_0123 +bed_0124 +bed_0125 +bed_0126 +bed_0127 +bed_0128 +bed_0129 +bed_0130 +bed_0131 +bed_0132 +bed_0133 +bed_0134 +bed_0135 +bed_0136 +bed_0137 +bed_0138 +bed_0139 +bed_0140 +bed_0141 +bed_0142 +bed_0143 +bed_0144 +bed_0145 +bed_0146 +bed_0147 +bed_0148 +bed_0149 +bed_0150 +bed_0151 +bed_0152 +bed_0153 +bed_0154 +bed_0155 +bed_0156 +bed_0157 +bed_0158 +bed_0159 +bed_0160 +bed_0161 +bed_0162 +bed_0163 +bed_0164 +bed_0165 +bed_0166 +bed_0167 +bed_0168 +bed_0169 +bed_0170 +bed_0171 +bed_0172 +bed_0173 +bed_0174 +bed_0175 +bed_0176 +bed_0177 +bed_0178 +bed_0179 +bed_0180 +bed_0181 +bed_0182 +bed_0183 +bed_0184 +bed_0185 +bed_0186 +bed_0187 +bed_0188 +bed_0189 +bed_0190 +bed_0191 +bed_0192 +bed_0193 +bed_0194 +bed_0195 +bed_0196 +bed_0197 +bed_0198 +bed_0199 +bed_0200 +bed_0201 +bed_0202 +bed_0203 +bed_0204 +bed_0205 +bed_0206 +bed_0207 +bed_0208 +bed_0209 +bed_0210 +bed_0211 +bed_0212 +bed_0213 +bed_0214 +bed_0215 +bed_0216 +bed_0217 +bed_0218 +bed_0219 +bed_0220 +bed_0221 +bed_0222 +bed_0223 +bed_0224 +bed_0225 +bed_0226 +bed_0227 +bed_0228 +bed_0229 +bed_0230 +bed_0231 +bed_0232 +bed_0233 +bed_0234 +bed_0235 +bed_0236 +bed_0237 +bed_0238 +bed_0239 +bed_0240 +bed_0241 +bed_0242 +bed_0243 +bed_0244 +bed_0245 +bed_0246 +bed_0247 +bed_0248 +bed_0249 +bed_0250 +bed_0251 +bed_0252 +bed_0253 +bed_0254 +bed_0255 +bed_0256 +bed_0257 +bed_0258 +bed_0259 +bed_0260 +bed_0261 +bed_0262 +bed_0263 +bed_0264 +bed_0265 +bed_0266 +bed_0267 +bed_0268 +bed_0269 +bed_0270 +bed_0271 +bed_0272 +bed_0273 +bed_0274 +bed_0275 +bed_0276 +bed_0277 +bed_0278 +bed_0279 +bed_0280 +bed_0281 +bed_0282 +bed_0283 +bed_0284 +bed_0285 +bed_0286 +bed_0287 +bed_0288 +bed_0289 +bed_0290 +bed_0291 +bed_0292 +bed_0293 +bed_0294 +bed_0295 +bed_0296 +bed_0297 +bed_0298 +bed_0299 +bed_0300 +bed_0301 +bed_0302 +bed_0303 +bed_0304 +bed_0305 +bed_0306 +bed_0307 +bed_0308 +bed_0309 +bed_0310 +bed_0311 +bed_0312 +bed_0313 +bed_0314 +bed_0315 +bed_0316 +bed_0317 +bed_0318 +bed_0319 +bed_0320 +bed_0321 +bed_0322 +bed_0323 +bed_0324 +bed_0325 +bed_0326 +bed_0327 +bed_0328 +bed_0329 +bed_0330 +bed_0331 +bed_0332 +bed_0333 +bed_0334 +bed_0335 +bed_0336 +bed_0337 +bed_0338 +bed_0339 +bed_0340 +bed_0341 +bed_0342 +bed_0343 +bed_0344 +bed_0345 +bed_0346 +bed_0347 +bed_0348 +bed_0349 +bed_0350 +bed_0351 +bed_0352 +bed_0353 +bed_0354 +bed_0355 +bed_0356 +bed_0357 +bed_0358 +bed_0359 +bed_0360 +bed_0361 +bed_0362 +bed_0363 +bed_0364 +bed_0365 +bed_0366 +bed_0367 +bed_0368 +bed_0369 +bed_0370 +bed_0371 +bed_0372 +bed_0373 +bed_0374 +bed_0375 +bed_0376 +bed_0377 +bed_0378 +bed_0379 +bed_0380 +bed_0381 +bed_0382 +bed_0383 +bed_0384 +bed_0385 +bed_0386 +bed_0387 +bed_0388 +bed_0389 +bed_0390 +bed_0391 +bed_0392 +bed_0393 +bed_0394 +bed_0395 +bed_0396 +bed_0397 +bed_0398 +bed_0399 +bed_0400 +bed_0401 +bed_0402 +bed_0403 +bed_0404 +bed_0405 +bed_0406 +bed_0407 +bed_0408 +bed_0409 +bed_0410 +bed_0411 +bed_0412 +bed_0413 +bed_0414 +bed_0415 +bed_0416 +bed_0417 +bed_0418 +bed_0419 +bed_0420 +bed_0421 +bed_0422 +bed_0423 +bed_0424 +bed_0425 +bed_0426 +bed_0427 +bed_0428 +bed_0429 +bed_0430 +bed_0431 +bed_0432 +bed_0433 +bed_0434 +bed_0435 +bed_0436 +bed_0437 +bed_0438 +bed_0439 +bed_0440 +bed_0441 +bed_0442 +bed_0443 +bed_0444 +bed_0445 +bed_0446 +bed_0447 +bed_0448 +bed_0449 +bed_0450 +bed_0451 +bed_0452 +bed_0453 +bed_0454 +bed_0455 +bed_0456 +bed_0457 +bed_0458 +bed_0459 +bed_0460 +bed_0461 +bed_0462 +bed_0463 +bed_0464 +bed_0465 +bed_0466 +bed_0467 +bed_0468 +bed_0469 +bed_0470 +bed_0471 +bed_0472 +bed_0473 +bed_0474 +bed_0475 +bed_0476 +bed_0477 +bed_0478 +bed_0479 +bed_0480 +bed_0481 +bed_0482 +bed_0483 +bed_0484 +bed_0485 +bed_0486 +bed_0487 +bed_0488 +bed_0489 +bed_0490 +bed_0491 +bed_0492 +bed_0493 +bed_0494 +bed_0495 +bed_0496 +bed_0497 +bed_0498 +bed_0499 +bed_0500 +bed_0501 +bed_0502 +bed_0503 +bed_0504 +bed_0505 +bed_0506 +bed_0507 +bed_0508 +bed_0509 +bed_0510 +bed_0511 +bed_0512 +bed_0513 +bed_0514 +bed_0515 +bench_0001 +bench_0002 +bench_0003 +bench_0004 +bench_0005 +bench_0006 +bench_0007 +bench_0008 +bench_0009 +bench_0010 +bench_0011 +bench_0012 +bench_0013 +bench_0014 +bench_0015 +bench_0016 +bench_0017 +bench_0018 +bench_0019 +bench_0020 +bench_0021 +bench_0022 +bench_0023 +bench_0024 +bench_0025 +bench_0026 +bench_0027 +bench_0028 +bench_0029 +bench_0030 +bench_0031 +bench_0032 +bench_0033 +bench_0034 +bench_0035 +bench_0036 +bench_0037 +bench_0038 +bench_0039 +bench_0040 +bench_0041 +bench_0042 +bench_0043 +bench_0044 +bench_0045 +bench_0046 +bench_0047 +bench_0048 +bench_0049 +bench_0050 +bench_0051 +bench_0052 +bench_0053 +bench_0054 +bench_0055 +bench_0056 +bench_0057 +bench_0058 +bench_0059 +bench_0060 +bench_0061 +bench_0062 +bench_0063 +bench_0064 +bench_0065 +bench_0066 +bench_0067 +bench_0068 +bench_0069 +bench_0070 +bench_0071 +bench_0072 +bench_0073 +bench_0074 +bench_0075 +bench_0076 +bench_0077 +bench_0078 +bench_0079 +bench_0080 +bench_0081 +bench_0082 +bench_0083 +bench_0084 +bench_0085 +bench_0086 +bench_0087 +bench_0088 +bench_0089 +bench_0090 +bench_0091 +bench_0092 +bench_0093 +bench_0094 +bench_0095 +bench_0096 +bench_0097 +bench_0098 +bench_0099 +bench_0100 +bench_0101 +bench_0102 +bench_0103 +bench_0104 +bench_0105 +bench_0106 +bench_0107 +bench_0108 +bench_0109 +bench_0110 +bench_0111 +bench_0112 +bench_0113 +bench_0114 +bench_0115 +bench_0116 +bench_0117 +bench_0118 +bench_0119 +bench_0120 +bench_0121 +bench_0122 +bench_0123 +bench_0124 +bench_0125 +bench_0126 +bench_0127 +bench_0128 +bench_0129 +bench_0130 +bench_0131 +bench_0132 +bench_0133 +bench_0134 +bench_0135 +bench_0136 +bench_0137 +bench_0138 +bench_0139 +bench_0140 +bench_0141 +bench_0142 +bench_0143 +bench_0144 +bench_0145 +bench_0146 +bench_0147 +bench_0148 +bench_0149 +bench_0150 +bench_0151 +bench_0152 +bench_0153 +bench_0154 +bench_0155 +bench_0156 +bench_0157 +bench_0158 +bench_0159 +bench_0160 +bench_0161 +bench_0162 +bench_0163 +bench_0164 +bench_0165 +bench_0166 +bench_0167 +bench_0168 +bench_0169 +bench_0170 +bench_0171 +bench_0172 +bench_0173 +bookshelf_0001 +bookshelf_0002 +bookshelf_0003 +bookshelf_0004 +bookshelf_0005 +bookshelf_0006 +bookshelf_0007 +bookshelf_0008 +bookshelf_0009 +bookshelf_0010 +bookshelf_0011 +bookshelf_0012 +bookshelf_0013 +bookshelf_0014 +bookshelf_0015 +bookshelf_0016 +bookshelf_0017 +bookshelf_0018 +bookshelf_0019 +bookshelf_0020 +bookshelf_0021 +bookshelf_0022 +bookshelf_0023 +bookshelf_0024 +bookshelf_0025 +bookshelf_0026 +bookshelf_0027 +bookshelf_0028 +bookshelf_0029 +bookshelf_0030 +bookshelf_0031 +bookshelf_0032 +bookshelf_0033 +bookshelf_0034 +bookshelf_0035 +bookshelf_0036 +bookshelf_0037 +bookshelf_0038 +bookshelf_0039 +bookshelf_0040 +bookshelf_0041 +bookshelf_0042 +bookshelf_0043 +bookshelf_0044 +bookshelf_0045 +bookshelf_0046 +bookshelf_0047 +bookshelf_0048 +bookshelf_0049 +bookshelf_0050 +bookshelf_0051 +bookshelf_0052 +bookshelf_0053 +bookshelf_0054 +bookshelf_0055 +bookshelf_0056 +bookshelf_0057 +bookshelf_0058 +bookshelf_0059 +bookshelf_0060 +bookshelf_0061 +bookshelf_0062 +bookshelf_0063 +bookshelf_0064 +bookshelf_0065 +bookshelf_0066 +bookshelf_0067 +bookshelf_0068 +bookshelf_0069 +bookshelf_0070 +bookshelf_0071 +bookshelf_0072 +bookshelf_0073 +bookshelf_0074 +bookshelf_0075 +bookshelf_0076 +bookshelf_0077 +bookshelf_0078 +bookshelf_0079 +bookshelf_0080 +bookshelf_0081 +bookshelf_0082 +bookshelf_0083 +bookshelf_0084 +bookshelf_0085 +bookshelf_0086 +bookshelf_0087 +bookshelf_0088 +bookshelf_0089 +bookshelf_0090 +bookshelf_0091 +bookshelf_0092 +bookshelf_0093 +bookshelf_0094 +bookshelf_0095 +bookshelf_0096 +bookshelf_0097 +bookshelf_0098 +bookshelf_0099 +bookshelf_0100 +bookshelf_0101 +bookshelf_0102 +bookshelf_0103 +bookshelf_0104 +bookshelf_0105 +bookshelf_0106 +bookshelf_0107 +bookshelf_0108 +bookshelf_0109 +bookshelf_0110 +bookshelf_0111 +bookshelf_0112 +bookshelf_0113 +bookshelf_0114 +bookshelf_0115 +bookshelf_0116 +bookshelf_0117 +bookshelf_0118 +bookshelf_0119 +bookshelf_0120 +bookshelf_0121 +bookshelf_0122 +bookshelf_0123 +bookshelf_0124 +bookshelf_0125 +bookshelf_0126 +bookshelf_0127 +bookshelf_0128 +bookshelf_0129 +bookshelf_0130 +bookshelf_0131 +bookshelf_0132 +bookshelf_0133 +bookshelf_0134 +bookshelf_0135 +bookshelf_0136 +bookshelf_0137 +bookshelf_0138 +bookshelf_0139 +bookshelf_0140 +bookshelf_0141 +bookshelf_0142 +bookshelf_0143 +bookshelf_0144 +bookshelf_0145 +bookshelf_0146 +bookshelf_0147 +bookshelf_0148 +bookshelf_0149 +bookshelf_0150 +bookshelf_0151 +bookshelf_0152 +bookshelf_0153 +bookshelf_0154 +bookshelf_0155 +bookshelf_0156 +bookshelf_0157 +bookshelf_0158 +bookshelf_0159 +bookshelf_0160 +bookshelf_0161 +bookshelf_0162 +bookshelf_0163 +bookshelf_0164 +bookshelf_0165 +bookshelf_0166 +bookshelf_0167 +bookshelf_0168 +bookshelf_0169 +bookshelf_0170 +bookshelf_0171 +bookshelf_0172 +bookshelf_0173 +bookshelf_0174 +bookshelf_0175 +bookshelf_0176 +bookshelf_0177 +bookshelf_0178 +bookshelf_0179 +bookshelf_0180 +bookshelf_0181 +bookshelf_0182 +bookshelf_0183 +bookshelf_0184 +bookshelf_0185 +bookshelf_0186 +bookshelf_0187 +bookshelf_0188 +bookshelf_0189 +bookshelf_0190 +bookshelf_0191 +bookshelf_0192 +bookshelf_0193 +bookshelf_0194 +bookshelf_0195 +bookshelf_0196 +bookshelf_0197 +bookshelf_0198 +bookshelf_0199 +bookshelf_0200 +bookshelf_0201 +bookshelf_0202 +bookshelf_0203 +bookshelf_0204 +bookshelf_0205 +bookshelf_0206 +bookshelf_0207 +bookshelf_0208 +bookshelf_0209 +bookshelf_0210 +bookshelf_0211 +bookshelf_0212 +bookshelf_0213 +bookshelf_0214 +bookshelf_0215 +bookshelf_0216 +bookshelf_0217 +bookshelf_0218 +bookshelf_0219 +bookshelf_0220 +bookshelf_0221 +bookshelf_0222 +bookshelf_0223 +bookshelf_0224 +bookshelf_0225 +bookshelf_0226 +bookshelf_0227 +bookshelf_0228 +bookshelf_0229 +bookshelf_0230 +bookshelf_0231 +bookshelf_0232 +bookshelf_0233 +bookshelf_0234 +bookshelf_0235 +bookshelf_0236 +bookshelf_0237 +bookshelf_0238 +bookshelf_0239 +bookshelf_0240 +bookshelf_0241 +bookshelf_0242 +bookshelf_0243 +bookshelf_0244 +bookshelf_0245 +bookshelf_0246 +bookshelf_0247 +bookshelf_0248 +bookshelf_0249 +bookshelf_0250 +bookshelf_0251 +bookshelf_0252 +bookshelf_0253 +bookshelf_0254 +bookshelf_0255 +bookshelf_0256 +bookshelf_0257 +bookshelf_0258 +bookshelf_0259 +bookshelf_0260 +bookshelf_0261 +bookshelf_0262 +bookshelf_0263 +bookshelf_0264 +bookshelf_0265 +bookshelf_0266 +bookshelf_0267 +bookshelf_0268 +bookshelf_0269 +bookshelf_0270 +bookshelf_0271 +bookshelf_0272 +bookshelf_0273 +bookshelf_0274 +bookshelf_0275 +bookshelf_0276 +bookshelf_0277 +bookshelf_0278 +bookshelf_0279 +bookshelf_0280 +bookshelf_0281 +bookshelf_0282 +bookshelf_0283 +bookshelf_0284 +bookshelf_0285 +bookshelf_0286 +bookshelf_0287 +bookshelf_0288 +bookshelf_0289 +bookshelf_0290 +bookshelf_0291 +bookshelf_0292 +bookshelf_0293 +bookshelf_0294 +bookshelf_0295 +bookshelf_0296 +bookshelf_0297 +bookshelf_0298 +bookshelf_0299 +bookshelf_0300 +bookshelf_0301 +bookshelf_0302 +bookshelf_0303 +bookshelf_0304 +bookshelf_0305 +bookshelf_0306 +bookshelf_0307 +bookshelf_0308 +bookshelf_0309 +bookshelf_0310 +bookshelf_0311 +bookshelf_0312 +bookshelf_0313 +bookshelf_0314 +bookshelf_0315 +bookshelf_0316 +bookshelf_0317 +bookshelf_0318 +bookshelf_0319 +bookshelf_0320 +bookshelf_0321 +bookshelf_0322 +bookshelf_0323 +bookshelf_0324 +bookshelf_0325 +bookshelf_0326 +bookshelf_0327 +bookshelf_0328 +bookshelf_0329 +bookshelf_0330 +bookshelf_0331 +bookshelf_0332 +bookshelf_0333 +bookshelf_0334 +bookshelf_0335 +bookshelf_0336 +bookshelf_0337 +bookshelf_0338 +bookshelf_0339 +bookshelf_0340 +bookshelf_0341 +bookshelf_0342 +bookshelf_0343 +bookshelf_0344 +bookshelf_0345 +bookshelf_0346 +bookshelf_0347 +bookshelf_0348 +bookshelf_0349 +bookshelf_0350 +bookshelf_0351 +bookshelf_0352 +bookshelf_0353 +bookshelf_0354 +bookshelf_0355 +bookshelf_0356 +bookshelf_0357 +bookshelf_0358 +bookshelf_0359 +bookshelf_0360 +bookshelf_0361 +bookshelf_0362 +bookshelf_0363 +bookshelf_0364 +bookshelf_0365 +bookshelf_0366 +bookshelf_0367 +bookshelf_0368 +bookshelf_0369 +bookshelf_0370 +bookshelf_0371 +bookshelf_0372 +bookshelf_0373 +bookshelf_0374 +bookshelf_0375 +bookshelf_0376 +bookshelf_0377 +bookshelf_0378 +bookshelf_0379 +bookshelf_0380 +bookshelf_0381 +bookshelf_0382 +bookshelf_0383 +bookshelf_0384 +bookshelf_0385 +bookshelf_0386 +bookshelf_0387 +bookshelf_0388 +bookshelf_0389 +bookshelf_0390 +bookshelf_0391 +bookshelf_0392 +bookshelf_0393 +bookshelf_0394 +bookshelf_0395 +bookshelf_0396 +bookshelf_0397 +bookshelf_0398 +bookshelf_0399 +bookshelf_0400 +bookshelf_0401 +bookshelf_0402 +bookshelf_0403 +bookshelf_0404 +bookshelf_0405 +bookshelf_0406 +bookshelf_0407 +bookshelf_0408 +bookshelf_0409 +bookshelf_0410 +bookshelf_0411 +bookshelf_0412 +bookshelf_0413 +bookshelf_0414 +bookshelf_0415 +bookshelf_0416 +bookshelf_0417 +bookshelf_0418 +bookshelf_0419 +bookshelf_0420 +bookshelf_0421 +bookshelf_0422 +bookshelf_0423 +bookshelf_0424 +bookshelf_0425 +bookshelf_0426 +bookshelf_0427 +bookshelf_0428 +bookshelf_0429 +bookshelf_0430 +bookshelf_0431 +bookshelf_0432 +bookshelf_0433 +bookshelf_0434 +bookshelf_0435 +bookshelf_0436 +bookshelf_0437 +bookshelf_0438 +bookshelf_0439 +bookshelf_0440 +bookshelf_0441 +bookshelf_0442 +bookshelf_0443 +bookshelf_0444 +bookshelf_0445 +bookshelf_0446 +bookshelf_0447 +bookshelf_0448 +bookshelf_0449 +bookshelf_0450 +bookshelf_0451 +bookshelf_0452 +bookshelf_0453 +bookshelf_0454 +bookshelf_0455 +bookshelf_0456 +bookshelf_0457 +bookshelf_0458 +bookshelf_0459 +bookshelf_0460 +bookshelf_0461 +bookshelf_0462 +bookshelf_0463 +bookshelf_0464 +bookshelf_0465 +bookshelf_0466 +bookshelf_0467 +bookshelf_0468 +bookshelf_0469 +bookshelf_0470 +bookshelf_0471 +bookshelf_0472 +bookshelf_0473 +bookshelf_0474 +bookshelf_0475 +bookshelf_0476 +bookshelf_0477 +bookshelf_0478 +bookshelf_0479 +bookshelf_0480 +bookshelf_0481 +bookshelf_0482 +bookshelf_0483 +bookshelf_0484 +bookshelf_0485 +bookshelf_0486 +bookshelf_0487 +bookshelf_0488 +bookshelf_0489 +bookshelf_0490 +bookshelf_0491 +bookshelf_0492 +bookshelf_0493 +bookshelf_0494 +bookshelf_0495 +bookshelf_0496 +bookshelf_0497 +bookshelf_0498 +bookshelf_0499 +bookshelf_0500 +bookshelf_0501 +bookshelf_0502 +bookshelf_0503 +bookshelf_0504 +bookshelf_0505 +bookshelf_0506 +bookshelf_0507 +bookshelf_0508 +bookshelf_0509 +bookshelf_0510 +bookshelf_0511 +bookshelf_0512 +bookshelf_0513 +bookshelf_0514 +bookshelf_0515 +bookshelf_0516 +bookshelf_0517 +bookshelf_0518 +bookshelf_0519 +bookshelf_0520 +bookshelf_0521 +bookshelf_0522 +bookshelf_0523 +bookshelf_0524 +bookshelf_0525 +bookshelf_0526 +bookshelf_0527 +bookshelf_0528 +bookshelf_0529 +bookshelf_0530 +bookshelf_0531 +bookshelf_0532 +bookshelf_0533 +bookshelf_0534 +bookshelf_0535 +bookshelf_0536 +bookshelf_0537 +bookshelf_0538 +bookshelf_0539 +bookshelf_0540 +bookshelf_0541 +bookshelf_0542 +bookshelf_0543 +bookshelf_0544 +bookshelf_0545 +bookshelf_0546 +bookshelf_0547 +bookshelf_0548 +bookshelf_0549 +bookshelf_0550 +bookshelf_0551 +bookshelf_0552 +bookshelf_0553 +bookshelf_0554 +bookshelf_0555 +bookshelf_0556 +bookshelf_0557 +bookshelf_0558 +bookshelf_0559 +bookshelf_0560 +bookshelf_0561 +bookshelf_0562 +bookshelf_0563 +bookshelf_0564 +bookshelf_0565 +bookshelf_0566 +bookshelf_0567 +bookshelf_0568 +bookshelf_0569 +bookshelf_0570 +bookshelf_0571 +bookshelf_0572 +bottle_0001 +bottle_0002 +bottle_0003 +bottle_0004 +bottle_0005 +bottle_0006 +bottle_0007 +bottle_0008 +bottle_0009 +bottle_0010 +bottle_0011 +bottle_0012 +bottle_0013 +bottle_0014 +bottle_0015 +bottle_0016 +bottle_0017 +bottle_0018 +bottle_0019 +bottle_0020 +bottle_0021 +bottle_0022 +bottle_0023 +bottle_0024 +bottle_0025 +bottle_0026 +bottle_0027 +bottle_0028 +bottle_0029 +bottle_0030 +bottle_0031 +bottle_0032 +bottle_0033 +bottle_0034 +bottle_0035 +bottle_0036 +bottle_0037 +bottle_0038 +bottle_0039 +bottle_0040 +bottle_0041 +bottle_0042 +bottle_0043 +bottle_0044 +bottle_0045 +bottle_0046 +bottle_0047 +bottle_0048 +bottle_0049 +bottle_0050 +bottle_0051 +bottle_0052 +bottle_0053 +bottle_0054 +bottle_0055 +bottle_0056 +bottle_0057 +bottle_0058 +bottle_0059 +bottle_0060 +bottle_0061 +bottle_0062 +bottle_0063 +bottle_0064 +bottle_0065 +bottle_0066 +bottle_0067 +bottle_0068 +bottle_0069 +bottle_0070 +bottle_0071 +bottle_0072 +bottle_0073 +bottle_0074 +bottle_0075 +bottle_0076 +bottle_0077 +bottle_0078 +bottle_0079 +bottle_0080 +bottle_0081 +bottle_0082 +bottle_0083 +bottle_0084 +bottle_0085 +bottle_0086 +bottle_0087 +bottle_0088 +bottle_0089 +bottle_0090 +bottle_0091 +bottle_0092 +bottle_0093 +bottle_0094 +bottle_0095 +bottle_0096 +bottle_0097 +bottle_0098 +bottle_0099 +bottle_0100 +bottle_0101 +bottle_0102 +bottle_0103 +bottle_0104 +bottle_0105 +bottle_0106 +bottle_0107 +bottle_0108 +bottle_0109 +bottle_0110 +bottle_0111 +bottle_0112 +bottle_0113 +bottle_0114 +bottle_0115 +bottle_0116 +bottle_0117 +bottle_0118 +bottle_0119 +bottle_0120 +bottle_0121 +bottle_0122 +bottle_0123 +bottle_0124 +bottle_0125 +bottle_0126 +bottle_0127 +bottle_0128 +bottle_0129 +bottle_0130 +bottle_0131 +bottle_0132 +bottle_0133 +bottle_0134 +bottle_0135 +bottle_0136 +bottle_0137 +bottle_0138 +bottle_0139 +bottle_0140 +bottle_0141 +bottle_0142 +bottle_0143 +bottle_0144 +bottle_0145 +bottle_0146 +bottle_0147 +bottle_0148 +bottle_0149 +bottle_0150 +bottle_0151 +bottle_0152 +bottle_0153 +bottle_0154 +bottle_0155 +bottle_0156 +bottle_0157 +bottle_0158 +bottle_0159 +bottle_0160 +bottle_0161 +bottle_0162 +bottle_0163 +bottle_0164 +bottle_0165 +bottle_0166 +bottle_0167 +bottle_0168 +bottle_0169 +bottle_0170 +bottle_0171 +bottle_0172 +bottle_0173 +bottle_0174 +bottle_0175 +bottle_0176 +bottle_0177 +bottle_0178 +bottle_0179 +bottle_0180 +bottle_0181 +bottle_0182 +bottle_0183 +bottle_0184 +bottle_0185 +bottle_0186 +bottle_0187 +bottle_0188 +bottle_0189 +bottle_0190 +bottle_0191 +bottle_0192 +bottle_0193 +bottle_0194 +bottle_0195 +bottle_0196 +bottle_0197 +bottle_0198 +bottle_0199 +bottle_0200 +bottle_0201 +bottle_0202 +bottle_0203 +bottle_0204 +bottle_0205 +bottle_0206 +bottle_0207 +bottle_0208 +bottle_0209 +bottle_0210 +bottle_0211 +bottle_0212 +bottle_0213 +bottle_0214 +bottle_0215 +bottle_0216 +bottle_0217 +bottle_0218 +bottle_0219 +bottle_0220 +bottle_0221 +bottle_0222 +bottle_0223 +bottle_0224 +bottle_0225 +bottle_0226 +bottle_0227 +bottle_0228 +bottle_0229 +bottle_0230 +bottle_0231 +bottle_0232 +bottle_0233 +bottle_0234 +bottle_0235 +bottle_0236 +bottle_0237 +bottle_0238 +bottle_0239 +bottle_0240 +bottle_0241 +bottle_0242 +bottle_0243 +bottle_0244 +bottle_0245 +bottle_0246 +bottle_0247 +bottle_0248 +bottle_0249 +bottle_0250 +bottle_0251 +bottle_0252 +bottle_0253 +bottle_0254 +bottle_0255 +bottle_0256 +bottle_0257 +bottle_0258 +bottle_0259 +bottle_0260 +bottle_0261 +bottle_0262 +bottle_0263 +bottle_0264 +bottle_0265 +bottle_0266 +bottle_0267 +bottle_0268 +bottle_0269 +bottle_0270 +bottle_0271 +bottle_0272 +bottle_0273 +bottle_0274 +bottle_0275 +bottle_0276 +bottle_0277 +bottle_0278 +bottle_0279 +bottle_0280 +bottle_0281 +bottle_0282 +bottle_0283 +bottle_0284 +bottle_0285 +bottle_0286 +bottle_0287 +bottle_0288 +bottle_0289 +bottle_0290 +bottle_0291 +bottle_0292 +bottle_0293 +bottle_0294 +bottle_0295 +bottle_0296 +bottle_0297 +bottle_0298 +bottle_0299 +bottle_0300 +bottle_0301 +bottle_0302 +bottle_0303 +bottle_0304 +bottle_0305 +bottle_0306 +bottle_0307 +bottle_0308 +bottle_0309 +bottle_0310 +bottle_0311 +bottle_0312 +bottle_0313 +bottle_0314 +bottle_0315 +bottle_0316 +bottle_0317 +bottle_0318 +bottle_0319 +bottle_0320 +bottle_0321 +bottle_0322 +bottle_0323 +bottle_0324 +bottle_0325 +bottle_0326 +bottle_0327 +bottle_0328 +bottle_0329 +bottle_0330 +bottle_0331 +bottle_0332 +bottle_0333 +bottle_0334 +bottle_0335 +bowl_0001 +bowl_0002 +bowl_0003 +bowl_0004 +bowl_0005 +bowl_0006 +bowl_0007 +bowl_0008 +bowl_0009 +bowl_0010 +bowl_0011 +bowl_0012 +bowl_0013 +bowl_0014 +bowl_0015 +bowl_0016 +bowl_0017 +bowl_0018 +bowl_0019 +bowl_0020 +bowl_0021 +bowl_0022 +bowl_0023 +bowl_0024 +bowl_0025 +bowl_0026 +bowl_0027 +bowl_0028 +bowl_0029 +bowl_0030 +bowl_0031 +bowl_0032 +bowl_0033 +bowl_0034 +bowl_0035 +bowl_0036 +bowl_0037 +bowl_0038 +bowl_0039 +bowl_0040 +bowl_0041 +bowl_0042 +bowl_0043 +bowl_0044 +bowl_0045 +bowl_0046 +bowl_0047 +bowl_0048 +bowl_0049 +bowl_0050 +bowl_0051 +bowl_0052 +bowl_0053 +bowl_0054 +bowl_0055 +bowl_0056 +bowl_0057 +bowl_0058 +bowl_0059 +bowl_0060 +bowl_0061 +bowl_0062 +bowl_0063 +bowl_0064 +car_0001 +car_0002 +car_0003 +car_0004 +car_0005 +car_0006 +car_0007 +car_0008 +car_0009 +car_0010 +car_0011 +car_0012 +car_0013 +car_0014 +car_0015 +car_0016 +car_0017 +car_0018 +car_0019 +car_0020 +car_0021 +car_0022 +car_0023 +car_0024 +car_0025 +car_0026 +car_0027 +car_0028 +car_0029 +car_0030 +car_0031 +car_0032 +car_0033 +car_0034 +car_0035 +car_0036 +car_0037 +car_0038 +car_0039 +car_0040 +car_0041 +car_0042 +car_0043 +car_0044 +car_0045 +car_0046 +car_0047 +car_0048 +car_0049 +car_0050 +car_0051 +car_0052 +car_0053 +car_0054 +car_0055 +car_0056 +car_0057 +car_0058 +car_0059 +car_0060 +car_0061 +car_0062 +car_0063 +car_0064 +car_0065 +car_0066 +car_0067 +car_0068 +car_0069 +car_0070 +car_0071 +car_0072 +car_0073 +car_0074 +car_0075 +car_0076 +car_0077 +car_0078 +car_0079 +car_0080 +car_0081 +car_0082 +car_0083 +car_0084 +car_0085 +car_0086 +car_0087 +car_0088 +car_0089 +car_0090 +car_0091 +car_0092 +car_0093 +car_0094 +car_0095 +car_0096 +car_0097 +car_0098 +car_0099 +car_0100 +car_0101 +car_0102 +car_0103 +car_0104 +car_0105 +car_0106 +car_0107 +car_0108 +car_0109 +car_0110 +car_0111 +car_0112 +car_0113 +car_0114 +car_0115 +car_0116 +car_0117 +car_0118 +car_0119 +car_0120 +car_0121 +car_0122 +car_0123 +car_0124 +car_0125 +car_0126 +car_0127 +car_0128 +car_0129 +car_0130 +car_0131 +car_0132 +car_0133 +car_0134 +car_0135 +car_0136 +car_0137 +car_0138 +car_0139 +car_0140 +car_0141 +car_0142 +car_0143 +car_0144 +car_0145 +car_0146 +car_0147 +car_0148 +car_0149 +car_0150 +car_0151 +car_0152 +car_0153 +car_0154 +car_0155 +car_0156 +car_0157 +car_0158 +car_0159 +car_0160 +car_0161 +car_0162 +car_0163 +car_0164 +car_0165 +car_0166 +car_0167 +car_0168 +car_0169 +car_0170 +car_0171 +car_0172 +car_0173 +car_0174 +car_0175 +car_0176 +car_0177 +car_0178 +car_0179 +car_0180 +car_0181 +car_0182 +car_0183 +car_0184 +car_0185 +car_0186 +car_0187 +car_0188 +car_0189 +car_0190 +car_0191 +car_0192 +car_0193 +car_0194 +car_0195 +car_0196 +car_0197 +chair_0001 +chair_0002 +chair_0003 +chair_0004 +chair_0005 +chair_0006 +chair_0007 +chair_0008 +chair_0009 +chair_0010 +chair_0011 +chair_0012 +chair_0013 +chair_0014 +chair_0015 +chair_0016 +chair_0017 +chair_0018 +chair_0019 +chair_0020 +chair_0021 +chair_0022 +chair_0023 +chair_0024 +chair_0025 +chair_0026 +chair_0027 +chair_0028 +chair_0029 +chair_0030 +chair_0031 +chair_0032 +chair_0033 +chair_0034 +chair_0035 +chair_0036 +chair_0037 +chair_0038 +chair_0039 +chair_0040 +chair_0041 +chair_0042 +chair_0043 +chair_0044 +chair_0045 +chair_0046 +chair_0047 +chair_0048 +chair_0049 +chair_0050 +chair_0051 +chair_0052 +chair_0053 +chair_0054 +chair_0055 +chair_0056 +chair_0057 +chair_0058 +chair_0059 +chair_0060 +chair_0061 +chair_0062 +chair_0063 +chair_0064 +chair_0065 +chair_0066 +chair_0067 +chair_0068 +chair_0069 +chair_0070 +chair_0071 +chair_0072 +chair_0073 +chair_0074 +chair_0075 +chair_0076 +chair_0077 +chair_0078 +chair_0079 +chair_0080 +chair_0081 +chair_0082 +chair_0083 +chair_0084 +chair_0085 +chair_0086 +chair_0087 +chair_0088 +chair_0089 +chair_0090 +chair_0091 +chair_0092 +chair_0093 +chair_0094 +chair_0095 +chair_0096 +chair_0097 +chair_0098 +chair_0099 +chair_0100 +chair_0101 +chair_0102 +chair_0103 +chair_0104 +chair_0105 +chair_0106 +chair_0107 +chair_0108 +chair_0109 +chair_0110 +chair_0111 +chair_0112 +chair_0113 +chair_0114 +chair_0115 +chair_0116 +chair_0117 +chair_0118 +chair_0119 +chair_0120 +chair_0121 +chair_0122 +chair_0123 +chair_0124 +chair_0125 +chair_0126 +chair_0127 +chair_0128 +chair_0129 +chair_0130 +chair_0131 +chair_0132 +chair_0133 +chair_0134 +chair_0135 +chair_0136 +chair_0137 +chair_0138 +chair_0139 +chair_0140 +chair_0141 +chair_0142 +chair_0143 +chair_0144 +chair_0145 +chair_0146 +chair_0147 +chair_0148 +chair_0149 +chair_0150 +chair_0151 +chair_0152 +chair_0153 +chair_0154 +chair_0155 +chair_0156 +chair_0157 +chair_0158 +chair_0159 +chair_0160 +chair_0161 +chair_0162 +chair_0163 +chair_0164 +chair_0165 +chair_0166 +chair_0167 +chair_0168 +chair_0169 +chair_0170 +chair_0171 +chair_0172 +chair_0173 +chair_0174 +chair_0175 +chair_0176 +chair_0177 +chair_0178 +chair_0179 +chair_0180 +chair_0181 +chair_0182 +chair_0183 +chair_0184 +chair_0185 +chair_0186 +chair_0187 +chair_0188 +chair_0189 +chair_0190 +chair_0191 +chair_0192 +chair_0193 +chair_0194 +chair_0195 +chair_0196 +chair_0197 +chair_0198 +chair_0199 +chair_0200 +chair_0201 +chair_0202 +chair_0203 +chair_0204 +chair_0205 +chair_0206 +chair_0207 +chair_0208 +chair_0209 +chair_0210 +chair_0211 +chair_0212 +chair_0213 +chair_0214 +chair_0215 +chair_0216 +chair_0217 +chair_0218 +chair_0219 +chair_0220 +chair_0221 +chair_0222 +chair_0223 +chair_0224 +chair_0225 +chair_0226 +chair_0227 +chair_0228 +chair_0229 +chair_0230 +chair_0231 +chair_0232 +chair_0233 +chair_0234 +chair_0235 +chair_0236 +chair_0237 +chair_0238 +chair_0239 +chair_0240 +chair_0241 +chair_0242 +chair_0243 +chair_0244 +chair_0245 +chair_0246 +chair_0247 +chair_0248 +chair_0249 +chair_0250 +chair_0251 +chair_0252 +chair_0253 +chair_0254 +chair_0255 +chair_0256 +chair_0257 +chair_0258 +chair_0259 +chair_0260 +chair_0261 +chair_0262 +chair_0263 +chair_0264 +chair_0265 +chair_0266 +chair_0267 +chair_0268 +chair_0269 +chair_0270 +chair_0271 +chair_0272 +chair_0273 +chair_0274 +chair_0275 +chair_0276 +chair_0277 +chair_0278 +chair_0279 +chair_0280 +chair_0281 +chair_0282 +chair_0283 +chair_0284 +chair_0285 +chair_0286 +chair_0287 +chair_0288 +chair_0289 +chair_0290 +chair_0291 +chair_0292 +chair_0293 +chair_0294 +chair_0295 +chair_0296 +chair_0297 +chair_0298 +chair_0299 +chair_0300 +chair_0301 +chair_0302 +chair_0303 +chair_0304 +chair_0305 +chair_0306 +chair_0307 +chair_0308 +chair_0309 +chair_0310 +chair_0311 +chair_0312 +chair_0313 +chair_0314 +chair_0315 +chair_0316 +chair_0317 +chair_0318 +chair_0319 +chair_0320 +chair_0321 +chair_0322 +chair_0323 +chair_0324 +chair_0325 +chair_0326 +chair_0327 +chair_0328 +chair_0329 +chair_0330 +chair_0331 +chair_0332 +chair_0333 +chair_0334 +chair_0335 +chair_0336 +chair_0337 +chair_0338 +chair_0339 +chair_0340 +chair_0341 +chair_0342 +chair_0343 +chair_0344 +chair_0345 +chair_0346 +chair_0347 +chair_0348 +chair_0349 +chair_0350 +chair_0351 +chair_0352 +chair_0353 +chair_0354 +chair_0355 +chair_0356 +chair_0357 +chair_0358 +chair_0359 +chair_0360 +chair_0361 +chair_0362 +chair_0363 +chair_0364 +chair_0365 +chair_0366 +chair_0367 +chair_0368 +chair_0369 +chair_0370 +chair_0371 +chair_0372 +chair_0373 +chair_0374 +chair_0375 +chair_0376 +chair_0377 +chair_0378 +chair_0379 +chair_0380 +chair_0381 +chair_0382 +chair_0383 +chair_0384 +chair_0385 +chair_0386 +chair_0387 +chair_0388 +chair_0389 +chair_0390 +chair_0391 +chair_0392 +chair_0393 +chair_0394 +chair_0395 +chair_0396 +chair_0397 +chair_0398 +chair_0399 +chair_0400 +chair_0401 +chair_0402 +chair_0403 +chair_0404 +chair_0405 +chair_0406 +chair_0407 +chair_0408 +chair_0409 +chair_0410 +chair_0411 +chair_0412 +chair_0413 +chair_0414 +chair_0415 +chair_0416 +chair_0417 +chair_0418 +chair_0419 +chair_0420 +chair_0421 +chair_0422 +chair_0423 +chair_0424 +chair_0425 +chair_0426 +chair_0427 +chair_0428 +chair_0429 +chair_0430 +chair_0431 +chair_0432 +chair_0433 +chair_0434 +chair_0435 +chair_0436 +chair_0437 +chair_0438 +chair_0439 +chair_0440 +chair_0441 +chair_0442 +chair_0443 +chair_0444 +chair_0445 +chair_0446 +chair_0447 +chair_0448 +chair_0449 +chair_0450 +chair_0451 +chair_0452 +chair_0453 +chair_0454 +chair_0455 +chair_0456 +chair_0457 +chair_0458 +chair_0459 +chair_0460 +chair_0461 +chair_0462 +chair_0463 +chair_0464 +chair_0465 +chair_0466 +chair_0467 +chair_0468 +chair_0469 +chair_0470 +chair_0471 +chair_0472 +chair_0473 +chair_0474 +chair_0475 +chair_0476 +chair_0477 +chair_0478 +chair_0479 +chair_0480 +chair_0481 +chair_0482 +chair_0483 +chair_0484 +chair_0485 +chair_0486 +chair_0487 +chair_0488 +chair_0489 +chair_0490 +chair_0491 +chair_0492 +chair_0493 +chair_0494 +chair_0495 +chair_0496 +chair_0497 +chair_0498 +chair_0499 +chair_0500 +chair_0501 +chair_0502 +chair_0503 +chair_0504 +chair_0505 +chair_0506 +chair_0507 +chair_0508 +chair_0509 +chair_0510 +chair_0511 +chair_0512 +chair_0513 +chair_0514 +chair_0515 +chair_0516 +chair_0517 +chair_0518 +chair_0519 +chair_0520 +chair_0521 +chair_0522 +chair_0523 +chair_0524 +chair_0525 +chair_0526 +chair_0527 +chair_0528 +chair_0529 +chair_0530 +chair_0531 +chair_0532 +chair_0533 +chair_0534 +chair_0535 +chair_0536 +chair_0537 +chair_0538 +chair_0539 +chair_0540 +chair_0541 +chair_0542 +chair_0543 +chair_0544 +chair_0545 +chair_0546 +chair_0547 +chair_0548 +chair_0549 +chair_0550 +chair_0551 +chair_0552 +chair_0553 +chair_0554 +chair_0555 +chair_0556 +chair_0557 +chair_0558 +chair_0559 +chair_0560 +chair_0561 +chair_0562 +chair_0563 +chair_0564 +chair_0565 +chair_0566 +chair_0567 +chair_0568 +chair_0569 +chair_0570 +chair_0571 +chair_0572 +chair_0573 +chair_0574 +chair_0575 +chair_0576 +chair_0577 +chair_0578 +chair_0579 +chair_0580 +chair_0581 +chair_0582 +chair_0583 +chair_0584 +chair_0585 +chair_0586 +chair_0587 +chair_0588 +chair_0589 +chair_0590 +chair_0591 +chair_0592 +chair_0593 +chair_0594 +chair_0595 +chair_0596 +chair_0597 +chair_0598 +chair_0599 +chair_0600 +chair_0601 +chair_0602 +chair_0603 +chair_0604 +chair_0605 +chair_0606 +chair_0607 +chair_0608 +chair_0609 +chair_0610 +chair_0611 +chair_0612 +chair_0613 +chair_0614 +chair_0615 +chair_0616 +chair_0617 +chair_0618 +chair_0619 +chair_0620 +chair_0621 +chair_0622 +chair_0623 +chair_0624 +chair_0625 +chair_0626 +chair_0627 +chair_0628 +chair_0629 +chair_0630 +chair_0631 +chair_0632 +chair_0633 +chair_0634 +chair_0635 +chair_0636 +chair_0637 +chair_0638 +chair_0639 +chair_0640 +chair_0641 +chair_0642 +chair_0643 +chair_0644 +chair_0645 +chair_0646 +chair_0647 +chair_0648 +chair_0649 +chair_0650 +chair_0651 +chair_0652 +chair_0653 +chair_0654 +chair_0655 +chair_0656 +chair_0657 +chair_0658 +chair_0659 +chair_0660 +chair_0661 +chair_0662 +chair_0663 +chair_0664 +chair_0665 +chair_0666 +chair_0667 +chair_0668 +chair_0669 +chair_0670 +chair_0671 +chair_0672 +chair_0673 +chair_0674 +chair_0675 +chair_0676 +chair_0677 +chair_0678 +chair_0679 +chair_0680 +chair_0681 +chair_0682 +chair_0683 +chair_0684 +chair_0685 +chair_0686 +chair_0687 +chair_0688 +chair_0689 +chair_0690 +chair_0691 +chair_0692 +chair_0693 +chair_0694 +chair_0695 +chair_0696 +chair_0697 +chair_0698 +chair_0699 +chair_0700 +chair_0701 +chair_0702 +chair_0703 +chair_0704 +chair_0705 +chair_0706 +chair_0707 +chair_0708 +chair_0709 +chair_0710 +chair_0711 +chair_0712 +chair_0713 +chair_0714 +chair_0715 +chair_0716 +chair_0717 +chair_0718 +chair_0719 +chair_0720 +chair_0721 +chair_0722 +chair_0723 +chair_0724 +chair_0725 +chair_0726 +chair_0727 +chair_0728 +chair_0729 +chair_0730 +chair_0731 +chair_0732 +chair_0733 +chair_0734 +chair_0735 +chair_0736 +chair_0737 +chair_0738 +chair_0739 +chair_0740 +chair_0741 +chair_0742 +chair_0743 +chair_0744 +chair_0745 +chair_0746 +chair_0747 +chair_0748 +chair_0749 +chair_0750 +chair_0751 +chair_0752 +chair_0753 +chair_0754 +chair_0755 +chair_0756 +chair_0757 +chair_0758 +chair_0759 +chair_0760 +chair_0761 +chair_0762 +chair_0763 +chair_0764 +chair_0765 +chair_0766 +chair_0767 +chair_0768 +chair_0769 +chair_0770 +chair_0771 +chair_0772 +chair_0773 +chair_0774 +chair_0775 +chair_0776 +chair_0777 +chair_0778 +chair_0779 +chair_0780 +chair_0781 +chair_0782 +chair_0783 +chair_0784 +chair_0785 +chair_0786 +chair_0787 +chair_0788 +chair_0789 +chair_0790 +chair_0791 +chair_0792 +chair_0793 +chair_0794 +chair_0795 +chair_0796 +chair_0797 +chair_0798 +chair_0799 +chair_0800 +chair_0801 +chair_0802 +chair_0803 +chair_0804 +chair_0805 +chair_0806 +chair_0807 +chair_0808 +chair_0809 +chair_0810 +chair_0811 +chair_0812 +chair_0813 +chair_0814 +chair_0815 +chair_0816 +chair_0817 +chair_0818 +chair_0819 +chair_0820 +chair_0821 +chair_0822 +chair_0823 +chair_0824 +chair_0825 +chair_0826 +chair_0827 +chair_0828 +chair_0829 +chair_0830 +chair_0831 +chair_0832 +chair_0833 +chair_0834 +chair_0835 +chair_0836 +chair_0837 +chair_0838 +chair_0839 +chair_0840 +chair_0841 +chair_0842 +chair_0843 +chair_0844 +chair_0845 +chair_0846 +chair_0847 +chair_0848 +chair_0849 +chair_0850 +chair_0851 +chair_0852 +chair_0853 +chair_0854 +chair_0855 +chair_0856 +chair_0857 +chair_0858 +chair_0859 +chair_0860 +chair_0861 +chair_0862 +chair_0863 +chair_0864 +chair_0865 +chair_0866 +chair_0867 +chair_0868 +chair_0869 +chair_0870 +chair_0871 +chair_0872 +chair_0873 +chair_0874 +chair_0875 +chair_0876 +chair_0877 +chair_0878 +chair_0879 +chair_0880 +chair_0881 +chair_0882 +chair_0883 +chair_0884 +chair_0885 +chair_0886 +chair_0887 +chair_0888 +chair_0889 +cone_0001 +cone_0002 +cone_0003 +cone_0004 +cone_0005 +cone_0006 +cone_0007 +cone_0008 +cone_0009 +cone_0010 +cone_0011 +cone_0012 +cone_0013 +cone_0014 +cone_0015 +cone_0016 +cone_0017 +cone_0018 +cone_0019 +cone_0020 +cone_0021 +cone_0022 +cone_0023 +cone_0024 +cone_0025 +cone_0026 +cone_0027 +cone_0028 +cone_0029 +cone_0030 +cone_0031 +cone_0032 +cone_0033 +cone_0034 +cone_0035 +cone_0036 +cone_0037 +cone_0038 +cone_0039 +cone_0040 +cone_0041 +cone_0042 +cone_0043 +cone_0044 +cone_0045 +cone_0046 +cone_0047 +cone_0048 +cone_0049 +cone_0050 +cone_0051 +cone_0052 +cone_0053 +cone_0054 +cone_0055 +cone_0056 +cone_0057 +cone_0058 +cone_0059 +cone_0060 +cone_0061 +cone_0062 +cone_0063 +cone_0064 +cone_0065 +cone_0066 +cone_0067 +cone_0068 +cone_0069 +cone_0070 +cone_0071 +cone_0072 +cone_0073 +cone_0074 +cone_0075 +cone_0076 +cone_0077 +cone_0078 +cone_0079 +cone_0080 +cone_0081 +cone_0082 +cone_0083 +cone_0084 +cone_0085 +cone_0086 +cone_0087 +cone_0088 +cone_0089 +cone_0090 +cone_0091 +cone_0092 +cone_0093 +cone_0094 +cone_0095 +cone_0096 +cone_0097 +cone_0098 +cone_0099 +cone_0100 +cone_0101 +cone_0102 +cone_0103 +cone_0104 +cone_0105 +cone_0106 +cone_0107 +cone_0108 +cone_0109 +cone_0110 +cone_0111 +cone_0112 +cone_0113 +cone_0114 +cone_0115 +cone_0116 +cone_0117 +cone_0118 +cone_0119 +cone_0120 +cone_0121 +cone_0122 +cone_0123 +cone_0124 +cone_0125 +cone_0126 +cone_0127 +cone_0128 +cone_0129 +cone_0130 +cone_0131 +cone_0132 +cone_0133 +cone_0134 +cone_0135 +cone_0136 +cone_0137 +cone_0138 +cone_0139 +cone_0140 +cone_0141 +cone_0142 +cone_0143 +cone_0144 +cone_0145 +cone_0146 +cone_0147 +cone_0148 +cone_0149 +cone_0150 +cone_0151 +cone_0152 +cone_0153 +cone_0154 +cone_0155 +cone_0156 +cone_0157 +cone_0158 +cone_0159 +cone_0160 +cone_0161 +cone_0162 +cone_0163 +cone_0164 +cone_0165 +cone_0166 +cone_0167 +cup_0001 +cup_0002 +cup_0003 +cup_0004 +cup_0005 +cup_0006 +cup_0007 +cup_0008 +cup_0009 +cup_0010 +cup_0011 +cup_0012 +cup_0013 +cup_0014 +cup_0015 +cup_0016 +cup_0017 +cup_0018 +cup_0019 +cup_0020 +cup_0021 +cup_0022 +cup_0023 +cup_0024 +cup_0025 +cup_0026 +cup_0027 +cup_0028 +cup_0029 +cup_0030 +cup_0031 +cup_0032 +cup_0033 +cup_0034 +cup_0035 +cup_0036 +cup_0037 +cup_0038 +cup_0039 +cup_0040 +cup_0041 +cup_0042 +cup_0043 +cup_0044 +cup_0045 +cup_0046 +cup_0047 +cup_0048 +cup_0049 +cup_0050 +cup_0051 +cup_0052 +cup_0053 +cup_0054 +cup_0055 +cup_0056 +cup_0057 +cup_0058 +cup_0059 +cup_0060 +cup_0061 +cup_0062 +cup_0063 +cup_0064 +cup_0065 +cup_0066 +cup_0067 +cup_0068 +cup_0069 +cup_0070 +cup_0071 +cup_0072 +cup_0073 +cup_0074 +cup_0075 +cup_0076 +cup_0077 +cup_0078 +cup_0079 +curtain_0001 +curtain_0002 +curtain_0003 +curtain_0004 +curtain_0005 +curtain_0006 +curtain_0007 +curtain_0008 +curtain_0009 +curtain_0010 +curtain_0011 +curtain_0012 +curtain_0013 +curtain_0014 +curtain_0015 +curtain_0016 +curtain_0017 +curtain_0018 +curtain_0019 +curtain_0020 +curtain_0021 +curtain_0022 +curtain_0023 +curtain_0024 +curtain_0025 +curtain_0026 +curtain_0027 +curtain_0028 +curtain_0029 +curtain_0030 +curtain_0031 +curtain_0032 +curtain_0033 +curtain_0034 +curtain_0035 +curtain_0036 +curtain_0037 +curtain_0038 +curtain_0039 +curtain_0040 +curtain_0041 +curtain_0042 +curtain_0043 +curtain_0044 +curtain_0045 +curtain_0046 +curtain_0047 +curtain_0048 +curtain_0049 +curtain_0050 +curtain_0051 +curtain_0052 +curtain_0053 +curtain_0054 +curtain_0055 +curtain_0056 +curtain_0057 +curtain_0058 +curtain_0059 +curtain_0060 +curtain_0061 +curtain_0062 +curtain_0063 +curtain_0064 +curtain_0065 +curtain_0066 +curtain_0067 +curtain_0068 +curtain_0069 +curtain_0070 +curtain_0071 +curtain_0072 +curtain_0073 +curtain_0074 +curtain_0075 +curtain_0076 +curtain_0077 +curtain_0078 +curtain_0079 +curtain_0080 +curtain_0081 +curtain_0082 +curtain_0083 +curtain_0084 +curtain_0085 +curtain_0086 +curtain_0087 +curtain_0088 +curtain_0089 +curtain_0090 +curtain_0091 +curtain_0092 +curtain_0093 +curtain_0094 +curtain_0095 +curtain_0096 +curtain_0097 +curtain_0098 +curtain_0099 +curtain_0100 +curtain_0101 +curtain_0102 +curtain_0103 +curtain_0104 +curtain_0105 +curtain_0106 +curtain_0107 +curtain_0108 +curtain_0109 +curtain_0110 +curtain_0111 +curtain_0112 +curtain_0113 +curtain_0114 +curtain_0115 +curtain_0116 +curtain_0117 +curtain_0118 +curtain_0119 +curtain_0120 +curtain_0121 +curtain_0122 +curtain_0123 +curtain_0124 +curtain_0125 +curtain_0126 +curtain_0127 +curtain_0128 +curtain_0129 +curtain_0130 +curtain_0131 +curtain_0132 +curtain_0133 +curtain_0134 +curtain_0135 +curtain_0136 +curtain_0137 +curtain_0138 +desk_0001 +desk_0002 +desk_0003 +desk_0004 +desk_0005 +desk_0006 +desk_0007 +desk_0008 +desk_0009 +desk_0010 +desk_0011 +desk_0012 +desk_0013 +desk_0014 +desk_0015 +desk_0016 +desk_0017 +desk_0018 +desk_0019 +desk_0020 +desk_0021 +desk_0022 +desk_0023 +desk_0024 +desk_0025 +desk_0026 +desk_0027 +desk_0028 +desk_0029 +desk_0030 +desk_0031 +desk_0032 +desk_0033 +desk_0034 +desk_0035 +desk_0036 +desk_0037 +desk_0038 +desk_0039 +desk_0040 +desk_0041 +desk_0042 +desk_0043 +desk_0044 +desk_0045 +desk_0046 +desk_0047 +desk_0048 +desk_0049 +desk_0050 +desk_0051 +desk_0052 +desk_0053 +desk_0054 +desk_0055 +desk_0056 +desk_0057 +desk_0058 +desk_0059 +desk_0060 +desk_0061 +desk_0062 +desk_0063 +desk_0064 +desk_0065 +desk_0066 +desk_0067 +desk_0068 +desk_0069 +desk_0070 +desk_0071 +desk_0072 +desk_0073 +desk_0074 +desk_0075 +desk_0076 +desk_0077 +desk_0078 +desk_0079 +desk_0080 +desk_0081 +desk_0082 +desk_0083 +desk_0084 +desk_0085 +desk_0086 +desk_0087 +desk_0088 +desk_0089 +desk_0090 +desk_0091 +desk_0092 +desk_0093 +desk_0094 +desk_0095 +desk_0096 +desk_0097 +desk_0098 +desk_0099 +desk_0100 +desk_0101 +desk_0102 +desk_0103 +desk_0104 +desk_0105 +desk_0106 +desk_0107 +desk_0108 +desk_0109 +desk_0110 +desk_0111 +desk_0112 +desk_0113 +desk_0114 +desk_0115 +desk_0116 +desk_0117 +desk_0118 +desk_0119 +desk_0120 +desk_0121 +desk_0122 +desk_0123 +desk_0124 +desk_0125 +desk_0126 +desk_0127 +desk_0128 +desk_0129 +desk_0130 +desk_0131 +desk_0132 +desk_0133 +desk_0134 +desk_0135 +desk_0136 +desk_0137 +desk_0138 +desk_0139 +desk_0140 +desk_0141 +desk_0142 +desk_0143 +desk_0144 +desk_0145 +desk_0146 +desk_0147 +desk_0148 +desk_0149 +desk_0150 +desk_0151 +desk_0152 +desk_0153 +desk_0154 +desk_0155 +desk_0156 +desk_0157 +desk_0158 +desk_0159 +desk_0160 +desk_0161 +desk_0162 +desk_0163 +desk_0164 +desk_0165 +desk_0166 +desk_0167 +desk_0168 +desk_0169 +desk_0170 +desk_0171 +desk_0172 +desk_0173 +desk_0174 +desk_0175 +desk_0176 +desk_0177 +desk_0178 +desk_0179 +desk_0180 +desk_0181 +desk_0182 +desk_0183 +desk_0184 +desk_0185 +desk_0186 +desk_0187 +desk_0188 +desk_0189 +desk_0190 +desk_0191 +desk_0192 +desk_0193 +desk_0194 +desk_0195 +desk_0196 +desk_0197 +desk_0198 +desk_0199 +desk_0200 +door_0001 +door_0002 +door_0003 +door_0004 +door_0005 +door_0006 +door_0007 +door_0008 +door_0009 +door_0010 +door_0011 +door_0012 +door_0013 +door_0014 +door_0015 +door_0016 +door_0017 +door_0018 +door_0019 +door_0020 +door_0021 +door_0022 +door_0023 +door_0024 +door_0025 +door_0026 +door_0027 +door_0028 +door_0029 +door_0030 +door_0031 +door_0032 +door_0033 +door_0034 +door_0035 +door_0036 +door_0037 +door_0038 +door_0039 +door_0040 +door_0041 +door_0042 +door_0043 +door_0044 +door_0045 +door_0046 +door_0047 +door_0048 +door_0049 +door_0050 +door_0051 +door_0052 +door_0053 +door_0054 +door_0055 +door_0056 +door_0057 +door_0058 +door_0059 +door_0060 +door_0061 +door_0062 +door_0063 +door_0064 +door_0065 +door_0066 +door_0067 +door_0068 +door_0069 +door_0070 +door_0071 +door_0072 +door_0073 +door_0074 +door_0075 +door_0076 +door_0077 +door_0078 +door_0079 +door_0080 +door_0081 +door_0082 +door_0083 +door_0084 +door_0085 +door_0086 +door_0087 +door_0088 +door_0089 +door_0090 +door_0091 +door_0092 +door_0093 +door_0094 +door_0095 +door_0096 +door_0097 +door_0098 +door_0099 +door_0100 +door_0101 +door_0102 +door_0103 +door_0104 +door_0105 +door_0106 +door_0107 +door_0108 +door_0109 +dresser_0001 +dresser_0002 +dresser_0003 +dresser_0004 +dresser_0005 +dresser_0006 +dresser_0007 +dresser_0008 +dresser_0009 +dresser_0010 +dresser_0011 +dresser_0012 +dresser_0013 +dresser_0014 +dresser_0015 +dresser_0016 +dresser_0017 +dresser_0018 +dresser_0019 +dresser_0020 +dresser_0021 +dresser_0022 +dresser_0023 +dresser_0024 +dresser_0025 +dresser_0026 +dresser_0027 +dresser_0028 +dresser_0029 +dresser_0030 +dresser_0031 +dresser_0032 +dresser_0033 +dresser_0034 +dresser_0035 +dresser_0036 +dresser_0037 +dresser_0038 +dresser_0039 +dresser_0040 +dresser_0041 +dresser_0042 +dresser_0043 +dresser_0044 +dresser_0045 +dresser_0046 +dresser_0047 +dresser_0048 +dresser_0049 +dresser_0050 +dresser_0051 +dresser_0052 +dresser_0053 +dresser_0054 +dresser_0055 +dresser_0056 +dresser_0057 +dresser_0058 +dresser_0059 +dresser_0060 +dresser_0061 +dresser_0062 +dresser_0063 +dresser_0064 +dresser_0065 +dresser_0066 +dresser_0067 +dresser_0068 +dresser_0069 +dresser_0070 +dresser_0071 +dresser_0072 +dresser_0073 +dresser_0074 +dresser_0075 +dresser_0076 +dresser_0077 +dresser_0078 +dresser_0079 +dresser_0080 +dresser_0081 +dresser_0082 +dresser_0083 +dresser_0084 +dresser_0085 +dresser_0086 +dresser_0087 +dresser_0088 +dresser_0089 +dresser_0090 +dresser_0091 +dresser_0092 +dresser_0093 +dresser_0094 +dresser_0095 +dresser_0096 +dresser_0097 +dresser_0098 +dresser_0099 +dresser_0100 +dresser_0101 +dresser_0102 +dresser_0103 +dresser_0104 +dresser_0105 +dresser_0106 +dresser_0107 +dresser_0108 +dresser_0109 +dresser_0110 +dresser_0111 +dresser_0112 +dresser_0113 +dresser_0114 +dresser_0115 +dresser_0116 +dresser_0117 +dresser_0118 +dresser_0119 +dresser_0120 +dresser_0121 +dresser_0122 +dresser_0123 +dresser_0124 +dresser_0125 +dresser_0126 +dresser_0127 +dresser_0128 +dresser_0129 +dresser_0130 +dresser_0131 +dresser_0132 +dresser_0133 +dresser_0134 +dresser_0135 +dresser_0136 +dresser_0137 +dresser_0138 +dresser_0139 +dresser_0140 +dresser_0141 +dresser_0142 +dresser_0143 +dresser_0144 +dresser_0145 +dresser_0146 +dresser_0147 +dresser_0148 +dresser_0149 +dresser_0150 +dresser_0151 +dresser_0152 +dresser_0153 +dresser_0154 +dresser_0155 +dresser_0156 +dresser_0157 +dresser_0158 +dresser_0159 +dresser_0160 +dresser_0161 +dresser_0162 +dresser_0163 +dresser_0164 +dresser_0165 +dresser_0166 +dresser_0167 +dresser_0168 +dresser_0169 +dresser_0170 +dresser_0171 +dresser_0172 +dresser_0173 +dresser_0174 +dresser_0175 +dresser_0176 +dresser_0177 +dresser_0178 +dresser_0179 +dresser_0180 +dresser_0181 +dresser_0182 +dresser_0183 +dresser_0184 +dresser_0185 +dresser_0186 +dresser_0187 +dresser_0188 +dresser_0189 +dresser_0190 +dresser_0191 +dresser_0192 +dresser_0193 +dresser_0194 +dresser_0195 +dresser_0196 +dresser_0197 +dresser_0198 +dresser_0199 +dresser_0200 +flower_pot_0001 +flower_pot_0002 +flower_pot_0003 +flower_pot_0004 +flower_pot_0005 +flower_pot_0006 +flower_pot_0007 +flower_pot_0008 +flower_pot_0009 +flower_pot_0010 +flower_pot_0011 +flower_pot_0012 +flower_pot_0013 +flower_pot_0014 +flower_pot_0015 +flower_pot_0016 +flower_pot_0017 +flower_pot_0018 +flower_pot_0019 +flower_pot_0020 +flower_pot_0021 +flower_pot_0022 +flower_pot_0023 +flower_pot_0024 +flower_pot_0025 +flower_pot_0026 +flower_pot_0027 +flower_pot_0028 +flower_pot_0029 +flower_pot_0030 +flower_pot_0031 +flower_pot_0032 +flower_pot_0033 +flower_pot_0034 +flower_pot_0035 +flower_pot_0036 +flower_pot_0037 +flower_pot_0038 +flower_pot_0039 +flower_pot_0040 +flower_pot_0041 +flower_pot_0042 +flower_pot_0043 +flower_pot_0044 +flower_pot_0045 +flower_pot_0046 +flower_pot_0047 +flower_pot_0048 +flower_pot_0049 +flower_pot_0050 +flower_pot_0051 +flower_pot_0052 +flower_pot_0053 +flower_pot_0054 +flower_pot_0055 +flower_pot_0056 +flower_pot_0057 +flower_pot_0058 +flower_pot_0059 +flower_pot_0060 +flower_pot_0061 +flower_pot_0062 +flower_pot_0063 +flower_pot_0064 +flower_pot_0065 +flower_pot_0066 +flower_pot_0067 +flower_pot_0068 +flower_pot_0069 +flower_pot_0070 +flower_pot_0071 +flower_pot_0072 +flower_pot_0073 +flower_pot_0074 +flower_pot_0075 +flower_pot_0076 +flower_pot_0077 +flower_pot_0078 +flower_pot_0079 +flower_pot_0080 +flower_pot_0081 +flower_pot_0082 +flower_pot_0083 +flower_pot_0084 +flower_pot_0085 +flower_pot_0086 +flower_pot_0087 +flower_pot_0088 +flower_pot_0089 +flower_pot_0090 +flower_pot_0091 +flower_pot_0092 +flower_pot_0093 +flower_pot_0094 +flower_pot_0095 +flower_pot_0096 +flower_pot_0097 +flower_pot_0098 +flower_pot_0099 +flower_pot_0100 +flower_pot_0101 +flower_pot_0102 +flower_pot_0103 +flower_pot_0104 +flower_pot_0105 +flower_pot_0106 +flower_pot_0107 +flower_pot_0108 +flower_pot_0109 +flower_pot_0110 +flower_pot_0111 +flower_pot_0112 +flower_pot_0113 +flower_pot_0114 +flower_pot_0115 +flower_pot_0116 +flower_pot_0117 +flower_pot_0118 +flower_pot_0119 +flower_pot_0120 +flower_pot_0121 +flower_pot_0122 +flower_pot_0123 +flower_pot_0124 +flower_pot_0125 +flower_pot_0126 +flower_pot_0127 +flower_pot_0128 +flower_pot_0129 +flower_pot_0130 +flower_pot_0131 +flower_pot_0132 +flower_pot_0133 +flower_pot_0134 +flower_pot_0135 +flower_pot_0136 +flower_pot_0137 +flower_pot_0138 +flower_pot_0139 +flower_pot_0140 +flower_pot_0141 +flower_pot_0142 +flower_pot_0143 +flower_pot_0144 +flower_pot_0145 +flower_pot_0146 +flower_pot_0147 +flower_pot_0148 +flower_pot_0149 +glass_box_0001 +glass_box_0002 +glass_box_0003 +glass_box_0004 +glass_box_0005 +glass_box_0006 +glass_box_0007 +glass_box_0008 +glass_box_0009 +glass_box_0010 +glass_box_0011 +glass_box_0012 +glass_box_0013 +glass_box_0014 +glass_box_0015 +glass_box_0016 +glass_box_0017 +glass_box_0018 +glass_box_0019 +glass_box_0020 +glass_box_0021 +glass_box_0022 +glass_box_0023 +glass_box_0024 +glass_box_0025 +glass_box_0026 +glass_box_0027 +glass_box_0028 +glass_box_0029 +glass_box_0030 +glass_box_0031 +glass_box_0032 +glass_box_0033 +glass_box_0034 +glass_box_0035 +glass_box_0036 +glass_box_0037 +glass_box_0038 +glass_box_0039 +glass_box_0040 +glass_box_0041 +glass_box_0042 +glass_box_0043 +glass_box_0044 +glass_box_0045 +glass_box_0046 +glass_box_0047 +glass_box_0048 +glass_box_0049 +glass_box_0050 +glass_box_0051 +glass_box_0052 +glass_box_0053 +glass_box_0054 +glass_box_0055 +glass_box_0056 +glass_box_0057 +glass_box_0058 +glass_box_0059 +glass_box_0060 +glass_box_0061 +glass_box_0062 +glass_box_0063 +glass_box_0064 +glass_box_0065 +glass_box_0066 +glass_box_0067 +glass_box_0068 +glass_box_0069 +glass_box_0070 +glass_box_0071 +glass_box_0072 +glass_box_0073 +glass_box_0074 +glass_box_0075 +glass_box_0076 +glass_box_0077 +glass_box_0078 +glass_box_0079 +glass_box_0080 +glass_box_0081 +glass_box_0082 +glass_box_0083 +glass_box_0084 +glass_box_0085 +glass_box_0086 +glass_box_0087 +glass_box_0088 +glass_box_0089 +glass_box_0090 +glass_box_0091 +glass_box_0092 +glass_box_0093 +glass_box_0094 +glass_box_0095 +glass_box_0096 +glass_box_0097 +glass_box_0098 +glass_box_0099 +glass_box_0100 +glass_box_0101 +glass_box_0102 +glass_box_0103 +glass_box_0104 +glass_box_0105 +glass_box_0106 +glass_box_0107 +glass_box_0108 +glass_box_0109 +glass_box_0110 +glass_box_0111 +glass_box_0112 +glass_box_0113 +glass_box_0114 +glass_box_0115 +glass_box_0116 +glass_box_0117 +glass_box_0118 +glass_box_0119 +glass_box_0120 +glass_box_0121 +glass_box_0122 +glass_box_0123 +glass_box_0124 +glass_box_0125 +glass_box_0126 +glass_box_0127 +glass_box_0128 +glass_box_0129 +glass_box_0130 +glass_box_0131 +glass_box_0132 +glass_box_0133 +glass_box_0134 +glass_box_0135 +glass_box_0136 +glass_box_0137 +glass_box_0138 +glass_box_0139 +glass_box_0140 +glass_box_0141 +glass_box_0142 +glass_box_0143 +glass_box_0144 +glass_box_0145 +glass_box_0146 +glass_box_0147 +glass_box_0148 +glass_box_0149 +glass_box_0150 +glass_box_0151 +glass_box_0152 +glass_box_0153 +glass_box_0154 +glass_box_0155 +glass_box_0156 +glass_box_0157 +glass_box_0158 +glass_box_0159 +glass_box_0160 +glass_box_0161 +glass_box_0162 +glass_box_0163 +glass_box_0164 +glass_box_0165 +glass_box_0166 +glass_box_0167 +glass_box_0168 +glass_box_0169 +glass_box_0170 +glass_box_0171 +guitar_0001 +guitar_0002 +guitar_0003 +guitar_0004 +guitar_0005 +guitar_0006 +guitar_0007 +guitar_0008 +guitar_0009 +guitar_0010 +guitar_0011 +guitar_0012 +guitar_0013 +guitar_0014 +guitar_0015 +guitar_0016 +guitar_0017 +guitar_0018 +guitar_0019 +guitar_0020 +guitar_0021 +guitar_0022 +guitar_0023 +guitar_0024 +guitar_0025 +guitar_0026 +guitar_0027 +guitar_0028 +guitar_0029 +guitar_0030 +guitar_0031 +guitar_0032 +guitar_0033 +guitar_0034 +guitar_0035 +guitar_0036 +guitar_0037 +guitar_0038 +guitar_0039 +guitar_0040 +guitar_0041 +guitar_0042 +guitar_0043 +guitar_0044 +guitar_0045 +guitar_0046 +guitar_0047 +guitar_0048 +guitar_0049 +guitar_0050 +guitar_0051 +guitar_0052 +guitar_0053 +guitar_0054 +guitar_0055 +guitar_0056 +guitar_0057 +guitar_0058 +guitar_0059 +guitar_0060 +guitar_0061 +guitar_0062 +guitar_0063 +guitar_0064 +guitar_0065 +guitar_0066 +guitar_0067 +guitar_0068 +guitar_0069 +guitar_0070 +guitar_0071 +guitar_0072 +guitar_0073 +guitar_0074 +guitar_0075 +guitar_0076 +guitar_0077 +guitar_0078 +guitar_0079 +guitar_0080 +guitar_0081 +guitar_0082 +guitar_0083 +guitar_0084 +guitar_0085 +guitar_0086 +guitar_0087 +guitar_0088 +guitar_0089 +guitar_0090 +guitar_0091 +guitar_0092 +guitar_0093 +guitar_0094 +guitar_0095 +guitar_0096 +guitar_0097 +guitar_0098 +guitar_0099 +guitar_0100 +guitar_0101 +guitar_0102 +guitar_0103 +guitar_0104 +guitar_0105 +guitar_0106 +guitar_0107 +guitar_0108 +guitar_0109 +guitar_0110 +guitar_0111 +guitar_0112 +guitar_0113 +guitar_0114 +guitar_0115 +guitar_0116 +guitar_0117 +guitar_0118 +guitar_0119 +guitar_0120 +guitar_0121 +guitar_0122 +guitar_0123 +guitar_0124 +guitar_0125 +guitar_0126 +guitar_0127 +guitar_0128 +guitar_0129 +guitar_0130 +guitar_0131 +guitar_0132 +guitar_0133 +guitar_0134 +guitar_0135 +guitar_0136 +guitar_0137 +guitar_0138 +guitar_0139 +guitar_0140 +guitar_0141 +guitar_0142 +guitar_0143 +guitar_0144 +guitar_0145 +guitar_0146 +guitar_0147 +guitar_0148 +guitar_0149 +guitar_0150 +guitar_0151 +guitar_0152 +guitar_0153 +guitar_0154 +guitar_0155 +keyboard_0001 +keyboard_0002 +keyboard_0003 +keyboard_0004 +keyboard_0005 +keyboard_0006 +keyboard_0007 +keyboard_0008 +keyboard_0009 +keyboard_0010 +keyboard_0011 +keyboard_0012 +keyboard_0013 +keyboard_0014 +keyboard_0015 +keyboard_0016 +keyboard_0017 +keyboard_0018 +keyboard_0019 +keyboard_0020 +keyboard_0021 +keyboard_0022 +keyboard_0023 +keyboard_0024 +keyboard_0025 +keyboard_0026 +keyboard_0027 +keyboard_0028 +keyboard_0029 +keyboard_0030 +keyboard_0031 +keyboard_0032 +keyboard_0033 +keyboard_0034 +keyboard_0035 +keyboard_0036 +keyboard_0037 +keyboard_0038 +keyboard_0039 +keyboard_0040 +keyboard_0041 +keyboard_0042 +keyboard_0043 +keyboard_0044 +keyboard_0045 +keyboard_0046 +keyboard_0047 +keyboard_0048 +keyboard_0049 +keyboard_0050 +keyboard_0051 +keyboard_0052 +keyboard_0053 +keyboard_0054 +keyboard_0055 +keyboard_0056 +keyboard_0057 +keyboard_0058 +keyboard_0059 +keyboard_0060 +keyboard_0061 +keyboard_0062 +keyboard_0063 +keyboard_0064 +keyboard_0065 +keyboard_0066 +keyboard_0067 +keyboard_0068 +keyboard_0069 +keyboard_0070 +keyboard_0071 +keyboard_0072 +keyboard_0073 +keyboard_0074 +keyboard_0075 +keyboard_0076 +keyboard_0077 +keyboard_0078 +keyboard_0079 +keyboard_0080 +keyboard_0081 +keyboard_0082 +keyboard_0083 +keyboard_0084 +keyboard_0085 +keyboard_0086 +keyboard_0087 +keyboard_0088 +keyboard_0089 +keyboard_0090 +keyboard_0091 +keyboard_0092 +keyboard_0093 +keyboard_0094 +keyboard_0095 +keyboard_0096 +keyboard_0097 +keyboard_0098 +keyboard_0099 +keyboard_0100 +keyboard_0101 +keyboard_0102 +keyboard_0103 +keyboard_0104 +keyboard_0105 +keyboard_0106 +keyboard_0107 +keyboard_0108 +keyboard_0109 +keyboard_0110 +keyboard_0111 +keyboard_0112 +keyboard_0113 +keyboard_0114 +keyboard_0115 +keyboard_0116 +keyboard_0117 +keyboard_0118 +keyboard_0119 +keyboard_0120 +keyboard_0121 +keyboard_0122 +keyboard_0123 +keyboard_0124 +keyboard_0125 +keyboard_0126 +keyboard_0127 +keyboard_0128 +keyboard_0129 +keyboard_0130 +keyboard_0131 +keyboard_0132 +keyboard_0133 +keyboard_0134 +keyboard_0135 +keyboard_0136 +keyboard_0137 +keyboard_0138 +keyboard_0139 +keyboard_0140 +keyboard_0141 +keyboard_0142 +keyboard_0143 +keyboard_0144 +keyboard_0145 +lamp_0001 +lamp_0002 +lamp_0003 +lamp_0004 +lamp_0005 +lamp_0006 +lamp_0007 +lamp_0008 +lamp_0009 +lamp_0010 +lamp_0011 +lamp_0012 +lamp_0013 +lamp_0014 +lamp_0015 +lamp_0016 +lamp_0017 +lamp_0018 +lamp_0019 +lamp_0020 +lamp_0021 +lamp_0022 +lamp_0023 +lamp_0024 +lamp_0025 +lamp_0026 +lamp_0027 +lamp_0028 +lamp_0029 +lamp_0030 +lamp_0031 +lamp_0032 +lamp_0033 +lamp_0034 +lamp_0035 +lamp_0036 +lamp_0037 +lamp_0038 +lamp_0039 +lamp_0040 +lamp_0041 +lamp_0042 +lamp_0043 +lamp_0044 +lamp_0045 +lamp_0046 +lamp_0047 +lamp_0048 +lamp_0049 +lamp_0050 +lamp_0051 +lamp_0052 +lamp_0053 +lamp_0054 +lamp_0055 +lamp_0056 +lamp_0057 +lamp_0058 +lamp_0059 +lamp_0060 +lamp_0061 +lamp_0062 +lamp_0063 +lamp_0064 +lamp_0065 +lamp_0066 +lamp_0067 +lamp_0068 +lamp_0069 +lamp_0070 +lamp_0071 +lamp_0072 +lamp_0073 +lamp_0074 +lamp_0075 +lamp_0076 +lamp_0077 +lamp_0078 +lamp_0079 +lamp_0080 +lamp_0081 +lamp_0082 +lamp_0083 +lamp_0084 +lamp_0085 +lamp_0086 +lamp_0087 +lamp_0088 +lamp_0089 +lamp_0090 +lamp_0091 +lamp_0092 +lamp_0093 +lamp_0094 +lamp_0095 +lamp_0096 +lamp_0097 +lamp_0098 +lamp_0099 +lamp_0100 +lamp_0101 +lamp_0102 +lamp_0103 +lamp_0104 +lamp_0105 +lamp_0106 +lamp_0107 +lamp_0108 +lamp_0109 +lamp_0110 +lamp_0111 +lamp_0112 +lamp_0113 +lamp_0114 +lamp_0115 +lamp_0116 +lamp_0117 +lamp_0118 +lamp_0119 +lamp_0120 +lamp_0121 +lamp_0122 +lamp_0123 +lamp_0124 +laptop_0001 +laptop_0002 +laptop_0003 +laptop_0004 +laptop_0005 +laptop_0006 +laptop_0007 +laptop_0008 +laptop_0009 +laptop_0010 +laptop_0011 +laptop_0012 +laptop_0013 +laptop_0014 +laptop_0015 +laptop_0016 +laptop_0017 +laptop_0018 +laptop_0019 +laptop_0020 +laptop_0021 +laptop_0022 +laptop_0023 +laptop_0024 +laptop_0025 +laptop_0026 +laptop_0027 +laptop_0028 +laptop_0029 +laptop_0030 +laptop_0031 +laptop_0032 +laptop_0033 +laptop_0034 +laptop_0035 +laptop_0036 +laptop_0037 +laptop_0038 +laptop_0039 +laptop_0040 +laptop_0041 +laptop_0042 +laptop_0043 +laptop_0044 +laptop_0045 +laptop_0046 +laptop_0047 +laptop_0048 +laptop_0049 +laptop_0050 +laptop_0051 +laptop_0052 +laptop_0053 +laptop_0054 +laptop_0055 +laptop_0056 +laptop_0057 +laptop_0058 +laptop_0059 +laptop_0060 +laptop_0061 +laptop_0062 +laptop_0063 +laptop_0064 +laptop_0065 +laptop_0066 +laptop_0067 +laptop_0068 +laptop_0069 +laptop_0070 +laptop_0071 +laptop_0072 +laptop_0073 +laptop_0074 +laptop_0075 +laptop_0076 +laptop_0077 +laptop_0078 +laptop_0079 +laptop_0080 +laptop_0081 +laptop_0082 +laptop_0083 +laptop_0084 +laptop_0085 +laptop_0086 +laptop_0087 +laptop_0088 +laptop_0089 +laptop_0090 +laptop_0091 +laptop_0092 +laptop_0093 +laptop_0094 +laptop_0095 +laptop_0096 +laptop_0097 +laptop_0098 +laptop_0099 +laptop_0100 +laptop_0101 +laptop_0102 +laptop_0103 +laptop_0104 +laptop_0105 +laptop_0106 +laptop_0107 +laptop_0108 +laptop_0109 +laptop_0110 +laptop_0111 +laptop_0112 +laptop_0113 +laptop_0114 +laptop_0115 +laptop_0116 +laptop_0117 +laptop_0118 +laptop_0119 +laptop_0120 +laptop_0121 +laptop_0122 +laptop_0123 +laptop_0124 +laptop_0125 +laptop_0126 +laptop_0127 +laptop_0128 +laptop_0129 +laptop_0130 +laptop_0131 +laptop_0132 +laptop_0133 +laptop_0134 +laptop_0135 +laptop_0136 +laptop_0137 +laptop_0138 +laptop_0139 +laptop_0140 +laptop_0141 +laptop_0142 +laptop_0143 +laptop_0144 +laptop_0145 +laptop_0146 +laptop_0147 +laptop_0148 +laptop_0149 +mantel_0001 +mantel_0002 +mantel_0003 +mantel_0004 +mantel_0005 +mantel_0006 +mantel_0007 +mantel_0008 +mantel_0009 +mantel_0010 +mantel_0011 +mantel_0012 +mantel_0013 +mantel_0014 +mantel_0015 +mantel_0016 +mantel_0017 +mantel_0018 +mantel_0019 +mantel_0020 +mantel_0021 +mantel_0022 +mantel_0023 +mantel_0024 +mantel_0025 +mantel_0026 +mantel_0027 +mantel_0028 +mantel_0029 +mantel_0030 +mantel_0031 +mantel_0032 +mantel_0033 +mantel_0034 +mantel_0035 +mantel_0036 +mantel_0037 +mantel_0038 +mantel_0039 +mantel_0040 +mantel_0041 +mantel_0042 +mantel_0043 +mantel_0044 +mantel_0045 +mantel_0046 +mantel_0047 +mantel_0048 +mantel_0049 +mantel_0050 +mantel_0051 +mantel_0052 +mantel_0053 +mantel_0054 +mantel_0055 +mantel_0056 +mantel_0057 +mantel_0058 +mantel_0059 +mantel_0060 +mantel_0061 +mantel_0062 +mantel_0063 +mantel_0064 +mantel_0065 +mantel_0066 +mantel_0067 +mantel_0068 +mantel_0069 +mantel_0070 +mantel_0071 +mantel_0072 +mantel_0073 +mantel_0074 +mantel_0075 +mantel_0076 +mantel_0077 +mantel_0078 +mantel_0079 +mantel_0080 +mantel_0081 +mantel_0082 +mantel_0083 +mantel_0084 +mantel_0085 +mantel_0086 +mantel_0087 +mantel_0088 +mantel_0089 +mantel_0090 +mantel_0091 +mantel_0092 +mantel_0093 +mantel_0094 +mantel_0095 +mantel_0096 +mantel_0097 +mantel_0098 +mantel_0099 +mantel_0100 +mantel_0101 +mantel_0102 +mantel_0103 +mantel_0104 +mantel_0105 +mantel_0106 +mantel_0107 +mantel_0108 +mantel_0109 +mantel_0110 +mantel_0111 +mantel_0112 +mantel_0113 +mantel_0114 +mantel_0115 +mantel_0116 +mantel_0117 +mantel_0118 +mantel_0119 +mantel_0120 +mantel_0121 +mantel_0122 +mantel_0123 +mantel_0124 +mantel_0125 +mantel_0126 +mantel_0127 +mantel_0128 +mantel_0129 +mantel_0130 +mantel_0131 +mantel_0132 +mantel_0133 +mantel_0134 +mantel_0135 +mantel_0136 +mantel_0137 +mantel_0138 +mantel_0139 +mantel_0140 +mantel_0141 +mantel_0142 +mantel_0143 +mantel_0144 +mantel_0145 +mantel_0146 +mantel_0147 +mantel_0148 +mantel_0149 +mantel_0150 +mantel_0151 +mantel_0152 +mantel_0153 +mantel_0154 +mantel_0155 +mantel_0156 +mantel_0157 +mantel_0158 +mantel_0159 +mantel_0160 +mantel_0161 +mantel_0162 +mantel_0163 +mantel_0164 +mantel_0165 +mantel_0166 +mantel_0167 +mantel_0168 +mantel_0169 +mantel_0170 +mantel_0171 +mantel_0172 +mantel_0173 +mantel_0174 +mantel_0175 +mantel_0176 +mantel_0177 +mantel_0178 +mantel_0179 +mantel_0180 +mantel_0181 +mantel_0182 +mantel_0183 +mantel_0184 +mantel_0185 +mantel_0186 +mantel_0187 +mantel_0188 +mantel_0189 +mantel_0190 +mantel_0191 +mantel_0192 +mantel_0193 +mantel_0194 +mantel_0195 +mantel_0196 +mantel_0197 +mantel_0198 +mantel_0199 +mantel_0200 +mantel_0201 +mantel_0202 +mantel_0203 +mantel_0204 +mantel_0205 +mantel_0206 +mantel_0207 +mantel_0208 +mantel_0209 +mantel_0210 +mantel_0211 +mantel_0212 +mantel_0213 +mantel_0214 +mantel_0215 +mantel_0216 +mantel_0217 +mantel_0218 +mantel_0219 +mantel_0220 +mantel_0221 +mantel_0222 +mantel_0223 +mantel_0224 +mantel_0225 +mantel_0226 +mantel_0227 +mantel_0228 +mantel_0229 +mantel_0230 +mantel_0231 +mantel_0232 +mantel_0233 +mantel_0234 +mantel_0235 +mantel_0236 +mantel_0237 +mantel_0238 +mantel_0239 +mantel_0240 +mantel_0241 +mantel_0242 +mantel_0243 +mantel_0244 +mantel_0245 +mantel_0246 +mantel_0247 +mantel_0248 +mantel_0249 +mantel_0250 +mantel_0251 +mantel_0252 +mantel_0253 +mantel_0254 +mantel_0255 +mantel_0256 +mantel_0257 +mantel_0258 +mantel_0259 +mantel_0260 +mantel_0261 +mantel_0262 +mantel_0263 +mantel_0264 +mantel_0265 +mantel_0266 +mantel_0267 +mantel_0268 +mantel_0269 +mantel_0270 +mantel_0271 +mantel_0272 +mantel_0273 +mantel_0274 +mantel_0275 +mantel_0276 +mantel_0277 +mantel_0278 +mantel_0279 +mantel_0280 +mantel_0281 +mantel_0282 +mantel_0283 +mantel_0284 +monitor_0001 +monitor_0002 +monitor_0003 +monitor_0004 +monitor_0005 +monitor_0006 +monitor_0007 +monitor_0008 +monitor_0009 +monitor_0010 +monitor_0011 +monitor_0012 +monitor_0013 +monitor_0014 +monitor_0015 +monitor_0016 +monitor_0017 +monitor_0018 +monitor_0019 +monitor_0020 +monitor_0021 +monitor_0022 +monitor_0023 +monitor_0024 +monitor_0025 +monitor_0026 +monitor_0027 +monitor_0028 +monitor_0029 +monitor_0030 +monitor_0031 +monitor_0032 +monitor_0033 +monitor_0034 +monitor_0035 +monitor_0036 +monitor_0037 +monitor_0038 +monitor_0039 +monitor_0040 +monitor_0041 +monitor_0042 +monitor_0043 +monitor_0044 +monitor_0045 +monitor_0046 +monitor_0047 +monitor_0048 +monitor_0049 +monitor_0050 +monitor_0051 +monitor_0052 +monitor_0053 +monitor_0054 +monitor_0055 +monitor_0056 +monitor_0057 +monitor_0058 +monitor_0059 +monitor_0060 +monitor_0061 +monitor_0062 +monitor_0063 +monitor_0064 +monitor_0065 +monitor_0066 +monitor_0067 +monitor_0068 +monitor_0069 +monitor_0070 +monitor_0071 +monitor_0072 +monitor_0073 +monitor_0074 +monitor_0075 +monitor_0076 +monitor_0077 +monitor_0078 +monitor_0079 +monitor_0080 +monitor_0081 +monitor_0082 +monitor_0083 +monitor_0084 +monitor_0085 +monitor_0086 +monitor_0087 +monitor_0088 +monitor_0089 +monitor_0090 +monitor_0091 +monitor_0092 +monitor_0093 +monitor_0094 +monitor_0095 +monitor_0096 +monitor_0097 +monitor_0098 +monitor_0099 +monitor_0100 +monitor_0101 +monitor_0102 +monitor_0103 +monitor_0104 +monitor_0105 +monitor_0106 +monitor_0107 +monitor_0108 +monitor_0109 +monitor_0110 +monitor_0111 +monitor_0112 +monitor_0113 +monitor_0114 +monitor_0115 +monitor_0116 +monitor_0117 +monitor_0118 +monitor_0119 +monitor_0120 +monitor_0121 +monitor_0122 +monitor_0123 +monitor_0124 +monitor_0125 +monitor_0126 +monitor_0127 +monitor_0128 +monitor_0129 +monitor_0130 +monitor_0131 +monitor_0132 +monitor_0133 +monitor_0134 +monitor_0135 +monitor_0136 +monitor_0137 +monitor_0138 +monitor_0139 +monitor_0140 +monitor_0141 +monitor_0142 +monitor_0143 +monitor_0144 +monitor_0145 +monitor_0146 +monitor_0147 +monitor_0148 +monitor_0149 +monitor_0150 +monitor_0151 +monitor_0152 +monitor_0153 +monitor_0154 +monitor_0155 +monitor_0156 +monitor_0157 +monitor_0158 +monitor_0159 +monitor_0160 +monitor_0161 +monitor_0162 +monitor_0163 +monitor_0164 +monitor_0165 +monitor_0166 +monitor_0167 +monitor_0168 +monitor_0169 +monitor_0170 +monitor_0171 +monitor_0172 +monitor_0173 +monitor_0174 +monitor_0175 +monitor_0176 +monitor_0177 +monitor_0178 +monitor_0179 +monitor_0180 +monitor_0181 +monitor_0182 +monitor_0183 +monitor_0184 +monitor_0185 +monitor_0186 +monitor_0187 +monitor_0188 +monitor_0189 +monitor_0190 +monitor_0191 +monitor_0192 +monitor_0193 +monitor_0194 +monitor_0195 +monitor_0196 +monitor_0197 +monitor_0198 +monitor_0199 +monitor_0200 +monitor_0201 +monitor_0202 +monitor_0203 +monitor_0204 +monitor_0205 +monitor_0206 +monitor_0207 +monitor_0208 +monitor_0209 +monitor_0210 +monitor_0211 +monitor_0212 +monitor_0213 +monitor_0214 +monitor_0215 +monitor_0216 +monitor_0217 +monitor_0218 +monitor_0219 +monitor_0220 +monitor_0221 +monitor_0222 +monitor_0223 +monitor_0224 +monitor_0225 +monitor_0226 +monitor_0227 +monitor_0228 +monitor_0229 +monitor_0230 +monitor_0231 +monitor_0232 +monitor_0233 +monitor_0234 +monitor_0235 +monitor_0236 +monitor_0237 +monitor_0238 +monitor_0239 +monitor_0240 +monitor_0241 +monitor_0242 +monitor_0243 +monitor_0244 +monitor_0245 +monitor_0246 +monitor_0247 +monitor_0248 +monitor_0249 +monitor_0250 +monitor_0251 +monitor_0252 +monitor_0253 +monitor_0254 +monitor_0255 +monitor_0256 +monitor_0257 +monitor_0258 +monitor_0259 +monitor_0260 +monitor_0261 +monitor_0262 +monitor_0263 +monitor_0264 +monitor_0265 +monitor_0266 +monitor_0267 +monitor_0268 +monitor_0269 +monitor_0270 +monitor_0271 +monitor_0272 +monitor_0273 +monitor_0274 +monitor_0275 +monitor_0276 +monitor_0277 +monitor_0278 +monitor_0279 +monitor_0280 +monitor_0281 +monitor_0282 +monitor_0283 +monitor_0284 +monitor_0285 +monitor_0286 +monitor_0287 +monitor_0288 +monitor_0289 +monitor_0290 +monitor_0291 +monitor_0292 +monitor_0293 +monitor_0294 +monitor_0295 +monitor_0296 +monitor_0297 +monitor_0298 +monitor_0299 +monitor_0300 +monitor_0301 +monitor_0302 +monitor_0303 +monitor_0304 +monitor_0305 +monitor_0306 +monitor_0307 +monitor_0308 +monitor_0309 +monitor_0310 +monitor_0311 +monitor_0312 +monitor_0313 +monitor_0314 +monitor_0315 +monitor_0316 +monitor_0317 +monitor_0318 +monitor_0319 +monitor_0320 +monitor_0321 +monitor_0322 +monitor_0323 +monitor_0324 +monitor_0325 +monitor_0326 +monitor_0327 +monitor_0328 +monitor_0329 +monitor_0330 +monitor_0331 +monitor_0332 +monitor_0333 +monitor_0334 +monitor_0335 +monitor_0336 +monitor_0337 +monitor_0338 +monitor_0339 +monitor_0340 +monitor_0341 +monitor_0342 +monitor_0343 +monitor_0344 +monitor_0345 +monitor_0346 +monitor_0347 +monitor_0348 +monitor_0349 +monitor_0350 +monitor_0351 +monitor_0352 +monitor_0353 +monitor_0354 +monitor_0355 +monitor_0356 +monitor_0357 +monitor_0358 +monitor_0359 +monitor_0360 +monitor_0361 +monitor_0362 +monitor_0363 +monitor_0364 +monitor_0365 +monitor_0366 +monitor_0367 +monitor_0368 +monitor_0369 +monitor_0370 +monitor_0371 +monitor_0372 +monitor_0373 +monitor_0374 +monitor_0375 +monitor_0376 +monitor_0377 +monitor_0378 +monitor_0379 +monitor_0380 +monitor_0381 +monitor_0382 +monitor_0383 +monitor_0384 +monitor_0385 +monitor_0386 +monitor_0387 +monitor_0388 +monitor_0389 +monitor_0390 +monitor_0391 +monitor_0392 +monitor_0393 +monitor_0394 +monitor_0395 +monitor_0396 +monitor_0397 +monitor_0398 +monitor_0399 +monitor_0400 +monitor_0401 +monitor_0402 +monitor_0403 +monitor_0404 +monitor_0405 +monitor_0406 +monitor_0407 +monitor_0408 +monitor_0409 +monitor_0410 +monitor_0411 +monitor_0412 +monitor_0413 +monitor_0414 +monitor_0415 +monitor_0416 +monitor_0417 +monitor_0418 +monitor_0419 +monitor_0420 +monitor_0421 +monitor_0422 +monitor_0423 +monitor_0424 +monitor_0425 +monitor_0426 +monitor_0427 +monitor_0428 +monitor_0429 +monitor_0430 +monitor_0431 +monitor_0432 +monitor_0433 +monitor_0434 +monitor_0435 +monitor_0436 +monitor_0437 +monitor_0438 +monitor_0439 +monitor_0440 +monitor_0441 +monitor_0442 +monitor_0443 +monitor_0444 +monitor_0445 +monitor_0446 +monitor_0447 +monitor_0448 +monitor_0449 +monitor_0450 +monitor_0451 +monitor_0452 +monitor_0453 +monitor_0454 +monitor_0455 +monitor_0456 +monitor_0457 +monitor_0458 +monitor_0459 +monitor_0460 +monitor_0461 +monitor_0462 +monitor_0463 +monitor_0464 +monitor_0465 +night_stand_0001 +night_stand_0002 +night_stand_0003 +night_stand_0004 +night_stand_0005 +night_stand_0006 +night_stand_0007 +night_stand_0008 +night_stand_0009 +night_stand_0010 +night_stand_0011 +night_stand_0012 +night_stand_0013 +night_stand_0014 +night_stand_0015 +night_stand_0016 +night_stand_0017 +night_stand_0018 +night_stand_0019 +night_stand_0020 +night_stand_0021 +night_stand_0022 +night_stand_0023 +night_stand_0024 +night_stand_0025 +night_stand_0026 +night_stand_0027 +night_stand_0028 +night_stand_0029 +night_stand_0030 +night_stand_0031 +night_stand_0032 +night_stand_0033 +night_stand_0034 +night_stand_0035 +night_stand_0036 +night_stand_0037 +night_stand_0038 +night_stand_0039 +night_stand_0040 +night_stand_0041 +night_stand_0042 +night_stand_0043 +night_stand_0044 +night_stand_0045 +night_stand_0046 +night_stand_0047 +night_stand_0048 +night_stand_0049 +night_stand_0050 +night_stand_0051 +night_stand_0052 +night_stand_0053 +night_stand_0054 +night_stand_0055 +night_stand_0056 +night_stand_0057 +night_stand_0058 +night_stand_0059 +night_stand_0060 +night_stand_0061 +night_stand_0062 +night_stand_0063 +night_stand_0064 +night_stand_0065 +night_stand_0066 +night_stand_0067 +night_stand_0068 +night_stand_0069 +night_stand_0070 +night_stand_0071 +night_stand_0072 +night_stand_0073 +night_stand_0074 +night_stand_0075 +night_stand_0076 +night_stand_0077 +night_stand_0078 +night_stand_0079 +night_stand_0080 +night_stand_0081 +night_stand_0082 +night_stand_0083 +night_stand_0084 +night_stand_0085 +night_stand_0086 +night_stand_0087 +night_stand_0088 +night_stand_0089 +night_stand_0090 +night_stand_0091 +night_stand_0092 +night_stand_0093 +night_stand_0094 +night_stand_0095 +night_stand_0096 +night_stand_0097 +night_stand_0098 +night_stand_0099 +night_stand_0100 +night_stand_0101 +night_stand_0102 +night_stand_0103 +night_stand_0104 +night_stand_0105 +night_stand_0106 +night_stand_0107 +night_stand_0108 +night_stand_0109 +night_stand_0110 +night_stand_0111 +night_stand_0112 +night_stand_0113 +night_stand_0114 +night_stand_0115 +night_stand_0116 +night_stand_0117 +night_stand_0118 +night_stand_0119 +night_stand_0120 +night_stand_0121 +night_stand_0122 +night_stand_0123 +night_stand_0124 +night_stand_0125 +night_stand_0126 +night_stand_0127 +night_stand_0128 +night_stand_0129 +night_stand_0130 +night_stand_0131 +night_stand_0132 +night_stand_0133 +night_stand_0134 +night_stand_0135 +night_stand_0136 +night_stand_0137 +night_stand_0138 +night_stand_0139 +night_stand_0140 +night_stand_0141 +night_stand_0142 +night_stand_0143 +night_stand_0144 +night_stand_0145 +night_stand_0146 +night_stand_0147 +night_stand_0148 +night_stand_0149 +night_stand_0150 +night_stand_0151 +night_stand_0152 +night_stand_0153 +night_stand_0154 +night_stand_0155 +night_stand_0156 +night_stand_0157 +night_stand_0158 +night_stand_0159 +night_stand_0160 +night_stand_0161 +night_stand_0162 +night_stand_0163 +night_stand_0164 +night_stand_0165 +night_stand_0166 +night_stand_0167 +night_stand_0168 +night_stand_0169 +night_stand_0170 +night_stand_0171 +night_stand_0172 +night_stand_0173 +night_stand_0174 +night_stand_0175 +night_stand_0176 +night_stand_0177 +night_stand_0178 +night_stand_0179 +night_stand_0180 +night_stand_0181 +night_stand_0182 +night_stand_0183 +night_stand_0184 +night_stand_0185 +night_stand_0186 +night_stand_0187 +night_stand_0188 +night_stand_0189 +night_stand_0190 +night_stand_0191 +night_stand_0192 +night_stand_0193 +night_stand_0194 +night_stand_0195 +night_stand_0196 +night_stand_0197 +night_stand_0198 +night_stand_0199 +night_stand_0200 +person_0001 +person_0002 +person_0003 +person_0004 +person_0005 +person_0006 +person_0007 +person_0008 +person_0009 +person_0010 +person_0011 +person_0012 +person_0013 +person_0014 +person_0015 +person_0016 +person_0017 +person_0018 +person_0019 +person_0020 +person_0021 +person_0022 +person_0023 +person_0024 +person_0025 +person_0026 +person_0027 +person_0028 +person_0029 +person_0030 +person_0031 +person_0032 +person_0033 +person_0034 +person_0035 +person_0036 +person_0037 +person_0038 +person_0039 +person_0040 +person_0041 +person_0042 +person_0043 +person_0044 +person_0045 +person_0046 +person_0047 +person_0048 +person_0049 +person_0050 +person_0051 +person_0052 +person_0053 +person_0054 +person_0055 +person_0056 +person_0057 +person_0058 +person_0059 +person_0060 +person_0061 +person_0062 +person_0063 +person_0064 +person_0065 +person_0066 +person_0067 +person_0068 +person_0069 +person_0070 +person_0071 +person_0072 +person_0073 +person_0074 +person_0075 +person_0076 +person_0077 +person_0078 +person_0079 +person_0080 +person_0081 +person_0082 +person_0083 +person_0084 +person_0085 +person_0086 +person_0087 +person_0088 +piano_0001 +piano_0002 +piano_0003 +piano_0004 +piano_0005 +piano_0006 +piano_0007 +piano_0008 +piano_0009 +piano_0010 +piano_0011 +piano_0012 +piano_0013 +piano_0014 +piano_0015 +piano_0016 +piano_0017 +piano_0018 +piano_0019 +piano_0020 +piano_0021 +piano_0022 +piano_0023 +piano_0024 +piano_0025 +piano_0026 +piano_0027 +piano_0028 +piano_0029 +piano_0030 +piano_0031 +piano_0032 +piano_0033 +piano_0034 +piano_0035 +piano_0036 +piano_0037 +piano_0038 +piano_0039 +piano_0040 +piano_0041 +piano_0042 +piano_0043 +piano_0044 +piano_0045 +piano_0046 +piano_0047 +piano_0048 +piano_0049 +piano_0050 +piano_0051 +piano_0052 +piano_0053 +piano_0054 +piano_0055 +piano_0056 +piano_0057 +piano_0058 +piano_0059 +piano_0060 +piano_0061 +piano_0062 +piano_0063 +piano_0064 +piano_0065 +piano_0066 +piano_0067 +piano_0068 +piano_0069 +piano_0070 +piano_0071 +piano_0072 +piano_0073 +piano_0074 +piano_0075 +piano_0076 +piano_0077 +piano_0078 +piano_0079 +piano_0080 +piano_0081 +piano_0082 +piano_0083 +piano_0084 +piano_0085 +piano_0086 +piano_0087 +piano_0088 +piano_0089 +piano_0090 +piano_0091 +piano_0092 +piano_0093 +piano_0094 +piano_0095 +piano_0096 +piano_0097 +piano_0098 +piano_0099 +piano_0100 +piano_0101 +piano_0102 +piano_0103 +piano_0104 +piano_0105 +piano_0106 +piano_0107 +piano_0108 +piano_0109 +piano_0110 +piano_0111 +piano_0112 +piano_0113 +piano_0114 +piano_0115 +piano_0116 +piano_0117 +piano_0118 +piano_0119 +piano_0120 +piano_0121 +piano_0122 +piano_0123 +piano_0124 +piano_0125 +piano_0126 +piano_0127 +piano_0128 +piano_0129 +piano_0130 +piano_0131 +piano_0132 +piano_0133 +piano_0134 +piano_0135 +piano_0136 +piano_0137 +piano_0138 +piano_0139 +piano_0140 +piano_0141 +piano_0142 +piano_0143 +piano_0144 +piano_0145 +piano_0146 +piano_0147 +piano_0148 +piano_0149 +piano_0150 +piano_0151 +piano_0152 +piano_0153 +piano_0154 +piano_0155 +piano_0156 +piano_0157 +piano_0158 +piano_0159 +piano_0160 +piano_0161 +piano_0162 +piano_0163 +piano_0164 +piano_0165 +piano_0166 +piano_0167 +piano_0168 +piano_0169 +piano_0170 +piano_0171 +piano_0172 +piano_0173 +piano_0174 +piano_0175 +piano_0176 +piano_0177 +piano_0178 +piano_0179 +piano_0180 +piano_0181 +piano_0182 +piano_0183 +piano_0184 +piano_0185 +piano_0186 +piano_0187 +piano_0188 +piano_0189 +piano_0190 +piano_0191 +piano_0192 +piano_0193 +piano_0194 +piano_0195 +piano_0196 +piano_0197 +piano_0198 +piano_0199 +piano_0200 +piano_0201 +piano_0202 +piano_0203 +piano_0204 +piano_0205 +piano_0206 +piano_0207 +piano_0208 +piano_0209 +piano_0210 +piano_0211 +piano_0212 +piano_0213 +piano_0214 +piano_0215 +piano_0216 +piano_0217 +piano_0218 +piano_0219 +piano_0220 +piano_0221 +piano_0222 +piano_0223 +piano_0224 +piano_0225 +piano_0226 +piano_0227 +piano_0228 +piano_0229 +piano_0230 +piano_0231 +plant_0001 +plant_0002 +plant_0003 +plant_0004 +plant_0005 +plant_0006 +plant_0007 +plant_0008 +plant_0009 +plant_0010 +plant_0011 +plant_0012 +plant_0013 +plant_0014 +plant_0015 +plant_0016 +plant_0017 +plant_0018 +plant_0019 +plant_0020 +plant_0021 +plant_0022 +plant_0023 +plant_0024 +plant_0025 +plant_0026 +plant_0027 +plant_0028 +plant_0029 +plant_0030 +plant_0031 +plant_0032 +plant_0033 +plant_0034 +plant_0035 +plant_0036 +plant_0037 +plant_0038 +plant_0039 +plant_0040 +plant_0041 +plant_0042 +plant_0043 +plant_0044 +plant_0045 +plant_0046 +plant_0047 +plant_0048 +plant_0049 +plant_0050 +plant_0051 +plant_0052 +plant_0053 +plant_0054 +plant_0055 +plant_0056 +plant_0057 +plant_0058 +plant_0059 +plant_0060 +plant_0061 +plant_0062 +plant_0063 +plant_0064 +plant_0065 +plant_0066 +plant_0067 +plant_0068 +plant_0069 +plant_0070 +plant_0071 +plant_0072 +plant_0073 +plant_0074 +plant_0075 +plant_0076 +plant_0077 +plant_0078 +plant_0079 +plant_0080 +plant_0081 +plant_0082 +plant_0083 +plant_0084 +plant_0085 +plant_0086 +plant_0087 +plant_0088 +plant_0089 +plant_0090 +plant_0091 +plant_0092 +plant_0093 +plant_0094 +plant_0095 +plant_0096 +plant_0097 +plant_0098 +plant_0099 +plant_0100 +plant_0101 +plant_0102 +plant_0103 +plant_0104 +plant_0105 +plant_0106 +plant_0107 +plant_0108 +plant_0109 +plant_0110 +plant_0111 +plant_0112 +plant_0113 +plant_0114 +plant_0115 +plant_0116 +plant_0117 +plant_0118 +plant_0119 +plant_0120 +plant_0121 +plant_0122 +plant_0123 +plant_0124 +plant_0125 +plant_0126 +plant_0127 +plant_0128 +plant_0129 +plant_0130 +plant_0131 +plant_0132 +plant_0133 +plant_0134 +plant_0135 +plant_0136 +plant_0137 +plant_0138 +plant_0139 +plant_0140 +plant_0141 +plant_0142 +plant_0143 +plant_0144 +plant_0145 +plant_0146 +plant_0147 +plant_0148 +plant_0149 +plant_0150 +plant_0151 +plant_0152 +plant_0153 +plant_0154 +plant_0155 +plant_0156 +plant_0157 +plant_0158 +plant_0159 +plant_0160 +plant_0161 +plant_0162 +plant_0163 +plant_0164 +plant_0165 +plant_0166 +plant_0167 +plant_0168 +plant_0169 +plant_0170 +plant_0171 +plant_0172 +plant_0173 +plant_0174 +plant_0175 +plant_0176 +plant_0177 +plant_0178 +plant_0179 +plant_0180 +plant_0181 +plant_0182 +plant_0183 +plant_0184 +plant_0185 +plant_0186 +plant_0187 +plant_0188 +plant_0189 +plant_0190 +plant_0191 +plant_0192 +plant_0193 +plant_0194 +plant_0195 +plant_0196 +plant_0197 +plant_0198 +plant_0199 +plant_0200 +plant_0201 +plant_0202 +plant_0203 +plant_0204 +plant_0205 +plant_0206 +plant_0207 +plant_0208 +plant_0209 +plant_0210 +plant_0211 +plant_0212 +plant_0213 +plant_0214 +plant_0215 +plant_0216 +plant_0217 +plant_0218 +plant_0219 +plant_0220 +plant_0221 +plant_0222 +plant_0223 +plant_0224 +plant_0225 +plant_0226 +plant_0227 +plant_0228 +plant_0229 +plant_0230 +plant_0231 +plant_0232 +plant_0233 +plant_0234 +plant_0235 +plant_0236 +plant_0237 +plant_0238 +plant_0239 +plant_0240 +radio_0001 +radio_0002 +radio_0003 +radio_0004 +radio_0005 +radio_0006 +radio_0007 +radio_0008 +radio_0009 +radio_0010 +radio_0011 +radio_0012 +radio_0013 +radio_0014 +radio_0015 +radio_0016 +radio_0017 +radio_0018 +radio_0019 +radio_0020 +radio_0021 +radio_0022 +radio_0023 +radio_0024 +radio_0025 +radio_0026 +radio_0027 +radio_0028 +radio_0029 +radio_0030 +radio_0031 +radio_0032 +radio_0033 +radio_0034 +radio_0035 +radio_0036 +radio_0037 +radio_0038 +radio_0039 +radio_0040 +radio_0041 +radio_0042 +radio_0043 +radio_0044 +radio_0045 +radio_0046 +radio_0047 +radio_0048 +radio_0049 +radio_0050 +radio_0051 +radio_0052 +radio_0053 +radio_0054 +radio_0055 +radio_0056 +radio_0057 +radio_0058 +radio_0059 +radio_0060 +radio_0061 +radio_0062 +radio_0063 +radio_0064 +radio_0065 +radio_0066 +radio_0067 +radio_0068 +radio_0069 +radio_0070 +radio_0071 +radio_0072 +radio_0073 +radio_0074 +radio_0075 +radio_0076 +radio_0077 +radio_0078 +radio_0079 +radio_0080 +radio_0081 +radio_0082 +radio_0083 +radio_0084 +radio_0085 +radio_0086 +radio_0087 +radio_0088 +radio_0089 +radio_0090 +radio_0091 +radio_0092 +radio_0093 +radio_0094 +radio_0095 +radio_0096 +radio_0097 +radio_0098 +radio_0099 +radio_0100 +radio_0101 +radio_0102 +radio_0103 +radio_0104 +range_hood_0001 +range_hood_0002 +range_hood_0003 +range_hood_0004 +range_hood_0005 +range_hood_0006 +range_hood_0007 +range_hood_0008 +range_hood_0009 +range_hood_0010 +range_hood_0011 +range_hood_0012 +range_hood_0013 +range_hood_0014 +range_hood_0015 +range_hood_0016 +range_hood_0017 +range_hood_0018 +range_hood_0019 +range_hood_0020 +range_hood_0021 +range_hood_0022 +range_hood_0023 +range_hood_0024 +range_hood_0025 +range_hood_0026 +range_hood_0027 +range_hood_0028 +range_hood_0029 +range_hood_0030 +range_hood_0031 +range_hood_0032 +range_hood_0033 +range_hood_0034 +range_hood_0035 +range_hood_0036 +range_hood_0037 +range_hood_0038 +range_hood_0039 +range_hood_0040 +range_hood_0041 +range_hood_0042 +range_hood_0043 +range_hood_0044 +range_hood_0045 +range_hood_0046 +range_hood_0047 +range_hood_0048 +range_hood_0049 +range_hood_0050 +range_hood_0051 +range_hood_0052 +range_hood_0053 +range_hood_0054 +range_hood_0055 +range_hood_0056 +range_hood_0057 +range_hood_0058 +range_hood_0059 +range_hood_0060 +range_hood_0061 +range_hood_0062 +range_hood_0063 +range_hood_0064 +range_hood_0065 +range_hood_0066 +range_hood_0067 +range_hood_0068 +range_hood_0069 +range_hood_0070 +range_hood_0071 +range_hood_0072 +range_hood_0073 +range_hood_0074 +range_hood_0075 +range_hood_0076 +range_hood_0077 +range_hood_0078 +range_hood_0079 +range_hood_0080 +range_hood_0081 +range_hood_0082 +range_hood_0083 +range_hood_0084 +range_hood_0085 +range_hood_0086 +range_hood_0087 +range_hood_0088 +range_hood_0089 +range_hood_0090 +range_hood_0091 +range_hood_0092 +range_hood_0093 +range_hood_0094 +range_hood_0095 +range_hood_0096 +range_hood_0097 +range_hood_0098 +range_hood_0099 +range_hood_0100 +range_hood_0101 +range_hood_0102 +range_hood_0103 +range_hood_0104 +range_hood_0105 +range_hood_0106 +range_hood_0107 +range_hood_0108 +range_hood_0109 +range_hood_0110 +range_hood_0111 +range_hood_0112 +range_hood_0113 +range_hood_0114 +range_hood_0115 +sink_0001 +sink_0002 +sink_0003 +sink_0004 +sink_0005 +sink_0006 +sink_0007 +sink_0008 +sink_0009 +sink_0010 +sink_0011 +sink_0012 +sink_0013 +sink_0014 +sink_0015 +sink_0016 +sink_0017 +sink_0018 +sink_0019 +sink_0020 +sink_0021 +sink_0022 +sink_0023 +sink_0024 +sink_0025 +sink_0026 +sink_0027 +sink_0028 +sink_0029 +sink_0030 +sink_0031 +sink_0032 +sink_0033 +sink_0034 +sink_0035 +sink_0036 +sink_0037 +sink_0038 +sink_0039 +sink_0040 +sink_0041 +sink_0042 +sink_0043 +sink_0044 +sink_0045 +sink_0046 +sink_0047 +sink_0048 +sink_0049 +sink_0050 +sink_0051 +sink_0052 +sink_0053 +sink_0054 +sink_0055 +sink_0056 +sink_0057 +sink_0058 +sink_0059 +sink_0060 +sink_0061 +sink_0062 +sink_0063 +sink_0064 +sink_0065 +sink_0066 +sink_0067 +sink_0068 +sink_0069 +sink_0070 +sink_0071 +sink_0072 +sink_0073 +sink_0074 +sink_0075 +sink_0076 +sink_0077 +sink_0078 +sink_0079 +sink_0080 +sink_0081 +sink_0082 +sink_0083 +sink_0084 +sink_0085 +sink_0086 +sink_0087 +sink_0088 +sink_0089 +sink_0090 +sink_0091 +sink_0092 +sink_0093 +sink_0094 +sink_0095 +sink_0096 +sink_0097 +sink_0098 +sink_0099 +sink_0100 +sink_0101 +sink_0102 +sink_0103 +sink_0104 +sink_0105 +sink_0106 +sink_0107 +sink_0108 +sink_0109 +sink_0110 +sink_0111 +sink_0112 +sink_0113 +sink_0114 +sink_0115 +sink_0116 +sink_0117 +sink_0118 +sink_0119 +sink_0120 +sink_0121 +sink_0122 +sink_0123 +sink_0124 +sink_0125 +sink_0126 +sink_0127 +sink_0128 +sofa_0001 +sofa_0002 +sofa_0003 +sofa_0004 +sofa_0005 +sofa_0006 +sofa_0007 +sofa_0008 +sofa_0009 +sofa_0010 +sofa_0011 +sofa_0012 +sofa_0013 +sofa_0014 +sofa_0015 +sofa_0016 +sofa_0017 +sofa_0018 +sofa_0019 +sofa_0020 +sofa_0021 +sofa_0022 +sofa_0023 +sofa_0024 +sofa_0025 +sofa_0026 +sofa_0027 +sofa_0028 +sofa_0029 +sofa_0030 +sofa_0031 +sofa_0032 +sofa_0033 +sofa_0034 +sofa_0035 +sofa_0036 +sofa_0037 +sofa_0038 +sofa_0039 +sofa_0040 +sofa_0041 +sofa_0042 +sofa_0043 +sofa_0044 +sofa_0045 +sofa_0046 +sofa_0047 +sofa_0048 +sofa_0049 +sofa_0050 +sofa_0051 +sofa_0052 +sofa_0053 +sofa_0054 +sofa_0055 +sofa_0056 +sofa_0057 +sofa_0058 +sofa_0059 +sofa_0060 +sofa_0061 +sofa_0062 +sofa_0063 +sofa_0064 +sofa_0065 +sofa_0066 +sofa_0067 +sofa_0068 +sofa_0069 +sofa_0070 +sofa_0071 +sofa_0072 +sofa_0073 +sofa_0074 +sofa_0075 +sofa_0076 +sofa_0077 +sofa_0078 +sofa_0079 +sofa_0080 +sofa_0081 +sofa_0082 +sofa_0083 +sofa_0084 +sofa_0085 +sofa_0086 +sofa_0087 +sofa_0088 +sofa_0089 +sofa_0090 +sofa_0091 +sofa_0092 +sofa_0093 +sofa_0094 +sofa_0095 +sofa_0096 +sofa_0097 +sofa_0098 +sofa_0099 +sofa_0100 +sofa_0101 +sofa_0102 +sofa_0103 +sofa_0104 +sofa_0105 +sofa_0106 +sofa_0107 +sofa_0108 +sofa_0109 +sofa_0110 +sofa_0111 +sofa_0112 +sofa_0113 +sofa_0114 +sofa_0115 +sofa_0116 +sofa_0117 +sofa_0118 +sofa_0119 +sofa_0120 +sofa_0121 +sofa_0122 +sofa_0123 +sofa_0124 +sofa_0125 +sofa_0126 +sofa_0127 +sofa_0128 +sofa_0129 +sofa_0130 +sofa_0131 +sofa_0132 +sofa_0133 +sofa_0134 +sofa_0135 +sofa_0136 +sofa_0137 +sofa_0138 +sofa_0139 +sofa_0140 +sofa_0141 +sofa_0142 +sofa_0143 +sofa_0144 +sofa_0145 +sofa_0146 +sofa_0147 +sofa_0148 +sofa_0149 +sofa_0150 +sofa_0151 +sofa_0152 +sofa_0153 +sofa_0154 +sofa_0155 +sofa_0156 +sofa_0157 +sofa_0158 +sofa_0159 +sofa_0160 +sofa_0161 +sofa_0162 +sofa_0163 +sofa_0164 +sofa_0165 +sofa_0166 +sofa_0167 +sofa_0168 +sofa_0169 +sofa_0170 +sofa_0171 +sofa_0172 +sofa_0173 +sofa_0174 +sofa_0175 +sofa_0176 +sofa_0177 +sofa_0178 +sofa_0179 +sofa_0180 +sofa_0181 +sofa_0182 +sofa_0183 +sofa_0184 +sofa_0185 +sofa_0186 +sofa_0187 +sofa_0188 +sofa_0189 +sofa_0190 +sofa_0191 +sofa_0192 +sofa_0193 +sofa_0194 +sofa_0195 +sofa_0196 +sofa_0197 +sofa_0198 +sofa_0199 +sofa_0200 +sofa_0201 +sofa_0202 +sofa_0203 +sofa_0204 +sofa_0205 +sofa_0206 +sofa_0207 +sofa_0208 +sofa_0209 +sofa_0210 +sofa_0211 +sofa_0212 +sofa_0213 +sofa_0214 +sofa_0215 +sofa_0216 +sofa_0217 +sofa_0218 +sofa_0219 +sofa_0220 +sofa_0221 +sofa_0222 +sofa_0223 +sofa_0224 +sofa_0225 +sofa_0226 +sofa_0227 +sofa_0228 +sofa_0229 +sofa_0230 +sofa_0231 +sofa_0232 +sofa_0233 +sofa_0234 +sofa_0235 +sofa_0236 +sofa_0237 +sofa_0238 +sofa_0239 +sofa_0240 +sofa_0241 +sofa_0242 +sofa_0243 +sofa_0244 +sofa_0245 +sofa_0246 +sofa_0247 +sofa_0248 +sofa_0249 +sofa_0250 +sofa_0251 +sofa_0252 +sofa_0253 +sofa_0254 +sofa_0255 +sofa_0256 +sofa_0257 +sofa_0258 +sofa_0259 +sofa_0260 +sofa_0261 +sofa_0262 +sofa_0263 +sofa_0264 +sofa_0265 +sofa_0266 +sofa_0267 +sofa_0268 +sofa_0269 +sofa_0270 +sofa_0271 +sofa_0272 +sofa_0273 +sofa_0274 +sofa_0275 +sofa_0276 +sofa_0277 +sofa_0278 +sofa_0279 +sofa_0280 +sofa_0281 +sofa_0282 +sofa_0283 +sofa_0284 +sofa_0285 +sofa_0286 +sofa_0287 +sofa_0288 +sofa_0289 +sofa_0290 +sofa_0291 +sofa_0292 +sofa_0293 +sofa_0294 +sofa_0295 +sofa_0296 +sofa_0297 +sofa_0298 +sofa_0299 +sofa_0300 +sofa_0301 +sofa_0302 +sofa_0303 +sofa_0304 +sofa_0305 +sofa_0306 +sofa_0307 +sofa_0308 +sofa_0309 +sofa_0310 +sofa_0311 +sofa_0312 +sofa_0313 +sofa_0314 +sofa_0315 +sofa_0316 +sofa_0317 +sofa_0318 +sofa_0319 +sofa_0320 +sofa_0321 +sofa_0322 +sofa_0323 +sofa_0324 +sofa_0325 +sofa_0326 +sofa_0327 +sofa_0328 +sofa_0329 +sofa_0330 +sofa_0331 +sofa_0332 +sofa_0333 +sofa_0334 +sofa_0335 +sofa_0336 +sofa_0337 +sofa_0338 +sofa_0339 +sofa_0340 +sofa_0341 +sofa_0342 +sofa_0343 +sofa_0344 +sofa_0345 +sofa_0346 +sofa_0347 +sofa_0348 +sofa_0349 +sofa_0350 +sofa_0351 +sofa_0352 +sofa_0353 +sofa_0354 +sofa_0355 +sofa_0356 +sofa_0357 +sofa_0358 +sofa_0359 +sofa_0360 +sofa_0361 +sofa_0362 +sofa_0363 +sofa_0364 +sofa_0365 +sofa_0366 +sofa_0367 +sofa_0368 +sofa_0369 +sofa_0370 +sofa_0371 +sofa_0372 +sofa_0373 +sofa_0374 +sofa_0375 +sofa_0376 +sofa_0377 +sofa_0378 +sofa_0379 +sofa_0380 +sofa_0381 +sofa_0382 +sofa_0383 +sofa_0384 +sofa_0385 +sofa_0386 +sofa_0387 +sofa_0388 +sofa_0389 +sofa_0390 +sofa_0391 +sofa_0392 +sofa_0393 +sofa_0394 +sofa_0395 +sofa_0396 +sofa_0397 +sofa_0398 +sofa_0399 +sofa_0400 +sofa_0401 +sofa_0402 +sofa_0403 +sofa_0404 +sofa_0405 +sofa_0406 +sofa_0407 +sofa_0408 +sofa_0409 +sofa_0410 +sofa_0411 +sofa_0412 +sofa_0413 +sofa_0414 +sofa_0415 +sofa_0416 +sofa_0417 +sofa_0418 +sofa_0419 +sofa_0420 +sofa_0421 +sofa_0422 +sofa_0423 +sofa_0424 +sofa_0425 +sofa_0426 +sofa_0427 +sofa_0428 +sofa_0429 +sofa_0430 +sofa_0431 +sofa_0432 +sofa_0433 +sofa_0434 +sofa_0435 +sofa_0436 +sofa_0437 +sofa_0438 +sofa_0439 +sofa_0440 +sofa_0441 +sofa_0442 +sofa_0443 +sofa_0444 +sofa_0445 +sofa_0446 +sofa_0447 +sofa_0448 +sofa_0449 +sofa_0450 +sofa_0451 +sofa_0452 +sofa_0453 +sofa_0454 +sofa_0455 +sofa_0456 +sofa_0457 +sofa_0458 +sofa_0459 +sofa_0460 +sofa_0461 +sofa_0462 +sofa_0463 +sofa_0464 +sofa_0465 +sofa_0466 +sofa_0467 +sofa_0468 +sofa_0469 +sofa_0470 +sofa_0471 +sofa_0472 +sofa_0473 +sofa_0474 +sofa_0475 +sofa_0476 +sofa_0477 +sofa_0478 +sofa_0479 +sofa_0480 +sofa_0481 +sofa_0482 +sofa_0483 +sofa_0484 +sofa_0485 +sofa_0486 +sofa_0487 +sofa_0488 +sofa_0489 +sofa_0490 +sofa_0491 +sofa_0492 +sofa_0493 +sofa_0494 +sofa_0495 +sofa_0496 +sofa_0497 +sofa_0498 +sofa_0499 +sofa_0500 +sofa_0501 +sofa_0502 +sofa_0503 +sofa_0504 +sofa_0505 +sofa_0506 +sofa_0507 +sofa_0508 +sofa_0509 +sofa_0510 +sofa_0511 +sofa_0512 +sofa_0513 +sofa_0514 +sofa_0515 +sofa_0516 +sofa_0517 +sofa_0518 +sofa_0519 +sofa_0520 +sofa_0521 +sofa_0522 +sofa_0523 +sofa_0524 +sofa_0525 +sofa_0526 +sofa_0527 +sofa_0528 +sofa_0529 +sofa_0530 +sofa_0531 +sofa_0532 +sofa_0533 +sofa_0534 +sofa_0535 +sofa_0536 +sofa_0537 +sofa_0538 +sofa_0539 +sofa_0540 +sofa_0541 +sofa_0542 +sofa_0543 +sofa_0544 +sofa_0545 +sofa_0546 +sofa_0547 +sofa_0548 +sofa_0549 +sofa_0550 +sofa_0551 +sofa_0552 +sofa_0553 +sofa_0554 +sofa_0555 +sofa_0556 +sofa_0557 +sofa_0558 +sofa_0559 +sofa_0560 +sofa_0561 +sofa_0562 +sofa_0563 +sofa_0564 +sofa_0565 +sofa_0566 +sofa_0567 +sofa_0568 +sofa_0569 +sofa_0570 +sofa_0571 +sofa_0572 +sofa_0573 +sofa_0574 +sofa_0575 +sofa_0576 +sofa_0577 +sofa_0578 +sofa_0579 +sofa_0580 +sofa_0581 +sofa_0582 +sofa_0583 +sofa_0584 +sofa_0585 +sofa_0586 +sofa_0587 +sofa_0588 +sofa_0589 +sofa_0590 +sofa_0591 +sofa_0592 +sofa_0593 +sofa_0594 +sofa_0595 +sofa_0596 +sofa_0597 +sofa_0598 +sofa_0599 +sofa_0600 +sofa_0601 +sofa_0602 +sofa_0603 +sofa_0604 +sofa_0605 +sofa_0606 +sofa_0607 +sofa_0608 +sofa_0609 +sofa_0610 +sofa_0611 +sofa_0612 +sofa_0613 +sofa_0614 +sofa_0615 +sofa_0616 +sofa_0617 +sofa_0618 +sofa_0619 +sofa_0620 +sofa_0621 +sofa_0622 +sofa_0623 +sofa_0624 +sofa_0625 +sofa_0626 +sofa_0627 +sofa_0628 +sofa_0629 +sofa_0630 +sofa_0631 +sofa_0632 +sofa_0633 +sofa_0634 +sofa_0635 +sofa_0636 +sofa_0637 +sofa_0638 +sofa_0639 +sofa_0640 +sofa_0641 +sofa_0642 +sofa_0643 +sofa_0644 +sofa_0645 +sofa_0646 +sofa_0647 +sofa_0648 +sofa_0649 +sofa_0650 +sofa_0651 +sofa_0652 +sofa_0653 +sofa_0654 +sofa_0655 +sofa_0656 +sofa_0657 +sofa_0658 +sofa_0659 +sofa_0660 +sofa_0661 +sofa_0662 +sofa_0663 +sofa_0664 +sofa_0665 +sofa_0666 +sofa_0667 +sofa_0668 +sofa_0669 +sofa_0670 +sofa_0671 +sofa_0672 +sofa_0673 +sofa_0674 +sofa_0675 +sofa_0676 +sofa_0677 +sofa_0678 +sofa_0679 +sofa_0680 +stairs_0001 +stairs_0002 +stairs_0003 +stairs_0004 +stairs_0005 +stairs_0006 +stairs_0007 +stairs_0008 +stairs_0009 +stairs_0010 +stairs_0011 +stairs_0012 +stairs_0013 +stairs_0014 +stairs_0015 +stairs_0016 +stairs_0017 +stairs_0018 +stairs_0019 +stairs_0020 +stairs_0021 +stairs_0022 +stairs_0023 +stairs_0024 +stairs_0025 +stairs_0026 +stairs_0027 +stairs_0028 +stairs_0029 +stairs_0030 +stairs_0031 +stairs_0032 +stairs_0033 +stairs_0034 +stairs_0035 +stairs_0036 +stairs_0037 +stairs_0038 +stairs_0039 +stairs_0040 +stairs_0041 +stairs_0042 +stairs_0043 +stairs_0044 +stairs_0045 +stairs_0046 +stairs_0047 +stairs_0048 +stairs_0049 +stairs_0050 +stairs_0051 +stairs_0052 +stairs_0053 +stairs_0054 +stairs_0055 +stairs_0056 +stairs_0057 +stairs_0058 +stairs_0059 +stairs_0060 +stairs_0061 +stairs_0062 +stairs_0063 +stairs_0064 +stairs_0065 +stairs_0066 +stairs_0067 +stairs_0068 +stairs_0069 +stairs_0070 +stairs_0071 +stairs_0072 +stairs_0073 +stairs_0074 +stairs_0075 +stairs_0076 +stairs_0077 +stairs_0078 +stairs_0079 +stairs_0080 +stairs_0081 +stairs_0082 +stairs_0083 +stairs_0084 +stairs_0085 +stairs_0086 +stairs_0087 +stairs_0088 +stairs_0089 +stairs_0090 +stairs_0091 +stairs_0092 +stairs_0093 +stairs_0094 +stairs_0095 +stairs_0096 +stairs_0097 +stairs_0098 +stairs_0099 +stairs_0100 +stairs_0101 +stairs_0102 +stairs_0103 +stairs_0104 +stairs_0105 +stairs_0106 +stairs_0107 +stairs_0108 +stairs_0109 +stairs_0110 +stairs_0111 +stairs_0112 +stairs_0113 +stairs_0114 +stairs_0115 +stairs_0116 +stairs_0117 +stairs_0118 +stairs_0119 +stairs_0120 +stairs_0121 +stairs_0122 +stairs_0123 +stairs_0124 +stool_0001 +stool_0002 +stool_0003 +stool_0004 +stool_0005 +stool_0006 +stool_0007 +stool_0008 +stool_0009 +stool_0010 +stool_0011 +stool_0012 +stool_0013 +stool_0014 +stool_0015 +stool_0016 +stool_0017 +stool_0018 +stool_0019 +stool_0020 +stool_0021 +stool_0022 +stool_0023 +stool_0024 +stool_0025 +stool_0026 +stool_0027 +stool_0028 +stool_0029 +stool_0030 +stool_0031 +stool_0032 +stool_0033 +stool_0034 +stool_0035 +stool_0036 +stool_0037 +stool_0038 +stool_0039 +stool_0040 +stool_0041 +stool_0042 +stool_0043 +stool_0044 +stool_0045 +stool_0046 +stool_0047 +stool_0048 +stool_0049 +stool_0050 +stool_0051 +stool_0052 +stool_0053 +stool_0054 +stool_0055 +stool_0056 +stool_0057 +stool_0058 +stool_0059 +stool_0060 +stool_0061 +stool_0062 +stool_0063 +stool_0064 +stool_0065 +stool_0066 +stool_0067 +stool_0068 +stool_0069 +stool_0070 +stool_0071 +stool_0072 +stool_0073 +stool_0074 +stool_0075 +stool_0076 +stool_0077 +stool_0078 +stool_0079 +stool_0080 +stool_0081 +stool_0082 +stool_0083 +stool_0084 +stool_0085 +stool_0086 +stool_0087 +stool_0088 +stool_0089 +stool_0090 +table_0001 +table_0002 +table_0003 +table_0004 +table_0005 +table_0006 +table_0007 +table_0008 +table_0009 +table_0010 +table_0011 +table_0012 +table_0013 +table_0014 +table_0015 +table_0016 +table_0017 +table_0018 +table_0019 +table_0020 +table_0021 +table_0022 +table_0023 +table_0024 +table_0025 +table_0026 +table_0027 +table_0028 +table_0029 +table_0030 +table_0031 +table_0032 +table_0033 +table_0034 +table_0035 +table_0036 +table_0037 +table_0038 +table_0039 +table_0040 +table_0041 +table_0042 +table_0043 +table_0044 +table_0045 +table_0046 +table_0047 +table_0048 +table_0049 +table_0050 +table_0051 +table_0052 +table_0053 +table_0054 +table_0055 +table_0056 +table_0057 +table_0058 +table_0059 +table_0060 +table_0061 +table_0062 +table_0063 +table_0064 +table_0065 +table_0066 +table_0067 +table_0068 +table_0069 +table_0070 +table_0071 +table_0072 +table_0073 +table_0074 +table_0075 +table_0076 +table_0077 +table_0078 +table_0079 +table_0080 +table_0081 +table_0082 +table_0083 +table_0084 +table_0085 +table_0086 +table_0087 +table_0088 +table_0089 +table_0090 +table_0091 +table_0092 +table_0093 +table_0094 +table_0095 +table_0096 +table_0097 +table_0098 +table_0099 +table_0100 +table_0101 +table_0102 +table_0103 +table_0104 +table_0105 +table_0106 +table_0107 +table_0108 +table_0109 +table_0110 +table_0111 +table_0112 +table_0113 +table_0114 +table_0115 +table_0116 +table_0117 +table_0118 +table_0119 +table_0120 +table_0121 +table_0122 +table_0123 +table_0124 +table_0125 +table_0126 +table_0127 +table_0128 +table_0129 +table_0130 +table_0131 +table_0132 +table_0133 +table_0134 +table_0135 +table_0136 +table_0137 +table_0138 +table_0139 +table_0140 +table_0141 +table_0142 +table_0143 +table_0144 +table_0145 +table_0146 +table_0147 +table_0148 +table_0149 +table_0150 +table_0151 +table_0152 +table_0153 +table_0154 +table_0155 +table_0156 +table_0157 +table_0158 +table_0159 +table_0160 +table_0161 +table_0162 +table_0163 +table_0164 +table_0165 +table_0166 +table_0167 +table_0168 +table_0169 +table_0170 +table_0171 +table_0172 +table_0173 +table_0174 +table_0175 +table_0176 +table_0177 +table_0178 +table_0179 +table_0180 +table_0181 +table_0182 +table_0183 +table_0184 +table_0185 +table_0186 +table_0187 +table_0188 +table_0189 +table_0190 +table_0191 +table_0192 +table_0193 +table_0194 +table_0195 +table_0196 +table_0197 +table_0198 +table_0199 +table_0200 +table_0201 +table_0202 +table_0203 +table_0204 +table_0205 +table_0206 +table_0207 +table_0208 +table_0209 +table_0210 +table_0211 +table_0212 +table_0213 +table_0214 +table_0215 +table_0216 +table_0217 +table_0218 +table_0219 +table_0220 +table_0221 +table_0222 +table_0223 +table_0224 +table_0225 +table_0226 +table_0227 +table_0228 +table_0229 +table_0230 +table_0231 +table_0232 +table_0233 +table_0234 +table_0235 +table_0236 +table_0237 +table_0238 +table_0239 +table_0240 +table_0241 +table_0242 +table_0243 +table_0244 +table_0245 +table_0246 +table_0247 +table_0248 +table_0249 +table_0250 +table_0251 +table_0252 +table_0253 +table_0254 +table_0255 +table_0256 +table_0257 +table_0258 +table_0259 +table_0260 +table_0261 +table_0262 +table_0263 +table_0264 +table_0265 +table_0266 +table_0267 +table_0268 +table_0269 +table_0270 +table_0271 +table_0272 +table_0273 +table_0274 +table_0275 +table_0276 +table_0277 +table_0278 +table_0279 +table_0280 +table_0281 +table_0282 +table_0283 +table_0284 +table_0285 +table_0286 +table_0287 +table_0288 +table_0289 +table_0290 +table_0291 +table_0292 +table_0293 +table_0294 +table_0295 +table_0296 +table_0297 +table_0298 +table_0299 +table_0300 +table_0301 +table_0302 +table_0303 +table_0304 +table_0305 +table_0306 +table_0307 +table_0308 +table_0309 +table_0310 +table_0311 +table_0312 +table_0313 +table_0314 +table_0315 +table_0316 +table_0317 +table_0318 +table_0319 +table_0320 +table_0321 +table_0322 +table_0323 +table_0324 +table_0325 +table_0326 +table_0327 +table_0328 +table_0329 +table_0330 +table_0331 +table_0332 +table_0333 +table_0334 +table_0335 +table_0336 +table_0337 +table_0338 +table_0339 +table_0340 +table_0341 +table_0342 +table_0343 +table_0344 +table_0345 +table_0346 +table_0347 +table_0348 +table_0349 +table_0350 +table_0351 +table_0352 +table_0353 +table_0354 +table_0355 +table_0356 +table_0357 +table_0358 +table_0359 +table_0360 +table_0361 +table_0362 +table_0363 +table_0364 +table_0365 +table_0366 +table_0367 +table_0368 +table_0369 +table_0370 +table_0371 +table_0372 +table_0373 +table_0374 +table_0375 +table_0376 +table_0377 +table_0378 +table_0379 +table_0380 +table_0381 +table_0382 +table_0383 +table_0384 +table_0385 +table_0386 +table_0387 +table_0388 +table_0389 +table_0390 +table_0391 +table_0392 +tent_0001 +tent_0002 +tent_0003 +tent_0004 +tent_0005 +tent_0006 +tent_0007 +tent_0008 +tent_0009 +tent_0010 +tent_0011 +tent_0012 +tent_0013 +tent_0014 +tent_0015 +tent_0016 +tent_0017 +tent_0018 +tent_0019 +tent_0020 +tent_0021 +tent_0022 +tent_0023 +tent_0024 +tent_0025 +tent_0026 +tent_0027 +tent_0028 +tent_0029 +tent_0030 +tent_0031 +tent_0032 +tent_0033 +tent_0034 +tent_0035 +tent_0036 +tent_0037 +tent_0038 +tent_0039 +tent_0040 +tent_0041 +tent_0042 +tent_0043 +tent_0044 +tent_0045 +tent_0046 +tent_0047 +tent_0048 +tent_0049 +tent_0050 +tent_0051 +tent_0052 +tent_0053 +tent_0054 +tent_0055 +tent_0056 +tent_0057 +tent_0058 +tent_0059 +tent_0060 +tent_0061 +tent_0062 +tent_0063 +tent_0064 +tent_0065 +tent_0066 +tent_0067 +tent_0068 +tent_0069 +tent_0070 +tent_0071 +tent_0072 +tent_0073 +tent_0074 +tent_0075 +tent_0076 +tent_0077 +tent_0078 +tent_0079 +tent_0080 +tent_0081 +tent_0082 +tent_0083 +tent_0084 +tent_0085 +tent_0086 +tent_0087 +tent_0088 +tent_0089 +tent_0090 +tent_0091 +tent_0092 +tent_0093 +tent_0094 +tent_0095 +tent_0096 +tent_0097 +tent_0098 +tent_0099 +tent_0100 +tent_0101 +tent_0102 +tent_0103 +tent_0104 +tent_0105 +tent_0106 +tent_0107 +tent_0108 +tent_0109 +tent_0110 +tent_0111 +tent_0112 +tent_0113 +tent_0114 +tent_0115 +tent_0116 +tent_0117 +tent_0118 +tent_0119 +tent_0120 +tent_0121 +tent_0122 +tent_0123 +tent_0124 +tent_0125 +tent_0126 +tent_0127 +tent_0128 +tent_0129 +tent_0130 +tent_0131 +tent_0132 +tent_0133 +tent_0134 +tent_0135 +tent_0136 +tent_0137 +tent_0138 +tent_0139 +tent_0140 +tent_0141 +tent_0142 +tent_0143 +tent_0144 +tent_0145 +tent_0146 +tent_0147 +tent_0148 +tent_0149 +tent_0150 +tent_0151 +tent_0152 +tent_0153 +tent_0154 +tent_0155 +tent_0156 +tent_0157 +tent_0158 +tent_0159 +tent_0160 +tent_0161 +tent_0162 +tent_0163 +toilet_0001 +toilet_0002 +toilet_0003 +toilet_0004 +toilet_0005 +toilet_0006 +toilet_0007 +toilet_0008 +toilet_0009 +toilet_0010 +toilet_0011 +toilet_0012 +toilet_0013 +toilet_0014 +toilet_0015 +toilet_0016 +toilet_0017 +toilet_0018 +toilet_0019 +toilet_0020 +toilet_0021 +toilet_0022 +toilet_0023 +toilet_0024 +toilet_0025 +toilet_0026 +toilet_0027 +toilet_0028 +toilet_0029 +toilet_0030 +toilet_0031 +toilet_0032 +toilet_0033 +toilet_0034 +toilet_0035 +toilet_0036 +toilet_0037 +toilet_0038 +toilet_0039 +toilet_0040 +toilet_0041 +toilet_0042 +toilet_0043 +toilet_0044 +toilet_0045 +toilet_0046 +toilet_0047 +toilet_0048 +toilet_0049 +toilet_0050 +toilet_0051 +toilet_0052 +toilet_0053 +toilet_0054 +toilet_0055 +toilet_0056 +toilet_0057 +toilet_0058 +toilet_0059 +toilet_0060 +toilet_0061 +toilet_0062 +toilet_0063 +toilet_0064 +toilet_0065 +toilet_0066 +toilet_0067 +toilet_0068 +toilet_0069 +toilet_0070 +toilet_0071 +toilet_0072 +toilet_0073 +toilet_0074 +toilet_0075 +toilet_0076 +toilet_0077 +toilet_0078 +toilet_0079 +toilet_0080 +toilet_0081 +toilet_0082 +toilet_0083 +toilet_0084 +toilet_0085 +toilet_0086 +toilet_0087 +toilet_0088 +toilet_0089 +toilet_0090 +toilet_0091 +toilet_0092 +toilet_0093 +toilet_0094 +toilet_0095 +toilet_0096 +toilet_0097 +toilet_0098 +toilet_0099 +toilet_0100 +toilet_0101 +toilet_0102 +toilet_0103 +toilet_0104 +toilet_0105 +toilet_0106 +toilet_0107 +toilet_0108 +toilet_0109 +toilet_0110 +toilet_0111 +toilet_0112 +toilet_0113 +toilet_0114 +toilet_0115 +toilet_0116 +toilet_0117 +toilet_0118 +toilet_0119 +toilet_0120 +toilet_0121 +toilet_0122 +toilet_0123 +toilet_0124 +toilet_0125 +toilet_0126 +toilet_0127 +toilet_0128 +toilet_0129 +toilet_0130 +toilet_0131 +toilet_0132 +toilet_0133 +toilet_0134 +toilet_0135 +toilet_0136 +toilet_0137 +toilet_0138 +toilet_0139 +toilet_0140 +toilet_0141 +toilet_0142 +toilet_0143 +toilet_0144 +toilet_0145 +toilet_0146 +toilet_0147 +toilet_0148 +toilet_0149 +toilet_0150 +toilet_0151 +toilet_0152 +toilet_0153 +toilet_0154 +toilet_0155 +toilet_0156 +toilet_0157 +toilet_0158 +toilet_0159 +toilet_0160 +toilet_0161 +toilet_0162 +toilet_0163 +toilet_0164 +toilet_0165 +toilet_0166 +toilet_0167 +toilet_0168 +toilet_0169 +toilet_0170 +toilet_0171 +toilet_0172 +toilet_0173 +toilet_0174 +toilet_0175 +toilet_0176 +toilet_0177 +toilet_0178 +toilet_0179 +toilet_0180 +toilet_0181 +toilet_0182 +toilet_0183 +toilet_0184 +toilet_0185 +toilet_0186 +toilet_0187 +toilet_0188 +toilet_0189 +toilet_0190 +toilet_0191 +toilet_0192 +toilet_0193 +toilet_0194 +toilet_0195 +toilet_0196 +toilet_0197 +toilet_0198 +toilet_0199 +toilet_0200 +toilet_0201 +toilet_0202 +toilet_0203 +toilet_0204 +toilet_0205 +toilet_0206 +toilet_0207 +toilet_0208 +toilet_0209 +toilet_0210 +toilet_0211 +toilet_0212 +toilet_0213 +toilet_0214 +toilet_0215 +toilet_0216 +toilet_0217 +toilet_0218 +toilet_0219 +toilet_0220 +toilet_0221 +toilet_0222 +toilet_0223 +toilet_0224 +toilet_0225 +toilet_0226 +toilet_0227 +toilet_0228 +toilet_0229 +toilet_0230 +toilet_0231 +toilet_0232 +toilet_0233 +toilet_0234 +toilet_0235 +toilet_0236 +toilet_0237 +toilet_0238 +toilet_0239 +toilet_0240 +toilet_0241 +toilet_0242 +toilet_0243 +toilet_0244 +toilet_0245 +toilet_0246 +toilet_0247 +toilet_0248 +toilet_0249 +toilet_0250 +toilet_0251 +toilet_0252 +toilet_0253 +toilet_0254 +toilet_0255 +toilet_0256 +toilet_0257 +toilet_0258 +toilet_0259 +toilet_0260 +toilet_0261 +toilet_0262 +toilet_0263 +toilet_0264 +toilet_0265 +toilet_0266 +toilet_0267 +toilet_0268 +toilet_0269 +toilet_0270 +toilet_0271 +toilet_0272 +toilet_0273 +toilet_0274 +toilet_0275 +toilet_0276 +toilet_0277 +toilet_0278 +toilet_0279 +toilet_0280 +toilet_0281 +toilet_0282 +toilet_0283 +toilet_0284 +toilet_0285 +toilet_0286 +toilet_0287 +toilet_0288 +toilet_0289 +toilet_0290 +toilet_0291 +toilet_0292 +toilet_0293 +toilet_0294 +toilet_0295 +toilet_0296 +toilet_0297 +toilet_0298 +toilet_0299 +toilet_0300 +toilet_0301 +toilet_0302 +toilet_0303 +toilet_0304 +toilet_0305 +toilet_0306 +toilet_0307 +toilet_0308 +toilet_0309 +toilet_0310 +toilet_0311 +toilet_0312 +toilet_0313 +toilet_0314 +toilet_0315 +toilet_0316 +toilet_0317 +toilet_0318 +toilet_0319 +toilet_0320 +toilet_0321 +toilet_0322 +toilet_0323 +toilet_0324 +toilet_0325 +toilet_0326 +toilet_0327 +toilet_0328 +toilet_0329 +toilet_0330 +toilet_0331 +toilet_0332 +toilet_0333 +toilet_0334 +toilet_0335 +toilet_0336 +toilet_0337 +toilet_0338 +toilet_0339 +toilet_0340 +toilet_0341 +toilet_0342 +toilet_0343 +toilet_0344 +tv_stand_0001 +tv_stand_0002 +tv_stand_0003 +tv_stand_0004 +tv_stand_0005 +tv_stand_0006 +tv_stand_0007 +tv_stand_0008 +tv_stand_0009 +tv_stand_0010 +tv_stand_0011 +tv_stand_0012 +tv_stand_0013 +tv_stand_0014 +tv_stand_0015 +tv_stand_0016 +tv_stand_0017 +tv_stand_0018 +tv_stand_0019 +tv_stand_0020 +tv_stand_0021 +tv_stand_0022 +tv_stand_0023 +tv_stand_0024 +tv_stand_0025 +tv_stand_0026 +tv_stand_0027 +tv_stand_0028 +tv_stand_0029 +tv_stand_0030 +tv_stand_0031 +tv_stand_0032 +tv_stand_0033 +tv_stand_0034 +tv_stand_0035 +tv_stand_0036 +tv_stand_0037 +tv_stand_0038 +tv_stand_0039 +tv_stand_0040 +tv_stand_0041 +tv_stand_0042 +tv_stand_0043 +tv_stand_0044 +tv_stand_0045 +tv_stand_0046 +tv_stand_0047 +tv_stand_0048 +tv_stand_0049 +tv_stand_0050 +tv_stand_0051 +tv_stand_0052 +tv_stand_0053 +tv_stand_0054 +tv_stand_0055 +tv_stand_0056 +tv_stand_0057 +tv_stand_0058 +tv_stand_0059 +tv_stand_0060 +tv_stand_0061 +tv_stand_0062 +tv_stand_0063 +tv_stand_0064 +tv_stand_0065 +tv_stand_0066 +tv_stand_0067 +tv_stand_0068 +tv_stand_0069 +tv_stand_0070 +tv_stand_0071 +tv_stand_0072 +tv_stand_0073 +tv_stand_0074 +tv_stand_0075 +tv_stand_0076 +tv_stand_0077 +tv_stand_0078 +tv_stand_0079 +tv_stand_0080 +tv_stand_0081 +tv_stand_0082 +tv_stand_0083 +tv_stand_0084 +tv_stand_0085 +tv_stand_0086 +tv_stand_0087 +tv_stand_0088 +tv_stand_0089 +tv_stand_0090 +tv_stand_0091 +tv_stand_0092 +tv_stand_0093 +tv_stand_0094 +tv_stand_0095 +tv_stand_0096 +tv_stand_0097 +tv_stand_0098 +tv_stand_0099 +tv_stand_0100 +tv_stand_0101 +tv_stand_0102 +tv_stand_0103 +tv_stand_0104 +tv_stand_0105 +tv_stand_0106 +tv_stand_0107 +tv_stand_0108 +tv_stand_0109 +tv_stand_0110 +tv_stand_0111 +tv_stand_0112 +tv_stand_0113 +tv_stand_0114 +tv_stand_0115 +tv_stand_0116 +tv_stand_0117 +tv_stand_0118 +tv_stand_0119 +tv_stand_0120 +tv_stand_0121 +tv_stand_0122 +tv_stand_0123 +tv_stand_0124 +tv_stand_0125 +tv_stand_0126 +tv_stand_0127 +tv_stand_0128 +tv_stand_0129 +tv_stand_0130 +tv_stand_0131 +tv_stand_0132 +tv_stand_0133 +tv_stand_0134 +tv_stand_0135 +tv_stand_0136 +tv_stand_0137 +tv_stand_0138 +tv_stand_0139 +tv_stand_0140 +tv_stand_0141 +tv_stand_0142 +tv_stand_0143 +tv_stand_0144 +tv_stand_0145 +tv_stand_0146 +tv_stand_0147 +tv_stand_0148 +tv_stand_0149 +tv_stand_0150 +tv_stand_0151 +tv_stand_0152 +tv_stand_0153 +tv_stand_0154 +tv_stand_0155 +tv_stand_0156 +tv_stand_0157 +tv_stand_0158 +tv_stand_0159 +tv_stand_0160 +tv_stand_0161 +tv_stand_0162 +tv_stand_0163 +tv_stand_0164 +tv_stand_0165 +tv_stand_0166 +tv_stand_0167 +tv_stand_0168 +tv_stand_0169 +tv_stand_0170 +tv_stand_0171 +tv_stand_0172 +tv_stand_0173 +tv_stand_0174 +tv_stand_0175 +tv_stand_0176 +tv_stand_0177 +tv_stand_0178 +tv_stand_0179 +tv_stand_0180 +tv_stand_0181 +tv_stand_0182 +tv_stand_0183 +tv_stand_0184 +tv_stand_0185 +tv_stand_0186 +tv_stand_0187 +tv_stand_0188 +tv_stand_0189 +tv_stand_0190 +tv_stand_0191 +tv_stand_0192 +tv_stand_0193 +tv_stand_0194 +tv_stand_0195 +tv_stand_0196 +tv_stand_0197 +tv_stand_0198 +tv_stand_0199 +tv_stand_0200 +tv_stand_0201 +tv_stand_0202 +tv_stand_0203 +tv_stand_0204 +tv_stand_0205 +tv_stand_0206 +tv_stand_0207 +tv_stand_0208 +tv_stand_0209 +tv_stand_0210 +tv_stand_0211 +tv_stand_0212 +tv_stand_0213 +tv_stand_0214 +tv_stand_0215 +tv_stand_0216 +tv_stand_0217 +tv_stand_0218 +tv_stand_0219 +tv_stand_0220 +tv_stand_0221 +tv_stand_0222 +tv_stand_0223 +tv_stand_0224 +tv_stand_0225 +tv_stand_0226 +tv_stand_0227 +tv_stand_0228 +tv_stand_0229 +tv_stand_0230 +tv_stand_0231 +tv_stand_0232 +tv_stand_0233 +tv_stand_0234 +tv_stand_0235 +tv_stand_0236 +tv_stand_0237 +tv_stand_0238 +tv_stand_0239 +tv_stand_0240 +tv_stand_0241 +tv_stand_0242 +tv_stand_0243 +tv_stand_0244 +tv_stand_0245 +tv_stand_0246 +tv_stand_0247 +tv_stand_0248 +tv_stand_0249 +tv_stand_0250 +tv_stand_0251 +tv_stand_0252 +tv_stand_0253 +tv_stand_0254 +tv_stand_0255 +tv_stand_0256 +tv_stand_0257 +tv_stand_0258 +tv_stand_0259 +tv_stand_0260 +tv_stand_0261 +tv_stand_0262 +tv_stand_0263 +tv_stand_0264 +tv_stand_0265 +tv_stand_0266 +tv_stand_0267 +vase_0001 +vase_0002 +vase_0003 +vase_0004 +vase_0005 +vase_0006 +vase_0007 +vase_0008 +vase_0009 +vase_0010 +vase_0011 +vase_0012 +vase_0013 +vase_0014 +vase_0015 +vase_0016 +vase_0017 +vase_0018 +vase_0019 +vase_0020 +vase_0021 +vase_0022 +vase_0023 +vase_0024 +vase_0025 +vase_0026 +vase_0027 +vase_0028 +vase_0029 +vase_0030 +vase_0031 +vase_0032 +vase_0033 +vase_0034 +vase_0035 +vase_0036 +vase_0037 +vase_0038 +vase_0039 +vase_0040 +vase_0041 +vase_0042 +vase_0043 +vase_0044 +vase_0045 +vase_0046 +vase_0047 +vase_0048 +vase_0049 +vase_0050 +vase_0051 +vase_0052 +vase_0053 +vase_0054 +vase_0055 +vase_0056 +vase_0057 +vase_0058 +vase_0059 +vase_0060 +vase_0061 +vase_0062 +vase_0063 +vase_0064 +vase_0065 +vase_0066 +vase_0067 +vase_0068 +vase_0069 +vase_0070 +vase_0071 +vase_0072 +vase_0073 +vase_0074 +vase_0075 +vase_0076 +vase_0077 +vase_0078 +vase_0079 +vase_0080 +vase_0081 +vase_0082 +vase_0083 +vase_0084 +vase_0085 +vase_0086 +vase_0087 +vase_0088 +vase_0089 +vase_0090 +vase_0091 +vase_0092 +vase_0093 +vase_0094 +vase_0095 +vase_0096 +vase_0097 +vase_0098 +vase_0099 +vase_0100 +vase_0101 +vase_0102 +vase_0103 +vase_0104 +vase_0105 +vase_0106 +vase_0107 +vase_0108 +vase_0109 +vase_0110 +vase_0111 +vase_0112 +vase_0113 +vase_0114 +vase_0115 +vase_0116 +vase_0117 +vase_0118 +vase_0119 +vase_0120 +vase_0121 +vase_0122 +vase_0123 +vase_0124 +vase_0125 +vase_0126 +vase_0127 +vase_0128 +vase_0129 +vase_0130 +vase_0131 +vase_0132 +vase_0133 +vase_0134 +vase_0135 +vase_0136 +vase_0137 +vase_0138 +vase_0139 +vase_0140 +vase_0141 +vase_0142 +vase_0143 +vase_0144 +vase_0145 +vase_0146 +vase_0147 +vase_0148 +vase_0149 +vase_0150 +vase_0151 +vase_0152 +vase_0153 +vase_0154 +vase_0155 +vase_0156 +vase_0157 +vase_0158 +vase_0159 +vase_0160 +vase_0161 +vase_0162 +vase_0163 +vase_0164 +vase_0165 +vase_0166 +vase_0167 +vase_0168 +vase_0169 +vase_0170 +vase_0171 +vase_0172 +vase_0173 +vase_0174 +vase_0175 +vase_0176 +vase_0177 +vase_0178 +vase_0179 +vase_0180 +vase_0181 +vase_0182 +vase_0183 +vase_0184 +vase_0185 +vase_0186 +vase_0187 +vase_0188 +vase_0189 +vase_0190 +vase_0191 +vase_0192 +vase_0193 +vase_0194 +vase_0195 +vase_0196 +vase_0197 +vase_0198 +vase_0199 +vase_0200 +vase_0201 +vase_0202 +vase_0203 +vase_0204 +vase_0205 +vase_0206 +vase_0207 +vase_0208 +vase_0209 +vase_0210 +vase_0211 +vase_0212 +vase_0213 +vase_0214 +vase_0215 +vase_0216 +vase_0217 +vase_0218 +vase_0219 +vase_0220 +vase_0221 +vase_0222 +vase_0223 +vase_0224 +vase_0225 +vase_0226 +vase_0227 +vase_0228 +vase_0229 +vase_0230 +vase_0231 +vase_0232 +vase_0233 +vase_0234 +vase_0235 +vase_0236 +vase_0237 +vase_0238 +vase_0239 +vase_0240 +vase_0241 +vase_0242 +vase_0243 +vase_0244 +vase_0245 +vase_0246 +vase_0247 +vase_0248 +vase_0249 +vase_0250 +vase_0251 +vase_0252 +vase_0253 +vase_0254 +vase_0255 +vase_0256 +vase_0257 +vase_0258 +vase_0259 +vase_0260 +vase_0261 +vase_0262 +vase_0263 +vase_0264 +vase_0265 +vase_0266 +vase_0267 +vase_0268 +vase_0269 +vase_0270 +vase_0271 +vase_0272 +vase_0273 +vase_0274 +vase_0275 +vase_0276 +vase_0277 +vase_0278 +vase_0279 +vase_0280 +vase_0281 +vase_0282 +vase_0283 +vase_0284 +vase_0285 +vase_0286 +vase_0287 +vase_0288 +vase_0289 +vase_0290 +vase_0291 +vase_0292 +vase_0293 +vase_0294 +vase_0295 +vase_0296 +vase_0297 +vase_0298 +vase_0299 +vase_0300 +vase_0301 +vase_0302 +vase_0303 +vase_0304 +vase_0305 +vase_0306 +vase_0307 +vase_0308 +vase_0309 +vase_0310 +vase_0311 +vase_0312 +vase_0313 +vase_0314 +vase_0315 +vase_0316 +vase_0317 +vase_0318 +vase_0319 +vase_0320 +vase_0321 +vase_0322 +vase_0323 +vase_0324 +vase_0325 +vase_0326 +vase_0327 +vase_0328 +vase_0329 +vase_0330 +vase_0331 +vase_0332 +vase_0333 +vase_0334 +vase_0335 +vase_0336 +vase_0337 +vase_0338 +vase_0339 +vase_0340 +vase_0341 +vase_0342 +vase_0343 +vase_0344 +vase_0345 +vase_0346 +vase_0347 +vase_0348 +vase_0349 +vase_0350 +vase_0351 +vase_0352 +vase_0353 +vase_0354 +vase_0355 +vase_0356 +vase_0357 +vase_0358 +vase_0359 +vase_0360 +vase_0361 +vase_0362 +vase_0363 +vase_0364 +vase_0365 +vase_0366 +vase_0367 +vase_0368 +vase_0369 +vase_0370 +vase_0371 +vase_0372 +vase_0373 +vase_0374 +vase_0375 +vase_0376 +vase_0377 +vase_0378 +vase_0379 +vase_0380 +vase_0381 +vase_0382 +vase_0383 +vase_0384 +vase_0385 +vase_0386 +vase_0387 +vase_0388 +vase_0389 +vase_0390 +vase_0391 +vase_0392 +vase_0393 +vase_0394 +vase_0395 +vase_0396 +vase_0397 +vase_0398 +vase_0399 +vase_0400 +vase_0401 +vase_0402 +vase_0403 +vase_0404 +vase_0405 +vase_0406 +vase_0407 +vase_0408 +vase_0409 +vase_0410 +vase_0411 +vase_0412 +vase_0413 +vase_0414 +vase_0415 +vase_0416 +vase_0417 +vase_0418 +vase_0419 +vase_0420 +vase_0421 +vase_0422 +vase_0423 +vase_0424 +vase_0425 +vase_0426 +vase_0427 +vase_0428 +vase_0429 +vase_0430 +vase_0431 +vase_0432 +vase_0433 +vase_0434 +vase_0435 +vase_0436 +vase_0437 +vase_0438 +vase_0439 +vase_0440 +vase_0441 +vase_0442 +vase_0443 +vase_0444 +vase_0445 +vase_0446 +vase_0447 +vase_0448 +vase_0449 +vase_0450 +vase_0451 +vase_0452 +vase_0453 +vase_0454 +vase_0455 +vase_0456 +vase_0457 +vase_0458 +vase_0459 +vase_0460 +vase_0461 +vase_0462 +vase_0463 +vase_0464 +vase_0465 +vase_0466 +vase_0467 +vase_0468 +vase_0469 +vase_0470 +vase_0471 +vase_0472 +vase_0473 +vase_0474 +vase_0475 +wardrobe_0001 +wardrobe_0002 +wardrobe_0003 +wardrobe_0004 +wardrobe_0005 +wardrobe_0006 +wardrobe_0007 +wardrobe_0008 +wardrobe_0009 +wardrobe_0010 +wardrobe_0011 +wardrobe_0012 +wardrobe_0013 +wardrobe_0014 +wardrobe_0015 +wardrobe_0016 +wardrobe_0017 +wardrobe_0018 +wardrobe_0019 +wardrobe_0020 +wardrobe_0021 +wardrobe_0022 +wardrobe_0023 +wardrobe_0024 +wardrobe_0025 +wardrobe_0026 +wardrobe_0027 +wardrobe_0028 +wardrobe_0029 +wardrobe_0030 +wardrobe_0031 +wardrobe_0032 +wardrobe_0033 +wardrobe_0034 +wardrobe_0035 +wardrobe_0036 +wardrobe_0037 +wardrobe_0038 +wardrobe_0039 +wardrobe_0040 +wardrobe_0041 +wardrobe_0042 +wardrobe_0043 +wardrobe_0044 +wardrobe_0045 +wardrobe_0046 +wardrobe_0047 +wardrobe_0048 +wardrobe_0049 +wardrobe_0050 +wardrobe_0051 +wardrobe_0052 +wardrobe_0053 +wardrobe_0054 +wardrobe_0055 +wardrobe_0056 +wardrobe_0057 +wardrobe_0058 +wardrobe_0059 +wardrobe_0060 +wardrobe_0061 +wardrobe_0062 +wardrobe_0063 +wardrobe_0064 +wardrobe_0065 +wardrobe_0066 +wardrobe_0067 +wardrobe_0068 +wardrobe_0069 +wardrobe_0070 +wardrobe_0071 +wardrobe_0072 +wardrobe_0073 +wardrobe_0074 +wardrobe_0075 +wardrobe_0076 +wardrobe_0077 +wardrobe_0078 +wardrobe_0079 +wardrobe_0080 +wardrobe_0081 +wardrobe_0082 +wardrobe_0083 +wardrobe_0084 +wardrobe_0085 +wardrobe_0086 +wardrobe_0087 +xbox_0001 +xbox_0002 +xbox_0003 +xbox_0004 +xbox_0005 +xbox_0006 +xbox_0007 +xbox_0008 +xbox_0009 +xbox_0010 +xbox_0011 +xbox_0012 +xbox_0013 +xbox_0014 +xbox_0015 +xbox_0016 +xbox_0017 +xbox_0018 +xbox_0019 +xbox_0020 +xbox_0021 +xbox_0022 +xbox_0023 +xbox_0024 +xbox_0025 +xbox_0026 +xbox_0027 +xbox_0028 +xbox_0029 +xbox_0030 +xbox_0031 +xbox_0032 +xbox_0033 +xbox_0034 +xbox_0035 +xbox_0036 +xbox_0037 +xbox_0038 +xbox_0039 +xbox_0040 +xbox_0041 +xbox_0042 +xbox_0043 +xbox_0044 +xbox_0045 +xbox_0046 +xbox_0047 +xbox_0048 +xbox_0049 +xbox_0050 +xbox_0051 +xbox_0052 +xbox_0053 +xbox_0054 +xbox_0055 +xbox_0056 +xbox_0057 +xbox_0058 +xbox_0059 +xbox_0060 +xbox_0061 +xbox_0062 +xbox_0063 +xbox_0064 +xbox_0065 +xbox_0066 +xbox_0067 +xbox_0068 +xbox_0069 +xbox_0070 +xbox_0071 +xbox_0072 +xbox_0073 +xbox_0074 +xbox_0075 +xbox_0076 +xbox_0077 +xbox_0078 +xbox_0079 +xbox_0080 +xbox_0081 +xbox_0082 +xbox_0083 +xbox_0084 +xbox_0085 +xbox_0086 +xbox_0087 +xbox_0088 +xbox_0089 +xbox_0090 +xbox_0091 +xbox_0092 +xbox_0093 +xbox_0094 +xbox_0095 +xbox_0096 +xbox_0097 +xbox_0098 +xbox_0099 +xbox_0100 +xbox_0101 +xbox_0102 +xbox_0103 diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ScanObjectNN_shape_names.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ScanObjectNN_shape_names.txt new file mode 100644 index 00000000..1dbfdb70 --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ScanObjectNN_shape_names.txt @@ -0,0 +1,15 @@ +bag +bin +box +cabinet +chair +desk +display +door +shelf +table +bed +pillow +sink +sofa +toilet \ No newline at end of file diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/test.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/test.txt new file mode 100644 index 00000000..48294e62 --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/test.txt @@ -0,0 +1,10518 @@ +03759954-109f1779a6993782f6426d6e3b63c5ce.npy +03759954-b726f3df205d3b5911daf38720b2dbe4.npy +04330267-aa0f6ff9f592b327eadb8f8b5bc7d9a5.npy +04330267-966ea3afa71e3a574bba687d3dbe6227.npy +03759954-baca1996923c25f943a6722dac94523b.npy +04330267-bc2daa0406ad3324d724d9ce5af6d8e.npy +04330267-f56ea6d924207b5515c4fa96a52ac4ff.npy +03261776-64ab866236bd012a43ccf9e3e30b934d.npy +04330267-f5c26b7b35991739281d68269dab9234.npy +04330267-a95a8fc9fa81aadf40332412c5d013fb.npy +03261776-5bb7c6bcd79bd45e16262e5b395acc86.npy +04330267-821634b0caa5cdb57f0571f06b666f9f.npy +03513137-ba62b73074d51637b61d7759f8544b8a.npy +03759954-e491db83f21a5a6c4fdb7f619836e43d.npy +03513137-89815c92980efb27226eabe1cca3e850.npy +04330267-65eb72bf33da5b1511ff208156ce047.npy +04330267-d6bbaeb047b53c43e6b2f975f419eaae.npy +03261776-97940f715478c1c4ce76da9b42b3ec76.npy +04330267-24dfeb26cc47a046e6fbf2f5ae574e36.npy +03513137-45d6e3b0b91073af7359b134afde902.npy +03759954-ae85334cc3752412374e74ec21028517.npy +03261776-e17597ea42e1e18f3f1da4d22f591d97.npy +04460130-44e8212fe3d44b1ec8b200f28f6c5853.npy +04468005-c6486d5bb854e5758e966271baaa42c9.npy +03513137-a612b83619ce985f3de9dfa8d65133cb.npy +04468005-bc1c21333b5e22bf8145a50db7d52d60.npy +04468005-8e5519f10f0748695a7f2ba88db92d63.npy +04468005-3aafecb126c5e46d49906937a72a14ff.npy +04468005-565d7f01c9f8b6b53ae1361afc45ac52.npy +04330267-8c2491e5245804d1ffc6e457221b9271.npy +03513137-f778971235a67bba754cd8e5dd1ab945.npy +03761084-71221c380da96cbebe67d9b32c3ddf8.npy +03761084-b95c595576a3846aad0ab2bac067d6b1.npy +04468005-b7306885432f3bd5299a59bfd8e7d284.npy +04330267-1d5eb167825bacba688d3cf9b52f4662.npy +04004475-30a39487e93a01dc8eeae74a05480d07.npy +03938244-57992207eebe4009eb332cd2d2a300.npy +02992529-d5fd6679ddfc8ddc59f56ab706e2f74c.npy +04004475-266014617a73853f9a8c3855109c1ee0.npy +02808440-7e5857a4abbcbe9098dcd47b5c6dc2e5.npy +04468005-1f4f874957d140cbc834d88a99ade94d.npy +04468005-13aac1cbf34edd552470de2774d6099.npy +03759954-4bd87bb547f266f3133483af4507508a.npy +04460130-8cf718ed6a5fefd8fcaad7f5ff5ee65c.npy +03938244-e8a13e84cc6db127616f4ad120b6332a.npy +02992529-2eae0713342e1103397d790c3d0a8fb5.npy +03513137-2c9086096c0fe9889215d30ce83ed4dd.npy +04468005-84a3fd24d2cefcfcd781754d41e2576e.npy +02808440-25370f9a01166beaa13edbe825cc0113.npy +04460130-7696d47199f9055a79ea17c9c8a4feb0.npy +04530566-2c8725b9a09b6d0a44ebbc705ad8c07.npy +02871439-a27245122e4c284d67aad4e7f685c416.npy +04530566-f2e303d85466a0fd88d5590328ce0ddf.npy +02871439-ca56637ae250ff1259adebe36b392f27.npy +03593526-276bff32316ddd3eec0dc003f0209134.npy +02871439-a45d9c141a0ae4a627afb81497348633.npy +04530566-ad8c4e406743c29a5b84e0ded5ffcc87.npy +04530566-2a86437a50f1b51727ac692756be9e24.npy +04530566-d188b20659011142c8067f9682b92f0e.npy +04530566-12900e06f0f4ec9e49f471d054f6b528.npy +04530566-de7c3942e8a460ffa9bd9d33180e7ac0.npy +04530566-957ac9708448e111f0ef63bb932093ce.npy +04554684-b91045b62241ebd158c88d30f502a452.npy +03761084-6942c30f25bbcde7ced224a469840964.npy +04530566-d1e59a48852965fb036cb639ea80765.npy +03938244-efd9fffc04d235dab55fde51a411949f.npy +03467517-8402cf0cbb6dfc92b5b477b4ad381f9.npy +02992529-298ca71453baf6ee2a9eb0f146e94477.npy +02871439-6f65749bdf82cca8d810b14a81e12eca.npy +04530566-d703643f4a4f76a16c63b8b48495261a.npy +04530566-296f0b6a15012e33d87f29c9afcc633e.npy +02992529-89f17a3563941ba9f2fdbae39bae1eff.npy +03467517-f86c277a6e1f444293f0194265a9746c.npy +02992529-d2f3eb92a31649647c17b7a9bb17a24.npy +02992529-657fbd67af945c39d9e3837723c05057.npy +02871439-704e5237bfe45aed809222e4341a7d65.npy +04530566-f26d39cd431135cbc92e1912af872cc.npy +03467517-a19b20b4ec66e57d6ee1932063f20d95.npy +02871439-dbcee69eecd13b3b5196bf7c8aa10ef1.npy +02992529-1e52452aeb4bacbd83156841b8188cc7.npy +04330267-f4f9375024901a8e41965be83b7745a.npy +03467517-2331b83b682e6dcd1082f2ea630bf69e.npy +02808440-2b9228db2c77130d44221bef0fa3c36b.npy +02992529-e33e1483c4c22b1ae71852a7b0e4fcb6.npy +02808440-caccc22a1266150d3321831d2245cf06.npy +02992529-ac0967f9fe8f63f46b2ba76eab0d2b1c.npy +02992529-515b5a63ebb56aad7aeb5bbdd191fd4d.npy +02808440-8932abdd856b615756e28fa5d4761d89.npy +03467517-dad399bf54b6186a40c20797381ee39f.npy +02992529-5f600251394fabe6808ca88aece2e3dc.npy +02992529-6e18484e72c79bf6943bfa124ea09a0b.npy +04401088-bf7daa3ade10ee75bad093be69512dcd.npy +04530566-2a3e2ecc6c6d3be83b2c1416b6e149a5.npy +02992529-baafe1add38af23a5f0b5b54dbc4f35c.npy +04530566-c359eef375afa3b6dd42314e00caace4.npy +02954340-188702a3bb44f40c284432ce2f42f498.npy +03467517-bdc8060a937278f25b6b4dd555e889f9.npy +02871439-ffdc8c4c72d7ca59ccbf1ee2df182caa.npy +04530566-b3090ee38204289cb90142192ec795d.npy +04530566-d0e9f4c4bb582c3cfa0636f27a8b2a9c.npy +03513137-73359cd0e38579745c351e299b24e355.npy +04460130-4264b506533b1e2e473f10e6caaeca56.npy +04401088-fc1675526d043e81a2811061ff7e0824.npy +04530566-ca529b32d5bccdfe7d66e5fb8a76ea1f.npy +03467517-4c5288cc18896f8f352e5d4d2615db5b.npy +04460130-e3f5234bfe086a3438cd8eb23853c009.npy +02808440-41c2075df14356713321831d2245cf06.npy +04401088-d2636f3af00fb3e2538f655e65b0b57.npy +02992529-54d5d64e0d3b0f95952ef623ec48449b.npy +02933112-3d5ef34ce469b11c5af597c14b093f6.npy +02933112-b9fd0cb66675dcc87c9ecef5753df626.npy +03593526-4d53bcb8348292d4b4be5695ea899000.npy +03467517-2f9d51c98d517ed1b647271c21ec40.npy +03642806-593d32126cea601d5a952e55d06611ce.npy +02808440-b7d1bc59194e2c5672101dcac4ed75d3.npy +04554684-c709c8a6cb97c8e55c67382e5c978dae.npy +02933112-c52cc29136169ea014038d588fd1342f.npy +02992529-6fe550e061e70579a05d3424fd8d541a.npy +04401088-e06b902efc1576c62fd4061aba358325.npy +04401088-f9ecc6749a251c0249852b2ef384d236.npy +03467517-e66d799f51f1558a2214be36f33a634a.npy +03467517-59e7e8bc76d47722b48e9ff3519bfb40.npy +04330267-e69db4d377603b7d37b2bb75885cfc44.npy +03593526-7bb71bbabeacfe9f27936e29850f1fad.npy +04401088-6cc44d39e099bb6b9ef9eb3ddb0818a.npy +02933112-2a9acc146f7310b1492d9da2668ec34c.npy +04530566-59fefd79eba35dbb723877c00e9cdc03.npy +02933112-3e881be7e5289fcb77a8ecb4b9a890c5.npy +02871439-601b64e8e27159e157da56e4c9ff868d.npy +02924116-27b5ee7b86057ba0c95c7a8a79dc0c72.npy +04401088-73ab63e7ac7a404b545fb5ece69fbf4e.npy +04530566-4d8ae6327ab4ed301e66f1783a4812d7.npy +04460130-c6e94a8464305378cedded8270815eaf.npy +04401088-b69603be92146a161ad8041551e9d3c2.npy +03467517-10158b6f14c2700871e863c034067817.npy +03642806-87ffe7aaa7304b1b775a6b1e21d79260.npy +02924116-40a40bc3ed3934a5a500884f38f28607.npy +03467517-42f3172b8770d2fd2200c35bfa7099ee.npy +04468005-25c3710ca5f245b8c62b7ed19a553484.npy +02992529-b8415769dc1bc92821844676433a0aca.npy +04530566-2c7a0d5909d8dd46a3599da6d4b3696d.npy +02808440-6e586dee4b54e6556ada9e1e675a2b32.npy +03593526-8b56cc59b433b83d42266d3d768f0d70.npy +02871439-aba0fe4f9da44175a51af6b739ab25e8.npy +04004475-c73c7f57faa4c40de5ae40d496bdd7b3.npy +02924116-dcc301919ebf2423b129901f80d24b7b.npy +02992529-9c1286570bbc6fc78f257ecba9a6ef8.npy +03593526-ce641a7a7b0cfe1ad85aa63241192dd1.npy +03467517-bfe1ea2edf94e0b86ee1932063f20d95.npy +03513137-3b45ee42f62559c74e5e6ac3ef6bff73.npy +04530566-99ecd71c5103416e698137c717c4ad11.npy +02933112-7ef036a41e1b9e2aac00fd1150223027.npy +04530566-49861c22df11a02b910f44c20a5d1839.npy +02992529-d050f7389538de04ae0591d02e40f07b.npy +04401088-d61ddb57397143e38d03482ac0270137.npy +02992529-528e6424ccdcf2af21844676433a0aca.npy +02954340-1eccbbbf1503c888f691355a196da5f.npy +04401088-fd3c1ac6cd1f94bd3982f71b09380baa.npy +03467517-1b7aed896667193ed5006a9fa189ec8a.npy +02933112-8e1a1e2879cfa2d6fe395915d44df772.npy +03467517-8d24a89192c4d9a593a3cb7ad5bbfafa.npy +02992529-6bda193370e2c7e9a30edee0b4a86a6c.npy +02871439-1761cc50604f9faef759bc1c69ff20e0.npy +04530566-e51dc5bb6b97700747d2f4d1390fa93e.npy +03642806-164b84d13b3d4650e096f6db40afe7bf.npy +02992529-18cb51f36acfe30a487d18402ebe69d5.npy +03642806-e55ececde88255b93e73f3893a7337bb.npy +02946921-7883b684806946276f056d414894e46d.npy +03467517-d528407fe43b5df193f0194265a9746c.npy +04530566-9fd71a532f7c732fb036cb639ea80765.npy +02992529-b35c2da756f8df5aa0eb5a85db887292.npy +02933112-5172c96ea99b9f5fde533fa000314311.npy +02933112-962de4481f2844aeba3e7e48acd3a1c6.npy +02808440-d6a1c1c47190649a54d7082b34825ef0.npy +02808440-f2306272d14861367c8e9b5cdcd2f0ef.npy +04530566-e42655032562701e746ffcbc44510229.npy +04401088-e71c51adfe4d4f00341e76467b172f31.npy +02933112-a03797c4034be11ac59350d819542ec7.npy +02992529-c65f71b54023ee9897d7ccf55973b548.npy +04530566-e1e3c053f4b4f1405e45696ec6d1a105.npy +02924116-cd89b45698f631a6a0975a87469abb37.npy +04401088-ac1e771d6392e912f594ca916b37180c.npy +03467517-4c082a95145f866a8388889c8d3c7bea.npy +02933112-b539b0bdf5c760b1c0eeb4326d5ba9e6.npy +02933112-7fbb7a6e017d3bd1921dd903dd0b8b17.npy +02933112-a5f28af83eb1dfbc3ffd072b23bde58.npy +02992529-eb61306048b7848c327b5f10f339d9f8.npy +02933112-4a2848db82ae01f7490ad276cd2af3a4.npy +03467517-de424132b05e349793f0194265a9746c.npy +03467517-54eedf9608f598d5329909d772c2a884.npy +02871439-cc38bc7db90f43d214b86d5282eb8301.npy +03642806-5fb5b09b324dc153ed883f1f11a51185.npy +03761084-2c453abc6198b01d3f7f3ed2c3c690fe.npy +03761084-f0c0893a5aabe2412fbb75bd5fac4890.npy +02946921-d511899945a400b183b4ef314c5735aa.npy +02933112-b649e3084819c7847445d25f394949d0.npy +03467517-e1d55b9cdd791c937fe275cdb56536f5.npy +03642806-f7c26b8c94ba8214397c35f585745a82.npy +02808440-c4920feed5e6b7ebccd0340812259a39.npy +04530566-3bb6a5deec68ef77fee64ca302793912.npy +02808440-4a7e3ca704e59439b362845c6edb57fc.npy +02924116-7369744c0ff9a5ef552840b851f9a5f9.npy +02818832-28bf7b22618b3df750bfb13a96421ac0.npy +02933112-9166dfd18ac60504f0fb3e3d2a0d34c9.npy +02924116-b96580140823a3624b8804c563aa0fc4.npy +03593526-b5f802103edd92d38c6cecb99943f941.npy +04468005-10e0da9af8eca77948b299c18ea5d916.npy +04256520-147df78321f90f20a494798fa117187b.npy +03642806-63e5805f8bd216313bba289a9fdd2a7d.npy +02933112-40f90a159f03321cc59350d819542ec7.npy +04256520-d20c3649494f2aac14bac2ebb8f636e5.npy +04256520-bc6a3fa659dd7ec0c62ac18334863d36.npy +02946921-540cb2a72840ec1130612f5c0ef21eb8.npy +04256520-ead2f0ef7103c963fc1f58a995f231d1.npy +03642806-e374559441d5c5bd386658d2bd45d727.npy +04256520-dcd037ab067a0fbc14038d588fd1342f.npy +03467517-dc623742d6d1518e19959b248340fafd.npy +02992529-4546af9a8a67e7439c3dc4e242073921.npy +02933112-76ee9167548caf224983f386c1ce1710.npy +04530566-6a9764e3e4127744be2fa29f46d19511.npy +04530566-ffb0a1240833569b9041e5038dbb1ef6.npy +03642806-e466c2c86a439c1faebff3b001eb4a27.npy +02933112-84ef04bae77ca17d532e8683617554c4.npy +04401088-8ea08c4be8f2f96095f577622f465c85.npy +02924116-15da18825e00c7709797a4124a9f002f.npy +04379243-268a739200930797c862eec8232fff1e.npy +03593526-275cc21fad6aa1b6bfa78a7d067c469c.npy +02747177-2251883e24a2527df155d75bbf62b80.npy +04460130-19e66890128da2d629647c2672d3167a.npy +04379243-b73a89c916a0237e90faae3c2240cd5a.npy +02924116-3c63a033cf78bc0f1cc733c58de8f512.npy +02933112-8488c41b4c17d0a81a8dfe268f567c25.npy +04401088-692e5fc16bc6ebd23737433332467411.npy +04379243-d5ca71b9b9ca6e5041b73991ca70550f.npy +04379243-95bfb466d603b6baa45e8d2f28a9ea98.npy +04256520-d546b9afa6d0a22fcabc196a7f35f1aa.npy +03046257-158ba1d60c6418fe4b3c42e318f3affc.npy +04256520-8b5fb1851caf5b4c5b89c9fa863d4b06.npy +02933112-2cf4888579296377c59350d819542ec7.npy +04256520-33ab50198c84645ef91663a74ccd2338.npy +04379243-e28354127815445a83e5416284930195.npy +04530566-7c23b6218a5041f36a2173cf491934bd.npy +04379243-56bb7376dfa9cb5c8cf069d506f8b5ac.npy +04379243-9f5cd9e55f0b4c42ba128419b7cd4010.npy +04379243-87666a40c8a35641c7166d921771062.npy +04379243-e9ebf354db8fc0fb4faac606fa48b508.npy +04379243-90f2e686389b56b3bf262660cda9995d.npy +04379243-d76d897ff334065a82130856eb48454e.npy +04379243-ea21cba1d83526f6deab8d9bfbc24756.npy +04379243-b23405a8f15f3fdb44175b4dddf5be08.npy +04379243-76de9805c6e208e6b2644d7d4d7ea2c7.npy +04468005-3d4ead5985c72e2fdc14ba0818ee5cec.npy +03642806-6f20fd2e8d8d518da5f7b1c78f76e23e.npy +04256520-f8d7dc3e169cd91d593ebeeedbff73b.npy +04379243-727b33a75f10861423fe3501bb9e7193.npy +04379243-d9faa371af8e7f443fa7114f9b06aaa5.npy +02933112-7bbdaeb0633738e611fc2b865c2a185b.npy +02871439-2aa9c8be14fbd5ffb8723a5122beedfb.npy +02808440-a9e1f301ddd72647fe52ffd0e748a1ab.npy +04379243-541ba3fe085905e19ccce4c6d5bb195f.npy +03467517-ba6d3dcff42ea7bba32c4b8efb0131e.npy +03593526-c1ded06f2af01612a54fd40ef3a8dfd0.npy +04530566-6fbb26f9372ee87648192cebc0015590.npy +04225987-e06b51f45c1aa29a98c63cb68f11df34.npy +04379243-c6c412c771ab0ae015a34fa27bdf3d03.npy +04530566-6c1cfb2fe245b969c2e818a707fdb3e0.npy +03797390-599e604a8265cc0a98765d8aa3638e70.npy +04256520-2f6f16e5a1d36f3fefc579970fcfc006.npy +04256520-25e718b0164f54d5a9f35e635b7e48b.npy +04256520-3a3cc27878713c19676de9b6e111da8b.npy +04256520-2835a9015c20d891261770c74651d29a.npy +04379243-c912a8edbaaf0fc72e6a7aad8523e7e6.npy +04379243-150c9c514d3274b315e97d83801e911c.npy +04379243-39bb09201e0cd201c17e7f250c5222bd.npy +04401088-ff9e8c139527c8b85f16c469ffeb982e.npy +04379243-b5daa2d15dad58d24fa2457d6e4d0c91.npy +04379243-818723195f30327b445e85eb534460b0.npy +04379243-ead000700697a012310af74324aae27f.npy +02871439-b105d36dbf010903b022c94235bc8601.npy +04401088-bf8e0289ba786e97487d18402ebe69d5.npy +04256520-a6cd2326b2660ac9a4dc2316a7e66d36.npy +04256520-4bebf39e3fd794937177a91ecaf96588.npy +03046257-cd17490f806732d460d9b527752ac99f.npy +03642806-80c013931b7f7b49636ee1998fc5378.npy +04379243-da5d6d0da4ed0c1cea65c47b660136e7.npy +04379243-151c68b48a1359c58566c6c3bc94c70c.npy +02992529-3ef278f78ddb1db52a39b1d7ef8834b0.npy +04256520-a54fbc57992e90b9593ebeeedbff73b.npy +02924116-8900a49e1cdb3470c95c7a8a79dc0c72.npy +04379243-67a49674df5b8a44f51f77a6d7299806.npy +04379243-3c5148ac155d020763ed57e35c972b4b.npy +04379243-ced7aa76ea532e0a68e125404f814ba.npy +04379243-bb7672d1a987dc303fb0851e9bc87551.npy +04256520-a63bc3a5d43888a962e682c9809bff14.npy +03467517-82f1a0f72d800cbd93f0194265a9746c.npy +03001627-bf89775d876f6849f2b7580a739cd4d5.npy +03001627-f1c6c74053fe8888c5f49519e3caf51.npy +02933112-323c85aa6d1949abaec7b0e2cd000db4.npy +03001627-c4ebef05a72fc4f39d62eb3fdc2d3f8a.npy +03001627-ec0258c40ac29da083deefb07c367f12.npy +04401088-e156db6fe3b9286c87cb3c64e47598b4.npy +03001627-62f442aaa230eb34e7697d561711bd2b.npy +02933112-4d3308cc92ffdab432b72c6a3d82ffd6.npy +03938244-f921237171924e992d9c07d3b9171829.npy +04379243-a5c68fc026173a5671e2498adb56e791.npy +04256520-4d5adaaa9b5d9d42ef188758bf2e3a30.npy +02808440-a31af845a610a552d83e8d4109d37961.npy +03001627-e854aa6a9c97d829cde6b082a301e49c.npy +04256520-a078e45c64ef80954a4ccb8d69e8d887.npy +03691459-835e01af50296235aefda81565fede7.npy +03691459-2db3489b490b0d9e2268dda5c324173f.npy +04256520-542656b66458b918cfc64925a56d7ba.npy +04379243-7813f4e4c0a58118cbb8bac2032149c.npy +03001627-76710f51915396e0327289c00b6dc9ca.npy +04379243-524af53b7863f506e227c1bcfe5b1fc6.npy +04379243-32a6ef11cd29c6333002761e7a3ba3bd.npy +03001627-e896f38e6b62f25ce030e064f3b8af2b.npy +02933112-8e46f3a871f86befdb955a8e38fc7dc8.npy +04379243-ae62ecc28b56c7ad68e125404f814ba.npy +02808440-9458bf8670645df33321831d2245cf06.npy +03046257-253156f6fea2d869ff59f04994ef1f0c.npy +03001627-bdffe559220b8a561b01b8d225cb89ac.npy +02871439-692947c56ddba208b773535ea8cba6d.npy +04379243-86951b133a4c6e9bd989b7b3fc68c580.npy +02808440-958ab8793129ffb53321831d2245cf06.npy +03001627-7c2bd3b26bff1d7568c981036afdae64.npy +04379243-39f0da2d45ad3b6deb82e56bb4ec31e1.npy +03001627-cd989e48c5348bb530e06a011e63236a.npy +04379243-f1695a9ec05b757ec7cb90e4399b486d.npy +04379243-a91554caeaa6f9db399bb05f18e8188b.npy +04468005-4c4e55e6cf8e81adb2faf16541f353f5.npy +04379243-175a624623ad6fb037b2bb75885cfc44.npy +04379243-96122c5c0777cb85d3520bbaf4a08c12.npy +04530566-b7a3a8c9e2e1f0eeb569bc98d0a027c6.npy +02942699-3d81cebaa1226e9329fdbaf17f41d872.npy +03001627-404d58ff6722e4a34014f1a5fb376d1.npy +03593526-b89f48fd4a8921dffdbe2bf897d8a820.npy +04554684-f0a1e9e6ad4b47b60a634b9aafd6dbd.npy +04379243-2dc5edae3c234a5b5706d1c54190f27a.npy +03001627-6cc771aa1a807dea19fb4103277a6b93.npy +04530566-f8b80289dbba94bdb7002bddf0942f8e.npy +03001627-891f1cd440afa11517b431cae0dd70ed.npy +03001627-37235898ebd06b3b504721639e19f609.npy +03001627-59f1f818fce72660ac285e4454a089f0.npy +04379243-6d54019f7543e4eaad16260d4d73b56.npy +04379243-15a6e8fae3343178b4c161851ed2b4e4.npy +03636649-eefbd20231e62d535c10b08ea69398c3.npy +04530566-70dcc0d460cacce0e63ec060b551ac57.npy +04401088-d4407c240737b0c73455cac94a339dea.npy +02942699-c9c9ffd08af8b268b52759c2c2fc0d1e.npy +04379243-b91d82b0ef56c395a8005eb66c8d94ac.npy +04379243-6bea2e040e199020e0c5923879d79f21.npy +04379243-8cda30b88d9bfa27d810b14a81e12eca.npy +04379243-356fbc66c305dae355f46d55537192b6.npy +04379243-7e03f7b740e118abeae724160fcfe6b4.npy +04256520-ead777f4e8c5bc346ad8177a9d42d3c9.npy +03001627-e967c4817872b637de03ab2a27ba7531.npy +03001627-924f413e0a7a6ca8492d9da2668ec34c.npy +02933112-1ee6393153a3146ebc19762eaa7ba40f.npy +04379243-8be5c241cef6212fbd1f60c111786ed.npy +03467517-b10a04b6b2e6bc42948046fa63441a28.npy +04379243-cc42f5cd765780d5dbbc9440457e303e.npy +04379243-3f411154853b403921db4632488a2ae9.npy +03467517-1218fa3b8681bfa5d57700c05b1862d8.npy +03636649-1579c3aae8e26472db1afe6c464e7652.npy +03001627-aa93247a7fa69991e074517a246f1e65.npy +04379243-fd57354b70d416386086aaeef17e8c87.npy +03691459-37b5f7222e0eaaa78803395bce6d7b63.npy +03001627-8c76b1db0a08653ffebad4f49b26ec52.npy +02946921-295be2a01cb9f29b716714dd1fd945b7.npy +04379243-34434ee1d6b154f8252b40995a250bde.npy +04379243-d6728931be54e6924b3c42e318f3affc.npy +04256520-84c480a1a055bd0f7223d6cbd6200e8f.npy +02933112-c5116cb158a5b4e6a0f23466c3c25e2e.npy +02747177-7a931ec996edbfeacb2a965e75be701c.npy +02808440-b5de770d4158a9875ad109ec59db9fdc.npy +03938244-4ae37fde7b123dab5dc3653f8341633a.npy +04379243-f2e1735aa2cba97222fbb0d1d627b825.npy +03001627-8be8093e99b94bd9cf320c31965db5a1.npy +03001627-ea7be2b97e78d5b35a4480134e0cdd21.npy +04256520-3cf0d27803acc8cf1290417619264ca9.npy +02933112-1d61ca99924b13fc99dd23ec22c4943b.npy +02808440-88f7396c2dc207d3b362845c6edb57fc.npy +03001627-bf879252fc85aa936d838816bd35691f.npy +04379243-d821813cdad2ca93183128a5e9c4cbee.npy +03001627-f5ef49d354efe6741cda53280488fc3f.npy +02871439-f10c63b9b25d17144dc074799d15faa1.npy +03046257-8a206a72f673973a435b6c388b558e5e.npy +03001627-353707e135c889d2dbbc9440457e303e.npy +04379243-8551281fe6e37db43002761e7a3ba3bd.npy +04530566-a8dd1e23448a492aad67d63ac9e4b707.npy +04256520-12843b5b189bf39f7cf414b698427dbd.npy +02992529-7f756e697cd03ac821844676433a0aca.npy +03636649-684a9c789b62321092cf95a109e87d7d.npy +03691459-539d5ef3031544fb63c6a0e477a59b9f.npy +02933112-14ed803c2251dfc1ec451f73f474981c.npy +03001627-d2af105ee87bc66dae981a300c94a911.npy +04379243-b11ab64f79e13e1b714473735ef35ab.npy +02924116-6060e1abfb2c85da2eed4e833c76b59b.npy +03636649-90651b3febfc3afe15226aa76eb7c3e.npy +04530566-1f9315ee16e03c64450e0a3087ad6863.npy +03467517-5a5469a9912a03a0da5505f71d8f8d5b.npy +04256520-930d2bd446a43e0ee8058cf23f6382c1.npy +04401088-f5f1fbeca9af99c98efee9b82d757c0b.npy +04256520-31fb6cfde1fec63897f7290a893b9fc7.npy +04379243-8730e3ce4daf7e264f265f0c85da0b1b.npy +03636649-d9f6bd064c9fd456fcb8d8c6d4df8143.npy +04379243-da23d0bdcd1de093de909714df3390c0.npy +04379243-a2561614d015f2fdfebad4f49b26ec52.npy +03691459-c134c61a5b45dc281574d21c0c95092f.npy +04004475-cadd6125bf30f513e10a48f2bbb9bef4.npy +02747177-71c45644821a8961ad5067eac75a07f7.npy +03001627-86e6ff997adb2a192c90ae7b7282b9f.npy +03001627-d4edd167061dac5f52a3901fa1436b1a.npy +03001627-56cc047440e7c999a23949c21eddef76.npy +03636649-70652459696b25037e0f056bfb925424.npy +02808440-2b1d6ad1dbdc945bc3f6ab99a06dd7a.npy +04530566-8d8113b30710a6bb68d1fcae6985bcc8.npy +03691459-77514a7ccd32860dd9dfbc520b0d9752.npy +03001627-1f8eaa7aededc7e637b2bb75885cfc44.npy +03001627-ee445cf3710af7e21548fc89657a4fac.npy +02808440-37f0a39abf371409ec54a7cce22716f0.npy +04554684-46251e61b0c06c0771ee000eee74cabc.npy +02691156-6d0b546bb6256eb5e66cabd11ba41eae.npy +04379243-b16b0c22f89f43ca9b40e76e725878.npy +03001627-f7626a4eb581bcd7140769279b0e5e15.npy +03636649-5ed0d3a50d9d77dcf1dc60fdf1e64165.npy +04530566-3838f398264452a47c97d792b03a31cc.npy +02933112-626bba505f03233ef51f77a6d7299806.npy +03636649-14d3d2418165ec86bba785994a529f86.npy +03691459-5e40ffef9d25d0f031f3d76ec3df45bb.npy +04225987-48bf45bffab55d7cf14c37b285d25cdf.npy +03636649-4e54fc131882f2233c8d0fdfb1cc2535.npy +03636649-29a363fc242b282b45df535caecae62.npy +03636649-15606afd522923eb4e91947b208587c6.npy +04379243-e2f60503a4fabc4aed20ed9a17aa05a4.npy +04379243-8569fbd5e27a1845e7c7bcb951a9c987.npy +04256520-9b651dee9548be90ded526a7be77b30e.npy +02773838-54cd45b275f551b276bb31db0358e9c6.npy +03001627-a7caeaff5582f54f55f9913e822d5318.npy +02958343-1d234607fafd576b6dede2eec861f76.npy +03001627-a1213da0e7efffcafebad4f49b26ec52.npy +03001627-ccf29f02bfc1ba51a9ebe4a5a40bc728.npy +03046257-1782876c0f584452cf5a37a70014c623.npy +02958343-c1192c946a99ee529bdb511fb702b5ae.npy +03691459-916d2e621caefe3a1a4345b067aab43c.npy +04379243-a4047a8f57451762a0ab1d82ef09f78f.npy +02992529-7392ea79052281e6bfbac23a8087e8f4.npy +02958343-e999dfb757ddca4830e7f6cd6fb3f1b9.npy +04379243-ec9861c234daf6bc915f51b5f5e95ffa.npy +03001627-55e7251e672cd45e796c584ff1fcf56d.npy +03691459-cc9edcabf65e42d3febdb1f263373824.npy +04379243-6b521eb69b5af97dcddece8d514fc823.npy +03001627-47eff1e5c09cec7435836c728d324152.npy +03001627-6c5b15a19101456219cb07ecb5b4102.npy +04379243-c193add7ee3b4fbd63aebe2e86fe0041.npy +02958343-28bb7eaa8037a2e9afe1d4530f4c6e24.npy +04256520-77196cfcaabb6f750cf3715818ccfe8.npy +04379243-634bcd3197e337aafe4e4de1adda2150.npy +04379243-206a239d64ad2b31664b3b9b23ddfcbc.npy +03636649-cd0f2eaac6719a3ddb039d8689a74349.npy +02880940-64d7f5eb886cfa48ce6101c7990e61d4.npy +04256520-fee915afe193518dc036a40816608369.npy +04379243-6560de55043db06ab0783d9ebb200d10.npy +03593526-7213aae6cdadc227d680196133d8b70f.npy +02958343-2854a948ff81145d2d7d789814cae761.npy +04256520-924761d5171a0682e5c139899870edf3.npy +04379243-e96108e514142d13b3cf15c77de45986.npy +03001627-64a699cf5b2a43473f7e27638e63d848.npy +04530566-684d665be29eaa49a1e649e7e3e5f054.npy +03691459-5336a4698616726725a4212543dabaf9.npy +03001627-e25c7c2469135e3fdd3adf3090c701f7.npy +04099429-daf0f6c6a4bfe6843656f5a839c1bd14.npy +02933112-45bb41433302f3f5490ad276cd2af3a4.npy +04379243-887ae0ad66669f1b302fb2a9e79d3e7d.npy +04530566-7bfb0e8e74e1bd2bbe7ca2216dc1576a.npy +03001627-61de75e888e8727486debb0a33c851f8.npy +04379243-d2222dbbaaae806cacd0ab81dc64966c.npy +03001627-6e53d494768386ca8579483a049f2a91.npy +03691459-73c76faf92402a9183247f812f2eaa97.npy +03636649-964d3a853d6e5a642b1c313558664cae.npy +04530566-60c58f42072396986d4334e260ec617d.npy +03636649-ff22bf19e2ef19d12f7ffc95c59dca52.npy +03001627-8f268673d08240d34eb6dda9557ab0ce.npy +02933112-1de9b71f35b51b56c59350d819542ec7.npy +02933112-c86f009c4d1e1d2941e1a63759e8b225.npy +03691459-a05dda1538ddcb4cd747b49524a1246e.npy +02933112-8e2f81ceda8e42ee4b4e980f23aaee7.npy +02933112-298dcf7bd982cf0712de5317fe5b354f.npy +03001627-997853f8fa3678df5ac8254dd793f590.npy +04379243-20d23be3b5180ea9e51ca3f3e83d9132.npy +02691156-e501a0327ab3731d0f859db45b95a2d.npy +04379243-ba99a0f31b2ba6e51f087e2218f8d26.npy +03001627-fbddac94cfa74a7b5c0228148b88226c.npy +03001627-bf41b418250959d0a8699b6183baa203.npy +04379243-696425932b878a839335a4bbd2281da5.npy +02933112-575d4aa0c1b95b0836d8dd30a594b2af.npy +03467517-301e0388592cc17bee974d1eb57427bb.npy +03636649-51a0575368d16f4c99e8bf807e902261.npy +02691156-273c9c0bd43443c3b4f192eea1889928.npy +02691156-86590fb6310cf7361f1ef59130c405d.npy +04379243-a9e23932f14fe0cd323ff07d83f4248.npy +04379243-47317755c82114d5c3bd24f986301745.npy +03797390-bf2b5e941b43d030138af902bc222a59.npy +04530566-a48181b53d207f702ec88d3440bc2d77.npy +04256520-b8ab014839e2a28af62af8489541547b.npy +04379243-b7ff6501981195caf771fa2e8f483ca5.npy +04379243-23937a360c840bbd2b70eac6546e93fd.npy +03001627-104256e5bb73b0b719fb4103277a6b93.npy +03001627-4ed8015bdbd8c03d2f95e2a1e9997b85.npy +04401088-8959f06b36d90e6a7c4a9987d1ab61dd.npy +04379243-44360c91a7e91098d93768e7b9b1eabf.npy +04379243-dade0594e68e2250be6c545952e7fa4a.npy +04379243-daca80d92e046faaaf90989a4df930dd.npy +03001627-d54100efac3ab743626ced72908b525d.npy +02958343-597c9eee5a5ba96b313436e774fa02eb.npy +02958343-19d35f3e0c0b402125ddb89f02fe6cc0.npy +02958343-62a7e17ce83e2f9cc0ed6ec757ca50f5.npy +04256520-c97af2aa2f9f02be9ecd5a75a29f0715.npy +03001627-a9053230c8e02442c8687ff9b0b4e4ac.npy +02691156-10c7cdfdffe2243b88a89a28f04ce622.npy +03001627-9ce08b44810f03c963cf8719fe855f3e.npy +04530566-eadf347da5aa8877da97052ff1f36504.npy +02958343-46c504c9760fcf0e7540f431cab4686.npy +02691156-9617ea33f17993e76f0c490da56d34b.npy +04530566-39875815bdfdce2193b1b9ed21f1fb92.npy +02691156-189f045faacc1b5f9a8993cdad554625.npy +02958343-ac56c7527df057173c5d25c30835eee9.npy +03691459-9ec130a3ef44b7a1e47833b310955a9f.npy +04379243-c14fe6a74a071b73664b3b9b23ddfcbc.npy +02691156-d1b1c13fdec4d69ccfd264a25791a5e1.npy +03642806-1a46d6683450f2dd46c0b76a60ee4644.npy +04256520-48b2e88f7d199d43517a64eed9809d7a.npy +03642806-7d733a513d905a1a56fd4d28526341bf.npy +04379243-10e2e8385b5322144708f4c6142673f0.npy +04256520-2c12a9ba6d4d25df8af30108ea9ccb6c.npy +02958343-1d0a46cfc2799eefdeea60824a43a0b.npy +03001627-63c7b59dbb2876b4aa2ac8cb6992212b.npy +02958343-11d1fdaedf3ab83b8fb28f8a689c8ba3.npy +02871439-b6bed1d1abf2f8cdc2731798aec2f82f.npy +04468005-fa69b96acfc4ab67d6d91af432c7bb1b.npy +03001627-c70f8a49f26a012f876b399a99a15c0f.npy +04256520-23482a90a12a7052bd184e94aa5ce5e4.npy +03636649-445724eab48f591cd650d96de5aec623.npy +02691156-dd4da4309c12d47bc2c2c81e2232aa95.npy +03001627-4abbd2b632d3aeae4b3c42e318f3affc.npy +03001627-eadb3d38d02343ba4d2a756b9ed2c425.npy +03001627-cd547b0ff5cd668a86c701087a194026.npy +04379243-538cda9b8cfefa3f4854e924c443f593.npy +04379243-35b005d11a25b25581faebbdea6bd9be.npy +04530566-4869abf7743f09b71f29de30ec1bf6a3.npy +02828884-956be1b39e4bf1b963b2acb037dfbcde.npy +04256520-b02c25874494cd60f51f77a6d7299806.npy +02691156-12a1ac26d29ed1083554ccf8c30febe7.npy +02958343-6ddb807414fa23e0d9f8911ce020a037.npy +04379243-d5a374e8465fb8c2858699aaad4acee4.npy +03001627-321f8b85785f082685e443e0ea51d93.npy +04379243-d06b3f46fd5a901d4854921d37f7e048.npy +02871439-ae26bec5a79f51943da27ece6ae88fff.npy +04379243-8e7c894039ae2cfe99e8bf807e902261.npy +04530566-950ebca8ad7d94051fba2cab1ada6bf6.npy +03001627-33617cc89afcf169e6543556f230fe9c.npy +04379243-7b3b160dafe7e122d93768e7b9b1eabf.npy +04379243-27eea1054be1880a7eaeab1f0c9120b7.npy +02691156-f016679500a76fbd8badc4a9f1acc937.npy +03691459-f156e32edfe185b76ac6c4392c71284b.npy +03636649-ffc2479f27a1013afcec439ba0368db0.npy +04256520-5bd1a7825fd8c16c6eb9b08c8a74d159.npy +04256520-b2a9553d5d81060b36c9a52137c03278.npy +02933112-8d4833c24a4e983fcf004563556ddb36.npy +04379243-20812fc7f9dac9a51b3e6b75a323070.npy +04379243-1a53d35ef172a6febbaf0ab08a397b2.npy +04379243-9831a5ae9045c6f39155acfad44fdd03.npy +04379243-1cbd4d2be9cf0e3e84ef3d675a0511c0.npy +04379243-3eb80174aa72a62910126c0551113ce5.npy +04379243-7e651b7d860842deb612ac3ee32028ed.npy +04256520-8e2912b6699ea81c3db8e8b3ea723cce.npy +02958343-86aedfff061c5b96f500cc506a763c18.npy +04530566-1ce3bf4b1ee8c4b41542b16dedc43949.npy +02828884-ee8c43b1ffc8e8cd7389336cf5b6aec6.npy +03001627-51f4ea68be319fe8990e5087098e19c.npy +02691156-a98038807a61926abce962d6c4b37336.npy +03593526-e93934fc1da4635d5aa09a1176194412.npy +04256520-cde1943d3681d3dc4194871f9a6dae1d.npy +04468005-82d34870d2b5b59b5176b359c67b3356.npy +02691156-752d9a010346862551cfdb4c9f126c12.npy +02691156-7f3446564689ac918f69a600441c970.npy +03046257-37d5bae8c287486e93eb10cbaac91.npy +02808440-3efe1e2fc2ab4c0e4e58e1f374dbffd.npy +03001627-f68ecc9ec512915f36d8dd30a594b2af.npy +04379243-928ea87878a7bbe26cf876b69450cd4e.npy +03001627-53a1b68bb05d5b1bf51f77a6d7299806.npy +04379243-a80fd4790dfa2d226a4bc5d920331917.npy +04379243-dbf47e19a5f352e0f1b010366bb60ce8.npy +04554684-3e4b1aaca677501b91219aad82abc053.npy +02958343-d810d7f83632da71556235a31d374eb5.npy +03001627-978ab0578d8691ceeaf7fa9cda77a592.npy +04379243-f6c1a97812bd6ebd952c86497c2cd532.npy +02808440-10e41094453d1c6d4c62bee40dcdc539.npy +03001627-fae27953e0f0404ca99df2794ec76201.npy +02924116-5201d514f274012b52470de2774d6099.npy +04256520-cb7cee345d3e7f75593ebeeedbff73b.npy +04379243-60ef2830979fd08ec72d4ae978770752.npy +03691459-4e68ac6cecd91de23d91ae2b92426394.npy +04256520-9cff96bae9963ceab3c971099efd7fb9.npy +04379243-f026d1e8b71bd18e97f16d67bfc59c23.npy +04256520-2d1ebd7356968c0919fb4103277a6b93.npy +04530566-3f3bf820fa5d171bd45d4d5673b732bd.npy +03001627-4f0fc7761771d073fe2cac60a76c70a.npy +03636649-16db10b6ee500ef94b3c42e318f3affc.npy +04379243-7a702fc01ec83c36b93dc42f7dcef6a.npy +04256520-857c4d70af14d9d9e9b88e9734c4cd55.npy +02691156-afd02e6d4cf0a342c1ccec171a275967.npy +02828884-50184fbabd0ac41acb2a965e75be701c.npy +04530566-70b4666e2da7ca32cfea3d4fc15719ea.npy +03636649-41cc8b1669429bf92a7d46e74f08da70.npy +03046257-4e8d2c3317d397dfd1f82efe36dcc0.npy +04379243-4eaf30762a61db196cc318d65b897138.npy +03001627-9e14d77634cf619f174b6156db666192.npy +04379243-4e232b14eff92afb268cf362bf3a8d20.npy +04379243-5edf1990c995fcd7693e54627de491a9.npy +02958343-1a0bc9ab92c915167ae33d942430658c.npy +02808440-ab60eb30629849e96b448b8aaebb705c.npy +04379243-38bbdd91e895c0f92c0404a105e586.npy +04379243-d70877569d163235aece045e8bdac80f.npy +02992529-caa0cf3c7bf2cc4e50e8879f012090b1.npy +03001627-664eb477f8098678f1783a44a88d6274.npy +03636649-c2f6c7b7b39fb06fbd4bf7024dfa167d.npy +03046257-44316e91d4926a73fe9c9da4b1c78d03.npy +02933112-dd7e681525a458befbfd931924135513.npy +02691156-e4237061106f5df1dc82b8fee1057b30.npy +04256520-b55c43cbec762a54eaf14273fa406ffc.npy +04256520-ff5aa5eb5ed4041c1ef9727a7f361b49.npy +02933112-7f47c97fbda19b57490ad276cd2af3a4.npy +03761084-df5bd51614d2fbdef114be17e2e7c4b5.npy +04379243-5c63f336ce5ea7d621d1a69a8eeb6a01.npy +03467517-26e1801ea747f72f14fe0da28e4f8384.npy +02958343-6107486a14c40227665f0dfc9cc02b1.npy +04379243-758ab4ddc8fde77cb2b755acb296d925.npy +02958343-74b4d0c4ba72eba8473f10e6caaeca56.npy +04401088-eb61306048b7848c327b5f10f339d9f8.npy +04468005-713beb3434e30be68498191d94ca767a.npy +02691156-1f08b579e153b2de313f9af5275b7c70.npy +04379243-200e41f83af78ee240add2170313bb0.npy +04004475-83c3034992c6afbca0622b21d729afbc.npy +03691459-b00c5ddc2efe42eea64e5c46abb30c70.npy +04256520-7e4cb0c15959883242095a33119f8ea7.npy +02691156-a34a2fa46d7a0a6390b1d6deb98feec6.npy +02828884-15b3111c1611c2e5738e43095496b061.npy +03001627-a1ee33aadb4754a492d9da2668ec34c.npy +03001627-452d2a10ecc96b34129a4a365910676.npy +03001627-35d60ae4cb2e81979d9fad88e2f4c8ff.npy +02958343-c8d8089dade71547d2350421a9405ba.npy +04379243-5cb93ef515036277253e170a96a633c1.npy +02924116-899abc9a81424b5d73ba5c85a4ea149f.npy +02691156-384da5cd806c436b35039158de2eb4b1.npy +04090263-b34827c2da8ed1e32029d06c0cadaf74.npy +03636649-9b558be5e2b60e3eb09f0ca9c143fdfd.npy +03001627-e0a19f7c41d7489211fc2b865c2a185b.npy +02958343-431ca41fdf0897c628ccbb4eb8965b05.npy +03691459-6070b86ba88f51a52d48173107aeaaf8.npy +03001627-38bdba5f6455c5ff91663a74ccd2338.npy +04090263-fa35dafb0a24ed8b2511f68da65f4c4.npy +02992529-41d95e8979b8377d251f8cf5c284bd7e.npy +02691156-a7df65b30f1e6a3663d1bfc21cc05e4c.npy +04379243-66298b3f4d2dc69db6572d78be2f91d8.npy +02691156-329b62a63e882c7c71d03b466c72ce41.npy +02958343-7e7cc90bb7f265d2b3cf5236f651a8e6.npy +03642806-8b10449b4c25fb0939773ee5b5578e3.npy +04401088-87b696d3942f6845fe75c83a5776ab77.npy +02958343-9c06490e82e122093f599d94ae17ce2b.npy +03636649-9afc2aefd6b17db014038d588fd1342f.npy +04379243-3d6b55fe2deb2aa3a1c746794f191dc8.npy +03001627-2159af8011e13b81713decb1a0563b12.npy +03001627-e9592e2a4fc74bf0492d9da2668ec34c.npy +02818832-b1a03d41a681ed0220192a5319e3e2e4.npy +04379243-35cfc39065c4073f4b8710a3469971b1.npy +03001627-3b788994cd578990c35131da26f8061a.npy +04256520-252be483777007c22e7955415f58545.npy +02958343-8280b8d35355bbd56204845b7cb50f20.npy +04379243-66b43780a0e81cbf16a2b5862518c93.npy +03636649-110b426397c707bdc9c869210ebfd6b0.npy +03001627-7eabd19312bde1dc9335750905007562.npy +04256520-bc72ab493655beb5d329896bbf26eda9.npy +04090263-d747c1f677349e78803b54e9738b20a6.npy +02691156-8f4e31ee9912f54e77fd7318510b8627.npy +02924116-69e61d2ec68e8184b1626da45836ca54.npy +04530566-38b55fc61393e40653d45bb9e1743653.npy +02933112-4e89985989c6a1936aedbd2a02b96953.npy +02808440-78648b94a2402ca6904e03fa15bd73ec.npy +04530566-d35fc449232d68474163d08524f89006.npy +02933112-d6bd6fb5d0149227fa242b893d7c243a.npy +02828884-bdc3a9776cd0d69b26abe89c4547d5f1.npy +04379243-eee6cf14a56af26ad71f17d6e8238d04.npy +04379243-4bac1dcc5b39f3d1a4328b1daf5160d6.npy +03467517-81bb9fa998f58f2e4bfcfdb26b8cb2c3.npy +03691459-427edc7774b50232a789103b1a0f3e38.npy +04530566-a77c64b41bcc66bbca4b459ebb5d9bcb.npy +04090263-75066ff8b9740bcccb88c9db6e396994.npy +04379243-4f31d399c2c778135fceaa39a8353bde.npy +03636649-d2fc5882e1faa78c1592f292ab531da8.npy +03001627-d521a48317d0b14d7ac55d461d1984.npy +03046257-944ce52789d061a74d6ea0439e37ef4.npy +03001627-589cd6a1f4367fd834b707eb14b2a4a5.npy +03636649-96837f1ee184d9a4522f1ade738c024a.npy +04468005-e9d3f23adfd51c53125a6be5853df664.npy +04530566-2dbe5ea82a45443b71f3cc81eb6c076e.npy +02958343-f7b9529fb166ee56ac922d597da8f180.npy +04090263-7f219882b778b66c67fd32336d183e10.npy +03467517-b47dc8ec5f06cd414bd9729c64cda7af.npy +02691156-c6342ca5cf5c445cbd46d022fd7d80aa.npy +04379243-74fe5611d491a2b77b286d3c174c2040.npy +03001627-d5d4dfb9e6901b66a3f22b4b00de6dfb.npy +02958343-f37c7ab91bef514b4125854591376336.npy +04379243-e12ce317c2d9fd0eb9fb1fee7d937756.npy +03513137-93acbfac563ebc4c1d05dd90478fa7ec.npy +03691459-5c400c09175e3801bb3613d5601159a8.npy +04330267-b99428bafbeb30ae4f925e12806745af.npy +02828884-cd7689a92e0d39896812e49a5c99d0f3.npy +04379243-f4888967269031b295feea036c244c98.npy +04379243-e2807c8c5f5653d4bd91edd7a65c1323.npy +04379243-878872e3494e6b26baa48d60edc63ba4.npy +02992529-d37afdca0c48251044b992023e0d3ef0.npy +04379243-561cd495a38e22dfddbe8a6b8178038f.npy +04379243-86e6caacc1e4ddb5e762cf5917cef4ef.npy +03046257-388da8044b2de673b138d9e8fa5eed8f.npy +02691156-8b1b372c0ea200bd225a23c790f08fdd.npy +03642806-d88e4093a73064b6b44d9812f259e403.npy +03046257-89618f2292b3d05d48d189f942cedc62.npy +02691156-b6fb57668129c4cd4c11ffe5517eef5a.npy +03001627-4785c094e81a5f8e3002761e7a3ba3bd.npy +04256520-96055e2a648903bbaf2302630d34f30e.npy +03001627-5a4c550b1b41114c3d2617f9171b5ccb.npy +02828884-5d8f7c82a04943fed201085e80edb26a.npy +02828884-7ddf43b3b160ba10eee5b98d7c69f27.npy +03636649-b75ab10d1235158ed91ade1c391e4016.npy +02691156-a07446a1799bdea7afd477f714c68df9.npy +04379243-68b18bb0c7eee83129e4b5aa807bb4e7.npy +04379243-43ac9f2d108ebcd0c3bd24f986301745.npy +02933112-a1f901768250762d4f60f15da4c665d0.npy +03001627-1015e71a0d21b127de03ab2a27ba7531.npy +03001627-ec7076f7f37a6e124e234a6f5a66d6d3.npy +02828884-901872a92ecdfa4863b2acb037dfbcde.npy +04379243-41c538c37e2ade9047f446d318aa6c9e.npy +03593526-b1584e986a706101773b5d04f2ffad47.npy +04004475-b6fa2dd4812d69d90071898148dca0e.npy +03211117-8ef52dd9b307eebfa31cc7b61ec6561.npy +02924116-c9bc84079b8ab89acdbb9fcf2ed3a2ea.npy +04379243-f7449ab20f45bcbab1b6b0c5ddacb607.npy +04256520-aef57ed7044469ba25e322bb8575a360.npy +04256520-7598c48286a63854c02170c33e00ea64.npy +04379243-5f3f97d6854426cfb41eedea248a6d25.npy +02871439-d49f87c534c4e0b5b4979bfe197a8c89.npy +03211117-4731c3b756e3366958aeac7d536d442b.npy +03691459-1a9a6a214c957757cc6617fc407c9ed2.npy +03642806-9ef061efe37e9889d7c51311132e27a8.npy +03211117-9d51ab35cca6288da8b55d3e40d96c08.npy +02933112-49b69d5e4330ae2457b1c0b6d5084bcf.npy +04379243-ccf36a20b7ef3bd128071d61462a212d.npy +02691156-79351c8f83f5a3abb2d09bc8d348e46b.npy +03691459-632510d0916f31a184d6a2fa7259858c.npy +02992529-183e8d61b3c4edcc90b5b1d619d7013b.npy +03001627-539dd50ce4d5fd97febad4f49b26ec52.npy +03467517-c5d8ccd04236514966382ee33d7a02f1.npy +02828884-db4aeb6354f5bd0dd4d8765e3910f617.npy +02691156-d07277bc3c95a365bd46d022fd7d80aa.npy +04379243-3b6b823039a912023002761e7a3ba3bd.npy +02958343-4b7b3b54dc04df53c19f1e8ed99ac2fa.npy +04379243-6fd88eb1bc87efd6f51fa0238791f5dc.npy +03211117-e80b420abf6c590c3841abb8f4ea69aa.npy +03636649-2af318d179f969aecbde89e0c48a01bf.npy +03636649-b88c9a7aaab268fb42b08fbc749346d6.npy +02958343-982448cbcbe56bb78f89cf8d2f8a85b0.npy +04256520-cf47942a67cae94eab49dceef0d15b99.npy +03211117-45cae393b431f75e8873c005ead1ead8.npy +03001627-ee6f7e45be30b0a5b9b8611336bc3051.npy +04379243-599200313a698b6cad5067eac75a07f7.npy +03636649-e507bc77c03a1b3afcb8d8c6d4df8143.npy +02828884-634524d6d74142ecd2b12aa6a0f050b3.npy +04090263-15c7233e2e883eb55a443e4394e3a0da.npy +02958343-bacc3c08f58dd96152c6e8b4fe0351e5.npy +03636649-53846d2802f58f97c066b9622c005c53.npy +03211117-7e3d087ac72e46c2e53dd9bb27ba3c50.npy +04379243-3068bb896d8a43c040e6664f04cec8b2.npy +04401088-816aef1e285ab957b1c67c24f425bd0e.npy +02958343-8590a6c8270375e34b5a812ecf553410.npy +03691459-2335c268bbd05a5f230584014222e685.npy +03636649-d0fde1daedab10365240248232b90795.npy +03001627-3211fc4f31b15964aee892adc836ce83.npy +03001627-73cf718c453779fe346b7e70ad2e57d8.npy +03211117-15e411905cf8d7d455c2bf8f07989ec0.npy +02773838-93ca5243aa73b5de81157c9325bb0e45.npy +02828884-1809f6221774f1b62d309335a9a8acb8.npy +04401088-cf0dc63412541764cf9d394118de0d0.npy +04090263-232beffe2c94564b678808412fe4ac8c.npy +03211117-c12a485b4241be83b70b5d25a1334116.npy +02691156-bb91e932504e90ffcc14f1e6f4f4f49b.npy +04530566-4ac3edea6f7b3521cd71f832bc14be6f.npy +02958343-5c960f83d0eab69cc9463ecce7643e8e.npy +03593526-324c9045843b9470d29670d38a4c9e7e.npy +02876657-7b1fc86844257f8fa54fd40ef3a8dfd0.npy +04379243-1c57228e08cdd81ea375e397f0227097.npy +02691156-a69d6f9ea766b9d1a13079850f677b69.npy +03001627-57583ba714a883ce71c3cf047830ec1f.npy +03046257-93369b3e29648260490ad276cd2af3a4.npy +04256520-3420ef8b6b20595e1b7dbdf53d301715.npy +03046257-ea3eb7aa3da2eb2df5f02cba8695cd8c.npy +04468005-7218bcb64665858c3fd38f4cd285f64f.npy +03710193-2c3e7ec7a87e73d8285663b602a605b9.npy +04379243-713a4be770bb19b9586b2526565371c0.npy +04379243-fe167899fda76d1e88dcbe86402c7c15.npy +03001627-d095dd9f3dbf4083a7e870da1ab2a36d.npy +04530566-5a3924c1fb78bb908dea00b146cfa3de.npy +04401088-2b33c33ab4beb7493ce1b993153ccc0e.npy +04330267-8982176eef2ad23fcbf3dda885c64a76.npy +02958343-3ba5bce1b29f0be725f689444c7effe2.npy +03636649-163fb10d7f6f09fcf1c7a32d97b27a4f.npy +04530566-8e1778cdc0bfec3e18693dd92ffa710d.npy +03001627-77d48297d441c7f5bbc0e8a3b6521117.npy +03001627-40e5d8e71ee3902a31358207d42bcb21.npy +04379243-eca46f21f2893069c0a61ad1cf92b694.npy +03211117-a3ada0a8bc0d4b8392ababf87635e60c.npy +02958343-5a9a67bb92fbfca3b1bb46d2556ba67d.npy +03001627-4a89a789f817ab5414038d588fd1342f.npy +02828884-2a80c18fc2b4732bfb7c76304cb719f8.npy +02958343-9aaf299edeecc76e7dfb1ee6a4b12bf8.npy +03001627-31f5725faebb53aba1fb86e891f97aa.npy +04379243-b69722ee8e35829feb20d49510853b52.npy +02933112-9935a1e91ef08470569e2e0d2caa039.npy +03001627-f736f06f8fd04e1119fb4103277a6b93.npy +03001627-420ca6eac51267538a2d6a427829a3.npy +02691156-ed2aaca045fb1714cd4229f38ad0d015.npy +04379243-d656a6250fe0058fd810b14a81e12eca.npy +04530566-6d96d3f9f621292b7eabc15108a128c0.npy +04530566-8d5e3b659cf0df154327dc86b5ea9517.npy +04530566-18429e2495592e5580c2e60c312b0f09.npy +03046257-50acbb342934ddd8ef71ac379ee99590.npy +03046257-9331dc400e10a91c991e9693c5aca3.npy +04379243-f4f96a7c9b71fa9855b72fb3e8922a58.npy +02933112-1e18f136798cb3f0c59350d819542ec7.npy +04401088-29c5585362cf4aa5b4f6326696174df2.npy +03001627-43897195d7f893d759c257be4c612509.npy +02933112-1a4d4980bbe2dcf24da5feafe6f1c8fc.npy +04401088-2cbfb354e5dd731dfd6c7e3f0d9c56c1.npy +04401088-e840fab2f764532ce4bb3cae511f21f0.npy +03636649-1b35500ce44ae7e344b6d51c32a5873f.npy +04379243-5de0ca3516c01ffe71a782a4379556c7.npy +04256520-240b9fc8d34f3af17e20865350fdf369.npy +03001627-4aafa7600e0aacbf7b11ae648ea92233.npy +04379243-56f6e87023f0dcbceba48f396a34b9dc.npy +04256520-5f32acd6df675a414b3c42e318f3affc.npy +03001627-99867a25638b6809b91b871e750ca615.npy +03636649-cdbe11124dbf418167ac0fa90111fad0.npy +03593526-e1fb6357c91654b455f46d55537192b6.npy +04256520-11b544b22dedb59c654ea6737b0d3597.npy +04379243-39806e081bf3fe564ee8db28f96ad26b.npy +03001627-88aea5f475654e491d77ac5988aa9265.npy +02808440-73f3495f2c64c929ccd0340812259a39.npy +02933112-15de6a77af2b4fccc59350d819542ec7.npy +03636649-1e4fd4cc6fee7cb2fcb8d8c6d4df8143.npy +04330267-d63a5fa4070c41c87b0af550cd1619e2.npy +03642806-a17cf326705a6443a09a37cf78d1b866.npy +02691156-4470a28f2dd0cca9d9fba06863881b8d.npy +02992529-54f1cca754751ec14857f88b08630a42.npy +02933112-533ca24b72a0552c5057ad0f363d6ddd.npy +04530566-ece02b7fb2257df139bf01a73033939f.npy +04090263-196b2e3c66d59cb54a4f87aa9a31cd70.npy +03642806-e5d666a9b3aceaa2626c1b61fb70e077.npy +02933112-b7f1176767b87b235c8607e33463027e.npy +04379243-425544b66203da392ebeb1e6a8111f53.npy +03001627-2d701c588b3bbbc458c88d30f502a452.npy +02876657-c771267feb7ee16761d12ece735ab44.npy +04256520-c3f48348482f8c5df4ae8c93f4db5e6.npy +04379243-92b044e982b28fb02075b603cae7ba22.npy +04379243-1692563658149377630047043c6a0c50.npy +02808440-dacf794f991fc0173e9b7c3ab7636200.npy +02876657-950d6ca1d2b53ce52f71dfd07ef088cf.npy +02958343-c7205c6c657daed1ecabc5c9d5c21b7f.npy +02691156-9f7d4125c4b705208b96ae1a0a8b84ec.npy +04256520-588f01ccac8746e1122e20a0279089a2.npy +02946921-6a703fd2b09f50f347df6165146d5bbd.npy +04379243-77b57f3eebab844707cdefe012d0353.npy +03001627-39911f927331db1c8687ff9b0b4e4ac.npy +02876657-4185c4eb651bd7e03c752b66cc923fdb.npy +04379243-9502eecc3a057115b129901f80d24b7b.npy +03636649-e6f2e77940fbc85a8e2d66cbf6a91063.npy +04379243-5b0e8fdc7208b8d3cafef66236db7ef0.npy +04090263-3474d85a58796c7a935777dcb8deec2d.npy +02880940-5019f979a6a360963a5e6305a3a7adee.npy +04379243-8ad88ee4442fd0fd8a6ba7ebad3985bb.npy +03001627-4efc68a96296be2ac785f06f424b9d06.npy +02880940-8b90aa9f4418c75452dd9cc5bac31c96.npy +03001627-5142e809212f8c314500047017815f5f.npy +03001627-d021835e503e575b4f7a7f19de079d1c.npy +02924116-d9208f7caab22206e70da94675b5e3ad.npy +02876657-cf6843231592b29e2586fa0d0359af6.npy +03001627-3a98a93f381ff5fb4b3c42e318f3affc.npy +04256520-e2ea1cd546d6cb4b94db33559ec0df30.npy +03642806-3b2db36aaa2546b99c7c402f274622c.npy +03001627-8e212bac2103bd626c518c577d808035.npy +04379243-93d8e32a11a3502336b0f2a1430e993a.npy +04379243-b399584ed464f6f5d2bdf2c065ab29bf.npy +02958343-60066a5369f1354e631a23fef2ba638b.npy +04379243-1b273f4af777469e42fd31df8966a338.npy +02691156-fc9b408aee84f46d70c4138179d9ed97.npy +04401088-b984d7e958fe9eb961179e7ef17bf7b5.npy +03636649-913ff6452d0ea43c9d62807daf4a2134.npy +03211117-eaad54605e6dfee6d862787d0e1b892b.npy +03691459-79f5622b83f85cac207a7604d676d24c.npy +04379243-1c228bbb8c23ab9295ba6c11631d3b64.npy +02808440-3db87ff05c046a58d787d15d1d196768.npy +04090263-8527c531b4e23b85819b42f03f652dac.npy +02992529-6e30906a4d0854e9f31b75c4a94a8879.npy +03001627-8f9f59e023572749acdc3d668e7c804.npy +02808440-30518996c975c64bb0c867f4bb42a876.npy +04090263-91d9c29371eb5c091b7837f7a64e3031.npy +03211117-9ab58a92609d8f5030b540842bf7e90a.npy +02958343-58d9741ad324623e9872e22d6b8eb647.npy +02828884-a03c239b05374a837c8303a5f3977966.npy +02924116-cdc36ce4f0dda33641cefd10ce5d6cc0.npy +03691459-7ba65164444ed5be3df08ed7d70af1ee.npy +03636649-85e79f31c24f878cef3a2c64cef919d0.npy +02958343-e14338cbdf53c0ae3a0daf3e5400b95c.npy +04468005-c10daecd154c8dc476d9bf960443503e.npy +02992529-ff8676e76a0fd471fc115be4ff5cfb9e.npy +03710193-abc7c3f050deef2b4146a0f3be16b19d.npy +02691156-1b7ac690067010e26b7bd17e458d0dcb.npy +04256520-386b2caac16694edbab0cb5a4ccf2fb2.npy +02828884-1f19f93fc7d88529ad5067eac75a07f7.npy +02808440-24b2f2a1856df791bdb62d1caa529a98.npy +02691156-14453b29e139d81f6d07c55cf995503e.npy +04256520-92720933afa1dfdcb5c1550bc8448972.npy +02876657-371b604f78300e02d76ab6ff59fe7e10.npy +03001627-1b5ab441fb8e3b1b450621b513a975bb.npy +03790512-994dd337f39a32202f2c109faf1ee2c9.npy +04468005-8044d52df3c796861a5e2b71533354.npy +04379243-6818e317471cf5739a83764a2641fc5c.npy +02992529-229077bcc4f52356f582eaab37b1c177.npy +02958343-9f3c463272d13d39eb7780cdb3ece367.npy +03797390-bed29baf625ce9145b68309557f3a78c.npy +04379243-bdcd0c8384971f2a684b7bc3f8a9aa55.npy +03001627-e1e7e66978b888703f146f1fbd99cb1a.npy +04090263-4c31d19625e911e1f8edafa0d47e47db.npy +03001627-483d22dbbee32ee54e5c7d89bdfc49a3.npy +02933112-1f336c9e48f1b54686d53ab0fe94e911.npy +03001627-1ec5a88141aefca9cf6e4dd7ee69d71f.npy +03636649-b75464a7a5546b39e9ad5e44c87685c0.npy +03211117-36255c016e837e6c234c2f2e8f2fe6da.npy +03691459-9080b08716a2be41e47833b310955a9f.npy +03636649-f64e567b44e550c0fcb8d8c6d4df8143.npy +02958343-e28490350bdbdf679ad3ae277a5ccc98.npy +04379243-288aadc96e908b29cc156800563d212.npy +04379243-38cc604066d18d1cae685ca100c909e8.npy +02880940-d1addad5931dd337713f2e93cbeac35d.npy +04379243-1534dd45b3253cfd902c0a1a69e25bd9.npy +02818832-946bd5aeda453b38b3a454ed6a7199e2.npy +02958343-910ba017e13a2220473f10e6caaeca56.npy +04256520-5209919e8e113ce3e09a21c3ea84d95c.npy +04530566-d1f0353c7fa985c91915777d56cf77e0.npy +02828884-5b9261d3ab4192a4cacb7e48ba59c48a.npy +03797390-2852b888abae54b0e3523e99fd841f4.npy +03636649-707a1c16fe9ba4fa60a25ec0f32e89e3.npy +04090263-2cc92e68121301c4ef0c52e20895a77d.npy +04379243-290df469e3338a67c3bd24f986301745.npy +04379243-3d3e1b8e6f1cd412492d9da2668ec34c.npy +04379243-8ad9868947e7391113625562b56161f0.npy +03001627-d2304054a8dc7ea4febad4f49b26ec52.npy +03636649-d6a5a84cc689a2bd620365f6656fe3.npy +04090263-f5522cbc96faae02cfbc7d85a5791e93.npy +03001627-478074fa4b2b604b6c0c723d8da50cff.npy +03001627-d375dfbaf1a2a3316b2befe83a0efe39.npy +04256520-e0c9ef28aff6484e6eb9b08c8a74d159.npy +03046257-6d2f8c13005c05abedf0adca85d84acc.npy +02818832-9daa02ae72e74b3f6bb2e9a62ccd177a.npy +03001627-98ac0106ad244505e04fc3fcc1c852e0.npy +03001627-ced9c5eee916cce089c398a8a379054a.npy +02958343-6bfc2bf0e72a0f66f500cc506a763c18.npy +04379243-e004afd245bd06337e2a6b10ca75153d.npy +03691459-ea83b0bdf2b13bc89c0528265c614919.npy +04554684-1ffd145c196f19fba7ad9409a09b1a9.npy +03593526-ee425a7b654bcac8bbdc99ec57ef9c40.npy +03001627-b9a88078b22a4485fdef1c01cbd4ae0c.npy +03001627-2f42261a7f658407d12a1bc232f6622c.npy +03001627-b60eb72661b2e56f7445d25f394949d0.npy +04090263-edcbf89b4491941b9905a3939c890ad2.npy +04090263-4106793af469db6bf0fea2ee98610322.npy +03790512-ef8672840524f3dea5b5a4b3c46e79b8.npy +02828884-a775a66a362089fdcb2a965e75be701c.npy +02691156-acb398aa5605abe5a8cba409c4409ba9.npy +04379243-9d7e5e8279ed8a30f2fc41ded2e6c02d.npy +03636649-79487b518c97cac315b5ce4486462d3f.npy +02828884-c1973b3aeb0e54df653ac91111db738b.npy +02691156-6ed172205a9805b8dd9eb6c0ee8316a3.npy +02747177-77905cdb377b3c47cb2a965e75be701c.npy +03593526-f1ae9b2eb551ba466dc523ea4bf73f1c.npy +02828884-3ff4401d898b488a601104cd2d998272.npy +02933112-274b2b7de6654d7ce6619119a89ba92d.npy +02691156-64f01ada275ba83df1218670339368db.npy +04256520-bb2ed216b00409665634c21965ee6bab.npy +02958343-39e10c5d24fee4a6311f5d9a1681aa3b.npy +04379243-88c2cbe9552b1b0571870da176ba03be.npy +04256520-7430f611140fffb68101accd22c701b9.npy +04379243-9dd91ad8d34c249970521b3539fadd3f.npy +02954340-3b0a1a20ef0ce1a34c90f2ddc14dc59b.npy +03001627-94371ddd6d62f7b762ec387b772e9e1.npy +02958343-836c3205338292d3a696fea828ec5eef.npy +03636649-ef12cf5aba58871e5510d59f3ab1ed64.npy +02924116-a3915ede8eff71ee9d151674c6eace6c.npy +02691156-7ce599765d4c11fe87bf26680c510802.npy +03001627-7a783968f5b1f88ff50f16ba773dd73d.npy +02828884-758b78e2ad5dfdd1edecfa50e41e5c9b.npy +04090263-152f598b96676178519f927f2bf92da9.npy +03636649-ab8e7d9b77455a8550f4a93ce2060c65.npy +04379243-ed392c6bd0a25ecf5a7a4ee31b873edb.npy +02958343-fe6749c82c57137b28044fe9244db50a.npy +03211117-928c86eabc0be624c2bf2dcc31ba1713.npy +03636649-66defefd07a3fe4548eb521885c87e13.npy +02958343-42dae5b435c27851b11647ffa4306609.npy +04530566-b4a2778eb3f3dc55f877f04737ced5b5.npy +04090263-42288e57b2436e3512b38b1d99376c0b.npy +04090263-1632f8ce3254cfccc8c51c73cb7275ed.npy +04379243-1872afa831cc7f671b50574ebd76a45b.npy +03467517-b928ffa886500109e391f0d9f72fb31f.npy +04379243-eed2efed8f2d5604a0ab1d82ef09f78f.npy +03001627-2da97edb618f05a5b2ccd937df5da28f.npy +04090263-5d806f9cfdf29bc640eee76592e4bb9f.npy +02958343-1569406dfc3b7ecba9fe1734a6086750.npy +04379243-d1ef98cd329a71d1d8a323bf2c61bf7a.npy +03001627-d4f194efb445914e4b3d6a0fb5682cc4.npy +04401088-692ed312d9ba1663577cfcf36d9b3392.npy +03211117-4f46683ad627700edb09a997c699dabd.npy +03325088-c5de940102fa0cdb50da8b99982a3057.npy +04468005-b123bc34ca87b8f88be7c8c5fdb9bd6d.npy +02880940-571f294b5ab7e47a5517442d05421cb.npy +03001627-42df32ea024077732463600025db2266.npy +04468005-9f7f3ea75364f7e6dc14ba0818ee5cec.npy +02828884-3a6ac28f247a30146d812a3e2aa98a91.npy +02958343-dfc08488e2ec687d1c64dffb0265c4d6.npy +03001627-f5f18fccf9e16800dbd185de408ea209.npy +03001627-e4931ffa06d7b05cb04cb542e2c50eb4.npy +04379243-673540ea8227449d1dbe3e8cd87b5167.npy +04256520-5b27e06a178965c5300703f05f8ccc25.npy +04379243-cfe4e4fb603b99c77843fb4efdc19510.npy +03761084-5392b189a357dbd6e5f8c8c5a6f910d5.npy +03797390-e363fa24c824d20ca363b55cbd344baa.npy +04379243-38b341526f21cc9f6e1c16d8c5e127.npy +03211117-676e65417cd3d59f3aabc01aa1c5608b.npy +02958343-aaa54ba9345b6784967bf54a1f364120.npy +04379243-d3645a097a49042bbeab86a0a7f61a1.npy +02691156-ea29b3af190b00367d3b11085e75c7ad.npy +02691156-c7749c0a8b61f43bc9b9e28055202e3d.npy +04090263-257fdddbd7b231b15063ff48525b373c.npy +03001627-643cac07025f195750f9fc0e2c94dd76.npy +04090263-1ecdd9fb715c6fb2b0a59d0f63b741eb.npy +04379243-9feefc5eb43adb4fb7db0056a767efc7.npy +04004475-db9d02b583bdc8cec25c9cef92ff2800.npy +04379243-51c6a7298408c3f19730cb37c9a5f63b.npy +02924116-7e06d4b6e53773f2bb808872bdd72fe1.npy +04099429-8fe2fda28ffb637369bc13a8c13458a8.npy +03046257-b9d78c6a787d2097786e4057cea53718.npy +03001627-8a87ac1748519dde2fbee880b9f634b4.npy +04090263-a86e3d993f82d44018a76e4544dcc8a5.npy +03001627-12f4d8c20ef311d988dcbe86402c7c15.npy +04256520-5cea034b028af000c2843529921f9ad7.npy +02828884-6f607a06c0d86895ad5067eac75a07f7.npy +03636649-75cd24d6b485e9e01735ea0e092a805a.npy +04379243-4fb40a85a2989785d5abaf84513415a2.npy +02808440-dccb280354aefe171e7f704273b6f731.npy +04379243-c6116173a1cffecaec9ff818c66c8a16.npy +02828884-13da7d4d1277574c64b7b850ea7b68a.npy +03325088-233e131ca64c2fd5c36fb70296e45483.npy +02691156-a57802c776ba1b69e44b1dd0f956e84.npy +02691156-49660fd24e5c2fbab87697d3904b168b.npy +03691459-155b9ee29dd8f068f9872b1642da5de0.npy +03636649-8c5f6d5f0ad51f1a45c8b1285cb15c2c.npy +03642806-b29c691472ec9064f67542ac0a8b28d5.npy +02933112-1d973f05e870af4b4da5feafe6f1c8fc.npy +04256520-f43b6b571d66991f95ca4adb70946a21.npy +04379243-8e3fc5f1f8e9658ce8b2b8dc0c816caf.npy +04379243-2ca3dcbd06295835593ebeeedbff73b.npy +03001627-e8ef93ed45300501bfddc5b20c9212b4.npy +04379243-dcee2fa2aa02fa7c4a05fa063da00291.npy +03691459-71b68a5e64903e0a1ad88f716ea80910.npy +04530566-65be4fb7c78125eda52f887aa13ba9c2.npy +02691156-3881241b81d379644d4cb1c2a5e48b7a.npy +03001627-224775a0c7f8fec65780b8d333445e3e.npy +02691156-e66996d97d9f553939e75b12f2e5480.npy +02958343-e0a8ac5ece3222ea16abce8cb03e7794.npy +03790512-d9a4e331d1ade5277395d58407f193ba.npy +04379243-588b84631bead4d1c1fa182c22e95706.npy +03001627-50e8ca681532bf195fa5d73d8d08a44f.npy +04004475-3b43609493ce118dc580fdeb5460f6d6.npy +02958343-4e6131bad4ae8b6c91af0bf49336b8c6.npy +03691459-e1be0b02973011aa4c5341ee07f41676.npy +02691156-7a95a024f5616009ab21e26e992b2c94.npy +02924116-9c9946b6fbd1a5452fd6f371aed2b46c.npy +02924116-e48f8c869435225e47b1d09f6cc16a76.npy +03211117-8a7b80310c1d8d1b3d5369d27421e60.npy +02958343-8b22da6bba6c81452af3f274e91bb46f.npy +02880940-9024177b7ed352f45126f17934e17803.npy +03001627-4a12589099b05c51e13b3410f3683610.npy +04256520-fd33f7d4b8fcaef5d39e33fed94f56ef.npy +03001627-359b6d3d29b08dfe19fb4103277a6b93.npy +04530566-598f1f474f1cedcf33827bf0303796ff.npy +04256520-1878633a36518ffc19fb4103277a6b93.npy +04379243-5f8764573a6f8321c1a89c6b124f2475.npy +04379243-7610fa5f384cbfe2664b3b9b23ddfcbc.npy +03211117-a44dc3e6f574bcc942e76de3842fd93c.npy +02808440-4310dc866b24e314cd49a3bbe129f2e.npy +04379243-cf478aac2058cae0e589b08489d157d.npy +04401088-aabbfc7463d49368419fdfebc874eb8f.npy +04004475-b8f50a9cf77e8b16cb2d9ca9c84945ae.npy +03691459-7dd0a1aaaf29b18529d8eecf3827c486.npy +04379243-7fdad5057b8da165fa9f3ec600076f26.npy +03636649-783b81aa54a69a26d42b9650f19dd425.npy +04379243-61fe7cce3cc4b7f2f1783a44a88d6274.npy +03636649-c3d57dada3819e60fbaaaf5884f2c88f.npy +02924116-d254d5e10bae194acbe05d30721721b7.npy +02958343-7337679ad4bb8f4016abce8cb03e7794.npy +04401088-d7ed913a3888696d289b03e5721252f3.npy +02691156-f1f12c4408b0b4ee445d150719ce97db.npy +02933112-158134028cc664b5c59350d819542ec7.npy +03001627-2499541ace317cbb8cb5d9909aeb1309.npy +03325088-c8f05f1ff6b10463b55b46d261fe0021.npy +04379243-fb6cfd7064a88468a9ae1099ff133d95.npy +02691156-46c07706f1bd10fcf9cf2c77edbc841c.npy +03710193-655cc66caed0a4759c0d8b17a41b6f3.npy +03001627-58bd152fb816ad2f7f91c3974257b780.npy +02933112-b7be75d3cb83457a44221bef0fa3c36b.npy +02828884-106494f75125eea6adf66a6d73888234.npy +03211117-5c16184e52d1317f5c188551f03b75de.npy +04379243-2f106667589a6cedc36874c8749f7812.npy +02691156-879ebdd198cf4aa58f6810e1a2b6aa04.npy +02871439-1db2ec3f8086669b955c7f158b9debb4.npy +03790512-ed0d6ea5407e542d31ef331a356b2886.npy +04530566-a45cbcfb2763423a6540eb087d7e15bd.npy +04401088-c556efeb2bb3df4621844676433a0aca.npy +03046257-66922901b74190cf7c70545e85230d83.npy +04256520-82d25519070e3d5d6f1ad7def14e2855.npy +02958343-7edb40d76dff7455c2ff7551a4114669.npy +02691156-de3a0bb3f0ca87a5674fc9582804ad0a.npy +02958343-5fe9cca902d8135aa36fba949f601317.npy +03513137-4730ce6da5433f3bd93d030573255054.npy +02828884-1348e440934494f581faebbdea6bd9be.npy +02828884-373ae08d8903dc10ba929f7d2edd1706.npy +03001627-ff2deccbef73ff5a349bb1cbbf9a4206.npy +02958343-76680f2bc0d53c6e3112e33afb0a091c.npy +03001627-12f395270a3316d01666e1246e760f82.npy +04379243-89fa346209ccdd0f16626db88aecf64.npy +04256520-51dd0bece7876a8744fe3ba945082ada.npy +04379243-f70df4cd7109fedb4824068fb42a2b57.npy +03938244-49cfb88c1291a152fd5b65552e5580b6.npy +02691156-8c851663113c3f6790baeef8ba5b93e5.npy +04090263-eb71e9847932ddda558fc0121b183f15.npy +04530566-f60404b62c44fd3b49f0e3dd7767881.npy +02958343-6f61af12304781b1297cfecdd0d5b071.npy +02958343-dee83e7ab66cd504d88da0963249578d.npy +04256520-627819d2ea8ab9d9c97e4283c3b75587.npy +04256520-f178d79c569c05d47edb0bede88c064d.npy +02924116-98568658cc2f000719e7223d2775d9c.npy +04256520-4a7db7357b6b6249492d9da2668ec34c.npy +04530566-176cea94ab59ce9949f0e3dd7767881.npy +02924116-82fcd4e8b161f07455653b4d8cecd79.npy +03325088-aba8b03696508ce65072198ae7ea0be2.npy +04379243-d08a421a6362b4bcb000f20a5153622c.npy +02933112-77aff49eccafcf2726831803d0b48347.npy +03001627-d2a5b42cf29b753f71a782a4379556c7.npy +02958343-82b9ce9740bfd28fe9fab7ec4b8a907e.npy +02933112-6686c3a7dc39cb59d2f1945599cd5176.npy +03001627-3dc8243b17bc790620768660cf080d12.npy +02691156-d438a4539d8068fd44601c64497858af.npy +02691156-bb9ba5deec9e2a5fca8607f540cc62ba.npy +02691156-6f96857e279a38793525b6164e3f382b.npy +04379243-39adf6058de74934ba18ade30e563d37.npy +04379243-2e23b1aa756399ea1138d031cf239f4b.npy +02808440-cd23523044b34cb29a461ceb2370bcba.npy +04090263-83a6f7a02470263ce71e857afa9df271.npy +04379243-fe5be6c8f1599697c3bd24f986301745.npy +03001627-3c1dc5c4b0c8db31d20c5daab0fdbf5e.npy +03001627-31bc7f782eb3bd7de40a8ba0cba661fd.npy +02933112-2f87d7d3c522f07b297936c81e7f6629.npy +02773838-5161d9adede671d6edc32c5c9ec9f827.npy +04530566-9b93b845578ee8a20c10ff7bcef26d.npy +02691156-82a2a1830758bacba389345bd31e2871.npy +03001627-d29c14f180ce319f71271c0017c27c86.npy +04090263-378c3f18cf130bace1f2a1daf140ac9f.npy +03325088-c34723e92771fc5b7a867e9b35a1295.npy +02924116-366e45c0ffa4f059f5faeb3213703480.npy +04256520-8d0d0661c57bdd09b6cfb56a0ae182ff.npy +02691156-a487d7527a0d0c2076b0a025d05432d.npy +04401088-a8bab81f66ac5d26acdce172dc618222.npy +02691156-c3600f9ede30352a663e90eaf6b4ca52.npy +02691156-229c164fe2c80acc1ca2e8373597f711.npy +04379243-99fede796e56b4b220eb25a3a058bd49.npy +03636649-6b2a590446ad5794b10e111f2d30684d.npy +03636649-85f1532468f57b13fb26684cf995edaa.npy +04256520-e03147a11bd7c10e3d23022ce06f940d.npy +04256520-1a38407b3036795d19fb4103277a6b93.npy +04099429-a410b9d1557f0bcad6a1861443498ca3.npy +03001627-e50f1b2d0835bb392764cfba57a5de73.npy +03001627-1b3c286bce219ddb7135fc51795b4038.npy +03001627-5aa3f60fb8fc208d488fd132b74d6f8d.npy +04379243-1eaad686e6b766597ff6ace05b36a5.npy +04379243-d38a9d0fd304f3eeb6e024121d412dd.npy +03636649-3edde0735bdd2aeec8bd09a8ecef3d42.npy +03211117-bf5a771386075e449b3250464ea24783.npy +02933112-ba5e1671d26af2763c6c38b12db4d8f3.npy +03001627-374b3757a04c6ab6b9569033586af233.npy +02958343-96c84869cb3c6657e49167a1ad5be1be.npy +03636649-cdf8043d57863c1b17b431cae0dd70ed.npy +03691459-29b26d5aeae88531574d21c0c95092f.npy +02691156-5d7c2f1b6ed0d02aa4684be4f9cb3c1d.npy +03001627-47ad261baf9609ffc27c29012942420f.npy +02958343-7c46bfff2f90f11044592db9be5db5c8.npy +02924116-54f3b48cf9c7ed13a3cfa46226644b04.npy +04090263-5b70d54d7f40fd8e5c413e9fcbe8ea71.npy +02958343-1768f55a3c29cd483337cb9d908ce86e.npy +03467517-5b6306025152e03a59a6208793b9dfca.npy +04256520-581808bf8d8e1d2448eb521885c87e13.npy +02691156-91948fbd89e316b9a1efa53c1b6b3c23.npy +02828884-c33b2dc4fca8fd178cca710901c2e97b.npy +04379243-222c56ff9cddbaf4139eb23f7c8036f.npy +02958343-b6525d69681e4f56813498cc26c2aee.npy +04379243-54dba548def577137f14c8d2897662a6.npy +02747177-62f4ed6e1df63042cecaed25e0da0964.npy +02691156-93da50dbee3d1f78a7d0c1e4eb8db7dc.npy +02933112-62e1a04718635c981c7fe5be55ca5cfd.npy +04090263-c9e48e2db6786fb7c90b07f90175a30e.npy +02747177-d3b69f01f5f02240ad5067eac75a07f7.npy +04090263-513ba432b16287f5baf4b37340b9dde.npy +02958343-9009d75263e350ffb3b0f00a15b90e0a.npy +02747177-8b071aca0c2cc07c81faebbdea6bd9be.npy +03790512-e38201d0af98e566ba85a673915bd3d.npy +03636649-389653b54a3b5d3cd73bf61f46c61ea3.npy +04379243-f40c11ff508e477d55f46d55537192b6.npy +04379243-8e358c6f92a0624219fb4103277a6b93.npy +02691156-be96646f774c7d0e2a23d93958262ccc.npy +02946921-6b2c6961ad0891936193d9e76bb15876.npy +03642806-4a715660d89e097664c908bd136dd7c0.npy +03211117-48c17189e6c58d619f4c3c326d704746.npy +04401088-a56fa90572f9e23db30cf593b4a23b0d.npy +02691156-f562ff06e51e573e42979ff355194f16.npy +04379243-e79e55e6e08245c8dd34b2617efa7e35.npy +02958343-25f9e0e65b8fae1f9916e41a3ca14d3a.npy +04379243-af592a064d5a83989ccce4c6d5bb195f.npy +02958343-24819ffdc34b28efe4bee94a37836d67.npy +02992529-e840fab2f764532ce4bb3cae511f21f0.npy +02924116-68d05210e6e4d4b4cfcd1fbe1cf0ecec.npy +04468005-6df2dec0dfa5731ebbdb7391763a8729.npy +02958343-1fde8f41c6a39c07111f983eb293b51a.npy +04530566-47c53f9cfdd4addfe054bb56e3407f7b.npy +04530566-9ea697394812ce328b68234f52d97099.npy +04379243-a377ae927e09bbe976e9713f57a5fcb6.npy +02691156-ea9eece7f2c45a2a82e4c37374fbdce.npy +03001627-33fcb31af4c4d039fac1db559484b15b.npy +03211117-d6752674a181d04829c956de83176829.npy +04379243-ad3e2d3cf9c03fb1c045ebb62fca20c6.npy +02933112-6a36134591ec32cd37c7771ad8a91690.npy +04379243-cd01fd75885d9f606ce1f91756352daf.npy +04090263-e9adfa95465f806b056c98b2e5e5e4e.npy +04379243-33486ab58b77ea46768449c155e32d73.npy +04090263-aedd534b9f323b2f9f433921788191f3.npy +03001627-8be5b3b2c8c8f067a341228b21d337a9.npy +02691156-9d3eb87e69fba56890b1d6deb98feec6.npy +03001627-719f6578bd1450cfe5b7031248b81d78.npy +03001627-68151e7a9fcd8545851e82fe58f53ce1.npy +02828884-18d0aff1a5eb486ae2be3aed8abfbbaf.npy +04090263-b519a23d82f367ffd39cbbc2eb28bad4.npy +03211117-2608db8ae887c6e0b996b003c2af3823.npy +02691156-2a906a12b740afe2fe93207afde39a32.npy +03211117-fe3e7a35b8a1c06d3bb4a1304fe504d3.npy +04379243-c838d6a451994749310af74324aae27f.npy +04090263-1533494d4139062e9f433921788191f3.npy +02747177-2f79bca58f58a3ead2b12aa6a0f050b3.npy +03001627-94e5d7fb2ff59ff98a94168388287ad5.npy +04256520-fdfcfc4e9daa45306aea2f18ee404fd5.npy +02828884-92f1fa8d3b5da497ad5067eac75a07f7.npy +04379243-23437993281f7e1fb06ed3dfa60b19a1.npy +02958343-d6def3a1a90ff22bbecf71e2e014ff6f.npy +03691459-92039123d08d8ad6adbfb30d8d1b297e.npy +02828884-504ad0bf35b2004dd2b12aa6a0f050b3.npy +02958343-3aa2614f69105d0f31780fdd33037c9d.npy +04379243-5403184c2b01e0dae4061112aefd200c.npy +03691459-a18c311eba5e551d20363e2561dd589a.npy +04090263-9280249d5e91334f0864f9e40a51390.npy +03325088-ddebdd166c4562e7c36fb70296e45483.npy +04530566-5af5aa92ba49930c3f41ddf3713a131.npy +02958343-198dfa16ba9f5f6617e76f36a4eac3ec.npy +02958343-dbded0816afdfcf776ad064d1c5fdd7c.npy +04379243-1b78b8e14a21439afab04609f4609e83.npy +03046257-45234ad309a071d0ce256d7e95c7a4ed.npy +02958343-c9b49f7b355528e5632dc979097a3ec0.npy +03636649-e6dae18d7ffbb7ff952c851f81463faa.npy +03636649-74df8c15024e81f79f1a71e46bbde97c.npy +04379243-2a0eff86efdf60a89a682a6d0e92c30.npy +04256520-770b9528c04f99d5a3bafec3b56382db.npy +03001627-3bd437d38068f4a61f285be552b78f9a.npy +03001627-dfd7e14d25b81c1db5d9b03636b8bad3.npy +04379243-9ba82ad65b1e90a1f51fa0238791f5dc.npy +02808440-1036dbcbbd36fbf385d4c5933ce331fd.npy +04256520-6051f687d35c6ba577dfa90ae0b0a3ed.npy +02801938-caefb14d743df2d69c3870d54ab64b77.npy +04256520-5ea73e05bb96272b444ac0ff78e79b7.npy +02747177-156fe84679171501f155d75bbf62b80.npy +03691459-2a32fbf104a7524ec78a85a5b5306f41.npy +03593526-acf2697f5c1cfe9b89035c25f0dfeb63.npy +04090263-981d2bf1b1b028e46b1aa8d90854daa1.npy +04090263-866fc73e306a47a1f246f64ee1a24a70.npy +03001627-d90e76683d11f75fde11596dfa0db02e.npy +02828884-ae6e6210e0280f24ad5067eac75a07f7.npy +02691156-d2412f19d33572dc4c3a35cee92bb95b.npy +03325088-3ab88b710b8ad3ee3321831d2245cf06.npy +03001627-20b36bbb42d36e0771dcb8deedb6c8d.npy +03001627-2a643eaf143a779f7eeca6709b6a824e.npy +03001627-91534e0a3b0aea7526fc87e2982c8a2b.npy +04379243-7953711de0134028ee18bc48b60b36b7.npy +04530566-ace32fcd2b6c3fd081e9f45621d2c8eb.npy +04401088-30d54e046b9abe8bf1cb19f636b1c2bd.npy +04379243-81094bd607e33c1e0c5923879d79f21.npy +02691156-67da7044f5bee4f65c6d168c6e7f59dc.npy +03001627-4450887b9a8867e6d9b53420a5458c53.npy +04090263-c57c4311f1f23690603b56d612737c9c.npy +03211117-d3f9fc10276d8922f7248d9dbed7a7b8.npy +03513137-d739548a9b15c18cfac6099f3d4830fe.npy +04330267-f8bda034dabaae9c9d2947b7231ac529.npy +02691156-d3856a35d1fb8536d8e727806889c9b0.npy +04090263-c0ac896c514cd91428a27232df2537e4.npy +02691156-bc764c59e4bf4e9f508cfa5a106b05fe.npy +02876657-20b7adb178ea2c71d8892a9c05c4aa0e.npy +03691459-d35894de19f2ac5af6ab94ce02a994c4.npy +04468005-d9a4a8423457bd92bd127c2230a8477.npy +03593526-f47da3a419cdf600e01d7dc978602402.npy +04256520-dd370ef3f3e8097abb9760cf9cd1a953.npy +03691459-f0629a8139a9ba04f398d0c5832df00e.npy +04379243-11cdaf2939502622815a10e5a35009c9.npy +02958343-7d099ac5bcc09250e61b9ff60b1be412.npy +03046257-d2cd542928c5b684c98f75a9ff83e3b7.npy +04379243-88676c2f87a5b54c4500047017815f5f.npy +03001627-4ce5a0d60fc942f2e595afbdc333be49.npy +03467517-5446e1b00632ba2186f9feebc35c79bb.npy +04379243-61c279a6f178a43c5f48f9175316bec.npy +02828884-2f2fb3e4f0d9c4fe9f8ae7ed6368949c.npy +03325088-ea8d250e3363377c36fb70296e45483.npy +02691156-551e8582c195944af1b991541832fbf8.npy +04379243-490eb3a23cd0ec4e9ccce4c6d5bb195f.npy +02691156-ffdaed95c3063cdf3ce4891c7dcdfb1c.npy +04256520-e92955e3e3ee33f32650883217a11488.npy +04090263-4cb322a9a37e3a4d1c1943a82a09125f.npy +04256520-4424a906da6fd4c961bf0ba277ea473b.npy +03797390-44f9c4e1ea3532b8d7b20fded0142d7a.npy +02773838-72dd1dca3421f63576bb31db0358e9c6.npy +03636649-6aa1ce4e245001589f1a71e46bbde97c.npy +02933112-9ba333215be4d6654c62bee40dcdc539.npy +03046257-220d4bef77a82fb164c33a5741e8e076.npy +04256520-5b23328fa6d5382d295b24579cf55b8.npy +03046257-854ce0d6ed37103248e2701b91d7249c.npy +02691156-83e4e523003294ab9a6e43b878d5b335.npy +04090263-34e8142e7b3cb229d735fa1ab17311ec.npy +02691156-b5cdecafe353e18ac1006ed55bc1a3fc.npy +04256520-c04dff28e5b5a2e5c283ca2c9df7372d.npy +02691156-46a1b199bd63c0b4505ae8d422ba349d.npy +04256520-ad274aa281d74c7d78e2b63e72b94e04.npy +03593526-bf2106de86fcdb3c9f695af5ccc7d06f.npy +03211117-26b26a5c4a8fad9e57145c11333eb62a.npy +04090263-a11f9df8336fd83e5cd09b5ae4a3c552.npy +02808440-848124bf8497ee436bb6bc0db07c71e8.npy +03001627-249f3eb6a7236ff7593ebeeedbff73b.npy +03691459-dc73b4f97b493d18176ac8585fbd7fcc.npy +04090263-daf8f85c017aa8c3e1f2a1daf140ac9f.npy +02747177-85d8a1ad55fa646878725384d6baf445.npy +03467517-1edaab172fcc23ab5238dc5d98b43ffd.npy +03211117-aa2f94416852aaccc60dad40a0c0e85b.npy +02876657-cc48fe97a95e8716ccaa5ad584801c3e.npy +03636649-bc704db7b62582e5d1cbf3e52b9b6237.npy +02924116-7b68c55d0cf319a6cd801adac9ea724e.npy +04379243-a2418ff066f38084ead6784d11c8f5b5.npy +03759954-2f65b3f9a1ed10c099bbfaf5793d01a.npy +03001627-1db766ad516a6993f4b6538438a0b930.npy +03001627-73f9aa75944ecf0b9debdd405104de8c.npy +02691156-e7158ecb09050b03873ec74c119307b9.npy +02924116-729f939672b218c26d09993d87837d01.npy +02801938-ac36b5a7ebeaf8fc317c35ada68f2189.npy +04379243-68f72d87a2f94e0c8f58b2a82381f0a1.npy +03001627-7ee5785d8695cf0ee7c7920f6a65a54d.npy +03001627-260768554aa1a64f2180a9964be89fad.npy +02933112-9572162eb971e75dc7cb20726c4d6c81.npy +02933112-eea67da61b5477c7d4c6910fb477cd67.npy +04256520-4ac96465d859ecc647826489152a0c30.npy +04256520-c3c5818cbe6d0903822a33e080d0e71c.npy +04379243-ca9bcd3ecad18d8fb4c161851ed2b4e4.npy +02958343-3ed487192c098a36811090af72684c2a.npy +04401088-49ce3fc723ee4b362d43b5caea00b490.npy +04256520-c1950e8c9869a7aa8dd711af5650bdcf.npy +04090263-eb1655ade2554c156e49a9db8e76daf1.npy +03325088-6c692c34625914a64cc3b7bdfa613934.npy +04379243-c1d99397e37782c0a8699b6183baa203.npy +04379243-f995c1239510cf8b5d009c98a5b96836.npy +04379243-2ec13bb2c3d06c0543dbb6421d614c0d.npy +03001627-68d41388f8a62fce19abd93be2967664.npy +04379243-647692d3858790a1f1783a44a88d6274.npy +02828884-2fec2d7fdd169e28bb90acb1046227f8.npy +04090263-b7a8d379fa29b41adfb4916f5d51df47.npy +04379243-7c653a77d59fbfbd84d52b3f4a5fb1fb.npy +03691459-1071f82bd0d6a23935cd53a06b1d2317.npy +04530566-9bb4fa1026322f0f3e39f2e17005efc.npy +03211117-4407eac60124e17789e75af9d2c4ee4b.npy +02992529-89019c955310bc56eeb3fafe1bc8c07d.npy +03636649-e993492372fce761cb3a30f2c37c38a6.npy +02933112-740392e1c6522664c20c4293bea04a44.npy +02933112-4f168576511489f91439869d172d3897.npy +04530566-e2ee62e09af461498d84ac376021f1.npy +04090263-aa724e9dd919edc3fef144202cb2b935.npy +03593526-23e0d277a58fba0abced73c51e99f8b2.npy +04530566-5d48d75153eb221b476c772fd813166d.npy +02958343-f8ccef3ebeaac7c0539e4d34a3035bd8.npy +02958343-f9f50e199b706caaa148ed368ea0303.npy +04099429-23ac907063ffc5de3df4fa4547276fc2.npy +03001627-5a60c649a221293d72ed554eb3baedcc.npy +03211117-a5939f4fbe1009687f2411014f221968.npy +04379243-6f92486fa7a1aea221ab9b8a0e862145.npy +04379243-2ce9bdf770b06e3745a4a35cfc2e42d2.npy +04379243-1cbd8a3d7208cd6b8990d2712ce4d993.npy +02933112-373fc669fbead0bd1f8d8332ee17945a.npy +03636649-5c7965b0835a1a241de9bf5a9c22fde.npy +03691459-c5b38593b74c39695f7109466a688ac.npy +03325088-ed88b271bff935dc4bbbee4015534b3.npy +03001627-bdfc3a43eccaac7e908cb3a44391b80.npy +04379243-82f1ed2a66bf8b49f08a713d0c983d8d.npy +04090263-da6a91e6557973ba78dd5400499d0e7a.npy +02924116-31d34e11e37ad640c6bf3b18b8ca71a.npy +02828884-e0f7a559a6066203dacc0b57c47fa747.npy +03001627-44aed693950b077d4f9691cdd5f8749.npy +04379243-8b963c7f5f091b3c98100807afd99d94.npy +03001627-ce2982a9b05fef738a075f7da2b32df.npy +02958343-7de59e150d4712b7b3cf5236f651a8e6.npy +03642806-9980e8f99eb0098bc6b48dee64de8434.npy +03001627-bcced2f12f206a927eaeab1f0c9120b7.npy +02924116-de8c870859f57c4752470de2774d6099.npy +03467517-6e65c6b79bd8df3184ce60b118ccc0b3.npy +02933112-82c05fe4890a7f5112de5317fe5b354f.npy +04379243-acd6ba50b3081e5cd3470f853139ec0c.npy +04379243-dde92f6460b1d7b2b4cb6dc412eb15ce.npy +03325088-412ac477ee9e761250da8b99982a3057.npy +02992529-3bc6f902628b3f7f85f6153ed2033a1c.npy +03337140-69080f3e82b012ae2590dcdc900ce405.npy +03593526-85b34acd44a557ae21072d05c97a5e0a.npy +02828884-cc08d4ced5931ed181faebbdea6bd9be.npy +04090263-cbcc80e6964f1080b2d09bc8d348e46b.npy +02958343-cd3db50308c852a02630fc4a206fe3d7.npy +02958343-6d083701a45fd0721ccbd9e5bb82dd04.npy +04379243-97e4bfc6f8d2e2fb986b72a93898270f.npy +03001627-7a5d539e3771a491ca6a405498436716.npy +04256520-52d307203aefd6bf366971e8a2cdf120.npy +02691156-7d180493022c01daace5721ccacba16.npy +03001627-515f8729b20cb3612412319d111a4961.npy +02992529-5bbf52512a45bddb7525dc2f981e5489.npy +03001627-468b7e16a29ce746bd08524bcb66a009.npy +04530566-1e8c9dd30d54392856d301bf1319ad4.npy +04379243-1bd49921fac3e815c3bd24f986301745.npy +03636649-1f58b59a1b6b06df766fc93a239bada0.npy +03261776-b26bc64c51736aa7eadbd0a9373027b4.npy +02808440-303b0d2566846f373c8d0fdfb1cc2535.npy +02691156-2502fffc569075b152486b4487d562c1.npy +03325088-5b0049fff25483854e0738735f157c3.npy +04256520-3897ad42f73988a62406c215cad9df09.npy +04379243-875f7a7c2d69b01a30bbd4cddd04c77b.npy +02958343-4c2c33070c6597ca9004afc0d5dfd164.npy +04090263-60ac11a84e307db07c52b7b7b148ce27.npy +04401088-fa9b007a326be6975c8fa950032e0987.npy +04256520-f2ad41a5ffb961c4276813f95a6b7283.npy +03001627-25957008f839ef647abe6643657b8aec.npy +04090263-10e60e0eb0d7915c8de11d571206924.npy +03001627-9e0a1e2857b13b5853353c404519f02f.npy +02828884-3830a5b2eec789ac63b2acb037dfbcde.npy +03001627-d5b9579151041cbd9b9f2eb77f5e247e.npy +04090263-235853d2947a90e65e9786b1603f45c8.npy +04379243-4068a0e8533230e4ed8cfda52671df0b.npy +03691459-c6480c816679773dde4fca22b4a322f6.npy +02933112-c8631f63ec5899a4a84a884e8267301c.npy +04379243-ce8ec2504676cf874b3c42e318f3affc.npy +04379243-2d1fef407ec41165700ade95b2f08044.npy +04256520-ace76562ee9d7c3a913c66b05d18ae8.npy +03001627-ebf8166bacd6759399513f98ce033426.npy +02958343-34762df3ff8961188bb11dbc05ffaa74.npy +03001627-cd7674dec40cb30f30e06a011e63236a.npy +04379243-99316252e1dfbde1d810b14a81e12eca.npy +03001627-8b886cf32f340c89a9e00c019d029152.npy +04530566-b9d541ece25778e12783b84b5d2d6e46.npy +04379243-2d27e4d0f8cc2c9cf577ff4de1ac394c.npy +02933112-2e4184763139ff274da5feafe6f1c8fc.npy +02808440-2677d8c3f8be424a6575a854c6bafe.npy +02828884-2f8bf1c9a8f70cb0f4fb4dee5181bee.npy +03001627-fb633f298fd5a44a9a8ef44e1d2c5b75.npy +04379243-af8d3848b96bbd0d18821e110fa8400d.npy +04379243-4c2103f096818e16ca368f1abf470106.npy +02924116-68a2211cb0d8c16a9afb67dd284d342.npy +03642806-d4a1b5ef035650a51021cd55d164c0ed.npy +04256520-6d7972e468db59a6613f0dbd986ed6f8.npy +02992529-f5f1fbeca9af99c98efee9b82d757c0b.npy +03636649-15fc5a4a342c00525412c66cb6f267da.npy +04379243-d80a4629ab6badc16469e58b3534356e.npy +03001627-4abbf49c3177b32c9f613b70ec8c2f82.npy +04256520-63fe6b5903df38a0ba0f037fee399b18.npy +02828884-9e429b7f77646b4ccc8f8e7f17e9d7b6.npy +04090263-c29bc7b0dcdbc2b9e1f2a1daf140ac9f.npy +04530566-587cc1fc65ac4991ff920fdb73e92549.npy +04379243-14d1d6227d6e111049afcf135d820991.npy +02691156-f50eba69a3be1a1e536cfc00d8c31ac5.npy +04379243-7d1fb46a27bd93252c4683dd00deec1.npy +03001627-51670c355ece91abe24f4cc9bc86052a.npy +04090263-e4a10d825ba51a1fc648677bc9b1d6ad.npy +03001627-d374912c3a9fca96c141a04b2a487fd9.npy +04256520-6caf860b216a951edd97e8e261a01f65.npy +02828884-b54d0fbc33d125bb7a6d149f6c9151a9.npy +02691156-df7313e87ef2905d37678474be485ca.npy +04468005-8cd345e5980cb800c3bf8b7b051cba6f.npy +03001627-59f7e527386ab08b7f0751100c225ea1.npy +02691156-3cd1b98f12d2a22bf3ad4b0977199f23.npy +04379243-a00017528f02804e85c2318bffd77ab.npy +02691156-25864172dcde70c6ace5721ccacba16.npy +03001627-f59627a077dcc2566c63b8b48495261a.npy +02924116-1016074a78aa410cc1c19bf4f4f5ddb2.npy +02958343-c23a65ae787245248580e2c19c4f9aaf.npy +04090263-faffd9098e488836fb6bde4b7e6c6613.npy +03001627-1b92525f3945f486fe24b6f1cb4a9319.npy +03636649-d90639e69c82f864eb2d9895648d1206.npy +03691459-cf7a2cb0c487f3a0bd1cba733b111584.npy +02958343-52abca690cceb7c634a65e2e5c663c7e.npy +04401088-585f02091286a7a82b7045644a6897b2.npy +02958343-2e37013195d95f494470fce578e2b84c.npy +04090263-461cf03b41be093d9ee71f8982c8aa68.npy +03337140-de98cdf56188a576731d11154716a6b8.npy +02880940-e3d4d57aea714a88669ff09d7001bab6.npy +03001627-5008d5e0ddf1b3dfa37d17ad9e86b6bb.npy +02958343-9aec89a595e4682fbc5845a373118df7.npy +02946921-96387095255f7080b7886d94372e3c76.npy +02691156-5f2f19cff434d86ceee9782f3a645bc4.npy +02691156-ca2a07b005ad4385ca8607f540cc62ba.npy +04256520-58cf696abb5d3e7426415728d9c23636.npy +04379243-decd9ab8c2714f2e7235016c2c2c8150.npy +04090263-34ad54857a4dd37e12b38b1d99376c0b.npy +03001627-587ebb2aa71acfe644dd3aaee16d3f4c.npy +03797390-bcb6be8f0ff4a51872e526c4f21dfca4.npy +02992529-7e8e9cc2cd70a66d4d1f2fe604198dc9.npy +03761084-42aac49442bb9f8bb4e3935c6cee4b35.npy +03636649-39bc57beb358fae677981b941eb4f5d1.npy +03642806-6e728e12c4b4dcf26479a182158bae5.npy +02691156-48a36df204cb05dde7fc8cd567dee096.npy +02958343-9a152b11907b11074549b3c52ae0632e.npy +02924116-e2824565083fd0c4ca8e0c77b23bb25.npy +04530566-ec97e9975c94f7ba727ef88d634f1148.npy +02924116-521fbafd6674948eeea69f3a548f8109.npy +03001627-490cc736a3ffc2a9c8687ff9b0b4e4ac.npy +03636649-67fc0e388b91d55fcb8d8c6d4df8143.npy +04530566-4021a170452d19393c79f1baa816886a.npy +04090263-9b5a5de7af6ecc4274e18e0e7a19212a.npy +03001627-32f918efaa64a4d9c423490470c47d79.npy +03001627-be0890a6a0f3fcf841f91bc9e1dece3b.npy +02933112-3c28e4a1a5154ecc59350d819542ec7.npy +02691156-f1111840bde23096ee2723567c7709e6.npy +04090263-4e42faa1861597c9f2c612775ea2be4f.npy +03001627-9ab18a33335373b2659dda512294c744.npy +02992529-350dad20c76cb54b7ad5140f7d56e11a.npy +02958343-83cbe72c4b5e9268ec89747d864c8515.npy +02828884-835086fd24eb283650f9fc0e2c94dd76.npy +04379243-640da7c995f9fcdeab571431db8834c7.npy +02958343-8997065fe94841771ef06e9b490109d8.npy +04379243-b69087245c6ce1c57fc1f91f1396c600.npy +04256520-e29de3e590d4541c285e5a1f74237618.npy +04379243-b18fcb1483fc0f4c8ea6bd444282b41b.npy +02808440-a64f942a8107ce5f44221bef0fa3c36b.npy +04379243-2a43665ce0526ec3bd24f986301745.npy +04379243-39f202c92b0afd0429d8eecf3827c486.npy +04004475-710bc6c5434612d6b1ce1e5dfb273bde.npy +04401088-424ccff9ceea33451c81652b127a0ec9.npy +02691156-b6d61068ef2bf2d46059aeb39e538eb2.npy +03001627-5c9b4af9d0e9c132b161f36d4e309050.npy +04090263-73dc8568cca29c0f7bffd97a22e78e2a.npy +02876657-70e58e9f89fd9802a9891f6668163611.npy +03001627-c7fe45610d10cb108ad3a7d07aac2767.npy +03593526-72dad3d3eb9aaaa6707cdefe012d0353.npy +03467517-46eca0ceefe7bf062b996d5d44e09408.npy +02691156-11def84f9fe8ab0acd726e804e5d7a.npy +02958343-18f6df600df7341ab0bbc6f39febba97.npy +04256520-c3cc9a21c0732ef9b2f052bd9ec28053.npy +04379243-a0796a2532fcb95fb1b6b0c5ddacb607.npy +03001627-c9913221819588b519fb4103277a6b93.npy +02828884-f4afba7266031dbbb62b272ea9e18d0a.npy +02691156-c2923f0931fa539f794f2d24bb38b7d1.npy +02958343-45bbe9d4f12433cf4f2af69a26c97402.npy +04379243-e056700bca093e0c1cf96a5dc33e37f1.npy +02958343-7112c1cb9b6461c9a551e6372afde900.npy +04379243-57f881c06c1080ac91829b477862aff6.npy +02828884-23931fb6b6c46da895f577622f465c85.npy +02933112-75c26ffff01ea7063ab3dfa44f5fab01.npy +02933112-315f29b2492f66a9c59350d819542ec7.npy +02691156-2d7562f5bf2c7f2da1d85548168d6015.npy +04379243-e72421299768187426a61458b682cfd6.npy +04379243-cc6283a5bcd5452360d9b527752ac99f.npy +02691156-d8d9de967255b4c562b600da24e0965.npy +03001627-d74870729fb3e3c5aa0a75782a86b0f3.npy +04090263-597f7914fa401ce1433d7c8e9cebd7c2.npy +03001627-1e2e68813f004d8ff8b8d4a282992be4.npy +04379243-88e73431030e8494cc0436ebbd73343e.npy +03046257-c45e4604958d9d1d3153a6db1fd05f23.npy +02691156-df0b14faa90bd4dce68b9e5f5c3d0eca.npy +03467517-120b5821b1d27de5ba32f71f79130dff.npy +04256520-5eb9da1ae0ae618f1190e285a2cbc9c.npy +03001627-9dcede4115b4379e2af4036e9c51cbc4.npy +02691156-b63c554a915454b7a8481a97c910a7de.npy +03001627-34d255abb83e8d7519abd93be2967664.npy +03001627-1fccc2ac4bfd3da535836c728d324152.npy +04090263-e6ffef0550b5b2aa7833354cdb66ee8.npy +03001627-9c50878c91aeb8126bb6bc0db07c71e8.npy +03636649-27ed76ca359d6eaffcb8d8c6d4df8143.npy +02876657-6821f9cc313dfdebe7ef9fff09638f8e.npy +03001627-a273d2fa5244c74f654ea6737b0d3597.npy +04379243-65e5036f67dbac4e1cb7b51444dabacd.npy +03211117-21de0761d0f8f2f9342b2a88bd008cbe.npy +02691156-414f3305033ad38934f276985b6d695.npy +03001627-e440059fcf6f36496ebf11292bdb9130.npy +02828884-85034e80317e36d9a6c03a53cf0a14c9.npy +02691156-123bd9e948881939c38a1d3458dafa1b.npy +04379243-cd413f0540b54bc1fcf003a332eb3241.npy +04530566-e969147de0934040b2533fe4d795f40c.npy +03001627-9faecbe3bded39c4efed9665e3f75336.npy +02958343-c52a2f6396ad8d5f97df6383472cc5b6.npy +04090263-f130c222ff91520182c15a8613f6374a.npy +02958343-eafa5935e963b0035e875676652081cd.npy +02808440-210c971bbc492960b022c94235bc8601.npy +02747177-9d453384794bc58b9a06a7de97b096dc.npy +03211117-ebe5a5c179cd4ae355b9f0c05f9db07c.npy +04530566-e0b49aa20792f2fdc99bbfcf5650bf52.npy +02992529-3036e6b2a898fc85e85776440ad91264.npy +02828884-e0777bc4f8e3c6db63b2acb037dfbcde.npy +03001627-f9fb36db323fb2d2df6cfab91d65bb91.npy +03636649-6c5b0451e99192cbd4bf7024dfa167d.npy +04090263-b9d2e06cd1844f6a6325009a8a12b7e9.npy +03046257-34545d313538df146463df620b7b4cbc.npy +03636649-5e7f0e657142fff3e4692b8e5c093494.npy +04379243-7842ac8b7a053dbf61bf305cc5ea87da.npy +03691459-bb570a28a0e81a51d747b49524a1246e.npy +02691156-9bfd7f4ecdd8efd8bd46d022fd7d80aa.npy +04090263-42b44473503d82101c7be7f1ec012899.npy +04530566-b0238a48839d2b1b64ada2fd6418de4e.npy +02691156-b4b1b113173a6ec6bbf3143b1cb6076a.npy +02924116-fd22e8ff23d7a4da3709ffc87474086d.npy +02958343-96c404939bdba58331ec7db1bc2ab2b4.npy +04379243-1b9605a88fdee0626bdcd672c2b17215.npy +03001627-ff2223a085d32243696b74614952b2d0.npy +02924116-a85b9a3ace923e424721d5612f98ae26.npy +02924116-d0f9952155dfafaa58e6c5721f48a106.npy +04379243-5e84051a6a839c24b577ea930304326.npy +03001627-7f820a5aef9899d5e2953fd13c76ba9.npy +04256520-4d8ec1a57f4ac78258db0ef36af1d3c5.npy +03337140-fcdd18edf5219ae6e7ecdbe73ef4323c.npy +02958343-b2f3ab0b028eaabe443ea0e3853eed5d.npy +03001627-dee24ea8622e2005dd0e1ff930f92c75.npy +04256520-6c3b3c37c20bf2fbb40f0ac0fb9a650d.npy +03513137-c3fb3e4f87ca6c91388f6c7a9d3e1552.npy +03211117-95244648a330b9c0330afa9b9b51085f.npy +03001627-be305d2400194ef726e926172da61b44.npy +03001627-64fcd1ba0df5d54d79b3e1be3524f72f.npy +02958343-a42b6210fa2682adeb4ea3744b7acd6c.npy +02828884-bbd82d91a0b7fc12ad5067eac75a07f7.npy +03337140-e8307e0cd56ea254c3aee8e9d3a6ffa.npy +04379243-bc36a2facb65a01263f50818822b2585.npy +04379243-54addcbdd400808f54d30af857cfae06.npy +03001627-5f562c9c8f0df90fd2f33aaf794b5932.npy +02808440-5663138e433fa57c79d57ee14f8ee702.npy +02876657-8b7933b0376cea4a1efe98244cb8c300.npy +03636649-1b9b6f1ddf363e0e8b424343280aeccb.npy +02958343-c07bbf672b56b02aafe1d4530f4c6e24.npy +03001627-61b94385426a74323002761e7a3ba3bd.npy +04379243-ce803beb471c728a4f5f1d630285ffb.npy +03211117-2f07cae4c7809f0bcf5a37a70014c623.npy +02808440-75957a7274c39d54b8fda7a3b5ccb8f7.npy +03001627-944a665e765a13ee6d7db84fa3ca3146.npy +02691156-f25ffb9cf92236fb9671f5163e7f6535.npy +02958343-e0901a0a26daebea59139efcde1fedcb.npy +03001627-d56da491d5dabacd4453212030cbb3c9.npy +02808440-97ce198e3d7cdda13991a4f3b0ed6e4.npy +03001627-b4b2e315ec8e17c9a4f70fb45099ec30.npy +03046257-2f484b80a9a0f8a1c1bd423f37647123.npy +04256520-63865747038e4c66c35131da26f8061a.npy +03797390-7223820f07fd6b55e453535335057818.npy +03467517-5c570a10f35716bcaff103adc6dea0b0.npy +03325088-320e3c136e71c412b0957d845ac33749.npy +02818832-30eb0a2f835b91b19e9c6b0794a3b4d8.npy +02828884-7cc80dbf0cb6f4c6b8134b0fbf68257d.npy +04379243-37299b12d2ac7fe13fcaef19d88744fb.npy +02691156-2bc9a8aa5826f7335fc197bbabcd5bd.npy +03001627-184b4797cea77beb5ca1c42bb8ac17a.npy +04090263-7e826b890b683200b63969f9f8d6f075.npy +03001627-e0b432f43a70aa4dc71dfa81bbc5b8ef.npy +02691156-133b74393a3349aa70c4138179d9ed97.npy +02958343-a9a86444fd7402cac69ef68baeaf5d49.npy +03636649-bf3c1ceb076a334acb43a77d9793979d.npy +04256520-5f1a2fef69c5c0ce19fb4103277a6b93.npy +02876657-c107c8cfe88fa057ce53fd26be6d8b08.npy +03636649-c20ca2a29975866cbc7ea0c51211251.npy +04256520-8c6348fe629fb8c876a45e9a12af8158.npy +02958343-6ca9967adcf862a461c6c61410fc904b.npy +02933112-78937816b70f990d8fe14b5c9bc18491.npy +03001627-8a5b706a57166350bc3c6c80ccbccb1e.npy +02691156-17ad3ab1b1d12a7db26dc8ec64d633df.npy +02691156-4de5861211ad5b95e7ef9fff09638f8e.npy +04379243-621ebcbaafeb91a78616812464c86290.npy +04379243-5cebb89b77fcf78084cb825ff0118ad1.npy +02808440-5a4cf079a43f0a793321831d2245cf06.npy +04379243-c43d83c84e8d2614742728b30848ed03.npy +04256520-adefd541f3b51aba5f5e789acd4d1122.npy +02992529-7552cd75673834c9c8470fd239ba13d4.npy +02992529-4dfc1e4efd7fbf083cdba96133f0c38f.npy +04256520-f3abd87858a226aabdbfcb10306a3977.npy +02691156-697161441b9da2a7ca8607f540cc62ba.npy +03467517-8ef7b4bd85885a185a7d605170ee325c.npy +03593526-889b2e6dc1b409cd5e29ce2c9d37b952.npy +04379243-6555b5004c742433e3785a46a5c831bd.npy +03467517-d7a9114b17fbacd376d05024fabfa1e5.npy +03636649-8e0f611116a8df69fc9ae1e9c70f67b1.npy +02958343-d17acdc9dd449748ca92a4cdad802b45.npy +03636649-90d70f0a6b1cf72d79f0be73913de469.npy +04256520-5bf5096583e15c0080741efeb2454ffb.npy +04379243-297778bf1a3f8db5cea003eff0268278.npy +04530566-9798a8b84987bd661851363a5850bdc.npy +03001627-97c5ee9d477c82146c7e21b4ce9a4103.npy +04379243-d6ed3a1e5d5eab8d97fe55e7ac43b9fd.npy +04379243-e1b85df09d33ddea3e43be0b542efff8.npy +03046257-6291b9e4aeed283688b34c259035ab5.npy +04379243-7f6db7a3f529949601104cd2d998272.npy +04379243-29d9c6d84c6a126917b431cae0dd70ed.npy +04090263-2165d568388bfe649a6e43b878d5b335.npy +03001627-bf3f14225e8f899db62f9fb4b7f0626.npy +04256520-6f22991fc456e7a5f63bf7d908efc575.npy +02958343-68f06cde1b907c44e9e6d625d754e501.npy +04256520-d1738a15fe737103917b96045c9b6dea.npy +04379243-d32ccda2f4614dca4b2ec20c30ace65f.npy +03001627-ff02a89047d6eca2f95b04490c0648a1.npy +02691156-4cdd238ccf9002344f59c2a67aa8473b.npy +04379243-dc956d4dc6982188febad4f49b26ec52.npy +03001627-e1897a4391784bc2e8b2b8dc0c816caf.npy +04256520-bf504bde782c3f2ce8ced3508709e1db.npy +02691156-3c52f7f687ce7efe3df325aac2f73830.npy +03211117-cebb35bd663c82d3554a13580615ae1.npy +04379243-5e3ad0f79dc0c429bc8967b0321bd9d2.npy +03636649-beab7a10e86dc5bd70d7da54cdb9b8d0.npy +02876657-ba4b48d76eb79f7cf54e1b6f41fdd78a.npy +03790512-707dfe4769f3e3c5ebe67d9b32c3ddf8.npy +02933112-8390466432e2c364298a4bdd07dbdc0.npy +04379243-2da006ded7b80b61febad4f49b26ec52.npy +02933112-7f50a6bb1827b9f582bfcd34215ccfc7.npy +04379243-a7172fa4177661f4858699aaad4acee4.npy +02958343-bfc1822c1d6a529d531e940de4b7770d.npy +04379243-d10bf548de6c75a966130541a711692.npy +03001627-353bbd3b916426d24502f857a1cf320e.npy +04379243-16e874e6165e836b30bbd4cddd04c77b.npy +04090263-3b8a22fe5666ec993bb35aa9d5fb636b.npy +04090263-56bb7870765f37a05ad0ccf97045200.npy +04379243-2908340693e3dbbd8608f23147a4e121.npy +02691156-861dbd415c83e12e67c647d96462f673.npy +03337140-4cb3532fef99ecaf4c3aee8e9d3a6ffa.npy +02747177-8a50955facbac20ecf19858fd1963d10.npy +02924116-6e303c1727509522c0e9e88e2a6f9b60.npy +02843684-7dd57384aa290a835821cea205f2a4bb.npy +04379243-4116d19d60fc24f037a346dba83c013b.npy +04256520-29ec7e1541397b0e5ae252905262c0ed.npy +03797390-cc5b14ef71e87e9165ba97214ebde03.npy +04379243-5191d64e9a1b9664bfdcc70dcc16baa1.npy +04379243-1a08afbeb4334efeefa472e59de52b43.npy +02828884-90a309f7ac2c947f155d75bbf62b80.npy +02691156-fd7c74a05072d3befef192e05c55dcd3.npy +02933112-16bc9f5821d887f2d7838dc22b16368e.npy +04090263-fe26829c67320001638241f3ad71c10.npy +03691459-4ca26cee4108632859d58b5bb5e2bfcb.npy +03691459-5338db4536b4a889de7da340cde8d034.npy +04225987-36755d38d12e80c0702c58bc53d1e55f.npy +03046257-82c54e1f130534969cfea89fa3f36223.npy +04379243-21cdc417e398378e40f3ac0af6b7e700.npy +02933112-14b5e16ba851e17ac59350d819542ec7.npy +03001627-d792c65f8b1710709b9f2eb77f5e247e.npy +02818832-d7b9238af2efa963c862eec8232fff1e.npy +02924116-721792117cbd8de252470de2774d6099.npy +03211117-5a4add4da7414d11f2a521bdff0d8feb.npy +04256520-54baa6e5d9584469b80b68728684f2ff.npy +02828884-54547a5cbc7cd402c955e5ed03ef3a2f.npy +02958343-e40b027b68ff767d76ad064d1c5fdd7c.npy +02691156-6946f7a2a5ef851215ea536736a1eb7e.npy +04379243-c44792206360e4e4be1b0e1de3e987b3.npy +03001627-1c5d66f3e7352cbf310af74324aae27f.npy +02880940-9a6cec1cfca7e8b5ebc583f22bd58b85.npy +02958343-1b25c745164e53b822d2fb8fec68f2a1.npy +03211117-c0125cb175a11bc4990549fb11675099.npy +03691459-66d9f9f961a12754d1fdf116b1be3b27.npy +03001627-d8774646afed0312732375ced502498.npy +04530566-739a6f209a49040a4f44d84b9baa5f42.npy +02691156-de9e093bb17848c3b2bd4a92202f8700.npy +02933112-6b7123a3631583c612de5317fe5b354f.npy +02992529-e1fb2b5e5a306e6621ecd2b49af349a.npy +03001627-24c0e6a8b10abb77df2b21995cbbbc4f.npy +04379243-6bccd5c9b9c64af7812abbc2a4d00ee8.npy +04256520-b4a72257eff26336d7231c5bdc5ab135.npy +03325088-ef853be8e39805d4589577ccf07b31e7.npy +03325088-b8e9b70818bef88814b35a7d7cea7130.npy +04530566-e64bb04b54022e708d7bd537eb907025.npy +02958343-536477e0842580e0c3c4805a61e06841.npy +03001627-f13d600a3c4515e220ccbe1c34ca182d.npy +02933112-b572114b0944ac203fe047712e43e185.npy +03636649-63e9be096e29681829a42a0444436860.npy +04379243-af5e2282958114c3f12d7184a2ad3430.npy +04379243-4d22674c2acd9cc9f51f77a6d7299806.npy +02691156-ad98f06fa29c52eb23db3adbb2f1dce.npy +04379243-1eefaae6b1ab9615a22802c4e64a501c.npy +04090263-8f38c44779be7fd4340b66282f54c877.npy +03211117-f6a08ec163a037c310b3ff08c68acccf.npy +03325088-8f1e94d2e214b5c076d20e73c57c9a03.npy +04090263-27a144ab9c20b710ae9e1c81f7e5b0b6.npy +04256520-f96f7bc4d005a88db38d1ee17ad4a4a1.npy +04554684-53e2b5c6f9a2103e3fb0920a55a7e805.npy +02691156-131db4a650873babad3ab188d086d4db.npy +02958343-9fda50a84e042ff1a7e7e5ea49ad8e45.npy +04379243-4e3191c1f133fca0586c8517ad05e6f3.npy +04256520-5e118f0edd514706593ebeeedbff73b.npy +03211117-c98e0e745a92abccaa60d250862f15f.npy +04379243-28710bbf732bd651c955e5ed03ef3a2f.npy +03001627-748957972cae6b03c56be62b05937331.npy +02880940-6a772d12b98ab61dc26651d9d35b77ca.npy +04090263-bbcaf90d1025714f98ee95803c8422bf.npy +03001627-11e28120789c20abc8687ff9b0b4e4ac.npy +03001627-e159d82f67a5953b1fb41007d56c0ca1.npy +02691156-85738a291d67c649f019a51d1a3b2e07.npy +03691459-8c7c72599c6bbafc8323fc17a8352c3d.npy +02828884-6fe6b24009d0ac4f19b647a92023d001.npy +02924116-60b79c17ea581aa99c7bbb03ea46a56e.npy +03211117-ebd183cd1d075dd3bed06f4e613c0aec.npy +02828884-5c1dea3aaa34fee26c289bdcae73ee89.npy +02992529-fe9d97823a25e56d95e43220ee0eb824.npy +04256520-899f5c18a528aac2ef0b2fc3511b6fbd.npy +02958343-4e488242b665d85f40bc3b36a331b786.npy +03001627-2c8f57bf281dd31119fb4103277a6b93.npy +02933112-87708c9ebd845c21854c6e2381cc9350.npy +04090263-b1cf5989ae77d71180ac63732535bbcc.npy +02828884-2aaf5fe631a855b4de9ff1d2442cc6d1.npy +04090263-c474fa4cf4a4c282f5cbed688a0bb106.npy +02691156-35c9e363ca3fa6f8e4fc4c6009ee9462.npy +03001627-8e6dcb9b3eadaf9ead885ade4bf3150c.npy +03691459-6152f977e3cf8ccae47833b310955a9f.npy +04379243-9109c50681f033d83b233a16f6b369c3.npy +04330267-5b0c38cda43ebcb35a7e054e0372a0f.npy +03001627-a3c4bd89e7570dcc6204511a506beabf.npy +02992529-2274e1f494d6d2c3226bc3b9ce9ff2a1.npy +03691459-27867443c228581e515eb678a856048.npy +04379243-656b7353e4580f8fa93e942a054d60b5.npy +03691459-bc09422920aec02cb8901bb57b05fb9b.npy +02818832-2c8b8a58ecffdaa17b9c6deef486a7d8.npy +03001627-68747a56aba6ee318677364bd64735c4.npy +04256520-4735568bd188aefcb8e1b99345a5afd4.npy +02958343-6bb14c1083ed44f5ac34b841f2070767.npy +02747177-1cb574d3f22f63ebd493bfe20f94b6ab.npy +03001627-c13d5f3639f427587fa29a3ea424473.npy +02933112-c89a5482bb756c041d86c17c15247b0.npy +04379243-5b685a0318bcf5ff4ced24553b268ec.npy +04530566-c83910ef0a35953756e0cfd6e5118fc9.npy +03001627-fa8f7c225d3b9f1def4a09e7eb872bd9.npy +04379243-610ccbf900e1bf4aeb34db531a289b8e.npy +04090263-ceba1f5b53f3c3f0a4c018b03e3993f7.npy +03636649-b000d66b8f78ab20cfdfe3f21f42a111.npy +02958343-7b74eb8f053aabe64eb766e5a46fceab.npy +03467517-e530bbce9716bf95bc4ac3caf16ef65.npy +03001627-d5360f2b0b0299c29b9f2eb77f5e247e.npy +04256520-5ff07557bb0a3a30dbbc9440457e303e.npy +04379243-91a56c9037ba4a63a393ceda265543cf.npy +02992529-b1537f1eabb7f5009f7477e2986c440f.npy +02691156-dfa310706fad49d873ec74c119307b9.npy +03636649-a258951f55855e41c02170c33e00ea64.npy +04530566-4719acf1c3e56fb489d39b85991ba25a.npy +03001627-3b1b0186ebeb8ea579bb09dc5605a57.npy +03001627-bdc58ca6d411823cae786e8787e8886a.npy +04530566-4c8c605b2b452cbba66c1707a338712c.npy +04379243-607f9e630d94edff9292bdf65b24b621.npy +04379243-a4dbf0f4fef1c36cf199233c9f2ce2ce.npy +02691156-3cdf7ea70c5a8471f446f92b52bbd82a.npy +04256520-21236ac9a464b22a91fa1c643766450d.npy +04256520-bc65c38188f1e72c532e8683617554c4.npy +02691156-5f0e7de6a86a694d3930849f1d75b1.npy +03001627-1b67a3a1101a9acb905477d2a8504646.npy +03001627-a203bbe3c9c1c676c3bd24f986301745.npy +04256520-6f0477514eb4f9319b0530265e62c9b7.npy +02992529-cf3f330fb6e3e034449ec657800ab951.npy +03001627-400ae609e39ff49639d5fb08047c894e.npy +03624134-8f499dae474bf37589757884a4547730.npy +03991062-84fb2bea1b0b6701dd3adf3090c701f7.npy +03624134-e0a78d771cfde145a5cea7e40e4d21ff.npy +04379243-4b47e8b6ac084de116a2b5862518c93.npy +04256520-592fdb44d4bbf0ee490ad276cd2af3a4.npy +04379243-fb1e39667d83506a41dea5e6084523ee.npy +03691459-b0d4ab08b9498de4f42138205659017c.npy +03211117-7636d7c650108b884dcb5392aaf2167b.npy +02828884-7a3590d0abb36b49593ebeeedbff73b.npy +03636649-6bd7a0abc6f77368b0cf606cb698fa08.npy +04256520-a03ca96c53c69c05f8a51dbffe0021e4.npy +02691156-c846ad445cc9acbb98427765723d5e48.npy +03642806-cb090bd99ed76f9689661310be87a70d.npy +03001627-bdbf18aefa5b980585b479b317175b55.npy +04379243-a29ee68d1279e8ff98d5fc0473d00a1c.npy +04530566-ffacadade68cec7b926a1ee5a429907.npy +02924116-73fa2052813f9e78730865f7b652666e.npy +03636649-c1532683707c38b51cce8c25b11ccdd9.npy +04530566-390de3a1bd0191c881d9d9b1473043a2.npy +03624134-cc38f97557029b2a2b5fd8277662be97.npy +02933112-dbcf0d09a1cef0aecfaf287992b2065b.npy +02691156-d7287ce98d521db5ca8607f540cc62ba.npy +03211117-149733a616f846a2b661587eebd6c4d7.npy +03624134-3a0f48139bfd3a4ea152d2e823b9fe06.npy +04256520-218f5acd2b8f2d7c85f6609ec867506c.npy +03001627-64ed01e4a892fa8e498bd5a555c21b1c.npy +02992529-16c6403551e81a3eeedfca8b846d3b01.npy +02992529-4475473d3a96860621844676433a0aca.npy +04090263-6cd490d9cce62e94d2c901959c439025.npy +03001627-5ef54fa5d00dbdf8c8687ff9b0b4e4ac.npy +04401088-e862392921d99119ee50cfd2d11d046b.npy +03642806-dd282ed5d4956590b713df0d260c2628.npy +04256520-494fe53da65650b8c358765b76c296.npy +02958343-2a0dad4f32251b353ffe0e5069bf1eb5.npy +03636649-9e0b193df5bf4f2097497273a66fca55.npy +03642806-247012532a6342f424afdcb79b0329d8.npy +02691156-cbb5ed444249f0a9e90916c8815b5c43.npy +03624134-c20cca071ea58e3ef2c542131520d62e.npy +04379243-6550c93bce51b9b4719088c8e42c6ab.npy +02691156-2b2cf12a1fde287077c5f5c64222d77e.npy +03001627-a9e2b04bb60240d0febad4f49b26ec52.npy +04099429-e98fdff7cfdf15edd8e5da8daec55d43.npy +02958343-c234638891f21417ec5e3fe5c33367cf.npy +03636649-92bdae8c11323fc518df0876cc6aa6ac.npy +03001627-241d81f586925ea0fbdebca9f6788597.npy +04379243-5ed584534db04e128ddc9f1b5f92baac.npy +03211117-946ec8b571ca42d378838533e331d3cf.npy +02691156-76a86e664e302f32fca1f1143bb6bc17.npy +03691459-2003690fcc8390a24c40f34de8f3bdb8.npy +03636649-421734c234a9ecce5c166769fb8a1974.npy +03001627-359331da71ed26eca6c03a53cf0a14c9.npy +04379243-fead7e0c30a347b1710801cae5dc529.npy +04090263-f0acf574b96f9fc3829eee2486bd54c3.npy +03001627-67b082d174af9ab06acc27496f96b513.npy +03001627-5c660775f1c7b202855c835f93769fb8.npy +03991062-aeec00d8dd6e196451a2ad3de1977657.npy +03001627-55740c07554a726257f40ff86fe708ff.npy +02924116-d8bbe91e70fb6dc0aa2a2973c341188f.npy +04090263-c37c062ab5ecca2ef3998727b15249db.npy +03636649-b9d353635f7e1134e95ee7559a2a873b.npy +02808440-69f95bd359cd47d0448cbcbac44a38bf.npy +03046257-1944938643bdb1dd56538cee362f80d0.npy +02924116-505d081493bd01a09600ffd1ed0f3806.npy +03001627-8f6634a231e3f3ccdfe9cab879fd37e8.npy +02843684-c815baf0ba9306cca9af96dabf6167b0.npy +04379243-f260449e91824f96d810b14a81e12eca.npy +02808440-ea012fc2a70eb38c14b1a3362bf89056.npy +02691156-5a38f5eb63dd8b20ab9d1113aabc16f5.npy +02958343-6c50a9b8e01fbca27dfb1ee6a4b12bf8.npy +03691459-fa2cf860e277919a7445d25f394949d0.npy +04379243-d06d27bc9ad1faabd7bf6fb68df7f786.npy +04379243-1f9923d1e65004d836e4b0ae0f52067b.npy +04256520-ecdefc9c1104da52bca88fbd368f59a.npy +04256520-dd8de6dddffe302f84633b41c8a09fa0.npy +04379243-bfd32cdb923c8430e260ed121aebe3d6.npy +02808440-4399b850494bcfcd2dee675288ffec8e.npy +02691156-ade3c4987f49895ff960bc420d751255.npy +03948459-b62475e6bfcc88a226735d0798dfa389.npy +03001627-6434921f88bd48deb0957d845ac33749.npy +03001627-421b11a26931160a492d9da2668ec34c.npy +03325088-8ea7517f0c9c8a5ce27c891af4570491.npy +03001627-f1787517791764e74b3c42e318f3affc.npy +04379243-9c57462582737eb7d46cc1240811b39d.npy +03624134-b678ebb41660034c32e713e886ed6efc.npy +02691156-c3a03137955f65c5cf67c0b63878e138.npy +04379243-33d620c4e8af291d5dcc7ddfa72357b1.npy +04256520-51194e8dad49dedeb38821f893bc10f9.npy +02808440-bbe02a8cb3ea4b4844221bef0fa3c36b.npy +04379243-8a47668d3584eef1e4317813b39d4fe.npy +03001627-b60546b326e585e03ac416718757a350.npy +04379243-38e83df89967420b876b399a99a15c0f.npy +04554684-bdfbadd16a5ddceb8e55c35c514cb2f7.npy +04090263-d761053ffff137701d9b004d9d8d2781.npy +04256520-3eb1a7a9a4ea97e3e44bad6fc9badfe7.npy +02958343-ee1d28a50a2b71e129348d14ca881f7d.npy +03001627-53675c4bbb33fe72bcc0c5df96f9b28e.npy +04379243-e8ce7c3e66e6aec08ee0a9ed0efc243f.npy +03948459-15a33eba4028d9e9359df9cdf4b82128.npy +03001627-7efeece3b5cf2853d706779c93538ee1.npy +02808440-6be7c8fafd1268776b448b8aaebb705c.npy +03001627-52afab7f974e7bdbac1ffe34fecf39b2.npy +04530566-8605c975778dc8634c634743f56177d4.npy +04379243-93d61cd5da999d774b3c42e318f3affc.npy +02691156-1e4fb40e5908f2bddf2f34e1100f0241.npy +03001627-20ec9403d616f96ee6cfc789522bfbab.npy +04379243-77e044ca2ebca1f4d148fd8215fc3114.npy +04090263-c77af288e7c373979905a3939c890ad2.npy +04090263-fb96b1414205d7b525c70fb1df3f879b.npy +03001627-d66cc87c717c15f57f0839ffd260627e.npy +04379243-5d77e8f6ad3741a0c30ab36bf7b0552.npy +02933112-8697ab2a0da98ba65588a2543ef0b0b4.npy +02958343-aa7f127bb8cd9db73755eb267a6f3b6b.npy +03001627-91645c82e357ec502744bf8869518694.npy +02992529-b1feb3020d9380ba4fb324159a14f34e.npy +02828884-ff71a0d33a3aa440565888a91a05d618.npy +04401088-ed5ac4e8c681102e848d333362aaa342.npy +02808440-6716bbccb88071daed20bf7873c38793.npy +02691156-62bc52c204b738317dcda43eefa0ac02.npy +03001627-329ec98f10af7214ac6962daa1b6ab91.npy +02954340-e8a97a1fd97c1a75a52821bf1aa3b19a.npy +04379243-10b6147009cbc17ec25cfdac7cd67ea3.npy +03211117-444fe598a0ff9d7ebe24753b6321b5ca.npy +04530566-5e8276dfb4c1db936f31e247620349e3.npy +03948459-5e895f53b72ad0ba49590df9bee4071.npy +04530566-762afb11bf41fc61642f9e27aaf0c47a.npy +02958343-9807c1d0bcec85fcc3c0146ad3ea2d7d.npy +04379243-b0d7c6d51712d1fbe76bc197b3a3ffc0.npy +02992529-976a8d10e8423f8d8f15e8aad14ff29e.npy +02992529-57ff44f979370766976fab5d6e2569c1.npy +03593526-96106df7b7d1ca5dfaeb9da29098949.npy +02691156-ca91becbfaf5a094bba1aa1c98256342.npy +03001627-4e9475fea6f3ca32c4cb3d6800567627.npy +03001627-c9d5ff677600b0a1a01ae992b62200ab.npy +03691459-a99cc4f1326b9b48b08cd968d6703683.npy +04379243-57f64087490954d2c015b1a51bdead97.npy +02958343-70d46fce66801e0f16abce8cb03e7794.npy +03636649-ae5ecfa01e88e47f41bb00bd5475793.npy +02924116-856afb0a9a494aa6402dc8d46be324b6.npy +03001627-99fbc3ebabd3b83e54beec3b24722e27.npy +04379243-62bba707a00a2fd0c271edf49b97f472.npy +03001627-a216d6a04494ef6a32485dc6e0b2347.npy +04256520-2ae32451bd6b947e593ebeeedbff73b.npy +03001627-3aa41731c9bde97796d5112fb101f3ce.npy +03636649-9b9b39303c66baba490ad276cd2af3a4.npy +02958343-b25bd03ac3b1ce39d5238b9ecc7822b0.npy +02992529-2703b7edaf11d79a6b203c09a4932f5.npy +02691156-76f142e62adc0f2ae768735f27170bc4.npy +04379243-2c14b0b718a1f3765828f54ccfceb8a8.npy +03636649-366a93bce1f6f524eaf14273fa406ffc.npy +02880940-8d1f575e9223b28b8183a4a81361b94.npy +02828884-3a7b2f1220e7c13092ccafdeb0ce5a8a.npy +03636649-e38e89e852fe924d957f81d76123f1a7.npy +04379243-ec3f93916a91e386c29f1e5c35eaaf93.npy +02871439-9e23b733b160313ed260ba674fb1fc01.npy +02691156-9618b78610150b53825b20c2472ad90a.npy +03790512-2d655fc4ecb2df2a747c19778aa6cc0.npy +04379243-cd895c35fff495cdd0b93fa304cfa755.npy +02828884-24f090d8ee565dd1601104cd2d998272.npy +02992529-1edc7aa574624ca0200a0406803801e9.npy +04090263-1d50f114691be38fa9286f039319ff7.npy +03001627-d1bef1cf465da3acdca30639ad4a20ca.npy +02958343-e4d1edc4cda4a6445fb81d6394b59c19.npy +03636649-13d5888a6598745f82bfcd34215ccfc7.npy +04379243-40e4f56f34f98a779ebe79011e3a0eae.npy +04379243-f3fd419f725aa894ba5342d638d0c267.npy +04379243-42afa0dc60b32a6d7dcf230d8b7d162e.npy +04090263-9642b6d77734a1c351cfdb4c9f126c12.npy +03001627-5509f56ce625c42aff2b8acf844d34d2.npy +03001627-225ef5d1a73d0e24febad4f49b26ec52.npy +03001627-5840d369b3e0e40f7c4ed45ce654123.npy +02958343-c8b196595745bbd241c181f4a7e1bfa5.npy +02958343-5cf1f82c6fd31a73e0445fc6d980dd5c.npy +04379243-30573f43ecfd93f0684b7bc3f8a9aa55.npy +04256520-1914d0e6b9f0445b40e80a2d9f005aa7.npy +03001627-6ade3daff4827379492d9da2668ec34c.npy +04530566-c4c9a32c9b1c3e515586434189043e91.npy +04090263-ce50f2f8034fafe86b2c8bb96250e4a0.npy +04090263-9ee24e8914555d18d0a6af9bfb470a20.npy +03001627-97d75ad96c2c08268cbb8bac2032149c.npy +03001627-d607e86b83f628faeaf288f952624966.npy +04401088-c410d13694b8ca1d15e144fc878b7afa.npy +04530566-7b568afff918289614621506c22882a0.npy +04379243-b0b0df035ab58b92822a33e080d0e71c.npy +03642806-25f391ae823c118963439329667c7723.npy +03691459-d6ad58677b397894224f9d60ad32613.npy +02871439-2d628b78cef91948636882dec160c4d5.npy +02958343-a0a1b0377d72e86bab3dd76bf33b0f5e.npy +02808440-d5c8f32fdf76cd316b448b8aaebb705c.npy +04379243-735acef5841a826b6ae95494c18318.npy +03001627-7aaf5573892cfe086e6e0f71258e961c.npy +04379243-53afd3dc40b699cf124123a40f9164a5.npy +02958343-caa7b1a7dabd0fd3be0e4b4a1a900aa0.npy +02691156-973211dfe6bcc4ae90b1d6deb98feec6.npy +02691156-87edb38cd76e89f5996d31205aa7f7a.npy +04379243-9c32d9398c04a66bddaf28b23330377.npy +02691156-4b10780b9e0f93f1d32761b337f8b72a.npy +02691156-365747560fafc7e847b5c8181a9fe9a3.npy +03797390-46ed9dad0440c043d33646b0990bb4a.npy +04090263-7e5c0d35215be21ff3998727b15249db.npy +02992529-c688e0c0830ddebed23d7150656e0d04.npy +03001627-f5be22e0a737ca9f2c0658ad22a9a9b.npy +04256520-63eeb7ea2c7683b3f811db9eaa01354f.npy +02828884-c52f48c97868b7dfea8a406c7edcf3b4.npy +03001627-30ba0d3e750dd7e0876b399a99a15c0f.npy +04379243-2c08b5408a7ee4da98cfd47a860803c5.npy +03001627-1f3591151aef17ab997a9cd87230da.npy +04256520-10552f968486cd0ad138a53ab0d038a5.npy +03790512-80e717f07645a4a0b37378f3c85478b4.npy +04530566-973d0293e286c80bf3e39f2e17005efc.npy +02876657-5979870763de5ced4c8b72e8da0e65c5.npy +04379243-638c86ffc1c9e00c5749f7a8e1644575.npy +03211117-ab2f9418c111cc6ddb965514105122a4.npy +03467517-9eee9fb35c1f62d34c9360dbc3be7004.npy +03467517-113b65f0e68314737c481698bd5233b4.npy +03001627-80fab0c55a60abb7dafb0be26f6b45d5.npy +03001627-2f1a67cdabe2a70c492d9da2668ec34c.npy +03761084-891f65c773939191c834958aed613724.npy +03938244-4691e0947b1e2a6b685998681d42efb8.npy +04330267-2b9af8c16f4b64595e5e29d9f2069262.npy +03001627-610ea34f683eaad58cbb8bac2032149c.npy +04090263-2d1fee5d2dfc73cd231b1db6fc883f4b.npy +02958343-41c5c3955dc6525a402257734064a917.npy +03325088-bf4f75844044654076d20e73c57c9a03.npy +03001627-a521fba02ca7f9aa822215026d1e8d82.npy +02818832-5f49c821b5223ab59c00f10333f1c0b5.npy +02691156-f5e271c3cb2edc1681209be1a5e8b10d.npy +04530566-59d2e9b3b4de8695a0c75f497eade21.npy +04379243-1b73a0ff61df00c5a1cccbba517add5e.npy +02691156-e2ddbf9e63bbf9cc4e99bd46be8e610a.npy +03691459-3110c18edcedfb6331f3d76ec3df45bb.npy +04090263-7aff2693a24b4faed957eaf7f4edb205.npy +04530566-3658be4cae1c98b84a51f4b900f5eb50.npy +02691156-c6ab8acad9e61a3e48227c7754aae2a1.npy +03211117-ab8cd6dd65cb0ca9770f31b5d5715b63.npy +03001627-34898c36e711fbde713decb1a0563b12.npy +03046257-4f0f676001ebb1de561dce3fe08634b7.npy +02828884-c2365f1009f94814ece2872dbe44bfca.npy +02992529-1292caa1282ad8cffc3c4ad908ac06f4.npy +04379243-41e443beb22248b46ba14bfd91a75020.npy +04379243-ec4675f62f6946118cbb8bac2032149c.npy +02876657-98f2bdf417a15ceaa5d6dc096343ac63.npy +04256520-5c0d256f2bf7559bfc8914dd77284b3.npy +02876657-656ef8a799ee1c5118431871c8e05789.npy +04379243-dd3de76ab27a6aee8141276dba5d99db.npy +04379243-6746eb452d8b84323087f84b199fd297.npy +02691156-3d6a8f8c27e465aac6747f7c9ffe9e32.npy +02691156-1cb757280b862ae52c7575c9089791ff.npy +04090263-43fc3a905d6024290dc2ed23ceb8a8.npy +02691156-76252e1b65ede02f889919e9428eee54.npy +03991062-4254d2adf7f909eb2cb3e065bdf11951.npy +03636649-36182fffe5b450fd65d1b2bc83ce78db.npy +04090263-7787dec9a3d40aa9c6b36efc015b1017.npy +03691459-2a6f78d39d66f6171bd445ab4c056b71.npy +04379243-e5ea9b41ff06d7ce2c396131c7cc7ef8.npy +02828884-11665c5093e85592b340344cde6e80c4.npy +04090263-332cc5d5d3484f8920517b73a75a21ed.npy +04090263-6c51211b773c51cf683e3750b53385d5.npy +04379243-e6a188bbf8315d11f1783a44a88d6274.npy +02924116-c88a4393e101d4e8b855cdc1bde1c5c9.npy +03642806-546b40d15cd483873339d8259ddfa7bb.npy +04256520-349f3f4d65f64c1235836c728d324152.npy +03001627-dd414923feefc1bd160139aa3ea05a51.npy +02691156-4a552066ae1da546cc34b900bb2492e.npy +04256520-e8e8f3249b237cb3450fa717654492da.npy +03928116-8b987a81642f3cbf195d81040cc60.npy +03636649-e303a8b8aa3aa14a39b3360f500ac52a.npy +02958343-95844f86f4f0a6b58a6cf8c6b92417f2.npy +04379243-71e814e5c0f59c1ec45dce3c044e7ab3.npy +03593526-a060ca371b0f70d736b0f2a1430e993a.npy +04468005-6a930aee7d68abd88e966271baaa42c9.npy +03001627-a2fdf98f85cec8696ca407465d3c74d7.npy +02933112-5a6715ef95a99bf59856fa70a578baeb.npy +03001627-3e5a18ae1c8d5fe068d1b9a1d97e2846.npy +03636649-1f30b28f2dfe65a21735ea0e092a805a.npy +02958343-2490227846d06e5a2387c64d55d0b4e5.npy +02871439-d1ce207dbd39b5695668a412457992c5.npy +03001627-1aa07508b731af79814e2be0234da26c.npy +03593526-c331b4c98868bfb529a42a0444436860.npy +04401088-424d356bbbdb38daab0fba1d15eaeacf.npy +02958343-2181653ec5313196d2c8600344d8bfab.npy +02958343-44c7a7a13fdc673abda72093f9b5aa73.npy +02946921-6f2c06bb129e52be63ed57e35c972b4b.npy +04256520-7ac7a4f53a89ecb48f966131432ef871.npy +02933112-9b28e4f5c66daae45f29768b6bb620cb.npy +04090263-a15d5a9816ba40bb76d500a9282a3dab.npy +02828884-d6924af4f2849c8219fb4103277a6b93.npy +04090263-8d9471defc6f3a8fe71e857afa9df271.npy +04379243-b23bf5b53e1e61768984d623cdd9496c.npy +03991062-51b09b5732e8f6baa2c59a4d90e63212.npy +04379243-c3023187d59aeb87a731e84e842dd6b1.npy +02958343-78555893ae97d1fea37127a27e431e39.npy +02828884-2c75963e304f490223ed665630afd1ce.npy +02958343-1dc58be25e1b6e5675cad724c63e222e.npy +03636649-cec37bc68adf2a20e6d206b2ed87676.npy +03325088-b1a88b5b7861649e7a31dd5af93fdb5c.npy +03624134-fe975241a968467ac3669fe98cc0dfc0.npy +02924116-739725054f3dcee41ef2486fe36a1e66.npy +03636649-9d1e04bd3df11256bef045a510a22fbb.npy +04379243-17ba1ba8f935f2bbdb01c957364e77d0.npy +02958343-664b8ab637c1fb54a78cb4f1b66f009e.npy +04379243-1ee2b2bc538245a85de04aad18bd94c3.npy +03636649-b1dc9ca886ac0cabb924fe739b83941e.npy +03797390-f1866a48c2fc17f85b2ecd212557fda0.npy +04401088-474b04796bf1ec91962bfd5bcfc9bf86.npy +04401088-17d4ef9fa59ede481cfeae953cc2339d.npy +03636649-23040992da19679aaa7cb30470f3273c.npy +04379243-bd516ff50ec6fcd498d5fc0473d00a1c.npy +03636649-eb1c735af1339e294b3c42e318f3affc.npy +04379243-472fe5ae8d386452bcd6195ec0f1e297.npy +03636649-b64e98c991d4103170365ad078f710ff.npy +02958343-5be79b1758410803be40bb45ea25a041.npy +04379243-67057f4425cf8fa5f46b0a91833c80a4.npy +02691156-dab7d624889233a863dc0bc8d259b20e.npy +04530566-61c17240229bf84581d9d9b1473043a2.npy +02808440-c843cc9df022e96ce6c3e73b818a2cc.npy +04379243-4e6db34a8ddef9abb9569033586af233.npy +02828884-1042d723dfc31ce5ec56aed2da084563.npy +02828884-4647754b7c5b31cccb2a965e75be701c.npy +03325088-c4c8a8f2ce62f6f4c36fb70296e45483.npy +04530566-3a68e8dc897fba988332d0d58794c3c4.npy +02691156-9818f0b88fed05b24b0a1bcf2fb497ec.npy +04379243-d77287719eb7bf0d66ef9dd2f3ef27d3.npy +04225987-ee1e75f67edf37707f29c61065b4dc5a.npy +02924116-a98700191f42cd976bed41d0253513f3.npy +03001627-f0f9d29b3eb76fb7490ad276cd2af3a4.npy +02828884-7b7e73cbc821d520f155d75bbf62b80.npy +02871439-d8a53f2b980eafae777668bd5471e4f9.npy +04090263-bfbe959eb045a3826e181e3da8402358.npy +04256520-38f6d097455e58053d6e282938a47f9e.npy +04090263-f04dfecd1ae139a23e7a62ab2a088af3.npy +03624134-889f73fac7e89bf932315e7b779fa298.npy +02691156-3caf95d83fcccdcc28662498a294724.npy +03211117-df2f0bef5a669d6262c440075d5ed193.npy +04256520-63e45aeea568f1b0c35131da26f8061a.npy +02933112-783ba337e5bf328abe81a9109a782712.npy +02924116-c9c6445740eaaa74a495c196d4f0cebb.npy +02958343-511962626501e4abf500cc506a763c18.npy +04004475-3a4e546431684c822f84cb7932f866fd.npy +03211117-e5b50925213ade6a340d4ac30c6d322a.npy +04090263-407324b2f2b89934b5945297ce426f02.npy +03642806-e1773be8392c5fc4f7d4d3ced798ad90.npy +02958343-ebc59fa7d366b486122181f48ecf7852.npy +03001627-fee36ec8c8ae503fc68456e8da5b9a30.npy +03624134-6d5466e70653d80aee22e58d18efdd28.npy +03948459-2f5b4bcb8d4dd901609e2d916fa0da27.npy +03001627-128517f2992b6fb92057e1ae1c4cc928.npy +02691156-902cc09a60a494a278d0cdddb0c08062.npy +04379243-250cd21169a42a2bfaf26c91ad27299b.npy +04379243-fcad199862c19cd97fb247f6727f93f3.npy +03691459-893bca10c44ffd673e1b2d018c0512.npy +04379243-7436f91df61e7d5bc10555abb2efb430.npy +04379243-d1457e572ef95ddbd2096b2fa6f98cc7.npy +04090263-ccf770542367f03f276c3d558130f8b4.npy +03948459-baaa7b7c8a39bfa5bf8434cfd671215a.npy +02691156-f0d6c53d21ae5b5cd0c57f18e8d8830d.npy +02828884-3e81e31d8cd99cdffae0a22d98098878.npy +03636649-5f865b98b4be6abf35836c728d324152.npy +03790512-c9e2437df080309baab0751e11299b9f.npy +04090263-79461905bb97ebc21a77229b9f90bf5.npy +02958343-d6089d1b75c35945b7e8c57d131d2ca7.npy +03710193-26ac0ea516715a5044b2fa2cac0778f5.npy +02933112-2f0a56c30e384642c59350d819542ec7.npy +04379243-3bcd7dc964487b1ae6c5cd45aa112726.npy +04379243-f622d7d6892fe02937251258858a7a58.npy +02691156-e6908f525ab8e6823a562128d0cdc8f1.npy +04090263-14a3a4e859a9462bb335d40260934189.npy +03691459-cfc38353ff8392e73a7dda43d8d95517.npy +02691156-940c9ed5d7610d915d3bbd70fc7759b7.npy +03001627-c98207781087c7c2995e7ab497adca70.npy +03761084-698b37ec06448da7160ce9e819e30139.npy +02958343-b3aea199d8f8945d3c8089ca2f2a9299.npy +03001627-2ae1dc95e09b858128fda76c378c923.npy +04530566-e8d1da5077f0fd3754f4583ac182c2.npy +04530566-2ab688c7eaa21bbd77e7acf84a1c4b6.npy +02924116-79e32e66bbf04191afe1d4530f4c6e24.npy +04256520-dcb434ec43228c7e98621bfaa41dc79c.npy +04401088-3aa3d13575540a99167196b0ec8ce495.npy +03001627-4cc4cb9b533e8b84b04cb542e2c50eb4.npy +02828884-3ca55ce22b40b8c2ad364a967d96b388.npy +02871439-2d68b12e799ec982df18258a84843c90.npy +04090263-e9cd2397c0a7ea86341aafe10fd0cbd4.npy +03636649-f4db9c55f72edb36ad0d9196eb691e00.npy +03991062-bd6ba738a4e40e23cb2a965e75be701c.npy +04401088-ae7098f0bc20cc6b2a87aa332da7bee6.npy +02691156-5efa09bee2cf193afaad157818f6ee1e.npy +02958343-a26d63de878b28fd52980f173b56924f.npy +04256520-bfd09a13ca8d039d24d3570ac22df4c2.npy +02954340-1fc6f3aebca014ab19ba010ddb4974fe.npy +02933112-5a3428f5690f57a7cf004563556ddb36.npy +02958343-77d9a23f45c888e595551e0d9e50cb0d.npy +04379243-737cc2beda4a023619fb4103277a6b93.npy +03325088-2e31697d451f89843321831d2245cf06.npy +02958343-78c5d8e9acc120ce16abce8cb03e7794.npy +02933112-e2d06603fba3bf3310af74324aae27f.npy +04401088-e0b1cb72aba261731fa8e666182e8619.npy +03001627-5e259c1b8640f5b7dfe5fb64510022bb.npy +04468005-1aa05c2e358d09b52470de2774d6099.npy +04379243-6f39877ac66ff1b55936c7265c890fef.npy +03642806-e34a4bd815f38858fb15d1c4afffaed3.npy +02828884-107c0b6b32282102493c8fb81dc7c4da.npy +03001627-ed953e5d1ce7a4bee7697d561711bd2b.npy +03001627-6dfb7b5b4bd0d5f9febad4f49b26ec52.npy +02871439-c9bccf9e749da5d6742728b30848ed03.npy +02808440-8604c03fb772a81eb362845c6edb57fc.npy +02828884-bee41df71228b870593ebeeedbff73b.npy +04256520-94988ca3a0f73d16cabc196a7f35f1aa.npy +03636649-ef45c648fe3b0dde8449e0b8dd14796b.npy +03001627-fecb6b1159091d36d0176f9a144100cd.npy +02924116-e17c497806951fadcb4d826afd1c8fdf.npy +02958343-3ac664a7486a0bdff200a72c9245aee7.npy +03467517-e7b57f47d2ff2093f0194265a9746c.npy +02691156-8615e879f5d72ed5860c8fc9227db68d.npy +02992529-a13cea3066cd5b1746ab0c6c4666145a.npy +04099429-3a571503ba7f70c73df4fa4547276fc2.npy +03001627-65da0b239837b0f3f3ee5e8ea028d6.npy +02924116-b445a7e6f824f2db6a6393c63592ba88.npy +03797390-67b9abb424cf22a22d7082a28b056a5.npy +03211117-cc499148f0e031054b8def6cb3b321af.npy +04379243-9649ef758d3334c74500047017815f5f.npy +03624134-5e14870221caf3bb1395331ebe4786cd.npy +04379243-dd24fcb1ceb67ded3d937a346d1565b.npy +04468005-78430d9dac1f443a43483de0903bef89.npy +04379243-4768cfe825063ef930c15a57aa97b3c6.npy +02691156-ddb96cc263869979f446f92b52bbd82a.npy +04256520-9f12f8119a52b141effcc073d8ec38f6.npy +03991062-37853a4a1a918e9ea4de89c8b25b5088.npy +02691156-dcb5bded8772135b4295343ee7255799.npy +02958343-9031339141bad8608f89f9805dc3c90e.npy +03211117-3529cd0cb733596bc22a9d71e5721aa6.npy +04090263-b10748ed5e3e01f99464f279e4e22634.npy +04379243-16961ddf69b6e91ea8ff4f6e9563bff6.npy +03001627-2475ead1cfa0a5a6490ad276cd2af3a4.npy +02958343-6103654b252c5d3bb1bb46d2556ba67d.npy +02691156-a4c41dc85210c3a0ae049cb809622fee.npy +04379243-c074e43821469150d6084fb53091249.npy +03001627-609d3b4977310957909e1fac9945adaa.npy +04379243-da234c874b8beef22e1a5fb6897c8678.npy +04090263-51ab5dcd79ccf3b5ffd7722cc96c6452.npy +04256520-e5da166f78544aabd37035c74acfab37.npy +02992529-fddadcb723b843eaafb07a946d621b3c.npy +03001627-85b73c87c4c73263a7c64d6a7060b75b.npy +02924116-c01459435b19e42b52470de2774d6099.npy +04379243-58cbc849279b38e0c16f7010a3b8fdee.npy +03593526-bd96246be9854deedfd64b437f0ace42.npy +03001627-3ae022522800685c610195e4fb10d1de.npy +03211117-34f6cff3e8fb6315fc2aaecaba21de51.npy +02691156-fac9c4f0d5f239e4f2b0736dd4d8afe0.npy +03790512-828210e9d0a307c0a9a5251e8f29bd8c.npy +04379243-f5a42533b878229d942b01e78b9a302d.npy +02691156-ace4fe6e9c97150a35fc197bbabcd5bd.npy +04530566-9746bffb188fa8d776dfbd72ad52dca6.npy +03691459-a24796b40f26be4a19f048d3a7935eeb.npy +03790512-48233d99d0bd59e5d8a587623571014e.npy +03642806-e4c34c87ed1bc2191ef7a71d6e01357e.npy +02958343-83e5b5a3f3aad942ed29cc2a32e4bbed.npy +02958343-c2467fec08734fc81e1473be174fcabe.npy +04256520-f7b17391a903c29ef84b0be7f50940eb.npy +03001627-a3c1460f50bd470dd064b65ccd89778c.npy +04530566-cd67f7d1ba943b162f84cb7932f866fd.npy +04256520-4dbe50ba1f562fb236413faee81117b1.npy +03797390-5ef0c4f8c0884a24762241154bf230ce.npy +02828884-ef1149155829a5175c7dbebb6c018341.npy +03636649-6efc48bb9267c2ab4c6deb9ede0648df.npy +02933112-cc198051642f31029a88326b888756d7.npy +02992529-5a28460645d4a28c7fa29a3ea424473.npy +03691459-af39a67dea9ff78bf46f716b2b22b550.npy +04379243-7a1d2827369011344d3fed2e930520c.npy +03691459-f6d4918c7dd190447f45370489ca3156.npy +03325088-e9dc5059372ef82e7843fb4efdc19510.npy +03467517-950b02a2db950424c4a359bec2c17427.npy +04401088-d406eebe0342fa8373acc74b15c67e07.npy +04090263-1f755931c16980e06ea2d3b1b25fdbb7.npy +04256520-9fdbd10380d433d0f564f8e3eeb8449e.npy +04379243-b28f6acc151cc20e19fb4103277a6b93.npy +02691156-61e8e8a7ea726a03c79f92df566f8c6b.npy +03710193-976e6d4efdcb81a0e9c2721ccab8cde4.npy +02691156-634de14a7721145fb3f2b01de37c0b29.npy +04090263-4a32519f44dc84aabafe26e2eb69ebf4.npy +03691459-7599541dac4a89ada1efd4f01acbedc.npy +04379243-e21fddb872844e02713f2e93cbeac35d.npy +04530566-7773c432613c96596cdd81a51107bb1c.npy +04379243-c3959f18e44ed46b40f4518b250404ee.npy +04530566-423f4d084e13106db75e46a5ead1e5fd.npy +02958343-f4822aa5b83b28cb35840786ceee5cd2.npy +04379243-184c944daf00dc9919fb4103277a6b93.npy +04090263-36b65f1b9161a5f231f3d76ec3df45bb.npy +02992529-2a6d70bc7ac6db391d4136675e1527dd.npy +02871439-47e8801869f3dd62ecb0f4b907025ed.npy +03001627-c4cab2a416a4537e2871cc0b3cc1a485.npy +03991062-2ebe359d8cf7f6aba2c59a4d90e63212.npy +02691156-e416ba617d5388401b0d75a1d7e2d58.npy +03001627-20e0e65d8a10a88f91b8ec332e6d93da.npy +03211117-8f9c63f788d0044dedea6f8de4918c9e.npy +03211117-fd2f94be1061ff2ac92f2f0063445de9.npy +03691459-a8de7f2c7e00f9a01e5b68ee10358ea3.npy +03001627-c833ef6f882a4b2a14038d588fd1342f.npy +02691156-d15e3519a61c5bad86442c51e82d8d69.npy +02808440-532ea759470c7e0b3321831d2245cf06.npy +02958343-c0b9eb823b9fff9a2764cfba57a5de73.npy +03948459-7c799e8aa1ea1d29804fa2d77fbff970.npy +04530566-83ca38043fa57a7de8e8428fe69dbbc6.npy +04379243-3de638f1ace536c41b17743c18fb63dc.npy +04554684-67e25e8640583e8d91219aad82abc053.npy +04090263-faf6a45b04c24fab1d9b004d9d8d2781.npy +02871439-2a40f207dfd0d77727eecd8b185d6f50.npy +04401088-d2f3eb92a31649647c17b7a9bb17a24.npy +02691156-4c0f48d49805a37298a97ddfb532e08c.npy +02933112-a1daa27571e67bf7239d26686a11c3.npy +03211117-977da77136819715cf8a1b5af7e0bc1d.npy +03211117-b4386438057e85988bfba3df1f776207.npy +04090263-934fabb18c71373f1326f2506129299b.npy +04379243-4a9ded4f31e089129cd1fe76686a65.npy +04379243-2b0c16b26ebfb88f490ad276cd2af3a4.npy +02828884-abf250a01f526137a035c800c58595d9.npy +03001627-65ff1205a5f89150315ec3dc61760fd2.npy +03948459-ccda5c751d3feb951e824347c651d873.npy +02828884-4f44a4d47a8911c4f155d75bbf62b80.npy +02933112-7f60f68c48e67cfb422ac19d4a83319e.npy +03761084-af1e967283fa203110b42f6d9481f5b.npy +04379243-5b0d2362c82416695b903ba10d2ec446.npy +02747177-9f9c097de7167031cb2a965e75be701c.npy +03001627-23c4d774910c9ce03c832f0140db42bc.npy +03001627-2ca81da56f941624191c3762b497eca9.npy +04379243-871530f9e0ad4e2be6b70bffe12b936c.npy +02828884-d25262c74c8269a04c80535a28040aea.npy +04090263-43e2cd954ae1e3ed18bc22abef3f86ce.npy +03467517-32dae2a523aea5cbf9165190cf65b885.npy +02691156-98168c1772b769c0ea1bd6f2443b43e7.npy +04256520-ed151b7e31cf582ffe00f644e4f1521a.npy +02828884-b2b856a8e25eb566ad5067eac75a07f7.npy +03928116-7387007f9b6d551cab2c39e7de6e100e.npy +02958343-ac3f9387cd4319592a9eb0f146e94477.npy +04256520-aced3dd677d1e2c46ef340d5b029818a.npy +02828884-5121a485a7eebfec5674b1bb8d658d39.npy +04379243-70562998ddeecf5ff5816ac43b9e4b2b.npy +03691459-4d033564f0dcb412afac285245c66df0.npy +04256520-29065562beae791be069c558a1f154b2.npy +04379243-11c16f6a5fbedf4213c3458a0fe5598.npy +03636649-511917ee5ee2f91649244b68aadec703.npy +04530566-c4830136a2451f8f45aff212946058fc.npy +04379243-db5a895ae7358c97b66213207f46bee7.npy +04379243-e97b4992a642a13c789195d85b2f8718.npy +03325088-84c1ef3fc2a614deb362845c6edb57fc.npy +03337140-839996ad49bfe12aaee45fb27ad3a6fe.npy +03001627-a559b02ec38b9995c5fdf6b0c2c57721.npy +02933112-7227b96bff4e94a86f9e9f74beb7c348.npy +02691156-6615d159d2e250376969ef231a00a44b.npy +02876657-6d680415396d14d4d7c5502d4a22edf5.npy +04530566-404061915066692d89e410fd8930ae43.npy +03001627-bf1dce61ba47209189343fd44bd400d2.npy +03467517-1c8c6874c0cb9bc73429c1c21d77499d.npy +04090263-54fd9a41c1e7b94329d95b93a79ce1ab.npy +03797390-46955fddcc83a50f79b586547e543694.npy +03593526-be9bec33a4c5323a7d44dc16af152638.npy +04379243-e881a6fa6c3443ad5d28221e3b996124.npy +02992529-2ea4a3d502b12c61707fb0d61a11775f.npy +03624134-a996f7e1614e0c8e6c51785addc24406.npy +02946921-f4108f92f3f12f99e3ecb6fd6ed1dd90.npy +02924116-6a4a5125ed80513aa4667b5cc14ef4e7.npy +03001627-fd05e5d8fd82508e6d0a0d492005859c.npy +04090263-b13e4eef50c826a2fcf264b62ed090b6.npy +04256520-5b9919f927005de3b867e31860078994.npy +02828884-868d86e47bcf7c9d1dd03d3141d85a03.npy +03691459-d457ef805b078d037f5e8f62dd90fb59.npy +02924116-9171f8d3aed990fd1759ca9eefe0e251.npy +03001627-47cd848a5584867b1e8791c225564ae0.npy +03691459-55e58eac4a2e7f4c24abfaa350249967.npy +02958343-45c88ab8a670797a134736201a79843.npy +03467517-eaa2ff0101bbc4ac352b6518abcc1cc4.npy +02828884-7a4a9c948c54de261dee989d1177ef4e.npy +02946921-3703ada8cc31df4337b00c4c2fbe82aa.npy +02808440-1fb49b048e21c27344221bef0fa3c36b.npy +03001627-b59735c72cf9af0c17b431cae0dd70ed.npy +04379243-47315d244171ef7171a782a4379556c7.npy +03636649-66acf7f6883db6a377b9297f3055210.npy +03636649-963e6743370d5c5c9b5d51fa8cce1753.npy +04401088-3bc6f902628b3f7f85f6153ed2033a1c.npy +03001627-6ea4ccd680f3635b14038d588fd1342f.npy +02691156-49e9aa7ffa2b1a25e9d8a35d7a1fb08d.npy +02924116-92766794a46801bfe8784f880dac0f61.npy +03691459-62729cd3a4f7403f712b392cfc0c51c0.npy +02691156-1b3c6b2fbcf834cf62b600da24e0965.npy +03991062-cc5d178dbfa91919beedb4c8fd29e2d1.npy +03211117-1308ff4c4998cec02918c93bdb2b63e8.npy +02691156-4377ea17eb17fa79216b327569dd806e.npy +04379243-a5d5fc6b0bb7881419fb4103277a6b93.npy +03001627-8ec3459ab9fa3ce8738e43095496b061.npy +04530566-764ed516b7f5f7e16b74ad4a219e448d.npy +03790512-12ffd15dabd7e3b596b84415a3f1393b.npy +04004475-4f891a5300d8b10b55b46d261fe0021.npy +02958343-84bc3155bc5c95bfaaafd94b9f216ef6.npy +04099429-796073614ef36a40a336873d5d63a7d5.npy +03046257-a538df6d82a197dd95f577622f465c85.npy +02924116-b74ad95e6bfc346062845e894af87f76.npy +03001627-5d681a38c0de5545205884f75aba3a.npy +03991062-a7bf27af31391712cb2a965e75be701c.npy +03938244-3fca753458f2b44c283b00891f680579.npy +04379243-34feac86a178437527eb00c151c6f711.npy +04090263-3da01ac97bf8e71b12b38b1d99376c0b.npy +03636649-1facaa0eb35496fb69783ac218a8a2bf.npy +03325088-70cf2fcc591044323321831d2245cf06.npy +02942699-5d42d432ec71bfa1d5004b533b242ce6.npy +04468005-dc490f62c19246fb4d04aae9d29ba449.npy +04379243-e15d98f37565adbe650ec61be62e0cd4.npy +04379243-66e0abda60998bf61a96060575291b6a.npy +02843684-8a159ab6dc7b409cc211ff482a022b4d.npy +04090263-2068c2f0972d82e569f9dfaaa2301a49.npy +03790512-7c4fc3a05d5fc8b1d0f568c31c1cd62a.npy +02691156-2893dc61be63a8a16d0ff49003c479bc.npy +02808440-393484a5228413b777138b91927032b0.npy +03001627-460eef2b90867427d9fad8aba2c312b7.npy +04379243-14922c38b2cbfce6fa31c88352968918.npy +03991062-3152bd6fb7bf09d625ebd1cd0b422e32.npy +02691156-56ba815f883279b462b600da24e0965.npy +03046257-32197ef6ce095472e59f529cd1b6faa8.npy +03211117-36ac6a08317e2c618f533a7f52262bdd.npy +02828884-48a9e1be51e751eec4da326c9127fbbf.npy +02933112-6543e0c78675e6eb868fb986bc092533.npy +04090263-2d2f48b293f5ed5d40385522d1beeb20.npy +04256520-1a78f3397910037885f6153ed2033a1c.npy +02933112-c817934380830ccb4da5feafe6f1c8fc.npy +02958343-e6643b95e245410b8efc69f75162eba1.npy +04379243-684dd5cc9c642f98f2dc935ce0a740fa.npy +02958343-fc6f6309eefa5178590462ce3bd1e59f.npy +04256520-fcff900ce37820983f7e27638e63d848.npy +04090263-45a756b1fadf20c7dd0a2071dde26395.npy +03636649-73a4a5e3a27aa7fcb9f5f10496f09f56.npy +02958343-c06a5f0315b3784dcece4698ae3579cc.npy +02958343-81fad64b8fd8f010b17445a1c29f6d34.npy +04379243-c6d1d2f8261885abb2c2cd006d206129.npy +03948459-aec662fe0a40e53df4b175375c861e62.npy +04090263-384d3caade76bfbda84690bd684fe15a.npy +04379243-497659c4723fbc4fe90ff84c89de437.npy +02876657-fa452996a220dd49257c84a0e95a18b0.npy +04379243-385521a6e023307644fad574b043beb8.npy +03636649-6e913f0b67bb638288c10250d0e7fba1.npy +04379243-4b5536d2e9c5b9b7febad4f49b26ec52.npy +03761084-dd96916749ee3939e793cc5433bece89.npy +02691156-732ff6155a096fb0151f2df200a24ac.npy +02933112-8c60fe0d274ef76f6b983cbae7aad051.npy +03211117-fd19c9fe3d5e58549c4081063e213a15.npy +02828884-f934f89d094313362056b4bd5d870b47.npy +03001627-c62a17ea91815a7a492d9da2668ec34c.npy +02691156-94cb05b56b89aa2223895f8c849f85e.npy +03467517-e3378988d0aee759d48b953ad82bf595.npy +02958343-70048a705ad4363642db06daf723ec44.npy +04256520-62852049a9f049cca67a896eea47bc81.npy +04379243-3863d248581965c0f42980cb0dac8238.npy +04379243-d92354e060c98854b0ffd7a60ee2298f.npy +03001627-d8b189ddc0ca5b8c681404257d94ad9.npy +02773838-7565e6f425dd6d376d987ae9a225629c.npy +03001627-7fbdef802b9e160cc242632b2a8c3129.npy +03325088-7313e873a641411b979c556124bee033.npy +04256520-28b9e6b16443e183fcc04d1259a0af57.npy +02958343-107699ca67fcdf3fea999fe4ffdc2504.npy +04379243-757bd36fa1b0f3984b3c42e318f3affc.npy +03761084-7b53aa1ce95b1efd1773834ba0a5df02.npy +04379243-208903274bfe69cdc5d1c45cadcaa3eb.npy +03691459-cb904746fddde134b9e8bdc9c4a49aa2.npy +02924116-a3a75e027a5274261bd9a8f6e632e88.npy +03001627-759d66c5dcf1cabfb99d75d512b660d0.npy +03001627-7212f652dd37232a80360680c1602c7d.npy +03001627-7a5215c4f74afd1af7c7ad2549a1b15.npy +02691156-2980f6ac8412890548437f47a316427e.npy +02691156-618b433a97bc23acb1f09c4591ed2db9.npy +02691156-26950e05ed379413bbf3143b1cb6076a.npy +04256520-9cfeab8ccdb908a7ada629e23b16719.npy +04468005-5dd23b3d7247b98b4c3a35cee92bb95b.npy +02691156-aa21bf2a545e710cf68a010d0fc56333.npy +03046257-ed4815a2c0d6e641809222e4341a7d65.npy +03001627-2c7d258bd18de1c28f7b968097bdb0fd.npy +02958343-74b73c2cca45cf483c1d9add3a87bd2d.npy +04256520-26a6dd90bc8d6a0e227f59b6a8b64739.npy +02691156-3231fc366c6f4f3cca8607f540cc62ba.npy +04379243-bf6c171ab896774d2f95e2a1e9997b85.npy +04379243-e55dde3c1153ae5d7eb43b1b22d3185e.npy +04530566-a8daa7461ff94965c0be177939e290.npy +03211117-e6a0a8940246d5bf4e104a60eb91ab8a.npy +02691156-c88275e49bc23ee41af5817af570225e.npy +03691459-2aad0ff91e947e64baf402ca36cbac3b.npy +02691156-63c78352b218c01a995425f067333fd3.npy +04468005-ed66247c141a18936ef38ad304e9224b.npy +02924116-60c404b902c5680985718c281d7fdf61.npy +02958343-14121abc9e2a868e52ab7aae4be20d81.npy +04379243-5d4eec616095ed87dbe6f297e0ec0d5e.npy +02691156-a8c4288e4027e6a319ba010ddb4974fe.npy +02691156-790e9d3a9e037d3efa86938af3fa9595.npy +03211117-132df41128e6b43356fd3a55668db806.npy +02958343-c849164176944e08e39b6a0d304ab967.npy +02691156-6812a13a1a99f0da2f20ac99f64093d.npy +02924116-63cb99592744321415a7b5ba389301f1.npy +03636649-ec01e8b79f2d07df784a45ea6efa1d77.npy +03642806-b9eb4471432dbbc3e4b68d3b17c43658.npy +02933112-3076e5d4a8078a0c59350d819542ec7.npy +04379243-c6304f008d2a44f81943903831aa7f4d.npy +03001627-5539a4a9f2f1b45f3eec26c23f5bc80b.npy +02828884-14af4a9931635c75f4fb4dee5181bee.npy +03001627-81158ce36c90c319740641939c9d6dc9.npy +04379243-68a7bad2b06bc1a9d93768e7b9b1eabf.npy +04379243-3bcf1f68540a478de2680d1a8f76531.npy +04379243-f7921f51bcf7e93b24a15e3e5e0014a0.npy +03991062-f5ecf2549d458beebd4a7a372c75ee76.npy +04530566-c680824e615c772d18d5c097fe7ed300.npy +02958343-86c8a3137a716d70e742b0b5e87bec54.npy +03991062-1e42e5b37a46fd9c3202f7933a14e59b.npy +02933112-4ec97e83a1e9725c77a332e31ab74b68.npy +02691156-de001f9e2311dffb7209009cfb89d4bd.npy +02773838-5afca35479b347786f0abe366609662.npy +02876657-ee3ca78e36c6a7b2a367d39c852840d5.npy +04468005-3b8c505fd1127ed88f134472f61cf6bb.npy +04379243-9ad79b67c56ead5dc862eec8232fff1e.npy +04401088-bbd5005058f01a54909425bd531e6033.npy +04379243-2854c3a6724724dbf5561b9d69a2eca7.npy +02808440-79db8c9f8cac9aa680ecb974987586f7.npy +04554684-5bd6bf181544ca23c5d1eba75162ba.npy +03001627-5d20adaf6d8f89fa2f1c10544d7d6f.npy +04256520-af978eb2f903536e5b9e30b3558dc362.npy +02958343-dc8765720d8d3828b3cf5236f651a8e6.npy +02933112-46bb63196198ffa2fc98aa4b97627df6.npy +02691156-77410e47feee769deb1a0518c224975f.npy +04004475-a74db482402e533d9d23dd9e1ad481db.npy +02801938-e3bae8da192ab3d4a17ae19fa77775ff.npy +04401088-3f4a507d616678da650fb6b8f6bf3419.npy +03211117-767a4f06f66596a4d0e90ab6c6492cb4.npy +02808440-99c5407b80625a0c904e03fa15bd73ec.npy +03691459-6c1ab06a1ae2471e86bb0379a61a0978.npy +04379243-60ebae123ae653e2a4385667567ce9e5.npy +02828884-a06d35db2ddc85e29656036c096710ba.npy +03001627-cf391bbecf5926ecfe51dc4aedc63243.npy +04004475-132325926d85caa6d0c63a304a95442d.npy +03001627-59b45e83bf13e8e2374110224c1c4eb0.npy +04090263-6cf8bb50d1a8f0d7663e90eaf6b4ca52.npy +03642806-229f440bbd8f5482355323b019d9d87e.npy +02691156-d390f0246fd43cc8bd46d022fd7d80aa.npy +03467517-c0cf37064ca57ebd93f0194265a9746c.npy +03325088-f2a2ad135f62a8351875e8709de3862a.npy +03001627-d645bf9037e7dabda341228b21d337a9.npy +04090263-6e91124a4ecaa1a365564d9c2ed3b493.npy +04379243-98482492d4cd11698a40b9ddd9e5eea5.npy +04379243-78b4eb949311548236da5f8a6c22b2dd.npy +02691156-6d752b942618d6e38b424343280aeccb.npy +03691459-27415ac0b56e87528dfe57cb1b540899.npy +03691459-15e847b20d22d56cd288bc0586930768.npy +03636649-f330eebb153447181735ea0e092a805a.npy +02691156-98480ee19ba4dc93ef5f09964a6a1f97.npy +02958343-4eb276926f620fa831354a729b0d6b5c.npy +04379243-6d59cd216e896670b7562ed1f28478bf.npy +02958343-8498fb254e1669faaaafd94b9f216ef6.npy +02828884-a11caea04fcac4f5643a8f56e2ede6dc.npy +02808440-25e9f914f5c18b2b3321831d2245cf06.npy +04379243-3f9462d720929e73873bf2cf33e10943.npy +02871439-9e509b3774ee8c0a398c13334e998500.npy +02958343-5b423f02b76df0ec1472a7f3e4685aa.npy +03593526-31c50baef63a3cd0b64920759fcc80ba.npy +02871439-43731a6a4bd64ae5492d9da2668ec34c.npy +03691459-ab6b43b6529d6d6f9580f98cb259b96f.npy +03001627-4c775cfff4afba83b02c91492945da50.npy +03001627-76f2ead0035fdb2ff94d7e6d8577c8ff.npy +04090263-7816689726ed8bbfc92b24247435700c.npy +03467517-3338f59aefd2066f5b3335548350bdee.npy +02876657-5a1e624764af0205bf8b9d530de7a108.npy +03636649-57930764a16deae9b219dbeac7819b2b.npy +03001627-aa7489c9c7cd0c1dc3a1be62b60323a7.npy +03001627-c465b7ee24741eea9edd9a0b28d406e9.npy +03636649-a0dfc97cf85ddccdac42bdc1d2df4a3.npy +04379243-7bbd69e2b6e1bb49f7075cbf4d009544.npy +04256520-8701046c07327e3063f9008a349ae40b.npy +03991062-a8b41d9e570e2a8e7afd114af4bb7b4b.npy +03001627-2a0f4fe08cec3d25680876614ed35a7f.npy +04379243-1f64fc95a612c646ecb720bdac052a97.npy +04379243-b63ab8d3dd4eee098d95727c923f3722.npy +04379243-7d518c96a145547073ee7d53b833ad02.npy +02808440-4cb7d2c28ef5d4d854d7082b34825ef0.npy +04379243-fba0f822f16932aa10566a0096ed09d.npy +02933112-575d99ba4197caf041ba999b450870a8.npy +04256520-fef42356f1acb01b593ebeeedbff73b.npy +04379243-52e7aecf3ca3a0db391e4d6c585a697a.npy +04530566-fa18c9283443b67388fb22c0c1b2b173.npy +03001627-62aac1b94f2b98cb9f9a4edc4751ad63.npy +02958343-1355f3aa779b599b16abce8cb03e7794.npy +02992529-a1c60f087535c7726fde3adc6768fe52.npy +02691156-a097428376f298abd872dc56d048665c.npy +02828884-69f724fd745669fcda56795a6fbde1f.npy +02958343-380e0c29c9ea00e9ce158c6cc0278580.npy +04379243-731b2115d66fc850999b33727fe6db14.npy +04090263-d77515679ddbcd9c8064e4301e947b0d.npy +02828884-5ce845f80b1d407282dde982679cd879.npy +02958343-744f3661d9030c059cc32a851e7d6f32.npy +03691459-dcf84867f92cef75a9c2f34ef56404ef.npy +02808440-7a3541431dbfc5d6dbb76013b759885f.npy +04379243-ab463d43646bd5dcd27b31bdeb5f5c79.npy +02958343-bc75e8adfee9ad70bda733a39f84326d.npy +04256520-7f6c75c2d820337b69867582939a3cf7.npy +03710193-af6f76f4e447991b9d6be629f8f5773e.npy +02828884-852d65fcf7abec4a301cd89e7156530e.npy +04090263-f154291136c45c24545c558f9b86cc0e.npy +02933112-b60bf64c7402978555a060c097fa68cc.npy +04256520-6d74c6092567868b65d5de7b04a51b37.npy +04379243-330b4c2ab42bc715f1783a44a88d6274.npy +03790512-992fbae5178edcbc4e31d0cb4d7568.npy +04256520-bd5bc3e6189f6972eff42b9e13c388bc.npy +04379243-a70771fd3bf24d65c16bd6fd1b8c7eae.npy +04530566-df575767acf17d7188ca49762bf17cdc.npy +02992529-5b826c910108d27a684b810d277e0e9b.npy +02958343-180d1e3463c29355bda72093f9b5aa73.npy +02958343-50e986077b994d6aa848f24544821b25.npy +04379243-519c9687ede3906dccda8d28b44378b7.npy +02924116-ecd4e00fe0ce46dc5d3130ea1c8a44ad.npy +03001627-175e2a8cd6e9866ab37303b6dde16342.npy +02924116-f59a474f2ec175eb7cdba8f50ac8d46c.npy +03001627-a9eae610d9ab7c40a7d147d66b8f507d.npy +02691156-f0e7808ee55510be1a7dd57f67482196.npy +02828884-702428ed9e72d74456f6fc4b4ce1db04.npy +04379243-b659c2162c4ff214684b7bc3f8a9aa55.npy +04379243-ee5dda5cfc8349caad5067eac75a07f7.npy +04379243-df811f7a858750875634c21965ee6bab.npy +04379243-6fb986ed2a4db0c1bc7f8f77923d8ffa.npy +04256520-549f6b723e4bcc91e2cded16638068b.npy +02691156-f485dcbd466f217286774cad40dd456a.npy +04225987-aa886bed91a13113d5498a74ca9ca78b.npy +04379243-949e39403ab4fab37ade8e3ca8db8db3.npy +04379243-416af739e6ae8b2ca9e3e4940ed610e4.npy +02924116-e06db4bbcb51cc281f3f27ff04a4459b.npy +02958343-965000959c53a8612fdbcd3e1b829315.npy +03636649-61555024958cb5efe4e7668ba612f00.npy +02828884-fcfc935c2ff7c66c858699aaad4acee4.npy +04379243-3d929eab6abafbc5cf004563556ddb36.npy +04090263-9a5e20b8f1881145d735fa1ab17311ec.npy +02958343-be86ce7f7aec3ad4f9e07ddc212a2f71.npy +04379243-7d040b260fae0807a2d3cfe77a14b5f4.npy +04225987-994dc9307a0f228e30eaaf40a8a562c1.npy +03593526-3c148476c78123f3283b00891f680579.npy +03636649-302c3b1ea1a86a1ed2da3773f06dbf7.npy +04256520-71783c8431b28220593ebeeedbff73b.npy +02828884-50c0de8fb13d6421dbbc9440457e303e.npy +02691156-8cf06a71987992cf90a51833252023c7.npy +04379243-2da415184cca0aeb2063f99c33f5c49e.npy +03636649-7e5b5fa94575f873c2e0b170f2ad8bc.npy +04379243-f19fb80eae2ed668962a9d5e42f53a23.npy +04379243-15bab3d19de247cd9cd431573238602d.npy +04090263-70ec646e9929c7cb9a2ee232a197081e.npy +04090263-6d247b103dece20af500cc506a763c18.npy +04256520-65fce4b727c5df50e5f5c582d1bee164.npy +04379243-565ad2f2a4caf3429d297e74104d3ac3.npy +02933112-3167991b1c87967ac59350d819542ec7.npy +02933112-d347f6e236975a6b7c4767a4f4c46bba.npy +04090263-528bc52f211ff34ed2a72bb74eb549ff.npy +02958343-a3881c3f4e8c807f2a9eb0f146e94477.npy +03001627-c97f8f3d828173607301b41e73e277b0.npy +04379243-59fe91d51febd1f3c83a073fb943e852.npy +02747177-b9b1108520918039a47fdd008f2ae822.npy +04379243-265851637a59eb2f882f822c83877cbc.npy +04090263-1dc15b9574f88cb1fa9286f039319ff7.npy +04379243-59a1703cb9320c018f49a52c8d710d0f.npy +04090263-61a0bef6e9c5a01dfa6c79a0c671edcc.npy +02958343-1cd4a2c1b3b4a9661487189ebf835715.npy +04401088-ce62e8c8a75a501535c433f6b651ec89.npy +03001627-9e08476e458e21519fb4103277a6b93.npy +02992529-c7e4a425cebaa04bf9c8feac0b33491e.npy +03001627-33e28d560bf1bbcc32db3218111111ed.npy +03636649-8872dceb7ba9f34c140406de8e63ea3a.npy +03001627-7573185356240f5e2b4f3c9a4b815590.npy +04379243-164ec64e7a28c08b221ea40148177a97.npy +04379243-8e3524b6312f60738ac5263758737a81.npy +03928116-f90c23de385d10f62f5fb84eadb6c469.npy +04379243-19c5696d315c359dda90d20b69102dd.npy +02871439-625ee2fe616a92c8d706ecb3379aa341.npy +03001627-94f9fa9f8a20f7d040ef1c8b63a628f9.npy +04090263-e3f16aded8ea5a2fc79f92df566f8c6b.npy +03325088-2003d9e8ba083c4e2f066782346a992.npy +04530566-27bee532a7cbe5dbc4bd6e2ad0dc6de6.npy +02924116-148441ff0fd22c774d9ae46885a85f72.npy +04530566-fe482b5db6daa95f88e2183678696c9a.npy +03624134-57795189a634e21fa0f8e9a2d8ead2d5.npy +03636649-5254dbd4b24449edfcb8d8c6d4df8143.npy +03001627-9d0ec3530b39e89640f4518b250404ee.npy +02924116-cd6f59fdefeeb46273873da0bf53928f.npy +03624134-d6924db1f51953eecaecbfc7057f661f.npy +03001627-9c339d9fd8068f81351d9ca36f76b95.npy +02691156-d2daef39d1cb8d027089ddd41f4af842.npy +03001627-56300f790763af1a872860b02b1bf58.npy +04256520-2bb1b5865455b2b814513156cf2b8d0d.npy +02933112-45553c754e1132533fe047712e43e185.npy +03211117-b8db7ada8acd039a3406f1378b19168e.npy +03001627-e3d3b3e060ef84c93ed60220ff139f8a.npy +02958343-292f6606c6072b96715e04edb8af9c53.npy +04256520-bb31bd378273e437f4b35f4029eb1ecf.npy +04379243-d81df8f708d4360c5e05d85b12fbe60c.npy +03948459-194195123b03cae8912fbf9a0eb12fea.npy +04379243-2e71bc549eca25fdfebad4f49b26ec52.npy +03790512-655b9dd9425cc3a12a45a87054fa7272.npy +03593526-739f97be019f29f2da5969872c705114.npy +04090263-a759e6ddc0378dacfdb02ff6a9949154.npy +04379243-cff664776c56345a6c71cc363c51a922.npy +04256520-1c54ad94269d0e786abe5555a3b447d.npy +04379243-8db2878df7471c53e45ef4135c266a12.npy +02992529-e6cfa46780f8634de8d86c9b116d4e0c.npy +04401088-57632112a9128a16a82783081c89c0aa.npy +02691156-413a85d9cc7f19a8b6c3e7b944b34fa.npy +04379243-a767beea4085c58d301fa758e52a6264.npy +03636649-e120efa70ef8efa71ce05d96d33be415.npy +03001627-c6409b289ef9aa2176f028c3dd1719d5.npy +03001627-ca53f7ce3b6951ad3991f56363dff980.npy +03691459-384fbf785f1691d2d747b49524a1246e.npy +02691156-a9a7f21271b3efbaf446f92b52bbd82a.npy +03467517-e585e31db7568c4cf0e1c0df18936d05.npy +02691156-224a8b6776a242f8adcbeb54f3d014e9.npy +04379243-316021f1937b32c8e3e78c911e081c08.npy +02691156-de9564aeaa585a6ccbc790a63192d2ab.npy +03001627-e3e76d624f1f855bcc8a9c365968620.npy +02954340-13295f09e0e9e5d4a6e67635b9d1cee5.npy +04379243-490b186d11cf5675a872860b02b1bf58.npy +03001627-dcfd665cdc0b01e7b04cb542e2c50eb4.npy +02871439-c28297dff455c1d88abbce8b0b4c2d45.npy +04379243-951d129ced4e7d13cd4e8a27ff8b78cf.npy +04530566-73fd73a8bda002eae8d6be23f236225a.npy +04379243-7afb1812e86fac4f492d9da2668ec34c.npy +03593526-44878567a2cae5f8b5e1005644816d9f.npy +02691156-ad9059778f3e34ed4c3a35cee92bb95b.npy +04379243-ad92bfc65465091c48d90eef8384210.npy +03991062-408717256509036d44c183864792bc2b.npy +04379243-146ecd9d7712eb81e6c5cd45aa112726.npy +02828884-c8fa692760ba875848d791284650e46d.npy +04379243-ea9e7db452d2df55d42ec7e303174a87.npy +02924116-50866b5fd13389b4193d7855ecfc1bd3.npy +04530566-1f7f1d7c3882f638fb64f9487ce62dd2.npy +04379243-be5501adc4564d9edf30786b8faddb78.npy +03593526-a258544f4f27cb7fbbdc99ec57ef9c40.npy +02958343-7d59691881b13cc5702956de1b65c053.npy +04379243-d6c875f6b3fa82fd9aa3aca17bb25c50.npy +03001627-96cb0c919d3f379dd0a96520c31993ad.npy +03790512-f06b4f382bac9c9a5a6093c81238167a.npy +03928116-231a265be57b08cd521f9db09805b6c5.npy +02828884-8f6890cfdd98450f4f782ac57aea97b.npy +03001627-b654fef8eb98e99d65ba78ad9601cf1b.npy +03337140-334b5457151b0cc4492d9da2668ec34c.npy +04379243-2bbd62449b56abee659dda512294c744.npy +04256520-e6ecc4e6734f056855f9a00acc25f137.npy +04379243-2e990f9b5c2bb3098eb91f418e60b82e.npy +04256520-575876c91251e1923d6e282938a47f9e.npy +03691459-70acca9ae753b952c71de83a48ed3076.npy +04090263-bd48edaecaea23d65814fafedc6971c7.npy +03001627-ca23c31de817db9b67981fccd6325b88.npy +04256520-1f9cf65275610cff14038d588fd1342f.npy +02958343-42ccff0d88276152e341b5704aa568bd.npy +03001627-b6843e186082096ebf80985a99195eb8.npy +04330267-a9d6e7fa088ddf177fde87eb01f5851.npy +04090263-14139593048f806e79093d8935cfe4f0.npy +03928116-854ffe2c60091876e07a1c4b84dfd325.npy +03001627-8b52303e5ee47ac617ffa9a4ab48724c.npy +02876657-15787789482f045d8add95bf56d3d2fa.npy +02958343-504e8dbdccd8beea7e488037e176d2f0.npy +02958343-df1081dd18fa7bcd57d7020aed3513bb.npy +04090263-1fd98fb84317ae248cb94bbc7f05ffb7.npy +02924116-6d81decd46d9040741cefd10ce5d6cc0.npy +03211117-5c67f17ab9c9db50fcf74172442ff5b7.npy +03636649-e6c64600128ca2c176e9713f57a5fcb6.npy +03046257-86a053255fdd01266559ee74abc3e41.npy +03636649-22c24fc303fa5c8c48cef9d4cb5ab8c.npy +03467517-92fee1447bd437898ca72a94f8440a42.npy +03001627-9cf25518a8d3eecd9c48aa7bc7cbcce7.npy +04256520-78742b25c20ae244cf01bc59d215f0.npy +02828884-a37801a9289678201f8b303c0da5108d.npy +02773838-74c548ef3ca7b1987515e7bb7dba4019.npy +04379243-131bca5d855f49d428e3317d62e4ff40.npy +04530566-8db75d7703406e81e4f8f268ed99350e.npy +03636649-dc5e7460dff922246a44fdd49dec8069.npy +04256520-69f5626d5dda497c2af11d59b11e0199.npy +02828884-98de2d75e89789a7d301ec101065cf10.npy +02992529-54539e30a59cce413864ee650d9e9c5c.npy +03593526-5c55279aabef108425b2c60a44b454aa.npy +04379243-785e93009913379a79f7c71429a96cf8.npy +04401088-db89fa13b1c3c53afff0e9d5e9e3da5b.npy +04379243-7573bc5999555ad635e2fdf95cd06839.npy +04530566-9c19eacc8033da3698a97ddfb532e08c.npy +04090263-b577e94cb0a28f73e8152bb1bb6e4c3c.npy +02924116-b081d18ce7fc240241cefd10ce5d6cc0.npy +02818832-e7e05f20bbf738c47ba6f8f10959534c.npy +03624134-ee7ced71701c3e88b9e3f0d9deebf307.npy +03642806-3934cb69fe3584ef8f6cc6fefa15515a.npy +04530566-d24616fb070d105d3a10f0b86a89bfc3.npy +03211117-c257e38f51bb660447de0ecdff019da9.npy +02691156-b76c6ef211d627efac8c46f8a114a34b.npy +02691156-b9006dadc7ae7f7d21afc48d963f897.npy +02828884-c069553c08631597cb2a965e75be701c.npy +02933112-b3328bd358d7ace07c68e936cd219e1b.npy +03001627-9c563031f09dc2459a87002a4eeaf610.npy +03691459-a6fe968066893c10faa3b42d05e08ac2.npy +03636649-5c25916b55fbe4ca29695ec09b98af5.npy +03001627-fe5310a3457bf0e5c4e8952b27b5f370.npy +02808440-a03a2f92431e190591a491e8257bd6fe.npy +02691156-f009f3112625ee00b8cf782e8c539948.npy +02876657-9da48acd8046be50307e049494951dab.npy +04256520-40f6e30804ff4aae20125f039fb4c8e.npy +03593526-25d459836c571e1e6e130a30b5ed875.npy +04330267-bda8c00b62528346ad8a0ee9b106700e.npy +04090263-419226b09e44e5bf8c8cac88a8c48208.npy +04379243-97e3768e85c686f9601bea3dca268229.npy +02958343-49a114b29a54300e51a95aaa6caba1d3.npy +03636649-d49a8626a9eb5ac2553bbd6d743ae8f6.npy +03636649-c8f5bf57a3215cbe9a6c869309041adb.npy +04379243-622e30a7ccf34ed5b64a7c8189aa3893.npy +04379243-8ea7ca2c8b48eb68ab610b0c94236463.npy +03001627-1b5fc54e45c8768490ad276cd2af3a4.npy +03001627-d6da5457b0682e24696b74614952b2d0.npy +04530566-b5d1a551525c6b7876ed13a8bcf33762.npy +02924116-ea5b5c44f4e0cd7ab06dffea8c2baf8.npy +03325088-e452db5f61ea4593321831d2245cf06.npy +02958343-2ef61a1083304211d27be7764701cfe.npy +04256520-5560a425c597eacbff841fc99bb16039.npy +03928116-3fc831f0c69c981048d189f942cedc62.npy +02801938-ab6e1ccf0f35228416fdce62f5c06e29.npy +04401088-45e907ca47e0122c1752adf979b66914.npy +04379243-2a48b2cc3a5b7da6833b2489037ae4d9.npy +04460130-76377cf0dc70d027e7abbab3021b6409.npy +04090263-6d88bd6c04bd5bb01a18bc096aeb4c21.npy +02876657-e7818a94d20fd8e1a4136492f17b9a59.npy +04256520-4e1ee66994a95492f2543b208c9ee8e2.npy +02828884-b2596a0e14772bbad5067eac75a07f7.npy +04330267-6fe99039481ce154c13f6e8e2f6bde6.npy +04379243-977787b51140f4bba100d1443e9d6b3a.npy +03642806-4f3575df3821e08c466909b3e9553909.npy +04379243-2d90a1998eca8778dcfcef693e7ec696.npy +02958343-828c32ae594a5409b1bb46d2556ba67d.npy +03001627-bb4868c1026c04fd7df0e9a69c97c97d.npy +04256520-1e4eb3bad18b75f23d6e282938a47f9e.npy +04401088-e6cfa46780f8634de8d86c9b116d4e0c.npy +03691459-8a5cdc3bf1ed6226b7b1e717b48d88bf.npy +04401088-80243e34f66a503bea95e61f66327e28.npy +04379243-1bf71e2f8abc7698b232f4221eaa5610.npy +04256520-909ea8e0e2728ced59f8e31ca87c470e.npy +04379243-9ec420c3155ef5af707cdefe012d0353.npy +04090263-b5aff534c7df4d86f06f0427d3aa3395.npy +02691156-398fc0e717b0cd524c3a35cee92bb95b.npy +04379243-7b22287c9a2ad418b9deee229eae6efa.npy +03001627-52d41eb69bb764e784aeb682b234df80.npy +03991062-b9126c3c945b19b7a2c59a4d90e63212.npy +04256520-9389ec8dd802a1fa7d7598e07139ebfb.npy +04401088-205b1494d7d3448e21844676433a0aca.npy +03624134-28d99b90d09e4205744848276b011f94.npy +04401088-67baf038e83456967f521a3dcd28e9d2.npy +02691156-5024341275a685bdecff69852469d7e3.npy +04379243-1950a6b5594160d39453d57bf9ae92b2.npy +04256520-1662f76e3762fc92413102507b68bcb5.npy +04401088-ebb6035bab99c3e221844676433a0aca.npy +04530566-e8b19c46e5beb3823b12275bdb30c153.npy +02691156-106dfe858cb8fbc2afc6b80d80a265ab.npy +03991062-496e747582bf5e7187abf842aa6d3bf6.npy +03001627-76919a456a23b9779368d1198f406e7.npy +03046257-4fea2346a95ff9fa97e30bfe57d923fb.npy +04554684-cf13890b1cead267be96d0229f49fd6a.npy +02958343-d6dab47acb946364f0cf9a4b3162f487.npy +03001627-223d0330466ac6bff7628281ecb18112.npy +04379243-7062f5b229674ab7b0b54dd2cf2a35d4.npy +03325088-a8ff57bb496e582ac36fb70296e45483.npy +03797390-1bc5d303ff4d6e7e1113901b72a68e7c.npy +03991062-a042621b3378bc18a2c59a4d90e63212.npy +04530566-f582d2315b6182ec6f6b59ea659e8324.npy +04090263-2f0c7483f4eacbf1c03d8e9f14212b58.npy +03207941-401ceb30354af54d20192a5319e3e2e4.npy +02958343-2c8e9ff5fd58ff3fcd046ccc4d5c3da2.npy +02691156-679d4f84caa5a1a8f019a51d1a3b2e07.npy +04379243-382b49301bbd3d707d6dfba3e792b660.npy +04379243-9d8f0444a8c09adff0d4c8f4dd125299.npy +03001627-cd4fa15a13d7448a14038d588fd1342f.npy +03337140-4374f1908ef835b1b25f5f33b0704a5d.npy +04530566-2f004ec4a719d231e513e51a78e5ea1b.npy +02933112-8e7dcefda14362f866f6836074ef23fa.npy +04379243-3ed500a12dfa511ba6040757a0125a99.npy +02828884-48ea3558db137e87ad5067eac75a07f7.npy +03325088-891944c98c72a487c36fb70296e45483.npy +04225987-97f85bc59f09a9f455c660e6cd8e92b.npy +02958343-6e76975ba073f2a89ba83e6d08a84f26.npy +03691459-374df728f54322363b0edb55efd49670.npy +04530566-cfb1882ac34b81d8a357368f9af15b34.npy +02691156-e49d1e1d176ec1dfbc0909d98a1ff2b4.npy +02871439-7b17701391dcaa7bd2473c216962c0f3.npy +04090263-2680233498fe409060c049bb6fb2fb09.npy +04401088-68918effca4b9becf3434ae1311a0329.npy +02828884-722f3510b849c950beedb4c8fd29e2d1.npy +02958343-e0f1de19f0f65ce09123224ebaa118d3.npy +03001627-c5afaadb73323de9645a86b04c64b372.npy +04090263-144201418b5dccef1a857c47fd0ecdc3.npy +04256520-fee8e1e0161f69b0db039d8689a74349.npy +03593526-5bffbd5a0ca14f342f841233486fac2b.npy +02691156-847bfe2bea87c55b2d49d91e9a282aa0.npy +04256520-1c756525061c4b0b4f3443b22038d340.npy +02691156-a281b2664e7e5b2fad9d7d48f3cddb17.npy +04468005-feb23a40a79ba13c9f97ca916781e800.npy +04256520-27c82d27a4d38e6f41b160b9adc112fd.npy +03001627-8cf71cf6f0bf6bb2b5af95b2c842e5a7.npy +03691459-181d03027d30429dced68ac20944148.npy +02958343-703bd04475fc330d59139efcde1fedcb.npy +04379243-b70eeabec7fd454581960a3202db094d.npy +02747177-ad0bba7ced79b52fad5067eac75a07f7.npy +04379243-26a28d973e40648db40f0ac0fb9a650d.npy +04256520-95c1e7d85da0497fc1a61b0a501d38f.npy +02958343-46a71fe0e651986fcfd826dd468a5497.npy +03001627-380a5345fda8e97492d9da2668ec34c.npy +04256520-3d7301760bbf315f3598efd14e493d5.npy +03636649-9464e80554bbd3de030fd2fa0608452.npy +04379243-f3775c07e5ba9515d6944324b21393b5.npy +03001627-35e8b034d84f60cb4d226702c1bfe9e2.npy +03636649-7264167cae71c90c72bce768f6d2af1c.npy +02924116-639822a6db5ec3d852470de2774d6099.npy +02691156-a4d75675f0f871c96466a07aedd68378.npy +02880940-db180e4f9a75ae717ba6f8f10959534c.npy +02958343-f76b9a9455b20cd875a45359f7e88a3d.npy +04090263-d109693d2d43e65b6ed5eb4c1d0d366c.npy +03001627-40020a5e90c75d94a93412f1b60e6fba.npy +03467517-4a15c0df0f02a9d840c20797381ee39f.npy +03948459-d965eb9091d180245f91354f947d2313.npy +04256520-b5eabf007a57d863a35a7666f0cfa5bb.npy +03001627-be38dc611c4bdef7f1cdfc0a8f38f2e.npy +04256520-934cbc4617c6a6f4b001e9ae2ac46c17.npy +04379243-178703fe974f63e9c3bd24f986301745.npy +02924116-66b963a73fc2c9b2f3f21609a16d7ba6.npy +03948459-286ed45d14215f6e2219667ae51f9fa.npy +04530566-7b0ed74742d27ff3ccc6f1de97150965.npy +02871439-53f91b5f850b5bdc2bec9713eaa8c4ae.npy +04256520-39f5e0c179377860d3eab83c82350281.npy +02828884-19bb2f65f3de8f5fbdc7943e19c9bdf7.npy +04256520-9900929c21330dacfebad4f49b26ec52.npy +02958343-6ea4111bb47039b3d1de96b5c1ba002d.npy +02933112-2544d05396cf1c91bc19762eaa7ba40f.npy +02876657-d5dd0b4d16d2b6808bda158eedb63a62.npy +04379243-136f3b0a4893cadf4f1b88c70d074e4a.npy +03691459-39c641a818474a46e10cf62a02f1a100.npy +02958343-63a4e46bbbd855fc2b63d3b2a8c4e8b.npy +04256520-40a6a3ef4e4e4c4c300703f05f8ccc25.npy +04379243-daa9e908b5aafc2fcce90f0d61ed7a70.npy +02691156-af696fc30a96a0c8bc0909d98a1ff2b4.npy +03001627-a5898fefb1733333a82b0d8d157287f5.npy +03001627-31d48d6b3951ea8e1191025061735ea3.npy +03790512-18f5c9d827522c859cfdf97abe35029d.npy +04530566-18a8a4aaf68d294f800a0120f3e757a2.npy +04530566-a431fbb7e58ef0c46c03c11657c96c60.npy +04379243-55a3fb19f099a06adc061043e7c712.npy +02828884-af79d505f2ef2223cb2a965e75be701c.npy +04090263-fd927e1258969e1ada4044967c19cf99.npy +04330267-41d11126029f5b98e793cc5433bece89.npy +04225987-5fba47ad66c45cd113314092564c13fd.npy +02691156-34e87dd1c4922f7d48a263e43962eb7.npy +04379243-91f6f0813eaf4e52707cdefe012d0353.npy +03761084-d713865a94c8229575f4e5007488531.npy +04468005-19daec6f2602f9c0dc14ba0818ee5cec.npy +02958343-b6bcc1b1ccbf0ea0996e71cb10be68ac.npy +04379243-30c9865cfc4294a7ad16260d4d73b56.npy +04256520-54215008a46fdb714386ad145fa8aba9.npy +03001627-bae3e35109b939cfe7c7920f6a65a54d.npy +02958343-3f6e9baa4657276f97df6383472cc5b6.npy +04379243-ba34c92a41a9ac9f20d3c05c08e26f.npy +03001627-35f83268d4280532dc89a28b5e6678e0.npy +03001627-5d959b0f79a22e8c67c9124d122355ab.npy +02933112-7cb7d54954caa7a2d3cedcecf1ed3b27.npy +03636649-284986b4c72d624abd73284bc3c3cbac.npy +03211117-ebc62d2dac989b7d8b71a158ed504795.npy +03211117-58fceeffe91b7b1c20685b5a7e34b501.npy +04256520-4f0d2de3a60f247662d15c83b2279a53.npy +02818832-9860944cfd30a13dc3bd24f986301745.npy +02933112-23b7a3961eda17df4da5feafe6f1c8fc.npy +03928116-c57408045e96f5d5b249ce9318fa571.npy +04379243-a5cbc0a86cdd01bd348f8ec207893cce.npy +02876657-7467b9892496a83fbf8b9d530de7a108.npy +04090263-18a1fb21c8c1c18f4dbc4096bca262f3.npy +03593526-c4ac6a5f651d12c6c6b4aaa0b0f9d794.npy +02691156-bbd8e6b06d8906d5eccd82bb51193a7f.npy +04401088-4f2919438ca46d8de8d8ad3bdef6aca2.npy +03001627-22b40d884de52ca3387379bbd607d69e.npy +02691156-917694a71164f2148e8405d6c51a908.npy +02958343-6c85bbbbbea160bd81bcd6355b440fd5.npy +03001627-3cf6db91f872d26c222659d33fd79709.npy +03636649-53685a90516a12c5f51fa0238791f5dc.npy +03001627-5cf55d9c3a3c7907489452a0032ea575.npy +03325088-78c5c2aee9ae697b3321831d2245cf06.npy +02691156-e777a6a46ae240a7bd46d022fd7d80aa.npy +04074963-8e167ac56b1a437017d17fdfb5740281.npy +04090263-736200c1ac8d1c34c14cbe2c343fa431.npy +03211117-17226b72d812ce47272b806070e7941c.npy +03642806-2c61f0ba3236fe356dae27c417fa89b.npy +04090263-7ca37968914be27d82b2a307d22750bd.npy +02828884-e66730e74570d0016e90d42867af9dbd.npy +04090263-ae57975d9461b324d10b86bd6e8bbc34.npy +03001627-f497cbcc4895d5386b684500e5db87c2.npy +02691156-75e9e2d6970f5ee71927c29d6faf370a.npy +03513137-9cdf5e674bf943bf69ed2daa3338779.npy +02992529-cf0dc63412541764cf9d394118de0d0.npy +04379243-26dc6dbcf6b36278ed4893d5d6c77f16.npy +02691156-317ac4d5ff597c9ae719b5362fe06bbb.npy +04379243-94672a37947da258f70bf5700b78659f.npy +04379243-b59753a2c0751e7f37251258858a7a58.npy +04379243-a05d8e55e329df41ca2ed12df13a916a.npy +02933112-37d41aa1ab8e7318534f016fc3878f48.npy +02958343-6d493677c8dfb9d8321338b7ef756ea5.npy +04379243-6d67f5a9d2daec3467ca2ad6571afff.npy +03211117-30e739ed4c65f67ab71158027becbea8.npy +03325088-876f08c390a7528ac36fb70296e45483.npy +04460130-3a1e36329722686c2c406efbeb1811b0.npy +04530566-3f3043e275bac07a6f315eca7454150f.npy +04530566-ea491bbee7524859cfea3d4fc15719ea.npy +03261776-bb2ea6e44847055d59a6208793b9dfca.npy +02876657-d9aee510fd5e8afb93fb5c975e8de2b7.npy +03991062-fe438d5b6303da859f9892433e1b1f4.npy +03001627-6e98c5d61e008b4c2871cc0b3cc1a485.npy +04379243-d1807006e89f9e7c3087f84b199fd297.npy +04379243-dddd611b4262ede6e3b9db784be35882.npy +04379243-32d832455878ef581bf2b66b52bf6885.npy +02691156-e36ce61195489a56c8da6d3458daff84.npy +02691156-bb7d526405e9347b8f6810e1a2b6aa04.npy +02691156-124062ccaeae95085e9e2656aff7dd5b.npy +02924116-7bb582b2e2a587d8481aa8b5531c68a9.npy +02958343-6b2766e55b6de7779d34b5c385de0e34.npy +02691156-ca359fd1ed701d06f119374ee5d5f944.npy +02942699-ee58b922bd93d01be4f112f1b3124b84.npy +03001627-d0a3e48a84f68a9143dbb6421d614c0d.npy +04379243-a0d2754011acdcc9d8a0e410093d6619.npy +02958343-a88c4427e1f0e871d7755e7baabe8a6f.npy +03207941-fba77111f045a448fad3c648a4e3c1dd.npy +03691459-9f43d3116f4162fdce029fab54b6cfbd.npy +02828884-9edc26b719dfbd49121811fcf3127a22.npy +04379243-87c49d4ca6b740d5275d003e423c59ba.npy +02958343-d1dcddb5b1d7404dd9b0c189eb588ce6.npy +02691156-7628e525228e5a2d9a46ec065c01b381.npy +02691156-f8d8b590a0dcd399718ac2a6ddb54499.npy +03001627-5043b2deab10560fc458ea4eb61fea2b.npy +02828884-d9479cb37b782ce5b714422ef873ad34.npy +02691156-7ae99c0cc14cdd97408827f71d73e45a.npy +03797390-37f56901a07da69dac6b8e58caf61f95.npy +04379243-821e6d43a82eadfe8818864c19a17b87.npy +02958343-59c662d403a108d47074a72a1ea2aef2.npy +03211117-db4de4095a962680c951cf8670bfff6.npy +03046257-5c9012a6af482ce01050b055aafa6fb8.npy +03001627-c658d1006595797e301c83e03ee59295.npy +04256520-1685b0cf2d1a2849d0a2ef258a9c71d6.npy +04090263-82c3357fcd007893d17373579e6fd9be.npy +03636649-941271c5d9b192eaccd8f9b9403fd602.npy +04379243-c9ad9501c31fae5c71a782a4379556c7.npy +02933112-93eaa414c043264910a7acb23a71a618.npy +02880940-4845731dbf7522b07492cbf7d8bec255.npy +02924116-93e1e926b47c010c861a6907a2829b07.npy +03001627-87e11c9e61442510b21450114b9ae3a.npy +04379243-604efea445d3f3ab6d322cb027df34ad.npy +03691459-2cb180d4322b8ee9c0d2bd04416ef7c.npy +03001627-66b7533af3449aa820b64028d2efc877.npy +03001627-bd6bc40b3327e5109501f2fa226917d0.npy +02958343-1c4590ebc214e029816bd8f64e08b2bc.npy +03636649-f77abf171ff5968720331d4c3b7d944e.npy +02933112-1ded292e60cf7f11178e7d331e641179.npy +04379243-86996ef1ba6aeacc64558a1c6a2a9f11.npy +04256520-b3fbac6ffe8e00622f6acf89a420ef0c.npy +03991062-e72ed3e25469c682a391a8379ceb19bc.npy +03991062-db9eea0b856faed772652f4081ec5a77.npy +04090263-89a5c8583b2e2306af646833cc36618e.npy +02691156-882b5868ee1382ab1608512333cae245.npy +03001627-3e1a5042dcff313971a782a4379556c7.npy +02691156-541ad6a69f87b134f4c1adce71073351.npy +02691156-ad66ece988a63911643ae903098a314.npy +03207941-1418f648e32f1921df3a1b0d597ce76e.npy +03593526-1666ce5ced647ed25d878ba9ec3c0d6a.npy +04379243-1d42f42755aa3a87b2644d7d4d7ea2c7.npy +02924116-8bf720e46c7f3dc2d27ba3fc43e70958.npy +03593526-434351669b58f5bd438d8caa9ae106fa.npy +02876657-c5032e4be091aabb36fe7a88df793982.npy +04379243-f7e7473775d8c3f3f51fa0238791f5dc.npy +04379243-87dc5ace74ed29fafe43ff1e45af424d.npy +03001627-780b18643b4cdd991df85a93cb67ce5f.npy +04256520-e809c16325be020c795085b4d203932.npy +02933112-b1d8cd17d6c936392caaf8842dbb8ac2.npy +03001627-5eb67ecc35e39eb59753496ba23f2183.npy +03001627-5fa533f71e7e041efebad4f49b26ec52.npy +04379243-42496cee03df8154ac2b62da1791c2b6.npy +04256520-cef25c3f7412814b4b3c42e318f3affc.npy +03046257-e23d73e264608468b5e1005644816d9f.npy +03001627-bf557411c41d07bbb38821f893bc10f9.npy +02958343-f3e467dba61ebb972a84c9dfab949065.npy +04099429-4936716925b1cd6428eba1f0b7744e9.npy +04379243-d6dbb647d85df780615b3e12f53b391d.npy +03691459-137c1194efbdcc1bfa0892265dbce8fd.npy +03046257-929afe0b3ad23608c7b37fe5d21f2385.npy +02876657-c13219fac28e722edd6a2f6a8ecad52d.npy +02876657-7565e6eeee63174757354938178674b.npy +03001627-c2220851bf50eda931ecc34700496180.npy +03938244-d777679b4dd35c76a4136492f17b9a59.npy +02828884-8f824b462a2870fd98e0d1738edd4f19.npy +04530566-93285afc55afb00f6bad0887a204b994.npy +04401088-6693fcd81ce5a4e6f5d789e33b735c9e.npy +02691156-2c1fff0653854166e7a636089598229.npy +04379243-7f5a875b5a2811b07d2313b9cd9e2952.npy +03001627-d4326cd55ed8333f6a059e1fc701f06.npy +03710193-445e18f9f2e42da4e911be944cb8c454.npy +02691156-3c2986906532a1c8cc36f752df32539d.npy +02958343-1f5a6d3c74f32053b6163196882ac0ca.npy +02880940-ab2fd38fc4f37cce86bbb74f0f607cdd.npy +02871439-81b8784259e3331f94cdfc338037bd95.npy +02958343-8bf2d0d0b01f6476c3fe7930fce05ded.npy +04379243-6aae683be40c3a9610c2a68437007d6.npy +02958343-7c13a71834d2b97687cc3b689b9b258d.npy +03001627-2ab4b8a3fe51d2ba1b17743c18fb63dc.npy +02958343-70899bf99412a69db38722563212fa4b.npy +03691459-76cb5a9b7b8dbea99b590f104a4a4c1d.npy +03636649-5614d1c24806ce0a8d1fe8cdc415f4c5.npy +04256520-42ebf2d478ab8af85ac3e286c38c6d66.npy +02958343-783f141774ea26e259d587c4b86a22ea.npy +03211117-44651d91ab8b2851fbff60ddd047b071.npy +03691459-aed2ee05cf37c85c9a8c31231dd99d82.npy +03991062-b4caefc750ad7f9723500a5b036df62e.npy +04379243-56fcca11e3d3a920c1702e8e8263bbd3.npy +03001627-a0c17b34d677907e1f98c0761af40e04.npy +02691156-d722973c75c85d93d0734afa0d357999.npy +02691156-a96c1589731b06a1efbd0f357ff7c40a.npy +03001627-4702e6196503ff84f1c0e03f321d0b20.npy +04379243-d3469cb008d98844902c0a1a69e25bd9.npy +04530566-59a363d3852757572b249fd16295bbfb.npy +03691459-4383b2bbce729356a9c2f34ef56404ef.npy +02876657-73632ddb4a5684503594b3be653e6bff.npy +04530566-2507ed5c9eb161569a704df179502ac7.npy +04379243-acafaecee00323af7ff6ace05b36a5.npy +03636649-e0a2948797cc33b2e19a0cc107ada7cd.npy +04530566-9043c404e310864cd5dfe0108665de88.npy +03001627-6ffbc6f14a7257caffa41024c63fa9db.npy +04379243-e9bbdfed8a39f4cbcb2a965e75be701c.npy +03991062-5b0f71dfbdc8089ca2c59a4d90e63212.npy +04379243-fe0e7198411fc340c057222d6d091c56.npy +02871439-1b35d8bb3a01668f6fa63795f94c4d8c.npy +03948459-383ed236166980209e23d6b6aa619041.npy +03001627-d0782d2afef19adf4733824eae5cd9ae.npy +03001627-bc722985df07090d51c4deb11af7079e.npy +04379243-a5cad9ba5e73ef239b11da89c22111dd.npy +03467517-709a1592b28e8c16489afeb4f07ae3cc.npy +03691459-e7af5657b90b9a73558880eed6ddb84a.npy +03761084-624edb4561b948c1374efba5c7752da1.npy +04256520-df912366bccfcc0258db0ef36af1d3c5.npy +02828884-319c099e8df5fcae2056b4bd5d870b47.npy +02828884-137c82020b8dc458eafa2f074f6cbe37.npy +04379243-98bba4f6837ece036c18e23645ff9868.npy +02958343-9abfdc63aa88be60733269057ed164db.npy +04379243-9098e2c564337b01bde1c279d540fc66.npy +04401088-f9bc179b45d2e5ffc55273be8e22f2c.npy +02808440-398f7f2f78f8794686ecff2582325794.npy +04256520-f12c92ab5f422c07fe5adaeab9475bc5.npy +04379243-51cef4b98624473e193a311b8faf4ace.npy +04379243-d15d37d902d2b8494ca386b8f1ce4c62.npy +04401088-35f584cf8fd22794e4b68d3b17c43658.npy +02958343-5d8476a9aecbbe1e9ec9fbf723f60ac0.npy +02958343-359841936db476cc8cf4cf458d5ff7b.npy +03636649-e94643bd9c777491d49b2e04785f8492.npy +04379243-813d34995b5c4406b65b71636c46ae49.npy +03211117-6fcbee5937d1cf28e5dbcc9343304f4a.npy +04379243-5649e478e7ef25c4490ad276cd2af3a4.npy +02828884-a4491b4a67356be5184c1614f4105c8b.npy +02828884-258a52f3077d3ed56c342cf382162bc7.npy +02933112-920b27c2d3c83a0c59350d819542ec7.npy +04379243-4987ccbc34697b446385bd4c1a835150.npy +02958343-513e2ad82336f56bc0e3666c7d0ec7d0.npy +04379243-5b69a60d7b980b134671d97b0fd17f51.npy +04090263-89f4f2458aa64d94daf2e4c786df29a1.npy +02933112-e3f3d58fe3cd9746a485daf2a997e28.npy +03001627-8cb34663a9e42f95c3bd24f986301745.npy +04379243-e0b333381b21780495e29b6e21e8c291.npy +03325088-c3bb910a7c423f8aa21506405d3c8c76.npy +02691156-97c12e6155fdf8ca90baeef8ba5b93e5.npy +02958343-cf698011f90ac05f253c03b7df20edd5.npy +03759954-e596111d27ca09f043a6722dac94523b.npy +02808440-f7e08b485c7e64bc1fc68ad6ef71f41e.npy +03001627-9961b26d1eb9170e98e0d1738edd4f19.npy +02880940-b007af6eabaa290dd42b9650f19dd425.npy +04379243-ae8f31ba66709b8278cd7885232df677.npy +03467517-64205848fba5d7f74fdc524a49e62393.npy +04090263-bca09e37935082a925ff9d2d1e4772c3.npy +04379243-6b8e579c5178d3e117b431cae0dd70ed.npy +02691156-6baefb84d6e12a0c6bdb424f4ee7ff8b.npy +03046257-5bbaf43f2f86ba638b33d3087add7a4c.npy +04256520-91839305f25521a3fa5b6212657ae4a4.npy +03046257-d5f08d4df09a74b327390fc4fd3ec0cb.npy +04379243-a11b3450e77331367948cb8e1d9ee487.npy +04379243-99686d07d8ced954490ad276cd2af3a4.npy +04090263-5f2f4771bf59c3a32edc45348090e195.npy +02933112-1f6d5268afb826c38b424343280aeccb.npy +03642806-5458437965b3d5da2462e129dafd29fb.npy +03691459-a690234747bb56ceb4767ab55965ebbb.npy +04530566-556a76a5d29e124635952e349f57d.npy +02691156-d4cc520929730248642fa8402286a797.npy +04090263-4b6647ba7664a03198467494eaaa2f8.npy +04379243-97551108bbb5afc36199d6fe090be061.npy +04379243-cca7e05c69a5d8e0a3056fa1e8da3997.npy +03691459-b526ef9f77ce64d398ed31a2f734ab49.npy +02992529-52a81d42c352a903a0eb5a85db887292.npy +03001627-d6f2d44c693d2e857062f2d72cde5c95.npy +04256520-6905206d5f2ac04bd9e0690b0b191.npy +02958343-d4434de782382a47a7e7e5ea49ad8e45.npy +02958343-51f4aebb148459a45fae7711b4095f8.npy +02691156-5f46b24028db58f490baeef8ba5b93e5.npy +03928116-a56bbdcb466fbe47472f0eaae2165f9.npy +04379243-8cc8e16280748c3823fe3501bb9e7193.npy +04530566-99f00898c6b373d5eb2c303a0e0d287b.npy +04256520-8904f205681acc62dd8a663469942954.npy +03001627-e388792a151735e57597e1f94410131a.npy +02933112-cd251287fd34d7e0e3f7a74e12a274ef.npy +04379243-681ee7768f9fa9072c5d34a902e568f9.npy +04530566-70f91186bb61208c56988d12ecb12e06.npy +04256520-86d2aa8a80fd9f38dcdd187a6a5d68ad.npy +04379243-30de7eb171cb381f99e8bf807e902261.npy +02691156-9fb60716f0f5a2b84408eb298433d643.npy +03691459-96904b01dbfa0d0c5865090ad6b0dfd2.npy +03797390-f7d776fd68b126f23b67070c4a034f08.npy +02946921-af444e72a44e6db153c22afefaf6f2a4.npy +04401088-37846d5854ef7da646e4b9487666a2f7.npy +04379243-ea60ea168f766580617092ec6e36103f.npy +03001627-115b11a77b8d8c3c110a27d1d78196.npy +04379243-54b26954e478b1a34ea8d5f5f27d7ce3.npy +02958343-2df4b1797723b140419bf2f84339ec5c.npy +04379243-3c7cf00cd78adaef4b3c42e318f3affc.npy +04256520-6db11b763b7c3e76fd5b2dc3df6521d5.npy +03001627-c605d4742f68a00ece45069973024eb1.npy +04530566-79a13d8bffa87b8ba8ae9698506bed5.npy +04379243-335c2e4c3991768218ed1f44219ab7b1.npy +04090263-19e16b7050b25507d43bb185feff0470.npy +04379243-e724ee5c326ecb9659db00799f9936b2.npy +02958343-d72ffa185738bccd10b75223b5be6dbb.npy +04379243-47a381f4ed3d30614187eeeb0dea4986.npy +04379243-aa54c2e6850253ffe08dd63aa50202d.npy +04256520-ece6da595e7754b3eb0f7c4d37fcbed7.npy +03001627-df8374d8f3563be8f1783a44a88d6274.npy +03001627-3a8b5f5a627bb2e199b439fff97886d6.npy +03325088-30316a92178da5683321831d2245cf06.npy +02808440-47b337a43af4d557b8724a732b3d4cc1.npy +04256520-99d036d409c1fc366f12b402757e5b72.npy +02691156-c494f446954523a8a32748a9f843a0bf.npy +02958343-936702a0367e95185b03bc28c642bc.npy +03001627-63e6c50e5435e35d822a33e080d0e71c.npy +03636649-e8350583c84b5e6731ae8c8ff1eb3d45.npy +04379243-c2679e65b9d5e95de6fd255f2d77a585.npy +03001627-1d0abb4d48b46e3f492d9da2668ec34c.npy +02691156-bb785567f73903da2661ac6da30aefd.npy +04379243-2c730735f7f3e60f848ac41b30fbbc29.npy +04256520-aa27de991298fb2eb3a010e5a9dcf3a8.npy +02876657-84bc4006535545fad2986c98896facaa.npy +03624134-ceb3b39c9a035752b4fc059d1d10ec5d.npy +02808440-a2e7bff47380868e6b37e99dfd7a802f.npy +04379243-ec6de49b6fee801a4b3c42e318f3affc.npy +04379243-ed1e06e886b5514fe8f49d7c9e73ab9.npy +03636649-9f09619002ab4d76f42a90fe4baf4591.npy +03636649-a5bfb9a3571e7e86e59f529cd1b6faa8.npy +03636649-97e63c1f813cb1926f43c7673a499bbc.npy +04530566-81a7b820899ccbf15ddefb7321dceac0.npy +02691156-1890f6391df25286394b1e418d5c594.npy +04530566-ba62a620689a976f721c8a4254856c86.npy +03325088-ccd1a028cc366882b362845c6edb57fc.npy +04379243-119819c15bec2e1e299457639cc3cfe3.npy +03938244-121f2fa5ec7a7db47df4feb40f08ca17.npy +04090263-b77b49b9bd84123140385522d1beeb20.npy +03001627-326f74afbed5d727da8b0c70313fbbae.npy +03761084-684b0477a4ffae9f92b1088bf3ddce02.npy +04004475-df443a41d3b4f092d5805a1d6e49bc4e.npy +04090263-4301f958c305ddfda1b7cf86a93141b4.npy +04256520-a9a8156722fa81dcbc36ee6cb276b00a.npy +04256520-4373d31c2ac1d0bc57278947e7c4dc7.npy +03928116-9ebbdc0d84ffb0039edb2d87f2bf300b.npy +03001627-88dda281b3dddd57517c7e27988bea5f.npy +04379243-54598a1cc5f389ffbeb83c64f2162734.npy +04379243-6be2058f02beb0569699d7bc7fedec1c.npy +04256520-3f1af655a7e3ee57b838ce7eb80b48a.npy +02933112-54dfbf6333cf06dd652b6926f989dd09.npy +02691156-8c3419a655600e5766cf1b4a8fc3914e.npy +02958343-e13ea26b1b229e74bbc8d784a25de148.npy +02828884-eb06da40812adaa9542357877f3143f8.npy +04090263-3e0b251299b8696592cea77f96988ae6.npy +02958343-6f793e0f29f6b0b4da82e7357e8ee170.npy +04379243-74e9d9cd7b3d632a504721639e19f609.npy +03790512-5131b742dad94f6175dadc997718614d.npy +02773838-83ab18386e87bf4efef598dabc93c115.npy +04379243-dc47d49db6ac670635d498476a30ff0e.npy +02808440-ff507a7e1febf2ea3321831d2245cf06.npy +03046257-6d193b1a63e7f617977a52409ec6c456.npy +04379243-d528d80f04f387fea570c6c691c987a8.npy +04401088-dd02413772656bf5f6cc8d1cc08b421.npy +04379243-70a4cc63977d8eb018d385624fdfc6d0.npy +03001627-bf8004c0d88210a291efd008fb89dc2f.npy +03948459-9647b6b16b7744e67b1ee883bfd9155b.npy +04330267-1b625db2af8c02b04253be890e153964.npy +03467517-2cbc0faddf227502bbc745a3524d966b.npy +02691156-f144e93fe2a11c1f4c3a35cee92bb95b.npy +04379243-155599b6ab61a872f51f77a6d7299806.npy +02924116-358ea149995d8b826ca2b6e5474aad11.npy +04401088-d5fd6679ddfc8ddc59f56ab706e2f74c.npy +03636649-370ff00dc6f08167c3bd24f986301745.npy +02747177-1ce689a5c781af1bcf01bc59d215f0.npy +03790512-ee0a3213a08a23d27d2d874548544c4e.npy +03928116-3696bdc9797130c56599aae9284a50cb.npy +02828884-756108c9b72e95aa57d85583f4ad07cf.npy +02933112-4d0ee9779956b74490a9ce3e4b15521e.npy +03691459-59455b5c509a7e9efe96ea0860283ff8.npy +04379243-97a137cc6688a07c90a9ce3e4b15521e.npy +04379243-61d5c19a08b3f4a9b3dfbaddaa1a935c.npy +03001627-3d988ea2b68f48c7492d9da2668ec34c.npy +03467517-d2938be9fd0a6cd340c20797381ee39f.npy +02691156-c46336844aa275098b96ae1a0a8b84ec.npy +04256520-4d251436236babb87189b31b3e8c8ef3.npy +03001627-1b90394dae690dddb53be07817c1dd99.npy +04256520-201a6507d261c9113847ce0a45864e80.npy +03001627-b251886df47a873eede14860b165d604.npy +04379243-68b5f18b0790e9e128ffacc8063f0f75.npy +02828884-1c79aa69e4ec26b65dc236dd32108e81.npy +04256520-fe591a1cfbb6219afebad4f49b26ec52.npy +03691459-e47b83b94a1956ad7a16fcc398700938.npy +04379243-525b2042bd4547fd7ef440dbce8c5be5.npy +03046257-237b0f3acdd0b69bd4bf7024dfa167d.npy +02933112-839393d59ef6c8cfc59350d819542ec7.npy +04401088-f7fcc773249429a2761eb63018291094.npy +03046257-b2b40e80c9d3f530d5f1db12f95f0fe4.npy +04379243-e731ffc67b03d0555f46d55537192b6.npy +03325088-23fb74a31fcbf2b6b362845c6edb57fc.npy +04256520-39b29bb4fd8140ac9829306a513f9466.npy +02924116-83efc266d8e8ec03fac5a1e8b1475766.npy +02808440-9eca0331d9e89d5bc3035ab7747ce27a.npy +02958343-aff67f837a958d2329984c4afd2e98a4.npy +03593526-14ac8d866a8ea8b398910e50f05b8001.npy +04379243-5e96ddc94f51f99d2165c54dcecaacb4.npy +03593526-49a97b1ceaee4a15525b133235812833.npy +04256520-9ea95280cf81f9c5c151419181ef256.npy +03001627-9d6fdcf7fd47fb5af22166a43d725fc9.npy +03325088-902a12f98b7d0b1a76c18e71fd49c4dc.npy +03636649-2b7eaa54eba94f34502b0796fdf972.npy +04379243-537e9f07962478412de1f397a20604d2.npy +02828884-6d1883ed7f0cec103023dc1d1218bb2d.npy +02933112-3b98711b877ae402824662341ce2b233.npy +04256520-5d382ebe0f2ab55efefccbce7fd86667.npy +03001627-d32fafb61e1e4a5bb0d5741be7de64b1.npy +04379243-ac40c46401406b71d9c36c82d746b699.npy +03691459-48a2091454502770408d050f12518231.npy +02933112-3e662f9afbe62838f0f8b2d752b1c7a1.npy +02801938-1f6046149060eb81cbde89e0c48a01bf.npy +02933112-9990d6c43d95c521c4df475ad1a6d009.npy +04256520-b228fe3ec218f2b7fd609f4a869e9831.npy +03691459-43730d7a76ea63f920363e2561dd589a.npy +02958343-c17e88a6b0267754c6529edfd0032791.npy +02958343-bad0a52f07afc2319ed410a010efa019.npy +02828884-cd49cc9aa0377a298fb953ed1ae534fa.npy +04256520-f4526b250d9ba847a1d83e910853d9db.npy +04090263-176b7637e807853d34ad43a472bf958.npy +03001627-a63ceaceaaae4af9753496ba23f2183.npy +04379243-6c6aaa451538a8ed6ec2cd9a23ae5af9.npy +03001627-6634fdee517153e7e8523833000f615.npy +02691156-c61f67c3f03b10537f3efc94c2d31dc5.npy +03928116-bb551a5c33e3743297a999e2367a4a2d.npy +04379243-695639f21a7995f592d5b25c536d8044.npy +02691156-8951b4f9834869a6673a028ac04b7de3.npy +03001627-eb23621d7ac1094398e0d1738edd4f19.npy +02992529-2c32c1b5d13074431c1943a82a09125f.npy +02691156-cc1e143cf7da051a6a6dc7e2bbcd098.npy +04379243-c139948ad09b042991a3d45e8887248a.npy +02946921-95ca52eaf8010a004cfa3ec30cb9847f.npy +02958343-e042d636cfca46f56436916a86a90ed7.npy +03325088-36e4eaad0530977a3c8d0fdfb1cc2535.npy +02691156-79e924263f903feb35fc197bbabcd5bd.npy +03624134-ce07e9a3b66742926cb0c1a2f69481e6.npy +04256520-9e3fd54c2e7dc4204b19d2c99e22ffe0.npy +04379243-913d774c845a0d7edc889d1ef9591d24.npy +04379243-8cf448cafd11acee84d4c0ff7581c569.npy +02691156-b26c50c3dd4a1cbb16b34c3751bc447d.npy +03337140-8c46c51995853d384c3aee8e9d3a6ffa.npy +02691156-e216667457193c729a6e43b878d5b335.npy +04379243-2ff9f572b715e86b1cfb6a573ef73942.npy +04379243-b69b6e09d5f5bc1f21ef666e979e4e80.npy +04379243-1c66f97bf8375052c13e020d985215e3.npy +03593526-a16e051fe5507ae2396ca3dd50467ab.npy +04256520-e6e2ed3f41a3eb951197663c308adec2.npy +03001627-bcc4ea0133864bfe4d4c0769270d8651.npy +03991062-a7bdcdf20b7e5ce7a2c59a4d90e63212.npy +04379243-45970e6048cadb39691e5fa75e122ce.npy +04379243-f361b2c70470eb71b71df3a52d67a993.npy +02876657-e9371d3abbb3bb7265bca0cae1ecfff5.npy +03790512-867e3e502de5cc0dd5dde04c96fd8146.npy +02933112-b74f87f4d4c7da7343638dabe1eb5336.npy +02958343-ea954837920f94e6f58ff156bb8fae0c.npy +04379243-8839cf79a5338a568ce66f12ba927a2b.npy +03001627-b80122c3a0543a7b7eaeab1f0c9120b7.npy +02958343-6482b8e8c8516a3b473f10e6caaeca56.npy +02924116-58b46b4dbf019171b4c69692992c7aeb.npy +04004475-94b56634065b6b4471df0fdd633b5540.npy +04530566-8b0d1cd6731593974543d90faa1260e8.npy +02933112-d4be807e568ae84d7b386db5665a1b3.npy +04090263-ef46f9c14bcb69193a3a90ed08de76ea.npy +04256520-9695e057d7a4e992f2b67ae827b02632.npy +03991062-dd92bd3e7c865023b3357f2f0418422d.npy +04090263-9751e6d0a0d6c1919c82b3f5ddca589c.npy +04379243-96db71d279b97c4ae02c30c9027468fb.npy +03991062-1c28000ccaa92ef72f5989acbfd15191.npy +04401088-271bc457eb5f8f4d2bcf2225e929a245.npy +03001627-7b2d8c9f611071c7d810b14a81e12eca.npy +02828884-38ea17d177c4e872fd07832c54eb7e78.npy +02933112-3891210a28be585fb9ac96152ab66583.npy +02691156-edc9fefa5fb82a0443a0c73d98327de8.npy +03636649-3330789450af921544fe3ba945082ada.npy +04530566-19a72473173bf26ff7bc9a344bb7bae5.npy +03624134-84ca0624075af918cc34b900bb2492e.npy +03211117-f8c22e6011567f655dee408cc1ce3ebd.npy +04090263-89c1d5cf1ceb8a81c8b8e03401520eba.npy +04401088-97e214d6b93e012f6337fbfda5096043.npy +02880940-c8a4719150446e84664b3b9b23ddfcbc.npy +04401088-6710c7894efe94cb918f30c146a92bd0.npy +02691156-c8dcaeda94da8da962b600da24e0965.npy +03001627-7051b028c8c1facfced9bf2a92246703.npy +04468005-582501051c6fb18a4c695bfe6fa2baf7.npy +04256520-dc35836a8c5bbdc919fb4103277a6b93.npy +03337140-c1aee431269eb53191c352d02061b3f7.npy +02828884-3e4f4c54420bdcae75becd8a4c3f1866.npy +02933112-4e33ef381f5be0e165b61ce1124a4806.npy +02871439-cfea3a81c83c30e775ece18553078e31.npy +04554684-b04403b592cf3516df3a1b0d597ce76e.npy +03001627-6e7455e21a6668a7f51f77a6d7299806.npy +04379243-9d039675f4d51869f3edd695842c6d58.npy +04090263-96023028ba4ec62b65b14b263bdb456e.npy +02958343-4fd6fe1f81a83dcee6513d84422cefc4.npy +04401088-1d390d2560fc259336eb9fe355d50fdf.npy +03948459-7afbd8e91df4282f1b5391e37ae81402.npy +02958343-e4b5734836d9519aa8a84951596cc1.npy +02942699-a3c9dcaada9e04d09061da204e7c463c.npy +02876657-b38eb308649c8c5de7de92adde5735ef.npy +02880940-9ea66797afeb86196ea1c514a0de6d2d.npy +02958343-9c65624c5d94aa29801b0db1d49ea10c.npy +03337140-5479c44349a3dbb4823b9dbfda3facc5.npy +02880940-3bedfd655c45c6747bc26b16f550876f.npy +04256520-98b6c00c4fa346cd187ccdd3303d9e5a.npy +02880940-d2e1dc9ee02834c71621c7edb823fc53.npy +02828884-696697545f8c8b9ff26d8e17374f38e2.npy +04379243-fc64a8a31f30ab8bb780b07b76df3b4a.npy +02958343-1dc757e77f3cfad0253c03b7df20edd5.npy +03001627-38ff18330fd5aace162bf7725b3fab02.npy +02924116-aedb07b6ad73e3b759a2046f98794106.npy +04256520-d20569519e7920bc38cb7d8503a3164.npy +04379243-dc3167808a79ebe24a1806c17996a001.npy +04530566-d77beeb2abffd0818a6b641df8a0d183.npy +04379243-f74c321042dbc8e684d78f017ff73fd6.npy +02958343-fd765ab34e7907db186bed5098d348af.npy +02691156-2cc44e0f9fb1efdb85e0a2007a11e92f.npy +02828884-127dcb2e061ae07f155d75bbf62b80.npy +04256520-9d1886cd5aebab3019fb4103277a6b93.npy +04379243-65ad913e23eec800cea003eff0268278.npy +04090263-428eadf77b50d6a6cfe6670bda9305bc.npy +03797390-edaf960fb6afdadc4cebc4b5998de5d0.npy +04379243-b1835f603e1477f61b50574ebd76a45b.npy +04554684-3a289ed95f5902fb46cde67a6a1ea328.npy +04530566-677ffbc1ee40a0a0db5a9ea3574bb285.npy +04379243-1c7d7b6754dccba230bbd4cddd04c77b.npy +04090263-cb35c8f7c723d041916965fb9c37252a.npy +03001627-19ee0ca97ed377fb69fffd0daafdccbc.npy +03337140-df26b9e9e3c642e0e7ecdbe73ef4323c.npy +03001627-7f11908f7ea9483c415dbfd895473b4f.npy +03691459-5ec12b34a69e34d9c85671f86a50354e.npy +04379243-d1e01c36346b4b839abebb636ba42f4.npy +02958343-e66bbdf57fa6f7f575f257e5fe0a71cb.npy +04379243-d9c11381adf0cf48f1783a44a88d6274.npy +03001627-383a9a2c39332f7f50eb11cb3709022.npy +03691459-b7c92dfdd563ffc74533f2e74542acda.npy +02691156-91d3479f5da120a9b4d73e4449062b04.npy +03467517-b58facaf0086786090794f393d445340.npy +02871439-f61465baa4c1c36de6089046407cf8f2.npy +03211117-ad3e62240370a4eab2c358fd992922e6.npy +04379243-6cadd91f66569c584f60f15da4c665d0.npy +04379243-d60166dbf522deccdc8726953f344666.npy +02691156-ae3556f7151098b0f64801ad2940cdd5.npy +03624134-38798b7013607bbf1e0b76f10c6e38af.npy +03691459-619442d40cba1f667a964feaf6ebeb.npy +04256520-781ef644347280bcce59ea70152320fa.npy +04379243-165e579c965b215b43dbb6421d614c0d.npy +04256520-9c18d53831315667af78305d7f7113c.npy +04256520-b9ab5b0ba01f4d896ae963205db1109f.npy +03001627-acbc30795b9826ec283b00891f680579.npy +02992529-5e485b1ae058fc11b26a5d88c8b02ed9.npy +03642806-17069b6604fc28bfa2f5beb253216d5b.npy +04530566-316d5a8e671fadf3a7fe2e170d12322d.npy +02958343-b3ffbbb2e8a5376d4ed9aac513001a31.npy +03001627-50477d125025879386855a8015309d66.npy +04090263-d0987a5b6c5c6118143bcc14d754d44d.npy +03991062-802f4afe1388b7b0ebe67d9b32c3ddf8.npy +02691156-3a54f2b6f9b053b759b859405dee3be8.npy +04099429-64803bab9799d0e698d2d2b2ae2563b0.npy +03691459-51b745123abc098c10198e93f73dfd5d.npy +03001627-51c8f249e778e84a5bae8923b29985ad.npy +04379243-5ba34bb2440aa2b917b431cae0dd70ed.npy +03001627-bbab666132885a14ea96899baeb81e22.npy +04379243-ae1a7b7c3ec72178b848d7d3af8eb610.npy +04090263-6e3239e448539dd25c351e299b24e355.npy +02691156-d45772f938d14d52736e55e9ba083986.npy +03001627-4c3f452cd60df0efb0957d845ac33749.npy +03001627-f0337929bdf10321d22730b0728b2fc9.npy +03001627-1e9004958eb935b2ef2777c7d8e09db2.npy +02924116-7b981340ba0b243ed7b025993d18028f.npy +02958343-330645ba272910524376d2685f42f96f.npy +02691156-515b1b36d9f7721a903a13c314c66013.npy +02828884-c0336b0471ca232bf155d75bbf62b80.npy +04379243-d27130df514414d1d8c46a3a266762d7.npy +03001627-c7da13238eb4a7e15128da2cbe23f6a.npy +03046257-9c9e80c64d5ab227d5f1e32336840b07.npy +04530566-141b2e976df2d4ed4ccd729f8bcb378.npy +04256520-d5aefefca08da17819fb4103277a6b93.npy +02958343-167ec61fc29df46460593c98e3e63028.npy +02691156-aeb538b2f1c36a8d9e811b082458229e.npy +03211117-1d1cd29446bff16090adfc5ef6476a6e.npy +02808440-e1133d232c5fd7993321831d2245cf06.npy +02691156-33ddbeb13fecf7868405970680284869.npy +03001627-4a0b61d33846824ab1f04c301b6ccc90.npy +02747177-4088f2056763a95752e986a5f722a6f.npy +02958343-19d0843797b8b2216abce8cb03e7794.npy +03991062-52de37a011a32c2fa2c59a4d90e63212.npy +02933112-7e6c0a7c630cce1d4702663c3b3faf8f.npy +03691459-882154aab31d483e130bc0755682f7f3.npy +03046257-1948275d99403353d7bf6fb68df7f786.npy +02933112-c18a4772bcfbb98e85bc264270ae0601.npy +03790512-9453199691f58147429f1c522640e6f0.npy +02933112-d209aaa7fd4035a34c7384dbb75cab0d.npy +04379243-913c38e7faa82c984a62fa5dd236505b.npy +02992529-9dc0c2ca8de18e28b4c18e3209e12990.npy +04090263-e5a2a579e54cf1bad87c63d8b3018b58.npy +02691156-20b6bc7d69902db4d3ccdbb72feef61f.npy +02933112-a0eb46b125a99e26473aef508bd8614e.npy +03001627-fb8b45151900e6e016a0c57b9ceb6d01.npy +02958343-1b2ef0809ca1abc7ca92a4cdad802b45.npy +02933112-14590b6bdb425e80d8986c3ed6c52fe2.npy +04379243-385f8323f5051b85f2c48e2288633251.npy +02876657-546111e6869f41aca577e3e5353dd356.npy +04379243-f1252c297d7ad9a47c51ec7d2716b33d.npy +02876657-b71afc7791d18eabc573899ac6ab82e4.npy +03948459-5a36e7861e4f414163e7abbde5e6b2db.npy +02808440-f033e6bfaf0c41963321831d2245cf06.npy +02818832-82df8acd0effeb9faf31209a7c3f5c4.npy +03001627-78779361a406474db516c05d046e8e45.npy +03046257-c39cf8d87c6cdb5a3339d8259ddfa7bb.npy +03593526-6bfcacdff00d57c633774da3deff863.npy +03046257-b972dcd268517c5df51f77a6d7299806.npy +04379243-6f58b8c1d826a301a97bcacc05204e5c.npy +03001627-18bf93e893e4069e4b3c42e318f3affc.npy +04401088-325ecc3acd232a5e981b9cd34407d026.npy +04379243-fe9d363792ee708b35836c728d324152.npy +02942699-ee0f44a37e50eda2a39b1d7ef8834b0.npy +03001627-602b7217c42d3d365eead856a4605937.npy +02924116-c8f079359109f462c6bf3b18b8ca71a.npy +04468005-1af852e72c44954b8bd91d7cadd7c123.npy +02958343-d838c8cb52c92df3b112e5ac235c21b7.npy +03046257-bd3924dc45097f029ba80f08c401fbed.npy +03790512-8521276f8a6df852c83b248a54afdeb1.npy +04090263-17577c2cbdb7c916642f87788fdb63a7.npy +04379243-241ea467140a03a1e015e8084a32eed1.npy +04379243-9c12baa3337390578592b396b177b348.npy +02933112-4bda28b19b2f6f865cd4f7d5b0608a.npy +04379243-56e00d6764a7205fa9fe1734a6086750.npy +04379243-8bf421d191e4908bb8fa4cb65e077db1.npy +03948459-a0a1633186261a031274aa253a241db2.npy +03636649-99efb45cf927a0c62cd2160e449d45ae.npy +03691459-ffd168e54f722339ef94793a67b4c5c0.npy +04379243-86604589a588bfbd98cfd47a860803c5.npy +04379243-7f1bd688960e2c1b97f2016c3d6097c9.npy +03001627-34160b90f6abd883c731e4cb72d7c0af.npy +04004475-1eb6bc4d41f19e07c29432ec481a60b1.npy +04256520-d2964213849329b494887ea54f3cfb87.npy +03948459-39105892cc0b553753e0a70586b5c8af.npy +02747177-8a321a0750972afff155d75bbf62b80.npy +04379243-e1a8e9e2059f4792fbb8cbddab1c2002.npy +04256520-ebc8467a8de995924b3c42e318f3affc.npy +03948459-34eb31e5ac8802246f2614b47f532d63.npy +02691156-f8bc6483dd3c87085df50a69f2f8e096.npy +04401088-959975a60ae104c48780444eaa02106b.npy +02691156-788cd4e599b0ca1819ba010ddb4974fe.npy +04401088-ed9149921b734b2941edb96d309c9a23.npy +02871439-fbc6b4e0aa9cc13d713e7f5d7ea85661.npy +04379243-135f9b1fb72e16d0dcf4cc877ea9b3ab.npy +04090263-2d5208bb08d89bf9a3e2fa8a8e389f2.npy +03211117-2c5b951b726b7672c137fd38f49b032c.npy +04379243-f511c1d4356a6a7ac0a61ad1cf92b694.npy +02691156-4e85ef428689df5cede07437dedab44.npy +02871439-d438f761339ebf6db2ac45db35c175.npy +02691156-ebd96d07a7d68cf2fc7b6f7beb3a27ff.npy +02691156-33fff5b8d113cca41b950a59358e57bd.npy +03325088-e4e3ed7621c9b135b362845c6edb57fc.npy +03046257-59ba9701544bcbe167944f5aabc774fc.npy +03211117-e58344689760e33158aeac7d536d442b.npy +02958343-7887e8306742cf844ca84d60642ec7e8.npy +04379243-e7655dfef36db9908c31ab4d97f0b44.npy +04379243-2fca68e0ce294506fe3e90bc90e90c63.npy +04379243-9f9d8c3acc3d33e628c187222995b2b5.npy +02871439-cfda7e588ae6c925ff1830d863863fa1.npy +03325088-66b11d49e1b91a7438dd26a27be095eb.npy +02691156-669060a91dc45dfd2ede7237ec38a80.npy +02843684-9d4da019570ea9748d438032a8fe6ff6.npy +04379243-7f14110c96ee2cf6afa167a727ddfb67.npy +04460130-8956ecd996dc60af97802b1c3f15658f.npy +04379243-ba73c0ea2797bded8adb98ef1d9443ba.npy +04090263-ba789d3b971e4095e2bb19fbad3e4596.npy +02691156-e761cf88524cf8f24c3a35cee92bb95b.npy +03001627-7e6b4a7b4dd60c40cc8bd7a04c9659f1.npy +04256520-68712432581f8a855739643afbd8c926.npy +04090263-5ed0e0b4d26a30fbd8990f79240f3290.npy +04379243-d1494e0665f06507b79de6fdd84b2221.npy +03001627-92e6546c4aca4ed14b96b665a8ac321.npy +02958343-3586f47af775e5158aa8c3cca6f13406.npy +02992529-9efabcf2ff8a4be9a59562d67b11f3d.npy +02691156-f6e6bab105ab890080be894a49cc4571.npy +04379243-f9ca8f7549af695a5aad165050e534c.npy +02691156-daf0298bbe90dff19751c7a6f15617f4.npy +04379243-186e501aa015cd367f768772b7a990fa.npy +03624134-1be1aa66cd8674184e09ebaf49b0cb2f.npy +04379243-18fef71ad80139a2af02521b7ec8a38e.npy +04530566-c6ef6b859205ab53609e2d916fa0da27.npy +04530566-b91a01dfd51d615b4f84436cd4bc7d29.npy +04256520-6336e1ec8679ae5c512941e37c7d7dd6.npy +02691156-8af65c495c966cd7c337e45399cf632.npy +03001627-675c6c0c5c9a4a8a3bad033fffa5c327.npy +03001627-238cd4b409ad9951f1d6726679b21945.npy +04256520-374c336ccd894dca717b2a5841d92.npy +02958343-d6786ef05af6127d58e7058c5c570964.npy +04379243-efc9a32719fc71962c95e86abe3e6416.npy +04256520-94728591e785c00278fe949fc1419876.npy +04256520-fb65fdcded332e4118039d66c0209ecb.npy +03513137-366a517ee3a9aa3db4c1516b11b344e0.npy +03001627-e0311d577cff9d85f6ea7461c0aa61c3.npy +02958343-1abeca7159db7ed9f200a72c9245aee7.npy +04090263-2b22712b66d3f1d7fa9286f039319ff7.npy +03467517-65e3bdc247b3ce3d4de904d1abbce016.npy +04256520-2efc425b95430055f7406d785bf36110.npy +03691459-ada2311f4edda41478108236e982c2f2.npy +02992529-5a7e19fca06d2bb7f2848e928a160066.npy +03211117-d8142f27c166cc21f103e4fb531505b4.npy +02801938-9b8db1890e6b74d430c7810cba6da248.npy +04256520-213484c5675cc80b4719088c8e42c6ab.npy +04090263-57337a97460a63129d5aeb7097eddbda.npy +03636649-b2d5929e66044aeac7db9c21ccfbc4a1.npy +04379243-fe4bcffc64838402684b7bc3f8a9aa55.npy +03325088-7219dec616569e833321831d2245cf06.npy +03001627-1de49c5853d04e863c8d0fdfb1cc2535.npy +04530566-e7bd994999e1d6d87ad17faf524063ac.npy +03467517-d2ad57f36e00c602baba3b7560fe62f4.npy +02958343-27e267f0570f121869a949ac99a843c4.npy +02691156-b590adb6d3486f6e90b1d6deb98feec6.npy +03001627-bec78ebd204764f637a0eda928b574d2.npy +02992529-8ea08c4be8f2f96095f577622f465c85.npy +04256520-411444708e41ec314b3c42e318f3affc.npy +03001627-bc6ca247b19398b89c7dd675565aedce.npy +03691459-d3a872834cd0aa94d77ea5e1afa5bfe6.npy +02828884-31846b186cddba04554672356b2029e9.npy +03928116-b896fde9d5fa81c4d0fb5e8be7de90c4.npy +02691156-42b71c3f82a845574c3a35cee92bb95b.npy +02876657-807f781ec8310baaa2e58dbee8c64797.npy +02691156-9f525ad90573de3dccc19f6800e20c43.npy +03261776-9790b84ae96e498d09efdd367bd2d59.npy +02828884-4ba13b996d6f1d3b286ea987ad5ffa18.npy +02958343-82bd66a7ffcb351c1527e35a652f449.npy +02808440-539296c36596f6d3b805ea9e53402739.npy +04379243-85f2fc137f3c7e57a19748ad08476c18.npy +03991062-b251cff600d748103918c3b319764298.npy +03001627-5c4c50c0a987f8c2d9789e40093c1324.npy +04256520-944842d74aad4e2617b431cae0dd70ed.npy +03991062-490e2e25da735cfd3df324363ca0723f.npy +03001627-2608335ef22bcee1c97114870bb573.npy +04468005-d2e368bd92b5180fa68662d570e5f2cd.npy +03211117-d061d2b6c934d0cc8b4b5227fac4401.npy +04379243-2b7b66623a00dd8b78838533e331d3cf.npy +02691156-c9f91acaeea4136f2863c6a2c8157d17.npy +04468005-8948aeb6b31b62bec3d4460f3366687.npy +04379243-7671a315e8ab32f4664b3b9b23ddfcbc.npy +04379243-10139657dfa9afe0c3bd24f986301745.npy +02691156-4cb1c851d4333d1c4c3a35cee92bb95b.npy +02924116-997db64d612406994b525b3ec330a8c9.npy +03001627-c4af5a5858b4f40082db9fca4b68095.npy +04554684-99871b9c854889ba5cb3e2021047f79e.npy +03636649-3b90765f78db34cdb827dc66c75bf2d5.npy +04379243-263e097a29c520c717b431cae0dd70ed.npy +02958343-a4fc879c642e8fc4a5a4c80d90b70728.npy +03642806-ef5b312fc20f1b20aab089a6db538ba7.npy +03636649-4521282bd4550113a5f600ed2cf472ac.npy +02691156-4cee36a2e8dd3b24b87697d3904b168b.npy +04379243-1abfb0c03c81fc2219fb4103277a6b93.npy +03046257-3521751471b748ff2846fa729d90e125.npy +04468005-e71a412203c7d783ddd78f4c842acf97.npy +03467517-4ad5927ac53f3660a1f7bd4770762353.npy +04379243-893d3871e46b18f79b11da89c22111dd.npy +04468005-d10cd54d59b35abd52470de2774d6099.npy +02992529-864e5512dd35164b2d477e233bc97afe.npy +03001627-e6355bbd9aad146a149098a193698017.npy +03636649-1e62d260a8a64b5d8f720345751070e9.npy +02924116-1005d0f6134d4afb69c93024dedae1a3.npy +02958343-7dac31838b627748eb631ba05bd8dfe.npy +04379243-d679b6e72d6c0ead391e4d6c585a697a.npy +02691156-3f3cd5461f7ec6edfa8a0c9a1860ff01.npy +03001627-4e1c6dd1146ba848f71f1345a68ed387.npy +03636649-5e2d2a5b9a69125b23c3accd4496ea68.npy +02958343-a476444d87bc7aeb1699b1ed8dbb7ad7.npy +04379243-3bc7c7450991737c36b0f2a1430e993a.npy +02691156-121e9fceb90440efed79d3bd546890bd.npy +04256520-7d8fde70f5c3f351567232766992241d.npy +04379243-dae4f6f734088c4de3a031805ace4a99.npy +04379243-11cf749cd0a65ca13339d8259ddfa7bb.npy +04379243-287f1318fd5e282a185574a5e2255bb6.npy +02818832-68df37a4bdb83f7c03cd8f7413e947b.npy +02958343-2131d5bcea38ce3a68bdb39538968e8e.npy +02691156-142acab4424009a123fc69eefd95e6d3.npy +04554684-46749d40640967a94b77d9f59f49ab0.npy +03207941-7d4a04196d3b8eba7984fb9ec7e40829.npy +04379243-35a65ddfe8690ccfbc96558434dabb4.npy +04530566-884454f0d5a376c295ea46728bcdc15d.npy +02958343-2650ad9e7a1d0ebf6df8cb2765f8ec95.npy +03001627-f2c1f929f451753de4ee93147efa8cb1.npy +04401088-c1077972752aac54e8deab000196f61d.npy +04379243-fc93d1a1476e4f86309c518184dfbf58.npy +02691156-5785c8651893ca6b7209009cfb89d4bd.npy +02876657-29b6f9c7ae76847e763c517ce709a8cc.npy +02691156-fc0dbd045c9391ce4a29fef5d2b2f3d7.npy +02747177-e5b7b5112e396a49b581cc9c4410f841.npy +02828884-6b4e4125c1a680cd2cc92e3c03668ea8.npy +04530566-215861c4bebeb328d9a75de54b023ae1.npy +03001627-1fd7d0fe883059e355feea066cda8f9a.npy +02747177-c904d927672acd48ad8a0ee9b106700e.npy +03001627-3baacc59dc30783a524dd35a546a4c2b.npy +02933112-22d10cc8165d310a15dd7d7985e749c1.npy +02691156-b1998932482a6215a9b2becd26dc2fc1.npy +03046257-5d47a83ce211f6a331387b9bbb0e1fa3.npy +04379243-f5b682cabede450d1191025061735ea3.npy +03001627-225891ce27478eec54e404e041bdecdd.npy +02691156-30b9882d1d75be3537678474be485ca.npy +04401088-937b3450c8976f3393078ad6013586e7.npy +03790512-eee947c35691b7d12279b76b11a9a16c.npy +04256520-e0b897af3eee5ec8d8ac5d7ad0953104.npy +03001627-a9a1147eae9936f76f1e07a56c129dfc.npy +04256520-60bca735b8dc8e487c4364ecff196aea.npy +03593526-cbca5373309e5e192396ca3dd50467ab.npy +02933112-c4d17b681e7f3d8a1e1f137e13140387.npy +04256520-f97cb4e2aed44b05593ebeeedbff73b.npy +03001627-f2dd3bc7d6c85a8f2813aa30be7ebdbc.npy +04530566-3e97094bc123e370be7ca2216dc1576a.npy +04468005-c56d3442d937eddb796ef482cb4dcf22.npy +04379243-33005098444c222b2b70eac6546e93fd.npy +03636649-20e4c5b5783eb950490ad276cd2af3a4.npy +03797390-54f2d6a0b431839c99785666a0fe0255.npy +03797390-eecb13f61a93b4048f58d8b19de93f99.npy +04256520-923e063599dc9ac7679edf1f9e4dc0a7.npy +03593526-5cf4d1f50bc8b27517b73b4b5f74e5b2.npy +03467517-5d6c1516b83dec8663e148e250c0340d.npy +03636649-a3ff2bc2ac65bf093aa7852a81a014bb.npy +03691459-a234d7b21f06dc58d77ea5e1afa5bfe6.npy +03636649-aea8305fcfd8a1d2ff0b82a28078fd3.npy +02691156-ffccda82ecc0d0f71740529c616cd4c7.npy +04379243-bb00ad069df73df5d1f943907d4f35fc.npy +04090263-98882aaa0d1b597127aebc12b787c594.npy +02958343-6af177bc78ee06a0e8acba6ad3725ca8.npy +03642806-1f8338b068279743f8267dd94d223348.npy +04468005-90fb6c97ceb13cd67b9bb226efd81df.npy +02691156-42b464affaa4b3f985e0a2007a11e92f.npy +04256520-f6dd2e82ae1f5f8d3d4d11ac89066d36.npy +04090263-63609476aad03e4b9a6e43b878d5b335.npy +04379243-d1d9e395bff3d3a7c8fc6229eb64e56a.npy +04401088-bd7b84ae3b88bd5cd2dd279a9538db3c.npy +04379243-adefdce69de361c58d8358620132e773.npy +03001627-bbba083270a2b0d031d7d27dc50ba701.npy +02691156-66a32714d2344d1bf52a658ce0ec2c1.npy +04379243-ec1c92efffb9ee78beedb4c8fd29e2d1.npy +04530566-82be57a43d5d1e14fa286e2f06a75d07.npy +04074963-1aa78ce410bdbcd92530f02db7e9157e.npy +02691156-66b9ccf5842ed7f79330265a9fff38de.npy +02808440-3a55b7caf574bdcb362845c6edb57fc.npy +03001627-3116d8714420cef4ba33c5b911977a18.npy +03991062-ef148620745fe8bc4fce6348712475db.npy +03636649-e11d2e065d90200c7543d7dbfecfffbe.npy +04004475-4e2784b9fe210ced4f2ac6d17d58c936.npy +02691156-1345cd9d0da6d149c6f6da58b133bae0.npy +04379243-adf250aa1c9e0f9567232766992241d.npy +02933112-ba17ef05393844dfcb7105765410e2d6.npy +02958343-620e8aac415e9805ea752ba39dde460.npy +03001627-c552529c54b0612e53041c49040be3d5.npy +04379243-2f8b594d23665a2de8058cf23f6382c1.npy +04379243-2b36b46dbda291b5855931d119219022.npy +02958343-49d6a631f23a324cde361784b4e1f04.npy +02958343-909422a9d1b42e1380360680c1602c7d.npy +02691156-e00d7bd590ac129bbc0909d98a1ff2b4.npy +03001627-8a26820faeecd40d4bf49568516d5f0e.npy +02691156-f55390ed02c0b2b36aa3bf023a2b42a5.npy +03325088-b33ff042286d575af51945de050323d3.npy +02924116-f4369a3f1b28a7da78c6ad1c898f52db.npy +03691459-f142707a0f0acab4cd229b7f28637ecd.npy +04379243-92246f29bdcfe82cd323d6bd8db8de5b.npy +04090263-2bdaaa66b6a2618b43c62aa3efb9d383.npy +04379243-a223fb0172d705fc3234880d6f34f7eb.npy +02691156-b812c2df636aa0218b96ae1a0a8b84ec.npy +02933112-6ecb73ea5a117e3fc6647a321d32ae9a.npy +04379243-58182c7837f0edc35da16758ae613576.npy +03636649-55077c2175d97b8889ab11a408196888.npy +02876657-14adee7ed296842c874073279cad6d18.npy +04401088-7e8e9cc2cd70a66d4d1f2fe604198dc9.npy +02828884-e3c1e31ca2a0247979dee05d9c95f934.npy +03001627-eaf5428e15655d0b3c8d0fdfb1cc2535.npy +04379243-ab0d3af786b87262fa74bdb8d964a92e.npy +02691156-776bd07271792d1b131c2ccc2e4397.npy +02958343-4f9db143aa853e69b207e9cc82f7c858.npy +03624134-81fe707672e60cc0873aebd175ac6f11.npy +04379243-a5af3ca6791da8292c48d6b905457dcf.npy +04225987-7fc2cddac7ad57a2aa4eefa8f42b566e.npy +02691156-57fe8ad460bcb4929a4a28ef635593ce.npy +03001627-b70600293bab55c0593ebeeedbff73b.npy +03636649-5656f1bb53d675ffcb8d8c6d4df8143.npy +04554684-a7c8177faa40c43a87be36ce60737655.npy +03642806-30cd08287b6ddeadb275781e0d014d27.npy +02691156-796d6fba50664f5b1bcd0717744cc5bc.npy +03001627-96a03b164315d2b65dc3653f8341633a.npy +04401088-cb80f0eb9d3566da655b6157f54b4abe.npy +02691156-f6b96f56212f55363023a5c0cae3fffe.npy +03001627-cb5f7944ec02defcc6a2b7fc00a47507.npy +04256520-7875815356fb41f3d772e458a8f80cd2.npy +04379243-abbdbed926968014b3c42e318f3affc.npy +02876657-c3767df815e0e43e4c3a35cee92bb95b.npy +02808440-7288fb375238b544cd97b994e487c6ab.npy +03593526-5b13716dfa70014c726dbbf7bc5e4df3.npy +04379243-f9bbfd8acdee30158a63c123f2a561a6.npy +02747177-23a38f8cafa5bc9657a8fa4c1cbcf3ea.npy +04379243-49672809018ebc55224dbcbd6815e727.npy +02828884-802e7f3207fe4306175516c727777db1.npy +03467517-8b1d0f73e54ef59c93f0194265a9746c.npy +02691156-c7f6766e4e96ca0f444c0cf9e8ad6399.npy +02958343-58dfa36440ada6cf2a9eb0f146e94477.npy +02958343-dc5c1b1d9bf826b8851f021b9ed69c58.npy +04530566-11c2a8719a7d23207ca6caab209ed3be.npy +04379243-c1ba1f5fa5781abe276333179717351a.npy +03636649-a8d45280f2ac4e7190c926f4231a7285.npy +02747177-7919df48b23e61ba6739a7caa0c577bd.npy +04090263-69765630d57639cdd7166ab41aa5cf74.npy +03211117-c32dfbc85ddecd0eab610b0c94236463.npy +03001627-90a15feb4f77c63e5e73882ba2654055.npy +02691156-b152548ae1a12bcb680558279a114842.npy +02871439-93903b233ecb3937c21c5d9d91c5c9b5.npy +04379243-4977e64ab070b003b778cbd50553af38.npy +03325088-b658725e78e7ae9014b35a7d7cea7130.npy +04379243-a1d2dbfb4b3a6c113ff4affcd321d45.npy +02992529-ab8243a880170c00cca1221aa4c4f70a.npy +04401088-adf64019f7a54162550c9b1b1c5f7e5f.npy +02691156-536f5d8e46467566643c3c243d611069.npy +03001627-4bcc7c4e4c0bfe47e8f8c11a24c52ebb.npy +04090263-b7e59df21f4859281a857c47fd0ecdc3.npy +03001627-c98c12e85a3f70a28ddc51277f2e9733.npy +03624134-ca6e866ca1133eeb1395331ebe4786cd.npy +02871439-30f45a446153b9f1fab6e40cce6926d7.npy +03001627-677846a1d3777e90ffb9df6156f4114e.npy +03948459-802312b6dd3bd38332a77024dbc3f67a.npy +03001627-46e1939ce6ee14d6a4689f3cf5c22e6.npy +03001627-70f57047512c2eb84104b1c5cb7f9280.npy +03624134-97cf540e9a88704972dde081fcd2b8ff.npy +02933112-2a22566c3bad34a7d0b36851d61b6fca.npy +03001627-5e89f5cc834553622acd2bb6205825cb.npy +04401088-5ce8fc4a82d2d97736d4d4df7a719b88.npy +04379243-3338d1a99d7387562a488bb287b71f6e.npy +03636649-b158a8e4f45653cecc571cd3cf8f17a1.npy +04090263-6021c3fad833e4e51646f62c9305a389.npy +03636649-e6629a35985260b8702476de6c89c9e9.npy +03948459-4a7d8a49bc6365f92f55420fa8e157d3.npy +02933112-6eb88254824387bfc59350d819542ec7.npy +02958343-eadebe4328e2c7d7c10520be41d00de2.npy +04379243-5420d2a9cdd0d511e76bc197b3a3ffc0.npy +03046257-f1e2c567a76c9b0ee3f7a74e12a274ef.npy +03001627-ddb53381dfd0a2d7d2b12aa6a0f050b3.npy +03001627-41bb8be36df856eb847d4e46a1f9f05.npy +03001627-432346a3345e3e5dd79b19c7c4f0e293.npy +02808440-f7b303def4a2c10f211278b445671dff.npy +03928116-512b7b3f96cd981f834096795cc3cf10.npy +04379243-855e0dd7d801faf61886830ef08153db.npy +03001627-cb8e63317e0ac998e6543556f230fe9c.npy +03790512-6ad8d3973ccf496370a48b7db120f9fc.npy +03001627-a1ca000d08da97ae43b5d2063387bd6e.npy +03001627-733b580501f3e25c21ede3e0ecf73091.npy +04256520-de6e76b4be0db5a0f81b347089add3de.npy +04401088-ad66da8440023d8a1e929774f9727b5e.npy +04530566-af936a44c902756dfb04eeadf4d8d0aa.npy +03691459-ce21542cb2b0bb3458107383640dddec.npy +03691459-5bbdb492122b18cf65d1c7f91840e570.npy +04379243-1adf96850963550f19fb4103277a6b93.npy +03001627-d19ab2197f8e8582f97cb7fd36f15198.npy +04379243-4e934cf95db4cd3bce58f346b4d8abe.npy +04460130-64942df95c33b2911dacca859c0fc7c.npy +03211117-91bd5e0ff352d942abfcccdda2fa4764.npy +02876657-b31ca446cb3e88dda88e473ddd1152a6.npy +04256520-a4367b42274cfad1f2b7580a739cd4d5.npy +04090263-8e40afb2fc5d8b1c91e284193311f752.npy +02958343-29e9a4beeaeea1becf71e2e014ff6f.npy +02958343-93c56f05dfcd4248274334f2451a8eb.npy +04379243-6dc0048e4326feaaa6c03a53cf0a14c9.npy +02958343-9a3bf26f461a1973b8013668e30e23b0.npy +02958343-ceb561c72a407ddfdc50a691c68014fd.npy +04256520-bb39e48c9c10abee77f0370a839e670.npy +04379243-24b563bccb68e78bf939d21e50c410.npy +02691156-8f39d2dbb98bce6057b643a522b3d830.npy +02958343-8e0572912893a657c697c8c1c6e09e0.npy +03636649-56cfd1c474b7b88920c80e4850e77325.npy +03001627-59dd7258a2a554c34671fddd657dec0a.npy +02958343-2d1adb247cc7a1e353da660a6567c5ff.npy +02958343-a53c3515eff9f3bc2f732d6dce34e9b3.npy +03991062-ac79fd7f10f274aba2c59a4d90e63212.npy +03691459-8296f03cef18cac011cabb4938bfaf4d.npy +03001627-2560232741878aa1ed0003a3eb88f6ca.npy +03928116-599f5594764eeabe36244e3d0dd95a13.npy +02958343-2d41d907b7cb558db6f3ca49e992ad8.npy +02958343-26c382bda051376daebb91b7dc4caa91.npy +02691156-561bab672a9e12352c1752d7966dcc0.npy +02958343-198d8e274c59511b36a1a31af8f59.npy +04379243-51874066ba946c58aaf15b62af6b513f.npy +03691459-23a1ad8f7fdbb6a54821f0e819875cf6.npy +02808440-e203fafb218840443321831d2245cf06.npy +04379243-dc0db74cd78a3805f5600f911d112095.npy +02691156-880715a3ef69f47e62b600da24e0965.npy +04379243-d623665165dc5af0f51f77a6d7299806.npy +02691156-c2be303f5abf0db7b3369733e21bbc63.npy +04090263-40ad008d081e3d40fa9286f039319ff7.npy +04530566-7b200ae33e01eda467fd076ce612c54.npy +03001627-6e923ab0f28c3c2e7251f1ec40392b93.npy +02828884-5f9d3dae06acf0e4e93e1127627b834.npy +04379243-47bfb0c5ef5c3c7ddb6175ef18ad3f80.npy +04090263-3ce5f5a20bae04221fca469af258e053.npy +04090263-ada26cb4cb6e0b1946177b6d1ecbf989.npy +03001627-8967e65c1541d1874aa7f42ef07f614e.npy +04379243-5385893962db72324b3c42e318f3affc.npy +04256520-9e9707ea4d5c5968a283d3d51bc54a1.npy +02828884-f72eddac559ca6a6a51c26819f8dbb51.npy +03636649-e7552c8c718a1a109f2349486c570dd4.npy +02691156-8406b2372f6e1478d62bfd1579f9a1c2.npy +04090263-c6bea91c2b9ac3245127e0873cfaa7b8.npy +03636649-98c7c2542dddd40af24f994bad42f06e.npy +02691156-376e9480ebe635b1e98208adea7b4e8d.npy +04379243-6848c467de649ac2af5e7c004818a73a.npy +04401088-45301b15dce2724e483a0f6665d9ffe0.npy +04530566-738eee54143b5406615bb39b45716cb5.npy +03001627-9d395454d6de675d2025ebfdd95f4ba7.npy +02958343-f8954a634d103c54ea778d6c713d08dc.npy +02871439-b8a7c4c8017e49085693f7ffb7544f67.npy +02691156-759da7376ab2196a66df9c92bbd3d5c1.npy +03001627-2b66adf2ba9858eb19fb4103277a6b93.npy +03593526-a76b1bd56ffba0ccc9f016d57db96408.npy +02691156-b63f7eb03f91f8a7de04805f7d685d.npy +04379243-b3f05a35fcb82f678d3a66f462d312e5.npy +03691459-b9c2454fc2ef38db3db7c6064037cd52.npy +02828884-e6b0ac08a5326f23faf575cbae5008b8.npy +03207941-69b0a23eb87e1c396694e76612a795a6.npy +03001627-fc0c6ce55282cb4dc8687ff9b0b4e4ac.npy +03642806-90c01fd78513bb99c9b20aa1b8066c46.npy +02876657-6c24c027831790516f79a03aa42f27b9.npy +02958343-cdd00143a3e1e33bbecf71e2e014ff6f.npy +02808440-76a687cb1dcacf883321831d2245cf06.npy +02933112-879c6614916fb6907812c3baf25c5bb.npy +03001627-2742c0a5e984d92fa0dcc52ca811e565.npy +04379243-34e70464c2a7c17d97b40b8029c75005.npy +03211117-d24f05f573621080af70f0a098b23d33.npy +03991062-ffa6f6a754334d00a2c59a4d90e63212.npy +02828884-759fbe8a3ffa3831a895774ea4e4686b.npy +04379243-2a0b5875dc999a7a29e047111bd79063.npy +02933112-4a30aaec0e83f992c59350d819542ec7.npy +02880940-a95e0d8b37f8ca436a3309b77df3f951.npy +03691459-daa10595347937b9ae7dd8d7b134d1af.npy +03001627-e66276c70cadd32a3eb520ff7cd241f0.npy +02691156-3daca58825ce2ff6dc82b8fee1057b30.npy +02808440-c7c0c46ba87f11ca4c62bee40dcdc539.npy +02933112-7c68771e303eddc16adc061043e7c712.npy +03211117-2d5d4d79cd464298566636e42679cc7f.npy +04379243-e72ff1a58d752d5867279908dcfb86fc.npy +02933112-2f30f402c00a166368068eb0ef40fbb1.npy +02992529-c4b66fac952d4ef7d9039fb3a1715e96.npy +04379243-2810c2aafcdd9fc3f51f77a6d7299806.npy +02828884-5bc75cb5c0270e60d2b12aa6a0f050b3.npy +04379243-3e0fb214c130556aea3f94b6bb1b2ed6.npy +04379243-60fdeb4561048f63f5823a6b2902a9e4.npy +02828884-eec9e185d9596e7ed2b12aa6a0f050b3.npy +03991062-aeef58096019b9e25d8d4d8a3cf8b294.npy +03624134-89f69d95f5598fddd42a2a5a47e9ed5.npy +03001627-3ccc4efe519087c470ef1a9d40467de.npy +04256520-24f5497f13a1841adb039d8689a74349.npy +03636649-43989558d13b1186dccf149c7b4065e.npy +04099429-3e34a0b61d3678f9646343ecf02768e7.npy +03211117-38ecf0c5f3d5ee533fb0920a55a7e805.npy +03001627-fbd890f1f0280b884b47ef9f38e7ab27.npy +04379243-8eb366f4f602219b490ad276cd2af3a4.npy +02871439-faf8ece43ab74cab21b8b4d51c5535a5.npy +02691156-8df55e58da6c297b4c3a35cee92bb95b.npy +03046257-6e143fc9eef8be8c788a9e26a791a23a.npy +02924116-9332819c99f0ba07973f659238edf3c3.npy +02801938-efc55d2da732898d188976e1056285ea.npy +02818832-fe11d05aad83a1084a5fb5c8287668d.npy +03211117-dba7ecbb12fffaebbf61576316934f86.npy +03001627-9df79431f16cad05116162acefe23592.npy +03991062-24bc34cdce868610346ed9821e11e90.npy +02958343-a2c9c1b4bf918cf6d2dcdf586ee56d5a.npy +02808440-767fd747f18ccf466c2e38b335c98be4.npy +03790512-abdfb5b2d82e555e3bd003e0bb7a3ed9.npy +02828884-c50aa1c3da488573ba5342d638d0c267.npy +04379243-bdefbb1f281434e39961e1085a81acc5.npy +04379243-78625405f6c44bdccd67f05ece4a06eb.npy +03001627-6aa1ac5d377261d1c2fbfa4bf3252b56.npy +03325088-470811d9dcd8133f76c18e71fd49c4dc.npy +04401088-5dcb666efc36d9a68480fb9b9f30e540.npy +02958343-f643555dde0f0838346c6b68550f2695.npy +04256520-21ff7152b3bd0bc3df63d1c7e43c783f.npy +02942699-2693df58698a2ca29c723bc28575d785.npy +03636649-4f54aea89016146f771b0e756a54d849.npy +03691459-969512b0adee661679c6a0f7677e9555.npy +04090263-2a2b25ca77af35cf30dd2b88f7efae34.npy +04090263-a3896a954602b229d9d2bbf707e9704b.npy +04530566-3fe8b8d9fcf031574bac1c894ff81b3e.npy +02691156-d18f2aeae4146464bd46d022fd7d80aa.npy +03636649-981b55897cee64403c8d0fdfb1cc2535.npy +02808440-ed208a6ca79ca685b974c98e4d49e283.npy +02828884-4273dca1b0184024b722a94c1cd50b0.npy +02691156-6db52e6917c80e5157b14532cc71431d.npy +03691459-bbe69ee745bd5c427d35e00bb4edf01.npy +02691156-ccc0bbcc236bdff9c1ccec171a275967.npy +03790512-506962955771904b1d471e626c3ad496.npy +04379243-7f57fcbe1e7af1c1b000f20a5153622c.npy +02691156-144070f63941362bd1810447902e2904.npy +04256520-9dbd663d977c64d1b982b1d54ee6ac1d.npy +03691459-9ea3e05166af97ed20363e2561dd589a.npy +02828884-8f99b25df578652ae37d4fb630545e64.npy +03325088-66cc5be6bf49f17589577ccf07b31e7.npy +03001627-6fe690a6f597351162fd10b0938dcb5.npy +02924116-c5f6d95268f6e9d7b96a75b253e6b907.npy +04256520-a109fd29656079e714b96b665a8ac321.npy +02954340-a444fff8c769de616a10eb60523df1e9.npy +03046257-640f12d1b7bdd262868fb986bc092533.npy +03046257-758885e4c4e7bdd8e08074c1d83054ad.npy +03001627-1fe33fe022779bf8b0957d845ac33749.npy +03691459-aede81c0789358891ae45cdab702386a.npy +04379243-7aaed3e906eaf675a57b3bec78e5d1b3.npy +04256520-db19747e2c5b126148cd16ceeddb841.npy +04401088-7d5180e005f1601ca36bec4fa7cd58c9.npy +04090263-a2d0d9e62c7fa469f02ee453ff283e26.npy +04379243-c180b07c9b0f46b9f8c3d2002c77ddb.npy +04379243-e104beba32cf40bee369d8ecc5b0e866.npy +04401088-52541b667e4dee9b1c1be4d7e88f11d5.npy +04530566-54196fe702cd0f5ba27ad5a09bb4c2bf.npy +04379243-5e0340e08510cfc52f84cb7932f866fd.npy +04379243-f9aab5dd0162b688e9a1a03c1d065394.npy +03001627-e35d7d19dcdc9e5c30e06a011e63236a.npy +02691156-c953df8a3f917663a9b2becd26dc2fc1.npy +02691156-d08471df3e76602427743256ca3834f.npy +02992529-34e36249166b8c6bc3f912172873d52f.npy +04379243-bbc451f0431c1b06cea52a85deb0c978.npy +02808440-417754618af59dd754d7082b34825ef0.npy +03467517-a4170135b1055cb8982c503992eaf09.npy +02828884-cd08399f8fd8bd3bec6d7b771f3c56c6.npy +03001627-bfb71bd97fdedc6c48ff063e62e02115.npy +04379243-44302defc423e34a8afd316e82119b42.npy +03046257-1d5c5121e29011ddb8183a4a81361b94.npy +02958343-97bcc7a1f73bfba93e5399147a5b4763.npy +02871439-5906acbe33ee8b218cbb8bac2032149c.npy +02691156-1fc2625479e798b11944f01d3ab2091b.npy +04379243-3b51d76c7770b81a3c6c6fc37120868d.npy +02876657-e4915635a488cbfc4c3a35cee92bb95b.npy +04401088-2098a0f7cef1e593f6c5597dd1efe723.npy +03001627-e07c55b60987e8fa4067a397c01042d9.npy +03001627-58b8bc3981302103b78c56df3d6a2934.npy +03001627-a497f206aa62e89c8ca0fe30c6caf3f4.npy +02958343-397d2e2b3e0988a2d3901a534bc610d8.npy +02958343-d55179fa8bec81799779c759176b96e3.npy +04401088-e7bb86cd04cfd98758f1d9dcdcb62d55.npy +03691459-40e4ae14fac94d0b45bf366c0f22b100.npy +03001627-f678b1e737eb4d5c738e43095496b061.npy +02691156-993599a55057f963ae7c0d0e12bd33da.npy +03636649-a138582b1d0b9cbb137af984a9f45d65.npy +04256520-54a209955f7a47bed8e8a8a207ee5bd2.npy +04379243-18c8f6ded2f14010746cec00e236149d.npy +03636649-4ed37408e5bb257ee356f23093e95c53.npy +02691156-298d674a14dcd356de6e2d41bcaaecbf.npy +03593526-d0be31319409de673ce0d177711e253.npy +04379243-23fdefbb27881722b0f92c9828c358.npy +02871439-b574e0258d18f4a283f3fdd3a2f8d59.npy +02876657-74221bae887b0e801ab89e10ca4a3aec.npy +04530566-dcd17bd79acb60f3ac8108ca15b709b.npy +03001627-658602dd0da08614a1b6f261c8f1ae0b.npy +04379243-5c2c29fd07c365afe5c65540d3456093.npy +03211117-ed7e0817614b1c155e7087f2d9a278a9.npy +02880940-a0ac0c76dbb4b7685430c0f7a585e679.npy +03001627-d75a219d343d2469e22abcbea1db98d0.npy +03513137-20ba624db264002082ee371ba207c717.npy +04256520-b0b942c484db4fd7afb07a946d621b3c.npy +04379243-6152e14b042aa17546f41dc2aaef556b.npy +03593526-ae9e1f9ff5b492524dff7c27c1f6df72.npy +04530566-36b38fd918d01c6b6c63b8b48495261a.npy +02828884-d014dd996cb7b8ba4f34c3dabeae093.npy +04379243-4cf6260ddc4e1ffc2ec2c1c65e9866d.npy +04379243-a95176f3c7a102acdfb197c00c97d72b.npy +03636649-bd9b0dc06cbe7b123c8d0fdfb1cc2535.npy +02958343-7af4a575dc3883afab355379ede04b04.npy +03001627-da7aeb7a73f298329940c34828c5731f.npy +03636649-13c361b7b046fe9f35b0d1c9f81f0b6c.npy +04379243-20ab56e8a819c7f06a9633583f89b17f.npy +03001627-e18776689e00c8b84f871aa82358858b.npy +04379243-812a19a717fb5bf34510596cb4be6a33.npy +04004475-b2330f57a3743c90b713df0d260c2628.npy +03001627-d080bfadaee310d8a21e3ca11c5bc05e.npy +02958343-212685bfc2a32cd9fe8cfdfb3bfc3376.npy +03467517-7eba657565cc69e913f86abea5e4b9e0.npy +02880940-be3c2533130dd3da55f46d55537192b6.npy +02828884-4814cb73a71235dbf155d75bbf62b80.npy +02828884-7d865d0774f34972814c9aa90ee14e.npy +03593526-57693fd44e597bd8fed792cc021b4e66.npy +04401088-f022d7789de219e1fb7ad0eb0a148aa8.npy +03467517-feaacb1b8c140e5ff962b6de585c4677.npy +03211117-e1eac12837bcadcf44d2fe7d13c65f0c.npy +04379243-6ed257cfcd73fc6830bbd4cddd04c77b.npy +03001627-8abd5158ec94dfd8924bf081da6f024c.npy +02828884-54650f6fee0e76b8b173657dabb4301e.npy +04379243-3b4dede09e8125639d653bd9cc95fa15.npy +04256520-dac6d5f66189b340d4ffe37a3ab73512.npy +03948459-1b8adaf6f8c40366c416aa58a067b7bc.npy +04256520-12cd30f7f83f441dc13b22d2a852f9c2.npy +03593526-2da4d88435eaab6aa7f0dc86456c3021.npy +03691459-f2eb4b53ea11200cfb10a282776be584.npy +02933112-12bb12017516f20d28b780bf7c8edf1d.npy +04401088-41d95e8979b8377d251f8cf5c284bd7e.npy +04401088-a3c1c9fc390b1bbbb099170e6f5a4af9.npy +03593526-7bcc0e91bd43908df4a06efdbafdd7ea.npy +03211117-faf54bcb640753a28c6daa755196a36.npy +03001627-6b9dc32e4d278663c8687ff9b0b4e4ac.npy +03211117-722df1da5778d45b1e43523279c7f09f.npy +04401088-5e485b1ae058fc11b26a5d88c8b02ed9.npy +04379243-2fad51052bae2366377b9297f3055210.npy +02924116-dff59b81f0eff60c8c5004350953aeed.npy +04379243-d35a2fb01107b6178727c7a6ed7a8927.npy +04379243-469122d4947cf83ee6942c5426df6055.npy +04090263-6e157a5e034eb9f49f433921788191f3.npy +02958343-76cd991287a5aac9acc9e84c45e9a610.npy +04379243-1ddbe75f64683937f4b6538438a0b930.npy +03636649-fa6b1702f7c1fa191b17743c18fb63dc.npy +04379243-ecf3d40b14300d3c0c26b04b6b8e17a.npy +04530566-355a85d0156984c75e559927dcb9417c.npy +03211117-59580147939bcb7e8b296db8a8f00728.npy +02828884-cb48fccedaee0e82368bd71100fb3a30.npy +03001627-d15c94b08b5d92e57962800be79c6e52.npy +03001627-4bd7a49e63e0e97936e3b2fa8d1eb4eb.npy +03046257-7e322702d66d54b560d9b527752ac99f.npy +03710193-1954c0e02dafb95291389b3c4840180b.npy +02958343-db86af2bec3e48d7beda80d430b92891.npy +04401088-280c7836d6302b4bf3f8467cb6fe657e.npy +03001627-4b79197258fad3363efeda73d60343e4.npy +02828884-a8a6aed819779d6b19fb4103277a6b93.npy +02808440-bab85a8a0338b58e3321831d2245cf06.npy +02933112-932abcefa2fa0d5960e37b3f76995f8b.npy +03001627-bcf67dfcbd6c1fe7da8e9e0272759299.npy +04379243-5640f565daac3dd3772b104757a4809.npy +04379243-a6f69bef589c295d51ef8c8b1fdb41ce.npy +03467517-ed486c24321fcddaa3d3eb77b119df6d.npy +03001627-74391d05121df162492d9da2668ec34c.npy +02828884-79b66254a33c4a80e68b7becf68bd6d3.npy +04379243-89e73205e8d18a8c99e8bf807e902261.npy +02691156-471ca950dbdf0c6c5f80f808704d6409.npy +04379243-3f1579c1713ae72e2d07d128adae16ff.npy +02691156-e45d71c7afb3cb1c67629418bd553f95.npy +04379243-e7adfbfabcafa394278f90ef85162deb.npy +03211117-6856b84c3a8463e3d5f7c62c7dfe63f9.npy +03636649-583a5a163e59e16da523f74182db8f2.npy +04379243-6c6f63434cc1f447f51f77a6d7299806.npy +04460130-6d43d4642c7a474638cd8eb23853c009.npy +04379243-2f5f32ab1652320dba18ade30e563d37.npy +03991062-eafe716a8ab5722278caa162a41a851e.npy +03691459-46ab468d333233b062a6cf00d929f875.npy +04379243-d16bb369a03f260cc48d90eef8384210.npy +02828884-498ef3fb51503dc36e07666ce67ff5a.npy +02924116-ac2444d4255279548a7522bf08a9766c.npy +02992529-efed528241cd773fa2c7c5886f4bbc93.npy +04379243-98b3a7df1e233ac7ff10e98a19606836.npy +04256520-a702d178064c7b81fc078d27c856022.npy +04379243-e42e2c616f8c38619ccce4c6d5bb195f.npy +04379243-3f80c1ddfce08d18525211e12d56c55f.npy +03001627-40a9dd43155979e7c40cffb9454b27e.npy +04379243-574447022c4473d455f46d55537192b6.npy +04530566-e604463b6c45712395ea46728bcdc15d.npy +02691156-b3323a51c2c1af9937678474be485ca.npy +03642806-476cd9a7a0a7c491c96e2e556a25ab0c.npy +03325088-ae3c54f6a88813d214b35a7d7cea7130.npy +04379243-496de03106abdf4ba766a367d5e2d6fc.npy +03001627-1e1151a459002e85508f812891696df0.npy +02958343-115170b8b44f9e2e5b2bb28aa7453162.npy +04379243-c20a5f8cfa29824b310af74324aae27f.npy +04256520-1b8894ce5f53e0007143b902ce4e435d.npy +04379243-689c4f50ce0aae27908caac6d5f8ca97.npy +02958343-9c827e532de4967285089a13cc567dbd.npy +04379243-c29a4a7506b89be2af4d0d91ea903469.npy +02828884-6c1ca36830d54ca5c9736640ccf985f5.npy +03207941-b187206fe6ed4228a805114916841d69.npy +03624134-20050969c1d7134cf69ec30ab244a145.npy +02828884-702870d836ea3bf32056b4bd5d870b47.npy +04401088-a6b2c1427dec317525bf2427892579c7.npy +02691156-d1e81c9479eb1b7da9263338bcc7d067.npy +02773838-e1838a13ace989545de21284bb515a83.npy +03928116-9071693a85f8425790845915a86bf9b9.npy +02933112-eaf341c056c79bec1a2c782fdbf60db6.npy +02871439-aa0bab8405274a3568966ba896bb15dd.npy +02958343-f1a20b5b20366d5378df335b5e4f64d1.npy +03636649-994e14ddae6f642ca0a1df19404132e9.npy +02691156-820ba20e5da8325f19ba010ddb4974fe.npy +03001627-b16f1858c1a7c0a65001cb19c4a0eee4.npy +02801938-526a9f51fe93659c3c140c326fab0b5b.npy +02958343-707c8930b987b1f3a6c0381be0943b0e.npy +03325088-1c0b65c18b56fc71a6c6cdd30dc62f82.npy +02691156-a331e93c3184742853a6ddb5892da51a.npy +02828884-22af1585e38e4e76ad5067eac75a07f7.npy +02828884-931017bd80aa7a90edccc47bf0dcf5d3.npy +02828884-ca85baab8740ffa198cd58ee93c42c40.npy +02828884-e8db4ae7ddd84627d4d8765e3910f617.npy +04256520-930873705bff9098e6e46d06d31ee634.npy +04379243-9160a9dc1c840e79c607634b4693f04f.npy +04090263-58b926ca85b6ea549a6e43b878d5b335.npy +02843684-5919f39dbe6c9351d474325246d1c061.npy +02808440-11fccf143d5209c71c17aef130ed6213.npy +04530566-6a541c64083d2bb9c5408f4f799fe72.npy +04379243-2a0f853dadd841f96f1e07a56c129dfc.npy +02958343-501ac8493044eff04d44f5db04bf14b8.npy +04379243-84d8b1ce802662984fa8d6439169bda4.npy +02828884-10b43623dbc8ab25ad5067eac75a07f7.npy +02958343-316086c3587f9c07d4db32f454eb6c4e.npy +04379243-1a8a796da899cb2c4d672fe014b9000e.npy +03001627-bdc892547cceb2ef34dedfee80b7006.npy +02992529-9cc581a6c5d0b8fcc14f5d127de947a6.npy +03001627-588bf81e78829fe7a16baf954c1d99bc.npy +02933112-7415fc8bf90b3696bc08b7cef3268bb.npy +03001627-802f70c906274da08616812464c86290.npy +03636649-19fc4044912f5cc4869594a32151bfdf.npy +02958343-b35117b7e025a012bda733a39f84326d.npy +04379243-c12ab3b5a8d40626c6027d1f057f82f5.npy +02958343-5dc3ec70f394965368d733072f36728.npy +03691459-af7aded6c26d2b119d3f10ce46ef328c.npy +04379243-1a96d308eef57195efaa61516f88b67.npy +03001627-b2d91caf3615a9a7f51f77a6d7299806.npy +03624134-c7a96262d5dfc1ae72c447ef6e5cffc2.npy +04379243-8d143c8169ed42ada6fee8e2140acec9.npy +03046257-30bfa6b225b030ba3756a875bf156f26.npy +04401088-678ec09bbde5f116716c29316ac4d0a0.npy +04530566-29af666e04825f66576378847ca0b69.npy +04090263-85e714acb678fc59ed6071560148e6eb.npy +04090263-945564d4497f3a0398838fdf70b3e60.npy +04090263-6eda9bcd1c2f4c8fa33c2b3fad570e45.npy +04256520-bf837b5821d05c00efe1cfa376f050c5.npy +02691156-845364350601ca0cbdf0b44e2f8f4e6d.npy +04401088-d2bce5fd1fd04beeb3db4664acec42ef.npy +04379243-b9ac8f3615d8ba0bf51f77a6d7299806.npy +02933112-7206545c3f0a3070e8058cf23f6382c1.npy +03211117-dcd4d3d6bbbabdc6376c487287ae2b71.npy +03642806-298cf1c20abcd641f9f562601150287.npy +04379243-35bce0bd439e04e63d039fd0dc042dcf.npy +03001627-cffe40b41d0162c46b2befe83a0efe39.npy +03001627-b7d4357aa24126a227a7baff096e3087.npy +04530566-2b1d09f8412f647899c0080e6a5589fa.npy +02933112-5d8c63fce0f30a46f251828d7c328331.npy +02828884-a5856a7738262b05738e43095496b061.npy +03001627-ef5eb51bbb7141c119fb4103277a6b93.npy +04401088-5fe99904fa4b22d4ff1911c2640f2e42.npy +03001627-1b81441b7e597235d61420a53a0cb96d.npy +04379243-631a942d7b87387019fb4103277a6b93.npy +02933112-646fa7efaaef21a41d20b5ad5ef1cb1b.npy +04090263-85d9133c2be9be93d017eaebc1ed8e2a.npy +04090263-702b1c4aac9e825f51cfdb4c9f126c12.npy +04401088-92ec69548761efc61f74e5d5bf005208.npy +02880940-bed9f618bef8d3e9f6d436d018e2b50f.npy +04379243-f992b2e0e44987698cb5d9909aeb1309.npy +03691459-dfc293d76992ed9656fd7f904d2e0c.npy +02924116-7e62538347c521325f7a2a8b8d62d402.npy +04256520-a27b9f94d052176af27383fc5a5a711c.npy +03001627-20627f21d8681503f2aa3fc45e8202cf.npy +03624134-6d542cef32a690f248c2fa4fb6bd3e62.npy +03046257-9986c03f7d7e8ed111d1123cebe2740b.npy +02828884-70edb39bb2710eebcb2a965e75be701c.npy +04379243-bf45b5c2c9dd8fa9fa24672a35ae8bb.npy +03636649-571137d6378372c5fcb8d8c6d4df8143.npy +04090263-1a289f162d63c0fa8dba2b86f956c537.npy +04090263-feeb8220f21521d4b4c6d1a32dc4f554.npy +03001627-b6de66042941f5691301e24e9e27a9c3.npy +02818832-de14f6786ddc7e11bd83c80a89cb8f94.npy +03001627-4a24652fbf2bed7e93583c67df8faf1.npy +03691459-8e54ec9d554584cfdfa0db1c1e10ab1a.npy +02933112-28b381915e04c62934b6da227fd64942.npy +03001627-e5da52f5d1ae95f75a8ae8f7c307d01c.npy +02924116-4fdc02421954e0fbc08550bf6ec9e732.npy +03001627-2aa2d2bb646fdc511b7ca0421af5a45e.npy +02871439-699468993d0ab5cb98d5fc0473d00a1c.npy +02958343-e3cf84131f9293a5ea0b6fe51a588e07.npy +02958343-e5247d798b4538094046e8fe9dfc34b5.npy +04256520-9c868997ced1aec1dd904956425d1eae.npy +03001627-bf37159b9ca55259e6fe3612af521500.npy +04090263-1711fdba3382cc39fa9286f039319ff7.npy +02843684-bfb6e6472e91e0148ac033353d37592a.npy +03636649-bf3e47e405833ab715655d3195f5022b.npy +04256520-6e3771d48b3982d0eca22c501ad0a77a.npy +02992529-ae7098f0bc20cc6b2a87aa332da7bee6.npy +04330267-898c20d376d7d44e5eb64c1003065596.npy +03691459-3b63777e658e7137f36ecf951968a8b0.npy +04379243-20e5bb165c5e129ea5a11194083a61e7.npy +02954340-fd63218d927ae58cbf444790f25ea3db.npy +04225987-e7c330f4c4421dbb24e49a3e82c3d033.npy +04090263-9bd4ef716fa467a6c72189e41b1941d4.npy +04256520-5a99fcbf7ad93010ebc1a7ae7c4c250d.npy +03624134-5da598733fda1b7aea5aa8dfe86aec5e.npy +02808440-4decc1afdd1eb8494c62bee40dcdc539.npy +04379243-25775a3ee25c6503dddd8ce1cda8c6d9.npy +03001627-e6778535d7fcbf6fff16555386d173d.npy +03624134-79e64f242e7101fdce92dcedd9b9f51a.npy +04379243-177c1102dd46badce958df2e8332e31c.npy +04379243-6d5aaba9f6dafca977252fffd1947df5.npy +02828884-35686cf1e7db69d580be56c7b04dd6f0.npy +02958343-974c3d82f8726f086b418c7d9fedcaa9.npy +04379243-927dbeedb2d864d635dda488a4bbb1e1.npy +03624134-b0f9aad955aebe6759d0a47cd36512.npy +02691156-cae48a376cb607547d3b11085e75c7ad.npy +03211117-195d9d0305fd1625679efbdc830f6d0e.npy +02958343-d060adfab4c02ec616abce8cb03e7794.npy +04530566-fe24ea1bc3383631370d3273b84cb8bf.npy +04090263-5dcda2b98242d00b55f41a702b987e76.npy +03325088-bedc697875ba693676c18e71fd49c4dc.npy +03001627-4304100faeef130337f67f4322e8d3d0.npy +02691156-d9d282f79262ebd4c3a35cee92bb95b.npy +04256520-54506969a60017ac8f0a57a8b9390a.npy +02691156-59b8d36b0f96aa5cca649c0959202cf.npy +04460130-17f5482dd8b9dbddc850800ac472a578.npy +04530566-a6d232b7443609fd20ded1536778b0f.npy +03211117-11c041a780cd7e58e8b612d9fc824411.npy +02691156-77dfd8d4ee3c54c3e99ea3c41458bc01.npy +03636649-f69d3903096b6bb78ca4aeb5e3b33af7.npy +04530566-933382c8b6cc6e24f0cdce9bd16b6c9a.npy +03636649-ac1e6d46bfff76a664b3b9b23ddfcbc.npy +03691459-91b781b40d32b74dc491effd0ae881ea.npy +03046257-4593877d0b238443728b983f64e482fa.npy +04004475-d3ea7b61f5fefcb59983625c07de3812.npy +02691156-a55a46c1442470aeace5721ccacba16.npy +03636649-6512e3a8e6566fd0cf004563556ddb36.npy +04379243-b4bc3e5192dc476f609fb05dbd8681bd.npy +03642806-28fbfd8b8c9c6f16e1e44e2fc05361d9.npy +02828884-7a89313a148bf1bfcb2a965e75be701c.npy +02828884-7229a4c3b3146f74d838ae16242881dc.npy +04401088-57ff44f979370766976fab5d6e2569c1.npy +03211117-182a5ccd3c0c9887c21c5d9d91c5c9b5.npy +04256520-b090f9315fc9e0cf9936c7914e42d921.npy +03991062-b384f62a88a2e5a8a127ca53341bcf9e.npy +03001627-c472a815afff5ff0e6c5cd45aa112726.npy +03991062-f794d82d7be73b1a9f7e329438453d00.npy +04530566-cfb7ca78b0b65c4f2d615e80824301ca.npy +02691156-a922f408bb1b1ea1f2cb090f7f07d463.npy +02747177-b03989e0afe2443581faebbdea6bd9be.npy +03337140-bff01605583f2d7af84b0be7f50940eb.npy +04530566-e3431dc06c6f4c22441d5d15cc0399df.npy +03046257-686a205c36f5c85443ee5a34155b4f2b.npy +02958343-ed4fb30733bd0979b1bb46d2556ba67d.npy +04379243-dc6f030d9ee566a5dcfcef693e7ec696.npy +02691156-4992d4c425b3cb426e8204b21fc3574b.npy +03046257-4936b4d8dfbdf2cdbd09663b97413cd.npy +02958343-6056451a4b65a12858dbdf2b5c6acfca.npy +04379243-b4ca27e38b327aa0240c1f0f1e25335.npy +02828884-a82c14ef1540d3abf4c42dc386169bd6.npy +04256520-c2d78f31b197e0bce2d881f085d6d86d.npy +02828884-c96afd58ad067a6871b66f80cfaa9877.npy +02958343-63599f1dc1511c25d76439fb95cdd2ed.npy +04379243-d9b418e6ec14dbf50efffb055ed6bd1.npy +02691156-da5fda29d2415fb09d92b4de623f5639.npy +02808440-fcf0ef94d568f97054d7082b34825ef0.npy +04004475-e3898229d4bac27b15a34fa27bdf3d03.npy +04379243-ce8fc9bf9c9fe3ce99e434a62f00f7de.npy +03001627-914f301fd07c20c840ef1c8b63a628f9.npy +03001627-95ff15679bc2d2bfab41e4eb455c2269.npy +03001627-df23ca11080bb439676c272956dad3c2.npy +04401088-fd1dd7c841cd9cf51f05b3da5aad55f7.npy +03593526-1d4a469bdb53d3f77a3f900e0a6f2d83.npy +03636649-107b8c870eade2481735ea0e092a805a.npy +03636649-e7310381c64cd87f8880edc6251fa529.npy +03636649-777a686890d74b350359b4e03cfdfa.npy +04256520-b8469c14aeb092f74fde46457697d80.npy +02924116-9e75756bd1bb8ebaafe1d4530f4c6e24.npy +03001627-4facf9c7f5555b28c0f947750540fb22.npy +03001627-477dfe89f1d5df337fa68300c57bff0a.npy +04379243-88b217db267f1ec61e616612e30565e8.npy +04379243-b04a4cb79890c846ab7f9d2da6fc61cf.npy +03325088-af708fe6eac1bc9450da8b99982a3057.npy +02942699-f1540b3d6da38fbf1d908355fc20d631.npy +04090263-d835a2aa71cfd29dff790997f2048517.npy +04468005-d928c4ee5ef8f84e186582d606e06e65.npy +04379243-29c6a184dfee3050820018801b237b3d.npy +04256520-dd3d82569d4cb2b5af140afd78cbb542.npy +02691156-7981eae34c05e8409a6e43b878d5b335.npy +03001627-434405216f00c9654b0375f3afdcad10.npy +04554684-177501db32f76aa4a2ef01d38c90dbd6.npy +03691459-a551777c3b35c06f43f491729931f44.npy +03001627-43cc05f81df8307a4357a62465045ec4.npy +02828884-9da3d1f848bb801c77ec6cec7835f07c.npy +03001627-633110fedf1efac0f7628281ecb18112.npy +03001627-d89e39192db6fa78492d9da2668ec34c.npy +03467517-df25fdb2b8ceac673b2deb8c31cb5d73.npy +03001627-9d63d69501b9ab9067994ca435825ef.npy +04401088-8cac6df50c515c498be6bc9d57b6a438.npy +04379243-d93d1957e7a38a6619fb4103277a6b93.npy +02747177-c5c2a3f8d66cdaf7ad5067eac75a07f7.npy +03001627-195464ae11f6bfe1cba091e036bf65ed.npy +02691156-90bd96c05c0208c642d1180c659735fe.npy +03790512-b4112da294c1febf65c8f8f77b16f337.npy +03337140-229a34f1529c4ac14c3aee8e9d3a6ffa.npy +03691459-e41aab211af3f84673e1b2d018c0512.npy +04379243-6f019fe6ab60a3e37b11ae648ea92233.npy +04401088-da1fcb7a374f9c43397c13131c65cbca.npy +04379243-216da8313bc7b192ab610b0c94236463.npy +04379243-9e22ea3530631b5e95937f6e581cbd41.npy +03797390-b9004dcda66abf95b99d2a3bbaea842a.npy +03636649-3fb39b80530c18842417a6b5541e7395.npy +04379243-4b1744fbbe73dfb39ccce4c6d5bb195f.npy +04530566-54daf1472c51bb47a97a590141e0046.npy +03046257-9b28217f38c32415e02c50e637560d85.npy +04460130-58695979fe916c43327144edfb578d92.npy +02691156-1490a4ae04d453784f856435f28995af.npy +03636649-3f6e9d27bf0e972b9f42325587eab087.npy +04090263-18271afb4b31686bb53dcfbf8e62caa2.npy +04090263-b50f6037b0f9b86879d9900c00629c24.npy +04401088-5b7901974a37066aee44e0ef4ed60fd.npy +03991062-3e2dd918360309554b3c42e318f3affc.npy +02880940-da5f13f4048dbd72fcb8d8c6d4df8143.npy +02958343-ebb3c22708c9ad3a55064a110bff2f03.npy +03001627-b2ded1854643f1451c1b3b2ed8d13bf8.npy +03001627-586f09dd66df0beb2f45520e48bbfc3e.npy +03001627-4f7e9b96404fe19af37f22e93a631b3a.npy +04379243-4315e96a1dbf9337cacf13745dbfd112.npy +02958343-d2e1dc21db9b45df6436916a86a90ed7.npy +04379243-15b0e9fbea6581354ea9b65fc2574d0a.npy +03001627-253ca5aa292b344b7e673473caa41d7f.npy +04379243-3ac69f9e2517f836a341228b21d337a9.npy +03001627-ae3b4195dfa9779f89e49c5729fd5d6c.npy +04379243-9330bd524773fa17915e97a8e8ae6c48.npy +02691156-9fe677b21938f6bfcc14f1e6f4f4f49b.npy +04090263-2a811e61b3d6ce11c45f65ad2adf422c.npy +04256520-88d523dbcd94be8a4af957103f4767ac.npy +03593526-4cd2f74d052b561952e2d18963a75b4d.npy +03636649-573500f52762f0ea8485cf03cd00c621.npy +03691459-f3f07513f7deb6d1e4ad2926a22bd27d.npy +03624134-b31cf3ccb489ba2e7b635ec9828c6ec2.npy +04379243-44e9b15e214b390b2b70eac6546e93fd.npy +04379243-5067a85ef67c2e45ed403132b02528bd.npy +03593526-a791d4fa1d840408c5beea20858a99d5.npy +04379243-acfadff8f5ab4e7880d6227ff9b21190.npy +02747177-c461a147d5dea8152e91d3ee7cb428f0.npy +03211117-ffc9068c8de1fe46d9869786ff7f6a46.npy +03001627-908fd690e253f651f1783a44a88d6274.npy +03001627-6f11d4ab55b7a63e261fd7080fd6f759.npy +04379243-ecdebac7ddf6ef0011c50f6f633c5e38.npy +03001627-37e2b82d5e9dde21cbde89e0c48a01bf.npy +03636649-cb4b887b5acd27cde76bc197b3a3ffc0.npy +04401088-3bdd569911660da81229c79e4cce736a.npy +03991062-d1ed787e654dd0ff25ebd1cd0b422e32.npy +03001627-3730f9cc29006f4b65ba78ad9601cf1b.npy +03001627-cd6d000df66f03368ce66f12ba927a2b.npy +03211117-1984fb95afb6dae5804722305621f918.npy +03636649-26316fabe129210317fad902853ecfd7.npy +03001627-6893a0aac52e31a3578fec929fed235d.npy +02747177-e19887ca50862a434c86b1fdc94892eb.npy +04379243-1d393a06a5cf567d3892cfdb72a66fb4.npy +04379243-8cfe3ff92244310534506cc3910614fe.npy +04379243-92ed9344484dd026dfd21203bf8b4b46.npy +04256520-47dfe5f98cc9075850336112dffe8551.npy +02747177-af32b6f5a0343c107c35d3c5d3b1fcf7.npy +03001627-ef3377832d90dbbacfe150564cb24aad.npy +03001627-cee5c4ec2b284e7317b431cae0dd70ed.npy +03636649-ce621e6df1ab9ae35d2cdb96c1afe34.npy +04090263-dc29aaf86b072eaf1c4b0f7f86417492.npy +04379243-1b70ae39748f9b97456cbf78e1e89022.npy +04401088-5050d6be55dbb7cbbf82a0d508a096d3.npy +03636649-f018f4d78d295ef3a78d991d8e8834d0.npy +03001627-d2fe67741e0f3cc845613f5c2df1029a.npy +04256520-9ae05089e29678adeeacda4374ad94cf.npy +03325088-9fca1d6653e2bcc914b35a7d7cea7130.npy +03001627-fbd48960edc73ef0490ad276cd2af3a4.npy +03636649-d9e6815b6af181cab76e29c9c43bc7aa.npy +04256520-1d6250cafc410fdfe8058cf23f6382c1.npy +04530566-3679338b5a90bbf5fd1d4880da709562.npy +03337140-7dc4c1459f2aeaa6eea9d91e5bfcfc8e.npy +04379243-3f198d5bb97b930c87e847ff3a8836f1.npy +02691156-f858fdc6841407e6d4bf37afb4832e7b.npy +02958343-67aebe9ff1f103e18d1e606155667e23.npy +04379243-4ed5863efaae348d8b773535ea8cba6d.npy +02691156-e814190f683946b798b4e13cd6d24c30.npy +02933112-3e52f25b8f66d9a8adf3df9d9e46d0.npy +02958343-a8ee57eddfe30b35553fca48ce732862.npy +04530566-eb8569cf15db1dac1640aadca4c54050.npy +03001627-28bdf067b9fea968f17e3402958be9f.npy +02933112-ca0fd2a5d6aa32945aeac558fa5c869b.npy +04256520-8c6d7c225ba8a152387133b1607f2aef.npy +04090263-84149440704cddbed735fa1ab17311ec.npy +03001627-e46d1c2bef1875e2ed30b335ddc8b66b.npy +02876657-4b5f54fc4e629371cf078dc7b29022e6.npy +04379243-ca577373ec8bbddc7730743b6aaccb6f.npy +03948459-8ae24c618fe450d9ad047ee0c12cdcc1.npy +03325088-3ca7d12fe0b4fc5d3321831d2245cf06.npy +03211117-9d9bfaf1a4d6c3a05f8ab9d7b9f9d24a.npy +02828884-55f637ec7432a97d1d677cb74bd6536a.npy +04090263-1c74382abb0281e26314c3b6a3a65519.npy +04379243-34d280e8968c180cdf63d1c7e43c783f.npy +04256520-fae52eb61560b246f8555ec936cd4b63.npy +04379243-40b632472f8e69a7664b3b9b23ddfcbc.npy +02958343-ae086c610d023693d8a99964311c4152.npy +04530566-abdd2218a607a19819194900293f58f0.npy +03211117-246f0b722dff7f16fb7ec8bd3f8b241d.npy +04256520-cd10e95d1501ed6719fb4103277a6b93.npy +02691156-8615fe6e2a959ac1efe5f291bc2f5fd0.npy +03001627-6ae8076b0f9c74199c2009e4fd70d135.npy +04468005-3a5753b332b0b735d85b408a8edc983b.npy +04379243-8807a8fdc7a08a0fb664d1885442ba70.npy +04379243-104ebf7f96c77fb46a0faccc2a4015d8.npy +03593526-67f7d931a1796b97331dae093cef31.npy +02958343-156d4748560997c9a848f24544821b25.npy +03001627-562e6354049ecbc19f8f9f2bcc40c84c.npy +02691156-50d2629e7e96c2883034111f96c5f617.npy +03001627-36cb782fbc164ac312591a3ac05fadf1.npy +03642806-4bacb1694e86005afb6e846333373df8.npy +02933112-4d9152d6df9883529c75eb4326997fae.npy +04330267-82cdf477807e2af5eb64c1003065596.npy +03467517-345a9c0aee179a2293a3cb7ad5bbfafa.npy +03001627-3fae0625f3cf5e862678f553478310df.npy +04379243-bacef6e42574bc25d43cd8b5619b5cb8.npy +04074963-d9ca2dcaf1d9d850dc605801df3f66ec.npy +03642806-35462b6ea0597bf555e8ddeaf1791474.npy +04090263-4defda42f01b1345119486cb086a6c5c.npy +04468005-e2e07adb05ebc0a14c213c1a52c1de2c.npy +02691156-372c95e7685363ca18e0889038e4fb6.npy +04530566-2570f4db767fa046760fb52676c518d9.npy +03211117-34d998b1845880795b1895ac674412c5.npy +02958343-37e8db361d61971b184a07a6c7fa882a.npy +03001627-d4d7607336810a548b95c9b52cba3b9d.npy +02958343-dab0cd8adac9404780575af49bfeda6.npy +03691459-ed0c530e245dfdb269d48411e34c9daa.npy +03593526-eb7d628a0c635eff5ca1f314f1afc186.npy +02828884-78c7cee6016d8dba2056b4bd5d870b47.npy +03001627-baee1a3918353466d1d10c27b779ddcc.npy +02933112-21a6906ec6cc806182db9fca4b68095.npy +03001627-6f6191af40bfc07116f5e76c24d541f3.npy +02691156-f0bd0660d9cec23cf2b0736dd4d8afe0.npy +02828884-adf284153a2a87208c9b655484c84004.npy +04530566-a32082d31b6b9a0566dd4c46ee29f5d0.npy +04256520-c955e564c9a73650f78bdf37d618e97e.npy +04379243-31678ef74b85de0b15b943c35c765be0.npy +02876657-6e57c665a47d7d7730612f5c0ef21eb8.npy +03211117-5e0fe73a4d919b1af5f79806bd65844f.npy +03948459-139ecc9b5ec25ea77a9772e56db4cd44.npy +03642806-fdf791fbb8fc7cb58ca8637757ac3f67.npy +04530566-7d997dbaf47acf92866219ff4a62ebc4.npy +04468005-1fe869656812f5b0d85b408a8edc983b.npy +04530566-f1800fb3a9873af1e64f09105f9c8a56.npy +03467517-96b506f34b6ed188b470346f25b26583.npy +02924116-9bb3fe269e2356a983e4699e0a71dab6.npy +04379243-6eb9e1ec0365f5cce7e684d25d4dcaf0.npy +03337140-e877142c58eb5b03f2e2911dd34dc68a.npy +02808440-8662ec01d9c580827ac6ce513ae497d3.npy +03513137-6fea034555e60897e9fed33f81b1fa79.npy +02808440-d1ad479b9c04a9e6ae410fdebd404ac2.npy +02828884-6ef84eb436bf63de8e7865f75f64bf68.npy +04379243-133f18648797d149e27790b0ec8671f7.npy +03636649-42fa87cd27edca9efcb8d8c6d4df8143.npy +04401088-e633f997f4a47b2d727a08b50053320e.npy +04379243-9431f50b757b81fb15e0f0bc4a421e4a.npy +03001627-184c07776b38d92e35836c728d324152.npy +02958343-292ade37cba7f109e5eb989e223f7e7e.npy +03001627-bca76c4925b9a33177a7d775ec38a82c.npy +02828884-fc6c2a011ba0997cdccf03d91dc58d38.npy +02924116-570b7043031f05b6601e240e768fce7b.npy +03001627-beeb89082b38c83c992640a67216b77.npy +04379243-826b18241c9c2fa83eeddbccbf885e99.npy +02828884-9d0eb5ca2d849ff01f9ede15ab569b5f.npy +04379243-37f1637edfc6ca5ef51f77a6d7299806.npy +02828884-5aa59235750d4dce9953235c64bd990.npy +03001627-c7542e15626489adab4faba16579e3d8.npy +02958343-bca97563f170ff4ad2bcce019eeaafbe.npy +04090263-3ed5ea03e0eee521bc6e84bc30e573cd.npy +04090263-d07b1082474dfc9889172d41dca064d9.npy +04379243-54215af9f13cbb0c62d6ddeaf5a29144.npy +04379243-b444c5e5488806439b9e80c00bcf83a0.npy +03046257-aea16490befe0ce676e9713f57a5fcb6.npy +02828884-9f757c0acb5264f665ba78ad9601cf1b.npy +04401088-effeac02fe96f769146071e83265f12e.npy +04256520-2723924e712ccf1b98f5bccb3529a48d.npy +04401088-76a4a3e8370bdc24bd2d4107e8dc02b8.npy +02933112-19e444da148930154692707833167ca3.npy +04379243-4ba0563454fc10f365f5f793afed824e.npy +04401088-c8948cb8ec0f10ebc2287ee053005989.npy +04379243-fcf0e9c2aed826c7fdb2052f1980b788.npy +03001627-d6075b23895c7d0880e85c92fa2351f7.npy +02933112-5a935225ccc57f09e6a4ada36a392e0.npy +02808440-99fcd275c9f57ae044221bef0fa3c36b.npy +03624134-cbc6636d399803d1276c3d558130f8b4.npy +03046257-a630e09afe21e711f51f77a6d7299806.npy +02924116-c2c5217043ec617952470de2774d6099.npy +04256520-d3b0fe62f115f0588bd90ebf95555835.npy +03636649-35975525ec3d835046f58f62995211d4.npy +03636649-5f7abec29905605b1a19392327642641.npy +03001627-c53054060b5fb91beb0fe7d6b5545a1a.npy +04379243-14be1ed92182d2da722332c7d77935ea.npy +04256520-f551048075b5042d7d6d37ceb4807b31.npy +03691459-800a0a91308845b4519f3f3e6cd6d1a6.npy +03691459-16f4517d129ed54fd747b49524a1246e.npy +02992529-d7b2a9546b6f68bfd0659574aaccef0b.npy +04090263-3db828bb2a32a5f356c95a1e5409420d.npy +04379243-9f5ac902975f409e820018801b237b3d.npy +03085013-18a5269c99053eff1aea59cd55c902b0.npy +02958343-c2d2e3f46f7cc1e8ba69e14689f7b974.npy +04530566-a7707ea8482e4c3f925ef26228f6f62.npy +02933112-7eecf98d3b8f93a684c210032662e046.npy +02958343-a17d5aa16a529a88cbc76a30015552a.npy +03325088-35fa2ea1fc9f855e14b35a7d7cea7130.npy +04090263-7c53d8e4c566843b1e262ec64ad2c6c7.npy +04530566-921a5d88994aa99c71327f667b2179b0.npy +02691156-dbab9feed7e936cfa87372b03d6dc78b.npy +03001627-3fa2fccd96f3e5b5347185e772ead5bd.npy +02691156-2988a7a566ea79797209009cfb89d4bd.npy +04379243-e98dcd0334fa639fef9f898cda0ff409.npy +03691459-ebe84e8ccc8b5f3fa817854e3b5b5439.npy +02691156-57b5666dfe2607ea1025c08d338b6d83.npy +02933112-48b9fbf28fd33df5c59350d819542ec7.npy +04530566-799d446d33e604f990f7927ebadab5fc.npy +03001627-f83f1cbaf6c41a5db04cb542e2c50eb4.npy +04090263-f97e307455ce56a734e7e0c760ac1c0.npy +02691156-bdbc01a1bea50bdba6cb562d18000d3d.npy +02958343-e4c4167bc6b8e77dccdeba95a15fc6d1.npy +03001627-30e3af034e3dc084ddfd4f4b3d47049a.npy +04379243-4de6d195f07edbe5cd18e512cbf0ebf8.npy +02992529-29cf2bce2e67ae76264e721f309fb873.npy +04379243-c153d0d6b4fcf74f54a61dbdbc1ac262.npy +02958343-a7bc9db453e66329abc6b562f9bbf76.npy +02958343-36b23cc38786599285089a13cc567dbd.npy +04401088-35a0dc407f3df8d27450656ae41f00c0.npy +02958343-b4d7ad07dbcefefaafe1d4530f4c6e24.npy +03001627-4edfd09b8d7717cc579600e6ae92ac5e.npy +02808440-b3bd8f6d01d70f47b362845c6edb57fc.npy +03513137-3621cf047be0d1ae52fafb0cab311e6a.npy +02801938-3c06fb3595c39a4eeb6c29873b08c02.npy +03001627-426ab868a6acc7c6492d9da2668ec34c.npy +03001627-356fc758685e9054347185e772ead5bd.npy +04379243-a38405108fb416d8356ca1f9220b9968.npy +03636649-e487374a244b5f03b428462f49e66329.npy +04379243-20129f3c7b65b98b9856fa70a578baeb.npy +02958343-69492fdcd530eb3da6ce6972f601a2e9.npy +04379243-a7941c2ffe089884fff16555386d173d.npy +02828884-58e85d628f86aa897bd76190db9f54d7.npy +03001627-6dbe90994925f51c26fa92f330dec063.npy +02924116-83078ef9d6ef49315a50a5b89c58e20d.npy +04379243-a8da41b28b37833d14f6a05ceb8c1a6f.npy +02691156-4761e30dcb30471cf7d5cc24ec79e682.npy +04401088-3d1d0255e2163917f4ad1770263e7f39.npy +04379243-e047af849d703eb51933ffef19678834.npy +03001627-eb51e814c3f44a07914ced7dab3536b9.npy +03001627-c0857de5101f704f3c5e1addd9922bf2.npy +03624134-cab9d14dc07b7179cc34b900bb2492e.npy +03001627-a96226408895c2685e3c4d3bc6ac3be0.npy +02933112-28e7fd7a7a5ee8787d3ced6148bd0a15.npy +02691156-b6a1b55eb79a383542086bcdee59b1cf.npy +04379243-9d5718ed61c116ae4b3c42e318f3affc.npy +04090263-99c48010cc0c6405e1f2a1daf140ac9f.npy +04379243-868bab5194e93577858699aaad4acee4.npy +03001627-917e8fa5d1253398ca6a405498436716.npy +04379243-ff404f70bb77a5a876e4a31295619fa6.npy +02691156-2c64c521c114df40e51f766854841067.npy +04090263-3c42d32dee40f39a1ba59fe23593fa2e.npy +03797390-10c2b3eac377b9084b3c42e318f3affc.npy +04256520-9136172b17108d1ba7d0cc9b15400f65.npy +04379243-9bb7bbab61c5d4e947839bae1bc65257.npy +03467517-9a4d1c4535c3f3d2d872eaafa837d692.npy +02828884-d673c7ec4a08aa6db6f5e7b313e4eaae.npy +04256520-b0a85031201b0fb1df6cfab91d65bb91.npy +03001627-3ff879e891701079ea07bd8096c66582.npy +04530566-4e8a28d0659e430845aff212946058fc.npy +02992529-7d93b8dae79d5bbe7015d3b6f402d5a4.npy +03207941-a2ca291c8660a3465ea2d22d991d7d33.npy +03001627-d43f7db89fe864691e046801e2748f1a.npy +03001627-7fee792f0dc5d74cf2cf6a9bef44d625.npy +04401088-7cf110165b54e7511d3a21e67b7da85e.npy +03046257-e6e0cc99a9c6c104f51f77a6d7299806.npy +04379243-d3a1f88f644f36722f92c6319744ac70.npy +04379243-8b61fd451bb28c80c8bcf367bf7d8952.npy +02992529-bf8e0289ba786e97487d18402ebe69d5.npy +03001627-fba62693a28b2e4c43f1c519d66bb167.npy +02691156-4b623f70c9853080aac5531514d15662.npy +04090263-cadcb2e4e882ce75dd0a2071dde26395.npy +03325088-95cfff8a4333c320a70cb86be490e5e.npy +03467517-dbdf45cab0adbded1f260c1b356c52ce.npy +03001627-702cebffa33a19f019f079d1b712f46f.npy +02876657-b8767b71c2216dcad317c475f024f3b8.npy +02808440-a82d1a985717e161a3d8d955f4f42c39.npy +04256520-db7851745fb04cf732388c13cc4a0ba3.npy +03337140-fb6851a182221bcf14d1291d9f969ff8.npy +02691156-63ca41783e5d41f1651e8da9cf70afea.npy +02691156-9b285862ababfc3a68222c7df7dc40f1.npy +04256520-66240ded565b0927a8373ea4ea947e84.npy +03001627-94f5c52453dfea0b6606be97908355b5.npy +02691156-5fed73635306ad9f14ac58bc87dcf2c2.npy +03991062-57a71b2cad845a76fbd91d8fa434e93d.npy +03001627-fa7347547e290732bf65e1af50b5b7d4.npy +03636649-77fb025b8a2314787eaeab1f0c9120b7.npy +02958343-7cdfcbaec700fb98d230ef808f13e7a9.npy +03691459-1445e30aa2d3212db6a78dbbcf2e408.npy +03261776-b71c9a055a7f45c759af6c3da8aff0e6.npy +02933112-b56494e8810764286739a7caa0c577bd.npy +04530566-8849abb0be0a0ca99cace9782a7cd30a.npy +03636649-6b7a76b841ad8bb3488017d48a7f7eb4.npy +03001627-3ff4401d898b488a601104cd2d998272.npy +04379243-fed82f2ee0c82f97beedb4c8fd29e2d1.npy +02871439-77d1e531262c00a9193fc676f19b70be.npy +04379243-ffe1c487f7b9909bfebad4f49b26ec52.npy +02880940-441cac4bae5c7c315c2a2c970803cfe2.npy +04379243-f80427c47d2fc4169ccce4c6d5bb195f.npy +03001627-326352f7a20c31e2e19a0cc107ada7cd.npy +03046257-143e665cb61b96751311158f08f2982a.npy +04379243-9c1ff252b47f13055764829adf9a789d.npy +03467517-9ccb3f9179bf47f8b9689591a51e7ce7.npy +03046257-18299916ec3e95bff5ca1792a289ecf9.npy +02958343-8ffc484a850350f916abce8cb03e7794.npy +03325088-e9c737ddba0610f33321831d2245cf06.npy +04530566-ddf03991440ea0d15eb13ba95b07c9cb.npy +04090263-fe286de2443835694aa96bdf46776318.npy +03001627-3e1e1070ed7a0ba67484091a041fe77e.npy +02954340-ed52d2c2a9c1b606cf9bbc203a5cff99.npy +03001627-ed9d0bf4b699c2e86393e0168650b62f.npy +04379243-ead93856b735ec90f0aeabfdcb4e1dd9.npy +03761084-3c475e459a7cf86a13508f8f9877b42a.npy +03691459-ac6d3202823055dc1918763f44383273.npy +04379243-8d2e17e38a624565fb70a55ca9d14169.npy +02691156-8238cca88d753930a23a96b0250afc71.npy +02958343-a1d85821a0666a4d8dc995728b1ad443.npy +04554684-29561b3ac0b7596cb23717c90dbac0d.npy +03624134-45e28ff647b388e12d2336c44ce1b2aa.npy +03642806-62818ccc8dd6a3ecb300959c6f62c5f9.npy +04330267-c2adda9e5b8a94dae7822b3160005e08.npy +03467517-1c374a198daaddc493f0194265a9746c.npy +03001627-bf9ea87a9765eed7d53b73fe621a84b4.npy +03325088-19ac42daf0dfd5f454d7082b34825ef0.npy +03642806-774f062adc4130eca309fc846e6b0c18.npy +04090263-af6601f4d67d85e9422881265f219fa6.npy +03001627-62127325480bec8d2c6c98851414a9d8.npy +04090263-93de686cc189544335a8ac768bd119f4.npy +04090263-53b50183730125e68c0007e5a8235290.npy +04225987-9eb11450fa872445ad8005b08617c09.npy +03624134-95d6e8797064d09ea4dd752ddde80fb1.npy +03207941-a238b87f02c5de1edf3a1b0d597ce76e.npy +04379243-7a22c6cba42b73cbb5a356b3f810d217.npy +02747177-c1b3e0b6930003fa3b146c3414841312.npy +02828884-3f8d7d662c9cd90bd6abb4efd157f402.npy +04401088-ab47334a425e1650bbef66962a25aa5f.npy +03001627-d3f393615178dd1fa770dbd79b470bea.npy +03211117-ab20e7f54f10bd0ec1f8c53978a2ad35.npy +02691156-ae837be3456bd54f71d03b466c72ce41.npy +03001627-3022c71659584118c62a9d560fc45fe6.npy +03001627-9894e30c8c7f7e56eaf35c5a2cc7d71d.npy +03001627-45e2cdf1708680822165c54dcecaacb4.npy +02691156-22ed115500e9648c5fabfc69ee61b28b.npy +04530566-8ecf57984f77fe84583ae8949bf11b56.npy +04530566-2228242cfad46b73a0928eccd5f75d69.npy +04530566-e6d6a78f53ed5a34d0a07165a76e5a8.npy +03636649-8d93a9b663a6378ef5c0c3f661e90ca2.npy +04530566-e3c5033a9367bfa5a6dc0341d8503142.npy +03636649-4bf29c47c18e7020fcb8d8c6d4df8143.npy +04379243-3558aeeb9698722acf19858fd1963d10.npy +03636649-8c4ca1f645def5efd5cb6d178687b980.npy +04090263-51a327bfd4cbf109a06a81572261e82e.npy +03636649-41fc6d8dcf353f9ae420612cf7bb547c.npy +02958343-bfa01c632be2eb06e8a3b392b986583.npy +03001627-27a8827b0ba5d743169bfe841050f4a4.npy +04256520-16296126c5a0b92ea597952f9a39cf73.npy +04379243-4c55e5b0eb04f854297c137c93a4b9a5.npy +03337140-2f449bf1b7eade5772594f16694be05.npy +03636649-57f1439f5161b8d366cff95abd9dc80.npy +04379243-a0fd031270822841febad4f49b26ec52.npy +04379243-aa2b82f576f3df62f51f77a6d7299806.npy +04090263-61204e00cd517e4e9d360253182ac1b4.npy +03691459-9b7001c69e6f1978bf518c96c02a8c5f.npy +03790512-152de80e31b016d4ced49279fbb1dcc7.npy +03325088-e26918664dbd68eb7a867e9b35a1295.npy +03001627-aae036d8ebdc472535836c728d324152.npy +04256520-fe48d9b6cba42ef214fa93b6acf93e82.npy +03624134-c71280ea272fbfed4b7644126b1d71e0.npy +04379243-2bc3439a36c0518b4b3c42e318f3affc.npy +04468005-2ae835c4b5d1eff25f72adf4b0bfab9.npy +02924116-b657b823876fc62b8449e0b8dd14796b.npy +04468005-efcf0fbc2d749875f18e4d26315469b1.npy +02691156-240136d2ae7d2dec9fe69c7ccc27d2bf.npy +04530566-3c8dc4a3621674aabb29ab7e4f889a04.npy +03325088-a0bb3e71fa03369e843f813f752a5e35.npy +04401088-ee7ef8b40cc2c90d6b7170bfc4da1f8.npy +04379243-dcc24b55654a9e6bb65b71636c46ae49.npy +02958343-8aa5d1c7ca4e3f2e61b9ff60b1be412.npy +02958343-1ee4f19fa617ec5949493d905c02fa86.npy +02808440-acbbca9c00c87c81c1a9d86dbf500665.npy +04379243-59c8b38f75ae93bf785953e8e787ef2a.npy +03001627-112cee32461c31d1d84b8ba651dfb8ac.npy +03001627-317b404839dea88d827b401415ba9e3c.npy +02958343-5dde5594b4e9e86ce60ff101126e254.npy +04256520-c4d65d8701b7e9b977e95ce4d5a0e556.npy +02691156-92306925325c9e8a3f3cc56bc9bfcde3.npy +02871439-d998e75348902a511dff03f33a13aa77.npy +02871439-c3c8f8d5a5dae6c2d42b9650f19dd425.npy +02958343-cf39999d7c9e2b4788ea3c115b90ce56.npy +03467517-1a96f73d0929bd4793f0194265a9746c.npy +04090263-56d737fe2e8ec9d81fa5c14a532505cf.npy +04379243-5807109a9db7124e894dec385705c4bd.npy +04379243-ee6ab3dfcd7757bc6f2c5bf7cec019c1.npy +02880940-899af991203577f019790c8746d79a6f.npy +03467517-8b005f829bec6bf263e148e250c0340d.npy +02958343-df037c72470d33217fbbc45f009914a6.npy +04074963-9fcf820f1362798e1c990bbe4403b3a1.npy +04379243-2e0a8f727d87045818e800f0d88f9019.npy +02992529-c589332137d854a1808ba9235495a934.npy +02958343-4b092065568af127d64c207b9313bbaf.npy +04379243-194fd39afab11888b84c578d4c100fe6.npy +02958343-1ca64f9d6e008fb35fcb05674109534a.npy +02691156-c8143c3384690147d13ef00338ba8c52.npy +03001627-bdedbb7887d2c1ac6a45b3b48c00378.npy +03001627-a08ad49c281128ea53615647c93fc704.npy +02691156-27acb1d0e8c808262347b4731688b0f.npy +03001627-ee665ce6679ac8cfb502ac2eb9128f9a.npy +04530566-2a569537a0f6abd34b5acb1c7aa990eb.npy +04225987-344e9402d06bd94031145076011658c5.npy +04379243-15be511a2433482aa192483aa282f8e5.npy +03085013-4b13c682d58bb2184e7e6a507a54ea94.npy +02958343-6f2e76e362ba6c73c0e3666c7d0ec7d0.npy +02958343-32e6ee437b8fa3fb5e52943dcb52313c.npy +04530566-82138919402b3b8f642f9e27aaf0c47a.npy +04530566-efa85ab5aa4704d299429033f40f0f8b.npy +03691459-91f4c25e1e325683e7ac477bac77def9.npy +04379243-9a762e9ca86ce96da5e3e028709e0474.npy +03325088-a4ae53ecdfdf393593ed75a828b3d239.npy +02691156-523f1c2392338cf2b7f9c6f6b7bee458.npy +02828884-d9c927569da63ff92ebeb1e6a8111f53.npy +03001627-e807c535765fbbbab40f0ac0fb9a650d.npy +03991062-606895063559fb1243c090e8cbe314ff.npy +02933112-863deff7bdee8cdff51f77a6d7299806.npy +02924116-a8783a6095646146d2551af1d853d82.npy +03636649-7a3abc9f27ffaa0418a6353ea60f11b6.npy +04256520-a1a4f5670251b8314b35a7d7cea7130.npy +04090263-68b0af57466b5a0d735fa1ab17311ec.npy +02958343-eefce52130d223ba2dcbf88f7c685079.npy +04256520-ef5eb51bbb7141c119fb4103277a6b93.npy +03001627-70ac5cb405df84575e62305d14755686.npy +03467517-36b49aff54f6d7e893f0194265a9746c.npy +04379243-14130d541c4a419df51f77a6d7299806.npy +04468005-311a3ef41603f86c3f51596dfebf9893.npy +04379243-6491dfcf1c9782154932af0c4e356b6a.npy +02828884-e3e3c49caf4b1885d661ff085a0f14b7.npy +02958343-16d6ecc22218e21b36dfef0450f0ee37.npy +02691156-aba51f26f4da1b44b785bc4e6e3fb739.npy +04256520-3d0575e2fbf2ed5c99e1e63653e7d97.npy +02933112-7e06d12a3db817df7f07552c1b0b212.npy +04256520-a19aacbd84e0ddd92bf36b92481c5940.npy +02691156-5ff1cd7d4fc48c864b6d6a3a20b9f7f.npy +02828884-eb940ba9c22e793f35f2c389ea4da425.npy +04379243-9954b8f6fc40f0ab1cf96a5dc33e37f1.npy +02808440-ea9a9f6922adb1b70c61a2b7d6910c.npy +04379243-11084af510183635ee56c4ac0904ebb.npy +04379243-884589066f028f237d3a650ebc940efd.npy +04090263-78a1e4efeac9bb6f55d33831e71fa52.npy +03691459-245ed4407d4cead6b9c1ae865c9193ec.npy +03001627-7f523cf6780aaeda2a691a30a5c88605.npy +04530566-296c315f8f0c7d5d87c63d8b3018b58.npy +03046257-e82da3357403f25376e9713f57a5fcb6.npy +03001627-1031fc859dc3177a2f84cb7932f866fd.npy +02691156-8ccaaa2429c01bd15e33fa4a58c78442.npy +03467517-8f4974d21383c817489afeb4f07ae3cc.npy +03691459-6ab218aba38bdada2268dda5c324173f.npy +04468005-9ee93d31c7fa7c20a5a56cb268819922.npy +02992529-39b78390f8d5067e983a0c5c52bdbaaa.npy +02992529-e8d704bfd9b6c7f39af985c9d0dd6085.npy +03636649-c41293c84dfc509cfcb8d8c6d4df8143.npy +03593526-216d97aaa039609555f46d55537192b6.npy +04379243-e52a290532a567aefa10901ed3f9da3.npy +02691156-cfb555a4d82a600aca8607f540cc62ba.npy +03636649-6f6fc4581830b1c49ae96150e853545f.npy +02933112-7324733dbe394447e78cc773ba5d9e52.npy +04530566-806834c2b3c0bce7989a4a13be837150.npy +03001627-e5ce55d61830cc017f1cdfc0a8f38f2e.npy +04256520-896e8970c81b33d068b6f94bb42f6cd5.npy +02691156-93c3ce7904b3258b2285a9bad03a0ac7.npy +03046257-23fc56bba1889c2e970d557f49392fb1.npy +03636649-204a4eb580e93c559d709998b2d6e774.npy +04090263-39ff99d67fd7eb1f4aaee15c65289469.npy +04530566-7b602de66f5eff247991cd6455da4fb3.npy +03636649-5aefcf6b38e180f06df11193c72a632e.npy +03593526-c2bd95766b5cade2621a1668752723db.npy +03001627-cbbf0aacb76a1ed17b20cb946bceb58f.npy +02933112-c4fd6d64caa1e371c59350d819542ec7.npy +04379243-6c763c259b83b9bcbeedb4c8fd29e2d1.npy +04090263-54ea995ca2645fe0f4c4f1f541cfa2a7.npy +03001627-b2c35c8b748491a1684b7bc3f8a9aa55.npy +04468005-a260584cbbf5c65eb73b721987a4f9d.npy +04379243-1b33172342f58feb76963e5e6f4f642a.npy +04379243-d28e03eaf042c33d714531f0291497fd.npy +03636649-5680570f242c595255ee7d0585fd5223.npy +02958343-57e16ac1b026db4e350d065ac10959e0.npy +03593526-4d054c0a0c2fd8e4503adffe35460705.npy +03001627-303a25778d48a0f671a782a4379556c7.npy +02691156-fb01b45a0659af80c1006ed55bc1a3fc.npy +02992529-7757585cdde7953d86ecff2582325794.npy +03636649-c0b0d7e15d3dfab1733c22d8b8e1c33d.npy +04530566-8480865aa92d13dd46687b3834d255fa.npy +04090263-212a96dc292df1bce1f2a1daf140ac9f.npy +04379243-91282b5e9c019a1944ee2f4962f1290.npy +04379243-c7f4004cece37b4bc08256cf85537e.npy +03513137-e4ac62dd8caeabb1f80d3a620e00dd9a.npy +03797390-c60f62684618cb52a4136492f17b9a59.npy +03001627-624339070f8a749260c69156bdab9446.npy +03001627-b932d245e5e9f98b504721639e19f609.npy +04090263-1cbfb1c063b34ab4ab379c9b5bf12bf8.npy +02828884-a6c3eea17a4b455d75b557dd77720f6d.npy +04379243-b62f2d11c2aae12cc54baced9903a02a.npy +03001627-86e15a077ee6f438910979f825490a99.npy +04090263-fcb3636dd82e1c37741da1d923dd6a96.npy +02954340-138d0b89ab5b5fa52821bf1aa3b19a.npy +03325088-efaff4f34573d23caac6c989b01c7.npy +04004475-13a521e846eaa8599c6f3626936936a0.npy +02924116-1e0ecacc02c5584d41cefd10ce5d6cc0.npy +03211117-31ea65d446d980162a544c9c0bfe248c.npy +03001627-52a7930e87e75591a78e44eefea09073.npy +04090263-d6ab580443ae008d6a2345809e2bb169.npy +04468005-e0468c8448d92806bbdb7391763a8729.npy +04379243-a860f37217b12b26bffdf578c739e217.npy +03790512-242d8c07fabbdabc78fe949fc1419876.npy +02958343-358ddbe8b39125e9e81913b1de19c3f7.npy +03001627-6b91f4fb8cdcd6f46fe24f5659031935.npy +04379243-5f64c977d89c2417e2059182b9d400ca.npy +04379243-665a646e8413fb17fe537547af4fdabb.npy +02801938-4867b23ae77c1c2a490ad276cd2af3a4.npy +03691459-5da457ae73142749280e0c1e89a63998.npy +04379243-9b91c3d35057b2f93eec26c23f5bc80b.npy +03624134-6ca0db952c7e2169e2bb19fbad3e4596.npy +03337140-46ec29cd38a7ad694c3aee8e9d3a6ffa.npy +03636649-e1891813cf904b3188e7efbf7ff736b7.npy +03001627-d7b8189fe69cebedc41b07b1627c4b43.npy +04256520-d1016939207fc52841b7cd2d531f3797.npy +04256520-823219c03b02a423c1a85f2b9754d96f.npy +03636649-b4e939adfc94954a276206fae5d3c473.npy +04256520-6e4ea95fa805aca632a526e2e9a7e9ae.npy +04090263-169bddb624e60dffb6c8238440c79e2.npy +04256520-8ffc9da1ad2dffb3200d50e893131ba.npy +03261776-ba1ba6d3a76841132e398c137a41081d.npy +03211117-31c2bcb49eebce088198059e96f7b9ac.npy +04379243-50882181ce7f2bc1739680f4e31f35e0.npy +04090263-5c463ee11ad412ffc75e2dd4efaea578.npy +03001627-6ecc9a0b03cb8bc2d2b12aa6a0f050b3.npy +02691156-520382dade7695c4906bca4ffd4af837.npy +04379243-8b4ec70a3c1283b1fb5f8baea920e189.npy +04256520-86b91784e9f32b8f10edd100dffd8d85.npy +02924116-b247dc34286641995d04635357309588.npy +04379243-ad746c9c7f7548be7608168119193cbf.npy +02958343-261d55ef790a2da187bc776d46f94d3.npy +04379243-8d177d02c291deeca7f2f03d5c90e79.npy +03001627-2581685a8aeff78b713decb1a0563b12.npy +04379243-415a08a66b8527519f803a8da27dd9a9.npy +04530566-94e1c24d7f205a39779adafea0303e70.npy +02958343-2bfcb2381581c05a95551e0d9e50cb0d.npy +03790512-9d3b07f4475d501e8249f134aca4c817.npy +04379243-637bc87d013b1b09f51f77a6d7299806.npy +02958343-721ef3846535bfad179005454847728d.npy +03325088-21b77fd7e71cc47ed773a8448a79e14c.npy +02958343-8783151b8f23f41144ad526dfb20e2f9.npy +04379243-2e632844af2fd0892ad0b8f780281bcb.npy +03001627-38d000cadbd439da63be0260dd648a5e.npy +04379243-37bed46307d59fa5cc4dc0a78fc422fa.npy +03001627-493b8b8eac5d3de978f8b40f4a2ae98a.npy +04379243-6dad3b17869cb20fdf94ba6a907dbe8.npy +03691459-665dfd9711b2a3ece4fcc1af3285ca51.npy +02808440-f84308c16a081311ccd0340812259a39.npy +03001627-95d83e52954e1ff2d19175e7d19b7cb.npy +02691156-2751a0d9a1effa41f0b8c8d7a19e0d9a.npy +02933112-1834778d026108e0ce5d6e9371bb5c33.npy +03211117-441c5d2f78e1100558ecbb7ebe658148.npy +03325088-7525991c21bda36c54d7082b34825ef0.npy +02933112-21dcc3c0485b43136473d8f2b21437da.npy +02958343-dff1f351bb34fbbabecf71e2e014ff6f.npy +03001627-73428fc75131e0a9d8dd12a67280079f.npy +02958343-8c6c271a149d8b68949b12cf3977a48b.npy +03991062-de23789ce3b881dbe42c56b45979e3cf.npy +04379243-d312c70dfc7017e9c55161a63fbd109a.npy +04379243-1c8121e1ad6cd6fc7a480f3f1d55ed3f.npy +03211117-76d351e5df26f91fb895bc5ff828fca.npy +02958343-eb575f66bedfeaf629ebc23acefb248a.npy +02876657-de71aa5eca9ee76a95f577622f465c85.npy +04379243-156ebd353a36f36ac3bd24f986301745.npy +03642806-a923fbd2327097c6e95cd0dc8c2f0e83.npy +03467517-6f456bbe112de70993f0194265a9746c.npy +04379243-60365049ca80d98b77e620d253d331c8.npy +04379243-23aca164c7b2e2d4ad8af6714b643432.npy +02933112-7bdeadcf72ee257dce5d6e9371bb5c33.npy +04379243-5c45f8d68b676f634b3c42e318f3affc.npy +04256520-37fa77e9e48371545397d07b571cbcb.npy +03636649-d2ff6b9d63c65ab71735ea0e092a805a.npy +04379243-664c6792448950dec19dc7c5f46bbf55.npy +03797390-649a51c711dc7f3b32e150233fdd42e9.npy +02691156-6cf5d850b55bc9f990b1d6deb98feec6.npy +03211117-76d87469c1fa3638577ed6878ebb1511.npy +04379243-af5fb0179304e7c48cbb8bac2032149c.npy +03001627-29883092cdaabd09b41b7625e8c42dfa.npy +04379243-1469f244a1968345e2d95336601deece.npy +02958343-e56749ccdc861495b9e97c7f06f23bd5.npy +02924116-748f9e642180de12481aa8b5531c68a9.npy +03211117-df5e129b50eb2f253bec56bff764ba78.npy +04256520-e8524ce4800693ad1aab7fc1a7e09451.npy +04379243-1a5febd8d65b97e4f4b6538438a0b930.npy +02747177-3b8ee522cf6c207063b2acb037dfbcde.npy +03001627-64ae981900a1c1a37753393bcfa5f775.npy +03001627-328685b8dd3a7353bfde9cad2b5fdc64.npy +04379243-1a15e651e26622b0e5c7ea227b17d897.npy +04401088-5a65ef748eb3a3d1ec475b573e4d1a38.npy +04401088-9f6acb21f86a88d93ff936510fe2e02f.npy +04090263-377f4054812dec1c9f433921788191f3.npy +03593526-28938abdb2114e53bbc7a6acbd8f058b.npy +03636649-bfa83d8f88e91d3fed83d50637042c60.npy +03001627-3aee7c282063723d8a17805dbfb751e2.npy +03001627-7862b32132af278f45ce8baa9aaad5d5.npy +04090263-68ce5805f49f8484a90f0d3f07dcdbc1.npy +04530566-e2f4c0d1c8b6e26549e3c7e37819c26e.npy +02958343-488fc8215ab4e5e02edf5935f10637d1.npy +04256520-d2a3268e85d81c6c6bd365389d6dc6e7.npy +03211117-ea4b90cca359e2d38b9be827bf6fc77.npy +02924116-2bfc0186f3f10b3174a16879fb3ac81f.npy +03325088-34152f014bc3955d188386a1b5f2f907.npy +04090263-966fb54dcc7bf00ba3fb48700889ab3a.npy +02933112-17d25c26485edcf94da5feafe6f1c8fc.npy +04379243-527458cf1c581025d4b7f1dc8ac42b22.npy +04090263-9d969dabaddc27568bb83d47cdb90d09.npy +02828884-9e4391cde5446bded98cca8f0ccd5f7.npy +04090263-580f6487cf149c497504cc74f24f0eee.npy +02691156-844d36a369cdeed3ac4f72bf08dc79a6.npy +02958343-b5a6e71a63189e53e8a3b392b986583.npy +03001627-ce242d5e5e3f4befb13cfeddf8d6bfe0.npy +04379243-c516c27390cd9890f3a67cbaf0fde1bd.npy +02933112-3fcb5eaa202513bd2f815a05dcd7ddb5.npy +02828884-5cb40adcdfa5247681faebbdea6bd9be.npy +04379243-f01ca36bab1a7a1d9e9583a661702ed4.npy +03046257-d08469a971f560102ea413435dde1792.npy +04090263-8560fbd0b90ff133b96aa5dc23c036c.npy +03001627-d6203deed1b54c8279b3e1be3524f72f.npy +03691459-1d7af68d31944c358a0181490cb73cbc.npy +02828884-b695128faed7cffdad5067eac75a07f7.npy +02828884-300781592a3dcc2313e9164feae00e7.npy +04379243-233c497df4d252aea5e91f4d594e20e6.npy +04379243-59b6e5cc2b4dab5ebcd25191f45283d0.npy +02958343-30f96aa701d4e088becf71e2e014ff6f.npy +04530566-9a20ab78eb6a5e7af7ff315fbee3c6eb.npy +02828884-6ec0ed3fc05dc7b7ad5067eac75a07f7.npy +03001627-30083f20e81ba69b593ebeeedbff73b.npy +03211117-ecb96d46eca5724fef0411fcb48f0299.npy +02992529-9fd7db6d334e6acab29f572d1167c0ed.npy +02828884-8d40e13e8d27786b5a2cd0e0d44dc51.npy +04330267-a82fa198411f80b272d42ea0c136b6e.npy +04090263-7bd5febaf49a0cd44bec850c6c6ccac1.npy +04379243-b5a3017da6739ea0c46152dd624f1d49.npy +02958343-78ff8795f2cce2f7bedced414fad522f.npy +02933112-a8e160457848a8be3bba238110c3df2b.npy +03636649-b4c69d04b835bd716c8ef569725a5272.npy +03691459-4c944233440d87f4b8e9f7eca3eb3e3f.npy +02871439-3a9d74e3bdefe4107550c20897273f9e.npy +04379243-4a5fa41eb0fff4496316c951e41c61a5.npy +02946921-a8d4a3b32149d3ae4f0b8af4571b1440.npy +04256520-51a14c2d62a2963d86234e915108e6a.npy +04256520-6822eea5cf7f5fc9d92d669b28d58950.npy +04530566-c74dbde6656efb4eb4248d66f92b2feb.npy +04468005-865dd76030699cda623728a0bfe80a.npy +03467517-33bc720b6836bef4c69ecd2ad81e89bc.npy +03991062-a46b5662ee7e2985c3648f83bb1262ce.npy +02843684-d5171f20e202b8aef74a754b7c345792.npy +02933112-a06df01467d298caac51268fdb437a9e.npy +03001627-cbbbb3aebaf2e112ca07b3f65fc99919.npy +03001627-d29bc9defb4f021cd1e6c0ed5832129d.npy +03691459-8dc1e06a23a2fdb7c77445c6f0b20418.npy +04401088-6e18484e72c79bf6943bfa124ea09a0b.npy +03001627-46185164829c492c9dcf2183c858e6e5.npy +03001627-49b38e22f104005ecbde89e0c48a01bf.npy +04379243-3fb8797c780710e45213cec267286d18.npy +03797390-1a97f3c83016abca21d0de04f408950f.npy +03636649-12d03f06746eb49990c2e24416edfe5b.npy +03636649-f0b6bf1a583cd99169d13a7b2498cca9.npy +03691459-6575a80a0daca56d1b37f37a4873fcf0.npy +03337140-109a19840a8fbc774c3aee8e9d3a6ffa.npy +04099429-a507b5c6e6cd71a191347c63d1dae43c.npy +03759954-1a2e3602e54e8e5f4fdb7f619836e43d.npy +04554684-ac2fd0b05d956f7a589577ccf07b31e7.npy +02691156-59209cb5ba7a34633e1e5609a53c0477.npy +03001627-6016c2e4f5d5c2ae181fb5b25ff8403e.npy +02828884-388d83f25e045007efe85e37dd46e84a.npy +02691156-c9620ae77d3eb16ea3123c495342b850.npy +03325088-91b9542a41c2c80dfcff3f0bf2219ec7.npy +04256520-c00d5c9b043b600019fb4103277a6b93.npy +04225987-70c8f82bf6a6fef2db8b0e67801ff73a.npy +03691459-d5f20697fdea1b20fbc9490485dff00c.npy +02773838-8569a0c606bbba73d9985ad45fbb635e.npy +03001627-5cf26a5558580c8c75a82b88fe6e733f.npy +04530566-93de96748cab511731205bd848315f04.npy +04530566-41032fa8e4f632a5447ea5854b3cf405.npy +02933112-e1ff64e53154ccfaf51f77a6d7299806.npy +03991062-9d200849933d76c52c528d33bca1ac2.npy +02933112-1767bd876a8b8c6e4da5feafe6f1c8fc.npy +02924116-5dedf1f1c3c1eb461759ca9eefe0e251.npy +02691156-b1deb3638098e9c92a4947824596dce3.npy +02828884-ecbc04934735cbc852dff9108cf86a17.npy +02924116-d493568e7c343bd6378953424bcbb407.npy +02691156-8add45a11c9fcb446eb5821e78d8898a.npy +02933112-98d963a9f353cd026b0f9e3b3feb2454.npy +03001627-5ef0c3e89d51eda2d62069fe2138d0b8.npy +03991062-e4f8e15dac885beb846aeca11136b56.npy +02924116-e879b8f56a0bb33ae87bec97f6a7c3b7.npy +04090263-4c41c172046a4a5e9a6e43b878d5b335.npy +03207941-f4d152d2ffb8b2d9f5f2f72b977592e.npy +04530566-5c0e6663c131610a2c3770cecdd58208.npy +02691156-2c89cc6eb008eaf5ca8607f540cc62ba.npy +04099429-d9b0e3cd3ce4507931c6673b192319d8.npy +03001627-6f84118b912eabbd4587e90e2fc67ac9.npy +03624134-7bdab5035a80cc52f361b515e2f5c19f.npy +03001627-fd5ac9b342fe518b9d3ea1c6b57a0095.npy +04090263-d8e64f106fc611c186029a2be51c0321.npy +04530566-5bc0bff4ead8277b421dcde4f714e772.npy +03001627-6cf6140483ba1b347b11ae648ea92233.npy +02958343-9240401e750395b456fd4619a315629d.npy +02958343-73140624a636925ada37be44e2d84539.npy +03642806-6c6a96e4486cc02cda66ecbb2c411f37.npy +02691156-951358ab93e7380c1ccec171a275967.npy +02691156-7b6f528acc10d3fbcf5b9c6e0c7ce895.npy +02876657-af853a8c58d2b631992eedbdd14b936d.npy +03636649-6bb38bc6fdb6adc359c5c7ba83ec931a.npy +04090263-8369cd1bf3c6f377504cc74f24f0eee.npy +02818832-5d12d1a313cff5ad66f379f51753f72b.npy +04379243-7727cc0cb47705632dfc2f8d5d30193c.npy +02946921-59dc6215c5eeb1ee749d52b3e269018.npy +03797390-2d10421716b16580e45ef4135c266a12.npy +03001627-f46ccdbf92b738e64b3c42e318f3affc.npy +03467517-46e8a39b49acb800cc766ee9bece4aca.npy +04401088-86fc58a0c40316f2562c8e1ac545ef78.npy +04379243-14e00e9bc6ea1b7230bbd4cddd04c77b.npy +04379243-61b88b501933ebae8f7068c66465c4d6.npy +03207941-5776239d3e133b68a02fa8dacc37a297.npy +02958343-8a28abfb5751e767b9f455b31f6fc3b6.npy +02880940-47175c7b12bf0b61320b691da6d871fb.npy +02958343-bbf84d45735af3314dde7b6e74a2cede.npy +04090263-57287268b594fb3f3a653cb492d78488.npy +03211117-dae83168187a9ef8628fbfd12f0feda1.npy +04379243-abeb8fa38979d2fb9d46068d27fb8249.npy +02691156-ab35aa631852d30685dfb1711fe4ff6d.npy +04256520-86a7258b0f094aa6a3fa78fb8c679d78.npy +03001627-3f8d0d53e2bd74124b3c42e318f3affc.npy +04379243-b8c0ed645cce028b3fa313db82fc9cef.npy +04460130-40ec49e3e3147508ca9081e720bd7dff.npy +04379243-c4ee00c87688f3b0b161476a346db176.npy +02958343-82720b201a7731e3b376886260eb15c1.npy +04379243-ea87ec56cc2fe88fb20577fd2a0fb434.npy +03001627-b6457a76f24de9f67aa6f8353fce2005.npy +04401088-a86eec9735db06a8226bc3b9ce9ff2a1.npy +03636649-d3f84442201b6c137fb7f79251dd7727.npy +03691459-3e33b290c010b3b88bc9d953a3f1955.npy +04379243-f66d010471970cf0391e4d6c585a697a.npy +03001627-f128d707527eb10cb04cb542e2c50eb4.npy +02818832-1f6eed9be4aa249de76bc197b3a3ffc0.npy +02691156-dae96d5eb7dd6fcd2863c6a2c8157d17.npy +02843684-80337f796ef8859a527f76f3d3db2f8f.npy +02958343-1cb102a066270f79db1230abb5fc0167.npy +03001627-33587d34aab902057add36d8e31831ec.npy +04090263-6f09a5d74998c8ec49a3c1009fa79820.npy +02808440-3cb7df6d3fd900acb0026ac53ebb5587.npy +04379243-7257fc99c253994c6fd6654fda9ac5f0.npy +03001627-4ef623a1f272c40019fb4103277a6b93.npy +04379243-a86b48fbcd775bb16cff9b44fdf0517e.npy +03001627-83839b89dd91996c7d910d51d878f708.npy +04090263-868aba7b4da060a3683e3750b53385d5.npy +02992529-bbbca195cd6b85f1562c8e1ac545ef78.npy +03636649-51634562e4cbb4be27c4ca11e0316b1b.npy +03691459-5072c19da106b95583247f812f2eaa97.npy +04090263-9cf5486d4aaa5c0dd107072754c68ce7.npy +04330267-7c82a4c439803269eacb651f5864b906.npy +03001627-9de69e28a07c6e10592cc471d13e2037.npy +03001627-7d8e6b132c64d909b161f36d4e309050.npy +02933112-26d924cab0c8e8f348d189f942cedc62.npy +04379243-6278f1b6aa0c85effebad4f49b26ec52.npy +02828884-14b63361a48a9fffe4a048c146e8bd43.npy +03211117-763d4754a37cdb953c491389420760.npy +03001627-accebea3a0e180f0812e3ecbeaae3980.npy +02992529-dd02413772656bf5f6cc8d1cc08b421.npy +02828884-cd1077a52f972810cb2a965e75be701c.npy +04090263-e61d4911c7142c65d735fa1ab17311ec.npy +03001627-f2075f1c3088a167cf513de9a02a2561.npy +03636649-cf6c082b9534049494db33559ec0df30.npy +04379243-64adf1d226e4a0894f4d213d7c852596.npy +04256520-9a88dcf980a527cb4b3c42e318f3affc.npy +04554684-3ccba2b436b03aa635325a5f07346e1b.npy +02958343-e90b0381a7c8841c1c65421fe734e7bc.npy +02691156-4658a2fb7353f839643ae903098a314.npy +03928116-6beccfcb76d8dc3fb12da0b74652c93d.npy +04256520-4146cfb4fce9055bf51f77a6d7299806.npy +03928116-a9ae9e2b1e80fed6a519a2fd2539c0b6.npy +02691156-5f11d3dd6ccacf92de7a468bfa758b34.npy +04379243-ed554b9e04b7f7eee7be13c697329304.npy +04379243-7e833179b58ae9ec115e53c2ed23d57d.npy +03948459-1e9955ac94f8facf9e272653667f1619.npy +03001627-a7e33746f41cd181e258d1c3e7302e7b.npy +04379243-214e52abf34b4e18ab96a46a16fcc9c.npy +04090263-1fdccad4c0b826680685c30eb1daeb1.npy +03046257-ce2c4226c28a7f51ffe3432ba4f2e6d3.npy +02876657-cec14f91bf10f86e8291825d073a05e1.npy +02828884-6887f90a83081b56a1ebafc9c1beded8.npy +04379243-9a294d3a661f96a3c98555c181f6055.npy +02808440-885497f2bb3cbd3c859d92988090f02a.npy +03001627-1ad766f9e95ce308aa425ecb668e59de.npy +03928116-532420acbb08cdb410a322420f6f5d87.npy +03636649-5383c9b60d5b66a2d22730b0728b2fc9.npy +04256520-c2e4095266254bc1948a3bd895ea5ecb.npy +02691156-f39e0412290bcc714917e69390d054d0.npy +04090263-216637165f69a2b5be0132953bc535f3.npy +03001627-19a3ac2ec0312e13c8687ff9b0b4e4ac.npy +04530566-320b3f040f6d5147ab87075c54b494cb.npy +02876657-a00a9d045b69171472dfe26068766359.npy +02691156-2c4228b79cf44778b96ae1a0a8b84ec.npy +03691459-d05c2dfdb34f38433e8a91ffbc9ffd64.npy +02958343-430941674faedcff6436916a86a90ed7.npy +03642806-1622e466794cf72998536cff5312b747.npy +02924116-a7791bcc705e5a4ee9479f80dcbf204e.npy +04530566-2e958577e7756f59bf9717d602b327f4.npy +04379243-3585c614e9a6825fd42225b7548c8765.npy +03790512-a52bac9239f4382ea513de4eb79b310d.npy +04530566-e951df8d8d2f6ebc96f165bae5f0d61a.npy +02828884-80593a84e45e4345f51f77a6d7299806.npy +03211117-61d0f582475b3d2089b367279b017ccc.npy +04379243-c736eb1545f8b7b4ed403132b02528bd.npy +04090263-7d0b9246a180c59785c111973dec28b.npy +03636649-a53112591be182b9d93768e7b9b1eabf.npy +04090263-e5e273acb04a5687bbb7f70943d3cb52.npy +03636649-ff1f829e2d6ff0d4fcb8d8c6d4df8143.npy +04256520-6bd1d677786634ad27118ebb1d23c10.npy +02871439-6e2622466f6264098a653a9f65a410f6.npy +04379243-4dd2d2ada39e32d15f522d72d0dd08cc.npy +03642806-ccf62b71e7a9aedfb162fa62b36ac9a4.npy +04379243-19d202ccdbc617d8eed6cfa9fc6d794c.npy +03636649-2cc1ea376c68da216502fbbc8833905.npy +02828884-1b1cffcc9435c559f155d75bbf62b80.npy +03001627-5f355e2a9fa2f0db4b3c42e318f3affc.npy +03691459-9b8512f0cb1fad4e73e1b2d018c0512.npy +02933112-230a987c4ff5f673921dd903dd0b8b17.npy +02691156-e88e090caa1ccc5d187bd96066d7269e.npy +03001627-54e9203b65ca4989bfac64b1ae78ad6e.npy +03001627-ddfe96c6ec86b8752cbb5ed9636a4451.npy +04256520-bcff6c5cb4127aa15e0ae65e074d3ee1.npy +04256520-e063706e52feb2db039d8689a74349.npy +03691459-18602a0608af58023b80bd981244df4c.npy +04379243-79f4f47f29267c4cc46152dd624f1d49.npy +04379243-e2efc1a73017a3d2e76bc197b3a3ffc0.npy +04256520-6d31bf9cfaa63bd1455785c13440f50e.npy +04090263-5ae6db470db214b258dc97820d1d9537.npy +04401088-e48a2eff0b0d0a39a0eb5a85db887292.npy +04401088-da390e1a895506db28792f2ae4de363e.npy +04379243-2b88cee2ab30101b9b11da89c22111dd.npy +03636649-c83073e02e70410a35836c728d324152.npy +04530566-7f81a9c7137c855cd03428b7741c342b.npy +04379243-e795845c4e472bfcac4834e2c94f2b9d.npy +04379243-9a8852ff4b82a1585d624cfcd9a37a7.npy +02924116-ddc86e59f6a2756b99ebcb8df4d39cff.npy +03001627-60763dc3cbf36974b0957d845ac33749.npy +02808440-ef03e3a3dd7de9cfe52ffd0e748a1ab.npy +03325088-a48b7d5d965f8cfeb362845c6edb57fc.npy +04256520-3fd28462dda59ee49ecd5a75a29f0715.npy +02691156-fc16704314dc71ee9a6e43b878d5b335.npy +03001627-6281a6537c8c4bdce6fe3612af521500.npy +02958343-1963641a15916c03709ce7955adef61b.npy +03046257-f4a7568fec31f2ce2e12ad5cca2dd4ca.npy +02958343-51b8011a2eaaed85cde8c99e4b182f9.npy +02828884-56916be69d224f2a3569fd2bf3d0a41b.npy +02691156-494660cc290492218ac43fbf276bac06.npy +04379243-6f3506c9c5202101c4e8952b27b5f370.npy +04225987-b2dc96e7d45797f69a58f604ee2cbadf.npy +03642806-be6af6c0bdaee6e06ec6fb380960ec65.npy +03691459-2b3a776ab2c38e3844f57509e473c41a.npy +03624134-b776aa0216ea6cc8fa45e0e67b513758.npy +04379243-a96600d919eff11c3f92fc6b6f6f5bda.npy +02924116-bee327978e3a95256ca2b6e5474aad11.npy +03325088-207dbdcd7f90c2f576c18e71fd49c4dc.npy +03691459-37325d57c8ea891ad77ea5e1afa5bfe6.npy +03624134-a8d99d551c341522192714da339f337.npy +02691156-a9240313c39307574c3a35cee92bb95b.npy +04330267-f23bc665def38d3950dca30f65c243da.npy +03467517-b6599453a9903ed45b0e6a2e453fe7f7.npy +04530566-5456c7546e3f3c3d9c5408f4f799fe72.npy +03001627-86ec9c796a6c1789e792598ed58dd1cc.npy +03636649-69a708be7245f4c9786e8e92cc08146.npy +03001627-5067a76bac4fd7892665f68ebc337f05.npy +02958343-4d0115d72892d27531780fdd33037c9d.npy +04530566-9df836e5ae285e2a5c5cb89ac1b518ee.npy +04379243-b7e0c66b0c6641137141495dc4a593.npy +03624134-dd2173371e7d5f83e255124126c8e640.npy +04379243-fb5e8a6361262c26acf7920879052e93.npy +02958343-f4440b2cecde4131afe1d4530f4c6e24.npy +02808440-4305c0f75a0bb2703af30a3946d92feb.npy +03085013-908428b9ee9db16ffd06de9ba37d44bd.npy +02828884-302c64b3f9d0e0a3961c690e3d679ac7.npy +03691459-73c40350f07efb92d207241113bee327.npy +02958343-d91d378248a55e44d9cc84cf84983165.npy +03001627-9bd5937be6aafe704c29eddba1f2e390.npy +03991062-e538a79b42c8db6b2d7a27ffaafaaddb.npy +03001627-c9d68e1e5309ac25ac57e7d566628472.npy +03211117-453b06180bcfd33a86b76551c6a3b2b.npy +03636649-e6b34319c9ce57258d6a77b750ad3e43.npy +03991062-c1505bf780727e15cb03b57fca000b1f.npy +03001627-e2c7903ad9e8f497a7be81e6de3c404c.npy +02808440-407e9ad1c8352e1f125fa9990176f0d5.npy +03691459-b6210936b5d1be007670e02527d78e8d.npy +03636649-2ba14b4b910e3f41d983ed4f6d016adc.npy +03001627-5d4252d082ae613a2fa77440dcb93214.npy +03001627-d5424b7fdd031fcdd41c21de8af66e26.npy +04256520-75214586f291a04fd45611d32fd7733d.npy +02958343-9c10e71c06558c3b1bb46d2556ba67d.npy +03636649-24fb5c490856f7bc12b31765ab67b41.npy +03636649-9dad7ce60aa168d72cd2160e449d45ae.npy +02691156-a72bf66e9213b313a9b2becd26dc2fc1.npy +02828884-243ac273ab2262b117b4e4e00788e093.npy +04090263-bbc67c7095126f60e3e6e6fc6b79d595.npy +02691156-befcb95d80e0e49119ba010ddb4974fe.npy +02691156-3923b98b26a3c7865f50257ecdfa5c7.npy +02843684-2e81196fa81cc1fba29538f582b2005.npy +02958343-9948d84501b8ab721e7b5f06a32cfcd1.npy +03325088-97189607e5264b2f58813b85ef7bf518.npy +04401088-de271ee7c512d31551c2056c93a582cf.npy +04379243-6765d83445c2338555f46d55537192b6.npy +04401088-7434bc601d949333cd5ca8d1acb8ce0d.npy +03001627-e658d490aaad69d1746cec00e236149d.npy +02946921-e706cf452c4c124d77335fb90343dc9e.npy +03691459-2a8345bd5d50456d8db1a0ee98c45ee7.npy +04256520-cbc445c307221601433b4c9b207205a9.npy +03593526-c9f017cf330911ab1fc611122dc20c0a.npy +04401088-e3e43df4a3fc1870d4d7de9e3c2bb6f4.npy +03761084-11b6eb19d293f93676839a521e23c8fa.npy +04256520-fd2f1f0d3c4b90d535ae67400a94a6fe.npy +02828884-f540ad990dbbd600f4fb4dee5181bee.npy +03001627-d8cb5a5707686c9295a391f7b991d876.npy +03001627-801fe0b3a0e555a937b2bb75885cfc44.npy +04379243-383c5e64f539b2852f852bdd38b1133b.npy +04379243-746f88894a7cadb6253bda70c38d078.npy +04530566-1e047e25506b4885eb5715ea2e14242a.npy +03636649-4b3bc509cc074ea5ccfcde790fc2f661.npy +03001627-239a5029476b8a2adb6f46583a3903bd.npy +04530566-ea34a8282ae86edcd3fb60637c014c9e.npy +03001627-17d7a3e8badbd881fceff3d071111703.npy +03001627-45dcb53af7bea0d091912372ddaeb001.npy +03593526-e0a62f7d9bb5cfea36b0f2a1430e993a.npy +03001627-8d7f0c67789caaa3f415ddcc43feede.npy +04379243-452ee9c2477e471b1aed2875db0a8711.npy +02828884-a7588e794de38fd055a60d8737d1c0e9.npy +04379243-ab9bafe307e11e7a2b8a1a2aaa466160.npy +03691459-7aba5bb94270d994451485c22fb285cd.npy +04379243-a83cda80e5c5a0fc3719086e0b4ab8be.npy +02691156-88771c5b02d6e267b02bf6205401969.npy +04530566-83aa90436933149311c337781d78350b.npy +03325088-3810cc92f4ed3420c36fb70296e45483.npy +03001627-f9c61b40d4f49158ca998f0f87d0c84.npy +04090263-897e6a6307da50906314c3b6a3a65519.npy +03636649-9cf29c3de0cf127730f6e0ede20c4525.npy +03001627-91819d15c2c044ebd47ffa500636d198.npy +02992529-1e597e56b6b2fef6c331b59dc8938ad.npy +04379243-91569ca6f0578ea9ca2ed12df13a916a.npy +04090263-aa858f23b682f5616314c3b6a3a65519.npy +04256520-709389fcd446ca6593ebeeedbff73b.npy +03636649-79bba57a00789023febdb1f263373824.npy +04379243-e18c2cce4bbab2e45b7bf37141f96eae.npy +04530566-f18739a47f1f08e08510ad9ae6ed36b6.npy +02958343-aebcf0140cd6206ed6dec0e17c3e2971.npy +03759954-61552084780cdaa311eba86b475bafe7.npy +04379243-a2baf45f001e118e2c79f7f31759bfa7.npy +03636649-41f3ad2781ee196bad0e80a2288e336.npy +04379243-a9d27bcf51153e4567de2aaf749e5256.npy +03337140-73ad48664248623691c352d02061b3f7.npy +04379243-92a05eba553fd1247674a65b52217c22.npy +04379243-10cc8c941fc8aeaa71a782a4379556c7.npy +04401088-c65f71b54023ee9897d7ccf55973b548.npy +02808440-2b6bea31677afd413321831d2245cf06.npy +02871439-348d539dade47e8e664b3b9b23ddfcbc.npy +03691459-c6c88ee9ea728a3220815abab29462c3.npy +02958343-33ce4837f282443258c27e607f6e2d4c.npy +04256520-c87497b3c00b3116be8af56c801ecf41.npy +04379243-a479fea6394b100a98f849d6224d303b.npy +03691459-453391a5d1d60bd51e859883d2ec3f1a.npy +04379243-a44249589b77b4674b3c42e318f3affc.npy +04530566-1fe84ad7b78667e47428866500a95dd8.npy +03467517-f4dc2860ddfa244caee8866e459a90ea.npy +03001627-e8e586ccf4dcac74cad9a65dbad13fea.npy +04530566-d0ed110df0d56672b26ad4ebd4ebcb88.npy +04256520-79a9aa1e8b3b108cc48383e281a276ec.npy +03790512-b91424e8cef60e3e1bcfe9129a6aea3a.npy +04401088-e33e1483c4c22b1ae71852a7b0e4fcb6.npy +03691459-e5c1a7e9bb2dd0d65a31d91ec836a511.npy +04379243-9a314f79b18ba7914187eeeb0dea4986.npy +02747177-d5c28f4d7b89bc87eb13448f2bce3ef8.npy +03691459-7f87d18e6cad013ba448d8e70febd930.npy +04090263-ed64394470cc3075feafd6f06fc45258.npy +02808440-2edc92c82cc5db3d3321831d2245cf06.npy +03337140-2cc64133d27c1946ce5d6e9371bb5c33.npy +02691156-b793e65c707e884262bbb378da4fdb53.npy +03001627-e9a8bc335a7faf78f91663a74ccd2338.npy +02876657-aa616bbf51ae233278d5828fe3be4b43.npy +03710193-a603aea34beaf4424b3c42e318f3affc.npy +04401088-ab5fc5879ace7418bdec90548bc24588.npy +04256520-c47c9d6c6c8291d61008a8e167b50735.npy +03636649-7ea1864f38bc326696a3517f50eeb9f4.npy +03001627-95c5a8897fa78d3883b06dcdd869d9ac.npy +04090263-d421d54e21e5f9edaf56497f051566ab.npy +04379243-a0ee8f7c4c2907b4e45ef4135c266a12.npy +02871439-5ec9bedab0bfa761664b3b9b23ddfcbc.npy +03928116-3d7066d8fc23db60df13db406a7a8ca2.npy +04090263-4bcc0ecc49ac0617525b3f0594400a46.npy +02747177-a2e9d8324c1f62cd5ecea499ceee624d.npy +04090263-6fafe3b82e6e07de460c5cf20e4c5e41.npy +04379243-8343d98e3710f5bee1b32bbe69d5bc15.npy +02958343-481c55b1fa36f6c7d834dead2eb68d68.npy +02924116-5124b67208af1ff7d26e47b24e76e338.npy +03001627-7553af75b08b6a87eaac479593c9ad1a.npy +02808440-6c92a80574e97e6a2f38c0d2792fb5e.npy +04256520-c734c6bc3524b673ff2c92c2a4f65876.npy +02958343-d695f936edcc28d497df6383472cc5b6.npy +03001627-c66a19f08d86386430bbd4cddd04c77b.npy +03797390-8570d9a8d24cb0acbebd3c0c0c70fb03.npy +04379243-5ef7fbec36f8854ef7b4b759a0c02e4a.npy +04379243-89942c8f3c2796a71e54ac67f0143e13.npy +02691156-e5af05179ffeb8fcbd46d022fd7d80aa.npy +02691156-d0ee4253d406b3f05e9e2656aff7dd5b.npy +02691156-4457652c2853e0bea8cba409c4409ba9.npy +03691459-3e16cce54c6f0b0f8c21317f25d028ee.npy +02828884-165cd9780f069ff31a546a81aa94b4a3.npy +02958343-e0978173fcfc5203510556e7c3123591.npy +04090263-7e316474bc8b072fca74c4e4ab012aef.npy +03001627-aef0600be3f8f384f51f77a6d7299806.npy +03948459-2e787f6b6f93c097a576fcada53c585.npy +02933112-29832b9c3d644c744da5feafe6f1c8fc.npy +03001627-5d3eff6a1b9a119da011ccf7cbabf68e.npy +04379243-8a179c7244ed94f4f8369c172d21d852.npy +03325088-adbea30c5cb5e4d94a0a22774477f1a9.npy +03001627-708cd72e15dfaab8a687729fda50af77.npy +03337140-7fe6d63cab6a594030bbd4cddd04c77b.npy +03001627-d64b2ba9f1f35362cffd61677456447e.npy +02828884-b4a9481e902d011ced98cca8f0ccd5f7.npy +04379243-ad14b4bde4a656dd53b1634376cbfb93.npy +02933112-4293fa9040a1790f5e30943bb32d54af.npy +03001627-e93d141a3dd25b46219e03e23fb59d78.npy +02808440-c69bef4275de0fd6412deb0d2b0f3dcd.npy +02876657-645cf2b7f442865ebf8d8d6022c8e3a.npy +03001627-97a4d1ab6d58bc2ef60f0f3341009abb.npy +03001627-ef6c2cd0b8bb6e8720768660cf080d12.npy +02691156-6ad89740605331aef5f09964a6a1f97.npy +03642806-461b3592ac4674cbd2079b28d473791b.npy +04256520-e232e06ccba3e82d27039dbb84e920ce.npy +03325088-7d2092c9bdaa6b6054d7082b34825ef0.npy +02828884-fa51b43a7de98d0b7a7695d948d413b6.npy +03325088-4335832712076999d84cdc7f15b1ee59.npy +03001627-6cd8056d4dd6b3c799b17588a5699c72.npy +04401088-515b5a63ebb56aad7aeb5bbdd191fd4d.npy +02958343-82b9bbf2c5c630d9acc1f3191aab65d4.npy +03636649-49749cf225cb899573ab7b7128d466a2.npy +03001627-eb1019c438090004db6175ef18ad3f80.npy +03001627-617f09d333443b8e91745c588e2e0fa.npy +02828884-c311a54150b7c64acb2a965e75be701c.npy +03991062-6e66370dd674686ec938effd02ae5d4c.npy +02958343-88ad6f5df57cf8ea16abce8cb03e7794.npy +02933112-dfe503e6a4a86d4dc59350d819542ec7.npy +03046257-90d93cd686935a4bd866363c8e6eab2b.npy +04379243-5b1000b7bc6e0d3b7e67c36deaaa271e.npy +03636649-3fca250636e2b47a8d0fc77aab7a8d33.npy +03001627-d1d9da0da16dbb1a765101d95c92a0e5.npy +02924116-320ef9e8fc776863670716c89dd036f0.npy +02691156-30d1974a29d95d8be8bfa4901aefcf8d.npy +03636649-5aeb223a91320c39edd4171cd40b3feb.npy +02958343-936eb7eec6b76e4b421c2195de5e56c4.npy +02958343-d43eae16d1c14f48788f2ee06c24b7b1.npy +03761084-1a79926636905e0ccb349a60fd15aa15.npy +02828884-ddd142d8dcd4e95bf4fb4dee5181bee.npy +04379243-dbc98a58a2425925febad4f49b26ec52.npy +03001627-fa263643fb3f45c7492d9da2668ec34c.npy +04379243-9b7b33f2892e7bb9562c69acee9936b0.npy +04379243-4c8992b5868f945c8164355cfcd0b549.npy +03593526-81a4a5f10f2f759fcee8a4975a4efb00.npy +03001627-49a3b0242c13f92da6fee8e2140acec9.npy +04379243-d6f122e1570e4180d6686dc2df08cca5.npy +04530566-5eb2d085267142f26192896700aa3bd4.npy +03991062-2ccd2b095bd8ec27e2ec5524ed185c34.npy +03636649-70b78b9439a9de7530f6e0ede20c4525.npy +02958343-3d6e798bed67ab81f00cd8c386c592fe.npy +02691156-cc86a2ca41e279bc89b1c1fd829ec927.npy +03001627-5d5ea6ab578db7ad331fc18393f04d2a.npy +02992529-9adae247285e9538836a2d8722d73dfd.npy +02924116-7400579f0ccb8df3193d7855ecfc1bd3.npy +03467517-1455e11a8e89e348c80076acba9f64d.npy +04401088-f46531484dea3574a803a040655859ad.npy +04256520-725def83aa65422dd4fd21ba7448467e.npy +03001627-447e5db7c84797272127b77d9c9dbf6a.npy +02691156-3fb7ceab42d7b17219ba010ddb4974fe.npy +03001627-d49ce87d43cf4c8f1679065e1c457f94.npy +04401088-73339a7ed1e72d89aef10502d58d4967.npy +04401088-e76bbcc0029c979721844676433a0aca.npy +04379243-9f4eb0d734a2b7a4ab610b0c94236463.npy +03001627-cd9cd0ec7bc9400b559cb8a953a07d9.npy +04379243-392963c87d26a617d5d95a669ff2219.npy +03636649-ddc2beaa04d1b06f5fa701976706a45a.npy +02691156-77a81458ea729c62ace5721ccacba16.npy +03636649-acaf95927290a89182bfcd34215ccfc7.npy +03636649-1e9a36b3360f23388962005ce0e986db.npy +02958343-c7bd3c33967a3f80d292079a67d9d7f4.npy +03513137-737e1c921100f038e263fa6049be3541.npy +02992529-4991cd37af08577070346e4935b9a42b.npy +02691156-cdbd857f25b1597c711d3e79ce66dfac.npy +02958343-8ceb581fe28a6496510c6353f9f7a5e3.npy +02958343-94c75ba9c6747f1bb491214a0cc2380.npy +03001627-6f0def5e832f3614c01e0156f398b4d2.npy +03001627-3ab3c9d99fcaa66bebd676e3a69dcf6.npy +03325088-d1a30eb29847c0d6c36fb70296e45483.npy +04379243-f616f5c2068eebaf6aa35752fcfa44c0.npy +04090263-8a8f66b04e6d8f4ca9e925ec046bd20c.npy +03642806-283a115028fffe6e4e67e2e8459ebde.npy +02876657-8adc0ce79962ac2021072d05c97a5e0a.npy +02958343-3973846825fc4d857cb2a55fa21392b7.npy +03001627-26bee1a8ea71545c3a288f3e01ebe3.npy +03001627-9451cb35f46ec0f6f946fe2e431cd4fb.npy +03001627-ba7dc0bb03a57732a9d30b145d59ff.npy +03636649-e65eb892b1d1730e52470de2774d6099.npy +02958343-5801f9eb726b56448b9c28e7b121fdbc.npy +02818832-16b4dfae678239a42d470147ee1bb468.npy +03001627-33dc06a8e0933b1efc385a284336f217.npy +04256520-5101b79892ce920b6ee5c30704fa2d08.npy +03928116-ce4945cde785aecb478fa0ab37c461c6.npy +04379243-56ef806397cc9c4a62e6af9325f07021.npy +03991062-ce9dbad314c55616cb2a965e75be701c.npy +04379243-f6f180c3e72caacb5077539b37310c29.npy +03001627-433c6c88f1a43ab73ebe788797b18766.npy +02828884-4b6276df295b3967601104cd2d998272.npy +03211117-ed31aec87c045ebdebe17c8dfb911d2c.npy +03467517-819251e11b46438ff6ff9bebca919581.npy +04379243-7982e2f2984978c6f4b6538438a0b930.npy +04379243-c421fdd1b116030fb129901f80d24b7b.npy +03211117-a296a6d7957a8ce9eb752889d5199f9f.npy +02924116-2403779924ebf18af446f92b52bbd82a.npy +03691459-b8b17a4a9b8d0d18b1561629b743a85.npy +03636649-45fcbb7812f0c9e729426a0f57e4d15e.npy +04379243-ec356bd4c5cea755748e58db1ff83cee.npy +02828884-a73601ecef6e3cf9f155d75bbf62b80.npy +02691156-c878cac87819f01490baeef8ba5b93e5.npy +02933112-228a83ea767bcab94da5feafe6f1c8fc.npy +03001627-46557f689f4cf5dd2acd2bb6205825cb.npy +03001627-e30bd575bbd6c68c9710e093c764abec.npy +02958343-216d910f71942f205df3c6413d40ccb2.npy +04225987-573daccbcfdc94a3cbd54f2dfaecbd51.npy +02747177-14a49c2b9f46faa04d6ef9ab90177563.npy +04379243-96cc60da5c390047c242632b2a8c3129.npy +03513137-f2107d6768adf4952fafb0cab311e6a.npy +04460130-8b52d84dc97eb3a74740473002adcaee.npy +04256520-9866fc915383a06cc85117b19e0f4ee5.npy +02808440-54cd5f394513b67fb0cfb8f47209a593.npy +04379243-37a73eab8cb0267f855931d119219022.npy +04090263-ff7afbe21c3c9408a2e534aa19c114b0.npy +02958343-be348430ab5fa5cfb1bb46d2556ba67d.npy +04401088-c2884eed47300891697f9662a764c78.npy +04379243-20cc098043235921d0efcca115b32b84.npy +03691459-2f4e9cc37c3bf5f1fdd84f4a160b8854.npy +04256520-fa0eb1bb05ebe3f2dd3adf3090c701f7.npy +02691156-1496504f42de2eef8b96ae1a0a8b84ec.npy +04074963-48d98af2e73604103c207eb23f7d33b0.npy +03790512-464a86f04b0f6e452a643a53ea2e7c56.npy +04090263-27156455bd418715a50ef3fc203c6ba0.npy +04256520-f0f42d26c4a0be52a53016a50348cce3.npy +03001627-681203ebfa280f5696d5b0735c6b5f03.npy +03325088-6a3bdf75976bcd914b35a7d7cea7130.npy +03001627-bca8d557dac05e082764cfba57a5de73.npy +03001627-58409b308683d908ca2bec46a3b47519.npy +03001627-1bda25dc158098f438f6f5a7dee76fde.npy +04379243-7d96b0823233ebe7b49b261a212e60b5.npy +04401088-e14de927fca30e267a351c9c1f605db0.npy +03001627-29483ee10e6c6e4c2c37553db37ec752.npy +02818832-2a177aa438616992c9b60ed0e1da4c.npy +04468005-539ad95ea77939f8f9a3483407086411.npy +03001627-a11592a10d32207fd2c7b63cf34a2108.npy +04401088-e0355773a18fc61224d795aabf4bd88.npy +03001627-ba1adc474cfa2f429ab926a7e944e795.npy +03325088-f17f569ccdf9e9e85b1c02ea3a290822.npy +03624134-298d152fd0adb0f33347c5de2992cc8.npy +04379243-4ff1ae700013a877ca6910e4922d61aa.npy +04256520-e0591c0d35f82023610c2a68437007d6.npy +04379243-cb860d60db8f3d18febad4f49b26ec52.npy +03001627-8176364215748b23490ad276cd2af3a4.npy +04401088-3036e6b2a898fc85e85776440ad91264.npy +03001627-b94002e3a92ca65efdcf3d27ddf91f4c.npy +04090263-fb36203aa01524aaca3e540900266737.npy +04090263-a24c70db5fb77268b61fca3643811d06.npy +03046257-1b315e0f647b812619a7b441086db5cb.npy +03636649-1129a07c75f5a709cf004563556ddb36.npy +02691156-d3b9114df1d8a3388e415c6cf89025f0.npy +03046257-26ab68f614b5b24f2f841233486fac2b.npy +02958343-4235a8f0f7b92ebdbfea8bc24170a935.npy +02691156-9a29495f38c07b0526a6eb5f28c0aecb.npy +03691459-4e0473ee9d5c72aef00aae52edb0b7b.npy +03636649-3ca37e415fe44ec2ebeb1e6a8111f53.npy +03928116-861b8b85db9652ee9f7eb1b54c601d0c.npy +03001627-f441e4f7f123bde3cd7677199133326a.npy +02958343-dfce5b313bebfba3ef8e28849949a11a.npy +02958343-23ae5d6c60ab3f60ee3362a8d2d8318f.npy +03001627-28ea1d2d2ff08b1b551d2444ac95a3d.npy +04090263-84b9cd6750fd102a9a2ee232a197081e.npy +03761084-30f4135ed68bff99186b61b33e112099.npy +02954340-4bd0b6df02772d8f59c9250a427b57f.npy +02871439-4996e0c9dac4ba3649fade4fe2abc936.npy +04379243-32d64e4638eb6e371594fba9df8f37fb.npy +04379243-649fb8e1ead691c6359e4b9c4f6dadd.npy +04225987-755dc44dae7791761082f2ea630bf69e.npy +04530566-de100dcbc3be32f2baeac688ed8ea6cd.npy +04379243-bb9304218d9741489ccce4c6d5bb195f.npy +04090263-5f2b8f1a75a51d90e76598b090652f4a.npy +02691156-5e31a194b02a286df8c6d04d97f8cf7.npy +02958343-b36c9481f71c2428ca92a4cdad802b45.npy +02828884-f5557538f4c6d755d295b24579cf55b8.npy +04256520-8affea22019b77a1f1783a44a88d6274.npy +02958343-2e6a9622bf83f04c38ee77d0178bbf4a.npy +02691156-fcfa1a67f34e7f2fbb3974ea29d1d642.npy +03046257-cb625b3a9b631d89dab8b525f98c6502.npy +02958343-99606d5346d6b958b96244559b61fdc2.npy +03636649-72b73a861b7626dcc8745da32e9100ab.npy +02992529-8a56e999d75c4d6e8d1dabf86742ec3c.npy +04379243-bb28f4978ec66a9d5369e32fb818f337.npy +03337140-fb5dcb6b8bceecaa4c3aee8e9d3a6ffa.npy +02876657-e017cd91e485756aef026123226f5519.npy +04256520-b37f1363aa93688619fb4103277a6b93.npy +04379243-228561e28a40fa1dda49e29c548bb1eb.npy +02958343-279adb2c37867b3a18d9ca1acf6633f6.npy +03001627-2759711dbb8b66ce66e463776e370597.npy +04379243-94a62cfdb84e88ca9a3528690d225ee1.npy +04379243-211f8bcd0542292a90eb1f8a00f61726.npy +03001627-f495c500ef468ea781a172d69c52a28a.npy +03046257-ce1c9b167cb2db948f83d145fcdeb409.npy +03636649-b1ac784f48473df1e7c7920f6a65a54d.npy +02958343-22abdb50fcc189d58a1aed4fb5fe5280.npy +04379243-993675648a0f1b1a9a87002a4eeaf610.npy +03593526-4f52256337d0d4a4c6e7cc40a98a4ef5.npy +03211117-90502bbf33c05edb369cafe8a991ad4a.npy +04530566-7edbaebf7d4fa994eca93934e5f39869.npy +03085013-e834257d8910fab3cfe78be5b7b99c8d.npy +04379243-9859cddbb637f5c8d3bb9bbe8087feb7.npy +03636649-d1b15263933da857784a45ea6efa1d77.npy +03211117-666902d92f3c8e3f8ee4af899d7fc545.npy +03467517-9e26dcbac33f056c343b0b12983b9982.npy +02691156-63f4d6895e0de9079bd3f7086e6031a.npy +02828884-21358aae456be5087e03aa42670e6f5e.npy +03991062-ad258c77538632867bc41009043d88b0.npy +03325088-55457023edc5af692f7a42055c3e9340.npy +02958343-6aa8f648cc8df63ab2c17ece4015d55.npy +04379243-78e1ea4568b0a1f5e7608f43dfbc9312.npy +03593526-b61141090612ac3ab361b6be63163da.npy +04530566-a7444ff7be7aad024c8ad92cfce1307c.npy +02691156-f7f69ecc4ff199ec5e9e2656aff7dd5b.npy +04379243-b623ede2cc40ae1d377b9297f3055210.npy +03001627-e4a93adf5399b23419fb4103277a6b93.npy +04379243-35ae6545bdefd0ae7ee217c21e683487.npy +03001627-65a1f4ac3e5b57dffff16555386d173d.npy +02871439-41bcf314c6488e939af4053b8815b239.npy +03046257-8cac6e868bd4b4d0db54f0ac1f9f81ac.npy +03636649-b2acbb6717c7a842fcb8d8c6d4df8143.npy +03636649-5e4f40ec0a77cd1e876b399a99a15c0f.npy +03001627-df8440d8678f3a91c8687ff9b0b4e4ac.npy +03593526-23f305e2ca3a3007ee106795de609335.npy +02801938-98c3ddee85264efd7cd51b1084c649a6.npy +03991062-7c86cdecd3b2d29125ebd1cd0b422e32.npy +03211117-5f2048a8af029336a186ecbc0474571d.npy +02958343-de79348d1ab77d2de1274d5dbd93afc8.npy +04379243-290dc618c8ac785cb000f20a5153622c.npy +04256520-d116e9440f64d7a0e7791a1581855f1e.npy +03211117-2361d8f169a7f3479ed83bc63b2fb8ab.npy +02933112-407a485c7d711903ae25f6fe802a8997.npy +03001627-32c2fe641cc95e2d3ed2a8b3ea354e3b.npy +04379243-169deb7aa6472eef2d26358520dd8de1.npy +03691459-f993f348260454bb538cf6df9faa9b65.npy +02958343-780d41c78c60794a6a2345809e2bb169.npy +02958343-e729c1d5c3cccfb3bda733a39f84326d.npy +04225987-515f3fab6bee0c40de82f1e4605731da.npy +03691459-68e85f236ca1b43467cfbcdcd1be46c8.npy +03001627-d454f99b99248bf337c99625b0c170be.npy +03636649-de93987085cf4dcc5208aab875b932bc.npy +03636649-31768574bcddbdde60ad823977adaa23.npy +04530566-3b662a6ae2eab330d7ea446be069b8cf.npy +04379243-47ebb5ac05b46c18488e54fc0c1b4fef.npy +04379243-47758895632d44efba4e573e8ad2f887.npy +04379243-95eb78897f03652eaaf42e97665fa72.npy +03001627-a52e8bd8b570f268f19146fa01c25917.npy +02828884-d8c1f1b9bdbd697b849cf9ca1e2dcbed.npy +03636649-e178ab3b967c7fddc901d9dddb735c9f.npy +02958343-5e857724d62912969acee38782dd9680.npy +03636649-5bd90c0cb1f01b24118486d21a76684f.npy +04379243-a12a759155f4d0ed7eaa96064512efab.npy +02691156-aa07239e9397cf189601fb40d0d298b9.npy +04379243-63aa14915f59ed8671a782a4379556c7.npy +04090263-42291af681d91a6493ceff0200cb9e84.npy +03001627-8c9b2023ecdeb7b049d998127ea6baf9.npy +03691459-993cbabbe4b4bc4431baa3c9ee4148cd.npy +03624134-f0402647fd0236f999abe44c28bf45e.npy +02871439-95eb9d33fae745a616a2b5862518c93.npy +03691459-3dd9222c775b1779239fd9d02eb7da4e.npy +03337140-e34cda176bbac1967a50afc9c93f8a50.npy +04379243-c7358b3aed4160cb21bc3cf138f79e.npy +03325088-832cb748754a0adfe2741a99971b1f5a.npy +03001627-1b80175cc081f3e44e4975e87c20ce53.npy +03001627-58ef4177c711f38fe302d4da760c718f.npy +04330267-45c494c0219a5ffaccb5c4dc056b97e2.npy +04379243-2aeebc06bc97ac054287bb3d3a4847fb.npy +04379243-2ec13926519716142b0659b9edd2a3d1.npy +03211117-3defd11d1a251becc2fd601ec7a8062b.npy +04256520-7f5f4774132a25f3bc8126c23d2deb4c.npy +03001627-5420d4699cf0125fd08f8c5dee475682.npy +02691156-a9e6abca0f6bf69416ee5e3e330ec691.npy +04256520-af796bbeb2990931a1ce49849c98d31c.npy +03001627-4c30d612b8663402492d9da2668ec34c.npy +02828884-648754d5b241b12e4886781cb92ae74e.npy +04554684-83546b11f6c0cbd0c6e1273d5c613c62.npy +04379243-7d3a5c7a3c319544bc4ac3caf16ef65.npy +04256520-8c788c0a04623efbb45ba874f2848e8d.npy +04256520-248e014f31771b31d3ddfaaa242f81a1.npy +04379243-378a4f0524756b0ab20aa91e9e90c311.npy +02933112-ccf7d017b67b51b7b9349bb36676bc81.npy +02958343-488e4530f2b157c2e877e82c90c24d.npy +04530566-c318af82802fdcfa9863712216521456.npy +03593526-6c47d6e5ee3f6a5da8f6851a5d3f13b6.npy +03691459-bb7dc95eb35acc8bfd7a7d6380a6ae94.npy +02992529-4a81237a7fc743763992b1138bb05b3c.npy +02747177-1860c92b11061edce3b4c991629e71ab.npy +02992529-6d85b3dfd681eba530400184d5d3220b.npy +04379243-8991703fa2ac67e7310cd758d9b7cf.npy +03211117-59e53aaa8d8e9d5d9bb1951c99c5330a.npy +03001627-f35645e0b1141804a57b3bec78e5d1b3.npy +04379243-58884a3e77d874efc3bd24f986301745.npy +03001627-9ab888a92d73e4d4a6ffec31b6fb775.npy +03001627-1cc6f2ed3d684fa245f213b8994b4a04.npy +04379243-4acb95a2fc33c3dd19fb4103277a6b93.npy +03001627-6a00357a35d0574b8d7d306df70cbb46.npy +02828884-85bfe701cf6398c69875b72c651247a3.npy +03046257-f01c3ee2b1210cafdb3180683be7ca4f.npy +04530566-bc691ae1f2d6cf0ba628de2fd7989b40.npy +02691156-b3c37b67cdcfd68571d03b466c72ce41.npy +04256520-66ea6f8add81adc848fda83c10428379.npy +03624134-ad5716a9d9b75daf812bade9b93f0eaa.npy +04401088-39e571ec1bcd371bb785a4ac4a0dbd73.npy +04379243-8c5f1bf61d4c1d55b65938a95e1f893d.npy +03636649-774d99cb78b5b82e3a5e6305a3a7adee.npy +03001627-9e5e03508b204754c2b64c0adffbe398.npy +03001627-6673cc5f492f48a229404a50338e24e7.npy +04530566-55d87dea079d2b991bc665188b93587b.npy +04379243-e97089561bcb8e85833c6c72c4b62a4d.npy +03790512-7c989bfae27a958b615e82f53965c4cc.npy +03001627-44ce5f9acd418c7dfebad4f49b26ec52.npy +03691459-b92c1ad2943ec29168faa7730065e439.npy +03593526-1654250bf1bc5a0131fef20bb2ae787e.npy +03001627-acfd2b0f06c128d72157d75d50a75b71.npy +04379243-edf4152aa274a8ec78fe949fc1419876.npy +03337140-a9f6d8883895ba6a19c53845e62c180e.npy +03211117-7940b411f730cb767ba0766d8bbd9a5c.npy +02992529-afa806973174e442ac4f72bf08dc79a6.npy +04379243-51cfb783895a8af9febad4f49b26ec52.npy +04256520-30ae6ca65155012e4b3c42e318f3affc.npy +04256520-22da5fee0352cf194b3c42e318f3affc.npy +03001627-b167632dc5c6c72b19fb4103277a6b93.npy +03325088-aaffe37373701787a5434dd1663ada09.npy +03467517-9ea48deefedac72c441861ef056a75b9.npy +03001627-73a7e497299da43885a2d2169cad3428.npy +02933112-c4db384855e345009f8c3d2002c77ddb.npy +04074963-436c74caa92dcf123c81d9b042c20aa4.npy +03636649-cd05ada0981bd85a2c528d33bca1ac2.npy +02958343-1d700f9bfc275cd23681114f72c10d56.npy +04256520-a46f3d5b1d3382d5cb11c9bb51caa476.npy +03046257-ffbf17fbe4ca367d54cd2a0ea6cb618b.npy +04379243-d1f808613f6dd787a2c8f09e8ae34f27.npy +04256520-2e445df8836c2f55722ac248306b14e3.npy +04379243-ec1e1abd7c9f2eaf5dc565f18990abf4.npy +02992529-112cdf6f3466e35fa36266c295c27a25.npy +03001627-a93d8aa9a17b9d07f5fc96890ba7d316.npy +04099429-b3b20a3769cf8797b95c8cfc3b5d231f.npy +04256520-4ebbe3f30aa1f5eb14038d588fd1342f.npy +03325088-d519321280e573574e65aebfba5f980f.npy +02801938-7a931ec996edbfeacb2a965e75be701c.npy +04530566-925c05dbefada808cfe472915a175bb.npy +03636649-13ec444752bd414bb01c58badc8bbc39.npy +02871439-81a1cbc08793679e75becd8a4c3f1866.npy +03001627-b6a89034b3da55b2cb79ea4974c73b2d.npy +03636649-af8fdc831cc65f0cb0a29c51aa6f10ce.npy +03691459-7c56acc57cae84a9a3e7d768d81f6afa.npy +03691459-3eed264487fcd94bd88a3e0e92891ad5.npy +03636649-b31a3ebb83f3c23f92bdd7f1055f4a13.npy +03001627-10e523060bb5b51f9ee9f382b1dfb770.npy +02691156-1ed9876ed48c145d663e90eaf6b4ca52.npy +04256520-ed1acc5b1cf032b94fb315ce917a9ec2.npy +04256520-fea783c6499e39ed4d304d5dc34c7e17.npy +03691459-956556bceabf511d871b94133e874f2e.npy +04379243-4fb805fd299207e7848af3cb674ead1.npy +04256520-ae1754891182af2675da567c4f0a0f43.npy +03337140-cd7ceb53a90934d04c3aee8e9d3a6ffa.npy +04379243-841082ec0a936a16a4bec68446bb57f4.npy +03001627-8e664a0bcaf9d2a45ca1aaa0789db621.npy +02958343-52a988b361f6cefd685753e73124c6e8.npy +04379243-a859f1f16a230a681a49add4e8d9a4bc.npy +04379243-f7896eb08596dcd6f9883d2fd957d60f.npy +03085013-f10ec7a7acc71e2db24a19cdd6afda6.npy +03211117-66a50da0551d36c9f13ece01395d269b.npy +04379243-1a521b256704b08fb6068c62e84866a1.npy +04090263-2832026da7b9c61ee1f2a1daf140ac9f.npy +02828884-9bd3bcb173dc1fdd73141c5c444ce860.npy +03467517-10b65379796e96091c86d29189611a06.npy +02933112-8d3d624b37b4803c33110e4a1f22f6dc.npy +02808440-4e399a21e6900cb9cbbed63b99f90f4a.npy +02958343-6dda1440d653d0c3bc5845a373118df7.npy +02924116-67658574bcbb1fb041cefd10ce5d6cc0.npy +03593526-6f2c815565cfdb97a1c637e821f12a67.npy +02924116-2c52d56ca79606a9459d3b2509b790cf.npy +03938244-15c98bfa322106a0d291861d5bc3e7c8.npy +03759954-f36757bccf80382a7db5f98d194d7618.npy +04379243-199d183157f213e0da7c128b58fc7554.npy +02958343-b12bcd0ba039b8d09362b924f11fb193.npy +03001627-d0e24e315e67bff2cd80b6234fc6097f.npy +02691156-e6363b1d63f6aad3c1006ed55bc1a3fc.npy +02871439-586356e8809b6a678d44b95ca8abc7b2.npy +02691156-5963e4385e6e5c0925c10fa44a32fd7.npy +04379243-5e70abb053c31036e9de663abbea1800.npy +02808440-f5dfd2eac1ede18c35403ea5eb244169.npy +04401088-5bc22a940bd88a21886d9e4484b773bf.npy +03467517-c99fd50cca7aebcf63e148e250c0340d.npy +04530566-a06a7f4b82beb87df6fc999231665677.npy +02871439-3d91b6fac7df81e4b209708994baff7.npy +04401088-9a4812cc600c67a6bc4fefdf821af065.npy +02933112-7d22aa2a9ce589b37ca94e8674788609.npy +02691156-c624907ad60cb9348a69ce464571d8bc.npy +04379243-a56fb908880a3693af8c4996d9577fba.npy +03790512-788d59c1aa057d8452ee90e577613070.npy +03991062-2352c917dd760e515510d59f3ab1ed64.npy +02691156-733afba7f61652e789850bc84e2ce90e.npy +02691156-b6d2c4beaec0520e9a6e43b878d5b335.npy +04225987-732270ac7e23d610e62bec48c266b5c6.npy +03001627-c6b6f0e604d6a5fe78a7b08b50e4d193.npy +03211117-3317e93256b3f4f15e7087f2d9a278a9.npy +03636649-32c0bfaac424ae9bf51f77a6d7299806.npy +03211117-2d56817501cf5fdbf477ab3f8ee0ba9c.npy +04256520-de14f6786ddc7e11bd83c80a89cb8f94.npy +02808440-721617d5fe78f33363ffebf86d8dd00.npy +03001627-61950eabab269b5c530a9fedbeceb83.npy +03642806-cc691d9e8e189ce47a381a112bfd785.npy +03691459-a159a9bfbe200e651ad88f716ea80910.npy +04379243-98791e9d594a7bcd41f7bb21ee1aab57.npy +02992529-a82fbd031a79f88eb6d41c42f7ade8c8.npy +03001627-e462df8166441ffaeedb49f6d982d28.npy +02933112-c04c1766fcc28fe886c701087a194026.npy +03001627-a4942597dbfd1e683ee344f731525f3c.npy +04256520-4e218928736f1e2bf35a12c589281a9.npy +04379243-4c39c5bcd53c1b593d08add0058f34c7.npy +04379243-b8003b8cd4263cb51573632af24b9a9.npy +02828884-92d4dbddae3f26772056b4bd5d870b47.npy +04090263-b84b0631fa25958f67ed496709eb9df5.npy +02691156-122963149f6a04272620819ddac40644.npy +04379243-70d0937e1d38a9c2a45b742ddc5add59.npy +03211117-3cb53b32b97c0a04c04cf0f68103eaea.npy +03001627-2314a3400230f50d14038d588fd1342f.npy +03001627-3f83565ed40f87c5593ebeeedbff73b.npy +02958343-8c835911f332db4ca92a4cdad802b45.npy +02691156-eaa0d465e9d0c16acfbf0f1430c86945.npy +04379243-e4487798c95013956a7d64731fd3b515.npy +03001627-1f65075818c1d832c05575120a46cd3b.npy +02876657-33dcf806c673d958f4bdca145ed48dc6.npy +04379243-26e020b7c9be193782db9fca4b68095.npy +02747177-e349b1d60823e089da15415f29346bc8.npy +03001627-b50529fcea40cea9e8f8c11a24c52ebb.npy +03001627-74bde5a0a8927f816e107e0a7fbbb723.npy +02691156-dc28756381ac019ac2912ef1a1302821.npy +03001627-46acde1907c1ee378523e42ce157c5d2.npy +03636649-9749404078fe4a8b6afaa22adc38077c.npy +04256520-3ac6d1680c7e0ba4fb315ce917a9ec2.npy +03001627-285931af369b12c2ccd42a2d6eea63ed.npy +03211117-44c3e596206ce29dec86cc96197c0b31.npy +04379243-5d2d0250111a44d49ca96b2737246fca.npy +02876657-6b884893938943f70b5ecdc69e74dca.npy +02924116-e136ec304c87d075a5d02bb361cb2bac.npy +03642806-850673bcbce8f73ec8a6d87a62ac0341.npy +02691156-762e29f11597581d62b600da24e0965.npy +03467517-8c3f4396af236610dae41e77f26f90.npy +04256520-1c78365aa05c3d2d64614cce5789ae5c.npy +03001627-42711692db3647394b3c42e318f3affc.npy +04256520-1de7678ce07c845e91ae3c216ac0d5c8.npy +04090263-2306f0777527603722267cbd3eded69a.npy +02924116-565bd4df285e7715f356d801a44749f1.npy +02828884-d25707cca23ab03ac8d56a266ac05b68.npy +03642806-b51683c6285fa0f69067ac5c9d4ee692.npy +02924116-f66b3c220fccee3bbc2719739d0b9f88.npy +03001627-89c85a35c353ab4c9a037b4abf810691.npy +04225987-16edf6f6574568723f7198a00163bb6.npy +04090263-38c4d7fda771b9b984593c54486394e3.npy +03001627-885c83345016a120c02b229e9105ae6d.npy +02818832-da206aa73f6083781ba83e86537e1799.npy +04379243-48054442012cf1989eea323f522c6486.npy +02828884-6ec8ad28c96e49b588c2a8e73c840fb2.npy +02818832-36980a6d57dac873d206493eaec9688a.npy +03001627-e9df7789d02eb998c8687ff9b0b4e4ac.npy +04379243-5a00f82cae6d2566d249abd69334079c.npy +03211117-c9ff448d7dd7b271c7c51d4ea74651a7.npy +04225987-9ac2d972bedd083342535d908ea693ac.npy +03790512-9b9794dda0a6532215a11c390f7ca182.npy +02828884-15ed07a6b7265f802056b4bd5d870b47.npy +02691156-ad2bebd9c3004b2e151f2df200a24ac.npy +03991062-48e2d1dfac6fdc05cfbdcee86b0a9a40.npy +04090263-2b331127befef5a184727a9a27a761c3.npy +02933112-5799c06f71bf6b88c59350d819542ec7.npy +03467517-e8ce159ab0250cdfb6e0a9d1e411d50c.npy +04379243-e8870f3190f6b8d4bd1025bd755a15aa.npy +03207941-776918b2918b11664a44340bf227e40.npy +02808440-985cd0d15f067f18a08bf4a5e8bfb746.npy +02958343-19f52dd4592c3fb5531e940de4b7770d.npy +02933112-abbb13b953629109d0b36851d61b6fca.npy +03761084-369e83693c7445a48ee2f8110bce2d6b.npy +03691459-6db722284891a7f684f5f65c78855f9f.npy +03001627-f3c0ab68f3dab6071b17743c18fb63dc.npy +03211117-dc004210d943c86073b4ec5aa28d567a.npy +04379243-9f75d067359e6db4f9f8d2db335100b.npy +03001627-f2e7ed2b973570f1a54b9afa882a89ed.npy +02828884-c8298f70c094a9fd25d3c528e036a532.npy +04256520-9ee861bebbc312d97fac4224dd2383a7.npy +04379243-de0267e2e1753bfe684b7bc3f8a9aa55.npy +03991062-8d4512e43c33cd0121f118c0cb20cf34.npy +03001627-ec00ee8e8345be7a852028c7654a8ec8.npy +03001627-116bcb3b43de74b9df9054bbcf5c6adc.npy +02958343-37249c6f16b203de2e877e82c90c24d.npy +04225987-79288e2c98c7be7c6e72f8cfa29d3672.npy +03001627-9c7c3478edebfc1031d38697be8abe58.npy +04401088-16685299c37055c2be40226527c9872.npy +04554684-4c90de8c1b850265bf258aa99523f66b.npy +02942699-6ca77b19e3f52c5031c1d3ccd72d7161.npy +02691156-3aa98ec8f8a1c1f44d210d9468aedaf2.npy +04379243-6327de18a3a3423c947ec73b27c6abe0.npy +04379243-c972e1b113c5972f577be0cbb9f51dc2.npy +03001627-76772a027634c747c8687ff9b0b4e4ac.npy +03467517-80aa2f0d66100844925eded29d6897b9.npy +02828884-8c95e3b240f590c52056b4bd5d870b47.npy +03001627-e454cdb43a7118678162dd776d80e71f.npy +04379243-d120d47f8c9bc5028640bc5712201c4a.npy +02958343-1c86d4441f5f38d552c4c70ef22e33be.npy +04256520-ed4ac116e03ebb8d663191fd557d3a61.npy +04379243-1a10879bcfca0534f8bc1f8036e08e44.npy +02691156-f8ceed6c984895079a6e43b878d5b335.npy +04379243-4f59b7e00a94352fb0bf045ee98272fc.npy +04256520-8092428a6a37b0b9970d4dd67731c543.npy +04530566-73c6ef5ee071b7f9791ed0cd6a81047.npy +02876657-41a2005b595ae783be1868124d5ddbcb.npy +04256520-9f6d960c57515fb491264d3b5d25d83f.npy +02691156-9e8f908bc6c822ae3f6fe63822cb343c.npy +03001627-459bef9cabed55cc593ebeeedbff73b.npy +03001627-5457691268846b073ca87feffb4fd9a0.npy +04379243-72a697466cab7851f51f77a6d7299806.npy +04379243-5245ab687729495b8c728dabc1255d.npy +04379243-70e603b83e06f7258de9f116e0231954.npy +04004475-dfd4fa58919862a071863f1e1f0d28a4.npy +02958343-2bbea02b59ed2bab944bfc22204b55bb.npy +03691459-93b8f4ddd36419998cbc76a30015552a.npy +02958343-8bb2ae81ca9e9a4ed14ae991e75ee782.npy +03001627-a9e72050a2964ba31030665054ebb2a9.npy +03991062-2f06f66740e65248ba6cf6cbb9f4c2bb.npy +03467517-df959f68bb22e402a24eeca91f583600.npy +02691156-41d4250764619ff5bbf3143b1cb6076a.npy +03636649-502e62c502cf2f10280b54299018290b.npy +03624134-172b9a77462dcdeaed90ead9558ee6cb.npy +02992529-8f3dfdb531d1b5dcb4ca066f17bc06cf.npy +02828884-cbe6101e5199ca2d88c88a4c0a3c4a21.npy +03337140-3076d27c5ed34949ce5d6e9371bb5c33.npy +03001627-3669c9b2954c730e492d9da2668ec34c.npy +04379243-2bc602c2b7d9a622ee05b1e9462446d8.npy +03467517-1b91e01820c9f2f0140b4ffd009f9ae1.npy +04530566-efc4de2b174c736dc99bbfcf5650bf52.npy +04330267-afa39ab158e8edc51ee4e0b833e7dfbc.npy +04379243-4afa7cb9a042b7e3c4f66791e25960f.npy +02691156-895939bb0da197f8303d346f4be7d4f.npy +02992529-14726c2482a092d3a9fe1734a6086750.npy +03691459-9d62d13afcca23d841c6e77793c5dc94.npy +02828884-c2c0a205bb318031ed98cca8f0ccd5f7.npy +03797390-b46e89995f4f9cc5161e440f04bd2a2.npy +02933112-48e0fa8a06a163014da5feafe6f1c8fc.npy +04074963-647b7f4f47b3fea54dc062c02826dec.npy +03991062-28859f582ed2c8a0f99b89f8ef639ae3.npy +04379243-2820444f78ca0d82399f8b5570a02c59.npy +03001627-bceab717048f35fea481048c76a35623.npy +04379243-77e03976667383c3d810b14a81e12eca.npy +04379243-dc49259a117af8f1d200faae04ce3f8.npy +03636649-8cf524d8cca9d451fcb8d8c6d4df8143.npy +03325088-e6a64eb10a355f02aa3dee53ca79e7b0.npy +02933112-5906bfad8f6d794f490ad276cd2af3a4.npy +04379243-5ebf57428b18f78a1ee6305032661052.npy +03467517-6c731c424671345c63e6b27c89da971e.npy +03001627-3fabddc7c0fa27f92bdc75f1ee88d8e0.npy +02871439-8815c0f0a0e21be7a09649082c657e65.npy +04379243-2c6beb9625fcb1a43c7fd9917aa4ff1e.npy +02924116-532569f907baac9134ac4f8ff2084698.npy +02828884-1a55e418c61e9dab6f4a86fe50d4c8f0.npy +04379243-1f067718ea071a4ec804f0ac5b784b6b.npy +03636649-2f2d4805ac5eb033e49675db0062ac74.npy +03797390-1c3fccb84f1eeb97a3d0a41d6c77ec7c.npy +02691156-18cd9dc7631ef3064c41882468413db8.npy +02691156-93ba822e84586999e3375a6b96a1d765.npy +04090263-5395c4dac8e66ab6543fc9b228fa4afd.npy +04379243-cce2b5399e5e46a45510d59f3ab1ed64.npy +03991062-f1d505c01e188533b11036f4855ac4b5.npy +04090263-7537fb364b25e32e999562d1784e5908.npy +04379243-79df23303a3192c1cdf1dfd78f33901b.npy +02828884-e28f8467945b5d526070f6b7b2547ecc.npy +03636649-670ad2964ad5a98c9f1a71e46bbde97c.npy +02958343-ec42bd73d57580a85b48f89d50b1db79.npy +02871439-eb7b06f942f4c8fa42e99d71e01c9ff.npy +04530566-53fb6683aac2191fa8a3d44052f8cb25.npy +04379243-bdc7c9339145602af51fa0238791f5dc.npy +02828884-ac4de7e08bc1f024c955e5ed03ef3a2f.npy +03624134-d68ad03780e0e08ee527a71b8fef8ccf.npy +02958343-6b7f573997bc6f8c953536e7c905b301.npy +04256520-7b405c1d6d2dbea9f91663a74ccd2338.npy +03636649-3768d9037d103d9630a24fed263415f3.npy +02828884-e18d11ff6f781d843d2dd82a57bb3bd7.npy +03938244-ea69362db645cb4c1185ac82ed4da80d.npy +04379243-236380670cdbf2c3a4a70f7cc08674ca.npy +04379243-bf17779bec6abccf161bc5243aab8ea4.npy +04468005-e95ce94f475f77d16d99dfe91d90e769.npy +02691156-54885d5beee4e76ab63969f9f8d6f075.npy +03001627-7a79fdfdd72f06e9f8bc1f8036e08e44.npy +04379243-ef130b03885738918f7d9678498f2295.npy +03001627-9910380fedce395e80165d5b901b6e64.npy +02747177-2f00a785c9ac57c07f48cf22f91f1702.npy +03001627-111cb08c8121b8411749672386e0b711.npy +04379243-e05344d8bd3ef63c5b7bf37141f96eae.npy +02691156-36393e03ed11f78461f1ef59130c405d.npy +02828884-ae9c8421189f6590809b609a351bc774.npy +04379243-8c1775d71c36f89d6ca407465d3c74d7.npy +02992529-7a2a5b36831f45501b670e8e7f0f2c3e.npy +03001627-502be527c054ebca6e0ad36e9a10bd13.npy +02691156-7f837b389e885af471b4c018296f73c7.npy +04379243-89aa38d569b025b2dd70fcdaf3665b80.npy +03001627-df2b7e697ab6ca0f155d75bbf62b80.npy +03001627-5ebe4b9a29d5c0274de7ed732f5aeea4.npy +03624134-832cbaf563c649305eec6d8d24f1fde1.npy +02958343-62499fa5041de142707223ebf2d3b38.npy +02958343-ced56d51c144b40373dc6d54075665ea.npy +03001627-980feda55fe02c5868e9405ab8968607.npy +02808440-2d765fd16aedb02b362845c6edb57fc.npy +03001627-cb714c518e3607b8ed4feff97703cf03.npy +03624134-60277f4060b8703e4e18d7136dc2dc80.npy +04379243-322897a771d4591f980d4e1477df0f00.npy +03046257-32a7331dfe2c9a866463df620b7b4cbc.npy +04330267-8bc67008044e0e8f843f813f752a5e35.npy +03691459-abd3b55d14db9b3c8db1a0ee98c45ee7.npy +04401088-acda976ba347a3e58ba35fc6cd3da287.npy +02958343-8922c6c3435f16fee694960c91796f38.npy +02958343-3e7884501c806601b9fbf66e2446b0a9.npy +04256520-9f5b090a3697b05f8f9cd2ac878055af.npy +03991062-69c0cf5ac04d356c6211b44918593b2.npy +04379243-904ad336345205dce76bc197b3a3ffc0.npy +02691156-9513fcab860b113795ff232cd38210b4.npy +03001627-d4b5f8edc72b4676f4175ee3a177350a.npy +02958343-c20ff7778ca2b8ca86ac29addefc0f11.npy +02924116-bb6a09f63ccb939a2d4ead5a1be351b7.npy +03046257-4468cc03f0d13d4286322e4cc6f2fa7b.npy +03001627-b8e4d2f12e740739b6c7647742d948e.npy +03325088-1c5b1091af3106fa2c3adce840300a4c.npy +03001627-fa27c1b8dac76b6d1f285be552b78f9a.npy +04256520-490383705f78d366bf67ac39195100ff.npy +03759954-ed1328cfa8749bb8d80ce3f2fd66be0.npy +03001627-1ef31b046039bf985c8a41baad250b1b.npy +03001627-ef2da724b16ae36654e404e041bdecdd.npy +03001627-3f41b4339ebd59c1c397356311cbeea4.npy +04090263-e88c326a1c2a570fe2bb19fbad3e4596.npy +04379243-e7b99aea5bbb980ad617d95dfd4d6158.npy +02691156-e3b06cf8bea9a6a5c1006ed55bc1a3fc.npy +02924116-7b86fbfc235e124e797ce0caffb8a237.npy +04256520-1746d1c62d9efc742665e2e07399c56f.npy +02958343-2d096d5dc0e0eeb370a43c2d978e502e.npy +04090263-e1f94a758b97b728c2ef4561daf0cd46.npy +03001627-37ed1b9ebaf4b92deca22c501ad0a77a.npy +04256520-2b4de06792ec0eba94141819f1b9662c.npy +03001627-cc6d6035bb5074261f98c0761af40e04.npy +04090263-30a2198addc7de5cedb0c6ac5ecac060.npy +04379243-a017b980b5bc255c19fb4103277a6b93.npy +02691156-6c87f8378066f8f171d03b466c72ce41.npy +03001627-42ceba8e460de1de820898ba01899de3.npy +03211117-3fc7b2412782b8e9964f7ff178873e82.npy +02933112-99ff3359d64f1f45ce5d6e9371bb5c33.npy +04379243-41a4cfee883a91f2d9ec500769fff320.npy +02958343-fe2ce22107693354f1cc1cb691702a23.npy +02691156-4a559ef6547b685d8aed56c1a220a07d.npy +04099429-668aa148b7147080227275b7e0831bad.npy +04379243-65f126afcc43ba69a4d89a7050f2b7cf.npy +03001627-b7a1ec97b8f85127493a4a2a112261d3.npy +03001627-54fc8ae4211e121a55450780441af433.npy +04379243-1c9048855223f744fb85ea6fd426098.npy +03046257-e8cbb09dcdce16f172b9579598bda76b.npy +04379243-38888628843f7b38f8b8d4a282992be4.npy +03211117-74cb25b4b8b2b89df9f3c6290096f50f.npy +04379243-5354ecb0e3aa1da074a16879fb3ac81f.npy +04379243-ef1e4af0d76ead1afff16555386d173d.npy +02691156-cb7c32bd7266daef37f38dedb2f1219.npy +04379243-e263fafc76ddb82b4cc80585c0d3d970.npy +03691459-101354f9d8dede686f7b08d9de913afe.npy +02933112-65f11f7cb5c5106eac00fd1150223027.npy +02924116-2142f1b622cc1b07e99562689078395.npy +02801938-cc79f97e37dd431ecbde89e0c48a01bf.npy +03211117-51b92bb1df3b1a10ad1d87becf13ddd9.npy +04090263-421da608bba18bf2688fc2fc0a14edd5.npy +03991062-b33edd2dae68b9c8cb2a965e75be701c.npy +04090263-338998b6f6f541c712b38b1d99376c0b.npy +03001627-123305d8ccc0dc6346918a1d9c256af3.npy +03001627-9c3e53d9d1e653c0bf80985a99195eb8.npy +04379243-d5b21d6154c0795813dd6eafe1477be1.npy +02933112-31a7cd3b7990834cde650492e45fb14f.npy +04090263-9278d3daffecc60a8e75bb5638d14ce9.npy +02958343-8648667e03bde366b17445a1c29f6d34.npy +04530566-1a2f00c6886f14354d85fb76de815344.npy +02691156-75d162523d703917b87697d3904b168b.npy +02958343-ef6b9ea0fbba6af828ea89475d3a158d.npy +04090263-a5f8af7423a45b293568a24dac4b6dc2.npy +02808440-3bbffbe6bf88c8cb362845c6edb57fc.npy +03001627-c12dc91e3564d8e3473f10e6caaeca56.npy +02828884-575595ab81e657315b3aba3f0877c74f.npy +02958343-a50a46d3423e7dcad1eb2a2149d13665.npy +03691459-aa8f197979376d792d563c85edb49108.npy +02992529-80243e34f66a503bea95e61f66327e28.npy +04379243-2c0ade2de5ed1ad66df14337f24e49f4.npy +03991062-d2fefb9c0ee02c2ca2c59a4d90e63212.npy +02691156-9912b47f0efc512b8d548f89c1029ea3.npy +02933112-956c437be87a2be5f51f77a6d7299806.npy +03001627-f2f0f205af792d3d40332412c5d013fb.npy +02691156-83cb2b58d88c0ae3f4fc64fb3aaf41d7.npy +03467517-5beb3384470cfb3e18edda4db8cbb5a0.npy +04379243-99720647e210078beaf288f952624966.npy +02958343-145e18e4ec54ed5792abb3e9ac4cd40c.npy +02691156-adaadca2be822544d81b6465d8dc20b5.npy +02958343-903b043072a209ba8290d32865eb3245.npy +04256520-72045d74edb0547581a172d69c52a28a.npy +03001627-939383f36692508afebad4f49b26ec52.npy +03211117-b3a975cb984a8fc6cc98452c8fce6b43.npy +04256520-8d0472ffc368a8e431b5f9e34ff03906.npy +03790512-3ef6b2e0a896e4ce54d08b5b71c0b603.npy +04379243-90f7b8cd8e41321c53315facdf531a34.npy +02691156-37f2f187a1582704a29fef5d2b2f3d7.npy +04379243-d1e231e9fc0e9127ea6202eee73b76a8.npy +02691156-2c16ac865f06542381598514fe928082.npy +03001627-28bbb851dd01a162a5615d35d4766b93.npy +04090263-2ad7a0bc552f1df96b2c8bb96250e4a0.npy +02828884-3bbca1223d18e2caad5067eac75a07f7.npy +02691156-a1a58070ca1749d76abbb3e202b76402.npy +04379243-673dc4bc9271880fa320e34dad7c78bd.npy +02871439-b587e9d84ce2158e1933ffef19678834.npy +02828884-b83b544f8536375ed00e4d1c6a5a3a74.npy +04379243-dad3122c094cf582ab82b08bd2b110cf.npy +04401088-5cc54b5db73e9e1e6decf1414eac2924.npy +03211117-b8386207364e622d5e7087f2d9a278a9.npy +04401088-69e45e401c1d05b767d8789d3a6519d0.npy +03261776-91a17b47f79aca8b2ed3579bacedc134.npy +02747177-9ee464a3fb9d3e8e57cd6640bbeb736d.npy +02958343-9f2721257bcbfc70dc1fa1f50eb490cc.npy +04090263-d91c45e8d51b2ffb12b38b1d99376c0b.npy +03001627-91cd85647eef236490e75b1cd0f0169.npy +03691459-ab70b452a7ba1c445f46e754938b29e8.npy +02691156-e2612c366bd11e305e9e2656aff7dd5b.npy +03636649-914a876b24bea577e97426e55fb77981.npy +02691156-a69edb40dbc1fc6c66cf1b4a8fc3914e.npy +02958343-5dcbc04a1ce783eb73f41773bda9db5c.npy +04090263-94d526e75ba18f3326243ac6fb5d9ad9.npy +02958343-4b841ea5b31090fe2bc9f17412005422.npy +03001627-892381333dc86d0196a8a62cbb17df9.npy +03624134-bee1a473472639e25ca3862a7efa6401.npy +04379243-a9cc8112fb8c4ed5dfd21203bf8b4b46.npy +02924116-377b4d3e6b5c47e9f5d789e33b735c9e.npy +02828884-704e4229c7f8a0771015feecec1fadc0.npy +04530566-42d4dfd73f7e27677e72e199dc6b40e.npy +04379243-34da9450728ca9fee0be4360cd00cfc.npy +03001627-94645127bd4168e03e63b721c3743983.npy +03001627-6352d748b1843287921ea62370e5ffe0.npy +03991062-4635eae69badb028d26da3063fcdd79.npy +04090263-5128892dbc0e8e4d12a8e5e6e6618c8e.npy +03001627-c2a7da6a1e1f896a301e9490bfb35bc0.npy +02691156-4ea714b785e24f0d9a6e43b878d5b335.npy +03001627-3289bcc9bf8f5dab48d8ff57878739ca.npy +03325088-8b96750136eac3c5c36fb70296e45483.npy +04090263-bcc0a71596e9df4a6314c3b6a3a65519.npy +03636649-fb76c5cd78d3c9deea3655638ad668b9.npy +03636649-7fa0f8d0da975ea0f323a65d99f15033.npy +04090263-409306cbe659e516bfd79d2627fd465c.npy +03337140-dc8eabfea086d0a7d6d49cce41472b6e.npy +04379243-888faedfa6002b8cdd7e7281b421bca5.npy +02818832-3fc3087faa29bce5b1b6b0c5ddacb607.npy +02924116-2d137b4ea44c3abbb1626da45836ca54.npy +03593526-d73ff526d74baad2ce891e9ba482e12b.npy +04379243-dacde6546ca2e07f66dc6ea1ac82d91f.npy +03001627-d6ac690c293a492d2d2a5d4c4022b4c6.npy +03636649-185e37856f55b2c4e9aa07397ea1cf8d.npy +02691156-ff13be97bdfa45f8254dc1d04198881.npy +04468005-3496b32efd7d03a74da9f355ed79f620.npy +04379243-c87729314f0a7e2fe67d6af004465e0b.npy +02828884-e68f6dfeb7ceea7084663e651cb1f07e.npy +02691156-e93a2143cbec37a173fac4529123dfb2.npy +04379243-e2a2fe3713803e9e04e2b29e7a72f7.npy +03211117-98b12e9101b3d93c972a63e345b45a25.npy +03325088-e173499d5c1b9aaf72101dcac4ed75d3.npy +03337140-f1bb8fefea5543554c3aee8e9d3a6ffa.npy +04530566-7a5de2857213a2547ea0f302610f14a5.npy +02924116-e79d84edb9ce21af550f48125b5f584e.npy +04379243-4e03170994b4347e6f1e07a56c129dfc.npy +03691459-a4a51863fe887cd970165cb455c090fb.npy +02843684-b68f37561d77468da6ffec31b6fb775.npy +02691156-c12d132ade345228d75cdfed9b20c6e7.npy +03001627-648fc7caefda981543d890f2dbb65163.npy +04379243-7ff6c7f050eecd378c9b2896f4602557.npy +03001627-udf068a6b-e65b-430b-bc17-611b062e2e34.npy +02958343-c18c78cf54b60f078e62780ddf14e62c.npy +03001627-8ce6f67b8683c0126db434563c7f5ea3.npy +03211117-ac30fac9534c509f2de252a52ebb4cfe.npy +04530566-86e404c548d965c6d28357d0413f2f80.npy +04379243-ec379ae9e5d850459f2349486c570dd4.npy +02958343-a532b61524432d454ed192f2298faac.npy +02828884-23378697712a8dc2d2b12aa6a0f050b3.npy +04530566-72eb488206297aeaa60ce6f0a0028c13.npy +02871439-f7b93826de3020f3a5f3ebd90cb33bd6.npy +04379243-a542ba8480b71843cea3bc3a9009695.npy +03636649-f0131187d57b6390fcb8d8c6d4df8143.npy +03001627-aa80259311e2a8c0d8bd0a659ff7eef6.npy +04379243-de46aee11f397e1c5af597c14b093f6.npy +03642806-950d3ea26d07b7dafdc319d8ace3a11.npy +02828884-1147218db46702242056b4bd5d870b47.npy +03691459-8e632ba25f8af84b9069c2d361390698.npy +03001627-b7184dd450c5fc2e17c1e3c52889f7b.npy +04090263-640bfdaa8cf5e3cd325474a1336ea459.npy +02828884-34577ccdcbd46908ed98cca8f0ccd5f7.npy +04379243-2b06a917abc1150b554ad4a156f6b68.npy +03211117-7e53c694e5a223346989969642549931.npy +03211117-d330d50a0255529d19ed6e1a590c9122.npy +02828884-5117dd16339a8b943ebaaaea70571daf.npy +03636649-f8d4e335655da8855e1d47baa7986b2b.npy +04530566-d7755acf25baf326e625a0837cc45a0f.npy +03001627-fd4cce51df6571ecd204c1ad14be926b.npy +03001627-b16ae1856433e726786e4057cea53718.npy +02933112-9fe8af4bc8683818579c9a60a6b30a2a.npy +03207941-5596ba626d613f2bfede59875ed98083.npy +04256520-14c77d23044bdfd5327289c00b6dc9ca.npy +03001627-9d9d69e5f2bc80a867903707764646db.npy +03001627-668857eb0c18b0785dc3653f8341633a.npy +02958343-19245fb8ee79038fcd059a326bfe20ef.npy +03001627-46f6a6e0f239282fc8687ff9b0b4e4ac.npy +03691459-77433c14eb1043a91e5b68ee10358ea3.npy +04530566-e28a79fa4880c3c5b0df8f7e348f816a.npy +02958343-cfb4626f879c8355b4d8ed7f5558a6a6.npy +04256520-120735afde493c277ff6ace05b36a5.npy +04256520-ffc0bf43dccf71865257cc5c33f9e8a3.npy +03325088-8fd048fe9a092189979c556124bee033.npy +02691156-8f39cc306f68c89c8139630c61d12904.npy +03046257-7b99bf2508d8c5f36d684a4a25bbc7fd.npy +03337140-90d57e3d7ad999254c3aee8e9d3a6ffa.npy +04090263-79f507c3befe69ba2987a7b722c00b7d.npy +04256520-3c56ceef171fa142126c0b0ea3ea0a2c.npy +02828884-9c9fc31bba4881794620a50068fc504d.npy +02958343-7e63db420468e1b1bda733a39f84326d.npy +02933112-ba6c211ed08d5c1b292e33b9f44edab7.npy +04530566-d4882179bb3a1868abc6b16fdb345d24.npy +02958343-a295d3ca78e2fa9a6a2345809e2bb169.npy +04379243-5d1333eea1b2a9bf85857023d32c345a.npy +03001627-9a6cf471cd7e26566acb4ace974ce36c.npy +03211117-3f4a2b59d82e0f353e72acd01188238a.npy +04460130-9ac90e8814cfe72dca7b89674ac5c6e2.npy +03467517-6a2ffe917b2171497b1bccfe0b4bbe47.npy +03790512-3de5068dfcbc766d3b44aa8d94a815c0.npy +04379243-587f53986db55d45738e43095496b061.npy +04090263-5835ff29188f0f493bbe4035b770f62b.npy +03046257-96573e0386f36abac5daf15558a4e938.npy +02691156-9f25e4e0aa598c7fabda204c62559ac3.npy +02691156-5335e5be2619bbed8141b488a44e65e2.npy +03636649-3a5a0f4c78e17b284f0c4075db76b7c.npy +04379243-a375aa82c58fdeb67cf50d57d36c5a02.npy +03001627-8e1d232ce609392ebd8eb8ad250e5135.npy +04401088-3ed359e502a24e5a79510444cc61f839.npy +04379243-6e45d510dca43cf6490ad276cd2af3a4.npy +02691156-7315cd530e4858246ed10e8f7fe336e.npy +03001627-43d40b726c369eaaed98cca8f0ccd5f7.npy +02958343-269676546548fba38e271c56304de147.npy +03001627-d6edce467efdc48eba18ade30e563d37.npy +04379243-1844a4ed0ff7ed38c2474c54a2e772f2.npy +04379243-72a7c2a8221afcd27e6cebe5e9a662c6.npy +03001627-455829a425b5f919fc93c3b1c0fca400.npy +03001627-e93714e5553f63619215045784774049.npy +02691156-83778fc8ddde4a937d5bc8e1d7e1af86.npy +02828884-381317c1e4c91e87855931d119219022.npy +03467517-d546e034a6c659a425cd348738a8052a.npy +03948459-ac39344e18972fc385eeb0104312297d.npy +04090263-fd00cdc539fded38ddd7320ddee77bde.npy +03001627-74a8078a8e89872780360680c1602c7d.npy +03928116-e8e4c13587e7a5ea6c0a067418a01c18.npy +03691459-4902b88bb0834522ea9b57bdefcbc9bf.npy +02818832-e07dffd4c5607a6672b7738d7a601564.npy +04090263-f499b088e48914256f260fa9465b564b.npy +03691459-a8f3e98220f34623b3d8c1107f6ae528.npy +03001627-1d8d16c0750f22f5ece93f2bb0b6d036.npy +04379243-d5d8632e5a2a286bea46bea76c64cc3d.npy +02958343-2dbfe9c041fc6b3a94ce9d7b04676231.npy +03001627-6b6507085db5a631f3c9c1464e55d580.npy +04379243-2df1f411c26e7d93ad64f84f9d54ddae.npy +02958343-7e12d83df581424ee61b9ff60b1be412.npy +02958343-676ea229aaf8f90858c27e607f6e2d4c.npy +04379243-c07c9ca0cfbb531359c956f09c934d51.npy +02691156-f97fa7329969bcd0ebf1d9fd44798b9b.npy +04379243-23dffe55684018589030b5e29a228aff.npy +03001627-6079b4aa115d08c28998b3b64a143d42.npy +04530566-77a02f09cd22e9f879863338881ed398.npy +03001627-d51112040176efccd5cb6d178687b980.npy +02808440-9c2761796fe65c9b3af30a3946d92feb.npy +04379243-7f7bc0b7e275d1079477196152a8f4a2.npy +04379243-641affca2294fe1879368d1198f406e7.npy +03691459-84d2d9ad08b4c39029cd33b1c7847c1d.npy +04379243-9bac9418d56234bcbc5996932c1238cd.npy +03001627-93bb03379efddea148bc9dfced4f8d35.npy +02924116-2ba84dc6a7d2070b973f659238edf3c3.npy +02933112-c55a7e2cb3ab9aea8ca4aeb5e3b33af7.npy +02876657-f62bfe9756ae99be9921431405933fd2.npy +03636649-d06ab2779bb0b73b822a33e080d0e71c.npy +02958343-af60bafcdba34eab56de8db8652eec4e.npy +02924116-d4af2f443f0ac8b4635756f2543f41d7.npy +02958343-b4250be25fbd19a994abc9429888948c.npy +02958343-adda68ed2da5cee0a413908c0e169330.npy +03001627-ffdc46ab1cfe759ce6fe3612af521500.npy +02933112-aab180818ea51dbc7cd8de3984cc1e94.npy +04090263-4f98bd25bb9e03ef7ec95138ef83ef2f.npy +03691459-9d62c46fc3fd343d1f9f3ce366e030fb.npy +04004475-11ff4341475b3731c39a00da16746b95.npy +04379243-e026b4997f7d037c39d3717288022c20.npy +04530566-eca25540e280ac1c2d1e53cffa2132f6.npy +03691459-64aed24bbb7542c6afac285245c66df0.npy +02958343-300f9c418d6ec9f6473f10e6caaeca56.npy +04379243-88e06a85e2a0f99fa7e7cb173e141227.npy +04256520-deb7ac5670e9bb27af8808fbf39db46b.npy +02808440-a91650269d8efbb454d7082b34825ef0.npy +02801938-9c7cdfa8de249b6c924bf081da6f024c.npy +02933112-aa3e41a51b1aa79a4da5feafe6f1c8fc.npy +02747177-e6ea9e633efbe1e281faebbdea6bd9be.npy +02828884-192684f9de3adfe827ee88e8274f281e.npy +04379243-ce3c408a60cc0e19e6c5cd45aa112726.npy +03467517-8ba739111f5e7c50373ab6cb5c0c1bf6.npy +03001627-3ea3cfa145794baec2454d017a7fc2b1.npy +04379243-a38f012987a2b29593df8c78d1d8e26d.npy +04225987-f5643778dbcd653655a834a7aafb0236.npy +03337140-8b0411805e3dfc164c3aee8e9d3a6ffa.npy +04460130-edf288c16aa9797a4d423544e7c5cb27.npy +02691156-1f47381312c9bebc9bff604afc480b65.npy +03991062-73475ea71ad4af98dff284ee8fea7cef.npy +03001627-465cb28961d2680bbda72093f9b5aa73.npy +03001627-26e8033e59a3adf6bb53a6a5f5051240.npy +03001627-5027bd5ab457e99068821642e9a54505.npy +04379243-20e65777d2ce327035ae67400a94a6fe.npy +04379243-3c46109dc46f1714cb2a965e75be701c.npy +03991062-fe7289fd89f504aaf91cf8caaf3da124.npy +02933112-dd2325abe32870f5a99e0f0bf1de3bbf.npy +02808440-526f26b56fbee9221291d1279f7bf122.npy +04530566-1fb578de4aebcd62b249fd16295bbfb.npy +03636649-da12a5d96b465cf6bced73c51e99f8b2.npy +02828884-16e3d7f2b75cd67dd2b12aa6a0f050b3.npy +04090263-e3d49735508753b6ac6a323abb28e29c.npy +02691156-e0e0d713c8969b52ca8607f540cc62ba.npy +03691459-92b24dc36603b59685a979ae0f537b4e.npy +02691156-26a29227d6326e20e63e266a803d9270.npy +02876657-714320da4aafcb4a47be2353d2b2403b.npy +02933112-695002fbea3c5e4a9a6b496c6e9f4c2.npy +03593526-311f29deecdde671295ffb61d1cd3a33.npy +03948459-897e6a6307da50906314c3b6a3a65519.npy +02942699-1298634053ad50d36d07c55cf995503e.npy +03211117-74e3d29a7e0d5bc48ce0f31e09d08e16.npy +03467517-511fc5ccf4f1c857a24eeca91f583600.npy +02691156-2c49289098e4492bca8607f540cc62ba.npy +02691156-9d292c07f1dff16e1304733e0af0907.npy +04090263-bb95e848c9e1940a2b299c40b68f70c.npy +03001627-235c8ef29ef5fc5bafd49046c1129780.npy +03636649-a2ff853cea4e3ff5bddb797cbb74c.npy +04256520-c6329e1d12285ed761fdb06bea79b81.npy +03001627-5fb53dd1dc9453e77eaeab1f0c9120b7.npy +04379243-2a7130734389335c5c5a7639ceca3973.npy +02958343-d5c046451e5bd6826a9c18480b4632cb.npy +02808440-e7d3cba805b57f5fd011a170fc36c24.npy +04379243-5e4a74e0bfb5bd2835836c728d324152.npy +03790512-9324341a957733ff52ee90e577613070.npy +04379243-230047ad76c117412cba66dc6aeabcd4.npy +04379243-8a385fd026d4efdc517376ab44a447e5.npy +04530566-a6af4bc3629fc5101998595492ff7acf.npy +02691156-7bd76c17b7194d571aa9d8d95b6740cc.npy +02946921-52e295024593705fb00c487926b62c9.npy +02992529-60df2f27d33f3f472eb2c67660ce4f3.npy +02958343-bd3130013af1d709be95cf6cfd2d0f0e.npy +04379243-e0ab42e831e007cf9be2020f4ae1ea66.npy +02933112-7cb09d16e07e1d757e1dc03b595bd36c.npy +04379243-e0229fb0e8d85e1fbfd790572919a77f.npy +03261776-943048e64cc2bc980a070963925e308.npy +03046257-2f638d0d4d5cccc35b903ba10d2ec446.npy +02958343-ef15b938dcfa9893c4d922e8a1141322.npy +04379243-3c686ac317c496f9a71c812e027f94d9.npy +02992529-59e5dc88174971c567964ba700cd97f5.npy +03642806-4e8737495201fa3f71f82dc8af2fe0e0.npy +03797390-f23a544c04e2f5ccb50d0c6a0c254040.npy +03001627-362f53ee8de161fac653c0205ce8ff57.npy +03211117-7fbb5bb76b0058be972398ea2df8e7c2.npy +03325088-49532a66e2ae68c6ec846e583adcece4.npy +03325088-78763ba6006732c754d7082b34825ef0.npy +03001627-9619f0c887f8d879d79b19c7c4f0e293.npy +02871439-f51959078d93caed379cb0fe259da0dd.npy +04379243-23e1e8b7ea54079cd5217e3e48d1c0d9.npy +03636649-18145f4b303c37f11c3739edd52fa3.npy +04379243-8965a7a0234bfcbf82f29b648e624c33.npy +03337140-30224544f65279f24c3aee8e9d3a6ffa.npy +04090263-47a40af2fde212a7b70797b2c89f136a.npy +04090263-d03318b031d2105b5bd5996a1713323f.npy +04256520-2c7d2bb93b49197cded06cbcf08b2fff.npy +04256520-63338a227246399141fba545b7232cfd.npy +02958343-3a735f1a5fe8906cab0fd77f2e9aa584.npy +02691156-ea58a51483e3604897dec65c2238cb8a.npy +02691156-c398f78fb73ccf29751c7a6f15617f4.npy +04379243-2d1400cf45b94df051a0bc243f04669e.npy +04530566-d8d49c7e002656aab572a59093f8c0bc.npy +02958343-7b01d9b011361e82a7fd25564c2e888e.npy +03642806-1d20a8518db7e689f0b97bc9b1844ffd.npy +03001627-4623efb456cc6070820018801b237b3d.npy +03691459-4f0173cf9b1472c37d4f87d95d70ab8.npy +03001627-447856e1071e8b83c036a40816608369.npy +04530566-d66b7128600af54e7afee304cce81d6f.npy +04379243-24dfa4c63b11373f5bb375b194991e4.npy +04379243-9ce692996699529b8430b7446f9e1252.npy +04530566-1c6c51d2d315d576852d4401c7cd1fee.npy +03211117-26c4051b7dfbccf4afaac116abdd44e.npy +04379243-915855afcc5f8918ab27cc93fdc68c94.npy +02828884-a5669fc418b91f9959cbde03ded257fd.npy +04090263-52486aec2292ddd48f0d3a3dadaf3299.npy +02933112-131072b0a226f05f51f77a6d7299806.npy +03636649-dd22b87797f960f47b0f9bd97c2f1a90.npy +02818832-71ebb1db4d8ef7c51db05bb2d8c217b.npy +03790512-24e12e9dfab0892e468bac13e007a6e9.npy +02946921-408028e3bdd8d05b2d6c8e51365a5a87.npy +04401088-e691c8f0fd7d64d7ab0b172d4dea80cd.npy +02933112-1ae6d530ee86ee9a4d87481e09b681b3.npy +03001627-47da08d9c7cd7e104b3c42e318f3affc.npy +04401088-2dccc7cfff6f9a28aca331f9e5d9fa9.npy +03211117-37a5faaf0eb38031e0e89fd83955713c.npy +03211117-2809c09ef575f34214618fe9321a9ffc.npy +03593526-c444d4f782c68dc9140cbb818dee6c.npy +03001627-7521f2a08fae96a7666933f2248e8d9.npy +02828884-aa27d1ed2ebb8ebdd2b12aa6a0f050b3.npy +02924116-fee9872b2821b79f366228b8d159e36.npy +04330267-1d032da39f25772fc99ba9ee5d4194d.npy +02808440-6a6fed877d517549b12da0b74652c93d.npy +04256520-470dd418057f9946a30f938496151204.npy +03211117-d854bf9f589e5a6e69a98c3ec2f88e7d.npy +03593526-1a953dddff37998ef0a5dc57c9d2438f.npy +02880940-53f5240e1e82c96e2d20e9f11baa5f8f.npy +04379243-f4b820ba5a347d939e0a5cd76ae8e45a.npy +03325088-e422f89f233787d7b362845c6edb57fc.npy +03325088-e2fa7af63f902bebb7a867e9b35a1295.npy +02958343-783577d449be4ded3121f82ae456ac81.npy +02958343-35d1938e4ab14fa79ea5c205086e2a63.npy +02958343-9fb89a485c814f7e18f8769175b6766b.npy +03001627-8f2e3c9cb5f25021492d9da2668ec34c.npy +02691156-a0d3a490ee1b74762a4947824596dce3.npy +02828884-b8eb131fb74aa39af7436fe692c24f3e.npy +04090263-7fa43df6d88d2391e103b85ae3ac182e.npy +04090263-6f14f17167243fac5427e47767269c4b.npy +03467517-30a1f256b5b691f09540ada8114b63aa.npy +04379243-a3474b03dad787de8c5fe7d2e262dff3.npy +04256520-66c8df461f312684d329896bbf26eda9.npy +02876657-13d991326c6e8b14fce33f1a52ee07f2.npy +04379243-79ae3e5787e0a07542ff37a1b760099b.npy +02828884-599dd0b655adc794ae143c6e852a4f2d.npy +03001627-938c0560f25a6a9cb76982957f05710f.npy +03691459-123f9066606d80206454c2aa07613033.npy +04379243-97bda10740c4a74036b0f2a1430e993a.npy +03624134-e5bc92012784d89592cea77f96988ae6.npy +04379243-b088212c18a00fa0c3bd24f986301745.npy +04256520-53f4088679746f1193f685578b3d085d.npy +04379243-cb631d4a3bdfb02d2c58f3c20d9d1840.npy +04379243-c46bea30afbbf07fc1997d3da2532033.npy +03001627-7e190338d3f213c3f7b1230869d2b89c.npy +02958343-f84ba2039d0a4ec5afe717997470b28d.npy +03948459-51c3ad915c53f9bde3f7f7749a803060.npy +03691459-813bb87d0679eeb9e4f8604d0992a17a.npy +04379243-dee160f20e1195a4b2cf6e4d01862bc5.npy +04379243-6f3e12831cfefc20a1d8e55816ec2b5a.npy +04256520-b651ea269f4aa92731780fdd33037c9d.npy +02828884-4bd994f25cd3e1fd2b12aa6a0f050b3.npy +03593526-d3978e26d3e0d773b3ffb0c309689ebd.npy +02992529-5c141e299b50f1139f24fa4acce33c04.npy +03636649-230efad5abd6b56bfcb8d8c6d4df8143.npy +02958343-c4d49c0625be70c417da7541f1b2fa76.npy +04379243-72fef5cb33aae9cf94d7e6d8577c8ff.npy +02876657-4a1fe3495565001d211b8bef58aae14f.npy +04379243-7b5c5d7e3b9d89b577cf3bb06f394ad.npy +03593526-9aff149b3b73200fb4b94732d6aa086d.npy +04256520-ebb29b67c390a28ae7c7920f6a65a54d.npy +02876657-412d5f41b5fda0b271dbcf1c4061c69b.npy +04530566-47133569866031669268271e4d570275.npy +03001627-cbc5e6fce716e48ea28e529ba1f4836e.npy +04379243-64e260594e3c3dceabe659e45c4a5b67.npy +02876657-1df41477bce9915e362078f6fc3b29f5.npy +04530566-b7d6c9e38884b121cf439004777f8b49.npy +02691156-96409ee8309b4c679c72d95bbb12b7e8.npy +03467517-ec1149cc44edf89a6909632a947fc19b.npy +02808440-e592e2536000ee2644221bef0fa3c36b.npy +03001627-c8aca0182d3e48add93768e7b9b1eabf.npy +02691156-d984822941e7a768c231d70e1e0cc567.npy +03211117-93b69d3caf90a837e441f5bb6f88ca61.npy +03337140-4eac890c8ae0edef735c6678fe50843.npy +04090263-8d0947db43c20e819ad96e0af6b934eb.npy +03001627-ca032d3b6dcbe1cea3056fa1e8da3997.npy +04379243-8b8152865839a79719fb4103277a6b93.npy +02828884-65e7b3316245780bb5512a11bb8b2bf4.npy +02808440-859f263919c702bbba4fe5622b726d13.npy +03001627-a770cb6ad4a97df84abd45348d17aaf8.npy +03325088-46b445c31887a70eb362845c6edb57fc.npy +03001627-81c481c1a0477555f0a61fe93fafdeec.npy +04379243-783af15c06117bb29dd45a4e759f1d9c.npy +03001627-20cbe565f98b4dab40ef1c8b63a628f9.npy +03046257-1c1899bd9fa34ba7275d003e423c59ba.npy +04379243-1bab21890e560d54d5cb6d178687b980.npy +04468005-9ce7b859b306c3224b0b2e6e63122009.npy +03636649-62f4efec7059e531ba5342d638d0c267.npy +02933112-2d2ce6dc51aa6c7a9856fa70a578baeb.npy +04256520-8737aff6eced02df3598efd14e493d5.npy +02747177-b74e2ac0928725ba6f1c1d4ef8eeb77b.npy +02933112-154f41bbdd20cd9d8430b7446f9e1252.npy +03938244-59657437cc799e51616f4ad120b6332a.npy +04379243-7a8399fc51d83969a8b1d0fdee586dc9.npy +03337140-dab5be91b21f031e995c80c53f5c4c0a.npy +04379243-ec316148b4cdd446b6068c62e84866a1.npy +04090263-d68f31ea513d3a5d6a816b111e5f1b47.npy +04256520-34df668babda666f7b0a2c22acd10794.npy +02958343-2a5df4956f694efe829e2483ba27ce0a.npy +03001627-30cc0df021a947e9706ce6d0dff37e85.npy +04379243-edf1d95e72479c4bbe13ce34aa7c0c1c.npy +02691156-697b4a3b6a380443c503a3776fc280fe.npy +03790512-52e096f02d12b3bfa70f3e863a68c2c2.npy +04379243-a82387cf9d9d253aa06f94abffad1304.npy +03991062-50f0a34edfa5a3b4db41ec1fc554dca9.npy +03991062-c0ed2720d248d4e125ebd1cd0b422e32.npy +03691459-c32bfe130412d9c6d9b106ceb230ede0.npy +03001627-2d80c89d4284b4db21f01d01c8c9dec6.npy +03991062-b89de6e29a5a1d6425ebd1cd0b422e32.npy +04379243-81a5a42f161688ef36d8dd30a594b2af.npy +03790512-9e9300a6e1caec217395d58407f193ba.npy +02691156-41fadd55b341e54ab87697d3904b168b.npy +02933112-d3ff3bd1badb62c2c59350d819542ec7.npy +03261776-2a6cbc4fe096263b6dd0f46427834ba3.npy +02691156-a692309cd39291106055329cd9432d36.npy +02871439-f595c01f296c220935c9a487bf9f4664.npy +03325088-5184b95d850acc92f84537dcf9baed45.npy +03001627-13e29ccc0722f4f958df8eeaf3dad1c.npy +03001627-3569709b421075c730bbd4cddd04c77b.npy +03624134-99c7feed0581cd1fb88eabc621107e4c.npy +04530566-f12f615701b9fd31a9e77d2a83027228.npy +04256520-9507b4091c4d02a37e1b1f098db17ba1.npy +02828884-990c56d6ab64279c2056b4bd5d870b47.npy +04090263-2b1fdf919d42a55828b12a43019163ae.npy +03636649-3977cc8807304dfc5adb3ef1dbe9e3b3.npy +03211117-d7b87d0083bf5568fd28950562697757.npy +03001627-37754da896362bcf28c0cecb7de2397a.npy +02808440-a0020274eb81d539ccd0340812259a39.npy +02933112-9c8dff9a5f5cc6ab490ad276cd2af3a4.npy +02958343-fed8994632223d52afe1d4530f4c6e24.npy +03636649-bc800138650bc4a6c7c8ce3bef5c2aa9.npy +04330267-38cc2f381576c90e36f5739020329c46.npy +03636649-ec344c1076b5c890b02103b4dd1798f5.npy +04379243-657bc03a22b4ee207638fc7b029fa96.npy +04379243-271db646af45e4e48312cb7420a2ad11.npy +04379243-5317439efc03a22de27790b0ec8671f7.npy +02818832-2d1a2be896054548997e2c877588ae24.npy +03624134-f316283f7b179d69faf4eb5f62ee440.npy +02691156-ed0a9a32a8e35f21ca8607f540cc62ba.npy +03636649-67b0ef08720310aa14f846b7e32e76c4.npy +03001627-6cf4bcb8a694242473ae2443c97a1733.npy +02992529-767205e25c8755fd89d59b774c6bc1b3.npy +03710193-757c1d231149dec8f1ad51d1ecbb963a.npy +03636649-dc04781fbec1e188b1baefce5cfff2fa.npy +04379243-3ac426922252c21a855931d119219022.npy +04379243-f1f3021c1469c8e5610c2a68437007d6.npy +02958343-aa9f41bc3925ffc4be9358e8c18dc481.npy +02958343-804c21bdd416783176ad064d1c5fdd7c.npy +03991062-2c262de36d12bc82411e92cfbad3bd2c.npy +02933112-2375dfeeab7fd8678430b7446f9e1252.npy +02992529-84cff93cb8ed08e55acbb5d30672759.npy +03001627-7910a6262ad8fc113fa02fd212ba0e5f.npy +02808440-2f90ff6319c74691c7cd249d921dad67.npy +04090263-93112d8e6d0710e774816c28a6351828.npy +03790512-73fd19410ce60b83d5dde04c96fd8146.npy +04256520-694c7bf2ad1b133b1ce14d4c70990479.npy +03325088-4162e08b1662a6cb3321831d2245cf06.npy +03691459-a23a775c5bfec73d8275986ae1324d10.npy +04090263-e4ddaed36daa1742fa9ff575e691c052.npy +04530566-2b17c0705ee0426e53b2b4f48361e0b2.npy +03325088-d75e4ebefbed7f50317551e5a477d434.npy +03624134-6813197ad5e7011fcc34b900bb2492e.npy +03691459-984d064e7e0310f54cb67f35c09e50ad.npy +04090263-468ac0df7f343a67addf8a484a63f540.npy +02958343-c8849755b29ad49b9af07fbc15eb8427.npy +04379243-7c1bcea89b0037a2d67bd369ec608dad.npy +02880940-4eefe941048189bdb8046e84ebdc62d2.npy +02958343-f9cad36ae25540a0bb20fd1bc4860856.npy +03337140-b078888d60179693c4f66791e25960f.npy +04530566-4e45c5a16f45c3bad9356bb4e82527e5.npy +04401088-87aeb552057c3d1a65a7971ba2230c53.npy +02880940-e072da5c1e38c11a7548281e465c9303.npy +03636649-be13324c84d2a9d72b151d8b52c53b90.npy +02924116-52f337f3047112b42534f02c8e8b5ac.npy +03642806-32ab7469a9c4bb584ae6254ab33d9f52.npy +03761084-f9e75a7b5abe9f3fdec134b6ed53c0d8.npy +04379243-50e69dfb7802b094cfedb1d8b135cde9.npy +03001627-ccfc857f35c138ede785b88cc9024b2a.npy +03636649-d7465ce6bfe4b898c98f75a9ff83e3b7.npy +04090263-84de9995b0a416b5fb5c1b0f759e2bc1.npy +02828884-303c1519c700d19299e8bf807e902261.npy +04256520-4f2ab57322d7a7e3df63d1c7e43c783f.npy +02958343-df8000281bcfdf0754f3692df239bb9b.npy +02691156-5a37bc42a52130a18f52dc705c3109b9.npy +03636649-e389b9eed612e5c225a454369d791fb0.npy +02691156-b9ee9a1ed9296e8c598bfdaf1b614b1.npy +02958343-7ccdf7bc2af0b068e43ab89cb5563740.npy +04530566-aac813074775281a4163d08524f89006.npy +04379243-4572e2658d6e6cfe531eb43ec132817f.npy +03001627-8908ecf5c86377ba7b31e6c3fa42a7e.npy +03001627-c78a6f04268dd802cf004563556ddb36.npy +04256520-e76457b55a3c041cfe49db72b6ffb2c9.npy +02958343-95d36965fc6d1f7de2d4c157e5bf1dde.npy +02924116-4dba3b31aa7de657e550942ea36e5443.npy +04379243-627248fa64c1db5fab610b0c94236463.npy +03325088-dbe7761882240c7a3321831d2245cf06.npy +02958343-7d4c3d9795570647657231d17e42d06f.npy +02691156-6896058e4bc0be46bdf566b587d6b21.npy +03337140-e6e8c85c84f7c6894c3aee8e9d3a6ffa.npy +04090263-97e856173cb708ecbb9224760a70fece.npy +03636649-f95012d97b44f6a52a1b9710536b86bc.npy +04379243-1a1fb603583ce36fc3bd24f986301745.npy +04090263-94540c8b2d13b48ae09d3d2b183cc5bb.npy +03467517-46c7ea02f3f06c26dc691b483dfba5b4.npy +02924116-2e94d54ce3a9aab42ddeeb09f6e4dbb4.npy +03001627-3d629d27b74fad91dbbc9440457e303e.npy +02992529-98b929df60f9ffab49f9ea699d984c9f.npy +02992529-bacbf0d14e0cb5df6a802ef1ce963117.npy +02992529-27085a2456319497f1cb19f636b1c2bd.npy +04530566-55853d0f4d5ba19745aff212946058fc.npy +04379243-6e849ffbc0c14739b31b6dfccf08260e.npy +04379243-4c3ca87e50585617f9696ffb3e2cb66.npy +04379243-6bc941dbd290c7f21acdac000802e11c.npy +04530566-3e233d02a6943be81c99ec30e7a67a36.npy +02691156-8ec085a86e6d9425f4fb6842b3610149.npy +02924116-d3e9d6e0a9a01fade1da81584e31b667.npy +03085013-ac37c2bffd932033c03cb21be18ac701.npy +03513137-1cebc02c679add362f20449572a3a77c.npy +03001627-3c58dc00cf251172c05575120a46cd3b.npy +04379243-71e00a86a67df6e9c225da989036c576.npy +04379243-6b01be46542d507e674ce64e4bf77aec.npy +02691156-c62237ac28c4ed61efe0d4e1eba2e3af.npy +02933112-3216246565768e2fa716f601854e234e.npy +03046257-7c7b518b7ce049e648718eb33db1802e.npy +03001627-fa5dab91cbaecea8ce9a0998abec10aa.npy +02691156-593dbc303a7afed7f44f89e40af48618.npy +04090263-74e930c54ddaf8add34ad43a472bf958.npy +04256520-7833d94635b755793adc3470b30138f3.npy +04379243-9a3df6c365a3df3db000f20a5153622c.npy +02691156-fe1d825ce462c3e7b96212c8f6cd06e.npy +03001627-dc77b920bda118d54627f3cd8db22919.npy +04379243-d1ea83fd1ee634963d5da2a72f595df5.npy +02958343-55c545ac0d94ea16becf71e2e014ff6f.npy +04379243-884eb62c72c1ee75e6fe3612af521500.npy +03211117-b2ec76ac8a5c7afa40ff33d80c1d7d1e.npy +03991062-595a2947c890819d58c88d30f502a452.npy +04379243-49d441b49adde95b20768660cf080d12.npy +02958343-6246696b7db8ab34eeae8bcbf655eede.npy +02958343-7bf415dbff028a3d4470fce578e2b84c.npy +03001627-3f0beaab92a08fd74138477d68528833.npy +04256520-69257080fd87015369fb37a80cd44134.npy +03001627-8a9af7d8a83d90fcd53e36731300f5b4.npy +03991062-d52b2ede7c05092662a167ea4947f3a0.npy +03636649-b384676ddfb3b657fcb8d8c6d4df8143.npy +02747177-f10ced1e1dcf4f32f155d75bbf62b80.npy +03513137-93a86f07803b31c7715a42c4b7cc3a54.npy +03325088-e013eb2f75029d25572f8e1c1caad99e.npy +03691459-3538a656bdfe47948dfe57cb1b540899.npy +03636649-5d265be0ec25af3a7f772a7ed7ffb61.npy +02747177-56efabe64ce30e08d7bc2c778b186f58.npy +03636649-6272bb389bb524f0c8e1fef75f114ecc.npy +03991062-7e9f9553fc4fa9d56d93e521f7fd48fb.npy +03624134-42d9f9c31522d61e8cf144cdbb59254f.npy +04256520-346f3d9b39930b87dbfb0f09ba9f2d99.npy +02958343-36b28d2fd1085c53b6581f6f0cdd370e.npy +02992529-ab9c56981431ec70f7b18034d9df056d.npy +02933112-9bcfb450ed3046a74da5feafe6f1c8fc.npy +04379243-c306205a10978fd695a4c885dffe439d.npy +03593526-bb1a0d719c6c92ec564ef9ade41a3447.npy +04256520-df2fd8e97036e287dce02b254c09566e.npy +03001627-49e3ef3939d7a6ec6bcd32c43682e841.npy +02691156-3b2a19d782234467f9cc1fc25372199f.npy +03636649-ab7895189ef13e754f3443b22038d340.npy +04256520-b86d536860cdcf4ce7321f25048c6142.npy +04090263-d147dfc972ff3a8c673a614c45f3afe4.npy +02828884-83e19abeae8b157d3eb520ff7cd241f0.npy +03797390-3a7439cfaa9af51faf1af397e14a566d.npy +02924116-196fbbd797e9738941cefd10ce5d6cc0.npy +04090263-90612c4b3a2c6d849d9fecebc5860b6b.npy +02828884-974668cad6e15520c955e5ed03ef3a2f.npy +02691156-6ba7cad8fa7301f9c1ca96a73599ca7e.npy +03467517-35cdae95d5e278291082f2ea630bf69e.npy +04379243-dbf4aeb1d6c8b77a30bbd4cddd04c77b.npy +02924116-3988f8e1321f90b36519fb49e2941e.npy +04530566-f7220f2e7b880c2492ab202de6ff04fa.npy +02691156-21adc93a24e86672f054f5e37c7ac323.npy +02958343-6c449b92891754c6b8b6b17d4ce17d67.npy +03636649-b45b40ea1c3a813235836c728d324152.npy +04379243-ac2ee1eebd5f2e335c8a49a27f01fd12.npy +02808440-12aae2c1b46580c48e48489883d168e7.npy +02958343-2b9cebe9ceae3f79186bed5098d348af.npy +04530566-58e6243d1aade364186e889431adb691.npy +04379243-fd6a530388f275c926700e14156d231c.npy +04256520-893e3f15f023e9abdba08b82bf5c2f3.npy +03001627-b79bc903ae820b5ffefccbce7fd86667.npy +02933112-8238404daa0a13bfce5d6e9371bb5c33.npy +03001627-750bc77ca0328a29dbbc9440457e303e.npy +04225987-d3ff56062272f3e6346e65609be6d72f.npy +03211117-9557d54db1c95572e15527f70689f25a.npy +02958343-667f7509425dbc60c43644e93a8d03ff.npy +04379243-6a357f24085bf0fcae199f04f49518bf.npy +04090263-3d0012e27bf8ff429bddaef1ba7e1752.npy +03001627-8b0886f97f038a5fabbc3f24ddd185bc.npy +03001627-78abbfe9ab73729f56d13e757b0dc374.npy +04530566-eb01f5a73f0239a348c096ae17d885c9.npy +02958343-719912031bd692fbd02bf342687ad381.npy +04379243-359ffca14508cbcc86c701087a194026.npy +04554684-828f6f95c6e8651691219aad82abc053.npy +03624134-bbe934c9cdca9c1839ec49305bb07d3d.npy +03001627-8aca9f9005d8a8bae36724f611fabaa4.npy +02691156-b4e9ebb75081f146f6babb7d9ead7011.npy +03001627-a7fc36d1b5d29280ad484915511ccff6.npy +03325088-c02b905c5d602a7ebfc2343650cf257.npy +03797390-9196f53a0d4be2806ffeedd41ba624d6.npy +03691459-95eb96eef8f0e3a7ed10ef1927ebd15.npy +04256520-fa1e1a91e66faf411de55fee5ac2c5c2.npy +03691459-496aea93dd8f7af1f3f18c4c348425c1.npy +03001627-26c9e85dfa18af9fcf004563556ddb36.npy +02828884-9ad5cab6ff1e45fd48113d3612de043b.npy +03001627-5194d56c118786fa1a4e0f13d375972f.npy +03337140-97df987c252a2623820018801b237b3d.npy +03928116-6da19d0d62f55b3257c37d9adada9daa.npy +04256520-4774343934cead2828a3b1af7eafd3f7.npy +03001627-5f5cb0520b70efce750821560ab1d243.npy +04379243-159a2a760327ca5bababe11fcea8796.npy +03467517-8cdeac5545518a07459d1a070aba30d3.npy +03001627-304efa07923fc3c1c681404257d94ad9.npy +02747177-ee8ea1be0821a32860b96188a6533c41.npy +04256520-a3cfcc4d567590e19d4d5dcd2cc33826.npy +04256520-5d2c7b6f863379f1788963ea499c61d.npy +04256520-a996982326ffe668593ebeeedbff73b.npy +03001627-2f282d5e4f140119e493511b69cc95d0.npy +04554684-da98f4f303a500856e27419626f050f1.npy +02958343-dd8b4530c7122fde6a8da1ee9004e891.npy +04090263-b128968ac3ba7207210b7d136d269713.npy +03325088-d224f4d3e56b42ba979c556124bee033.npy +03790512-e54d1fb6aaabcaf8d5dde04c96fd8146.npy +02691156-66e0fbcab927f21a875d37e2f5bce5e8.npy +02992529-471a1ba8c1e1fb0a5b031707d900d7ec.npy +02958343-a8a4b511451c2f36463d04eb22b0bb17.npy +04379243-ae5ac5b2b027fcf9118ddfdb81cc6068.npy +04379243-68ea1f319a9d724ec3bd24f986301745.npy +02958343-12a034b6be9afb50ae983613a2e0a741.npy +02876657-b7ffc4d34ffbd449940806ade53ef2f.npy +04379243-8c2bb08ed6fcbcf3fdd3e2baf05d0f57.npy +04090263-e818959be12871d461b28e02a259d647.npy +03991062-7de2c51034e824811f2146f064414afc.npy +03642806-9fc5b76d363ca64ed03066fc8168e9c6.npy +02691156-ca4443e9a37c4f0b16ade7bb280a6832.npy +03001627-eb89f3b0af31bf40a97cde0b3996ce62.npy +02992529-3621cec4df1ddf421844676433a0aca.npy +03001627-411a1a4ac8ade7da76e9713f57a5fcb6.npy +02691156-ea527508bb74f476f64801ad2940cdd5.npy +04379243-4ced745f960f7439b91767277279ac70.npy +02691156-d883e6e5622a0cab72351dbf9e0687e0.npy +04256520-1fde48d83065ef5877a929f61fea4d0.npy +03928116-5a62d52920d2fa959335ab591bdc347b.npy +02958343-f64f81f7cfcb74033a2b1a2e5e169910.npy +02924116-1d00d8fe776689ac485dded84d35fc65.npy +02828884-9c1310c5ab89888bd201085e80edb26a.npy +03691459-21b9af9e21bbc7975afcf0aaed5d73d0.npy +03691459-65bb8f59e10a0cd837f1b3cce66816ca.npy +02691156-cbabb37711c06d4046ed10e8f7fe336e.npy +04090263-18953ef908bc743a5baa05bb713f2498.npy +03928116-5574c469aae489c355005b4420ff0a5.npy +02818832-447c50e658d729f044ededc21cf0e35e.npy +02818832-64c2347dfd79c63a63d977b06bbd429d.npy +03938244-3fab1dacfa43a7046163a609fcf6c52.npy +03991062-ed86685bc4a0711044c183864792bc2b.npy +04379243-5141810a02a145ad55f46d55537192b6.npy +02933112-a95f93b9da094471c59350d819542ec7.npy +02958343-420d1b7af7ceaad59ad3ae277a5ccc98.npy +04090263-365ed0964805ef59f5cbed688a0bb106.npy +02691156-7f6e55daa567aade3a1cddb101d3e1ea.npy +04379243-e90b641f8f1489d44b5e2e6b95708893.npy +03593526-a5db4bacbe009f2ef51f77a6d7299806.npy +02691156-48e9c61de4db838d84b83051fa0ae5d2.npy +03991062-912c3e1cf2ef3b9ea7d0cc9b15400f65.npy +02808440-c6449e52f945035a1ee236984e84b5e3.npy +02828884-c6dbedf2028735ccd2b12aa6a0f050b3.npy +03001627-c45ff54d4192633684cd6dc1b226aa5b.npy +03001627-be5df38dc7877c13c681404257d94ad9.npy +04379243-2aad9a8f3db3272b916f241993360686.npy +04090263-42aa9630886c7512ed6071560148e6eb.npy +04256520-c7631617fc36715c37363131ac7e8139.npy +03001627-49918114029ce6a63db5e7f805103dd.npy +04379243-8891a73ddf73656be4ef113421a70a46.npy +02691156-a1947665b3f56b584f127ea45c2fea1c.npy +03991062-bdbabbe2c21689fa3d382fe678ddae38.npy +04074963-4df6e942001af26f16a077c4c0fc1181.npy +02880940-b941ca9770b59c3918a27ff49f2f297f.npy +03636649-ba05f660341b7b7b70be09f44cb2fef5.npy +03948459-d0547b978857a41ceb7091f9004469c6.npy +03636649-dd1dde844f5b8ceef361255e85d5896f.npy +02691156-95cfdf728da16975c5f6fdebb053ab2f.npy +03001627-ee2ea12a2a2f8eb71335bcae6f5543ce.npy +04379243-580cac53a1f9a799446ad0d387c02a3.npy +04090263-731b2960620dd7883bb8b3b6d2fcf780.npy +04379243-3622046c1b2266a0fad46760e869d184.npy +03467517-92c2563a4df361dc93f0194265a9746c.npy +04225987-b140249e4615f0db6d8b6ba513969afe.npy +03001627-70711d5a1aead05b90a9ce3e4b15521e.npy +02933112-1cd80ed7f3ab7a5d4da5feafe6f1c8fc.npy +02691156-77ab8bb69221b13bbc0909d98a1ff2b4.npy +04468005-8823677178c21f28dc14ba0818ee5cec.npy +03467517-40cd2cafde62ff7ca24eeca91f583600.npy +04256520-4ed1591fa1c692df44265a262962e6ef.npy +02828884-579e02140aa4c03edd67a519fc8b2283.npy +04256520-bca2ce9beb8b9a3c909c248d0d9da9f5.npy +03046257-db230ee6f183643b14038d588fd1342f.npy +03991062-23c2a637319a07b425ebd1cd0b422e32.npy +03001627-708e7ef3c2afc842febad4f49b26ec52.npy +04379243-3339d615f108948876e9713f57a5fcb6.npy +02828884-7a500a01f5ade316ed98cca8f0ccd5f7.npy +03001627-da7fd2dca5e9f29455f0f54ca9692531.npy +04379243-70d8bfb20df2a08ce4730f03eef08800.npy +03046257-7c7204ae38cd5ec7af8a2e210ebd5168.npy +02871439-49d402238a272804cd114fa69ff09cf.npy +03001627-62c3b6eea96337609ae676623bdd3284.npy +03624134-debbbf239d59d8724662dc124dd336ed.npy +04379243-3532707a0addc62e13680f9c7026bd5b.npy +04090263-e24570b7293756b7cc34b900bb2492e.npy +02933112-9a7263ce1cb720d7c59350d819542ec7.npy +02958343-c2adec4dfc0dd05b2e877e82c90c24d.npy +04256520-28f2563c5e757b1c1b7dbdf53d301715.npy +03001627-35ee4bcad88ab50af6e44a01c524295b.npy +03636649-27e4369a1d6a5a2d490ad276cd2af3a4.npy +03001627-24465c99afde3b9782f320c67d1f2e15.npy +02691156-498ea154c08d51abc863ab010b80d9ed.npy +03001627-f1f69b9b2dbf7402c862eec8232fff1e.npy +04379243-7595d2709fdae7f4cd6ba6431f9f9d71.npy +03691459-2fc738e7a7dae1b59e08df3ef197add6.npy +04256520-f8fc1fa935aa8f792ebeb1e6a8111f53.npy +02808440-ab48dc1b65a3af0a3321831d2245cf06.npy +03001627-b72342e210414024e3e472a115551ec9.npy +04256520-e03c28dbfe1f2d9638bb8355830240f9.npy +04256520-ee5f19266a3ed535a6491c91cd8d7770.npy +03948459-d747c1f677349e78803b54e9738b20a6.npy +02691156-a87c4bebcad260edc05997f3aeab04c6.npy +03001627-1b7bef12c554c1244c686b8271245d1b.npy +04379243-8d9b10974c5e3b35a82a6374374c9dbf.npy +02801938-dc4a523b039e39bda843bb865a04c01a.npy +04379243-9da456630ad311b917fe334c5911fe13.npy +02958343-5b925881cf8678cabda733a39f84326d.npy +04401088-4546af9a8a67e7439c3dc4e242073921.npy +04256520-200324d0bafb1c2e19fb4103277a6b93.npy +02691156-dd9e42969d34463aca8607f540cc62ba.npy +02801938-be3c2533130dd3da55f46d55537192b6.npy +02808440-4a7d4186a966d777e49bb55b21b2d30a.npy +04090263-d9eede71f6941a7c766069834b8696c7.npy +03624134-6671717c417bc68bf912acc8c54e7fc1.npy +03759954-1e3831bff914f234bd4bf7024dfa167d.npy +02691156-41fd618a15692db27359b134afde902.npy +04379243-91c3c63dddd49d3a5271513b292108db.npy +04530566-ff77dc4561e1a8a531d119333f70ecc8.npy +04256520-eb34216913b891ad54a1f8a695b8eea2.npy +03991062-d049058e41674c06c584aa932b291740.npy +03001627-f8594a24176f732b4c7e2600dbaebf40.npy +03948459-10640377f4eb9ecdadceecd3bc8bde14.npy +03211117-9ec1a96e81e1e714fa6dbbeb09c2f316.npy +03636649-d153ae6d65b31e00fcb8d8c6d4df8143.npy +03325088-79a4a16b4062810c4f50865b470f2168.npy +04379243-f99ebf0f053140525a0e5699b3040a35.npy +03001627-a4da5746b99209f85da16758ae613576.npy +02876657-26e6f23bf6baea05fe5c8ffd0f5eba47.npy +02747177-cb8c6fc0e70e3dc12d1fcd0df2dc6d5c.npy +03325088-1309cb5bbd90c7b250da8b99982a3057.npy +02808440-42c74e5da10975c13af30a3946d92feb.npy +02933112-2d0d55da9d8de4356e79c14dd16aa04b.npy +03991062-728dbfa809bc9f4b62747237d98979dd.npy +02691156-4fe7bcbeccf207a5a2a2a57a63160d60.npy +03001627-4e294d057291c50fc8687ff9b0b4e4ac.npy +03948459-9f6b3d59f7ec96fac4dea24d28c9ca05.npy +03046257-1a157c6c3b71bbd6b4792411407bb04c.npy +04256520-eda881a6ea96da8a46874ce99dea28d5.npy +02958343-78c0bec338fa1c01d6b98bf27ff43caf.npy +02828884-928fa92b9f25292f75a9709a8c0e1e6.npy +03636649-5b74e8ee70acba2827d25c76a863dd52.npy +03001627-52b667b2014bdf0482db9fca4b68095.npy +03261776-1d4f9c324d6388a9b904f4192b538029.npy +04090263-251deeda2394fcbc9c96fa78389d2873.npy +04379243-99a3484c310cd1211e8fb9cbb32d2cb3.npy +02958343-2650c2325b7a8d0c811f8dcd8963ced5.npy +03046257-adf095adc30803a148996af2140a9136.npy +02691156-67b2e9282e92abe110ac482828ea39f.npy +02808440-268967dc3b0b09d0412deb0d2b0f3dcd.npy +04530566-22078503d5625b985dd2c581ea62184.npy +04468005-4f0ee7b0644ef0ad930027595c4fa0af.npy +04379243-adfec21e21737eeeb000f20a5153622c.npy +04379243-d0ef9d431a16e70de6c5cd45aa112726.npy +02933112-26657a42d9ec207ee30ec6a0c7ae873f.npy +03948459-a97fdc331fd7c8299cb41f075aef64e4.npy +03513137-43c7b9475c17df536b9e4b1418714282.npy +04090263-69e59c0feb5415ff71936222e0293591.npy +03624134-14f5a704b3898ec7426c116c412c132.npy +02871439-dd3ff69f2d82461777668bd5471e4f9.npy +04256520-a17ba222a54865cdcbde89e0c48a01bf.npy +03691459-93cc6af2bbe3675cda8f53dbeb7453f9.npy +03691459-22d5aa5c6a173d31b59e9758ae7f41a7.npy +02958343-dda10fc985eea0868c368040825ed335.npy +02958343-57e91b50c5420cbb4628d74a95bb7fe.npy +04379243-3b36f062f56e320674b9a1885f058618.npy +03001627-735df13871e3ab4edf6cfab91d65bb91.npy +04379243-264a075e293394a843638dabe1eb5336.npy +04460130-ab10a5607c25e6b0d730ccbc8780d609.npy +03001627-312b3fc351fc0998660e7db8c993ec8.npy +02808440-ad70bacd3a9234bcac5ad68050161b06.npy +04379243-1d447e3b068b924ad91787f0eb159c8c.npy +04530566-112743160fae5bd7ad83f267e8f0b536.npy +03691459-4f4629b12510571886be4ba1f667c92f.npy +04530566-46421ef3a412660b428cf87eb5ebe5e6.npy +03085013-d22bad5e72b815c41aea59cd55c902b0.npy +04090263-19c5068675de48b839264bb933c2348b.npy +04256520-79c3dfc2f90a5cb619fb4103277a6b93.npy +02958343-a836fc66c01eccca58c27e607f6e2d4c.npy +03046257-e1275afba2cf3718d5e4ad512ec499a0.npy +03636649-e138b41985e7382cfcb8d8c6d4df8143.npy +02958343-40f0bac5bcb4f8686ff5dbbe822945fd.npy +02958343-4eb5fe734f4eee71c6fc5b6f6b2a70c.npy +03211117-12ea5095e96f9ed185d624cfcd9a37a7.npy +02933112-951377627e2fb20f86d53ab0fe94e911.npy +03001627-1e283319d1f2782ff2c92c2a4f65876.npy +02828884-b9535bf9b002a226d4d8765e3910f617.npy +02691156-6ea7eb1ef18eabcf8699933784576e73.npy +04530566-8a553a23adde929ceb2c303a0e0d287b.npy +04256520-1e658eaeeb68978214038d588fd1342f.npy +04379243-3aadad80a0e8d21620768660cf080d12.npy +02691156-abb19f2adc42aea2579c3d4943e463ef.npy +03001627-5f33a76ff2e4d25ea7c7a7d30ca93d68.npy +04379243-3a800ccb5e7de7811705bfd3afcd10e.npy +04090263-fdee9fa34e570910f2a8e4598a15f7ce.npy +04379243-689cf8174210c2701933ffef19678834.npy +04256520-ec77376330a7975214e726c15c7dc200.npy +02828884-550e62946d2f55554bce3147c41ec725.npy +02828884-28e12ef0e54e204830bbd4cddd04c77b.npy +03948459-623068000236841ec686380962888391.npy +03001627-11dac7c4d7e4b32af9aec59741c69cf7.npy +04379243-86dec892a246e0c02cbf13da1d4abcc5.npy +02691156-91ad0ff431597651767529f9ae81ac0f.npy +04530566-88cc060aa20b340611b3e656ab4bd115.npy +02691156-3a18489f9615a350e768735f27170bc4.npy +03325088-a9b43b9181475e5b7a867e9b35a1295.npy +02992529-67524ffa83e3eb7c4948b3842dede005.npy +04256520-ad708015fa2c131853227dcd0d547ba6.npy +02958343-ca9a4a00209632808acb0ff76f4aec7d.npy +04090263-267af66d92c1b6b6e6819fcae2e26ad8.npy +03001627-cdd2c7251be91ca779b76fdb1a0daddd.npy +02958343-cd85df142f1999e5f38ed4497f2c53c.npy +02818832-f87682301c61288c25a12159dbc477b5.npy +03211117-ed0975c0bfab1af75f17e2852ee16b0c.npy +03211117-6946bf798ab999b7cfbd2b4a434b378.npy +02691156-6e4570ef29d420e17099115060cea9b5.npy +04379243-ba6a1d8d3f8e832d67668f34c2939f7d.npy +04460130-927ee8b508cde67f5ac73f8a88a91040.npy +04090263-c14017bc897d73f46314c3b6a3a65519.npy +04379243-12567fb8261120cf63a97d76062d3220.npy +04530566-4a01d52c0d8346fda8215f78849a813c.npy +03991062-e9eb1e4250b5c727d0546e77f7d9b0d4.npy +02691156-12d15ac778df6e4562b600da24e0965.npy +03001627-fc2a1c4c332f7731e45ef4135c266a12.npy +03593526-5e1c630396c0a1ce30cbeaf8f6d93761.npy +02828884-fa1b7b9630c840eff4fb4dee5181bee.npy +02808440-33718430c3a5c88bffc6e457221b9271.npy +02958343-c21cb9575910e30bf0174ad879a5b1cc.npy +03642806-2da650d7d946a4f04b7717340dfa57ba.npy +02958343-8fedb0c03a49bddaa8c38723d07b122f.npy +04379243-8e009300d7671a33b2a5818319136c5b.npy +04379243-111df730a9d3f2a8eab46ab0515e8186.npy +02958343-36f8760e54a7a1835cb0db8915167503.npy +02933112-26eb1d73803b2426ef46cffe4939fce1.npy +04225987-6867832e7b9d3654aacda7f1c4fd3ea7.npy +03325088-f0bb725ec0ddbc7eca25b2e822a430b0.npy +02924116-cdfb80edb15ba29762e9ca743c2e311.npy +04379243-1e6d470b0330afe7abccd5469c032787.npy +04256520-e541933c90eec36182db9fca4b68095.npy +03001627-758a68f80f0754f14a8a0ee8b17f83bc.npy +04090263-39c1ebbe7f6f1d5f4a4df88f87b30520.npy +02691156-351c9235749e398162147e00e97e28b5.npy +04530566-44c07d26323910f4fdef75f370a46dd5.npy +03001627-807c16e4f6f2c5852cf52ec1a1c9b69d.npy +03636649-36c1653a021a526319620b61f6587b3e.npy +04468005-76470b75fcaffab629054625f34e281d.npy +04379243-956776ee66e095df2822b5101b06e070.npy +04379243-f58b9e92e45367326c3484ac7eef025f.npy +02958343-5db9380876853a6eb690ce0453406d16.npy +02933112-3aa643b4eb4a165675a4e003752c1044.npy +02691156-a87cad03c8f717e230dd29e8b6a554b3.npy +03001627-2194e6394a31194962e682c9809bff14.npy +03001627-4e0dcb9beee7bd3f3a11565e5be9cf53.npy +04379243-6b2edba33e92b96998fc1d0403f6ad0.npy +03001627-9c499d86350d32a28639ef683ea7ed9b.npy +03261776-56c4d7e643d6a7286329e8c7b28434da.npy +03593526-45ba72a5187c5fd7b9c6deef486a7d8.npy +04379243-65ffcbd025d2151ba5901d93c937a07e.npy +02958343-c9bc4690b171e5d7f0ae46ab6a68f9fe.npy +04379243-cc58de930acd321fac242c3aebc81b2f.npy +03691459-fb4c855848345ecd3e738e11bd8803f8.npy +02747177-3c03342f421e5eb2ad5067eac75a07f7.npy +02828884-8b19ea942987fd72eb753607b9a115b5.npy +04256520-d0f30590066a88fbd5cba62773b8025b.npy +04530566-1e0c84d82fd52f8c394eb4a27c704b88.npy +02958343-fe29b245be45318c80e6a7abc49befc7.npy +04379243-f0f1835eca48e3ae3241548166bb146.npy +03325088-9b15d9a617b37d16d0157e3e7a8917c.npy +02691156-8ba22e93df58242b61c0a7e9e23d6288.npy +04090263-2428abd6cf67771461cca2fd9af9f2.npy +02818832-a903172a5a2b7f7534ac8202f42b5791.npy +04379243-cc1666f0fa7a1672e5a8eba5f6050bab.npy +02691156-881a9dd186e1d5c3ca8607f540cc62ba.npy +02691156-7cbd504262e2d17ee91114a141d25a9d.npy +03636649-e12e898cceec4e23f51f77a6d7299806.npy +03085013-60101361c899c9b54ee5c9c77434cb10.npy +03636649-7f518fe982aae1b5940c8a2639c8747.npy +04379243-40d0dd3fe786e120d75c27ddd792e41a.npy +03691459-112deef454bb8345c6bd342792702e80.npy +02691156-6021cb206f3db880c57b4651eeb679eb.npy +03207941-e4919cebeceea53028b72743e7b13756.npy +03001627-3776f058b918372899b00821ae388810.npy +02828884-7ac31f1da37aca5160ddc468fe733ed1.npy +02691156-82cd0676627c20b0879eac31511e27a8.npy +02691156-72c28618e3273795f9066cd40fcf015.npy +02924116-fb8045ca34f292a087c6856023914391.npy +04530566-2a9b44ad6d6200c02b3fb35c6618f417.npy +03790512-55caf44a43f2c04d468bac13e007a6e9.npy +03761084-cd475ed6b6300dbdbe3a55bdbe3532d.npy +03325088-a7e23856ee1f9789a12b86efa90a53a4.npy +03001627-cd238045ebff9be59186f15d520c12ad.npy +04379243-8be0acca4f67e4a4ea966ed2fa6fd5c0.npy +04379243-b23030e1b7084fd9d38913e96bbf2a5d.npy +04256520-1050790962944624febad4f49b26ec52.npy +03001627-8c4d57109ce0f2f222659d33fd79709.npy +04401088-5b111b3a3e94b5907e1c85c5c15da7fb.npy +02933112-52e92f372629cf356e8f1932e45c9faf.npy +03636649-f2f6fbeacda7cbecfcb8d8c6d4df8143.npy +03636649-342ea0134b504918cf5a37a70014c623.npy +04379243-977457a28e32ddbec242632b2a8c3129.npy +02691156-1de58c7eec71b438bbb26c14135f164e.npy +02828884-23bb9c45796a28d4154e78d1322f3484.npy +04379243-20292fba71362950c59c53f7df509858.npy +02992529-5ce8fc4a82d2d97736d4d4df7a719b88.npy +04379243-d5de572c3f6517374b3c42e318f3affc.npy +02933112-b50c25e6b5447714e90f8ac2c1271ce3.npy +04554684-725bbfc557d3e1b9b5af85a5be833ee.npy +02933112-3f668a006192f1afffcdb54593f6ab3d.npy +02958343-eebbce8b77bdb53c82382fde2cafeb9.npy +04379243-e1f77c5cfd7ea402738e43095496b061.npy +04379243-d40fb361cf8aa18767dc358060e3c47b.npy +02958343-125a4780c2d5095d19454008aa267bf.npy +03636649-bb7d710f4104d16b88e7662971dc736f.npy +04401088-b9f67617cf320c20de4349e5bfa4fedb.npy +03636649-8e9c28fc5813a5bdcf004563556ddb36.npy +02691156-ebe0d0bfa6ec36edd88eab18f1be033b.npy +04379243-79f63a1564928af071a782a4379556c7.npy +04379243-a80b1f16f5dfae242aed93548190eee8.npy +03790512-48372a904ec9cda048272812609617e2.npy +04379243-6cd84ff61583805c85e2af9bf984f0b5.npy +03001627-41bf66b762decaa42c6c98851414a9d8.npy +03636649-3607a2301201064ce7c8fa552499fc0e.npy +04379243-91dfc3575149ff71342398ca9dc32672.npy +04401088-db96e9b2c96c273de7d92dda5756fcfd.npy +04401088-768648ae74e9d84e6d445fdc5fd8bfe7.npy +03001627-37e5a1f7f0409a3b81d7f282a3dff363.npy +04379243-94966aa8a7a6f540f6807434c358ea12.npy +03691459-9a94af940a768aee5865ac92cffc2982.npy +03948459-73c9733fb85d974b3b2b25ffabe35ca6.npy +03636649-c372499c4fb0b707e262a7452d41c334.npy +04256520-3acbbce6f05c2623fdb2be860bb16c8c.npy +02958343-1724ae84377e0b9ba6c2c95b41a5446d.npy +02924116-29a4e6ae1f9cecab52470de2774d6099.npy +03001627-73b369b9808bc2d0f6ba522682be8978.npy +04379243-cc5ef32dc87e0f245dcc7ddfa72357b1.npy +02933112-bc1298b1c55849b14e82b8d74b98baba.npy +04090263-b0a050985a5ce6be25508ed649b952cb.npy +03691459-7d2bd4d349ae34a2fcefa74f1d0bc6e6.npy +03636649-3c9f0efc08817ab6fcb8d8c6d4df8143.npy +02958343-12a445770f7d6f2b70a43c2d978e502e.npy +04379243-c05f807d12761472dfe9cab879fd37e8.npy +02691156-9550774ad1c19b24a5a118bd15e6e34f.npy +04379243-c5178a8a0da618a25d78ff7fb413274d.npy +04090263-d9aea67e3209d6aa1153b2cafc57da88.npy +04379243-60fbc4c64d6032337af2ac6660aa6669.npy +02958343-41d317b520eec9d38d3d01fa03326bb0.npy +04379243-cfeda84f71e95e6169ee3dc2896968a5.npy +02747177-d75e58ff57a881286aecdf1bc1fdd961.npy +04256520-d55d14f87d65faa84ccf9d6d546b307f.npy +02933112-3a0492e3892bb29f12de5317fe5b354f.npy +03948459-98c0bd351e275b3c96893524e607761d.npy +03636649-ee9849dc8d93e16c118ddfdb81cc6068.npy +03085013-c6f97082a7d28645ecda5e76a9473fca.npy +04379243-7affe342bb9be16d5936c7265c890fef.npy +03467517-b7e1c7e7ddd1485277df4c4d253ba3a.npy +04530566-93c013c922b90649ec08eb6485163157.npy +02958343-e1c3687f400be151cd21a68c6dc7b5e3.npy +02747177-1f4f53bc04eefca6f155d75bbf62b80.npy +03991062-92dd4a5efaf2a1702d7a27ffaafaaddb.npy +03001627-1aeb17f89e1bea954c6deb9ede0648df.npy +03001627-22740f20eddc5420492d9da2668ec34c.npy +02876657-545225eda0e900f6d4a7a4c7d6e9bdc3.npy +02933112-92e421ce25931b6da5e3e028709e0474.npy +04379243-5c6cad6a12d7cff3bb6e988dd2500ba5.npy +02958343-50ba203c086c496df43db49cede9f847.npy +02691156-56ace4b209c9ee823bb911cbca3906a3.npy +04379243-2a4f92a70be4e2159c0b027ae5b223d6.npy +03211117-96f01698d0446641ea6e0950aa8ac31b.npy +02958343-dd0b595b15a7203e185ce5d54f27f6b9.npy +03001627-b44d32061d313fc1b7a3c315f744bdd8.npy +04379243-8af6aa6372ade15d8457b637f6fe1690.npy +02808440-f5713226c59f9332ca11f350bd7ec054.npy +03636649-aa1e797797bcc2b161b08af0433fd9aa.npy +03211117-648fe31415502db61c298d13539601a.npy +04379243-3dd217a06e76292b372b6139ac78b39e.npy +02992529-59a168f51f8d7dd9e59685727bdd9ae9.npy +04379243-690e073a4000c7ae540e292bd26f307a.npy +04379243-6137e19255f71a0a26700e14156d231c.npy +04090263-346d1a548be65182a67ac8a08d7e171.npy +04530566-548c6234fc7c787bfeea5c85a86089b5.npy +02747177-1864da0abd05dde7f4fb4dee5181bee.npy +04379243-cdd6c99231cca3c65b187a2f89229cea.npy +04379243-eaea1cf98b61abd043383304411cc9ec.npy +04090263-d3f3e2dba3dc32c0ebbc1e980ea10b4f.npy +04090263-1e6e823412133e585a5fb2c1a52fc5c.npy +04379243-bb5dbf708d5eb7f82099f9e22ca45b04.npy +04379243-cf010623152e31ad2366f6466c2cbc19.npy +03085013-ef86e713b0f71801d5ed7cc6bf6e7003.npy +03001627-6223f3849d57154b5ecb3cc57fe87cee.npy +04379243-f0d8620b49ea76db83130614d8020b3.npy +03001627-e4a890f2330ebd7e4a11872aa986426d.npy +04090263-fbf5a7f93f70cfde12b38b1d99376c0b.npy +02691156-2f4133664133746cf64801ad2940cdd5.npy +03636649-66f7a541e0459b06fcb8d8c6d4df8143.npy +03046257-7627cd63f72a64c3a50aad89e0fb309b.npy +04379243-30afd447dd7201d652c0eaae5c15cab1.npy +04256520-81a7007ead4051cd22ed3259ee7e608a.npy +04379243-128011ffc7787d50f0920fefbe028677.npy +04090263-5b9b869475b3af7281112f9b0beb0a14.npy +03001627-6440fcf4fd8214b7dd58412a5e38ff83.npy +02933112-54a7817fcd0919697753725ea42159e8.npy +04379243-7ec1ec1db13eb349ff085529822a7226.npy +02691156-d48064100e793155f56a7ca118af1bd1.npy +03001627-c92721a95fe44b018039b09dacd0f1a7.npy +04379243-5b97f44d872864c21f7d7307c1f45af8.npy +04090263-285854c90afd66c4c9e18dbb8de06b45.npy +02933112-2c6aee97b0325e92de650492e45fb14f.npy +04256520-929614d79ee9b3f7ba83cc8b3ca4d7c5.npy +02828884-671cade486e88b3880d14ef4d993c2fa.npy +04379243-a96f4daf990b3eda53a3e8b300a51f98.npy +02924116-321c0fc84c8fc3c82d4e86573259e388.npy +03593526-a6d49ec1234f2465f84f031022f95405.npy +04379243-abbc5e4950ff6ea8f4b6538438a0b930.npy +02773838-e5fea6c1dacf3ed4cd99ccc7ff441abf.npy +03001627-4f66b8a004a1515df33978a307b45373.npy +02958343-30774e3218da1f793eccc98914b46c47.npy +03001627-cdf733e544e6646f9b75b6346baf0c12.npy +04379243-4fad1101568fcd48fa7b9a6c80e4e324.npy +02808440-8de00e529b8b39a244221bef0fa3c36b.npy +04379243-8e5c3b7366f2f017b4e3935c6cee4b35.npy +04530566-997054b7ea21f5829588e71e21de9f30.npy +03325088-29e597c4e5cf1612b05296093fcb87fa.npy +03790512-5be7e00fe279ac927cb7616d82cf9fae.npy +04379243-3695727c04b15887b983088451bda93b.npy +04090263-a8b65f50dfb2a74a9a6e43b878d5b335.npy +04379243-441e0682fa5eea135c49e0733c4459d0.npy +04256520-bf816001f25b2ff822e11aea23332c0.npy +02828884-2bfeb0ef0693823d1418b6bd61b3ca4.npy +03991062-39ea99284138e5e835b3d63776480dcf.npy +02691156-13370c42b8ea45cf5e8172e6d9ae84ff.npy +03325088-36aa5b58afa181c76d20e73c57c9a03.npy +04090263-ea9ee0992bdcad77e641d7676ac20451.npy +02691156-1fccf0064e0aebfeb179f2ac46747670.npy +03991062-de673ddf9df03b8278cf1a714198918.npy +03211117-2971f417b08961475a4cd9b26f359d36.npy +02773838-631fd8c280dfb9d5cd3852d63efc4336.npy +03691459-af4dd70becae7293efcf7226d1117163.npy +03691459-4aa41b48ef7711f89e87d2bdcb41f548.npy +04379243-98dcbe480586e9a951d5d1004657a651.npy +02924116-782fb7fc878169906ca2b6e5474aad11.npy +02958343-cfb6c8867c6dd84c80e74058ee862f05.npy +02691156-6dead775080763b94c3a35cee92bb95b.npy +03001627-79c9fdc6bba82709c8687ff9b0b4e4ac.npy +04379243-ccd3c75b72708a90c955e5ed03ef3a2f.npy +02691156-9436273fc1a5e3ca7af159eaf7625abf.npy +02691156-e25794343ee37d6fa8eeb11153b68d81.npy +04090263-128cb9e49c7e214ef2e947b62e6a6cce.npy +02828884-5a52ec36c75fd3d87f502c4e1de97042.npy +04090263-b2c3114a9acd55636d4858690640024e.npy +04090263-b13c2dec1a1dd7ab9bba8f87a19ff3bd.npy +03001627-77dcd07d59503f1014038d588fd1342f.npy +02691156-a9668a32a91787a6be5437d0813f18f0.npy +02818832-ddd75dd50dc40a3f8c1632739e6c2fc5.npy +02828884-ea892969e4035e0fcb2a965e75be701c.npy +02691156-4209abb3ec319f85e5118a089c2a99af.npy +04554684-5e071ea7184305122c5cdbc97c64ef41.npy +03797390-d7ba704184d424dfd56d9106430c3fe.npy +02691156-fe4ad5664773074cb536c73c7d134340.npy +02924116-b5d8740b0662dee71cb7939487e62b3.npy +04379243-476e7d25434b67e75f490d1795e78588.npy +03642806-67e4cc8e13aa863cc418dd4d8b66af83.npy +02691156-439c0ad637f11af762b600da24e0965.npy +03593526-7fe9e595c5eb7d04bb4fd842f8631c2b.npy +04379243-d2cc7d1f7fff8488698b889b37529d3f.npy +03001627-972d675d3ce3555d492d9da2668ec34c.npy +03211117-68a4fc70bff1e1cc700fc5aa044d9995.npy +04256520-6e4fab35f29925f14f438613584cbdf7.npy +04530566-6fbf3621aa1d3a8e49f0e3dd7767881.npy +03636649-ce406a32bdc610198ca4aeb5e3b33af7.npy +03001627-fe1081843a08b7a64d8fdc4d7658fe42.npy +03593526-76b3419536fa2802ead5bd90ea492d1b.npy +03211117-dd8cebcb4d0564059352b002a7d38daa.npy +02958343-528c01214da6d4bca7fd25564c2e888e.npy +02958343-f5e0edd70d644777cf1e58caa15acb49.npy +02958343-85f3dc3318f5200c8672c9b355cd2075.npy +03211117-caa4afd404f24d21275c1147a304ed86.npy +02942699-e9e22de9e4c3c3c92a60bd875e075589.npy +03001627-b5706706df77157627d4fc401a34f3de.npy +03636649-4bb676c497969016de98d10ab5975b59.npy +02818832-f6fb20673932fe50230e608bf41b643e.npy +03593526-370c9228a2f41e99346cca8c07629c62.npy +02691156-74797de431f83991bc0909d98a1ff2b4.npy +03636649-10ba42fc70f16d7f41d86c17c15247b0.npy +04379243-cea61ac56a07271a96cc2d2cb6bf6019.npy +04401088-57245f4db78fc2be7aa291768a04b26f.npy +04379243-73d57c83a4ac0979d80195020ba66865.npy +02958343-1d4066f8ae88a1ebec8ca19d7516cb42.npy +04530566-6e739e28803bbf257446ad526c7486ad.npy +02828884-e8403ea994ecb1cf855931d119219022.npy +03691459-3ee30326a3bdf219ec2ca8479368108a.npy +03593526-b59f693b45f636d54c6c80caaf15808d.npy +03691459-6d6fef896f1196416526bbcfb9a38489.npy +03001627-63d45791c56483bb2662409120160a57.npy +02933112-9a195ea2a21bc7511a4db721d603d852.npy +04379243-8cc8485f249a37f595b25bd3accf45b5.npy +02958343-3e823f89c611fe57a413908c0e169330.npy +03001627-f7b52f9c95ebaf3ff91663a74ccd2338.npy +04256520-5850eba97de66d8e283b00891f680579.npy +04379243-c1fab1be028d2d1192d39b162a300de1.npy +03991062-6067418287b99c57c0592af70eec7f.npy +02691156-65b3e612c00a65a6bc0909d98a1ff2b4.npy +03001627-21a7166815b80f3f7fee47aa19e2e28c.npy +04379243-3ceb74b707f814a17bcd6a9a3aec51dd.npy +04379243-3243ddb2aa4d1659beb83c64f2162734.npy +02871439-920251969a40dcb155f46d55537192b6.npy +02691156-adad9536c34c673862b600da24e0965.npy +04379243-1e4d84c0be21fadfe84db9643b62f161.npy +02958343-b8c8758f8ee058182a9eb0f146e94477.npy +04379243-4f5c111a89b3fd27aa29e9f0529e8ef7.npy +04530566-ad8b5aaa3eb9f2f69330265a9fff38de.npy +03624134-eeb6322ec7492375bef48d9603e8869b.npy +02924116-be3a3b68029787359751c0a6c5d226d3.npy +02958343-f82b9a21855ef3feb1bb46d2556ba67d.npy +03991062-26d74b9867e986b08d38155f5ee83a11.npy +02691156-a61a59a4c48154db37678474be485ca.npy +03636649-12c0b15c8ed8a3edb039d8689a74349.npy +03790512-bf7794ea4ceb978bafc70af22a99299d.npy +03797390-7d282cc3cedd40c8b5c4f4801d3aada.npy +02691156-8700f6db654c5d2aca52e8e28cb200ce.npy +03001627-5ca11d3f35d870e1b724bccd568c5fc1.npy +03636649-33147aaf3d2c6fbc137af984a9f45d65.npy +04379243-f0735e59fa7222f9fe8adc3c073336.npy +04256520-515431e0c0854f1cce8417aef1b7a422.npy +02958343-318eaf9f125d8296541e8704b64e3884.npy +04379243-b1ca280d9567270ade98d10ab5975b59.npy +04379243-16ee1b2d9a12abead99c7626c95596.npy +04256520-9ef66cd1ab321cd3872052160bdade26.npy +02691156-53d8ce9573e361d990b1d6deb98feec6.npy +04379243-a5e061fc25bff768623d10a210f40a3f.npy +02924116-85efa9b5820d4fede381e109d127fc51.npy +02828884-2f815697256fce5a155b270ed8c04b46.npy +04256520-1867c1751ae7bb2829024035009201d2.npy +03948459-75476ba20ddf71fae868ed06b4dfef2d.npy +04256520-36ab61ce3c894d6514038d588fd1342f.npy +02828884-ef207b78de8277ec42fc59644ef58e22.npy +03337140-1d11f72cd35fdf2a4c3aee8e9d3a6ffa.npy +02924116-49f6f4047f548094b343a6a5860e15d4.npy +02946921-25c253b2e40b6f4ea61649b05d63e9bb.npy +02958343-626738526152dd13d76439fb95cdd2ed.npy +04256520-bda845f53dace1a7ab610b0c94236463.npy +03001627-e905abdafadb48d4155b2bc3322563d5.npy +02691156-bfd02b9a1ad7ce73fe2d13a096d8b561.npy +04004475-d92d3fe1e9174e3fe0db0b99552a07a3.npy +03001627-654b7415b53b5138fc5718d28351c534.npy +02958343-45745eab59d4ed09e9415adaaf77fdbf.npy +03001627-7aa759758e3b0d5024ef48ae9e8e965f.npy +04256520-1545a13dc5b12f51f77a6d7299806.npy +04379243-c578d2fa302f0b935e7f9846384b5857.npy +03467517-19edd59f5ac0f3c7972b486a47e2bd46.npy +03001627-7729d76b67931981f9111ef49c078dbe.npy +03001627-885bc048615523273eec26c23f5bc80b.npy +02828884-e79a991fbf64c2c771dde564c9e207fd.npy +04379243-a355108bb5272ff256d80c2792e1f42c.npy +02828884-229d510bace435811572ee5ddf1b55b.npy +04090263-f646b2bad0332c0a52a927716d03931f.npy +02691156-735aad15a1d22ed3dc92eaa8f8f40f9f.npy +04530566-82242062558a24bc97a9c690ec97cc81.npy +03001627-e862a41f869a4274ac7f1a00b76bd166.npy +02691156-edc185566c1df89c35fc197bbabcd5bd.npy +04256520-1f620792984f66fd22c3a2386a9dfbe9.npy +02992529-2fe9e8fd2a7c512ad1f278e1513f3b7.npy +03642806-39e61115ba9df4d3cf75707bd872e2b3.npy +04530566-e9c603efb5aea8087610cb1c03c9c3ea.npy +03001627-55dadd6acaa2a0c0dab72035db8eafd.npy +02691156-b837c3b8eec02a4967c54439d6177032.npy +03001627-219c0f0f7ee5c3737f9dcf5672c2dd0f.npy +04379243-5b67be496c11533c66289707fcc0ca1d.npy +03001627-b2239339005b14c8d675cc466d0d6fbc.npy +03636649-69baf1ded62a0259970e9f7b51f4efe.npy +04379243-2024beb1477fb5d2278d386bfa54545.npy +04379243-f2a759729bafbe88fef3fa725923b557.npy +03001627-5f256dd64efba74a4316d3320fdfa899.npy +04090263-fc0cf8eee4c33cbcb53b1ee7df9d3a60.npy +04379243-6ab7ebf9b94176456f1e07a56c129dfc.npy +02691156-12b25b8de7aa37a0bd46d022fd7d80aa.npy +03001627-934f911815518a12862ec27465061d4.npy +03337140-f4e9f25443ff6f963b59eeb47ee49193.npy +02691156-b2bb5a56b3d805b298b8c800ae001b66.npy +04090263-2f5dd43b4ffd7d433dd48eebe8f7b24.npy +03001627-60e8cbfd3cbf85d097b3b2f2bf40d247.npy +03636649-aed950102f1e9c7a659dda512294c744.npy +04379243-d2b0fe8551e6e3b0ab610b0c94236463.npy +02933112-c9ead211b387ce0c5c59c6146ff01de4.npy +03001627-1e03b1793723dc25fbd332e3dd079259.npy +03636649-b4f7f20fe212e633c14d5c159bab8297.npy +03691459-6450e70e275a80e0e39b302b17f4c82d.npy +03636649-fac2081abc0375649f41ef09e8fcdbeb.npy +04379243-feb92b34c698d396cbde89e0c48a01bf.npy +03211117-f7623667b09f2737a10a38d9fc3b0d4e.npy +03001627-b738a4aa965784abd86234e915108e6a.npy +04530566-5001bc761fe86d60a43a471ceb7c72ac.npy +04379243-4afbcdeba648df2e19fb4103277a6b93.npy +03991062-fd68b3538d3f12a2ff67c12005f72d2.npy +04090263-a9c06da447ff8ee6d6d33c92d1d05e93.npy +03001627-42ecccc972b45e38f4cccb2a97578c5d.npy +03636649-13f46d5ae3e33651efd0188089894554.npy +04379243-5b375eacdbe49cfaaa539cd22945e538.npy +03001627-e90f124b13901eabae8375def5e736d8.npy +02691156-4fbdfec0f9ee078dc1ccec171a275967.npy +04468005-618256f81ca14c15c50a037462bade42.npy +03001627-2f24021efe2ccfcc2db431502a680805.npy +03624134-8bac6592cdc56dcd3cfaf38598bf5d36.npy +03636649-169d73f18f7b17bb4a6ecce2eeb45768.npy +02808440-cb38405e384c79c05e4e385b035691bb.npy +04090263-cf5538e2b369b7b33ed6ca821e0a9e81.npy +02828884-4b715a1f611b30768b45d2a1081eca04.npy +03001627-8fd6ca8f2d0ce46b846c0e4d54382ad6.npy +03691459-590e2fa429a94e711b45df3fb820c9cc.npy +02924116-d630edbde8e8c3c1cbcf10e5718c0454.npy +03691459-ae4bcb4baca763c24521562865ab775e.npy +04379243-cba38f14dc16d5b5fbbc7c456d85ce59.npy +02691156-68ac5704aefbe4f54e86b47976e55141.npy +03001627-cccc93857d3f5c9950504d983def56c.npy +04256520-9b5e8c302f7e6fb4593ebeeedbff73b.npy +02691156-8fc553e3a88b7ad54e461d462a3ccbc4.npy +02691156-47b409c5c80dd7c533de69c9cd670995.npy +03467517-2e51f4d434d7f760e7447543ac4d4049.npy +04090263-6694001fb50d3f1237ff6d90891805e8.npy +02933112-59b0ac376af08592824662341ce2b233.npy +04379243-8bcba9172db65219ad5067eac75a07f7.npy +03001627-9fae85a69532d03fda686a7d8e3d0692.npy +04090263-6f09b74771f8b4808962281585efe24e.npy +04256520-4d05c9f0f34e1c22715de3ea7b582d7.npy +04379243-f2fee52b9098c13fdcfa6f33a3c5eb83.npy +04379243-201c3e44a5967cd030bbd4cddd04c77b.npy +02828884-ffad1499a8bb6c7c19fb4103277a6b93.npy +04530566-d5b2fe7ceeed1ff59268271e4d570275.npy +04090263-8d9d9b749562c59a9a2ee232a197081e.npy +02933112-8fcfa31d1df6e8ec9c2edb56a98b4be7.npy +03001627-d7da1c65f996cef2febad4f49b26ec52.npy +02691156-debd942c5fcdc9c84c2c88971423d0be.npy +02958343-1f7393970917e558b4a20251cec15600.npy +03046257-2d65d034332ffc8397cf3f86b15a00c0.npy +02876657-882d477872fd88347df6165146d5bbd.npy +04379243-8efb3d9ec93520a797046e48d8f1e936.npy +04379243-5ef5685e19c5b253674ce64e4bf77aec.npy +04256520-b281da26ecd358e1e7e684d25d4dcaf0.npy +03467517-c5f9c372078561644368de794b251ad1.npy +03624134-229edf8adcfee7ee70b60f242c0a291.npy +04530566-4b63a567e41b63974de203ef6842ee61.npy +04379243-74d470850c9f9fbcc2b64c0adffbe398.npy +02691156-e805054e6b9b3666fcfb100fed3ed97a.npy +04379243-40f1be4ede6113a2e03aea0698586c31.npy +04530566-6de5985910b222f8afa96d6d0eac8962.npy +04379243-884d2cc0d3aa8a72640e544a5d67c33a.npy +03001627-45a0b8c6923f587e694253b740159af8.npy +04379243-e2571e4eba2d9f5eab610b0c94236463.npy +04379243-49c24587a96211191679687a9323c13.npy +03710193-7ddfa116704ae5555bee258e658f9767.npy +02691156-ca0f8f701a042689331960c3710d952.npy +02871439-82b88ee820dfb00762ad803a716d1873.npy +04090263-5658068646336771cba7035647fbacdf.npy +04379243-104c8e90ecf0e5351ed672982b7954af.npy +04379243-fb4d71ac2bbefa2297936c81e7f6629.npy +03001627-59f4a5d8390c3c3d5fce6078044eb87.npy +04401088-8b291d445d412c09cc018c0e073a98f6.npy +03001627-b2f125cba550eb8bfebad4f49b26ec52.npy +02691156-d7f71651e6571ee2f63894cf4226f14.npy +04330267-902f4ee7655514ba109dc73fee74b150.npy +03636649-e6de1ff0564f172ad96790493cac7283.npy +03691459-75f07f0e8343639d37276d660ae66f0b.npy +04468005-7c511e5744c2ec399d4977b7872dffd3.npy +03001627-39fb5d3f557f64d4389f9a01d027a78.npy +03001627-9aa05f609e6731bbec19069e387c0327.npy +04379243-7f808e545bb01ab7ac91966b4f1152b0.npy +02876657-368bbfbb2fe08a6b4c5c5c89015f1980.npy +02958343-41a6deadd39b4c754d0f9a1ef5f184fe.npy +03001627-610b1621d1997ee1daf3c002be658861.npy +02924116-fbb06ea3f0c57f4d57987cc554f65cff.npy +02828884-4ddee322f191096a54e14b4b3de20526.npy +04379243-de500885a5cda50f99284d844aba7576.npy +02958343-1bfe2cb495f63c8f6bd865f153842b49.npy +03001627-12a56b6d02a93c5c711beb49b60c734f.npy +04379243-1ef656b0524b755eca6c3f11f48d07ed.npy +02958343-ddd17a0d7ca713f2291ea03049d40375.npy +03001627-780809a0d1b68f4a8ef4ac3a24abb05b.npy +02958343-8fe901ed95e115ed70a5d1d8432b5405.npy +04379243-32c78783100eac55b45b50ab552e35ba.npy +03001627-b3ef1c8790d42507d0dd5269e5b9cc8.npy +04090263-d9f1cee28bd9a88c2f2258791e7c116a.npy +04379243-b86e23bb0a3d337ef4b6538438a0b930.npy +04379243-c3b49ab37876c7f219fb4103277a6b93.npy +04379243-2a44569c8ab6ea22f222df538827afaa.npy +04256520-5d6a4faa40dd337826fc8d57346a2e4.npy +02691156-7977f492ebf2c1d5ce78be835f7c74e3.npy +03001627-d80ea722df716bd0b15194162f658e87.npy +03001627-76767a15f8de108975907ca70d2973a4.npy +02958343-79d4876cf799516b977b27045b1d8055.npy +02933112-3bc232700d2ed20b89a68decc32d3e34.npy +04379243-f89a468c302c89d9534fa06200d07790.npy +04379243-a4dfdf3529355cd934fbd63590727729.npy +04379243-f34a17d1b45ccc541763ab8766fa2282.npy +03593526-8ba355a47e0dd19c491effd0ae881ea.npy +04379243-711b4eeae1c12b77cdd18be3aeb2d66e.npy +03642806-f5fc954736b06be15fd06491ae919ea3.npy +02843684-e49629ce9c305ea6c725388bb41d64e3.npy +02992529-ec549f2ce1fd9acb634c1ac38a055513.npy +03636649-a90fe01c3ef3ee30fcb8d8c6d4df8143.npy +02958343-906e1969f7974f85977b27045b1d8055.npy +04379243-a6ddbd0556f5de20c64b3fdd6a5588a9.npy +02691156-71ddef945e2ae8de7d64cad20089f027.npy +03691459-b865f12d17532a3fdb24fbbf172c2159.npy +04468005-a41ec8a882ece95956055ed8cb4119ce.npy +03001627-387a0509406a8653b40f0ac0fb9a650d.npy +03467517-b58fa1227a9dba7941e721059b25b8b8.npy +04379243-33d18dbc04c4fc02e76bc197b3a3ffc0.npy +02691156-65d7ed8984d78a797c9af13aaa662e8e.npy +03948459-f6fde7ed3205f66bc440ec33c5d16292.npy +02808440-b7f3c33d4cf8d2fd191c3762b497eca9.npy +02958343-6e25d6cd4b112d0654ed192f2298faac.npy +02958343-e67509fb6192be6a7e7e5ea49ad8e45.npy +04379243-c582922f61a11b1ae76bc197b3a3ffc0.npy +04379243-64b2121e41762bd47954eb05bbab463f.npy +04379243-f0617cdf9dd8ece3d838ae16242881dc.npy +04530566-293781c9bf4f6168c4ff53ac1cae3d62.npy +03790512-780767b19b3201fc80ac3c28ee20beb9.npy +02747177-b51812771e42354f9996a93ae0c9395c.npy +03624134-6fbb80c3ad257a0bca53a8c40217e117.npy +02992529-1c87049d11292c5d21e2fbffea258ad5.npy +04379243-f48e40d7f7b07b8ae0c7300d2b2cc1d.npy +03691459-2ab4f9bbdc17d9cd618e9d35559b7aa.npy +04379243-cd09a9641ea97d873823cce3247aa03b.npy +04090263-498b4043ab8a0675e19905e7053d006d.npy +02691156-bdc5360ff3c62ed69aa9d7f676c1fd7e.npy +04256520-db09115f98ebf4bc20768660cf080d12.npy +03001627-741db054bd52c8884733824eae5cd9ae.npy +03636649-54d9556d51287bb470a43c2d978e502e.npy +03001627-501b15f5ff2152e5f7628281ecb18112.npy +04401088-8ef2182a6f91e71e7877a964f5722626.npy +04379243-8d7ac6078989980fad16260d4d73b56.npy +02958343-91be65c386bafdd21aee99ace10c2d7c.npy +02808440-8399987b9bca0dd0e63a9e8397b31118.npy +03691459-c15fdc911c54f4cb62c440075d5ed193.npy +03513137-eafb1b2b77dbf8c8172c0c1bc4c72a8c.npy +04530566-f17262f7443b98de38d037116a032a18.npy +04530566-7af3abe01d2ba4ddf09d36263ac1039c.npy +03991062-5a1ce09a479b866f1ec48bc3c478566d.npy +03642806-25192ef0befdd75d291d2d0d560233f4.npy +02691156-ffef991d85e3136a9a6e43b878d5b335.npy +04256520-91e6ad8710f56cbd91d7b2865937b45c.npy +02992529-ad0af9e3dc8473296841a8d53aa30506.npy +04379243-6fd426f7cc1a2b00d5130a83cfbc8bfc.npy +04090263-5f8daf709c9d4edfd3b936925082270f.npy +02691156-baa972f48cde1dc290baeef8ba5b93e5.npy +04379243-80ad425b12c2c008738e7290b6f3237.npy +04256520-2d4bda48253f35bf52979c729a1f9cc2.npy +03001627-5da5cc7b5a6a9d6f433334f7dfc6c30a.npy +04468005-a9c9ad88e5b800ae810c01b1498aa2b.npy +03325088-b17ff4c76129d106742cb5615ada39cb.npy +02933112-2b45de8320e0b2ca55d7f0828042fbd.npy +03211117-57093dac689edcf2cd318d8b7a33448f.npy +04256520-7c4bf66c71ca90b5c2c449c0c0579ec3.npy +02924116-9f2a6f480d60dd2424e09d2b1795b9f0.npy +02933112-265521e0fc7a663259f8e31ca87c470e.npy +02880940-530c2d8f55f9e9e8ce364511e87f52b0.npy +03991062-fc24453aa13d6b2293b2b448490135cc.npy +02992529-623bc1157836ddeff8a51dbffe0021e4.npy +03001627-a45477c29f71d4f37597e1f94410131a.npy +03636649-e8c75d7c6f151e2b3d23022ce06f940d.npy +03790512-24359f14ac176b13d270caeadc60b9bb.npy +02828884-54c5e4961c97527dcb2a965e75be701c.npy +04379243-6560601e3e72b64296c50b25b74de6ab.npy +04379243-1ac080a115a94477c9fc9da372dd139a.npy +03325088-ede36d1ad901fffa54d7082b34825ef0.npy +03691459-469f794b77f3f82b5f1f3016f773503.npy +02871439-39ef7e982d00763560507fdad4357e06.npy +03001627-34b1b2ee54ea314486a1cb4b695edbd9.npy +04074963-57759e351ec76d86d3c1501c166e6b2a.npy +03636649-1e5e1ff56c27c0d2adc5f5aafedb1c38.npy +04379243-e7f44c111fc65019e76bc197b3a3ffc0.npy +03948459-752a981f2d8910a5fef144202cb2b935.npy +02691156-e06c2333068e9bd0755d33896264181d.npy +04256520-1c7c7a7b20831d699cd2678508cc27b8.npy +04099429-7fead32a8af2bf9d347bb8efbe3bdc7e.npy +03593526-75ebd17ea72f4e6257f40ff86fe708ff.npy +04090263-dfc1c3367bba345c45727cc98c29a700.npy +03624134-4fdd99c04126b0027037e93b1456fd1d.npy +03046257-31c8a274d5b80d798325b286685278a0.npy +04554684-c0a1a342e0ca945edb04615d958147f5.npy +03001627-5c95a378674a05b313236fa00fce09e4.npy +04379243-e5261b63c63b226bf7e56c1f3346606a.npy +03467517-c1d8991c3a219e335f1fa9e7c1fad10f.npy +03325088-903a72db42df53f5669f229cc42f76.npy +02691156-8d847b813fa70470bc0909d98a1ff2b4.npy +03207941-d6b3d8434fc41179db4c5469c0c1ba80.npy +04379243-a04a45fc865cb61dbfb7d42898b82ecd.npy +03001627-a00f4f424b6b4c4c19fb4103277a6b93.npy +03691459-e849b0017baa1a978a0181490cb73cbc.npy +03691459-db9fa74a2b9ae465c7e50d673f14088d.npy +04379243-c8bab1768e4af6ad5e89486951545417.npy +02747177-3886bc0f590dd5ef2056b4bd5d870b47.npy +03001627-bc75933af4146bd3fdce5d02dd243c32.npy +04090263-e92b167233273b73f4085f263b03d26c.npy +04379243-1b4e6f9dd22a8c628ef9d976af675b86.npy +04256520-901440644e396746bab0cb5a4ccf2fb2.npy +02958343-479f89af38e88bc9715e04edb8af9c53.npy +02691156-d837b5228d9c010bbe584d85bf07b4ac.npy +04090263-79e15b2cae644af4e8d3100f6970279c.npy +03001627-a734ccbcbd430e8c9eea64ae4d2b4158.npy +03636649-c1d2b20435cbeea0c0028f3b08785d05.npy +03642806-a702d347f32e0d3a229fe85eb79d32b.npy +03636649-b31c246d2341429f76c2a9de5c96f76.npy +03001627-6f04104e178fb858f7628281ecb18112.npy +04256520-9e88cb24b40dfbfb85b479b317175b55.npy +04379243-9d02362926dcb3f6951c1fffab4f5807.npy +02808440-f6f8241116920f45b362845c6edb57fc.npy +04256520-330d44833e1b4b168b38796afe7ee552.npy +04379243-48afc56a733cf916660094e03bb531dd.npy +03991062-9da456e7bae24501ffc6e457221b9271.npy +03691459-e02649d9d5ee2f26d07c55cf995503e.npy +04074963-5eacb3e90eed9700fee59de128b08a7e.npy +03001627-c960ba7a781b6fb9fb7e1f95705d8fb1.npy +02747177-208777cf36e27cdef4fb4dee5181bee.npy +03636649-2ab4c7882329710f29a42a0444436860.npy +03948459-34d72e4e5e487d9c93550d252b5c25ef.npy +03001627-9582e42453da574f37bf42a4ca375618.npy +04460130-dd36bd331fce23aa5a4e821f5ddcc98f.npy +03636649-94eae2316754482627d265f13671170a.npy +04256520-a2b3c5312188bfc2789b222a43900931.npy +03325088-8323ee8eae530a642b3e9b6eb52d35df.npy +04530566-5b88544e42981ce0a71aa3ce894d7bf7.npy +03001627-10de9af4e91682851e5f7bff98fb8d02.npy +03691459-3fe90423ef5b56386af2396cb8af8a8e.npy +03001627-cf32f38c2b6c58dce45ef4135c266a12.npy +02691156-675464537c846822aa7669713586004c.npy +03211117-e767c4f34fdce88a9c4081063e213a15.npy +04530566-54c0a11324d0ca82942dbbe2d0488895.npy +02691156-455bcf19112ebab52e78e1154b9a2647.npy +02691156-f58b4ed02fc2fd1d4e7648015fd29a1c.npy +04090263-77ef2da2754d6b82fa0021572e849910.npy +04379243-e6e92596fe6fa9c965124e7461e47506.npy +04090263-6cbf83cff8dc7b23623b64770edb4be.npy +03790512-923ce819405ae29230c72ee872e188e1.npy +04379243-883f5e54f764056f6dd4165bd7fb497.npy +04379243-e4e30282a0089a5bff06c5af4a0771d0.npy +02691156-56fbecc11e62071553a6ddb5892da51a.npy +04379243-3d95c4ebb88f94b3d2f054448bd437d6.npy +02808440-88b4942caf79dc944221bef0fa3c36b.npy +02691156-30b5160e2870b7a0ac8be969b55649e0.npy +02691156-f27927b066b0696d1f95d2b537942ba5.npy +02992529-fcdbba7127ad58a84155fcb773414092.npy +03001627-6a8e63f10bd6736e713decb1a0563b12.npy +03001627-b1f50d8d41a8c53b6197fd390b16d14d.npy +02933112-7822a30ec2e5c57f59f8e31ca87c470e.npy +03001627-6d78523e939aedd482e23b5f9fd46e1e.npy +04468005-1ceea57dda2812282ce211b1462eb07e.npy +04256520-fd2c3219b28d98768dd711af5650bdcf.npy +03991062-aff6b11c514f2c07f9aec59741c69cf7.npy +02958343-47aa50eef6b59ddbc552d162ae439d98.npy +03624134-539ff9b2a7a0329e759e4c424bcdaafe.npy +02876657-fca70766d88fc7b9e5054d95cb6a63e2.npy +02958343-6dbae14e481e8fb9333e0bf0b765fa12.npy +02808440-691d75148d42c03cccd0340812259a39.npy +03001627-91cf38c4b99d75374fa746d16faad4f5.npy +04379243-83a2a5dfe03a2be1b2b755acb296d925.npy +03636649-1c2327fed3930660177f2a3a0c71fbcd.npy +02808440-70b6ec39b993a7437a809fceb352d42.npy +03636649-f4994cf967f3407ff47b2ae6b11d6f43.npy +02933112-b6fa01c7e28a4a777024462ecce15220.npy +02958343-89765af115d9a4955591fcdffe729c55.npy +04090263-2edfa6fb67b14cbe6659d9c9bcbf8054.npy +03001627-2060f4d31feb73dd7762ba3a489df006.npy +04256520-7e1d225f13bf40d0d39e33fed94f56ef.npy +03691459-cc88df1c3cfac12a99db62650613bd48.npy +03593526-8c1d8325da907adf51f77a6d7299806.npy +03211117-1a9e1fb2a51ffd065b07a27512172330.npy +03001627-736630a749935489f78c99506bdaf97d.npy +03759954-738c4d765012dec0c0038311e9d5344.npy +04401088-a698b67778c02fcb5a0a15c8380e928f.npy +02691156-b0599ecbf78aa615a8e091cb544689d5.npy +02691156-596cddf6fbdc9d6b96212c8f6cd06e.npy +02691156-261093138afff514d8d7812d176664b2.npy +03046257-cbf19a9c2a47ae354b3c42e318f3affc.npy +04090263-4ae8bb7c50daf1352e4df18fcaa65e04.npy +03991062-ce15f18c40d5cc66a2c59a4d90e63212.npy +04379243-c7b8f5ba396c07331eb51344489c49f3.npy +02818832-b31dbe37497a7fd3812729af89b046f.npy +03001627-d16b62da42fa61f0cbce248a4e686c70.npy +02691156-ea1aa637a6cbe7b4fce29e20147f9d9e.npy +04256520-9840eaff2718fe1214038d588fd1342f.npy +03001627-b6fcfd4f7af69e1ce8f8c11a24c52ebb.npy +02876657-bcacdde81063a5df30612f5c0ef21eb8.npy +04379243-adcb67b58024afb99910b7ec4c4e599b.npy +03337140-8fba7de21910dcfc4c3aee8e9d3a6ffa.npy +03001627-a682c4bf731e3af2ca6a405498436716.npy +04401088-ffe8cc1d33f3fb83d954b120b2d50f0f.npy +02691156-e0b5c450de6d7fe3d87c63d8b3018b58.npy +02691156-ce827e4c857d553f71d03b466c72ce41.npy +02691156-3fb3fa76a2e67bae71d03b466c72ce41.npy +03001627-95ac07c8c517929be06a9b687d35bd76.npy +02691156-ba662ec78231c493252b4f9439ef95a6.npy +03636649-c78a8f317896b79f51f77a6d7299806.npy +03636649-34a9c2b926de1db2a50b88953d263a42.npy +04379243-956752510546d938788e70128ded264a.npy +03761084-628ab6e5d0cf78b8931f48202f034c81.npy +04099429-3e75a7a2f8f602df390a81c7a00f98eb.npy +02828884-ff7a08ac16701dcec0277fc71766d822.npy +04379243-99f15c63712d9fbe84868d3618d73011.npy +03337140-30aa30307b5c651f4c3aee8e9d3a6ffa.npy +02958343-c12a701bbdcb3df7473f10e6caaeca56.npy +04379243-5c4557a826e80297490ad276cd2af3a4.npy +03593526-3ce0e5906686042c939163818f3c3007.npy +02933112-bf4aed04442c31e4f759a9b042055cc.npy +02691156-5aee97ad467ed9d75fe4b20a3aaa51a2.npy +04090263-c513665dbd0d0606f85b811e02bb4272.npy +04379243-7e1f5ec947e7587e391e4d6c585a697a.npy +04401088-44cb63b74117f9a77877a964f5722626.npy +03797390-fad118b32085f3f2c2c72e575af174cd.npy +03211117-40c53f54e7fb0e3ff4c409c17e0a5165.npy +03691459-9d0734e39f06529ac0cc451921109913.npy +02828884-8a5a59ab999c03ccfb0eb7e753c06942.npy +02691156-1d5beedb73951ef68649ad8da70da1e.npy +04379243-39fb0260d1e669bed0037f03195bf42.npy +04379243-27fd962813feeb26be25fbd47cafc694.npy +04401088-96f4e3797b8e66042b8a15395c060463.npy +03001627-ee001ffa8483ae1b7f0e458a1629fd0a.npy +03991062-1ecef53ddd34e07d78caa162a41a851e.npy +02958343-fdb16a8648016157994a3466f8481f8a.npy +04379243-9a0f67133d4757964ef2fc89218529a9.npy +02828884-4d38a3e7f051446a9b5ae2fb66e1e25c.npy +03337140-4791327c6e5d0ce68962005ce0e986db.npy +04379243-3437f0ce3933d664842f894f9ca76d59.npy +03001627-e09466e9c122dbfdf51f77a6d7299806.npy +03001627-ea6c45a1a6accfa7201a419fa3bbf2e4.npy +04379243-6c9ab42a8e028b103fb0920a55a7e805.npy +04530566-14241942d79f89226587cb13c78fb9b.npy +03642806-645a52293092eceea37e4476f3cf2752.npy +03636649-629f9f656b05ee62ac280f441d6450c6.npy +02992529-d3dcafb368c1defaa2c7c5886f4bbc93.npy +02880940-fa23aa60ec51c8e4c40fe5637f0a27e1.npy +04256520-8c03e6ea484108bcfebad4f49b26ec52.npy +02691156-6f0ad1fb7917fd9b50577cf04f3bf74a.npy +04468005-68fa56bae19b6cc32b97ac865c3ecf8d.npy +03593526-f93f2a0590a805da30f549f12038e49a.npy +03211117-f75d1962eb04669a164790a64bab08f0.npy +04256520-5e9e4d6551b775d8cabc196a7f35f1aa.npy +03691459-e5012f54d03b863ecfd43bf63e641a70.npy +02958343-25c292692638406620f29d4da2b76f7a.npy +02992529-6609f05bbe9c49172cf708d3028fb325.npy +03001627-483cfed0659965ed73c478529c40c4e6.npy +02828884-5125cca7f42b90b2ad5067eac75a07f7.npy +02958343-e7add7a018da8056bda733a39f84326d.npy +02691156-fc7c3ccb57f65337209009cfb89d4bd.npy +02958343-33f95e59143938ddb490a9cf145bf702.npy +02933112-4d97127bea831058b26ee99f2f592682.npy +04090263-d4312787c89edb399a6e43b878d5b335.npy +02992529-fe553cf733e29a349426aa93c5c54668.npy +03691459-98cff6064749a5f3e746404352385716.npy +04379243-11fc4731e38789e0210283402c81dbf4.npy +03001627-86fc0fd9ed51dc11664b3b9b23ddfcbc.npy +03001627-6b8c5cd585ef8c67ff2b8acf844d34d2.npy +04401088-5a37ad3759b4d93df843a7d4732b1d6.npy +02691156-157936971ef9b6bb858b20d410ebdb99.npy +02747177-7b407dedd933e3812f59b845f0db2ab3.npy +02958343-9a22505d1e6221533c35e65001c8c258.npy +04379243-609f064ea48440645d8fcbc36a5e8c00.npy +02958343-5d381fb0fcb9ec3f3c2fa80e345b3e7.npy +04256520-fb859910000d1e219b709c9b379c59d9.npy +04256520-500fdf3d6ffbab95cb57ce1986fa546e.npy +03636649-1a87883fd4f52527e21c35aa7a22a003.npy +04468005-97fad8d4386e8be41183ae1f57465c4f.npy +03001627-e96c3df69c2a6fdee7e684d25d4dcaf0.npy +03211117-3f15446861936b20eb1a50f8f2ea3a88.npy +03636649-c05cc9636722504688e7662971dc736f.npy +02691156-cc9b7118034278fcb4cdad9a5bf52dd5.npy +02828884-e25c7c2469135e3fdd3adf3090c701f7.npy +04090263-d90fda1aec4042ca42b011d8a1631bd1.npy +04090263-41a9912bfe0dc96239169e4b52d9f093.npy +03938244-530cc7dd793df95f8f5ae2c97614087a.npy +03991062-9a5019501c85aa9c897534402e0f40.npy +04379243-b6884eb4e95d851b5f606243e56be258.npy +04090263-96b74853ff1d922f42d160994fd6c822.npy +03001627-ff5e8226b88c6b95741cdb62023d6a2f.npy +03948459-ac5baab43d72fce2771f90a41c66ca88.npy +04379243-c3c635d741fab1615f0b5ee0fb357b4c.npy +04379243-7c2fb7a6dde6be96bd5a65d923c337a6.npy +04256520-c1ae15118f856e5e3759b16de9b6963c.npy +04090263-1aa5498ac780331f782611375da5ea9a.npy +04379243-dff5b7cb4f72def6641f7a370ac2809e.npy +04256520-fb835879f66b7b95c43a4855019be9b5.npy +03928116-8678ed372995f6e49d1512864d95af6d.npy +04090263-27937d4b55596d689a2ee232a197081e.npy +02933112-7bd5510b4451cb651d6ac856ecde9eb2.npy +04379243-d9994cf6d5d444379dbfd5cfd194350d.npy +04256520-a3eef12c108186997b9a616d4541ada8.npy +02958343-c42f9dec04f0fb3151a95aaa6caba1d3.npy +02828884-3e323c2a7e5ea5dcbd4364391061cfa2.npy +02992529-271421566061988a93d9d97ff82834ba.npy +02933112-4e217d2ef816a08251c4deb11af7079e.npy +02992529-d8071a38bb3dd8f097c8d78b9aede742.npy +04074963-d393e6667bb949b74ee7c201cd897ec6.npy +04004475-1eb2eb87a623d9422d24866ea0018e08.npy +03001627-77cf056c6beffa5e3b6eb1ba4e121206.npy +02691156-86012cd0bb6727e9e80771be8faac585.npy +03001627-524bfc8159111e4571697d26793100d2.npy +02691156-5f8fa607106199e7bd46d022fd7d80aa.npy +02924116-4c13b5050aa7fe24ad3f75ce207a0bf.npy +04379243-a1cc1745e89098913a4642fe4c259750.npy +04379243-3031461b84576d7d6a69760cb58e50e8.npy +02924116-ced158ecd466c371d53a1e636a178955.npy +03337140-1bf8e2a98e2ab4316bdc8a5dbe375ecf.npy +04379243-90d87b4d9a5a1e78f4b6538438a0b930.npy +02691156-143326cbe409ca9f62048be44e1fa435.npy +02992529-e8d826158072a6bf1455397a420729a1.npy +04090263-7efdd44bf9d6ace13a653cb492d78488.npy +03211117-5fb06d76ec44a16bfa6dbbeb09c2f316.npy +04401088-7ba45cacce4b4c09c7a217851f86faa1.npy +02691156-c476ac72594e39ffbd46d022fd7d80aa.npy +02828884-9d56087c9f98bf90717cca22daef45e7.npy +03691459-6d070eaa65ffa57193fef5a7dc080ac7.npy +03467517-6602c186baded145d57700c05b1862d8.npy +03001627-72827d33aa4e3f54d8ce2b7ddb5bbcea.npy +02992529-933d5c217d9c01789daa2bf0c68f794f.npy +03513137-c347db0e6df5e11efbf020c099468179.npy +02808440-faf3f0ab58eb18d263f5120cfc7fc76f.npy +03691459-e8dd60afd061fb273ad55e05c29c23ee.npy +03001627-2fc2b897b6b131c4dc75a59e280f3bf8.npy +02691156-acb99bd964b1b23ad13ef00338ba8c52.npy +04379243-eca9efad6364021cf42a90fe4baf4591.npy +04256520-3f8aba017afa6d94f78aa2d67f081607.npy +04379243-21e8c818e9d517f919fb4103277a6b93.npy +03001627-7b4dc28c2d3268a09af25a2e608033f.npy +04256520-336fc8a43b3120932c48d6b905457dcf.npy +04379243-6124096fd3488b7fbbc8ef3196ea5fd2.npy +02958343-9446a1c34cc06eb518b1741f84b73b.npy +03691459-a31ac0bd8915d99631c992914b89bc52.npy +02691156-d171967c6353177bb87697d3904b168b.npy +04379243-14786ae920496ca7197c43c7dc584772.npy +04256520-3a693ca4add94bdffe1db2d0679386ff.npy +02924116-8b44b2dfd3de8e638468bf2aa02981d2.npy +02876657-3d758f0c11f01e3e3ddcd369aa279f39.npy +04379243-54807aa2b0f646a448efbbb060f51a02.npy +04256520-37cfcafe606611d81246538126da07a8.npy +03948459-434a15053bf9d88c670144fdfc186d25.npy +04401088-d6120b12aca39e73cdbe8a30cf95821.npy +04530566-68e60ab321e4198ab437d385637c4e1c.npy +04401088-983b045d30322f96b102e855af58e521.npy +04256520-9473a8f3e2182d90d810b14a81e12eca.npy +03636649-f4da1907ed935101ad5d0d05865f4466.npy +04256520-5a419dd9295d84c538ae0e23b03ac623.npy +02933112-bb741a003e5ff46c59350d819542ec7.npy +02828884-57678bef578b487a738e43095496b061.npy +03001627-11c7675a3dbc0d32f7287e3d21227e43.npy +02828884-6a3bc6b44ba974b69c0c9824ccd078be.npy +02828884-61cb827012c745e0ba29d2aa241f8fc2.npy +04530566-1f846bab69b20a23561fc06c3ebd59d2.npy +03001627-f5d8dd0309401ebac47a35332c17cce2.npy +02958343-fabcb04fc015f822ca8bf2993ca245b.npy +02843684-c5a9713e045f91363c04c1aafcac3ee2.npy +03001627-f0f9048f45eed1ab3a8888e78d004b3.npy +04379243-6cdb79b485d9df2dc667146eae95e931.npy +03211117-ffbe714918d982594dea158f05aae320.npy +02691156-af6b292c7857c78abb0e5c1799dab683.npy +03636649-8e2c822e2a316fa04f3443b22038d340.npy +03948459-5b31070deb9226b134c40d765f77199.npy +02958343-395d86efa3a1a55a49ddf31673a8d73d.npy +02958343-863d6f24aa1a478e569564f61ef539e3.npy +02958343-85952ffb35de9bb951a95aaa6caba1d3.npy +02828884-72d5a7338dd7ccffd7262b1b986920e7.npy +03624134-9cd61c62fb1bb4c6fe72e087f55a178e.npy +04090263-c253c204b55470eaf4e90b82ab227094.npy +04090263-5eb64afe7a276c243a653cb492d78488.npy +03928116-e97e0ec1af5c74002e20b5399bb84222.npy +03001627-2f0318b23d899a84493f17f4fe9b9eb2.npy +02818832-d8de84e7c0f8cbb19473aab1da686220.npy +03642806-39778c495baf4bd9ac41b162b25b4656.npy +04090263-cd4fe695c04daeda6d976be0196645ff.npy +04090263-d83e4e5a7957117be6e1d9f65d65c2b6.npy +02691156-724be1fb093a31a1ac8c46f8a114a34b.npy +02747177-18dbebd6527cffa254685f5f473de41f.npy +03928116-3a27071e0436ca2e5917531e67f8d3c2.npy +03211117-3f83beaa4da6209dca62ec94d15d08.npy +04468005-e981f0fedd7680cbb2faf16541f353f5.npy +02691156-95fe3a31e4c084a128132d87f74ffe13.npy +03001627-590ae1748c5acdedb05550de345b6d0a.npy +04379243-d198fccb12ad508a3c97cc6789da1c31.npy +03001627-341e18eafb46f892a6fee8e2140acec9.npy +03928116-ef398cc2782a3a2191e9393f43799b4a.npy +04379243-87fd23051b01997418885412f2b0a4f7.npy +04379243-280949332aba8b8a6d8dfe83fd00685.npy +04330267-2a5cd751b522d07dce1b91578a49ea56.npy +04379243-cb6a8ea7b323c023f046f610ef0e4e90.npy +04379243-15e651b8b7a0c880ac13edc49a7166b9.npy +03001627-2448d9aeda5bb9b0f4b6538438a0b930.npy +02924116-9b2d743cdac60228ecd77a402e690110.npy +04379243-7a2f94d95992b5716521d4b69744cc6d.npy +03593526-9998f783571e10a7d680196133d8b70f.npy +03467517-3fba85bfdb125b1b93f0194265a9746c.npy +02958343-8c01303b68d30be5b9ad5039d820c924.npy +04099429-b6cc97a892c025c07ec95138ef83ef2f.npy +04379243-34df750af2640f576d616bfd695eec80.npy +03001627-34fc767b72047d9ae97426e55fb77981.npy +03325088-7224a70801bec99c3321831d2245cf06.npy +03046257-330f2677d7ba810ed527a9a6f5a872b9.npy +02871439-33c1b4d529f6899bd810b14a81e12eca.npy +03691459-d09f0e2e33452a739d3f10ce46ef328c.npy +02958343-87020c25b9166cf11d27be7764701cfe.npy +03636649-1c05f1a7125402ea4c135b40422475eb.npy +03636649-366b8a4c8e38961597910e2efc6028df.npy +04379243-8da6fc70195d2b4029820ac1e8a0acf2.npy +04379243-7ec59be3e55081f788292be2b58381eb.npy +02958343-15a5e859e0de30e2afe1d4530f4c6e24.npy +02876657-add17b35bc4665e6f33a685c2506bbe6.npy +04004475-c88c542028fe83834454439c22a43db6.npy +04256520-e21b95b9dbfcbed28ccbec49bbc083f6.npy +03046257-8a759c2f399d11e01560641bf48464ff.npy +03691459-a3f14846404245d5bbbcb091dd094e5f.npy +02691156-74cbf170c5f2fb587d9c9c8a8ba32919.npy +03325088-7b24ed5898c4971450da8b99982a3057.npy +04530566-4464fb8cf0d04cb732c0857fb4bcf47a.npy +03001627-deb0889d902f08bef51f77a6d7299806.npy +02691156-b5b6f5ed2031f34cec7a415ac918303f.npy +04379243-b00de96484b0275a5cca18918d24f6cd.npy +02933112-97ff4614190d8cdfff05fff9845ac53e.npy +03211117-318d349c03f0926e9b72ce7a99d3dedb.npy +02691156-3ca058682dfe98f7f678b53750b6d181.npy +03467517-2a7bbcd317bf2abc5eec6d8d24f1fde1.npy +04379243-5e1ca9adfe8c6af61f8d8332ee17945a.npy +02958343-9c686d6ec470f280473f10e6caaeca56.npy +04256520-93d5203022d651c831ae8c8ff1eb3d45.npy +02691156-afc975c77f6d5a1bd23d6ce2c840685b.npy +03691459-af4a2a3b3e3510bad49b96b9f2811c7d.npy +03046257-788d32da6b0e8ebdc6df46ed5c17ea84.npy +03928116-18d4bd26fc3946c536244e3d0dd95a13.npy +02691156-12877bdca58ccbea402991f646f01d6c.npy +04379243-1acf7b0939f3eea2eafdf94e5032b200.npy +03001627-7e2ef2a1256f2dc1ebe13e25a6ad0d.npy +02958343-300c1f29d253f94a97e6e890ac2fb198.npy +02691156-1850f4acdfb738bd7456183f198fd1e9.npy +03001627-b8726f4ca171189ca858c901f3d90b5a.npy +03001627-320261e5f3835f6381f667e2a25e0619.npy +03046257-e479a6ba9b2792d59c2f1b6ea824cfc.npy +04090263-f297de88033168facb88c9db6e396994.npy +02691156-ff12c3a1d388b03044eedf822e07b7e4.npy +02933112-46a618f995c1019b15dd7d7985e749c1.npy +02801938-284c23b810fc7823466f97f37dccbde.npy +04379243-be0174f29dba41c19dd07b7af48c9a5.npy +03691459-9c5a473824505151fdd0cc0c1a7bf8f5.npy +04379243-4c809952877b2a0bde88c30a08fbb953.npy +02933112-5ba1fc89122c13c5d4a147733422d301.npy +04379243-cb7ebc943b1b424988386fe1512ed26f.npy +02691156-2c1f66380af03e4c5d1df55cbe0874aa.npy +04256520-8d8d2859338eadc7bd16d4490a10a752.npy +02691156-949acc63ad8f8816e816c75152573ee0.npy +04379243-5d45378d9d2e11ff497df23b9b74f339.npy +04379243-83a8d95b2dcdd3a854cd2a0ea6cb618b.npy +04379243-691caf9e558fa4dec7f671ba289ebd83.npy +04379243-8f29431ef2b28d27bfb1fc5d146cf068.npy +04379243-63ed1dfd7ccdb5be20768660cf080d12.npy +03211117-27e65dc223cc8bc0ec059109909662d2.npy +04379243-b8fbc4e32270751830bbd4cddd04c77b.npy +03991062-bfd7c0ba3d690291271666a0c21c3f2.npy +04379243-6f5813533bb9001dd24546afc5de2582.npy +02876657-289b2ca2562277a9ca3fbd0e4ec160a5.npy +03001627-74d4b9b13cd160e6f51f77a6d7299806.npy +04554684-ccd7d621279425b8d1b2557b80a0d3f0.npy +02933112-6e4407e2b40dac9eda9c49a653a829eb.npy +02828884-69494ba3ad8569aded98cca8f0ccd5f7.npy +02958343-579bc3731a8a25f7c639b4cb04d4d746.npy +03337140-c0e291566ec3e3978aaae3d020f5ddf8.npy +04256520-e16abadfd438100b65569474a61cabc5.npy +03001627-6d270bd691a168f48fa2f6eb9fb1de7c.npy +03001627-a1cbd161f91e80eb450e3da30d6676cd.npy +02691156-1322a9cabb1517219a6e43b878d5b335.npy +04379243-7d9073ffce209233865f763ab6e6778a.npy +04379243-91e7dd99a4c945f9dd03ec353c1af474.npy +03001627-2b783fe4230af5436a7b680929b3b0fb.npy +04379243-bcbc5e30e12a58f07ea323bc74055b8.npy +04256520-de55a935ca4af29649a92ce7de587886.npy +03001627-8dfb550d8fc07ebe490ad276cd2af3a4.npy +04379243-f0990151fa433f1498cfd47a860803c5.npy +03001627-b5877df9f111bb91222f2fee97f8bdcd.npy +03636649-3bd57e05db01e224e7e684d25d4dcaf0.npy +03624134-508b292d7fee30b0cc34b900bb2492e.npy +02933112-bcee1a76f453723c4cc1952ae0d6e81a.npy +04460130-6cd9f0f548979d5160ddc468fe733ed1.npy +03636649-b1e552b454366a9d7787152e5befb05b.npy +04379243-4a310db5ebe11142eaf288f952624966.npy +04256520-cf2e145ae0b8923488df69d6c56c6047.npy +04090263-b28220a981c84b25427e47767269c4b.npy +03325088-935514d63bb8c70e3321831d2245cf06.npy +02691156-226e3f0a844a3b4a77fd7318510b8627.npy +04256520-9c103621101bcf9919fb4103277a6b93.npy +04256520-b33ce45211c0950e3ca067e8715715df.npy +03636649-e062fc06dd5e0e01469ef73f4f6c51df.npy +03001627-4a672cf09d7fdb7c83b06dcdd869d9ac.npy +03211117-28ce23d5e56e9afa8fb952c92850e1dc.npy +02924116-e2d650d6572321281ab9df4be75138d0.npy +03001627-5d5e887b9479de0ea9bdc22a1e02e82.npy +04379243-712d2c844d61aa9cefead98a255f706f.npy +04004475-6a5612fc6e4c19f65afcf0aaed5d73d0.npy +04379243-f7574c55aa4d5c80cba9caf4d254cef0.npy +03001627-17883ea5a837f5731250f48219951972.npy +04379243-307bc4f0db5cb0452f0ebd444c10bd0c.npy +03593526-256b66cbb1bd1c88b2cb9dff9356b165.npy +02691156-41acaa4d19dbdca75ad6eb90e75c835d.npy +03636649-5038edfd2c36fdc1bf1911e2d5611e35.npy +02876657-b2507913d631e8b8bcfad79fc308fa6d.npy +02828884-2fd70e9049377e22d4d8765e3910f617.npy +02992529-86fc58a0c40316f2562c8e1ac545ef78.npy +02691156-3636483aff4b7977b7d7aa9b9ebcccb0.npy +02747177-64b0698f21be2061fc555f910d0519eb.npy +02828884-77323ba74273cfe017b431cae0dd70ed.npy +04554684-58bc4edaefdf3b0e1db42cf774e49bf.npy +03001627-b998016472e9dd7a9b9f2eb77f5e247e.npy +04530566-f5217865935d63c61f2cd7f4ede43a74.npy +02992529-fe34b663c44baf622ad536a59974757f.npy +02691156-2bdf8800514abd05a7d2c4e7aae73d33.npy +02828884-8def49409282ccd4d8d8ba9872cc7fb4.npy +02828884-f2390f9103195622ad5067eac75a07f7.npy +04379243-cc5b638d81529dde3c2e50348f23d3d.npy +02958343-f4da249169898dd915212cd62adf957e.npy +02747177-1532546ac3d8a2cff155d75bbf62b80.npy +04256520-628d837b3c51f539dd97e8e261a01f65.npy +03001627-b2968ca25d2e2fe0f51f77a6d7299806.npy +04379243-1fb2be490f45ec6e19fb4103277a6b93.npy +03001627-70230673214644cc7954eb05bbab463f.npy +04530566-7fbdbc374263bc0e44fe68fe7fbc12cf.npy +04530566-8e7fd92d91a9974a2d220e1baafcedd8.npy +04256520-6d32f20579c9f422843ead12644a79bb.npy +03624134-6566d89cf6d6075c955a1453af41c99.npy +02958343-e67e3e3a21393927df59757e1209f2c7.npy +03001627-1f501c5ed6423e259c89c86daa5af59d.npy +04256520-21e0ce3126c67610c397356311cbeea4.npy +02958343-3d358a98f90e8b4d5b1edf5d4f643136.npy +03001627-f34a4514f72a3a767c11a4098d0a0259.npy +04090263-7864fa7de2295d33e6e039bfb82a52e6.npy +03001627-f1fcbd856669e000118128b8b252e07b.npy +03211117-60e6ee2c3a2aa3fd6d07c55cf995503e.npy +03991062-c4e339d4ce70c55a6ec7369fb34c68f9.npy +02808440-5c77eba7135d8703b362845c6edb57fc.npy +04379243-50fb47768cfdada29f2349486c570dd4.npy +02871439-5c600328b252bf051da287f87237ff38.npy +03211117-e52ef251efe783ab9475cee1777b2299.npy +02691156-366b149545ba4df546ed10e8f7fe336e.npy +04256520-dd375d24e534101b33f2b52ebeafcf18.npy +03211117-38517a97e7eaca1cf801e8fe8a186462.npy +03928116-95440fc9b3fbb5fb1d4127b3f0e05b90.npy +03001627-7f3562432f02b8a897d3ea932731fd42.npy +02958343-cd7feedd6041209131ac5fb37e6c8324.npy +04379243-8ffcdc51a930bc408964093366ba01ab.npy +04379243-1a05bd57d0ea709e7d3ba54b9bdaa55c.npy +03211117-d1b3804c23311181f361255e85d5896f.npy +04256520-1aa509f3d8c1d1e46bc58b7f28700afd.npy +02924116-3805858e0567994041cefd10ce5d6cc0.npy +02808440-617e1aa8b3e05d49bb6226644eb475ad.npy +03211117-1dd3f80712873a638f6095a93258c867.npy +02933112-3297041a1a8de1d3d0f3f1f5f6accdb1.npy +03001627-e2ced471afce616454bfa32aa0766acb.npy +03636649-721baad382f73c46fcb8d8c6d4df8143.npy +04256520-ed90b3d1d41c46a82b09cb731e7a040f.npy +03991062-d6154a1c8df6a464a3b06ba374e12b77.npy +03636649-933176941f95f833fcb8d8c6d4df8143.npy +03467517-887c39981c4cfef661cdd121f4738c70.npy +03001627-a241ab0fe7fbb1f41dea5e6084523ee.npy +03325088-1554a9af8847c2bf14b35a7d7cea7130.npy +04379243-8ad152454e2f1663cd701e9c04d3cf7a.npy +02691156-8ceca54101f96a96d972c9dd75ed77d4.npy +03325088-310875f409f511ecb482922dfbcdcc.npy +02946921-70446b4dc6649d0173c0d206b70af93c.npy +03001627-30d93191cb91f8ece6c5cd45aa112726.npy +04379243-20ca7b1864d7badc75bff8d65bb29152.npy +04256520-33bfb06af948d3415cab680ae8f530b6.npy +04379243-39b90508935f0118dde86ae42c792b26.npy +03001627-c1b64fef5f3efa0a129905ebfd12d5cd.npy +03691459-3636ebcd2e5568616bb15da9e307a14.npy +02691156-9d72d4ac799977bb71d03b466c72ce41.npy +03691459-ab5c8c38528f06daf398d0c5832df00e.npy +02958343-2669bd62546a8c8176ad064d1c5fdd7c.npy +02828884-1b40594ce6fa66ca35028a2641239f56.npy +03001627-58a7b826ed562b7bb0957d845ac33749.npy +03636649-c4dcfcc8c434f13230584014222e685.npy +04379243-5f0c33039269b7a9f0e84b9d9ad447e2.npy +02958343-560cef57d7fc0969b1bb46d2556ba67d.npy +03001627-a85ce69dd5aa852055dbece39a4b7905.npy +02876657-d829ffd1d35f36a61ad51dad4e9c1543.npy +04379243-1dae9ed6781af75f6675521fa630312c.npy +04379243-8770701a1d5cddb9def21b8ee4b159e4.npy +04090263-9fd0c3cd4a6a4afeb8d88853b13ee149.npy +03001627-75d28a98c151cbe678d2ffcbbc0020d.npy +02958343-3870022ab97149605697f65a2d559457.npy +03636649-f2038cb9bb9438a6c790d7efcdfb5239.npy +04401088-19208607cafce17dcb85f279c97d4c5c.npy +03642806-19117e74b575cdca82555f4c45537277.npy +02958343-61f4cd45f477fc7a48a1f672d5ac8560.npy +04530566-cc6656baa69ba0defd40bb12da2df97e.npy +02871439-5a163a048d89f667731124f40d99e6f.npy +04379243-4b1ca7263ad178f8bed8cac5da4f54bb.npy +04330267-917676329f834bed201769e59267569b.npy +04379243-85db937f27544f5f9f23b3819daf3902.npy +02958343-4e201189ae860008bc1bdcb65bf3d926.npy +04379243-f88d344aa47deb52276813f95a6b7283.npy +03211117-5530382ad4ea8b364abfe5850a7ebd07.npy +03001627-309674bdec2d24d7597976c675750537.npy +02942699-a4b0c73d0f12bc75533388d244d29c5c.npy +02933112-e47b9d0905d05d656fa63795f94c4d8c.npy +04090263-9bf95da67ffa58213a653cb492d78488.npy +03211117-792839c9e28f5afe4edf4a0df1fbc500.npy +02958343-923007b377bb1cab473f10e6caaeca56.npy +04530566-410c336c78ce00ebe2f628ca3c07d462.npy +02691156-b8fbf59025f18f1ccf5fcd318778a0ea.npy +04530566-1442afdc0aade741c46814fb26e284d4.npy +04379243-f44c91626e4900a5a26aea0642029fc.npy +02691156-b43165635fa89eb11416125fa4d8926a.npy +02691156-fe266c740580c102ff9ce0c50c2cd25a.npy +04379243-6ab1ece006f03b9c955e5ed03ef3a2f.npy +04379243-af953537017f49351e3178ebc750d175.npy +04401088-23cf8469ffbd93ff8faab772f03eba4b.npy +03467517-1904d163ebaac00722b42f314feaca43.npy +02933112-a5b61e473c6ceef9f51f77a6d7299806.npy +03513137-e3d98ac62469795b20f6e48f6a30cbf.npy +02958343-56d463162ff5352cbd835ce3c63f4d10.npy +02808440-3358fed603caf82bb362845c6edb57fc.npy +02691156-d6ca5966c5ed5b86da2b0f839aba40f9.npy +02933112-a55b6196e3402ba340789cf33f2f1153.npy +03467517-c8010d22e39c2f0c2b996d5d44e09408.npy +04330267-411079245246f35841965be83b7745a.npy +03001627-4b366b7995cd8d7fce4f274577283b16.npy +02691156-db73a3c857949f469a6e43b878d5b335.npy +04004475-c8ddeb1636a1c90ac327bda7ad667fab.npy +04090263-23a91d141cd1cd36a9405d5e0b8196f.npy +04379243-debd11754f993031eef3a45c2f31a227.npy +04401088-ba9f7bd05d6f028fc1a1659eb4f57afc.npy +03001627-d27be0741f13327efc66b92945eed242.npy +02871439-18fe362284ba7ca4d810b14a81e12eca.npy +03636649-77a7d38645738e2212c5719ce6179.npy +04379243-15ec20de98359ec88de7bcb173109d60.npy +03636649-e35009c75fb246453f02f5b8959142cc.npy +03642806-80f23c80d8d050db169ad157eae2079f.npy +02958343-494e45d11299de95c571e4850ce1413.npy +02828884-77597f34b5f37c5e7a403ae58647b271.npy +03046257-9cb8f60044f2f2e014038d588fd1342f.npy +04379243-67b25a96e4a0f49bc41d4e0e25295960.npy +02880940-4227b58665eadcefc0dc3ed657ab97f0.npy +02691156-63c63aed97f15526bbf3143b1cb6076a.npy +04379243-fadf4f0b608be6272648eaf710bc2c44.npy +03001627-cadf69f5353039e8593ebeeedbff73b.npy +02808440-4aef9fc6633010a927b4493ee0c4db3f.npy +03001627-487040c5fdc68fdfe6cfc789522bfbab.npy +04379243-9dcda566c3265d2784868d3618d73011.npy +02818832-a6635de3c4a0e934b822d48a43773c62.npy +03467517-95b6d674bd840b674817b69d2797a90d.npy +03001627-583deb9e5cf939a9daeb838d0771f3b5.npy +03991062-f47da3a419cdf600e01d7dc978602402.npy +04379243-8ce70dead5119191cc3492a06e9bd850.npy +04256520-ad5ef1b493028c0bd810b14a81e12eca.npy +04379243-aa6cfcdad80f0ea961e8d86dc5569c02.npy +04256520-bd088259c8ee711c3a4642fe4c259750.npy +02924116-1dea3af9695415f71f6a5b0146bf3030.npy +02691156-557429a274a21e1e6a257cd6bc529741.npy +04379243-97779400c9a7a15e3c7dffee9c6890af.npy +02828884-c0840a82cd05765c924bf081da6f024c.npy +03467517-fcab134da044e5fc77f469126771fc30.npy +03325088-bb428566c6138a876c18e71fd49c4dc.npy +02691156-2c97e6b2c92913cac1ccec171a275967.npy +02691156-a04d10b24ede5e9a3de778e85611513b.npy +03001627-c29f439d92c7ae8d6d26324fae5ec3af.npy +03642806-b3a2081fc19c7bbac241f229aa037cc2.npy +04530566-9fe579f5bc52735cdef1530f49dfe050.npy +02691156-b702e35f4a59e81f64801ad2940cdd5.npy +03691459-ca052c8db0c94fd345189af3887d3c51.npy +02933112-c28ae120a2d2829e50e9662c8e47fff.npy +03636649-9b579915b883bea042a65b86449bc7bf.npy +03636649-1fa4508dad05235a7d3aa3bae1f7b494.npy +04256520-c2a8f4c920b6f7c24097c269bc92f53.npy +04401088-8da5c29d14a1003d23247d005da93d43.npy +04090263-4c5a984272a922ef94a57adad86ebb52.npy +04379243-aabcb5d610e76ff19ca02c396af0c503.npy +04379243-29ec54b06d35acb2027cee422df2aa3.npy +03761084-b6f8be7f5c4a97424a44340bf227e40.npy +03211117-810fac004670692fe9d7a3dffbf25100.npy +03001627-2d711c85c60a0785c3bd24f986301745.npy +03001627-67017c046fee2900d09b414c3d8c49bc.npy +02880940-b5d1f064841b476dba5342d638d0c267.npy +04379243-6a8df7fe3bed16f736ac40071701c687.npy +04256520-f4830a8e2ba2c531b18ea2be5fef7826.npy +02691156-62fe06fd4f1b390fa9bcc7eaa4032fa4.npy +02828884-2fe40aafbefd99a9d2b12aa6a0f050b3.npy +02828884-87783e267a4db70044a8a9dc66c6c095.npy +03046257-fb95a457d7382fd5902df966e52b1aca.npy +04379243-ce4e075487aa05ecdcfcef693e7ec696.npy +04530566-4d95b6e392c9d95981e1e9063401fa72.npy +03001627-a97e09489b46f7492933f312813ce997.npy +02958343-30c86c4764df9f795686045783681fbc.npy +03001627-68b26c9353e65419c3e46f55b34610cf.npy +04379243-dd0521f27114171e492d9da2668ec34c.npy +02691156-172e23ab5b4d189566cf1b4a8fc3914e.npy +04256520-21140988a7602153f05a611b5fe35f32.npy +03691459-8150d4e919381c64e1ecc02d6acf021b.npy +02958343-dcdee01d7fe6e1a76ad064d1c5fdd7c.npy +03691459-c8a343f35b8593981ce8823e87f4a7fd.npy +02924116-32fd2bc978defda79aa320f2e657a09e.npy +04090263-5d461974aa75e99fd88db40a5e607f21.npy +03691459-8a536e4254674fbb73e1b2d018c0512.npy +04379243-f7fea253245d97786c02d42bfa6c5667.npy +04379243-a15f31e2302f6ae5d67a73ffd62ba73f.npy +02691156-15ce56898a636466afc526de59117398.npy +02691156-7fce28d597b3137cf24f8f5f80968450.npy +02691156-f6373cc88634e8ddaf781741e31f0df4.npy +03642806-7766bddc0cc89e4234b8b727387e0b56.npy +04379243-1c1f65cac6bbd1e15dd7d7985e749c1.npy +03001627-7f647aa4750640fdaf192dd05d69c7a2.npy +03001627-6d4ce042f204e89db413bc67c6e4035a.npy +03325088-5ba4d7ff5de1e727c36fb70296e45483.npy +03325088-d8baf610ba6cc3cf3321831d2245cf06.npy +04379243-72bd77bd74cce09cbc6a236746230424.npy +03636649-433c55dc486ff83398b2240479533a01.npy +03636649-bad7893ac164cc44a43934c3f4e340d5.npy +03001627-183974726abab0454aa6191ddaf4b676.npy +04379243-55457cc3f0e7d0e06bcd32c43682e841.npy +04225987-a34d794cd11272512cba79096b49c1aa.npy +04256520-e78c23ab7426227b4b3c42e318f3affc.npy +03001627-3eb60e6679d1df1dde7eedbb2790491b.npy +02958343-768ea3241699f663f1cb19f636b1c2bd.npy +04530566-e0d1f833e8dc5c604947b319a9e09fd.npy +02747177-45d8951ac1dbf2cbf51f77a6d7299806.npy +02691156-56bb8130f49b481e230ac8907b9b7f90.npy +03467517-bd6057c7ac1ef31193f0194265a9746c.npy +04256520-317850f9c80cafb561bfbba8a5defb02.npy +04256520-e4ca81487385c5f490ad276cd2af3a4.npy +03001627-4b1e09314ecc02d53c8d0fdfb1cc2535.npy +03691459-fc6066741f5b60e5280e0c1e89a63998.npy +03991062-29a8f4b92a1702f6ba14bfd91a75020.npy +02691156-2cc1ff07bcb27de4f64801ad2940cdd5.npy +04256520-a7bab06221eb932e79c251b4a7838829.npy +03001627-58b1c10a6e1d67b3b0cf2e642b746bfb.npy +03001627-ffa6c1a509986a5676708f8dec712a28.npy +03691459-83cdedb3431e8d8a41c95631f0cd177d.npy +02691156-3fc5fb97d23b6bf111f78b196c636566.npy +04379243-8b2c3c73b624c3faf4b35f4029eb1ecf.npy +03642806-5b5247b13d5b21bdad2954b86711abbd.npy +02818832-20b7fd7affe7ef07c370aa5e215a8f19.npy +02691156-9e30fc9f2d9ae56e3ec83bd6bef75c92.npy +04090263-420822a543c50b05230a4d129580843a.npy +04090263-c755cce8095ceaff4b49cd65dfcc3a9a.npy +02942699-b27815a2bde54ad3ab3dfa44f5fab01.npy +02958343-15c785a7505992c3a9be8fd09fb14f4f.npy +03467517-ad6cab75780f3f10d57700c05b1862d8.npy +03001627-a66d78cbf3603e8bba9df3ea0397b1a6.npy +03001627-c97b5b80a24030ae70e99aac955544a0.npy +04401088-6ff995a8e9faa6e83e43be0b542efff8.npy +02691156-76f949c39923b0778f297017462c6cb0.npy +04379243-6365205d2324234fc8a1efeb4b91d393.npy +03624134-435cd82d4017a783dccb54aff8e9710f.npy +02958343-23e7ae83601f893b575116d39d0ffbba.npy +03636649-f56600b8cb2f94d64d8b0368afacc65.npy +04256520-557d878e747fa35db161f36d4e309050.npy +03001627-72669be1815b2bb81e4fe86c4ad3ec90.npy +03593526-f2cb6d5160ad3850ccc0a0f55f0bc5c2.npy +04530566-7abde2cf79febf6efe4db18443aaee4d.npy +02691156-fb62efc64c58d1e5e0d07a8ce78b9182.npy +02924116-4f9ace193131b8e34ac4f8ff2084698.npy +02992529-35a0dc407f3df8d27450656ae41f00c0.npy +03593526-9669911986797a4584d1421a33bba279.npy +02828884-447ad1f23f96171f8d9b3c3ef984857e.npy +03001627-def8af022dceee892acbf58c0b138e50.npy +02818832-4dbd37cb85686dea674ce64e4bf77aec.npy +03001627-fc5f813d499cfd84d540c52e6ddbbebc.npy +03928116-1d139c80e904584b4243f79fcf368f62.npy +03691459-95c24657d2ac0469a3cd3bc808c81de5.npy +03001627-e92063f7bf538df17eb00a494c61433f.npy +04256520-4fcaa3e642e153f3450621b513a975bb.npy +03928116-cddea83b86dde871205444155ae5c84d.npy +03001627-a0e9606288d3ac22b61d9ed7bbbb5b3f.npy +03790512-ba9a5f13dcd8312f543a79ca976efea2.npy +02871439-3ba1563f381785bc6739a7caa0c577bd.npy +03710193-81f30bae0a1474fff601d2ded3aef05a.npy +04379243-b4015b8800115683b3f10885d03d0fb6.npy +02828884-23672bcfaa06a86764ab399dbd3ef465.npy +02958343-7000274ad11a419715ed2279a90f8f38.npy +03001627-a13fa904e05d60f176e9713f57a5fcb6.npy +04379243-e608701de43f3edcc0f947750540fb22.npy +02691156-912219c657177b17774a720fca15e35b.npy +04379243-683ddfb4cf9c8f2883f21c04f5e0acd2.npy +03046257-9e1e652f6477ecc87b9aa4fb5234ab40.npy +04256520-5a95984eaab1d85dfebad4f49b26ec52.npy +04090263-481372303918c2b22c12168d5291219c.npy +02747177-9ea0965fc34131ba7b104108655459df.npy +02691156-5e29fd83e0494cd815796a932d10290d.npy +04530566-f269ef3a1c758432e8d6be23f236225a.npy +02691156-bf5d59729b0c0e336cec6e2299cb4a76.npy +04256520-4fa4da6b966578cbe78a749ef6aadd72.npy +02691156-7317dec9c1cd67a815ce9e432a3a77b8.npy +02828884-2edc5c32e3ca7242aa6d4fa3e14dc1ab.npy +02691156-b3a59a941500e76535592b447835a16e.npy +04090263-5605d839bc4fee8d51b9e8cbda863b2.npy +03636649-b15485a55d855bf980936c51aa7ffcf5.npy +04379243-77f54df25e2d1bf99a1735fdc80135be.npy +03593526-c072c3656e9022977af7743c26a5495d.npy +03593526-49943fa341bd0fc86bc258c0f0234be0.npy +03691459-60d58e77382f081a69d22ff82177f51b.npy +02958343-d6e27c6523a3f2b58b8cd97e9d1c6a86.npy +04401088-6e183cdeba6b83b3805062aaa3bb7665.npy +02933112-77d1cf70e480af7e6a400d4015c42de.npy +03991062-9307ad32b595cd82cb2a965e75be701c.npy +03467517-9fb36e3b793183268853b066b4c501fc.npy +02828884-98af453dfb3b2284cb2a965e75be701c.npy +02958343-b8de49dd963c0669afe1d4530f4c6e24.npy +04379243-e79b8e7272ea19ca2112c05ea370d321.npy +02828884-81df1fcd6e2eec15f231d3622caa1150.npy +03001627-ec41d22862df4aa7eca29403b7226aa1.npy +02958343-625861912ac0d62651a95aaa6caba1d3.npy +03991062-415cae243e110f5cf155d75bbf62b80.npy +03325088-af09dbd4880d1fc8b362845c6edb57fc.npy +02933112-1b3d4f2291545e472dc6c96daf8fd5ea.npy +04530566-d0aa1202f01227f7b9528bf167ff877e.npy +04379243-9c2fb771ec6073b37ff6ace05b36a5.npy +04090263-7d7a915cefca95471db44ede0efdfd5d.npy +03046257-ae8042e2ded0cf01b17743c18fb63dc.npy +03636649-d42435906e79e4131de8e551fc6cf2b0.npy +03691459-570321d63f5fcb9391666edbc97a985a.npy +03001627-124117cdec71699850c2ec40da48fd9d.npy +02933112-8589e65944de365351c41225db8e334.npy +03325088-c1c670ecd6f00497c4cbb2ffd574f216.npy +03636649-574e0de3cea53dd472b623d6378b1581.npy +02691156-c54ca35ef1df558850ea677bbfebf3fb.npy +03636649-390bc0018f132788fcb8d8c6d4df8143.npy +04379243-f97cf997df0945fa1e09e4a1b10c649e.npy +03593526-d278b42591a08a1555f46d55537192b6.npy +04090263-e32501e54d05abf4f1b2b421ee7abb94.npy +04090263-c4eff07f05998965c79f92df566f8c6b.npy +02828884-10cfa696ba2259ccbbba142d6df53ce.npy +02958343-662cd6478fa3dd482d7d789814cae761.npy +03928116-c327cc501312d1bab9492d4f3d8bee7c.npy +03991062-38ea4739b92f125c81a172d69c52a28a.npy +03001627-3af90da238ac4ddbf91663a74ccd2338.npy +02808440-e78f7e89878402513af30a3946d92feb.npy +03001627-97b3a1b718278c09bababe11fcea8796.npy +04379243-802287d31c1f5c5ba4ee05a5737b7178.npy +03467517-52ecf1d8e279c1bb1f8d5edb17ddb332.npy +03636649-ec782fd2f4825158f24dd57a3f1f3b51.npy +03691459-cefdbfba01e3128920363e2561dd589a.npy +03046257-a67f72b0df7d9574b3c42e318f3affc.npy +03001627-d3a958aa302f198b938da3ea2c9e0e4f.npy +03624134-b80c5d63962c04b41395331ebe4786cd.npy +02876657-99d595bf3ac08bace13f76b539e1d69a.npy +03325088-fbe2cc8e19ad7a13b362845c6edb57fc.npy +03046257-e92cdca0cd98e908c3795daea94ab3a9.npy +04379243-339f5b3610ea836682f29b648e624c33.npy +03593526-2ff5347d6ee079855337cdc4b758988c.npy +02958343-36bc228a8722bf27473f10e6caaeca56.npy +03001627-c47e364fbc29803b2c0eb4a518e123ac.npy +02958343-7b2ad420c7829e881cae32f43c09c982.npy +03691459-4ded23cf84c993e9df3c63f2cd487888.npy +03001627-329c2234d134dc89492d9da2668ec34c.npy +02924116-557073f60379b9c852470de2774d6099.npy +04090263-b8828cd2b6bba8989091900cc7eb1968.npy +04530566-234541314abebbd02783b84b5d2d6e46.npy +04379243-6a8f125c174c07a57b11ae648ea92233.npy +03001627-8ab6783b1dfbf3a8a5d9ad16964840ab.npy +04379243-e59fa20a6988b93e29e4b5aa807bb4e7.npy +04090263-7eb5fbc480326d64f02ee453ff283e26.npy +02828884-eb038519c5ba87b663b2acb037dfbcde.npy +04090263-36083138334c7981d735fa1ab17311ec.npy +04468005-ee396a4a5fac385f1183ae1f57465c4f.npy +03636649-636d72f06ebabbdf9e8cd846ef13776.npy +04256520-1f438263a82a1b8919fb4103277a6b93.npy +04090263-357f37fd725c0fc116814c0baffb6c9c.npy +04090263-b942751009dacded735fa1ab17311ec.npy +03928116-df61cf8ba982c0f29a9d23378ae33f35.npy +04090263-b20d634c826cacc3b1ba4c891c81b80a.npy +03636649-47a7bbd995c37d3d4aeb986669a16017.npy +02747177-5a947a76bf8f29035b17dbcbc75d58df.npy +03001627-3981642f57a689276ef2faffa907bc32.npy +04379243-d582887570d2c1c2d7e17ccda34f6b0c.npy +02933112-e18f47b52ff3aa2452174f43a416bc6f.npy +02933112-2b9b2ece245dffbaaa11adad6b2a69c.npy +04379243-dd2c3ff28a34556a47839bae1bc65257.npy +02924116-3553a35ebb586c10550f48125b5f584e.npy +02958343-ec0555ccba700387b45e6d6d9af21f30.npy +02992529-5a65ef748eb3a3d1ec475b573e4d1a38.npy +04256520-d50233ec66ac6ee2b70eac6546e93fd.npy +02958343-63f9acc425dba89d68c45fd057f7db12.npy +03001627-1cf77ee00faa6de7fa6450cce25dc4cb.npy +04090263-48bddbcdd626298540385522d1beeb20.npy +03001627-89208a619341d9fdb8c516ed5c4ce32.npy +04256520-74490c45305da48a2b3e9b6eb52d35df.npy +03636649-3b15a4be5e248d114cc30865d6337b9c.npy +03001627-ff9915c51ece4848cfc689934e433906.npy +02958343-b70d970f8020c25dd141480e2c154d3.npy +04530566-9c2c87ceba2a465f86b234e3f0128df2.npy +04379243-506ad995cecb082f54e1b6f41fdd78a.npy +04256520-7b9f151735391e7a14513156cf2b8d0d.npy +03991062-ed1d39c6592739f72652f4081ec5a77.npy +04379243-f7c25526cd3740cb52e2d18963a75b4d.npy +03211117-dfde382270f1d69a28010a96423245ae.npy +04379243-57364a6bcfdd730f166ddaef2c2c61ae.npy +04460130-e5819354e7ddc4a2545370dbbc80d144.npy +04256520-bfd337ddffdd91b4190a91fd9a6f7d55.npy +03001627-544aeccfe77f230a1cf10a36e3d0884.npy +03797390-4815b8a6406494662a96924bce6ef687.npy +04256520-146ad9d78f06f1f0b246c4171f2c393b.npy +03001627-59704fd0f662d7b4da986730050de1e8.npy +02691156-7bdf4816b61c0e1748766ee3c52f8ba4.npy +02808440-7ecbb98e2bb428c85721e2cc9a13e7cc.npy +04379243-bee3ff1926f3068cf09df371fae9d63d.npy +04090263-e8a019a32c42bca7bc6e84bc30e573cd.npy +02691156-68303a007a6c8ab02d6ff44f79e93a89.npy +04401088-69b74f6c66dc2adf5a627be422951096.npy +02691156-c5d748c352d8eeeb3d4e343a1ac21b93.npy +04090263-bb1dff989d7b563124fcd7bb489fc827.npy +04530566-e3a49772e431fa6a4911559f9f073abb.npy +02691156-2cf6583a74dc4d1e373ed874fe97420b.npy +02958343-b8599e22b152b96e55e3ad998a1ecb4.npy +03948459-36af281561491d77ea768093544ea6d8.npy +02958343-83731bad1b7d6ec531fde3a1e19a4940.npy +04379243-a6c192247329a32e6a19b0779ac03754.npy +04379243-40afcc31186c0b452d19175e7d19b7cb.npy +03691459-8d7d7dbf8f0c0f7673e1b2d018c0512.npy +02691156-420f3bb771e8e75ed878249aca2571f.npy +03642806-b5f6fd84a3f44ddb1aa47689117a61e1.npy +03636649-90c323c4d6288aaabb40b038e5e0b7f0.npy +02871439-29b66fc9db2f1558e0e89fd83955713c.npy +03636649-1b957f2c258ed744b3c42e318f3affc.npy +03001627-30beaf15d2d2beb1febad4f49b26ec52.npy +02691156-2e0c7d77c0b74e87c1ccec171a275967.npy +02691156-c1fd4eb9f911851f4352ea917328a5b.npy +02958343-f3dc4ff3cecb4eaf8ee29572addd5275.npy +02924116-5bb2d2fdaaecc6d2542f64e03384ee7b.npy +02828884-2af98dcf936576b155f28299c0ff52b7.npy +03636649-e1916a904163748e8cc413950b617e8f.npy +02801938-b02c92fb423f3251a6a37f69f7f8f4c7.npy +02871439-fe025a756926fd9620192a5319e3e2e4.npy +02958343-f850f5ddc42bdc3a117db354abf0d721.npy +04379243-da0badcc10ee1a4aea966ed2fa6fd5c0.npy +04530566-e364eac9ec762c54de203ef6842ee61.npy +04379243-da84e4621c255691490ad276cd2af3a4.npy +02828884-32bd91d61ad0824e2729c156998d6717.npy +03467517-78704c7d77e34b803283ea69e022bdc8.npy +04256520-72252b1486f22ce3490e0c0c00192ce3.npy +02808440-19e3356bdc1600e48356c7b0827e2e54.npy +03001627-31e59dcaa15f2599a52abcb0c06a3598.npy +03046257-24841121c7d090d72d2d2896f4b277fc.npy +04554684-677a00ae2e3f7a2145ca70e41d71c65d.npy +04090263-242a543a598c3d7a657e1a784010b9cf.npy +03211117-2fc578c8daf35023ef641b9022b66b97.npy +04256520-7527c6db4e52d511db01c957364e77d0.npy +02691156-7e1d4583f70c8583431589819e5ca60c.npy +03593526-ae81dc3d42c59e8c500158c23c4c5a8e.npy +03211117-ed9c1a4011d870c258d40d577ba17fc6.npy +03636649-eedd40c0191a90a5cbde89e0c48a01bf.npy +02691156-f96426f2392abb1d8d58389384d9812e.npy +02691156-19fc1b9ff4b6456f1232236eecec447b.npy +04379243-70f1b5f74faa9bda664b3b9b23ddfcbc.npy +02691156-8855c5531c093275146f724acb952fba.npy +04379243-3b3b35ab4412c3263edd525d249a1362.npy +03691459-8705c20e8dec94539b0037ed0d57b3ef.npy +03928116-c43e1a3537d56f439a957a60b2bcc479.npy +04256520-df7cced6f0e5e65c26e55d59015dabc6.npy +04379243-1096b4a30bd7717c4733824eae5cd9ae.npy +04530566-35960e065788a31b123c06ea72522927.npy +02818832-4abe567bf6f1e2eee213bbda0587ff6e.npy +04379243-19c0e93cdca6433fb8d33c22fd35264c.npy +03001627-b967ac98b1cbd8fe36a7a71199dc2cb3.npy +02691156-1914552110aa5a61c1006ed55bc1a3fc.npy +03001627-d10ed00430a61909793b1150bb246dc0.npy +04379243-cde43e92674a66f46f3f02fb4d0927eb.npy +03928116-d2eb696f6bf5569ee6abebbc3abab4cb.npy +02828884-8c387d5e8ca71237d2b12aa6a0f050b3.npy +04379243-d20e0f359f37f7f5648b060eabbed82f.npy +03593526-2872c4b8e2f86201b7d0f3d89bbac230.npy +02747177-c0951455fe667165599c7cf847d431a7.npy +02933112-7b98e7b25bb83413c59350d819542ec7.npy +04379243-5a2f605200b4e4d5eb6d17f913d54c76.npy +04256520-c029d82ea1d3af4e19fb4103277a6b93.npy +04530566-beacf34e9b0c0597894b951d14f8e56.npy +02828884-ecef040a94ab9e59928f4521e8b299ce.npy +04256520-e3f5405a4843343e91fa1c643766450d.npy +04379243-4c5ac5335e50ba35b385698e6487d3bb.npy +04379243-14c66bb1292a764f7e7c9f487eee4fdb.npy +04379243-6a56d0f447d477e12de0bc4fc4d02dd6.npy +03001627-c400749eaa4d10871a782a4379556c7.npy +03001627-3ebb8f29a7c44776f51f77a6d7299806.npy +03636649-833baf068fb6225c99570bac758be6a4.npy +02992529-a56fa90572f9e23db30cf593b4a23b0d.npy +02958343-d7a09b2936b3d3e7e97c6bb243ef67d.npy +02933112-1a51237c9515ad0a4da5feafe6f1c8fc.npy +02958343-704e60e6e5be85e1f500cc506a763c18.npy +03001627-3d04cb63d2b1873fcf0dfe1797286ae.npy +02691156-9469590435736800b87697d3904b168b.npy +04330267-510d5da107f80051e1d0950dd1aa903d.npy +03085013-72d9a4452f6d58b5a0eb5a85db887292.npy +02958343-eb5f04670263d8bd075955b404dedb5.npy +03001627-96fb86091881d54724894811dd3e6d32.npy +02958343-db1e6a78a84615b83c9d2d3d4dc0edb0.npy +03001627-1986eeb9bb594bf9a6d7a9f3c5f7bb41.npy +04256520-294afbd7a0e90ba9490ad276cd2af3a4.npy +03001627-7f2f8dd929421cd130e6a28391d443c5.npy +03691459-96a3c3653c343db6ba8a1820ecdbe891.npy +03636649-32bf66766c1f33983466f97f37dccbde.npy +02958343-5d0e79c02907bb8f5cde8c99e4b182f9.npy +04379243-384bf53e12744e2019fb4103277a6b93.npy +02924116-550dd89fd258d839f01129d246a5d1a5.npy +04530566-a85ef79371cb1edb52fd6b83c5929135.npy +02691156-e3f68fbd5d1629e238976998fb731b88.npy +04379243-857ae7eeae1508e9b0957d845ac33749.npy +03636649-22a0864cef495771fcb8d8c6d4df8143.npy +02992529-bf0f0ba650108d03cf144715a1bb5595.npy +03325088-9a4a7de766558e343321831d2245cf06.npy +04090263-3c33a0754d1c6a71b9a4a5375572bf62.npy +03467517-cb99963122f01a92e8bcbdd9e5145d74.npy +03001627-80c1f7ee486e7b5aa61649b05d63e9bb.npy +02958343-3093f587c5660c7a473f10e6caaeca56.npy +03325088-3d9c646e912c7723af0b75abe6dfe88a.npy +02691156-2d4a57a467307d675e9e2656aff7dd5b.npy +04256520-173d2bf95fb2e6353a9b2e04441ce376.npy +02958343-cb5fd4e2c29b9193a134736201a79843.npy +03001627-547ad86927566ed0f9111ef49c078dbe.npy +03211117-ffd0fd5aa21b9c8fb441e189e5a85c02.npy +04379243-d455b490f08607a57c6de7e52b00ebab.npy +04379243-c667df83b0e77f96770db120e736ddf.npy +03636649-d5480fd1d05e8962d42b9650f19dd425.npy +04460130-7344d6188932b2de72f6aef300d24d64.npy +04090263-e0c6be7a5b560f3af13eed41b64dddca.npy +02992529-2cbfb354e5dd731dfd6c7e3f0d9c56c1.npy +04379243-97b3dfb3af4487b2b7d2794d2db4b0e7.npy +03636649-14c84c76c927fb282cd2160e449d45ae.npy +04530566-7b7847ccb4f15fa9b1bb46d2556ba67d.npy +04530566-943567584893fd5218591932caa46ff6.npy +03001627-d283b1073ceae03f35836c728d324152.npy +02691156-f62ad267cdd1a00a34b1f3550986bd42.npy +03001627-9a8e84b82ca17e3f2f21cf17406f1f25.npy +04074963-a67e5a678c54d757db8fa1712f9ee93.npy +03691459-67e18c3be264e30b636095aedba53117.npy +03467517-238f738a7012b713e909a939d5488b76.npy +02691156-5c72cc06d79edd1cbbf3143b1cb6076a.npy +04256520-87ab409c03acea4af994e2a430ba61bf.npy +03513137-aa51f885208208375094ac652b5174eb.npy +03928116-8b533074327be24b776ccba7ee1e3e9e.npy +04530566-ca2e4bd483c006a5c9f3294669fff77d.npy +03001627-8cc42bd1f681f126d0176f9a144100cd.npy +04090263-4acda16abeddc1a24d0af51460733e47.npy +02828884-564474f25a4400c5dc20930e6fc85682.npy +02933112-63465f2647384da7cf44224546cb0306.npy +04379243-c900e6f4dfefafbae06f10e4878a855d.npy +02828884-9ef2f740d6dc7cec8d01d636ec229b2.npy +02924116-c479358dcb0168909df4e878bc750cac.npy +03948459-9a1208d777d287bbaf2c6c19cc41708a.npy +02933112-433b0fe363861867b25e7c54df7809b7.npy +02933112-cd3c926cf4ae4564a80ff03f6dc10926.npy +03207941-53ad4a901e8b0dd9121859336e292a5d.npy +04256520-1e71489bb315efa0eea222b336f100f0.npy +02828884-2cb61abc0c2663ae8f0add668496d7a1.npy +04256520-f76d50f900b034af19fb4103277a6b93.npy +03691459-9de56b4a4a9eb3a4cd4e2b9cb7f670fc.npy +04256520-63d67bb924a00203fff16555386d173d.npy +02958343-a6842a04cef3e5ce69a949ac99a843c4.npy +03691459-394302e20816d0fa07828ee23920679.npy +04401088-3bd6626a05b4f79bcf17364e7927abd.npy +02828884-4be9494c9b476dbbd201085e80edb26a.npy +04256520-41c838f99b46093fdb5f60e9c5fe6c8e.npy +03928116-d3a9b80fd68429d7f2dfae6f0c6544.npy +03636649-bf4b1a3597373ac0664b3b9b23ddfcbc.npy +04401088-2266b891f080ad7eeb2a3da43bd37462.npy +03001627-d30ecbe6cbe364e5c8687ff9b0b4e4ac.npy +03001627-c80c0b8107583898c1956375af82917f.npy +04530566-7e0d128b6c8ce8b59e5ca238b1551011.npy +03001627-2c6fa3007e79013cc3cf9ae716575390.npy +04379243-8c10cd9e5b4d589299ef6b0e70be718.npy +02691156-647e76622faa22b626b85a24a73a298a.npy +02691156-23c8d6c73cf78ab23cf128905a10d59d.npy +04004475-41e1eca9857f0ed1f7cd74b993fa73e3.npy +04256520-ee57ae3e04b1930aa6bb70ffc9e4e52.npy +02958343-413fcc9afd53136a16abce8cb03e7794.npy +04379243-e428b7d6634444a910bed4209a0dd8ed.npy +03001627-4602fbcc465603882aca5d156344f8d3.npy +02747177-2ac7a4d88dfedcfef155d75bbf62b80.npy +03337140-149a105979cad722c1467c54b9e09ce5.npy +04379243-f78e16c1dbc4dbd31349824369d952b3.npy +04379243-b5529f6f5679d705c8b2ff62b26cb42.npy +02933112-adb7c7229f4871c2c59350d819542ec7.npy +02828884-9920a0a8393494c59ec4bb690ca24962.npy +03642806-a4b410734514306ac401e233323032d6.npy +03691459-8d698e60c436d75cf398d0c5832df00e.npy +03001627-b7e01301bb1eef41f92f3e7bff4c4ab0.npy +02876657-e824b049f16b29f19ab27ff78a8ea481.npy +02773838-f5108ede5ca11f041f6736765dee4fa9.npy +03467517-ff3b5763b3dedda3241d076ab53023c1.npy +04379243-b23b29f4b08cb2e7b65b71636c46ae49.npy +02954340-d7de36db04c61722a52821bf1aa3b19a.npy +03001627-beccd4a6031f6a5a3eaabea23fed5ec2.npy +02958343-e9bccdd7a52f13329b3f352e6fa9112e.npy +04379243-f26d68c69a06b95ac440f8a1412258d1.npy +04530566-a668bb9ccffe8cb627ca60ff81c74bf5.npy +03001627-3334213d3f378a7eacac9cf65380267d.npy +02828884-327dcb9a47911686815bd25a546c8489.npy +02876657-7d41c6018862dc419d231837a704886d.npy +02691156-aafb38ca8d8f27de350ef9fb5390c42a.npy +02808440-f88e093eff5adc09ccd0340812259a39.npy +03001627-7348ec0e16e99fe1ad484915511ccff6.npy +03636649-ef4478daba21f2d49244b68aadec703.npy +02691156-ce682d7a2bbf77b6fc4b92d3d335214a.npy +02924116-8ae47b15b7cdbb4ad4bb8b9a2c4a2dc7.npy +03636649-a16fe5e25c99ee73172986dc05e3b9d1.npy +03001627-276932e7bf229d37c8ad93869b52d215.npy +03991062-c63b1b8785020e1e340ded9bd2d6948f.npy +03948459-506a25c906db09ca1bd872e105bb611f.npy +03001627-d8e2e2a923b372731cf97e154cc62f43.npy +04530566-47ab7cf5568066fc86f968b3508ebacf.npy +03593526-6d652a95363bb682b692b490d9871ff1.npy +03001627-7948f2715d32c813fd60059ad8523f1a.npy +04379243-c356393b27c3fbca34ee3fb22432c207.npy +02924116-f518e29070ab89c541cefd10ce5d6cc0.npy +04074963-226078581cd4efd755c5278938766a05.npy +03467517-4e4d180e78d8b52a93f0194265a9746c.npy +04256520-ef511c56878424e4a6380f3fc7269ff.npy +02958343-287f4c8f87099957473f10e6caaeca56.npy +04379243-e3ade6122be60b39742cd3471ca7caf4.npy +04379243-7acabc265397e604593ebeeedbff73b.npy +04256520-debcadc4067158674ab1b242068f86fb.npy +02691156-4031ee8a4631762c9566f663623859aa.npy +02933112-8382308b895aa93286d53ab0fe94e911.npy +02958343-2f13fc44e7e06816a134736201a79843.npy +04530566-d262a9cfdeca256e228ca1071b304db.npy +04090263-5eaad35703c992f71092539e96a339ed.npy +02828884-31af3758c10b5b1274f1cdda9579594c.npy +02691156-f186d2998485c6ed5e9e2656aff7dd5b.npy +02933112-1074bdcb3c2032fe0f3f8b6e1796773.npy +02808440-df67f38c55e4dd0b3321831d2245cf06.npy +03991062-7a971531ff72a48d5706d1c54190f27a.npy +04379243-10f0753ae756fe489c0c9824ccd078be.npy +03624134-da94bafd8b3ea6a6a6e0c365eca0e86d.npy +03001627-31f34cbd9385944181faebbdea6bd9be.npy +03790512-59a2f0fd2b81bb273b6d7f17f2b61d2d.npy +03001627-7e298a6653f0febd1f30b807ae39b61d.npy +03691459-4c68944b2b8105d11a2f7b80918eee9d.npy +03001627-f69b87648aa2c6f52ef787234c3ff353.npy +02808440-868517dfb1753d901d91d3160643d7d9.npy +04530566-8d53d8f4cacbff77853339423b00f029.npy +03001627-3ce9a0301f36ecf4cb32c5fb502d0e18.npy +03337140-b35f8b3cf70ec503bb31aa2e1985084.npy +03710193-19c6003e0b37b66675b7cfd132afcda6.npy +03211117-2d0138ffe3eb25b9e23244d89a2e66d6.npy +04379243-462c1b0c6f14f168c3bd24f986301745.npy +03001627-8bce3b7b7f0f48ad28a1548e344f0e2e.npy +04379243-3c9a23693b76e2f8acb16624e184454c.npy +04379243-5bccf52849ce93b5f4d0ace72e0fac85.npy +02691156-8938ab05c9dd830cb422638f4c34a0ac.npy +03797390-b98fa11a567f644344b25d683fe71de.npy +04256520-188505b2fc90ffad780bc2708a85ba9a.npy +04256520-2b73510e4eb3d8ca87b66c61c1f7b8e4.npy +03797390-127944b6dabee1c9e20e92c5b8147e4a.npy +03001627-680b3add007725792feb9fdea8e07927.npy +04379243-15676a89e39262ea852bb95bccedfda9.npy +02958343-7a12f058a0474559a7fd25564c2e888e.npy +04256520-8112da888f66bbf3c1a52e5a697bb944.npy +04401088-db1f83761a7a19f6d0c7ebb68662b4e5.npy +02958343-a2d1b78e03f3cc39d1e95557cb698cdf.npy +02691156-e8bd07a978ac82baef40e4c1c2686cd3.npy +03938244-80326c3f2dff14412257a9702919f3a.npy +03001627-534c5f9ea1ae94b54644491844ed9566.npy +02958343-9648aaf755e6556e2a9eb0f146e94477.npy +04379243-91530c95f442dd71793b6229a2639a1c.npy +02958343-ca24e69261dadc94a9fe1734a6086750.npy +04460130-15cc3d9020384e8d6e09a8e31c7575c5.npy +03636649-b37e07ac31fa4f311735ea0e092a805a.npy +02933112-aa1077aff8bd9e44d8f27b2e727c3511.npy +02691156-54c13e95f07492a9e10e757961deca98.npy +02933112-648bdbefbe72c6e596d5fa1ee6ada8d1.npy +04256520-c8b6897dac50a2c3eaf288f952624966.npy +02691156-f7c2edc1beeedd006e68e46a69a2d96d.npy +03211117-76b4b83212ffcbe034af0ed44f2ab2fe.npy +02691156-d2e2e23f5be557e2d1ab3b031c100cb1.npy +02691156-86a5bdbd8c0c70eea7de26672c5fab85.npy +02958343-ea3561150f4f2790253c03b7df20edd5.npy +04379243-a269c3b2b456e61af4e73c80c5eb704f.npy +03928116-2f6fb505856129f640e11a38b418d644.npy +03001627-1e40fef11894c4b9ce4f274577283b16.npy +03001627-11e6e58798ae5be83e5b5dbd84cdd0f8.npy +02691156-d8e8540acddacf98c1006ed55bc1a3fc.npy +04256520-660cad84e71a5f67a74931688d634d2.npy +04379243-1acc3dae512b56b01f8b303c0da5108d.npy +03001627-4552ab193b8566acea343d0d02e4d3bf.npy +02691156-af55f398af2373aa18b14db3b83de9ff.npy +04090263-dbbb9a848b8a6697e1f2a1daf140ac9f.npy +04379243-67d97102f9c54cc95512673aa47c7e3d.npy +02992529-7772938405ac56c1b6d41c42f7ade8c8.npy +02958343-effb7322805482465740f5f1a3b45938.npy +03691459-dadb71e216b54f701c5d4854f1aaed94.npy +03325088-d1383f1ba0a348726f893b5bc716a3fa.npy +02828884-15cfe15285425b67bc96b70d50d39da4.npy +03636649-1475fe59961fc726f096eadaad23f93d.npy +02691156-6b15289a71312a5af8ea21a9397429b9.npy +02958343-e8745e2d659061ee4a15d27f5dbfc7ba.npy +04379243-db89cf8ec0ae8e10f42e033ed19d598b.npy +04379243-77fd14f1a7f2d27ec3bd24f986301745.npy +04379243-649cea3b17ffb31bfebad4f49b26ec52.npy +03001627-4178e43e2756f1d0af7a8f97983e7906.npy +02876657-2efb9eef0ed832a89769b3a50399d097.npy +04379243-81f049a3410c8d295833b7f8c91b5b48.npy +04468005-8714037a49f313b12e97c1a558edd2de.npy +04401088-39359aaddcc4b761b0a79e28606cb167.npy +03001627-5ce636f716f8f11e601104cd2d998272.npy +03467517-715d17d76a80c54bcc34b900bb2492e.npy +04530566-2f682d31b26398cc2218383c174cbd7c.npy +02958343-8df7178ab0f02bd7a795ba688a0bfdb4.npy +03001627-e6c900568268acf735836c728d324152.npy +03001627-a2eb6e2ab073dfb2e0340d230bdc7ee7.npy +04379243-9fe655d18bce7ede23fe3501bb9e7193.npy +03001627-e9e224bc0a0787d8320f10afdfbaa18.npy +03001627-b3c503ee276ed0a75298386582afecd3.npy +04379243-91df49ec00f2c5ce73f1ca2ca101a20d.npy +04256520-73111c5505d7b5eae3db80a3cacc6e3.npy +03001627-3aaa59b19eebcb5f41552c6ecbda964b.npy +03636649-89b168160388c29da996f5a90dae9cac.npy +04401088-4b91c9711ca991768a57ed2dc0905847.npy +02958343-1f0d149b320aa4faafe1d4530f4c6e24.npy +02958343-30e971ea6fceac68f5cb3ca022cf045c.npy +04379243-1028a9cbaa7a333230bbd4cddd04c77b.npy +04530566-f6288a9297948fdc67383adf153b22c5.npy +02828884-323f0787810ef9a285a030bdc6cb9884.npy +04379243-a99a74777f6aacf2489e5619471f9f53.npy +03001627-2320dab001320f69f91663a74ccd2338.npy +04379243-fc66d797cc6b4bb672a7060b4557c0e.npy +04379243-429d850ac1621fc176dc93c8128c2c20.npy +04256520-2c6dcb7184bfed32599dcc439b161a52.npy +03467517-33da9c54f43be3e17693a84bff425e3.npy +03593526-21efadc7372648164b3c42e318f3affc.npy +02691156-4c5b8babafbb7b5f937ae00fead8910d.npy +02691156-36d2cda57906072c1e08b6601b6fd998.npy +03691459-80000b93ffb0ab8ae47833b310955a9f.npy +02691156-ac0d1320328f5636b819f3a4f3895504.npy +02958343-752d240eb33f328cbf95baecbc060806.npy +02933112-d6edc4c02e38c7dda5737ca21e62ad39.npy +04090263-fb4969c29b155f2e9c8bfc08f511409b.npy +04256520-c06d35db226f47d4de03ab2a27ba7531.npy +04379243-48af84a5600ad5bc19fb4103277a6b93.npy +03001627-a1240606049c440edbf3c13c5c0e828e.npy +03636649-ba95511c0a79f2fc73b8ea30c1700f67.npy +02958343-4db6c644912bfbb3e0445fc6d980dd5c.npy +04530566-90bb60a421727973e3852f9948e4ef35.npy +03001627-8f4c2a7243b571f3b21450114b9ae3a.npy +04530566-eb00c722894c3d70c40386bdd72f9a0.npy +04530566-29a131678dfba5339a6e43b878d5b335.npy +04530566-9b90b9cbd9577d842b72b4a851b36ab9.npy +04379243-194b279c7e892a2d15fa8082e5524f79.npy +03001627-4138f85b00b53185dc3653f8341633a.npy +02747177-f53492ed7a071e13cb2a965e75be701c.npy +03691459-92b3275e46a63fce1ccf3280eab717b.npy +04530566-84097ba1b35f844ceb2c303a0e0d287b.npy +04379243-a767059df7040b5fbe127423452ccc7b.npy +02924116-775c6216da8ba981cb2ecbd32dc2119e.npy +03001627-a544d05ee3bf362d27e1ddec710c515b.npy +04379243-efa1b72ece626ac6e3989b96851850ed.npy +02691156-d96f2b6990d0d79e247412be0e58d7d4.npy +04379243-21d160eff925f48055f46d55537192b6.npy +03001627-cb867c64ea2ecb408043364ed41c1a79.npy +03001627-49d6f3affe205cc4b04cb542e2c50eb4.npy +04379243-233efac14ec7189e809222e4341a7d65.npy +02958343-48723bca810f80cf7c84d27684eb86f7.npy +04401088-7617e95211fc3ba0e02ee35b95994e2a.npy +02933112-809d5384f84d55273a11565e5be9cf53.npy +02828884-f35697e0ec1d35dd357ea07594f25728.npy +04379243-d97e2a50640387adf90c06a14471bc6.npy +03001627-966aaab0434c950cd7f7a4c4609b0913.npy +03046257-8fc855cef77177e8c598d38a6a69ad2.npy +04090263-76eabf417f880fbaf0cefc099c5b436c.npy +04401088-54d5d64e0d3b0f95952ef623ec48449b.npy +03001627-edb86d102237488ce8f8c11a24c52ebb.npy +03001627-89dba482df6fd02732e2044f695909a.npy +02958343-2928f77d711bf46eaa69dfdc5532bb13.npy +02691156-3033e5dbbff674a55d3bbd70fc7759b7.npy +02958343-3d2fbd9bfdfe08573a93df79ef2b80ef.npy +02818832-ec8298e0eb6fe81aeb3829c3063c353c.npy +03337140-1d5d3b178c89b282492d9da2668ec34c.npy +03467517-a92cd0b5d559075daa9518d76daaca23.npy +04256520-28cb2ca084164fc15da92fb9f7555d73.npy +02691156-4044d5954ef85af8279326882e8430cb.npy +02876657-935b737dca29fbf4ef026123226f5519.npy +03691459-46d03a4d9dec071d1047e2dc3fdce97a.npy +04004475-eecd888b440831bffce3743f4e2437fe.npy +04090263-d5322c4c21c1d16ceff31787d7394ead.npy +02942699-2fc6168fba3ef6953ada8db96f6d95a3.npy +03001627-c1b312919af633f8f51f77a6d7299806.npy +04401088-c960421b8c637137fb4952f06d5e75bd.npy +04090263-6d2761d9749fb354167e6355c6e5b5ad.npy +03636649-13e4f5f06cb42211fcb8d8c6d4df8143.npy +02876657-9f50b2ddbcc2141cfa20324e30e0bf40.npy +04379243-d21405eeeebe4085d42ec7e303174a87.npy +02691156-aa3a801045f6fea9afd51f67d3985e6e.npy +03211117-75ba7901816b273fe24979df4ff99c50.npy +04256520-aa8b70ecfdd237bbf91663a74ccd2338.npy +04379243-e29252434d37520ff008d8a3590fb522.npy +03211117-3ca0f34c03ddd760234c2f2e8f2fe6da.npy +03636649-8508808961d5a0b2b1f2a89349f43b2.npy +02691156-1304ef60fe9793f685e0a2007a11e92f.npy +04256520-7db3c05e67e9b847393b0262b4e8b707.npy +04256520-ff2dbafa8d66856419fb4103277a6b93.npy +04554684-3cafaabfd4924ee47e5b110192149385.npy +03001627-5490efbdadce792f524f4eb395a8604.npy +03001627-7289d67cc454e7215790e40d47191474.npy +04379243-2ca883ba6a9dc6f68985be89a0ee21a.npy +03001627-e7ae6edc3fc6c92ac423490470c47d79.npy +03001627-432138c30378b2a8e1b6c3a3e12d929a.npy +04256520-5b693b3edfb323d0febad4f49b26ec52.npy +03691459-e34b3e11083387b9c9d5b08933b9e0c1.npy +04256520-7669de4a8474b6f4b53857b83094d3a9.npy +02876657-8aeb546f0381df6e97b6ee740552021c.npy +04379243-2ad1a20d43c6106f71b1188ea929234b.npy +04379243-8e8b8a01fc4abd88fc4a4d8514534de1.npy +03636649-2632d9a8462774cd81255bc546ed0fe3.npy +03636649-8006e3cb3ba934a05b977412e02c412c.npy +04256520-5cc378efd61f0333afd8078191062c7f.npy +03001627-3be2c90d1c2730fa14659d605ff53c6f.npy +03001627-24cd35785c38c6ccbdf89940ba47dea.npy +03642806-dd205f0f8bc78bae359d7b39cfebb287.npy +02958343-b5a25bcf42cdfb15523270fc16562838.npy +03467517-58ef47d7e4f4ce9b2442fc1f96a68061.npy +04530566-44d1e432239591887b2cd6c1f3acedb0.npy +04530566-5b45a9913b90c67f8e2d64007fd7ea91.npy +03001627-c3a3d9cdaf29cf6597c8d78b9aede742.npy +02958343-a238facc26681bac8efc69f75162eba1.npy +03636649-a690290543a1b904cd5a7785cb8ad4.npy +03046257-7158637af55b7c51f51f77a6d7299806.npy +02828884-cd052cd64a9f956428baa2ac864e8e40.npy +03001627-6c25a321d75405aafdef1c01cbd4ae0c.npy +03642806-c012da029408fb8d498c10f665c444af.npy +03211117-ede70dc992195dc272e55f1aa85cc5f.npy +03001627-ea577a1e9dffe7b55096c0dd2594842a.npy +02924116-6875d86990f0e143c3326b0bcdf7d332.npy +04090263-1030525f8d49753e519f927f2bf92da9.npy +04256520-8f8aa68c8c6cc6b53dfad56d2a4eefcd.npy +03948459-e4b03ae84f8d11394c3466ee2269609a.npy +04379243-1557647df4c4d298f6e8f2cf4a97051f.npy +03001627-9c825b20d4e35eb595a6db6161d501d6.npy +02691156-35835c28f33d985fa18e0889038e4fb6.npy +03691459-6d5698eba0fbb1cb2a9eb0f146e94477.npy +03790512-aae0037cd1dd489b468bac13e007a6e9.npy +03001627-76fa373d984bd515504d5af97121b5f.npy +04256520-6f0f6571f173bd90f9883d2fd957d60f.npy +03001627-bbcdf9d0ecf02e7e9fce07ae6c046b8c.npy +04256520-3dd89f170133fbd7d609055a51359428.npy +04379243-ed66ef9698fef541b945039752747042.npy +03046257-4e4d010aea4d533756325576fb0d1968.npy +03593526-81cc70eb5ec9e3c75706d1c54190f27a.npy +02818832-eccc3a7a3a5785e8d359a99f94460600.npy +02958343-470fc68779da0f923d68b6d025852738.npy +02828884-87086d24c964f9524ee9546b7112f88f.npy +03046257-487f2bacddd58bc9f959a2da56ff43b4.npy +02933112-3aabe5c704cf7a6d1db624f8d6f26a7e.npy +03001627-a8a2f0865365b521c87106a609982130.npy +04379243-4302fa68485f0734776f723457d34a2e.npy +04256520-23eb95ad8124b45cc27ecf743c1aa320.npy +02691156-b4dbf6f6b0cc8ec5ce19d55bc5e6a406.npy +04090263-c6e6cf657ba3f2df4376957d2c85a4a.npy +02876657-ad33ed7da4ef1b1cca18d703b8006093.npy +03001627-63249ce6d12ee0bc7b20cb946bceb58f.npy +02958343-42134787c805fffe1ab9df4be75138d0.npy +02958343-e920afce255de6ee3781057335c8a2e8.npy +04379243-7bc45a32e5b7f14f7e1dc33a9d8d260a.npy +02871439-14e2cc3454ffcc65cd1d915262958e02.npy +02691156-88af6c30339602c2c87c199a35aa58d6.npy +04379243-450ca83285f0a0bff51f77a6d7299806.npy +02691156-b02aa659514366aa2c6868c67da0489.npy +02691156-7385f1416e93f1c14ba2821676102936.npy +03211117-cf7434589520c549e420fe49ae1a5a34.npy +02958343-7275ca45638f16041899a3ad18d10126.npy +04530566-d235d9f72448d9f82c1bf9a642a59d24.npy +04401088-dcc94b8d84b5093df47a365062723f15.npy +03691459-97f758c8d327d072871a975200291c6f.npy +04379243-6f86cce2bf8fa88821da01c0bdc324b2.npy +02958343-1688bcda878d3b18afe717997470b28d.npy +04379243-41b548aa6f4146fb1962281db2f162a0.npy +02828884-66af742be9a0c722b93fc2b66c6b86b6.npy +02828884-26f583c91e815e8fcb2a965e75be701c.npy +03001627-c04f515b688f9d97fff16555386d173d.npy +02691156-24fbe7a49fd786c5fb5c1b0f759e2bc1.npy +03001627-47ac4f73d91f8ff0c862eec8232fff1e.npy +02958343-bf37249fc8e16fd8f9a88cc63b910f3.npy +03325088-569dc8ef952c3e039bc6283fe73f66e1.npy +03691459-142f66a7bc5e119d18d385624fdfc6d0.npy +02958343-c8bc71dadbdaa890becf71e2e014ff6f.npy +03691459-b7b69bc187bfea4a8b1598dab950d979.npy +02747177-edcbeac5da0b42dd7936acbca381136f.npy +03211117-846b6c8cf241ce2648d13901d1f48e04.npy +03001627-ef7d9ace8098733b8e80abc614a52973.npy +02691156-d639c8d2f55982558b96ae1a0a8b84ec.npy +04379243-c18781f9d9d6f34a79368d1198f406e7.npy +04379243-6d3828602ec4b79232a1f4cd459cdfdd.npy +04256520-875b65ed8484c7908bd21f911d388ab2.npy +04379243-f643a64a4e38723f73c478529c40c4e6.npy +03691459-fcd642cc82a4417848db103415b9e9da.npy +02871439-55c822c909fe5df991b2b5632f598ef3.npy +02933112-21ae39cf6ba8557f4da5feafe6f1c8fc.npy +03710193-5fea323ff9baae9e8ee9863a6dff6d33.npy +04379243-59ef41df3ae8a4026c2e61baa2a8130.npy +03991062-b06b8ff170974a41bf01982c823d8b4d.npy +03938244-d212b1cf646b23f5fdad967a7c361c07.npy +02747177-d0811b88cf8db844375bc8943daa105.npy +04256520-41149ca3a44aff87707cdefe012d0353.npy +04256520-dd85decc87fd988c524446331aa4f326.npy +03001627-3af3096611c8eb363d658c402d71b967.npy +03001627-c7dcd3fdd4ccb7563dce8e6b691b2a29.npy +04379243-d81388de1add33d8e41c171730c26c4e.npy +03636649-2f02e4f875d651b3c066b9622c005c53.npy +04379243-e78e481200b9c01323720b60324690f9.npy +03337140-7d4abd821dfbc7dfcc786970133d7717.npy +02691156-57e135ae4fc03f2e6d06e36417078f.npy +02773838-20b4891228ecfb4876bb31db0358e9c6.npy +02691156-bd2a375de8c7374195adb59fcbb6489e.npy +04256520-980d28e46333db492878c1c13b7f1ba6.npy +02747177-c2d6739b7d2b6cadad5067eac75a07f7.npy +03211117-9b6d300449f7bd573cffc71116771f14.npy +03001627-4dae16dcdfd7d10be6fe3612af521500.npy +04460130-4884377f5433a9324f2ea904df2fe040.npy +02691156-425619faec43ba86a000a5a61b867bca.npy +03467517-9c260623916034b6f7d037d5768b173f.npy +02958343-6a13836c3bc23bf316d7d2293315a234.npy +04379243-2c6c50203f519351bf5f47124ed0461e.npy +02933112-df509063ec7b78ce8f7d9678498f2295.npy +04379243-da330cf1b5a8f1ad26f51cb1aef0ea9c.npy +02828884-7abeb2903fa22d0fad974a50533b722.npy +03642806-8b4de33bc47389d17cc7e57b94b43e43.npy +04256520-a939afd0e1336d17d20e3ea5765d7edb.npy +04225987-234b2d3aae0b3c44b17369c768229699.npy +02933112-c6a306867328d90fe42c2d012c73c412.npy +02958343-19042f5a90290859441c11ab4641b257.npy +04090263-1cc47a6181beff44f18a63d96554f7.npy +03001627-c405457198f59d86492d9da2668ec34c.npy +04379243-bc7a99b74e3dd257c955e5ed03ef3a2f.npy +04379243-1846b3533f41ae82f8c4b4cfc2702232.npy +04379243-97b7baeb8a172de42f56f09e5bc67bee.npy +03636649-39af776c1435a3374b59758e9336ca87.npy +03001627-9253f198c06794cdc7689830acac6e59.npy +03467517-c739664436ac5237aa0c867d5b070a5d.npy +04379243-65f27b374b83dff560ddc468fe733ed1.npy +02958343-97d0903cf8912c3ee9d790a68c844819.npy +04379243-5835aec0e4aacb278305420c03f867ef.npy +03636649-5d3d9d6a6721646e441f5bb6f88ca61.npy +02958343-a2fa0bfd39718f1688a610ac9b7aaa40.npy +03001627-5427106126c9851dc862eec8232fff1e.npy +04379243-91b962b6de5efaad79679c2bd6c2f2c2.npy +02958343-6355bc126ff0c2d9ef923467520bd6ef.npy +04090263-7c8a7f6ad605c031e8398dbacbe1f3b1.npy +03001627-c12da8acb2c7973597e755dddca14449.npy +03001627-98b003470034007f51f77a6d7299806.npy +02691156-68d3c213b16ee2a6b5f20f5912ee034d.npy +04090263-232a75ecb85c7fef6c70dd7879e7e453.npy +03001627-a1575aa70fbaab0fc05575120a46cd3b.npy +04401088-df2299185baf20a17b1546f309a98bd9.npy +04379243-a2554ec7e2331a8fab610b0c94236463.npy +04379243-c97fe8ab1bb4e195af983a27c524ad0.npy +02958343-e1d2157def9f3ff469856ab03b318817.npy +04530566-fd13e9a9d84bf26266d02be2d9ba0945.npy +02691156-fb0f2907b977e7cb67c5e3041553656b.npy +03001627-e7d4a3cca8edfde4829113e62386fd50.npy +04225987-591971ce679ca4b93ad38b993d9e745f.npy +02942699-c3a410e532cbf900e5a8b3dc188dc518.npy +04379243-6bbd16ddf2f8be61377b9297f3055210.npy +04090263-907def283c0727f7143bcc14d754d44d.npy +03797390-b18bf84bcd457ffbc2868ebdda32b945.npy +03001627-f5caa9b5ada31a8b3cf15c77de45986.npy +03691459-710014b815369e1c2bcea2cd4cc7b042.npy +02958343-45189b11f0524a85e921d7ca67acd2a.npy +02691156-2103dcb213151791acf77e718d93f3e1.npy +03001627-d94490f503e005cb9eeee305ab9432f0.npy +03325088-d24b5c4d9635352c76c18e71fd49c4dc.npy +04530566-9115745cde6f30c67f141c9abbacbdb8.npy +04379243-42db26c80b9530b7c188d6c6d00e7440.npy +02691156-1066b65c30d153e04c3a35cee92bb95b.npy +04256520-855407f176aeecd6ee7d178666aae23d.npy +04225987-2785d91a40cd41a659c9250a427b57f.npy +02958343-19541db644551287ee0112963a7e11e3.npy +02958343-21999849a6a8aad752470de2774d6099.npy +03948459-b022617c83eda074de67c4fcc9fa48e9.npy +03001627-32f007e84efcb9d12cba66dc6aeabcd4.npy +02691156-a4b26e08b6080277a47575cd04a1d851.npy +02828884-4e512ab638542762d4d8765e3910f617.npy +03001627-9e03f57afb7bbfb21b356ab8b24c147.npy +03636649-2958cd9fd799bf02cfbcbf340cec6da1.npy +04379243-e58448ee821f56bc409de7db3ae4697a.npy +04090263-7d54a0f10b79f06af70f35281ca419ac.npy +03642806-920c43f5940ad5516395c48c836f48fc.npy +02828884-213ddf647e36ce28c933c4a3701f5695.npy +03001627-cd6a8020b69455dbb161f36d4e309050.npy +04379243-d056e7c8c972455b22a22d22d00874ec.npy +02871439-aef9733c1f4f09498381de546409094b.npy +04090263-f6b9cfaabbcfbc494298740d1f3c17c.npy +02691156-d1b28579fde95f19e1873a3963e0d14.npy +02958343-6bf75ddeac192594bda733a39f84326d.npy +03337140-30ad23a8f6a3a4479725f8348364f5a8.npy +04379243-92973023278f568a4594f83fd12bcf18.npy +02958343-cadd53fdbf69727721f6e2b0f75cf9c4.npy +02808440-ff0a7ba89bc77fd58797cf21d0643b9f.npy +02924116-91394611fb3302e973f659238edf3c3.npy +03001627-7a9969fac794484c327289c00b6dc9ca.npy +04379243-9cc8c5869737e8e3f51fa0238791f5dc.npy +03001627-e908c290fb506f2e19fb4103277a6b93.npy +03691459-64ebe165fa668ad4abbfc2108a5a7885.npy +02933112-18798a19664ed14c14038d588fd1342f.npy +02933112-7155c1f2abcd7dd2e3f7a74e12a274ef.npy +03325088-957c49fda3109da9c36fb70296e45483.npy +02828884-5cbed790bc24fa22056b4bd5d870b47.npy +04256520-dcd9a34a9892fb11490ad276cd2af3a4.npy +03691459-4d8420f146df7c37ec2dd234c32c102.npy +03991062-a5db4bacbe009f2ef51f77a6d7299806.npy +04256520-216821d05f00b1ccc3bd24f986301745.npy +02933112-3700aafc0160b162c59350d819542ec7.npy +04379243-1f67cbeebf4f65b22b71faa8701e3f78.npy +03467517-fc897eb93c621572ed724609df3eb104.npy +04256520-6fc69edce1f6d0d5e7e684d25d4dcaf0.npy +04090263-37f8e929e458d0a9c2c44977d8755d41.npy +04401088-add38cbd2fd27d62cc98c9802550400.npy +02871439-b2284a33e3a49eac120a829bd43c87b1.npy +02924116-a45862b9b23c240f3c898e35284e3eec.npy +02876657-3336ff069b249afcaea6c6fc97ee6184.npy +03691459-67f091721c90a533d747b49524a1246e.npy +02691156-4d13a1b180422efc2d0334ee3a22c9fc.npy +03001627-8748c7f2041761401fc5750ce9890422.npy +04090263-e40227f3cfb50588ed6e4dd9aa9b9ab0.npy +03467517-c76525770fe831c21082f2ea630bf69e.npy +04530566-4cbffb314a589346b9b184da9c0040b5.npy +02933112-6d30a4d1ed6f4bdbf51f77a6d7299806.npy +04379243-f718cb5d6202341dc183308b9aafe2ca.npy +03691459-1a4ec387ea6820345778775dfd5ca46a.npy +04530566-630bc6dc892aa9bc642f9e27aaf0c47a.npy +03991062-5e825f4aa6a916c544cd688b4bc0d629.npy +03001627-6fd7e0881e4148a238dcf62407724e73.npy +04530566-1f2e662c92843dc9c083d5272d526845.npy +04379243-408b03db5a9972cac3bd24f986301745.npy +03001627-46a6c470367cb57ec5facc3cc8dc041e.npy +04379243-4454343a673c8b3483e0de42574c850a.npy +02691156-45985e48353c65cfd14a90435b48593.npy +04256520-f1e1585a89e6826a1d1a08d58541ab5.npy +02691156-6fe8da29821a60d75057515802db06ab.npy +03001627-8fa742589b47b596e8f8c11a24c52ebb.npy +02691156-fef935c1f862f4aa31309643a94d8a5f.npy +02958343-a78990822fd4836a12615f8be9c552d.npy +04530566-80930e10f1f3ab9358401a911725e987.npy +02691156-580e54df8765aac1c1ca96a73599ca7e.npy +02691156-90489d6f74296c88daf24b8b932d0212.npy +04530566-6c1458eec06ad0c147a67ad1fb1cf329.npy +03636649-5a1484a25a5b8a08e0df09c6ef42b40d.npy +02691156-f95d8e86feb79b17cbebff57eecf0a64.npy +02691156-84e45a6f079cfb9526360e1e29a956c7.npy +02958343-b9ae3fb6b027dc4294a553cca1043426.npy +02828884-ec917ab14b06fe402056b4bd5d870b47.npy +02871439-7bc107131eb35d089de7cc26da67a42a.npy +02958343-18aad9d102afbca57ba2273581c30cb.npy +03211117-f2f41913123a7a7e4b87db09ac4cfa73.npy +03691459-bd76dee31cdad0f0bb62a53e25c6d701.npy +04468005-896352cb09e6bd1e398968fd209b2972.npy +03691459-c766463a3623d0ab8a0181490cb73cbc.npy +02992529-452b924abd2ece2d58932236a22029d3.npy +02808440-f02c871c08d664544b97a2297d337e28.npy +03467517-a1eeab052ed7be831082f2ea630bf69e.npy +03046257-78083db936435d0a410f8c2a2eb53871.npy +03337140-c20ce998ba99451991c352d02061b3f7.npy +04468005-97a93d1479a6382752470de2774d6099.npy +04379243-e81af191bb828526815b2b467e8e2eac.npy +02958343-1736b8494abf38ba4eb766e5a46fceab.npy +03710193-f76e818f809a73921b17743c18fb63dc.npy +02691156-cdccbb56939fcdafa266a0298675ed53.npy +02747177-7069760a16db98f46c9e5b09a1c294d9.npy +04379243-c755eeaa4a588fcba9126dd5adc92c1e.npy +02691156-fd0e59013a16eb5184306f3bf0a1f2d7.npy +03636649-47cd62ec53571be3276206fae5d3c473.npy +03636649-a4f257a3eb6c5c37f716a9f638b146ab.npy +03001627-b51e2ec95cb6ae33999b33727fe6db14.npy +03624134-e6d18d45abd40a22e5ae31c6c631a39.npy +03691459-cc01f463f825ee9024fa1bc380696e03.npy +03001627-6a2ae8bc01eef7b25e655c6c6e834498.npy +04401088-738e377ef785ee92d3429357dd0adcaa.npy +04379243-869516eb98eb3c2fb54d798b09097adc.npy +02747177-af6fa396b2869446d4d8765e3910f617.npy +03337140-f33558146907dde59118eee0b123125f.npy +04530566-3ff4ba746d73fdd08f845c46c317c0e2.npy +02691156-b1021932b387da327f58a59a37266b2e.npy +04256520-1053897adff12c7839c40eb1ac71e4c1.npy +04256520-884edfe9e34533543ede9e7417860fbf.npy +03636649-980e88a168a94790899bad344dc01f2f.npy +02958343-3905d1dcfd5e702333d445f141c62a67.npy +04379243-168e317409670cf2a0006518e6ab8b1.npy +02691156-b458bf7d57d211ee43bc2645d97a220e.npy +02958343-83afcd8ba9cf63cba7094e4ecf18eecd.npy +03001627-df55d3e445f11f909a8ef44e1d2c5b75.npy +04379243-a1d9f62e3bf2863278f39854b0025475.npy +04401088-844633a98977c10d9eedb085a3d8dd72.npy +03001627-866e1be9f53830ed7a6617a3ecd0b52e.npy +03636649-9d340cb226868e39ce4f274577283b16.npy +02958343-33e897abe9e7df46a9aa61915b4add2d.npy +04256520-4ec9d99e4094a2bd91659e904513cf6c.npy +04401088-a3f4cae960ac74babc54d4bc75a1a826.npy +04379243-e6b84acd543ebf20662cdc2f77e49a85.npy +04090263-f5f4d746b6d0b8f59f433921788191f3.npy +02691156-a6b9d686a7b977035bae66e2c509821b.npy +03001627-eb039f6a86785f3a9e633556753261cf.npy +04090263-25cf1e85d9875c9412173f61ff9d1fe5.npy +04379243-71a26c00d3a4bf834397d3416be8cfe5.npy +03593526-9d4bd3ecfdecc031561dce3fe08634b7.npy +02958343-f6d7cd8a000997b1aa69dfdc5532bb13.npy +04379243-967d0f37416158b897a6420376995cd0.npy +04256520-cc4f3aff596b544e599dcc439b161a52.npy +04379243-15339648435a8e6290ef7803f19df417.npy +02876657-d10b549075e8f3812adf8abaa25e0215.npy +02942699-416ce9adf7ad40f4959c1c3d740c4f1.npy +04379243-2f98d5e721e84debaa8081a7009091db.npy +04530566-3076e52758d28680b534b494664155d3.npy +04530566-65f8bb163e351bfa9399f7cdb64577ad.npy +03211117-ea58a7f6955d740fd18c7d7f7c43f51.npy +02924116-239f4f66030286e73a304988a6618a7b.npy +03467517-c7c7542265b8172c7e1c85c5c15da7fb.npy +04401088-39b91aa425472c3676fb191f3b44695a.npy +03325088-e34fce990f5c1e3bb362845c6edb57fc.npy +04530566-dc27c81f14e3a89c84306f3bf0a1f2d7.npy +04090263-897084449b84192db449aac65ff63543.npy +04379243-da96905b5b3c821c8cbb8bac2032149c.npy +02958343-e98955e5d46a492c036e20efe5e5ca8.npy +03636649-8207274d3677061673ab7b7128d466a2.npy +04530566-20c2bcd71abffc2a93add66353cae8ec.npy +03467517-b6d0cf333c7e013993f0194265a9746c.npy +03636649-8fdfdb325c5239e798e0d1738edd4f19.npy +04090263-c0e05e56826d5fbc38cddde805fe966f.npy +03691459-30bf1d16fb6c28fefa70f8d6bbdfb0f4.npy +03001627-f0f04644e071d9348ca588a3264b9f86.npy +02958343-affba519865b72fc2c95ae1829869305.npy +02691156-a09773e513ca86ba8699933784576e73.npy +04256520-b10f96a79a4fbb039444333dad662f20.npy +03636649-c2f055fac2817b263cd6abbbeca4e2ad.npy +04090263-c497e1a1ef3515f197e3ac788f68f6.npy +03790512-f145950bc661e61bc4b71cf5644b0ee1.npy +02691156-92e445da194d65873dc5bf61ec5f5588.npy +04530566-a58fb21bfa4e2f451ddea1d5aef06a06.npy +04379243-367284cdf79742334305d9043f82a6a0.npy +02876657-532376fe56d3597ac65f62bae01f4803.npy +02958343-36fe332c1b11696d51a95aaa6caba1d3.npy +03691459-e2c1e8958295f84459fca7a6b28640d3.npy +04530566-5bd0346e72866c8256f77b6bc6731cda.npy +03046257-c9dd71db5e6713937d0fed3563de13d.npy +04379243-50bc6269b12da0e5f88cd736e1bad067.npy +02801938-d9fb327b0e19a9ddc735651f0fb19093.npy +02924116-a20de35fdfc74932bf5e15f245b14644.npy +02828884-4b00859dc8ce46eff4fb4dee5181bee.npy +02958343-ac3585c59a80b822b4d8eb72d337b2e3.npy +02958343-e5c45e408595abe2bfff0ff366de48fe.npy +04379243-c45e6ceae72c7a97be8908669c476d49.npy +04379243-a8dac23add615b33313f9af5275b7c70.npy +03691459-c82577c608e88a8fb2ce325c854088c2.npy +03636649-8cb3f83d6ca1a4849364e552d5e4060f.npy +02958343-7cba7b4a6e106bfa2bc5065d4094ca0a.npy +02691156-b97900a7f44bd7dcca8607f540cc62ba.npy +02691156-2d0945065aa2a427eec7473defebb526.npy +04090263-347cee581e94fbe5d735fa1ab17311ec.npy +04256520-d851b8a016cf114c742f75bc7df727ae.npy +04379243-f5fa9f592d891083996915f7802ec40.npy +04530566-482ad82769d6b5b11274a3ddd0ec9301.npy +04379243-c0e8eca9811baaf1237b12b19575e7ae.npy +03001627-ffcb8206f907e663eac685b1b2988af.npy +03261776-1a5e2a7cddc8e46aa681aea7976a4565.npy +03928116-ee5f02473d056362ead00c9724dd9a8.npy +04530566-d271233ccca1e7ee23a3427fc25942e0.npy +04090263-1c6064f070b55dbfa449921c4b97dd7b.npy +03046257-e26485c0a14a90867903707764646db.npy +02958343-f21bd46dced01bd835da01f298003d56.npy +02808440-545abe6ce52a927d3321831d2245cf06.npy +03207941-f0a18797e3fe9456ca8fc0fc5ee911.npy +04090263-164248eefde5ce846314c3b6a3a65519.npy +03691459-7b81d4cddf859fe7ec8f1b76923633de.npy +03691459-33b19fdf42fd767d871a975200291c6f.npy +02691156-b90571e8736a296c549b705aa127253d.npy +02828884-fd6ae258090bf95b693e50e46681af47.npy +02958343-ec469722be9d015c1ef32d215d1c8df5.npy +02691156-e4e98f8654d29536dc858dada15498d2.npy +02828884-818879b4a23c12bf575f9747ff6fb5e8.npy +04256520-67386a2dcd3be10b8a09f7075b904cc.npy +04379243-1cce99367326fb45a7f4087375d26b7.npy +04090263-a3d111fe5fab82a54aef47a2c7bc343b.npy +04379243-5247e4e978399f1b486040c0d9e85846.npy +03001627-e65ca690574bfca53ccbceb68fb352fd.npy +04379243-c62dd18f43f11b858d2fa6ffb11d1cb3.npy +02992529-52494d36a6d136f6b34ae4286be3d813.npy +03001627-882f30dfcc94ccb5ee57043a0b4866cc.npy +04090263-508230aada88eb0a550a87cda3436d95.npy +03211117-b06ad1afbbc8ba7536b34d1a0ff085ad.npy +02691156-59bbe6a07a5a68d5d96b332cac4e78f7.npy +03001627-68e9a9ebe0475536194b666f21552cb8.npy +02691156-7d89d64afbb5b24056dd1ba442ba87e2.npy +02992529-54b4288766d87dcf332f5e5df5b42874.npy +03001627-2ae70fbab330779e3bff5a09107428a5.npy +02933112-4c8e95fe5fdbb125c59350d819542ec7.npy +03636649-bd2dea41f32e4562ce11183544874734.npy +04530566-6e3db071ed95552b3faeafe37c2ce4f6.npy +04530566-847e8fedddf6bee5518c49741aed1bc1.npy +02958343-1660d6b7221223708a49a62fbc70ff9a.npy +03001627-b431161712ea348cdbbc9440457e303e.npy +03928116-2ada8e6257eee4b73bb4a1304fe504d3.npy +03467517-4b325df8da005995f0e1c0df18936d05.npy +03001627-7178731312819be3ecb14096838a20c5.npy +03337140-d88e590e79117ec7e7ecdbe73ef4323c.npy +02808440-7e3f69072a9c288354d7082b34825ef0.npy +03691459-67192701cf183eaaf2a2172bfa1bbe55.npy +02691156-636dfe39d75701b6cc14f1e6f4f4f49b.npy +03001627-d0894aed032460fafebad4f49b26ec52.npy +04090263-abcfbaaa409d62001d263b1fb57ddbcf.npy +03001627-80784cc9f549e4abc3bd24f986301745.npy +04090263-1762f93a8249ef356e4806bebefb1ca8.npy +03001627-ad7a6efb5aa6c289810da4adc58441d.npy +04090263-c4787a48747c6db1cc34b900bb2492e.npy +03001627-2d204f50f33b3994fe52ffd0e748a1ab.npy +02958343-175a289947f549b0e088606e38104b2.npy +03211117-bb01397739208d30d39a67ea53079d95.npy +03636649-956ef7ea0d496de01735ea0e092a805a.npy +03636649-64a45d75c1c5bad6f51f77a6d7299806.npy +03211117-f2b3efb28b5f5d56fb4038701c4e8e29.npy +02933112-36d62d9dcba0e3ec4da5feafe6f1c8fc.npy +03467517-11e4201608076126d67ed0980f6dfc4.npy +04530566-5cee5c3afee327cf360d3819686769c9.npy +02958343-b12841de144ea6fbee3362a8d2d8318f.npy +02808440-e4cd718118a15c40dcf3aa5cc0c09272.npy +04379243-6986716a76d8a2952ca3f5e9a38d33a0.npy +02691156-c330992ccc6154d82b6925c3587009fe.npy +02933112-a3a6f9e80956ec6f4035f93ab9531db.npy +04379243-37ef68300b944adac5a1529d102e7db9.npy +02933112-3115a3a0a61aacac59350d819542ec7.npy +04256520-7e728818848f191bee7d178666aae23d.npy +03325088-1943c8dfb6d5f0bb362845c6edb57fc.npy +02933112-4c7cc0a0e83f995ad40c07d3c15cc681.npy +02933112-817e119f087cf8f8f44880b8ee951142.npy +04379243-14bbf802bf00121267d783b4714d4324.npy +03001627-805bb12faecf99a9bbc0e8a3b6521117.npy +03790512-c7c8d9406c1a93ab52a0573c504629a6.npy +04379243-3cb345b1ef0f4d929a7e020ff2597416.npy +02933112-4de45ae952657a45330a170e9ceed373.npy +02958343-99f9ab439e890e79aff8ec395bcde91f.npy +04401088-e1effe88e974292f8ba7bc4a733e1db9.npy +03001627-2ca91e56bef8cb5034af953b663e921b.npy +03642806-8d9bae8897ac3f973c28672f19a43c87.npy +04379243-3af5b1ef3e742dedf4b6538438a0b930.npy +04401088-a13cea3066cd5b1746ab0c6c4666145a.npy +03325088-a9411c894038543ec36fb70296e45483.npy +04401088-d9ce2d0be1f3952aa36bec4fa7cd58c9.npy +02958343-a49df2707037f82a94ce9d7b04676231.npy +02958343-2fe4a878e34bd3bab8013668e30e23b0.npy +02818832-6284bce6e6fe15c8aa69dfdc5532bb13.npy +03761084-13290e02935a82a22846fa729d90e125.npy +03001627-89509ce24bf62df0950baa3a522faef2.npy +04379243-6be99fd273c3eb879d4c79351958f461.npy +03337140-657db7fc093199c891c352d02061b3f7.npy +04401088-312c430f8b1a3fc80249ed612e14df4.npy +03211117-eb54df4a6211364d49d7025d277c28a1.npy +04379243-7f6a5ee3a0fb9ff19fb4103277a6b93.npy +04379243-c87012fece9848de87f79701ecbb26ac.npy +03624134-594dd047f15ec08ab1e00d60b0f9cc70.npy +03001627-6aaa9bd6e835eb0f9b9f2eb77f5e247e.npy +03325088-460cab47b5657c7176c18e71fd49c4dc.npy +03593526-10af6bdfd126209faaf0ad030fc37d94.npy +02691156-e69631d34410f99ac4f72bf08dc79a6.npy +03710193-d80f223e5e1c96d8e4ae8899818510b8.npy +02808440-ee230a2651945801b20f6e48f6a30cbf.npy +03948459-f6d52684720d52a01ab78426351eea4a.npy +02924116-c8284ae0b7a06eaba697ce29493f3815.npy +03691459-2c64384906f809f09e9eb484700b40ce.npy +03790512-c9c41d106fc36402b0f9875a6c9bf605.npy +03593526-78c709102ee8d89ab7d0f3d89bbac230.npy +03001627-26ece83dc8763b34d2b12aa6a0f050b3.npy +04090263-1dc7cb6866488d93cbb897b3e6934456.npy +02691156-fbb2e9c15888afcaca504cdc40c452de.npy +04379243-41a464b6ea17ef5ce7321f25048c6142.npy +03928116-809307d04ffd3fe5650ef5c65206a324.npy +03325088-32afa83cf029cbd414b35a7d7cea7130.npy +04379243-cfe15cdc16a2e2054e2e1b2af0cc59a7.npy +02808440-cd21cb60750fd91f4eda040ae95dd4aa.npy +03001627-8ca2c0a0eed4a31abb93315448664e1d.npy +02691156-c7ae9f9e3f95ce76adecb6fc00604132.npy +03467517-233064561655ddbce4ca9fc57c06f078.npy +02691156-4f9b12d07dce21ac9d93a50cb0355558.npy +04379243-4019bfe9bd7605f7a52709499e423710.npy +04379243-6adda4f50154d662492d9da2668ec34c.npy +04256520-93b09a953435a00175aa7f24a9b6003a.npy +03991062-b8ad53f8af09fd10e299f2c0038a26f5.npy +03691459-6e6b4d2603930dfd4fc88114be3a6b6f.npy +04090263-70459a553f42c300f85b811e02bb4272.npy +03797390-8012f52dd0a4d2f718a93a45bf780820.npy +04379243-a59ef94cc10c7a434e6953a92bb25210.npy +02933112-c365225746f2eb94ce5d6e9371bb5c33.npy +02958343-d5c4532a34ba10e6f9798a883006064f.npy +03001627-3b8f2b955ee9a904b3c42e318f3affc.npy +03636649-c43c89d862e10552b24ecc319936dfe2.npy +02871439-9c3319cb3c0a2ccccfb1f9b76452480a.npy +04379243-d083fd20f6f953fd4187eeeb0dea4986.npy +04379243-ce4fde399bd5f6f6784a45ea6efa1d77.npy +02876657-6b810dbc89542fd8a531220b48579115.npy +04379243-565225390d303601c0f947750540fb22.npy +02924116-9384cf835d1edf0dc95c7a8a79dc0c72.npy +04379243-15d58d8098de68aa48d189f942cedc62.npy +03001627-5b1744a03be753cf3ccbceb68fb352fd.npy +03046257-e43b7ebc9a1b71c95dac0a5eac75a2a5.npy +04379243-e01e72e173dd2cec8c76ec1f86d432b3.npy +03467517-3f287ca94b719bec282708d01f090528.npy +04379243-97deac79537426ac9255fc5df0de0bff.npy +02958343-8242b114695b68286f522b2bb8ded829.npy +02958343-91440448603dffb62c8b6ee41d7d5d62.npy +03636649-c61d6c246dde340462a510b8f97c658e.npy +03001627-9b27e1b557a5e499b01c58badc8bbc39.npy +04256520-7e1321155d43dc8bfff16555386d173d.npy +03211117-324ef9fa783f6fa3a70ed7ac6903e853.npy +03211117-4a2a1d7cf80d6031275d003e423c59ba.npy +02876657-78d707f4d87b5bfd730ff85f0d8004ee.npy +04379243-65164df6ae3dd848a1d7c136d0e341.npy +03691459-dfe7f79a9a4279d09596b23e90d45a7.npy +02691156-437de410d7c23cbb29b33c3ec58287c9.npy +02747177-5268d7d72312c3645fa85fb6e983b148.npy +03790512-52e2bc89667a8e35617798af67b81f2f.npy +03636649-1a963b28c5520cc737b2bb75885cfc44.npy +03001627-b42e4fd21f39ff4a19fb4103277a6b93.npy +02933112-91b2bed2f4b87e615164a043915ac8c4.npy +02992529-20346d307d39aa7eb6a804c25e3218a.npy +02958343-95ebb3fd80f885ad676f197a68a5168a.npy +03001627-71b53a5f441d45b742b7e4c0136bdb7e.npy +02924116-193fdf550fd5f12f446f92b52bbd82a.npy +03624134-3fe6dd259603ea70f342cbac7471c0b9.npy +02808440-9d3e7604b922e1e551b711a0825fda5b.npy +04401088-19b1c1a790c6824578bfad8b5ed8c4ef.npy +03624134-1574b4bc968ff33b33ae329611c23135.npy +02691156-c4f22c879e8adbc6aaae11b67645c759.npy +03046257-702fe577155d343cec77540dd1841b98.npy +04379243-ea3ecd082151c2137ff6ace05b36a5.npy +03636649-7d6dd04be7630ff01735ea0e092a805a.npy +02691156-24c2cc372c63603137678474be485ca.npy +04468005-96d5563fd3dffff75706d1c54190f27a.npy +02933112-5c2d14889827e1fc14038d588fd1342f.npy +03325088-a851047aeb3793403ca0c4be71e7b721.npy +04256520-251cccb082a6d36024f2ff737a52b0c8.npy +03001627-beb8876f47c5d4287eaeab1f0c9120b7.npy +04379243-11e12804b2712d08bee8ec52a122c491.npy +04401088-50504687883a08e3c6587b192c4cd3e.npy +02876657-33f6ca7ec9d3f1e6940806ade53ef2f.npy +03624134-4ad7d03773d3767c2bc52a80abcabb17.npy +03001627-4ea3d680127a9fe91360172b4b6205b1.npy +03636649-f9ee021d829cb2ba1cff7132ce500fbb.npy +04468005-3dcbbdebe3be1c53f54087fb0e024d3.npy +03991062-fe6737dfa2c07780d4d8765e3910f617.npy +04379243-3f14c153dc861c0990453a996fcb7627.npy +04379243-7d4c3e8b3304d8f823fe3501bb9e7193.npy +02958343-1176dff7f0ec879719d740e0f6a9a113.npy +02808440-d0df653cb5c1ca016b6c87c9f47318a.npy +03211117-ac2ea2d41c57d1075999f9ba82d15928.npy +02691156-420eb46efaa81427b60ce16063f0788e.npy +02992529-b45f58361ed3ae739d2375e90e0e0425.npy +03001627-bea34ffef0c02f07492d9da2668ec34c.npy +04401088-e8c4ef4c74c631e83628c1e9941a8ab9.npy +03691459-2dfc635b5ea197bbb611871e114769d9.npy +03948459-b0a050985a5ce6be25508ed649b952cb.npy +03636649-89622a50662e28d56c09b6371c58b533.npy +04256520-cc4a8ecc0f3b4ca1dc0efee4b442070.npy +04379243-192ec952a75014d09eaa55bb236fb6e1.npy +04379243-6d2783fa677cdfdc14e775cfdf4a76ca.npy +04379243-125ef28adc874f72934a4834f9d7586.npy +03513137-1dc0db78671ac363f99976ddcaae4d11.npy +02691156-b5b0dac4093a61cb3f2b01de37c0b29.npy +03636649-2b8dbd2f75503fb0c29700c28ff4f50b.npy +04379243-8d608e1a1a1f34adf4b6538438a0b930.npy +03636649-def342a8d095d8501ab5f696a41d80c.npy +03710193-514ed68efd116443493f0d0eb265f250.npy +04379243-3e34ca92c5067543fe9536dd9aed405f.npy +04256520-5cc1b0be0eb9a6085dca6305fb9f97ca.npy +04256520-1837416f6aef641bafcd24b8661a2fd9.npy +03325088-6102c9de80e5625eb362845c6edb57fc.npy +04090263-ce400eea04127631b8611345dfd403f1.npy +02808440-8825b869b855967fc197f3661a4ec752.npy +03636649-608db437f2aab3c13cedb1808e691a01.npy +04379243-991738fc61b81af030ddb6ead95f49cc.npy +03636649-66fbe6533abfe75195b26656722dea64.npy +03001627-42836979b217e0535836c728d324152.npy +02828884-aec473af77a77008cdb14b1e0ff2c14e.npy +03467517-1387dfc170091bb33c5494866fecdbc.npy +04004475-7f60e19e4f1b7b92f08c6efc59ec3825.npy +03636649-7ec821d5d8bd9f17d4aea4231844b26b.npy +03325088-684e3d299f3f7910843f813f752a5e35.npy +02958343-ae088f798f2c99c2927e12317acf49e7.npy +04530566-1c974cf5f4053701876d2c2355e426da.npy +04379243-d1ef95530469a1de1fc4857cc94b6562.npy +02747177-c1177110cf5b9b12a3c9394112c76917.npy +03001627-5283a98b5c693e64ebefe6b1d594ad2e.npy +04379243-cc05a1835e7edda1c02daa819b61338.npy +03001627-6697a325ee92e17695e321e9c6480.npy +03991062-81264e9ebc22cab136b0f2a1430e993a.npy +03207941-270b80325b30676592a31ec18c4e190a.npy +03636649-b88130805777f2efb76e29c9c43bc7aa.npy +04379243-20f561347df7703c9c9e05c155b1837a.npy +04256520-f0961a7006186493df6cfab91d65bb91.npy +03001627-671d34c27cc0f1bf2deeb5ec76cf103b.npy +04379243-c676bf562cb559e5ea820b41f77ab7c8.npy +03636649-421c9c7d606e0cbf26c27fcd604ee778.npy +02958343-24866846d728484e1d1a964dea8a7aab.npy +04256520-2507270b7e344bbda494798fa117187b.npy +03928116-6a5cbedab021de133516f91af8d2e0cb.npy +02691156-acaccf2af6ed78925a25a01ca5b91f98.npy +03001627-6be6173e7eea5888a616caf97d73fa02.npy +02818832-1aa55867200ea789465e08d496c0420f.npy +03636649-42cd4d8cfa141d4d374110224c1c4eb0.npy +04090263-199c603cb0ba88899ac559af07c55afa.npy +03636649-1d5ed34e8ccd86a88c94c2386714981e.npy +03001627-7508cbbffe5f2f95f51f77a6d7299806.npy +03467517-6bda8064db052734cefc37637c8d9a99.npy +02958343-5662d48de15dcacee1c2519ec6f06d41.npy +02691156-71fe2583bff79bf1c66589cdaf418925.npy +02992529-e76bbcc0029c979721844676433a0aca.npy +03948459-6b2d89a7f2b173f0d9deb3f829cc2475.npy +04379243-5fc5ebe830d27064563796b09a95b12.npy +04379243-dab44e951363e187ed44d599900d391d.npy +04379243-2633bba6168a580c8997f7623978b6e4.npy +03001627-b30517fab8b8300bfed6ad7429dd8443.npy +04256520-99ec963187a1cd2593ebeeedbff73b.npy +04256520-1168fc14c294f7ac14038d588fd1342f.npy +04379243-d5402d5be271438ef51fa0238791f5dc.npy +03636649-64f61c9c81e3eb7b8aaae3d020f5ddf8.npy +02876657-cdeccf2f410846d0e0155f56493d36bc.npy +03636649-6ffb0636180aa5d78570a59d0416a26d.npy +02933112-17e3997117f88d921ba9fd11dc8bf457.npy +04256520-ae4f28a7c4e22d9535dda488a4bbb1e1.npy +03046257-14d26e0c75890a69d1100e95297cce90.npy +02691156-2764f43226260c94a5a118bd15e6e34f.npy +04379243-690c3f8a4e7d384f1270a3c39ec25c61.npy +04090263-cb392c32ad0446aa576cd215d51ddd.npy +03691459-dbb3db217511d9cbfb906a2c84fd375f.npy +04379243-98c67a49d64d7bed1cf96a5dc33e37f1.npy +02958343-1336353d15efdf010f6f717db02df67.npy +02942699-e57aa404a000df88d5d4532c6bb4bd2b.npy +03636649-d3194dd3e07881828f58d8b19de93f99.npy +04256520-ffc1283c098f46cbc6ff4c4f6444568b.npy +02933112-56253642219df29c37d43e094da89ace.npy +04256520-a0ce7fd10e80a9f9f0fb3e3d2a0d34c9.npy +03593526-398818a67897e02fbab0ed993e467961.npy +02691156-4f7814692598ebdc7dadbbeb79fd1fc9.npy +04256520-d8b0f33dd965d49447558b47f7ba0b0c.npy +03001627-d0255120e3351121c3bd24f986301745.npy +02924116-6f764b306282152971a782a4379556c7.npy +04468005-e429a05307bfdefeb8976e45db2e8d04.npy +03928116-4b29f873229621a13a1b23713d5a88eb.npy +02818832-2cd2307d0ff140d71bb5b0562ff6c354.npy +02691156-37d32db3143814fd9a55c6af6f4b2bb3.npy +03001627-b34d40cf68d35685edd5830365d88456.npy +04004475-37f2687738571a0518e2de4e83d3a734.npy +04090263-4f0659c5971bcfbead2649d755c19c29.npy +04530566-396fb90a02afe669258bd22729297863.npy +04379243-91981bcdf94b60cf3e5af54d0ed82d00.npy +04379243-57e4a4a4806c38e33702d3e624608075.npy +03001627-92373022868b812fe9aa238b4bc8322e.npy +04090263-8fbd9668fdd563f5359ad7d9ce49f504.npy +04379243-7486e6cc0f457c4c12a1d8ce70d3a8e.npy +03636649-44cb50f7614a4574d09ae058ff1abff8.npy +02691156-e51b620853f2cc0137678474be485ca.npy +04256520-3b66e52a5272e0b4851fe006c784eab.npy +02808440-b9faf51cd53539ae8bb4434d620302e3.npy +02942699-4852ee95e7bd8556c60396a717ba6c7e.npy +03991062-f8a37a9da22f9e19c2ed3fce8969c0e9.npy +02828884-1d5d89cc3c83bef056f6fc4b4ce1db04.npy +02828884-c67c3e22b0c0f34e7db48c721db3fba4.npy +04401088-528e6424ccdcf2af21844676433a0aca.npy +02958343-204b1b3e35df174859fcf77704d7f1e8.npy +04401088-31e8327ffa4ba6a87790cd6f6e8952aa.npy +04379243-35b696cb05089cdcc8dbe21f531a88d0.npy +04530566-f2b504b2e368bee6d3c2fcae9650358c.npy +04530566-792427f5da01907ddf48ca5a34c88e7c.npy +04090263-60eccc70ad4f9aed15b3bff1113c0f8.npy +02871439-b45ab0b19e7ba07fbad912dbade87ed7.npy +03001627-b7fbbd8cdd2b0b27a37bacfe19b0d747.npy +03691459-5755d5aae08a8f2dd9c568a52c35ec71.npy +02818832-162af9629f9071cd38f8f3d7f64ab05f.npy +02808440-8183d981730d9f4b4c62bee40dcdc539.npy +02958343-b11c0c16e0eed1f4b8671dc42cc45273.npy +03691459-1301670e3ddb72b099284d844aba7576.npy +02828884-cad0a0e60708ab662ab293e158725cf0.npy +02691156-b98a46b40d030e8a26360e1e29a956c7.npy +03691459-6d755a3d6d0f265d77ea5e1afa5bfe6.npy +02933112-b1f23b772bfe59c2f766c600156dc40b.npy +03001627-f33b6f791e9d64387d01b77e04a0bc7b.npy +03593526-6c7bcc925e7c6fdfb33495457ee36a49.npy +03636649-3a58b059261aa07229a42a0444436860.npy +04379243-23b7e640f09dcfabf1477cd05362531f.npy +03593526-97401d5d5b06df3cf470479da1b48414.npy +03046257-3d027f0431baa68a9dcc4633bad27c61.npy +04530566-ff54247b18f676d9129032621d548b11.npy +04401088-69e334b26683a81935bbff93749c520.npy +03001627-70aaed71e394259c87a0ca36e3a00f4e.npy +02828884-4eb3dc26aad9ace8f4fb4dee5181bee.npy +04379243-f7600660924857c0d31d0d81bfe9c743.npy +04379243-25244dda23e8f58d788f926f4d51e733.npy +02691156-de1a7b4e9911e48b48e8405d6c51a908.npy +03001627-4dc7fe6e98c4db21d79b19c7c4f0e293.npy +02992529-a24fb0602fc7fbf4ec059109909662d2.npy +03790512-8134a965cc0b134bb37378f3c85478b4.npy +04379243-480ddc59636d6516659dda512294c744.npy +02958343-1c1a3dc04b6f1f8fd8162cce87567b4.npy +02691156-fc5d7c28e254a0d84c3a35cee92bb95b.npy +02876657-6987e839b802a349a9039b9668d0f11f.npy +02958343-3261855155346979473f10e6caaeca56.npy +03790512-a9e2a1de33b99d08b37378f3c85478b4.npy +04379243-1b90a6d174038fca46ae6b1cc949e238.npy +02924116-b94d71a0d28f79de613cc927c5b662d.npy +02691156-9acef1e2e46120f8fdd77aff53f4b7ba.npy +04090263-a14547884e1ab54f48ae8c3efb265806.npy +02808440-1384585a48232ade2b4641ae88b2ff3f.npy +03636649-8f7863c4940c99211735ea0e092a805a.npy +03211117-f6722edbe92ed28f37b2bb75885cfc44.npy +03001627-491eb8f7028d06152966622c3d8ee695.npy +03211117-37eab42757ae1545be36894b151eda76.npy +03593526-98317e58cb7f2c5c598a453fd9fbd988.npy +04090263-6afd1407c216151994bdc5b116ecd8dd.npy +03001627-b1f85c18b3ccbe3a8bc6f322a9608b07.npy +04530566-1eac28fe0b2d620bf0f75e254acd7ce4.npy +04379243-a1446962064bdf3ba5342d638d0c267.npy +02958343-44eb9496921072b6e5f9082491d52810.npy +04330267-69ad4c4dab82ce29a642711976cdde72.npy +04256520-11b36d8f9025062513d2510999d0f1d2.npy +03001627-54054535e70d9ca0f91663a74ccd2338.npy +03636649-67e03d2c2b7f6b19b38821f893bc10f9.npy +02876657-c80173e23efaac35535deb3b0c692a2a.npy +03938244-89fd3acbd34e72106a6cca39468798a8.npy +04256520-d9d4b2af7ada1426fc385a284336f217.npy +03001627-99a4ced5a15438131ff008919d662aea.npy +02933112-4073ca6ce52b5d65ce5d6e9371bb5c33.npy +03636649-90b0f9a1ac2e54ecbc7f58784fda27b5.npy +02958343-c53256341ac5693c66d89345e534c861.npy +02992529-c1077972752aac54e8deab000196f61d.npy +04530566-cff1998a2a2f1b5985f7a3de54751f1b.npy +03624134-5ee83e84f18782eaffe50f88045d4553.npy +02828884-5d4fd92c09e3369256f6fc4b4ce1db04.npy +04379243-bd974108a3455842668ae11a7db5e82a.npy +04530566-3173f703a1e52d7f38d037116a032a18.npy +02924116-1bfeb10fc8e4435591020bf045ba1fdb.npy +04379243-17936c67b822fdbb6129e6c3b6c36a7e.npy +04379243-53b0206102d236c99f8c3d2002c77ddb.npy +03593526-24f615dd07dab76cc6040c0e6de6a84d.npy +03636649-9c3c8db3c4b29c8e7bcb070cc655f13a.npy +03691459-fbb7610643dae4a34c5341ee07f41676.npy +03636649-3b20c6ffdaf2dc97ef0add8da8532fa8.npy +02828884-cf873b381095c2d43cbc166debd211cf.npy +02773838-adfe9029a1ca723eb8966aeece708f87.npy +04530566-27476b5c965b010618b731fab8bc3743.npy +02808440-8177f9d2397e8dd3d85b29704f5fc7f2.npy +03001627-5c28b7d86cdf577c944bd645bf5a9d4f.npy +02808440-6458583a168aa52af42a90fe4baf4591.npy +04256520-95c9ed9cbdae00eb768c07b3cdb90be.npy +03001627-8b38389cef61cf06fa675450a2f0c084.npy +03211117-3c475567446dc6b7d6f4cef762589739.npy +02828884-cb4c2ef4e926f7c6d4d8765e3910f617.npy +02828884-7a8dbe4a1ce3be987962800be79c6e52.npy +04256520-c8466c51d29e4782dc149927e19d9b07.npy +04256520-709f1d6837ed560bb12cf25c409aac26.npy +02871439-840ffef504ac563cba5b64592e406eca.npy +02958343-cde88b5900e8dfba725a7749daae1afa.npy +02691156-8af350191d35e65cc3fe7930fce05ded.npy +03938244-7a555dba7e9f00549276a66e8d922b73.npy +04379243-3b8af4931096a5b7310cd758d9b7cf.npy +02880940-ff7c33db3598df342d88c45db31bc366.npy +03991062-3dcea39601c77b69a2c59a4d90e63212.npy +03624134-135f75a374a1e22c46cb8dd27ae7fcd.npy +04256520-ae1b6411a089bfabfff16555386d173d.npy +04530566-d09202ccf8fa18d7de6289e76b045123.npy +02933112-5e6c95a93849d3a9cf004563556ddb36.npy +02924116-6c3edb2e494dfb34238f44c3636a01e9.npy +04379243-2fb395d53b34b02fae5873f5a6ed699.npy +03761084-1508af47d1e83932a10831b4711b98b9.npy +03001627-554dbcee2b9ea7301c75d484f9069623.npy +03928116-4a969cd6fc3f2c0a834096795cc3cf10.npy +02691156-cb145792217196e27d64cad20089f027.npy +02828884-aa7f8ad0e6108db92056b4bd5d870b47.npy +02924116-a1569abb031718b9193d7855ecfc1bd3.npy +03001627-c523e86242af4b4ecf6d196856691e1b.npy +04379243-9a2529a1b49282cd6eeb02236344250.npy +04554684-63b49123983e4cf67a31dd5af93fdb5c.npy +03211117-1a5494c28b607f699263b5578aef09fa.npy +04379243-17624075a52c9b15cab01e89f60c9290.npy +03001627-5a95f4fbfbfc55bd93768e7b9b1eabf.npy +04090263-344d200007e2f72e9352b002a7d38daa.npy +04090263-3cb82befc3290e36b58435942a1b4dac.npy +04379243-1d93291de09fa5c876e9713f57a5fcb6.npy +02691156-9712035b78970ca71e623da3c4e40c05.npy +04379243-57f273bd63f5287199e8bf807e902261.npy +02691156-4f1fb7c062c50fb15a2c5766752aea65.npy +04379243-68e8c6def7cd57053e946fb2184f0c4.npy +02691156-e7c1bb596e9a1ce9ca8607f540cc62ba.npy +03636649-e21f21744e65eb1a4ab1b242068f86fb.npy +03593526-9119ef4a6a876ff3664b3b9b23ddfcbc.npy +04330267-177fedf455e50b4d352845ab138522d8.npy +02876657-c82bbd1b1a929c7ce8ed8cf0a077ddf7.npy +04256520-25fd91f0cc5c2e30e1c2ef56608a124e.npy +02828884-fb39d112f22db46616462411d4c2b1b9.npy +03790512-3d37db1d974499287395d58407f193ba.npy +04379243-80131db5f6be83b7d7bf6fb68df7f786.npy +03001627-e93649e36377a12050e52c25df21b57b.npy +02958343-feefd0978ed8e256bc050b2495b2b4ff.npy +02828884-4eb44cf234eb74dfcb2a965e75be701c.npy +03325088-5450352c9ce20b61b362845c6edb57fc.npy +02691156-81bfc74dd037d1ea88d58cc5b9d401bb.npy +02828884-6b7e64a23106bc6ad81bfa7b5196f847.npy +03001627-8cb44a50906b827615e7ec87bf4cc5ab.npy +04256520-f6ef2cc4bb31d953a40f4c396e0c7dce.npy +04256520-e09efbe78b2adfc322d06a647cb73a3b.npy +04379243-7205a833bced185c41bad6f6f893aff7.npy +04379243-1c9aa0fdd563da04c397356311cbeea4.npy +02828884-6d9c95a2409a8c90391e4d6c585a697a.npy +03211117-83ceb90b398df731a8b411915b2949d6.npy +03691459-663174c8076b969eff258dbde860ecfe.npy +04256520-45cc71dc2483972e742728b30848ed03.npy +03211117-c8d02bdfb32767648e4cc49dd8a5f1a.npy +04379243-7fda06ada2d897baadab4c26397edfab.npy +04379243-64d243c58e649783002761e7a3ba3bd.npy +03325088-247e144e0babc15d76c18e71fd49c4dc.npy +02992529-48a2000b54f4fc792a56a29c6d979b82.npy +03001627-d5c67068390ece634060d2cb099a78b3.npy +02828884-9dde18e7a5ea2416cb2a965e75be701c.npy +04554684-a428bf705d0b6a5ddf3a1b0d597ce76e.npy +04379243-cec8fab8ad62fe3840f3ac0af6b7e700.npy +04256520-b3b18a2b0bec3bf1593ebeeedbff73b.npy +04401088-49a51e66314253d3f2a0433fb7c53e0f.npy +04090263-2859d1753713558412b38b1d99376c0b.npy +02691156-f3cbfb52ea1c907a850e00840470903a.npy +04530566-933aa8e54e97de9392694c864c93195e.npy +04379243-9f2dbddee73c639ecea003eff0268278.npy +04379243-92c68ae13848ef32c3bd24f986301745.npy +04090263-12a5e976e028409ca67ac8a08d7e171.npy +03691459-6eecf81ba7508617cee3603bd2c54843.npy +04379243-e8502118aeed3381d5b708f09789d978.npy +03337140-98db6cb890a9776f65ec59d478b48347.npy +03710193-8700fb772854d8c2dab143a63ea21a89.npy +03513137-9c5d16afab1cd899d1f50c75142faa8a.npy +03001627-eea2622d5a8ad64bcb23db7a28593905.npy +02958343-e05680db6f028c15bda733a39f84326d.npy +02933112-190cb7264781df604da5feafe6f1c8fc.npy +03325088-b73c4ec843ff090dc36fb70296e45483.npy +04379243-a9e371d1c714f222716641f54c7a54f1.npy +02958343-ba3e00431d584664c0f081c0bea90dfe.npy +03046257-e8c8090792a48c08b045cbdf51c133cd.npy +02691156-59eecc0a983a27a8130cc35407fba74a.npy +04090263-2c9de4575938dc88d1987c07c912c6e1.npy +03001627-48dbd34c00d1a5ccc9daa743e958a401.npy +04256520-6017c8c817937296e1df71e82caa58ae.npy +02691156-157a81baeb10914566cf1b4a8fc3914e.npy +04256520-6e213a2ecc95c30544175b4dddf5be08.npy +02933112-ca15dd33a276b636d1fef881bd33f613.npy +03211117-195ab29b4e0bcdd07b20cb946bceb58f.npy +03325088-97a5a1bd8e59e98ce2f066782346a992.npy +03691459-1cfd7a56b1d59ed837f7fabf76ffe0b0.npy +02924116-9862dbfa48af20f5353941f152341c47.npy +02691156-fc25e0cdcb2ecf1ca2bd098b9203af.npy +02958343-646359acaac0219f4096f51fd3e2ee8f.npy +04379243-7eea0fef45efd698a22a3fbee2fd609e.npy +02828884-5b24beacd0385489a6ca26b5255a8e6.npy +03325088-1fa1f1515365ecb0b362845c6edb57fc.npy +04379243-146f90f6a4d8c7bd142fb08fcc642f29.npy +02691156-c06b54fce5cc4961c9d5e99e50e5e709.npy +04090263-cd50da8bd34f050af27eb335b754fdaa.npy +03001627-60167ae64899f8ae966a40fb39b34846.npy +03691459-c389dd22f9209798f72fe2e3cc67d234.npy +02924116-cb5239d87f4d903b6df42853f67b5836.npy +04530566-ec685f1f4bd71a191bf585548743bf8.npy +02958343-875bc6efc7f33c052e877e82c90c24d.npy +02924116-b2c1a1240442a1edbd2004256abd019f.npy +03642806-fd2f7a1c6eb7a0d4803dd502eefd8dc3.npy +03636649-3ca8da93aff926a4edd822c7d5ea26ed.npy +04379243-5807c27ba3c04612f51f77a6d7299806.npy +03467517-1b65d2e0c0ed78237e1c85c5c15da7fb.npy +02691156-6aeae52e38f892a7e0091ae06332b2d5.npy +03001627-748d7e99a0ed4646f4b6538438a0b930.npy +03001627-8da91a953d645457456cbf78e1e89022.npy +02933112-429488f8be42c9ed73149e0cf45b2c4e.npy +02924116-290c67589cbf5a1e52470de2774d6099.npy +03207941-707e9078bd63a41af7fd77472e77581e.npy +04379243-a6fea71cb6bee0ccf529ce6ea3376441.npy +02828884-b65f1141e4eb2529100a6411eafa7455.npy +04530566-63f170670881b2deaf6320700e3cf173.npy +04530566-b00e1af5a8d0674efe9d6d96542b8ef4.npy +04379243-8b3bae4e65ee0f67caf7718498824d44.npy +03636649-bad4a1e98a6111f7db48c721db3fba4.npy +02958343-235392f8419bb5006a34aa94ca8a3355.npy +04379243-711075229a3bb0fff51f77a6d7299806.npy +04090263-9af23e8759e070ef35d753857de68a9a.npy +04530566-b25e91edf5510306eb2c303a0e0d287b.npy +04256520-73e342d3bef02e923d6e282938a47f9e.npy +02942699-c3e6564fe7c8157ecedd967f62b864ab.npy +04379243-f2797245a220fbf1850622797c13f562.npy +04256520-a17c259d1af349dd45c21ae2e309d69f.npy +02924116-c6861c7c959431979868593c91e945f9.npy +04530566-61142394175b9e2b6a42e03bb7759e0c.npy +04256520-f67714d13805df294b3c42e318f3affc.npy +02691156-3b9241e85d07de6a8b6c3e7b944b34fa.npy +02691156-3e0e8b37400e290125b57604d8b9519f.npy +04530566-bc698a05ff49b6e06d793283e2a4a87e.npy +03001627-5ed72ca90351b0c4d5b24cafb84903c7.npy +02958343-6265f0745d3f40546bcd32c43682e841.npy +02818832-a2499fdc5535875087693c0a016606d4.npy +02691156-18d994c4f8362cfaee9d01b4b18e1b2f.npy +02958343-33211aabfefa14603b05c2ad25b4380f.npy +04379243-b84b06178cb49ee171d0a1a8ffd305f4.npy +04256520-16fd88a99f7d4c857e484225f3bb4a8.npy +04256520-6a2f4e3429093be819fb4103277a6b93.npy +02828884-29aa1d7505e08fb66706998a3e61629.npy +02992529-5e87bca3231cbdf15b5f05be350ae67e.npy +02691156-e812f54386acd072d44f37c9e0fb10d0.npy +03593526-af61c129521b9a36ad56360b1d2e97b8.npy +03624134-7855c181c65e964a7f277d7152b6b3ed.npy +04379243-8af2d1420ac255be490ad276cd2af3a4.npy +02958343-fd3c767468a825ba860800e6696b8284.npy +04379243-ad62637a77b172af3542091189dc62b5.npy +04530566-c746175e0993abc19a6e43b878d5b335.npy +04256520-5d15e6c23f233a13ce60514f9a637ce.npy +02828884-748e447a5f7a698df155d75bbf62b80.npy +03691459-e22ec5ee664f7c172a9eb0f146e94477.npy +03325088-7719e435d30b6aed50da8b99982a3057.npy +02958343-8f7520f908ee54e2391da6d66c78fad2.npy +02958343-6058ad4a6ec4eba46436916a86a90ed7.npy +03001627-c133c2af39e7d169b1a9ec000a076431.npy +03001627-273fe8996937648ac8744f5d8b9af88e.npy +03001627-766d7892fbd7a9f58d6e12c39b2d5023.npy +04379243-3e4cba53909d9bc8455060ebe53aefc2.npy +02958343-61c4db4cd886250f473f10e6caaeca56.npy +03325088-c8b9f478f3b94b3513bcf6712568dadd.npy +02992529-cd74be6a1d8a6cc721844676433a0aca.npy +04379243-782a5262c3d349e3c3bd24f986301745.npy +03691459-ed0f8fdfd9e1182cf83b540214901572.npy +04401088-953a952a18e389e4eb386a4e845c05f5.npy +02691156-24d4c063f7a361bacbc6ff5546f4ec42.npy +02691156-bfcdf2928e854d109b6724d4f3457e3e.npy +02958343-d3869e2527ff032623276041d0efb3cb.npy +04379243-729673ab33a7c9cc4d3a0a56bdd58a7d.npy +02958343-a86655c0ca05c2646d3e11439c6c22c8.npy +03636649-bf792ee1a5570858d0615e6a68ba2d50.npy +02958343-bf493207165e9359492225f5fc55e666.npy +02992529-4b97582ec707108c6ace02f573c40387.npy +02828884-edac7cf37d1d7a42c79156efeb6d05c4.npy +03691459-3fa5d9e396596d36f7d10596716a94c9.npy +02691156-a9b2d531e073113f9d1eb836604648db.npy +02992529-7f6a27f44d8c9f2bbcde31492651e03.npy +04379243-33b727a7c5e984bd377c09d18bd75e8a.npy +03636649-29a1afd3e6c25af71b17743c18fb63dc.npy +04256520-2434dbf29922a0a44cd8f60141ab9d6d.npy +02691156-5459029489f68030590874dcd9dc8481.npy +02958343-fa8ecf7278bb320bb7ecd40416f4e39.npy +04379243-895c87ab1c2e404de7c7920f6a65a54d.npy +02828884-84e95910bf6b0b3bb411c6406cd0f9e7.npy +02958343-174f1a421f652029d577c0ac53e96823.npy +04379243-9f321f05a7808719ab610b0c94236463.npy +04401088-55698d990b8147e33c7b6ed91d531bc.npy +03691459-c7c2dcdb1f3e85dd35cd53a06b1d2317.npy +03337140-533fa6cf9a7e1e724c3aee8e9d3a6ffa.npy +03046257-49aa40472dfb892ac5d70d7dd4a0dae4.npy +04379243-8ba76dfda765f72b7c363db824bff7dc.npy +03001627-4e26eab28703c12bdd5f3f2440a93d21.npy +02828884-644043e43b18d2fb4ae9e8fe36a5d4d7.npy +04379243-3822433e287ad25799e8bf807e902261.npy +02924116-b501b9b43dd02c2beb2c303a0e0d287b.npy +02691156-93e0290ab5eede3a883f7527225435dc.npy +02958343-84dc5b9d1a60419b7cbc6cda01aaca49.npy +02691156-4ed01f44e3e422dff64801ad2940cdd5.npy +02828884-c3ce87b94f493cba4ecb12161a6eb47c.npy +02933112-11224ef64e1702b412e0c474ff07001f.npy +02933112-fe5f6a2aab0091438860c69ebde1e4b8.npy +03636649-caf2efbfc9ebf42ae068fd8aad8767f3.npy +03691459-47f062aeb83f19e1618595b659cf68fe.npy +03001627-8e7f354489bf4d9b65684b1827478535.npy +02828884-991c84609666c015da34af5fa7da2314.npy +04074963-5938818cc2f2cfbe9cb9203a133c0554.npy +04256520-2477014dfd55144ded526a7be77b30e.npy +02691156-c9584d90a1da19f723a665a253ac8cae.npy +03325088-8e912dab210f460778fe949fc1419876.npy +04379243-951a9c85494b53993c2e50348f23d3d.npy +02691156-2dec9e7b1acf88fea8e091cb544689d5.npy +02942699-c802792f388650428341191174307890.npy +02828884-b03c1ad073bf95cde9edcfa70ed557a.npy +04401088-5fefcb474b6dca4b23b380c931ece1e8.npy +03001627-3d67836a3bff5f733aaa67d66207f5e3.npy +03790512-7c34fdccf25e4113d5dde04c96fd8146.npy +03325088-24f5bd8d409c7d89b229726a165222c0.npy +04379243-57afaabf994feb305512673aa47c7e3d.npy +04379243-6358336cbeedb9232d9fe390e23fd20f.npy +04256520-8634968c859b2dba5e4b35ff1ea95f37.npy +03001627-2d0344ee62954b0afc4743bde9e89079.npy +02924116-486ef7a6c13e67522e8c450c92d469f5.npy +02924116-6747a3af99c639e683d931288a9d25a.npy +04090263-315038c85d3e3f4a1a857c47fd0ecdc3.npy +04401088-fe02978cb3b6fcc4cec837e48e8de67.npy +02958343-cce33c56b1c83237c7b48e36e31209b9.npy +03001627-5f8b70c628c7f6fcd4fd21ba7448467e.npy +03211117-3ee0923254671a1ef2bc9da1ba799c60.npy +04379243-5b75e36e302eb2cee9b7ceaf400b2906.npy +03001627-b08dfb07c78a348b19fb4103277a6b93.npy +02933112-a5d193fd45690070b93ba26740e73067.npy +02691156-5e34c340059f5b4b1c97b7d78f1a34d4.npy +03211117-42ad980a4102f1c1bac465483662a51d.npy +02808440-a6c700ba871bb9d7f76e18bed49cf55c.npy +02958343-80ac9cc0d4c9dde3b7a7bc444c2d756b.npy +02828884-8967e65c1541d1874aa7f42ef07f614e.npy +03790512-eb74f2365d6a55c212fa50e85877ced8.npy +04530566-379fa7ba7c753376619ef21bc094a137.npy +04379243-81eea4f86f308c6a589aae130c1f06fb.npy +03001627-b6e662b81c62dc9b688f5a44034a346.npy +03467517-2e2d2d6dbb316502872341b062fa57a9.npy +04379243-43e2a0220f1fbb9cc1bb249ae60b3bdc.npy +02828884-e9491a1e77cb2a65cb6a91bf3956b490.npy +03046257-757fd88d3ddca2403406473757712946.npy +04379243-d67a0b5dfecb565f2197da8dec8488d.npy +03211117-78e3dd96ff1dab94e20f4d2769bff1e6.npy +03001627-7dc1a66d228c8787e39e97231748e33.npy +04468005-e3f9be0bb0da7a23e70da94675b5e3ad.npy +04379243-9ea5a3905313b07e3d752b0785b76136.npy +02958343-2e5ab446d0767e1aa6dd909dc6fc8d4.npy +04379243-5b31b07efaee09fde63a9e8397b31118.npy +04090263-86db029236b5dbafcc34b900bb2492e.npy +02808440-dadeedcb7aeb8344fdbe2bf897d8a820.npy +02691156-7191b4709d5142a1f86c2bd4e090c60d.npy +04379243-28743475c1892193b0097f8288b985a5.npy +04401088-bacbf0d14e0cb5df6a802ef1ce963117.npy +02958343-93a813f96365c108f217b9504689397.npy +03001627-85208e245c49fd72349bb1cbbf9a4206.npy +04090263-4adfca873edc6ad8566f788c330079dc.npy +04256520-20b6d398c5b93a253adc3470b30138f3.npy +04379243-562288b15bd065d4b29ac64be50e118a.npy +03636649-d05b908d82722b5ab15194162f658e87.npy +02691156-4bdb2c4fc6701174ca8607f540cc62ba.npy +03642806-92e6341ab62ce4875c0be177939e290.npy +03001627-ca84b42ab1cfc37be25dfc1bbeae5325.npy +03046257-835f94a1d33ac78bdd7f1cd6f7ae0960.npy +03211117-f4877a34163978f84efc7e7114f1b9c5.npy +03636649-c904c93a0a1739e5f51f77a6d7299806.npy +03001627-cf62f90e75531ac63cf953ab4f77463.npy +02933112-1a46011ef7d2230785b479b317175b55.npy +02747177-872810933ae35485ad5067eac75a07f7.npy +03593526-8c6d7ad2b0674bd61952fef39dab6347.npy +02747177-44ed0531eedc723dfaaa4370fa1ccec.npy +04379243-eeaa44341a57c0cfb9531c981c83e1.npy +02946921-203c5e929d588d07c6754428123c8a7b.npy +03001627-36a2d17d63dc83f983c05814b11dc86.npy +02828884-6a5ba469761d03c0d60ded25865ac76b.npy +02801938-44ed0531eedc723dfaaa4370fa1ccec.npy +04530566-5f2ddca70687dd3062ba640dde834b4c.npy +04330267-40c7d35e40916b3d9c50c94ef954cbe9.npy +02958343-444829c02bec2ede60d2daa56695faba.npy +03790512-fb5d82c273bdad39359c7139c3be4ec1.npy +03001627-738395f54b301d80b1f5d603f931c1aa.npy +04379243-46cdb3dd8b6c460d473f10e6caaeca56.npy +04379243-2873620cf8be87ec798432661977bc1.npy +02691156-54984229a5e704f2941d71475449eb25.npy +02808440-a5da160ffe4b697e35c5b7b901a05c6e.npy +04256520-660df170c4337cda35836c728d324152.npy +03001627-7846afaf010913e4110b42f6d9481f5b.npy +03513137-cfd3bb444cb730458636fc327bbb2619.npy +03001627-e84d39ce475415399f165f18603a28b1.npy +02958343-d0ea101dad5bc464a134736201a79843.npy +02876657-b6261066a2e8e4212c528d33bca1ac2.npy +02871439-61ebec53da40801f99e8bf807e902261.npy +03001627-3f04a08d840c0a9c18b14db3b83de9ff.npy +04379243-d37205936d372513ff868cd4e441fef3.npy +04530566-b71deabf89e42df5cb167b89a3c3ef9a.npy +04379243-d013cc09fdad8ecca282c4787019214e.npy +03001627-977b3355b3f93b09e6fe3612af521500.npy +03046257-56f3829b744dc836158322a6470db5f7.npy +03593526-636eea1d5a7b3c61fdbe2bf897d8a820.npy +03325088-a1bf1c47f2d36f71b362845c6edb57fc.npy +02958343-2a9b4308929f91a6e1007bcfcf09901.npy +04530566-11e04ef8f037194919869180453a248.npy +04379243-9913e76fbe2c438f4bb836860bc1cca3.npy +04379243-7ad23def902ea4f37b7a2c2624e46d0a.npy +04530566-859daa33e58191bee2d4c157e5bf1dde.npy +04379243-11520534ea9a889c7d36177f6cb74069.npy +02691156-d8a43017132c210cc1006ed55bc1a3fc.npy +04379243-8eb85236a450db4c44e1d3da2eab581a.npy +02958343-5f78048536beb320afe1d4530f4c6e24.npy +03325088-78e4f87c3e5580b276c18e71fd49c4dc.npy +04379243-1509a8710d2fce3c4785a5d3b6c47521.npy +04379243-fece36426ea77b92a7bfc1660a1e18f0.npy +03001627-4e9d664144f4249d8957917d005717e7.npy +02691156-369244d49f8f1308b858e64ff0fa8db3.npy +03467517-667746d97ffd439868ef8f8a433fc787.npy +04379243-81514408605063ccd7be956e59a3bd7a.npy +03046257-d3ee26da2bf297d9815b2b467e8e2eac.npy +03691459-10d03876d94ec5f4e7670ea63e6cabfd.npy +04379243-2fdc21532b09d7e37f768772b7a990fa.npy +02958343-e6846796e15020e02bc9f17412005422.npy +03761084-6db8ab6c9693a340575f4e5007488531.npy +02691156-8a25b5ee4421f96a349a1add3c9c4a87.npy +03642806-d2eabcc071cec6f420bec9be02f008ca.npy +03636649-c816540b4e0eacd57697d9c3588bbfc5.npy +04379243-67a9dcc974fc402552d23bb2388b1b0d.npy +02924116-458aac785c7ef79455467fd13bb5a6b3.npy +03001627-27c476533e66bc04b21bc3cf138f79e.npy +04379243-33e59bac5a2a5c5e8300cbd55c34dfc.npy +04090263-60cd2f3d326475e829c6b4b73d88655.npy +02958343-ec5c003421112630f53148c8cdf6fc9b.npy +03636649-495af808806f1727a753b1b88fff4abb.npy +03593526-1252b0fc818969ebca2ed12df13a916a.npy +03467517-3ad4c0cc3aab8cf31377689fa4e4b2d6.npy +04379243-d045064064381237e9ada1586a8c9364.npy +03691459-6b9dd73a65dd50a71ad88f716ea80910.npy +03325088-6f954843bec713b6c36fb70296e45483.npy +04256520-53eaace9bb8bb34ab4fa97f642d1a681.npy +04468005-30892de05b7136a6e810c01b1498aa2b.npy +04379243-be9467a2641fb58330bbb59b54a585de.npy +03001627-762e86b38d1428fe78e6c2bcdf90770f.npy +04256520-c9c0132c09ca16e8599dcc439b161a52.npy +04379243-e7580c72525b4bb1cc786970133d7717.npy +02818832-4954953090ca7442527e7f2c027f7469.npy +02924116-2a46fe04fdd20bfdbda733a39f84326d.npy +03636649-e3ee6b31e54e95b7d42b9650f19dd425.npy +02691156-9ac7fb5963ae673f7d64cad20089f027.npy +03642806-4573c3dc7525a4754145b5f47fac09a5.npy +03001627-676287fd6b02428f2fe023c7dc3e5231.npy +03691459-e62dd51d47ec4e2ec29f84f96a7e29f.npy +03636649-9534bb19e66fa5cbfcf6007208e5f114.npy +04090263-6529b6134cafc299d43bb185feff0470.npy +03636649-594b2fcea3d15eb4fcb8d8c6d4df8143.npy +02958343-9eaafc3581357b05d52b599fafc842f.npy +03001627-a554d5e0eee3109762411d0498399c28.npy +03593526-39a8179c80a38ee130612f5c0ef21eb8.npy +04379243-fd7f26ea3a1d1cfab092f06f28d82d71.npy +02691156-8c2d5c6dd599a5bb68c7efc443fd2354.npy +03001627-48015ffd76a443f89f8c3d2002c77ddb.npy +04379243-564385b1081e9ab760eb699207aa149d.npy +02773838-8ea3fa037107ec737426c116c412c132.npy +02691156-a359cd0297d4e655a871065f9ebc6ac5.npy +02958343-554bfeff3c44a3d6425b2c354eccabaf.npy +03337140-72bbf19840933991bdf5f95bea7759e5.npy +03467517-6fdbbb1a44f2ac2854b87c21f44ed61a.npy +02691156-e79e9e1c8dae48888ee1ba57de3d34e0.npy +03046257-637237e978d5168f9751189c905e470.npy +03467517-28ba8477fe3db939d57700c05b1862d8.npy +02828884-b6e3891b9a761300b77f0c4f1c150c3f.npy +04379243-9e5973d8a4ac051f6e71174964d90e49.npy +03001627-8bb74c3e07557ba9177f2a3a0c71fbcd.npy +02958343-f60955dcc1d1c48687dc1da2515df8f7.npy +03001627-bb9efb4912a018b3c329e2758ab09ecb.npy +02933112-8f453f19fa9396a7824662341ce2b233.npy +02691156-1e44b99c8de5eb01ebc54ed98d6399b2.npy +04379243-b2eb5e56fb8342f81c25d54737ed5c8e.npy +04256520-14016326133a68c72897bf4febc9c106.npy +02843684-689f228f64564e663599338e3538d2bd.npy +03948459-e9d193e6c5ae7a4e265b6d46c677f2ac.npy +03797390-1ea9ea99ac8ed233bf355ac8109b9988.npy +04256520-781a7cb1d7f9347d7ec5a98b3b8c425f.npy +04379243-a0ccae355918b63714038d588fd1342f.npy +02933112-1d7b35cda1bbd2e6eb1f243bab39fb29.npy +04379243-85b930a031d9036481aaf17ac7662991.npy +02828884-9f27ed5d7877a38fd46c340938e2ff1c.npy +03513137-7a0772798520e9e141bb12648ac801b9.npy +02808440-6be2b6d4aa8124a34e61c48313846944.npy +02924116-ea08e81401c6e458490ad276cd2af3a4.npy +02691156-125417c3fa9bc1b130f57e42c77d3894.npy +03691459-81b711a75b8781956faee4308b49b522.npy +03001627-7932489d9aa9fb58492d9da2668ec34c.npy +02691156-1ea7a36e4f353416fe1f6e05091d5d9.npy +02958343-cba0b54cd104c411e9d8921ebe6d5b8e.npy +04256520-4c49cab86dc3ffd2c84c076312b543ae.npy +03001627-8cfbde91dc175e2ea54b9afa882a89ed.npy +02933112-8f7a277ae05da76c1bb088904f7cb154.npy +04090263-3e5711b79fd4876a4ef2a27f51a6e36c.npy +03948459-1115b4018238385ef1714763a5a5ab.npy +04401088-313e9b124e421a4efa9922db9b6aab31.npy +03001627-5ab67b30e17a2ed1c862eec8232fff1e.npy +02691156-fb01f6b428d094ad3ec83bd6bef75c92.npy +04530566-b820d42d6b9a08a03cf31426f0438400.npy +03046257-d86dcc32261d58424b3c42e318f3affc.npy +03085013-f6517b0bad40b72d36871b478a4420ba.npy +04401088-f48cb1a242e99745ab905891b6fa1a.npy +02958343-e15f9acabfa0adc5470d3ca356fc4190.npy +03938244-75c1215326a32653de03ab2a27ba7531.npy +04401088-3921288228020482b305960cf7a7281f.npy +03001627-72beb9225a841cef24367084627d607d.npy +03001627-48fe63616e70f84778ae896933c670d1.npy +04379243-167559b98bf6139712d9440c7a73ec3c.npy +03001627-8b5f8b83715a378e473f10e6caaeca56.npy +04379243-d14bcc93169f80d9b2d5d82056287083.npy +04256520-3a503e0e9b48a8925ff61a3a2a0e2484.npy +03085013-1e11af6fa598cd6960113b959388060d.npy +03001627-36f85b1709a62c406daafc9da8386a39.npy +02958343-d679b2dd7a7d6b1da71ed5958a35c6.npy +04401088-f73493b7c8a78000b594bbf2c494ab81.npy +04225987-fd3627deb2476b0f1f942c57ac0e8959.npy +02933112-9bf9e8d47f7b996263d977b06bbd429d.npy +03636649-fdc4b403601fedf955b7716fb9f91d35.npy +02828884-e56b95381904bfd08ccde000e771fc1a.npy +04379243-ab8735a26c5c9ea4f8574543281e850f.npy +02942699-89f0e0da4747aad1172ac9cfeff21994.npy +02818832-fb9019af9de69ffaf50f16ba773dd73d.npy +03948459-efb488715a03085b9f433921788191f3.npy +03593526-1d7868b4ad0913bf9f6b966b784c8347.npy +03624134-bcd7ed830358dbd6d58ea69ee1ced10e.npy +03467517-16bc13ee237ebeb38460585fe283a1c9.npy +02958343-1f191e0327ce54474cdd04162f008888.npy +02942699-509017601d92a7d1db286a46dfc37518.npy +03001627-9061324684c39682c2c449c0c0579ec3.npy +04256520-4c92e530e76f4ee3febad4f49b26ec52.npy +03624134-342f17b5c8b892311209554d4cff7188.npy +03624134-cb188764e239f18d4282aa337cbc8f81.npy +02808440-4d3a9133a7297ff54f0ef2e216a06871.npy +02691156-3e7e119508f0abf935fc197bbabcd5bd.npy +02691156-21a1049ee5b7f531bc0909d98a1ff2b4.npy +03797390-cf777e14ca2c7a19b4aad3cc5ce7ee8.npy +04256520-279150abc1b0b0b75369e32fb818f337.npy +04256520-fdca3e183b3d1eca45e6e5503635ab1.npy +03636649-dbc50a84c8d24f9168c981036afdae64.npy +04379243-1299579419252fa954b02959579aa6bb.npy +02876657-d45bf1487b41d2f630612f5c0ef21eb8.npy +04379243-3f756d8d35b51ad629e4b5aa807bb4e7.npy +03513137-48b7dafda49b9175365930cae725a1a.npy +02691156-da9d111e1175d318bbf3143b1cb6076a.npy +02691156-e25e3dc95243a92c59bcb260e54d3785.npy +03001627-216821d05f00b1ccc3bd24f986301745.npy +03710193-8787c825338116b2ac6beb6ececaf6e1.npy +02691156-7ecb807e2270606619ba010ddb4974fe.npy +02958343-2ccc8183090b97cb21a66e8dfcce514a.npy +03991062-b2b0dd16870742a2fc41e59f3518733.npy +02958343-44f30f4c65c3142a16abce8cb03e7794.npy +03001627-e867483a25b070ed89ccdb4a5b6b972a.npy +04379243-c5b224f6fcdbd7e655f46d55537192b6.npy +02958343-e57092f6c51ed37dafa781871c8b9ebb.npy +03467517-a64761b5f748cc61082f2ea630bf69e.npy +04256520-a0baf84e4bde88691912372ddaeb001.npy +03624134-d61a5fa6dc3f703613abf93d1c879c43.npy +04401088-2c32c1b5d13074431c1943a82a09125f.npy +04530566-325c2da58c641c12e3bdba9430565083.npy +04256520-4444828846fc38269fbbbda5e1d9195c.npy +02958343-b782800ed15ae74c6227cba038bf7c95.npy +03046257-6bd4036a2ef142fc956e5f06e8cf4db.npy +04379243-df3f7ccdb375675fb145a08fb49c17fc.npy +02691156-aad69c419b27d6744d8e7d3c15c98c3b.npy +02876657-b45d6cadaba5b6a72d20e9f11baa5f8f.npy +03513137-f232d07e98fae2d4eeb425ad8cf9eedc.npy +04090263-29f33014b958d37e6d25219b6c577d3f.npy +04379243-8797234d59d03951bcc69f56814897a1.npy +03691459-7a48d550ef85f41d4873a2cc06a4fb6.npy +02933112-74c058f9f24fbb524692707833167ca3.npy +02691156-3cab1ffcff8b84cbcad035c2ab458.npy +02808440-d8ee3cc88f58ef06a39450bfd028c5f0.npy +03761084-faf8ef1f6f78b75bdef92a6dd2a4a6ef.npy +03001627-4f1f4c4d1b2f6ac3cf004563556ddb36.npy +04256520-8dd277fd02903b82bc0e720bd48e2c3.npy +02958343-db86af2f9e7669559ea4d0696ca601de.npy +02828884-84cd6e96a464894af132460d3f8b116.npy +04090263-77dbed07aef42a5e3b9e9f1cae8061dd.npy +02880940-9c7edf31042fea84df95dda4222cd1bf.npy +02924116-6cc0a9c53066efae80288501d9901d7b.npy +03001627-548ab6b6e8b2dc505ff61a3a2a0e2484.npy +03948459-1e83ef6ed5d0b78b7efb854782e23566.npy +02958343-ee5839537440f8b6f2e4b4084cb7a07d.npy +04090263-5afd33d495b111449a2ee232a197081e.npy +04379243-6ca761172d2c1ba3ce522e6dda26fb51.npy +02876657-829ad86e645d11b1bcbe24a1993b1795.npy +02691156-70bb20cf86fe6afe76b85a01edd4a109.npy +02933112-1aeff9aef2610ee1c59350d819542ec7.npy +04530566-3bd4a80ef718b9c9a069f11e22e91bb4.npy +03991062-8c278785a66bd82ababc8956356bfae7.npy +03928116-66428302f0c879c068661782af60b711.npy +02808440-210e770d7cf45629b362845c6edb57fc.npy +03636649-3a3d292307c4831f4dc0ed4c2f72c4cf.npy +02828884-2b065fc9d62f1540ad5067eac75a07f7.npy +02871439-b12a523931d15b49a169b9ecd9e046dc.npy +02691156-ba0f83a82b18613d2350d07acbcc057a.npy +02691156-1169d987dbbce76775f4ea0b85a53249.npy +04256520-970aaae286331b9cfdef1c01cbd4ae0c.npy +04530566-485f63613911c93fd316c98a55307c24.npy +04090263-5df501ece93bd3f522e2c8abc98c5f41.npy +02801938-3e88bbe0b7f7ab5a36b0f2a1430e993a.npy +04090263-d33dd32b628e46f1d483df64f44884fa.npy +02828884-db8f61eb5dab7b26b7710a2fb1bf7a26.npy +04256520-3746c2c38faaec395304a08899f58b0b.npy +03991062-4bfda925e35d32df2f4930ba29aa525b.npy +02828884-f98acd1dbe15f3c02056b4bd5d870b47.npy +03001627-49795a9ebd9a9c6d2c697f0a1454869.npy +04256520-a39fcabef17deeaf593ebeeedbff73b.npy +02828884-496f1d6cdd0a0aa247b74f4d1238a1fd.npy +04256520-a4c8e8816a1c5f54e6e3ac4cbdf2e092.npy +02691156-e5fe5ed2cdc8b11d62b600da24e0965.npy +04256520-6c6cd4a17f142fffc3c1d36485e9888e.npy +04379243-bb93a65aa5768c557b9c6deef486a7d8.npy +03207941-b93e45ceb3030c473321831d2245cf06.npy +04256520-9d56b14e39f4c1f9ff6eb780c82e5ec7.npy +02992529-c3e18e5d0f7a8709e41b17b375798648.npy +03001627-794e80fd66c833917d20e6f91e9b2f9.npy +02691156-80770c90ba84524e825b20c2472ad90a.npy +02958343-c911f8a7084e7929593b8de380af24a3.npy +02691156-3bff0d84311470a357f53fe209e96fca.npy +03691459-5679f86d9eb0bd1ed4ab0eed66631cfe.npy +02958343-21cb55aae53e3eb351a95aaa6caba1d3.npy +02808440-5b8badaa652f4363210c439c61dd9b9e.npy +02958343-f16194da236b7c595264a3f45260d821.npy +03325088-eb5a55c6f9887aceb3425db9d50d5dff.npy +04379243-cd94233033b1d958ef2438b4b778b7f8.npy +03001627-42140baad25c8598baa1a4ff2c45ffc9.npy +04090263-9384db12f13af3e4e1abf5082bc04e75.npy +02691156-8d49b7496a2575d5146e44cc99f07c52.npy +03636649-b66524f44170023ff7248d9dbed7a7b8.npy +03046257-7f5f3d2526d1c5a46463df620b7b4cbc.npy +03001627-9dc77fb24cb14e5b3abfc4d0a5688916.npy +03790512-346e30470cfbabdd7395d58407f193ba.npy +02691156-8c11ef88dd944d00fca1f1143bb6bc17.npy +04379243-8bd8776f65913f17b3c03e06e3a5c3f8.npy +02958343-8fc220461ea512f3abeba927b56dd398.npy +02933112-919591b27262702ad0b36851d61b6fca.npy +03211117-4736b46f6cb97d091e02c9947dc6e279.npy +04379243-3ce930bb150aef8a69fb38085fbc320c.npy +02691156-2bdb44eece3409a5a18e0889038e4fb6.npy +02843684-7d5679fa05d7ee982e1d0f368aa4d2b6.npy +02876657-cb3ff04a607ea9651b22d29e47ec3f2.npy +02828884-c2c788ec4dc9f467d85a7a4d55e9b869.npy +03001627-ff529b9ad2d5c6abf7e98086e1ca9511.npy +04379243-d064b468c3cf683cedf48f9fa39262b.npy +03001627-acef669b784a4fec1b17743c18fb63dc.npy +04090263-aa21e208420cd4c2202be79d8b285c1e.npy +04256520-948923ab76b8d9efee7d178666aae23d.npy +04256520-187386c46e9fb3a44b3c42e318f3affc.npy +04530566-fdd7433470c31c8b5332ddd5fe4d4fe0.npy +03001627-5b68a6c2baf0ad61d0de9c949c366777.npy +03636649-a524e5a1d81df32b68b4a15ea963e059.npy +04379243-8ee93ff23d882efef3eaa8afef8adb8d.npy +04379243-b063b55df11f5df434b168be15357fd0.npy +02992529-ebb6035bab99c3e221844676433a0aca.npy +03001627-8ec95f15623085a7b11ae648ea92233.npy +03624134-1943c87f92ac76e112cad8be168fe72d.npy +02924116-3b7f02cfc5be11825c91439f98ea327b.npy +02876657-2f4cf418cb91949d38fc23bb1b265fa7.npy +03991062-a537c640764baf41ffc6e457221b9271.npy +03001627-a248417b6ba82801610c2a68437007d6.npy +03001627-eb8073ac89cf7b4181f667e2a25e0619.npy +02924116-fcb54368287c9e10602b8b650088ca6c.npy +04256520-7061f5384074da6d6f37a8be59c15bbb.npy +04090263-61a502275b50f6624a38706cd8ac54a1.npy +02933112-a248de70fda12c5af27383fc5a5a711c.npy +03001627-6897c2665267cca39eea64ae4d2b4158.npy +04468005-9130d6c4b0823dacc9de7b195ccfa970.npy +04379243-dc0e0beba650c0b78bc6f322a9608b07.npy +03636649-7d77f1dd8bcf114ab71c4c06094146e8.npy +03001627-106a0dbaead5066519fb4103277a6b93.npy +04530566-2a9df36f9327beb27244f3b2d7f5074d.npy +02843684-6918606915c91f0ec5c86021644af7b5.npy +02992529-bf11938460e160c78190e4bafebe046b.npy +03593526-488139f06d9905d830ffab76baff35a5.npy +02828884-10db917982072df1739680f4e31f35e0.npy +03337140-dbfffa51bd4f094353227dcd0d547ba6.npy +04090263-cced6c0c2bd60368b0f24bb611f821a8.npy +03001627-1512e3c41de7a461e10a48f2bbb9bef4.npy +03001627-5932d26671d104d76370a012706ac174.npy +04401088-e8508eef82fb9163a1288f74f9304471.npy +03001627-730fc3ae87640d952c528d33bca1ac2.npy +02992529-dea7ce7ab01c08dfd4ea3f4c41b1b9bb.npy +02691156-b552a6155c5b340e70828dc2c11733e1.npy +03790512-3fd1bff496b369f71765540024eb9fef.npy +02691156-1e358e70c047687a1a8831797284b67.npy +04379243-bba5ce8555c8fa89ba18ade30e563d37.npy +02942699-fd058128095abf343ce579773d34f5bf.npy +02828884-3c2ffb35d0b3d831e1aab65fbcc9b689.npy +03001627-3d7ebe5de86294b3f6bcd046624c43c9.npy +04090263-89f53c736eabcca966c0c88d96ba938f.npy +02818832-1347959af4df977a15dd7d7985e749c1.npy +04256520-9b94f7822f3d73e84b509f4ddcfa8ca1.npy +04090263-fb11e17c9dd72d6851cfdb4c9f126c12.npy +02828884-554a52dd42ce558bd2b12aa6a0f050b3.npy +04379243-a4473d9c69324b492c026fed19c0d206.npy +03001627-9ecd81b505ac3a175634c21965ee6bab.npy +02691156-563cef4df464ddb1e153dd90dac45a6d.npy +03001627-89133468bce0e63f8101accd22c701b9.npy +03691459-a4ffce648faf8349e651a075b3dd0597.npy +02958343-10247b51a42b41603ffe0e5069bf1eb5.npy +04090263-1c0d3cbd1bacfa815f8d7780d59bb4ae.npy +03001627-37b432326fecc8a1327289c00b6dc9ca.npy +04256520-3e2cd7495af88fe352e393d25dabbb72.npy +03325088-efd013235615a4924c62bee40dcdc539.npy +02933112-27e65f34c3b8dd7f490ad276cd2af3a4.npy +04379243-3edc519c38938ee8d42b9650f19dd425.npy +03001627-9c103621101bcf9919fb4103277a6b93.npy +03001627-670b6b7d3fe6e4a77c5a5393686fdcfc.npy +02958343-4c3b9ecbafc80b9cd485372bb746f3c7.npy +03001627-d5bd619acad1bed3d2b12aa6a0f050b3.npy +02871439-225da2a2b7a461e349edb0f98d2a2a29.npy +03691459-3ff725e1e30e4ed6a939d6b77e949639.npy +02933112-69544db102786237f51f77a6d7299806.npy +03001627-3ffd794e5100258483bc207d8a5912e3.npy +02691156-4e1dfdfdd417479f49e1f7e01fe2ed1.npy +04530566-5ecf8b2c217b840fef5e991e1c32e94a.npy +03001627-d81327c591d1a709377b9297f3055210.npy +03636649-81e0c3b0d851492fb79ee87044437bbc.npy +03001627-331f49270df51b2e5bfcb9d3e84d74f0.npy +03046257-8fab6c1e294c7b936e72fdd3e26969d4.npy +03211117-f2a27af5dba2217a38a57abd4646e319.npy +03001627-42db4f765f4e6be414038d588fd1342f.npy +02828884-21409db44ac9db8b6f1234a0997684f.npy +02691156-2b1a867569f9f61a54eefcdc602d4520.npy +03636649-367546484916da6275225719b7a8b341.npy +03948459-2dbd07826cb984cde687f35a3b96a31.npy +03001627-10d5c2f88b60bbf5febad4f49b26ec52.npy +02691156-a75ab6e99a3542eb203936772104a82d.npy +02828884-ad9f6cdc0cab11986bcd8c7601df5d35.npy +03691459-3986913c6dc63598d2e26510f3f5390c.npy +04379243-3411daa955306811d93768e7b9b1eabf.npy +03046257-2277c1146f943ec8a5f9d52c12457194.npy +04530566-c172ec6226c1374c43a8324aee7340e.npy +02992529-4bef48f1c1b4a40fbdeec9c43546255e.npy +02992529-e1effe88e974292f8ba7bc4a733e1db9.npy +04401088-18dc34a116734b43bfd324d8acaeb3f2.npy +04401088-de48276b397bfbbe8fc27711a3d87327.npy +03790512-30968c53e0d37b6448c90b3a2fec4b8.npy +02808440-d917f63efd341a0f54d7082b34825ef0.npy +03636649-7bebdd742342ba93febad4f49b26ec52.npy +04379243-e97546c24cad95ee9eea323f522c6486.npy +04379243-525d48d65079b2003f222a37719e9945.npy +03636649-88ea703e063e715d6770da39e2737f95.npy +03001627-8709db708ec617ec8b5d4279936d177a.npy +03991062-312f18959d1a04edf9aec59741c69cf7.npy +03211117-217e2634c55f240c18533b168bff8839.npy +03001627-2d51bd678668a0f182db9fca4b68095.npy +02828884-c0e755071b467ac433faf2dd5a7ff771.npy +04379243-941c65a25cef70c184edd435e02f1ecb.npy +03593526-306e447225c6976082db9fca4b68095.npy +03691459-d8fe44ea5aac77504d0c24eb0094dc21.npy +04256520-40dccfef363dd1474b3c42e318f3affc.npy +04256520-ef2d1c27124c41e06bb6bc0db07c71e8.npy +02691156-46791426a5b92fed6cc9876a2c35084c.npy +02691156-7934ca36e240e91d5e9e2656aff7dd5b.npy +04401088-2601fb1cdef9d37223d5a55215ee8f43.npy +02808440-5703aca738f8d92b44221bef0fa3c36b.npy +03948459-59849eb8aabd97a189e70f2b8644e333.npy +03211117-5e70a62a7a1bdac5590b59440deecfa9.npy +03948459-2f2ee52394a53c74bdd651b07eb299e.npy +03691459-e75c0fb00d2b70ef1aadbcf355bd688f.npy +03636649-1dc135b611b2f4b2fcb8d8c6d4df8143.npy +02946921-d53fd8769ff53b9a2daf5369a15791ca.npy +03636649-1bb78fe58e75596d9f42325587eab087.npy +04379243-40fa6161e7f921f6738e43095496b061.npy +04530566-b0ef1a0332a50ad1ae4c18c4a7d1a8bd.npy +04379243-857d1ef816b8409fb20aa91e9e90c311.npy +02691156-35fcf4cfd91d7cb3e1211756a8e887aa.npy +03001627-9c7a028edc97dcbc3012f749207726db.npy +03001627-5141e8716b98a16d632786b910371d31.npy +02691156-f9209166fc259d8885e96081cfe0563b.npy +03761084-db63e48b9a308d9efa80fb391ee7ccee.npy +03636649-6c5d68e495c1f0a4d42b9650f19dd425.npy +04256520-e91742c726572352593ebeeedbff73b.npy +04379243-f6474c0704d2198278696f3c9c5b8290.npy +03991062-7ade1ebc752ac3a1713f2e93cbeac35d.npy +03467517-442d447797c93b4769da8e7f9a803d12.npy +04379243-bc44413ddfc3f861c5f48f9175316bec.npy +04379243-36a6d851dbe02410ad16260d4d73b56.npy +03928116-3d0e93c7aeb06cfccb349a60fd15aa15.npy +02691156-e31da3ac74fa3c0c23db3adbb2f1dce.npy +02828884-715e78fa6ac13a5ba5d322186fc10e9d.npy +02958343-1d82316d98f620513b86a9df4269733.npy +04256520-83d48b9accecd4bae7200b78e3310827.npy +04090263-8cfac69c394c3cf8de423072102e0bc5.npy +03691459-d4ae1449bdee448b1ab68128992ea30.npy +04256520-de431e15a30f57f27d5681734ecfe522.npy +03337140-78005cd4b4389fb73b59eeb47ee49193.npy +02933112-a5b0aa0232ecc6dbd2f1945599cd5176.npy +03467517-2b26ca6b597b39464804bd5c9b82ce7.npy +04379243-984ccfa5aa5c87334187eeeb0dea4986.npy +04379243-4c4c719ac4b61d8f812c9aaa38f9a422.npy +03636649-e9a9f966236acafab48ae76bc6e76e1.npy +04401088-18bab729642c42631308c95c9c0fcafc.npy +03948459-4421883492edac988075e9c7f3d235af.npy +04401088-3d5d7e610fc235cbcce71a7ef3de6f04.npy +04530566-5aac718c51fc73ca00223dcc18ecf69.npy +02992529-aef45c975ed647778768dbb598f40c93.npy +04256520-55f6500b52310f26352ecf815a233abb.npy +02958343-cb19594e73992a3d51008e496c6cfd2e.npy +03001627-a8febf7ef6ce1d8cf7d0fb681a992ad6.npy +03001627-8ade914cd21b6e49656f29b05c68d39f.npy +03797390-1be6b2c84cdab826c043c2d07bb83fc8.npy +03948459-d1cc54762432fd058a2c998c0df41abe.npy +03001627-fbee8c9e5b8c0c19492d9da2668ec34c.npy +03991062-48862d7ed8b28f5425ebd1cd0b422e32.npy +04530566-ee09bd0664e0a02292b9fcc49a614e2b.npy +03001627-587ee5822bb56bd07b11ae648ea92233.npy +04379243-712167f9036fbfd050e7fa8e7f4c04f7.npy +02691156-30bfb515f027be9a4642ec4b6f68a.npy +04379243-c9a9feb520968bc79ccce4c6d5bb195f.npy +03624134-906b20dc0a5a5022714112b147c95c8b.npy +02958343-8fac42d0e74f5b454ca84d60642ec7e8.npy +04256520-40f968fe1a3442acfebad4f49b26ec52.npy +03948459-1374e4af8a3ed46ea6766282ea8c438f.npy +03790512-f1879331710ab83ca7e3c21092c26d09.npy +04379243-ac424c33c6fc302355f46d55537192b6.npy +04256520-6c26b5608557f3e8bb41d1ff31a800de.npy +02933112-720ee748eb25f010c59350d819542ec7.npy +04554684-1ab22863c5f183eab00a4eba25ea081.npy +04256520-59959eb5b4cd9fd15e0ae65e074d3ee1.npy +03001627-2031dca3aaeff940f7628281ecb18112.npy +04379243-cbd789375190fd62f3d2cb60d3f3bab.npy +03325088-d72e5aa3ab8bb33ea82a83c21accafdf.npy +02933112-534d0386ab0bb650ae96150e4aa362f9.npy +04256520-fe652e6e444a8b827f06bb1a83bb6426.npy +04004475-37a4e11b0d449a0dd8f9dd7647048a0c.npy +03691459-d5bca27bf05ac5c92e8dbf40bb4c181d.npy +02808440-24ade9db94db6f22b50d0c6a0c254040.npy +04379243-fe2aee5ff66e4fe8d5f95109c85d2816.npy +03001627-196b9e195ccd4a0de03ab2a27ba7531.npy +04090263-4cdfe4029f51c3b16314c3b6a3a65519.npy +04530566-f5dcf3213002301ee4326375f53c1686.npy +04379243-765786fb271e394a204812d6a020ec9b.npy +04379243-36e167a2c51751a630bbd4cddd04c77b.npy +04256520-43c435a4a10d90204d724d9ce5af6d8e.npy +04090263-a0361a353c93899fbe35b76ae96c4b7d.npy +02958343-133b51a2dcecd83c7c3c6f82a395b347.npy +02933112-1257abde355da7ebc59350d819542ec7.npy +02958343-30776fb35aa99150ee3dd0c47654345b.npy +02871439-79f81b259e597d168e6da51641e48238.npy +03001627-1bec15f362b641ca7350b1b2f753f3a2.npy +02691156-54711bb9127ddf7ef412783097373bdc.npy +04090263-8cff3ca8a9a250272472dec3b03e0eb.npy +02691156-4a15b999378e1831dee83316225be271.npy +03636649-7f1a429b9df0dee97c36714e9fbbc038.npy +04379243-96ef5cd61c49b9ebdd50ab7b10e346f.npy +04379243-c876b151a22b59a24702663c3b3faf8f.npy +03001627-a32e0ecf12641f34515e5383285f6afd.npy +02801938-91b15dd98a6320afc26651d9d35b77ca.npy +02691156-8bfcf5618f2d169c9a6e43b878d5b335.npy +04379243-b4ef1de99422b08768661782af60b711.npy +02924116-7905d83af08a0ca6dafc1d33c05cbcf8.npy +02691156-f47c5c54c4e49f62e0a768dae1badf69.npy +04460130-b13143d5f71e38d24738aee9841818fe.npy +04379243-3942f02501161134c3bd24f986301745.npy +02691156-f691f2409e006d33f412783097373bdc.npy +03211117-dab9064d7c98acaec5aa65dab0a56ab7.npy +03001627-749c3d0d59bf7aface4f274577283b16.npy +02880940-2d2c419136447fe667964ba700cd97f5.npy +03211117-5c53dd3bab676b6444ac2f2630483b52.npy +02691156-c1b9934ddbf4f29e77fd7318510b8627.npy +04379243-b286f1a5450d3958c5da39cd0403824.npy +02808440-7a9c46a3a33c7f5b15c4530387bfd.npy +03991062-a3223c8dd57ff46e1118b641f14b480d.npy +02958343-535f244d5b6043e8cbc76a30015552a.npy +04401088-4f2b1a13f06a85961138452c33de4a3d.npy +03001627-6072a4739c12979baa69dfdc5532bb13.npy +03001627-f9f55661e6437920c5a208307819a3a1.npy +02958343-18e16129375e723e6f8f8c736fcc7940.npy +02992529-57632112a9128a16a82783081c89c0aa.npy +04379243-adabe7da527cc52983572753b9298b2b.npy +03691459-f000edc1cfdeda11bee0494534c13f8c.npy +02691156-2f576be042897eae38f859e2bc79169c.npy +02958343-b7909c8d862ac27a82c3507e44bb5d92.npy +02828884-4e1acb893cafc1ea29c39f613cc72411.npy +04530566-8595fde74bf250a5d9fd1bb6b75d9865.npy +04401088-b8415769dc1bc92821844676433a0aca.npy +04256520-1843c388615d12dacb16624e184454c.npy +02828884-f2bad48085f087dac95c21b3fa5ebf36.npy +03001627-b2dc781aae692b2555182f299fe41fdc.npy +04379243-8f48ccd17a15baf5ce01c07526cf2aa4.npy +02958343-72502c40fc59b62f4fb68b983a4df738.npy +04256520-6131018e5caaedb87980e3c69ea07675.npy +03001627-f5e5ad69111b96646d6e68ce9f2601c6.npy +04090263-e2d4ef975cbfe84bd9d2bbf707e9704b.npy +03624134-15f5527e669eebfeeb7c476925d02aa.npy +03001627-8ad1db95b5b9d60136d9cfd13835101.npy +04090263-f31b23b6dd65d8ed8edead259832feba.npy +03001627-26a5761e22185ab367d783b4714d4324.npy +04379243-9614faa3e0472656b988865f09908beb.npy +03691459-b209054be0f71cfdf398d0c5832df00e.npy +03636649-fa853b92d9a5cb66168e1d639d85c126.npy +03325088-d7c83d555374c3b27fde87eb01f5851.npy +02958343-9539149f41e453052a9eb0f146e94477.npy +03636649-7591d7cc9587643caa5752b5743a662b.npy +02828884-6ee8866fa7b253e8f4fb4dee5181bee.npy +03001627-450cd2f81b38b6fc7ec728abdd798547.npy +04256520-acafbbf4c4f3aed424367084627d607d.npy +04379243-9b6395c94a80daefcea003eff0268278.npy +04379243-a9946cff00d5a43c3b0db8c24d855998.npy +04379243-6216ba4ee25256c9490ad276cd2af3a4.npy +03211117-cb8a39997ea5433b159fbcda62e85465.npy +04379243-73d4df18ad195ba6492d9da2668ec34c.npy +03691459-49e47ec81395e290d3e5b33a5e1cb23e.npy +03001627-e8089df5cd0f9a573a3e9361d5a49edf.npy +04530566-4bd85ce20325ba7442c20743f866e1a6.npy +04379243-bbc0faf338bd07c3cffd61677456447e.npy +03642806-6c1cba2e5d2ebb552209327b12ad3fd.npy +04379243-174928ae6f9aaf3cb1b6b0c5ddacb607.npy +04379243-e6ec89773cb0e3ab3880b925e059dd8.npy +03467517-ff956097c2e0fd2cf66a9e192dbe265.npy +04379243-a74cad1781afed87dcfcef693e7ec696.npy +04090263-26744766d59c28fb6b2c8bb96250e4a0.npy +03691459-ecd9a96ebfd0caf6d8f9dd7647048a0c.npy +02691156-e7fed0e0dbd871ce35ae6d8873b772f2.npy +04256520-f567137b74a175c6f49a23658fe5597c.npy +04530566-248092c201dbf7008088de1a3d7f09f1.npy +03691459-8c2bfce4c190934da98a11883c15abf.npy +03001627-11e521e41ff6a64922e4620665c23c97.npy +03001627-a8bb7a8d6f2e1c5dbbe43d356df0e955.npy +04379243-a0e6486608007bf4c955e5ed03ef3a2f.npy +02691156-65cde29553fe7d763a63e8ba97b45ddc.npy +03001627-c3cfd2188fe7ae365fe4ecea39e8bd40.npy +03001627-37a79a0b617e2e711d172d0e1c97cfd4.npy +03636649-85574f6036ea1f90d8c46a3a266762d7.npy +04256520-5e6fe3ce7afd4490441e918a50adf356.npy +03691459-beab6a006f44f33de19807d50c8d841b.npy +03001627-fe56059777b240bb833c6c72c4b62a4d.npy +02958343-862a345b6328d641ef3ecc8551d2c1fa.npy +02818832-b1debacef4d43e4a20685b5a7e34b501.npy +04379243-d2ad73295752e323255c4b3adac8f815.npy +04379243-a084dbfaa217331894c13f8f78a6d62.npy +04256520-b9faefaee3f409ce2d86e6f67ef12498.npy +03636649-e88e3d0c851a00fe6764a784715fb668.npy +03001627-9979c8433d92fd80d1dcc55e36186e4e.npy +02992529-8caf79a2bf3be9fabfbac23a8087e8f4.npy +04256520-c8108de19d8a3005c5beea20858a99d5.npy +04379243-f434ad9d54919c9029d8eecf3827c486.npy +04530566-2dc008ba026e4c8c8209e983a346eb25.npy +02691156-afe6a70cc5fa98fbd93d05336f155bb9.npy +02876657-f4851a2835228377e101b7546e3ee8a7.npy +04256520-f4a0d0169abf306a754ec1f2eef2c6cc.npy +02992529-6475d2eb77c7ed5a59812638b595a4ce.npy +03001627-d2771921272ad1536a69760cb58e50e8.npy +04379243-bfe852b57d198bd2e83f416cc5d1e30.npy +02808440-d127726fbd237ab197c5304296d7b1a1.npy +04256520-34d7f8dbbe80413c4ad33b69f9597739.npy +02691156-abbe69a6f94918c79eb9aa3111a82815.npy +03636649-e4c9bb21fe5bfeb3e21f078602e2eda8.npy +03991062-c868008632d3523a25ccde673a683af0.npy +03001627-9e36380dfd1364f6d01673c7c57450c9.npy +03761084-5b2633d960419bb2e5bf1ab8e7d0b.npy +03636649-78f5bbde973fa96780b013c1c827c9b8.npy +02691156-d31a0f4f945775de5823df672991ed66.npy +03001627-8f54c32d7097b753542dfd131ca455a.npy +03636649-b4af7e9a7338a9a3225afab722d9fd2.npy +03691459-be277cf919c1467dfc1c2fb0640247ec.npy +04256520-a1a8920f91e2f3d25dc3653f8341633a.npy +03337140-3ab7d894293dff6bc5bf424b15c73f47.npy +03001627-31569815c88e79de4458bae25a4e518a.npy +02691156-12f4778ebba781236b7bd17e458d0dcb.npy +03001627-42d5b7df0524a3aaf785f45147f3e474.npy +03691459-56e11f06a19f9c3edb24fbbf172c2159.npy +04256520-c5f48faf560bbcb3debd3ac8a0c825d6.npy +03211117-f5f5e872bf70f59983f551e0fd7d32ac.npy +04225987-5c55e6b6708f730d758f6def7204bd6b.npy +03001627-98cb91189f35e5f57c311bdc1462c34a.npy +02828884-ea56c97ec123270c2d776d9e024e5deb.npy +02958343-885207d4e9d28f317bcd1993e004117a.npy +03991062-aeb4b2eb456518022271466eed05a4d3.npy +02958343-ac488b046b024bdc3aa029ace5323fc1.npy +04090263-ce351c4fddddba2a7dd22c0aa3913f0.npy +03636649-edce64335e42ac2f58452382da1a79f3.npy +04256520-199085218ed6b8f5f33e46f65e635a84.npy +03211117-fc542f42b786ae20c40162916d18053d.npy +03001627-fa8860d6a0d45a4688dcbe86402c7c15.npy +02691156-1d96d1c7cfb1085e61f1ef59130c405d.npy +04530566-1d075cc087e9c9e3e3d3b281e2d34942.npy +02958343-56332360ecedaf4fb095dfb45b5ad0ce.npy +04256520-acf458d2b16dd918ef188758bf2e3a30.npy +02808440-ed35928bd1dc8a2fbec80b85c820859d.npy +02691156-3a5aa99b9e9e37a6bbf3143b1cb6076a.npy +03948459-42de9b896d23244fe6fbd395d87e5106.npy +04530566-97b9c8f223390554e2584b7a39a94cb9.npy +04090263-9d80168647f0c0ac9f433921788191f3.npy +02828884-870562aca7165d703c78f7fe78269073.npy +04256520-5c69960804458df5255ac1b93c90af25.npy +02691156-d919249737749c36417568af9ae9577f.npy +02691156-45bd6c0723e555d4ba2821676102936.npy +04379243-bc2f853a8f2c42701b126712b4d6e5aa.npy +02691156-5903b9eeb53f1f05a5a118bd15e6e34f.npy +04379243-3b5195c53046e4bd6e9ad486918e1764.npy +03001627-38b5f764afc9d28f200ad3f421b6c3d0.npy +02880940-e816066ac8281e2ecf70f9641eb97702.npy +03001627-8e853d5bb145c11486c701087a194026.npy +03642806-9ddd8a548dce36fc800b903035974869.npy +02691156-78a94b8bd2971595ca8607f540cc62ba.npy +03001627-fbca73a2c226a86a593a4d04856c4691.npy +04379243-9391dcc782fa7f6bfdad344760a9dafd.npy +03691459-a6cc92fec1071df0fb2034808cbff90e.npy +04379243-9e94631e0dcb5c15890bbb282640d692.npy +04379243-f7ec331aac39a17fb129901f80d24b7b.npy +02933112-ac536462e72dea3211fc2b865c2a185b.npy +04379243-6f576d151a46bdefd5cb6d178687b980.npy +04090263-9e98bccdfb3cedf612db810b4de23290.npy +04379243-b3fc5247186936f1dcfcef693e7ec696.npy +04090263-31895d26609fb45dfbf44f447f38c175.npy +04379243-7afdd54c53562cfe43008e14d7d4c137.npy +02958343-ac7e674eb67488dcafe1d4530f4c6e24.npy +03325088-4de724831f09791676c18e71fd49c4dc.npy +03325088-996932ea9d17bc9ab362845c6edb57fc.npy +04379243-3cec584145ee513d635418e95eea8a17.npy +04379243-dfdef0c8739cdd0944b0115560181a7a.npy +03691459-86f45d4bb1f5f8597a040c8bcae232df.npy +04530566-249d543a30a88020be7995d5b4bc81b7.npy +03636649-761fb0822bb05bc8ee0cd746086d989.npy +04379243-9c87f81ccf8a2559dd33a7e96aec2a56.npy +04090263-5c646e68fe7981366314c3b6a3a65519.npy +03001627-d13c7cdbaa6941c2f0f0b1b5588b0b7e.npy +04256520-d6f81af7b34e8da814038d588fd1342f.npy +03001627-9641c65e9a8f9a873f9d6e0ade5188b0.npy +02801938-5fc11cef6ff80f2250da8b99982a3057.npy +03636649-ea9ec4d9db2e06202471e6dd5ac3ef92.npy +04379243-1b6ea0e8c6785638ad8d9da81848733.npy +02773838-b1234d3adf9e476e9432386574f02229.npy +02946921-3c8af6b0aeaf13c2abf4b6b757f4f768.npy +03636649-98cdb45ca9925feb194eb328dc97c7e2.npy +04379243-b292c70f70377635192ae4e26f16c930.npy +04379243-3576a576c81f2966f2f40b9b3af5eeca.npy +03001627-eff6231acedae01c17103f9c0716a636.npy +03636649-3c012309d5c68153302ef84771572fcb.npy diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/train.txt b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/train.txt new file mode 100644 index 00000000..1d77abdf --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/ShapeNet55-34/ShapeNet-55/train.txt @@ -0,0 +1,41952 @@ +02828884-3d2ee152db78b312e5a8eba5f6050bab.npy +03636649-86f8f2c064c79e6cb0c0d433974e32b.npy +03001627-d3a38afe0a0341cefebad4f49b26ec52.npy +04256520-fafd58ba00e8590119abd93be2967664.npy +02958343-41175e2053fb636852e23117ce8d150e.npy +02933112-41472c96b430a1c44f03bfce55719739.npy +03001627-5bb5b15807158f71504721639e19f609.npy +03001627-41ef5dfaee26499afe0dc3bdfa883025.npy +02958343-1c8cc8dd7b2d9671c7709b125ddd3d3.npy +03001627-6cb6373befd7e1a7aa918b099faddaba.npy +03593526-8872d686186924e6c8724d5673a063a6.npy +04379243-efe2bb181502eac1f3c9c1464e55d580.npy +03636649-273314626729b1e973222d877df1ecac.npy +04256520-c5e55f00566f0da2ec012e3517533bb1.npy +03636649-de5799693fbddbe3c4560b8f156e749.npy +04090263-710148ab44c6e48441c4ee8eaf0d3f6e.npy +04256520-1ebf04ee0e620619ea006adb8af93414.npy +04256520-6c9f559b0adfbd6985d87e0aa09f3117.npy +04090263-f373746d1ef6fb5da4dd752ddde80fb1.npy +03991062-8442df5146f188a925ebd1cd0b422e32.npy +04256520-8918d572cff6b15df36ecf951968a8b0.npy +04379243-994e524d70043c3496e349c87c588bf2.npy +04379243-33e18d453f4a8c90ab610b0c94236463.npy +03001627-9e65e8fdde35dcbef91663a74ccd2338.npy +03761084-ca0b473a5c373dc1f3d773b4af1f0c9.npy +04256520-5f66f9b4afd7d0bbbe99c53d7c66ee1.npy +02958343-a358931939481311bda733a39f84326d.npy +04379243-2d1d8a2f976387bd3145205f02ff9fc5.npy +02691156-e0cc4f538a8da2d65d3bbd70fc7759b7.npy +03001627-cff9a523a9e20eaeb40f0ac0fb9a650d.npy +04256520-8889b2abd894ab268d1b9a1d97e2846.npy +03928116-54e3ca588d0975b6a3c4aad99618c729.npy +04256520-ee5d770da5335578f7d7b7d6143367b0.npy +03001627-75b9ddc5017a5eb137f8f3a1ea8633a9.npy +04090263-a1f46e16994569d8743d370dddd1ff3e.npy +03636649-db88171d1793fa2785718c281d7fdf61.npy +04256520-4f5780a3a0466469e5c864cdd2c65afa.npy +02691156-c600de8c83303e6a441eeb748bfdabb4.npy +04460130-a2beb5f14190c1702637f1559971e0a6.npy +04379243-2598bfc04772f90cc20778ca035801.npy +02691156-ab7001e6d0321374b378822897b79a81.npy +03991062-3185f5566da7b4fe78253215bd9538ec.npy +03636649-a957a1304a1fe3f2f78c91c136e5b5f8.npy +03046257-9d3efcd35cda4abac7cdfa94351d0f74.npy +03636649-c26b7862f2afb7ee4b3c42e318f3affc.npy +04256520-a9ee7aaca080a86798e0d1738edd4f19.npy +02871439-2c55ab36465941714dad8cf98230ae26.npy +03636649-617e98c1d743c17420ccbe1c34ca182d.npy +02958343-1aef0af3cdafb118c6a40bdf315062da.npy +03001627-5472ab8df7cd3ecc1c1b3b2ed8d13bf8.npy +03636649-c0a0f01bf127b972257cafc2ddee5167.npy +03001627-93ee27f70b593cee7b11ae648ea92233.npy +03636649-f6425a421a497aad6cc679ef84e06ad6.npy +02747177-92fa62263ad30506d2b12aa6a0f050b3.npy +04090263-c07f9e5e064bd0ef93c9577cd4b35faa.npy +03642806-e8f89f185dd8165b9b07343517e0f88e.npy +03636649-4bd3f50f903cb1bffbaaaf5884f2c88f.npy +02958343-2655a48c8867146bf63ee8a34069b7c5.npy +04379243-22b4c1176e8433134ea79bdd828d5828.npy +04401088-7f55d778584ee63d2271b84575f49c3b.npy +03691459-43990265c9b6be4a989542bab68e6843.npy +03001627-66e1329d6098499382e4e6b3ab10271.npy +02958343-b481b928be9f2bb0e71f141b16973142.npy +03001627-fa5bb6d18535f66219fb4103277a6b93.npy +02933112-6e75ca2b08fe53a344221bef0fa3c36b.npy +03636649-44b84b479d9f8ae7ce2b80886d544375.npy +02691156-c6e4d12318bc4a3b262daac8a0882e96.npy +02958343-a2fa9237519db867f606d4ef0b8dbe5b.npy +04530566-d608bdcd8a87f3af7d2dc2b4ad06dc44.npy +03211117-64fe6e4480939c5e9b485b25e7417c6f.npy +03325088-ab01f61d19cce83aaf0b75abe6dfe88a.npy +02876657-62451f0ab130709ef7480cb1ee830fb9.npy +03001627-58f3e49e746363dcf91663a74ccd2338.npy +03085013-61f958f07b7489e56f03051f81ab06b7.npy +04379243-906eed2a218acb42699c80a6f97edc9f.npy +02808440-d95901baec87549e54d7082b34825ef0.npy +03691459-b3158c23dbd08f554cf39544f467e5c6.npy +02691156-42b63c881861105ccc14f1e6f4f4f49b.npy +02933112-1ef44fc1b4cac21af51fa0238791f5dc.npy +04530566-33d7cf0698dea49acaf9c991e0bc2cd.npy +04256520-165a78e3a2b705ef22c3a2386a9dfbe9.npy +02992529-cf7973f49aa611346be7f66e5722d994.npy +04256520-514d64dec987c01d552ef6186e5d52ac.npy +03001627-6cc65de3b510406ba0c5548d84070f68.npy +04530566-68babb87d66a981dd187e410b169ccd0.npy +04379243-6b6c03883c704389c3bd24f986301745.npy +03636649-5f943996d99dcf59726dbbf7bc5e4df3.npy +02958343-c6ab70b8319d7f2451751fb7affef409.npy +03001627-86c28989c2edf29a2bb396d08a9b621a.npy +02958343-2996a60389105deb649a971570be83d.npy +04256520-bd3cb48163e43810f29b3e56ea45251a.npy +04379243-6d705b609f98e559173b9f28a2caa84d.npy +03636649-418a6ed14b4571daa5af58528d00e4fc.npy +02808440-a369b8bb41a81cf7dbabfe882776e1f8.npy +02691156-4bfa5d948d9ca7ab7c5f0032facde6fe.npy +03636649-55af2652c4460b05ef3a2c64cef919d0.npy +03337140-90a2174624d8b62da53326e496617646.npy +02691156-48e47a6e592cf635590b4d838791a67a.npy +04004475-8f0d3efa9e511ed53fd0acbaa54efdfa.npy +02958343-282293948b21262769416db9b743e50b.npy +03001627-5d346bdb7db27accf3588493d5c284.npy +04468005-553450a802f3ae6b33bba21b4e20708b.npy +03636649-d08941d91a52d4ca411abfe83236ee8a.npy +02876657-3e7d7a9637e385f2fd1efdcc788bb066.npy +02958343-b18e5aaa86cd8716a7fd25564c2e888e.npy +03001627-7a1de77ca204eaf28a514cac7cb18507.npy +02958343-6e651b2230b8474c2de77cee5dfe5031.npy +02808440-fcc74af36543018db38325455ee7a49f.npy +04330267-ef0ac3eec2bd550a2bac1bcdfc2402d2.npy +02808440-c4c3e4b9223ac6b71c17aef130ed6213.npy +02933112-3cdabe258ed67a144da5feafe6f1c8fc.npy +02828884-f958d18643e7dffd99892aa9c57c2870.npy +03001627-30bbee7ab9026c5e4b3c42e318f3affc.npy +02992529-2b33c33ab4beb7493ce1b993153ccc0e.npy +03001627-269698853d294f595761a0b53ed37cec.npy +04090263-ac161c74926a5face378cd9d51dc5be0.npy +03325088-1ae1609816687a883792c04fd8184496.npy +04004475-7c1ac983a6bf981e8ff3763a6b02b3bb.npy +02828884-26299b4f8e03f3ae9470a3e695aa4fae.npy +04379243-176d3994129f9307c3bd24f986301745.npy +04379243-ceb0c123378d24bd9f4b4145f6688869.npy +02691156-f2d4b8440d4bde5330afbcb38d77d0c3.npy +04090263-94386a700272405ef0d11ae402ef940e.npy +02924116-585f25e44777c5a1403c57e7ce69f902.npy +03337140-20f41c44148871104c3aee8e9d3a6ffa.npy +04379243-bbddae0c95f3b7b636b0f2a1430e993a.npy +04530566-7a6634eb949d72719e6f7dedb7e5f584.npy +02933112-c01ecf4426f58beec3c7482d23c2379.npy +03636649-534c7e2c9495d7987b6fd5468f603b31.npy +02691156-4129199695b9344930813b40bae6f4cd.npy +04554684-5a94498353af7763e169a380d7bfbfc.npy +02871439-4f53f0d00d3491f35eea3e3d89293379.npy +03636649-67e18db74dfcf7f418df0876cc6aa6ac.npy +02828884-23b5a3c3d7d6057636ebcfdda999d232.npy +04379243-c416034b70b1d339838b39398d1628f8.npy +04379243-68ef6fc62b9d7f161a8a283df3396be6.npy +03001627-5e3cf3c40c6bfc0471a782a4379556c7.npy +04256520-a659b730251c2da7b3660298957b3f6f.npy +02828884-6d420bec5284eb43ad5067eac75a07f7.npy +04256520-3ced29b0f7f38bcb8964df2a32faa49f.npy +03593526-c81fa64321c8d49fb9be450193b1790b.npy +03001627-a93aac9ad86008e69fc01fb65ca37d30.npy +03642806-a3d3ce1084c2dc3457cd4ef590dc070.npy +04401088-a24fb0602fc7fbf4ec059109909662d2.npy +03001627-e8126f9e2d106620d2f33aaf794b5932.npy +04256520-2639242e8f06f93919fb4103277a6b93.npy +03691459-796384ba0e8cb525e17b9e33c097dbff.npy +04379243-3429a5b0d0497316ce44dc01dba1e174.npy +02773838-5f3af8ff93de34c9e7922afdefd88b6e.npy +03636649-a21744a28956c93cc5a208307819a3a1.npy +04379243-fb7af067384d120b46ebf4f1147c3f0f.npy +03001627-6a72bf1b1ba3254c51c4deb11af7079e.npy +03001627-da160f272c6d77f571a782a4379556c7.npy +04379243-bc48080ee5498d721fca2012865943e2.npy +03001627-b6b426ede67febd4a413908c0e169330.npy +04401088-d3dcafb368c1defaa2c7c5886f4bbc93.npy +04379243-7dd4c0baac6c76703002761e7a3ba3bd.npy +03593526-19fb5ee10bc867a492ffc535cab01f7a.npy +03938244-f7a1abde2723321e8bd9de6b28931bb0.npy +04530566-75198f9e1c5a075c1e6afa6efa6add34.npy +03001627-c0739ef0c29f005ef1f5e7b74609d54c.npy +04256520-acd97b28893414c41e4599068fc59335.npy +02808440-ca63d5d8d3f1933354d7082b34825ef0.npy +04530566-cea154f7fb5351bc26da67afecb7dc87.npy +02958343-53a031dd120e81dc3aa562f24645e326.npy +02828884-f5c6c9a4c5787dae19fb4103277a6b93.npy +02691156-4542d34685168ecf7a571401e6605fc2.npy +02828884-2ab2387e58cfd17ef155d75bbf62b80.npy +03636649-752a9fb2cf32fb5481e0c510e9bf91d1.npy +04090263-6639f08c2275398352d6d9553235a14e.npy +02691156-c0c32558decf271df3ad4b0977199f23.npy +04256520-ec836d156e8157fec862eec8232fff1e.npy +04379243-18ea2f5371184926764a784715fb668.npy +02992529-5b111b3a3e94b5907e1c85c5c15da7fb.npy +04401088-c9a50d65e19a4aa3e2da685d55be1eb.npy +03001627-6aba15a68e745c8d48fda83c10428379.npy +03211117-b302ee5206ec79c34ec31516689e34ad.npy +03337140-f44e926b21e1633e492d9da2668ec34c.npy +03691459-14f7468c0ae24a73d6317d54cfc1018f.npy +04256520-2a8554af80cfa5e719fb4103277a6b93.npy +03001627-5bf38f7840d4c8fc8e9d341bc3648f0d.npy +02828884-6d6143cd573920ba7251f1ec40392b93.npy +02924116-df3f687930b79392d6990bffe29902a9.npy +02958343-2c3e7991d4b900ab35fea498c4ba7c5a.npy +04379243-447f9f9dcd85f6242849dacb94997f4a.npy +02958343-acf64e44b021fd4613b86a9df4269733.npy +02691156-f4b734236ec678d269e10d525d6df27.npy +02691156-6e324581dbbdfb5548e8405d6c51a908.npy +04379243-b7aedc93c53ab7c1490ad276cd2af3a4.npy +03691459-c52531bfe9fcb17a87586c1eb104adc8.npy +04379243-10fbf670bb017ec94ebb593f0d0b4581.npy +04379243-aecdd6e67c790959504af6e1321617aa.npy +02880940-f0fdca5f5c7a06252dbdfbe028032489.npy +04530566-bc8cfba04c86ab537117d5d39e7f9235.npy +02958343-a19d008c68e9c942a78cb4f1b66f009e.npy +03691459-acbda0d16acd03329d4b859036b8707c.npy +03001627-61943ed43201e59ed7f7a4c4609b0913.npy +04256520-8952146d844d41f78dd7a714af22f7ca.npy +04379243-461e2b86470326ed70e89b1ce671b01f.npy +03325088-af92e8fc813b826550da8b99982a3057.npy +02924116-c50e814a2e40e78ce8784f880dac0f61.npy +02691156-118e8142a8cb1fe19a4a28ef635593ce.npy +03691459-e71f2c0e0c760ae98139dd63d55edc44.npy +04379243-6d5a70271c0529071360172b4b6205b1.npy +04379243-3f4ee26a68f2e9386051d49e4b21b83c.npy +02691156-ddd06628f3bfd0b64e1dedff94c67c76.npy +02958343-8212b62591234c743a0daf3e5400b95c.npy +02958343-54514b3e6ea7ad944361eef216dfeaa6.npy +02958343-bae4b861b5cf87275b182da8c76b7238.npy +04090263-3190d8d6542e51fa4b349e4b3dd5565e.npy +04379243-a3dd0302fd716e8624d89cbad731b903.npy +04530566-fa2b5f163549ca457ba04de7d6d93ce8.npy +04379243-e40afb4171ccc460de03ab2a27ba7531.npy +04530566-6e52344e2aa435d37e264261353b57e1.npy +03001627-da6cbcac794d377df9111ef49c078dbe.npy +02933112-e05be650930e7eadab9ab77fc8888129.npy +04090263-30d7d9f98893cfd62511f68da65f4c4.npy +04074963-a036b6be1c50f61fa046bbac53886364.npy +04090263-39bfd3455413996df8f666ba0e601ac.npy +02871439-29398b8b0425408a887c133d6a014f38.npy +02818832-a39d775401e716948cbb8bac2032149c.npy +04401088-7f6a27f44d8c9f2bbcde31492651e03.npy +04379243-e801542eb03f6e3b96d5fa1ee6ada8d1.npy +04468005-a301441491fed52e98d3c3293089ec31.npy +04379243-80b20fdbf1183f37b7491f8d3451cded.npy +04090263-db8f1174280680de5e561f212b7229f3.npy +04379243-146a019a7269fabc45656b6a28cfe2cf.npy +02691156-4c9214d70e0a00c6c1ccec171a275967.npy +04090263-2b6e43e973ee42ea1080be321101ad10.npy +03467517-bad8978268948ea3d3eb77b119df6d.npy +04379243-e0c570b6776eeccec715f352ef265874.npy +02958343-f8885a2372b427f8f2626f7f7bd2296e.npy +03001627-6b5edd2c4df6e85cf9b9977a2406713a.npy +03001627-65f3d57bd9c6911d492d9da2668ec34c.npy +04090263-30621c7dddddd06f42a2e92acc266edd.npy +04090263-4edbccf034f4ab241c3656c6593bed66.npy +02958343-49da37115bf906a7548ac25911d2130a.npy +02958343-49f3932e6fe0828951cc889a6330ab15.npy +04530566-726a60f7dabb1c88c746ec5b7259bed7.npy +04379243-fe710962895c20914476c40fec27b24f.npy +02808440-57f5f67de9a46afbb362845c6edb57fc.npy +03001627-662409af279f322eeb82005949031741.npy +04256520-7dbdddc3a60664f9e87dd5740f9baf65.npy +04530566-37aeaa30913d6ac73e7331a68f273ff6.npy +02691156-72aee7d0e998a68aca8607f540cc62ba.npy +04401088-8f1ec459492c61ff562c8e1ac545ef78.npy +03636649-1f5919744e0376315f38797299bc3fc7.npy +04090263-8fb4cf2a9f6d0abd8e7e8cfdb2f674b.npy +03797390-83827973c79ca7631c9ec1e03e401f54.npy +03991062-4192ea096a7afd3595f577622f465c85.npy +02691156-350d4b260bb18470f77959a47a1c16a8.npy +03642806-719be2a932ea7891374110224c1c4eb0.npy +03513137-b14fa79d2a1efb586f7dd5dd40daa88a.npy +02691156-3e5aa51d27e294a835fc197bbabcd5bd.npy +02958343-7a5eba46ba4cfac35aa429db266f0c30.npy +03001627-510b1295f70873e2f91663a74ccd2338.npy +02691156-b51032670accbd25d11b9a498c2f9ed5.npy +03046257-b9493a141be0e2fe192693a5c1e96238.npy +03325088-c9c3fce5cf0e964f116162acefe23592.npy +04530566-a771ed8115610f0320d75154997de910.npy +03691459-f529e7d74d5ec3d9a1bb636e72c59b32.npy +02924116-9188b08104130e52f446f92b52bbd82a.npy +03001627-2016d09b261b09f05413c1f22a911d58.npy +02691156-33c5c1919425791de038c01d73511063.npy +02958343-d50fcb81298e51e4afe717997470b28d.npy +02954340-da5e5ec4c486d6c03baa6271927f050e.npy +03513137-ae0a3cf547c0534ab0aa56928723eca5.npy +03001627-c0b45de1c0e8f80d4521562865ab775e.npy +04379243-2933b92d193e31b46cff9b44fdf0517e.npy +03325088-3af3bb6e47732764c36fb70296e45483.npy +02933112-29b2a25804651a34c59350d819542ec7.npy +02933112-267545b2c6ec6ee1f51f77a6d7299806.npy +03001627-807f08096308af5e28c0cecb7de2397a.npy +03636649-181ec75aca2de25f6dbdf247ab8522eb.npy +02958343-2e5dbf98157a53a55cde8c99e4b182f9.npy +04379243-6cb41b2a5e27533f436e6787c76ef3f0.npy +02876657-70172e6afe6aff7847f90c1ac631b97f.npy +02958343-55181c34dadb4f032db09455d18fca0.npy +02992529-d809653bf5a21f10e5b8860dcdb97aaa.npy +03001627-9a789be179253acd66c580e84dfb7998.npy +03325088-98543b751804811c36fb70296e45483.npy +04379243-1a767b8130e8a5722a7d46e74f08da70.npy +03797390-92d6394732e6058d4bcbafcc905a9b98.npy +02958343-d07300cbf12c42c3c427f8508e3d634b.npy +04379243-ea96b8a866121d1abed1bd9593e318c.npy +02828884-56f65bffa385a635f4b6538438a0b930.npy +02691156-55b7a2661bffdf9d55a352cb563d3195.npy +02808440-3981200a977815ae3321831d2245cf06.npy +03691459-a872cbdc66e671ec29d1e4faf5d375.npy +02691156-2f01cae5fb585d56ca8607f540cc62ba.npy +04090263-733fd68ce2fdeeb76a853eef701ef7ce.npy +04004475-e232d3b7ba947154684a64a3647d1ec0.npy +03211117-fac8bc5420f9d472b36c473722d8f02c.npy +03001627-9682d28e03acd2e3735013f3db728e20.npy +03211117-6ac7bd79924399c4a0778cc08d9b97f8.npy +04379243-391005d8f1291cb71bb088904f7cb154.npy +04379243-8e7b48d1eba786cde8ee269f00f30d13.npy +04401088-428ac05b36bb576d2a9eb0f146e94477.npy +02876657-1c38ca26c65826804c35e2851444dc2f.npy +04256520-6d60b813582de6c1febad4f49b26ec52.npy +03001627-4b35fbf5df52938a76d876646d549aa0.npy +02924116-7822eead7ed7abc5c150a7c590f1de60.npy +04256520-2f1e6b2c94d6b6c474072e8e7f655555.npy +03636649-80a5ce76688700a2fdd36147bc6b8031.npy +03928116-58fbc1679a7b229b7773fd259c9bf7d7.npy +03991062-a2841256fc6fd90da518b93bb7233de6.npy +02691156-dcbd333ef51b76862b600da24e0965.npy +04379243-832ea764f0d3ffad9923defa57043b67.npy +03046257-811e5e7b22e7ed15b9cdfe8062f449fa.npy +04530566-d95c49195e51912056f316a86bec8b19.npy +03001627-314c04d32f9e42c5f91663a74ccd2338.npy +02876657-d34628eb8992d1f418ae046addd85243.npy +03001627-a06114a07a68c995c8687ff9b0b4e4ac.npy +04379243-9d17b91f7f301cfc6655d494d4092078.npy +04379243-63f568ee89ac03c6603557e69ac4ca11.npy +02933112-be7d2a1a7fa7ce0b11fc2b865c2a185b.npy +03211117-cdf8eff26c940d7fcd1272091a2a216.npy +02958343-360cc5c25fd6bf20ea50ea60f77ab4cb.npy +04530566-6f3384e934f3588ccc37416b6163cbbd.npy +04379243-1d3aa66972004e861f5bdd219902caa1.npy +04256520-d8e1f6781276eb1af34e56d1d9ad8c65.npy +02773838-2f97f841aff238b74245c6fcbfdfe98a.npy +03001627-44ddb3d46266bb0ffebad4f49b26ec52.npy +02992529-3f3770476f094a6f2093f68f248ba9f6.npy +03211117-25df40f2502c6bc2b2fee0e811c64fd3.npy +02933112-24eb9773fec0eb609e4965f0106e00d9.npy +04379243-6292216ef69f6edb11c5cce13f76151.npy +03593526-6cccc41151a9578d4b3c42e318f3affc.npy +03001627-e3b04359a3e9ac5de5dbcc9343304f4a.npy +03948459-391e01226bccecab1d74bbc1a32c7aba.npy +03797390-b815d7e084a5a75b8d543d7713b96a41.npy +04401088-401d5604ebfb4b43a7d4c094203303b1.npy +03325088-465491e7cfd3e0b198a7e0d99b5bf4c9.npy +03337140-9f26b723e21d0fe94c3aee8e9d3a6ffa.npy +03001627-529c0a3650d6a7be97e2a21b8bc2d948.npy +04401088-67524ffa83e3eb7c4948b3842dede005.npy +04401088-162341ffb94a3884e4ba5fe92f32019a.npy +02871439-3a3015426ff544c46fb17e2962e0eb20.npy +03636649-1a6a520652aa2244146fa8a09fad6c38.npy +04379243-c38ba6c06d2b813230c589758b4b5646.npy +04379243-1cc70da57ce2e9e7309b03efb521ec1e.npy +03207941-45eb04a33128a2065dc3653f8341633a.npy +04090263-abfec35b505a92da64c4db7c3b428292.npy +04379243-e9546947de34dde213a5873d239ac557.npy +03001627-bf3c19bb6bf16aa8beedd4e6b38acced.npy +02691156-dcca40aae3eb0c8757bef59252fb18b5.npy +02801938-9394df08489ae97eba5342d638d0c267.npy +03797390-7a8ea24474846c5c2f23d8349a133d2b.npy +03001627-247353514479969ce6fe3612af521500.npy +03337140-8633f465415ec9e41933ffef19678834.npy +04554684-7de9dc34c7230ca54d3df84a5eca1a73.npy +02691156-7d928af41b7dd26e1d0f8853f6d023e3.npy +02958343-e61dadc02535e6e44b6e62b17dc78f70.npy +04530566-e72c59779e1a85f05308b39b1b1978d6.npy +04225987-f9752bb556ab1e20681083250d6ef1.npy +02958343-e64dd4ff16eab5752a9eb0f146e94477.npy +02958343-505ab718b8083f02ff1370452e3a0154.npy +04256520-5e8b318948817989a33ae3b0de29197.npy +03790512-8e956bae37beff87c2743f037f439af3.npy +02691156-c510e14ac20edee814a46d7ec44fc258.npy +03001627-d1237422881f4d22ff25b0c2db862d19.npy +03691459-513775c0ca44462d912b963d265d5e8.npy +03211117-bba0cad6dbbef2589fb287620a60b403.npy +04256520-7550aa9d29f252611431dc89d81d788b.npy +04379243-68fb0825ec07a521febad4f49b26ec52.npy +03325088-1226b60bf7593f08c36fb70296e45483.npy +03001627-2d018e8c0a34a863ff59f04994ef1f0c.npy +02958343-9232d8834704e5f9dd141480e2c154d3.npy +04379243-ec16de40e8415006855931d119219022.npy +03513137-257676761b471e0e69508b2b14833df3.npy +04379243-f5d1fc338e804d7fca7e81cd26bdd69.npy +04379243-1c814f977bcda5b79a87002a4eeaf610.npy +04090263-5019d7c3b413a57012b38b1d99376c0b.npy +02828884-8a541c1e735e834ad5067eac75a07f7.npy +02871439-a37d60f8e90a3afd810b14a81e12eca.npy +04379243-4c1048076c0a8a09c785f06f424b9d06.npy +03761084-77c4453bb4349e398128bc89a67202b0.npy +03001627-ef8b9243c75bdc93347805f93d32915b.npy +04090263-e574eb37ea6ee685e1f2a1daf140ac9f.npy +02876657-9f2bb4a157164af19a7c9976093a710d.npy +03467517-909e86e4a5af7fdf93f0194265a9746c.npy +03636649-cd1d426e08bcbe3e5a4e392b59939d74.npy +03001627-31423159297243ded65766fd3c4f994c.npy +03991062-4976f22bb8ba359713c828323b9d4bf.npy +04256520-b85dd5219ebb52455a1bada754e9e91.npy +03001627-5cf5615844b41442118bf3432a979b3c.npy +03636649-63fc809815b9639de7c7920f6a65a54d.npy +03636649-f049bbd180d89cb5490ad276cd2af3a4.npy +03001627-b3a9c49a1924f99815f855bb1d7c4f07.npy +03325088-b7ca2740aaae2d2c908061a998e20526.npy +04530566-4bf2dba91007f0285ce1e6c1c914b7a9.npy +02828884-3c40692f71e9b773c2c0fe12f0bcb343.npy +03467517-71137de8f3188ab3ac61a2f8346a8f.npy +03636649-36cbe594af434ef9a89ecd28750d46ac.npy +04379243-dbc5a4d1dc3a6e8271a782a4379556c7.npy +03211117-d41ff8cc1f08db6341d8f14d547541e.npy +02808440-e9344c904146df46533e0927d26599e2.npy +04379243-7689de934d5af6505e8431ceb98e6b3b.npy +02933112-b404faa639b8600855f46d55537192b6.npy +02958343-37954fb8bb9a7e351076d1567fc9aa51.npy +02818832-b294f0771e8cf0f4b844ed59ffd3b45c.npy +04256520-e08354a352fd0d6914a163d2b227b320.npy +04379243-9705c2610980d0fdb2d0500bdfc28f70.npy +04090263-2f8a672751f8c284a5d999dbf2c5fd3b.npy +02691156-2b99e54070c8b6d466cf1b4a8fc3914e.npy +02958343-71ea237c598aad1becf71e2e014ff6f.npy +04554684-8d3cd0d2cf88b2c2a83d16be6f14bd8.npy +03001627-a5de4210ba131f0e6ac7817035f206f9.npy +03948459-a7f7db7ce1dd7772515515e554d8cca8.npy +02747177-d6474403437240d578e4d091a0ee3ecd.npy +04379243-2d468e75b3063c165dca6305fb9f97ca.npy +03991062-ea473a79fd2c98e5789eafad9d8a9394.npy +04379243-c28f9a82cb7ddbb53651bb31f42d2f80.npy +04256520-9152b02103bdc98633b8015b1af14a5f.npy +04468005-dc52a7e38d59a2aee68cb23a969dff91.npy +04530566-227db3047b2ab275b3492776d9bac18.npy +02933112-36223972cc8153718cd9445de76e734d.npy +04256520-2dcd9c9795ce4471b65843dc986fdf7a.npy +03001627-55e4b862b56e873eb36dcc661f3905d.npy +03001627-fc14c1aa7831f4cbcaef18b2fd3fb17c.npy +02808440-6e4339050c5338933af30a3946d92feb.npy +04256520-5a7b6de19865d1332c8896155b09445c.npy +02871439-6f46c38f86fa961ed2f1945599cd5176.npy +03001627-d9af882ab6d1cbbd492d9da2668ec34c.npy +04256520-a8ff859fcdae8f70f2543b208c9ee8e2.npy +04225987-571dd1b4d09773c5bbe43d356df0e955.npy +04401088-43b59b01866f23e6f8d380ef6d10e2a7.npy +02828884-58eb1f7c59fda8271068f29f0b65163f.npy +03001627-abe225081bec7d21c5a208307819a3a1.npy +02933112-316bd800a04f14f0de650492e45fb14f.npy +04090263-8949412a776f34e6a821a9df9523f811.npy +04554684-a4fd18ac554ef926756dd585069c80a5.npy +03593526-80059506552f4a2cc97114870bb573.npy +04379243-fe0ac2e334ad4d844fb315ce917a9ec2.npy +03001627-dfda3c467eb6066fe6fe3612af521500.npy +02958343-66bdbc812bd0a196e194052f3f12cb2e.npy +03001627-ea02e94e39a2fd3922963ea1e168015d.npy +03001627-59ee0ee98def6f1e14b86d5282eb8301.npy +02691156-468831f7b19aaebabbf3143b1cb6076a.npy +03001627-53eea17c88e31519492d9da2668ec34c.npy +02828884-ea4e8de5b98a0463c955e5ed03ef3a2f.npy +03797390-d38295b8d83e8cdec712af445786fe.npy +02876657-b742bd7f675191c24ad6a0c67b7f7a5b.npy +04256520-57ceb2601802a37e534fa06200d07790.npy +03001627-9aecd48a3af10deeee83c0324834f3fa.npy +04256520-8ef1ea7a7c4b4e7d5cba62773b8025b.npy +03325088-71a0a8c0c7d749fc4c586a3fab372c5d.npy +04256520-849ddda40bd6540efac8371a83e130ac.npy +04256520-3a525a1286d4879ed35d1c787a8f626e.npy +03467517-a31ef3a8c70b789b93f0194265a9746c.npy +03211117-abc4a3eb2c6fbe8064d221a686772b82.npy +04401088-24d22e3257420bc2b785a4ac4a0dbd73.npy +02958343-b809864c779761ab7ac2a2313c9e8844.npy +03001627-e3c79d6e34b1285e4580ed619ae2daa1.npy +04256520-fcf30cec3180c05da5f9d52c12457194.npy +02924116-de1800e9ce6da9af52470de2774d6099.npy +04379243-a1cb5947d7b09c2c7ca68e217a316e15.npy +03001627-97f1121561e481a3a1f1563b05df75c6.npy +03991062-8d930cf7b852fc6181faebbdea6bd9be.npy +03593526-bf43945eef1782f7f6f19d35df0b096d.npy +03636649-ce798635ececbffd5ac3a75efa13522c.npy +02924116-c9991032ff77fe8552470de2774d6099.npy +02958343-3ef7cfbc172840b2393bf61b30c528bb.npy +04530566-f61524a539deb8097f7b259a472cabd9.npy +03593526-6b1e3b2af2a9e54bef76898f881b76a.npy +03636649-4e3d1346e76084a2c1caa73a5e644b6.npy +02992529-e633f997f4a47b2d727a08b50053320e.npy +03691459-a9d5719c3c2af900ce029fab54b6cfbd.npy +03938244-fe2236c135bc169e7676dfce60793e46.npy +04379243-bd430a701652963faf0ff870be225563.npy +02843684-f71f6bcd0bea761d32e483dbd0fffcb.npy +04468005-4aac817a256e3121fbaac8096a32753b.npy +02958343-62393db2dee065956e28ffc6e1f368fe.npy +04530566-6ab4ddc238851014802f537afffb178.npy +02691156-b80bd34ab330babbc8727b27ee96a4b7.npy +03211117-4f598d41b30b28e84158c4db508f74e8.npy +03001627-49a60133d6b05b8d19fb4103277a6b93.npy +03001627-1230d31e3a6cbf309cd431573238602d.npy +04530566-81170170d0cf36eaa5c5aafe837d3f8f.npy +02691156-26bc67e3ecda6aa1adbb4c4e06ad649.npy +02691156-71a96b4e134ceaacbfacbd9a73055b6e.npy +04090263-b0bff9f866c3d101af25bbd7d4e31ad.npy +03325088-1170e12f08a5f2952dc86760e17ef6c.npy +04256520-1f74a21433c43c784209d14d674fb332.npy +04090263-a33697175cda9f2d742567ca48f0f7e2.npy +04379243-a1a9c417180124f1a6c03a53cf0a14c9.npy +02691156-feb0bd0dcd155af4cc34b900bb2492e.npy +04379243-d5f2968e4b7254ccf4104961857ca9c.npy +04530566-645382862cc284869bfdd98fcb85ea6d.npy +03001627-4a4c7abae3929595184740798d03a659.npy +04379243-86bf47a73d93b66ecd037ccdf14d7446.npy +03001627-d0bb642e810bd2fea6fee8e2140acec9.npy +04530566-d49066858c55d7b021d7ca6ede0e9373.npy +02992529-aba1179bf8b62c812a6d73bcecfd73da.npy +04379243-133d7c9a1f79b01ad0176f9a144100cd.npy +04256520-22c68a7a2c8142f027eb00c151c6f711.npy +02747177-4606c9bae0c3a717ba6cf6cbb9f4c2bb.npy +04379243-ab2967188299bea54cb0654f4cfa9684.npy +03001627-8731945435676805aa29e9f0529e8ef7.npy +02808440-ceb077ecef095d452d70ca35ac1a10ff.npy +04530566-c1825c8ddf2f263ed6f64c5c0b0cdccc.npy +04530566-686a53aff9209c258d25d8990968dc68.npy +02958343-114b662c64caba81bb07f8c2248e54bc.npy +03001627-8bb3a13d45c5337d20e3ea5765d7edb.npy +02691156-e8d5a3e98c222583d972c9dd75ed77d4.npy +03691459-c9de3e18847044da47e2162b6089a53e.npy +04460130-47ce1a5380447249c26ade84d8048a3.npy +02691156-6d3965fef2c63d37b3a197029fcc978f.npy +04225987-ab76bf4b966e3fb5b10029f76a5ab54a.npy +03467517-ea23bdf251c9be975c6a44a505804654.npy +03513137-8eb4152bc0f6b91e7bc12ebbbb3689a1.npy +04330267-a5fab90884f5b576506c648223cdabe9.npy +03636649-4c4078f8206ef3cfe13094731a5351fc.npy +04074963-cd0c46f23b28b94ce56eff8fe87c1176.npy +02871439-13d1ffe8682729b29af4053b8815b239.npy +02828884-989c5de438050d9d6664ead1964339d.npy +02933112-62d67406fb239e21533276a8c0b1c862.npy +04090263-4e0cf21c4e7e1eb58c7ca3bb219438a1.npy +02942699-fdcd83539b8db2c8b5635bf39f10a28a.npy +04256520-c22dd8c395f465c87599bba30f391291.npy +04401088-98c63a8e5485b0a12737a4ff69ca3cd7.npy +02958343-5b1f078a81df862ec2c2c81e2232aa95.npy +04379243-8281936e9123cbbcaf95ae40867329f.npy +03710193-7b722675af1f1cec91adfee365fdcaf.npy +03636649-ec8dc2311d381a9e3d39d8012919dd25.npy +02691156-d56fba80d39bdff738decdbba236bc1d.npy +02691156-381111f176565d48fe4c91be246ef13b.npy +02933112-9166a54bcb06b6c7c59350d819542ec7.npy +04090263-ab9da6638fe428e87f3efc94c2d31dc5.npy +04379243-be045fca16562f6764c85287e21825c4.npy +03001627-117bd6da01905949a81116f5456ee312.npy +04401088-e13a5d5b3f7581cbecf207e73a787c06.npy +02958343-8c04413559b71fccbda72093f9b5aa73.npy +03001627-9570ea7fa3a0ef775436c76691cf3d3.npy +03691459-892af085a4518fc673c609379da5b9c2.npy +04090263-8a95676f5965c580276c3d558130f8b4.npy +04379243-66a801881c4ef524848eff6ddf1058ec.npy +04090263-ed01d61bb0439a33b4cdad9a5bf52dd5.npy +04330267-7020994986d2bc01bc59ed4ab44a78f.npy +04090263-670857f79c4d47c13a6842b1f893c19.npy +02924116-a02e4c26e3d769be221d7b13f13a827e.npy +04379243-7050eed75c60753cf0eaa338269104ae.npy +02747177-e3484284e1f301077d9a3c398c7b4709.npy +04090263-4ec09a25c05bc7d0fdc1361c2b9ae6a4.npy +04379243-f5ee06263c91d7eadfe9cab879fd37e8.npy +04379243-2a2d6560f14a01c6afac72146bbc9d59.npy +03636649-688d88d300429b7dcf78a76e06ee9b92.npy +02958343-28d7a23b2311b1029dce0c74b747947.npy +04379243-a33b6291afb1f8b066b38b193b506338.npy +04379243-71ec472682954cee353c1d159a8a8422.npy +04530566-c04df151b8677becd8af3a076c923cf.npy +04530566-f5fc09f67a5fdb0142d0e83abdfab1fd.npy +04090263-2c0f882d4c5fae8f2bd05e1cf7da8957.npy +03001627-b66a32bed74e203591f74997d435672d.npy +04256520-9cf1a9ea641d548a7e1dc33a9d8d260a.npy +04530566-3d396cf4279378456d165da625f3894c.npy +02958343-7cb387de84bfd2f5fcf949f5ffa7ff6.npy +04530566-d23e71adcc315d56c748af2814b558c4.npy +03261776-63179fbdf2db65fff325ea98afcb29f9.npy +02828884-19aa04605b1b00d0ad5067eac75a07f7.npy +03001627-u6028f63e-4111-4412-9098-fe5f4f0c7c83.npy +04379243-877e3505ebab096848f551687b50fb00.npy +04379243-4be0f809a66f1797ad9d8182e90fd7fb.npy +02691156-4b4fd540cab0cdf3f38bce64a8733419.npy +02691156-399449fd9e6149de62b600da24e0965.npy +03636649-8a9f2e5b726ea37f60ad823977adaa23.npy +04256520-3ac827b804fee818b0b88207ef0f5bc6.npy +03636649-43deffcae6d595f3fcb8d8c6d4df8143.npy +03636649-5179edb45a24a785fbd4fd7714358815.npy +02691156-eb2fbd46563e23635fc197bbabcd5bd.npy +02880940-12ddb18397a816c8948bef6886fb4ac.npy +04379243-e458913e25ca7053c1eb59469984d29b.npy +03001627-352bfa764478b1602bc694a93134e562.npy +04256520-b3346d1b7ced3daf1b2fbf268ed76a.npy +02818832-9dd1b8e40151bee5d2e83a37b2825e1.npy +02691156-a361d82b2c510ca5208842e3d616cb23.npy +03001627-d9061907b7b411dbe3db80a3cacc6e3.npy +03046257-3477c3900a9b1124738e43095496b061.npy +03001627-d7d709cd13cdca931afedc87fe387fe.npy +04460130-f14b153ab99da1bb73a921481ee71edc.npy +03691459-c20a8c3b7a06cd323a5b5efb52c46c0d.npy +03001627-9bb6d3d76d4f5ba94b3c42e318f3affc.npy +02992529-dd8b9ca9abc834feb5784fac792d6797.npy +04379243-1855a4b70958b3354b8710a3469971b1.npy +02958343-ec11fb287c9a68475de701ebc922ac2c.npy +04090263-92164d8660dbb9d278fc07d6c8069b8c.npy +04379243-19140f9ff7eebc13470412e9b69c8933.npy +04090263-ee7d9264ce8c77d79d9900c00629c24.npy +02808440-487665836aea026ccb2f32ac395fe2b.npy +02992529-87f8a738b3f0ae0194feb18ebe41aa84.npy +03636649-f5a48805f020d3e3967cdbf1c849239.npy +02828884-b4a8d71b840fa5f7b90be68f49e6aacf.npy +02871439-dca2cd661bece47bd810b14a81e12eca.npy +03325088-d35cada73c24af13321831d2245cf06.npy +02871439-dc9af91c3831983597e6cb8e9bd5d9e5.npy +02691156-97bd6259fd4dd69a90baeef8ba5b93e5.npy +02691156-642b46912529c6e57f1f82f6fc8747b8.npy +02828884-92b9ca91ff514bc90658f68885fd5d0.npy +04379243-44d70581b7c1468e1771ee930e861b13.npy +04379243-5b74412eba257e5182b796aa5845e185.npy +02691156-1f96a33a3a461544ca8607f540cc62ba.npy +04401088-4ce4f7fcf5f0c57a3caebb882f007959.npy +02933112-426f7850e60a5447616fb9ab42452112.npy +04530566-4a5ad5b71ce08abc687e743787d2aa6b.npy +04379243-1f7143556f4d75522d1adc013ed654e9.npy +04530566-5c46f6ce5efa21175060c1b57f88c056.npy +02958343-996c99bc344453ec6436916a86a90ed7.npy +03928116-afaf8f844c5b0ec37f96386fffd17d87.npy +02828884-117259de2f72887bad5067eac75a07f7.npy +02924116-ddc770ef4e0c0681c7f2b15673ec88ef.npy +04256520-62bc75a69029614877bb84100a5c6b59.npy +03636649-51fd15743cd0568219179d4701451afa.npy +02958343-712826b933a6818c7e003129afd0cbfe.npy +03211117-cf16012ae10b993bd15e5f70c1308761.npy +02691156-62ebb16b6b4ffd74df8fc3a07f996293.npy +03467517-ca9bba09dcae4b487693a84bff425e3.npy +03001627-91de3157ea61d943f27383fc5a5a711c.npy +03046257-db1ae97ebd6440613ca265f557f5dc3e.npy +02933112-789ee42d2fc0c5e088c59e12e565eb6c.npy +02992529-b1085da37756ddd1d3f1ccf368ff60f9.npy +04379243-4ae4635c7c69ea908d0eb3d070197e49.npy +04379243-a369da8e8e47d0f3f51f77a6d7299806.npy +02691156-52c9b1a9f8d3cbcb9a6e43b878d5b335.npy +02876657-26a8d94392d86aa0940806ade53ef2f.npy +04530566-1d8adfa96dca83849143982c80da1e75.npy +02691156-5e0331eab3f051988f6810e1a2b6aa04.npy +02808440-7ab615debab4fff9afc85023f866b252.npy +03001627-fd43278c60023763d4da89766e80607a.npy +04379243-ff26f7003826d1a2d810b14a81e12eca.npy +02924116-28e730a4db0602e3f446f92b52bbd82a.npy +02933112-defde3dac0ce562361c0d25e41396e8c.npy +02691156-69121d9daf6d569fb96212c8f6cd06e.npy +02828884-c4c9828b5c0e5db1ad5067eac75a07f7.npy +04379243-cc6fbdc6f2aa5ea3d889130b88839a0c.npy +03948459-cc014e78b5cd9e7ed957eaf7f4edb205.npy +03046257-45bb09eac47597ad6fe2eb61cd6e74e5.npy +03691459-d5e77992b28da2729c90f715a36a51dd.npy +03761084-617358ef5ce2639ff5b1c85b3db5d1ce.npy +03761084-91aa6504b3900385df3a1b0d597ce76e.npy +04379243-22ea80a1c8798eb22d19175e7d19b7cb.npy +02924116-3714ce121ae95608a971f258593ad6f4.npy +02958343-12097984d9c51437b84d944e8a1952a5.npy +03691459-84a87ff36612b3e53ef7ad0f5cedb0e3.npy +03337140-b8dbf1725cd55f7492d9da2668ec34c.npy +03001627-98ee09de954fdab1843ead12644a79bb.npy +04468005-a10330472393343e44399be51ebd0ad9.npy +03325088-4352119300b754d4e3f7a74e12a274ef.npy +02876657-ab51424e92acace2a1c3f37422b63004.npy +02992529-b87251d1d4f4b7ab2c216c5e0f221195.npy +04379243-949143f5e3b772a7986b72a93898270f.npy +04468005-773aeb7f76f9a0c4dc14ba0818ee5cec.npy +03691459-a4a0efdf9359987515f30bbd054cf549.npy +04468005-1fff38d54059eb1465547fd38c0cec46.npy +03467517-900c3823f47a8ad1d57700c05b1862d8.npy +03636649-aa381aff183b1427b7d9d23574a480ae.npy +03001627-233009d4f30fb416dbbc9440457e303e.npy +03636649-bd1cbcb990375022b45fed2806c331ab.npy +03642806-11494281ca09a63d3b54554be306bc70.npy +04256520-33f862846366476fc79619984c97c1ff.npy +04256520-305d64b9fec0015b62a510b8f97c658e.npy +04401088-610a9f79a2f2faacc43c9f60fcc79b4c.npy +04090263-2cb0634dfd39f71623c02c1a690f1e7.npy +04379243-970e70ae46244887c35d3c5d3b1fcf7.npy +03593526-3f7d866f4e28e8014b3c42e318f3affc.npy +04379243-52257815b77da840f7628281ecb18112.npy +04379243-95d3519b036c862d4e3155c362b85bd5.npy +03624134-75eabcbd45e92882a87957ef7e9f3d70.npy +02691156-9321ab235b82ca268c9bdb0f364cdad.npy +02808440-e65dc1c9c07f7eaeb362845c6edb57fc.npy +02924116-4972a57b656446979a426d999467f4a5.npy +03636649-261cc5f20787f50cdbb57594c19a59cf.npy +04379243-70bfb9d08e50970093fcbf4338a54def.npy +02954340-a4f94067b0ec9608e762cf5917cef4ef.npy +02946921-ac0eafed7aa1719b297d1fadd26a7035.npy +03624134-ee0b4054d8b40ba5812bade9b93f0eaa.npy +03001627-bf39672eec1e343284c6c80813d54fe5.npy +03046257-b602321e87ba6ffedce1f8ab000da922.npy +04379243-f99f09473fa068dfc834d9ecc7d5f465.npy +03790512-27733dbe070efcd8c9a9842c993649ff.npy +03790512-46afe9d5d8a45a17a26d3c6c2e980dd5.npy +03636649-a11dd450220af960ca70272754aeb3c9.npy +02992529-1b43d9193794748e31811399a4ff3aa0.npy +02933112-8a758b29a751764d14038d588fd1342f.npy +03691459-1eb6ae90ea03673ee792f9d89b97c271.npy +02808440-55eca9bc125d32fd54d7082b34825ef0.npy +02958343-7376511fb191429eff1370452e3a0154.npy +03636649-dbe15772a731fff01de2a416d49fc18b.npy +03797390-43f94ba24d2f075c4d32a65fb7bf4ebc.npy +03593526-b145d989080a57afe0b42601a8b58d3c.npy +02808440-911847b0eff48ba087a301d05ef6a538.npy +04379243-dc3fba5ae5e86e62416e6e65da17ce54.npy +03636649-c906a9c7ae536a0c7fb7f79251dd7727.npy +02958343-a26b62fa78e9d6e016abce8cb03e7794.npy +03001627-8b22c3e3be1f8fd8b645b903fc5f4135.npy +02691156-fd9f1cdaa381599bca8607f540cc62ba.npy +03001627-b405fa036403fbdb307776da88d1350f.npy +03001627-3aad9ca0d7fa80d76beba0439e85fb62.npy +04379243-155af42283f8ccb9b3664229461d7332.npy +04468005-f98a21d6b11f26935febed8de0838d7.npy +02871439-fedd668769a5916a30aad3a2f98e3b63.npy +02958343-c8fb314a1866d1d2428df271ebc70bc0.npy +04379243-c37632eafbf41b9c1fb41007d56c0ca1.npy +02933112-dca4c8bdab8bdfe739e1d6694e046e01.npy +03001627-66f18d05d960ffe0bcd12732b5a4b789.npy +02992529-29f27d4472a17e723fd445ae159c2cb2.npy +02828884-23325f47d2a812351165bc0a3b02b27f.npy +02958343-26cc3a9cc0c28174ae30cad08127b470.npy +04379243-c6e3f651d2acdb0a746f36c9587bfc04.npy +03928116-7324583e739a28075931320aab0d7485.npy +02933112-37e5fcf70007bc26788f926f4d51e733.npy +02828884-23d1c6e2e35cb252bb85b5a298d72ac7.npy +02828884-e4d1d4714d5dff9b79fb1978bf47fafc.npy +03642806-26ad81059039dfcca3e30e62a8e6f77f.npy +03001627-3e973b624578fc89b76e29c9c43bc7aa.npy +03001627-195c379defdff8b81dff5c2e57ad46e.npy +03467517-3634c40841a76b348c91fa35e72c6c9f.npy +03001627-11ff2e9f9b0993b7f51f77a6d7299806.npy +04256520-f50d32a6083c8f146dab7044457400e6.npy +03624134-a05ea45d396c86784e52b614e584a543.npy +02691156-2ab4a5c3ca32ba9a4d4cb1c2a5e48b7a.npy +04256520-7517e2a0c921b89d593ebeeedbff73b.npy +04379243-e58e958428584b2b79972b30518c97e2.npy +03046257-10312d9d07db5d9a4159aeb47682f2cb.npy +04256520-e491dc151c8e801186abe5555a3b447d.npy +02958343-72d4deb3b797c03dd4f6529a209c5dc0.npy +04090263-6c56be203155b9d2c3d04f57fc87fcb0.npy +04256520-a28bfe80037449cf5eea3e3d89293379.npy +04460130-f982e86909ed9e7f2c8891dbc3e6988a.npy +02691156-6db64533897238af392d539dc5a47ed5.npy +02992529-81f527c62191bcd465c46de8aef92580.npy +03207941-cc244af17335b1af52f4523ded466b8c.npy +03513137-791c70769828cda852bc033e87de1006.npy +03001627-a55140d6d7b1148519fb4103277a6b93.npy +03991062-3e4c784f765dce24766224c8ed44ac6f.npy +02828884-7d79d398f56c13eb12185770c6bc35e3.npy +04090263-8a40c59eaf7bc85c322a3e035e31af50.npy +04379243-e14e867c0cfbf1f42cef66bb37b0cc33.npy +04530566-b7c24dca7db1d2985c00e52236fed2eb.npy +02773838-c4cb5bcb1a9399ae504721639e19f609.npy +04379243-ef5788dd59881f2dbeea80ff21252e37.npy +04090263-4e292f614c51676c6118b98f3fdee6c0.npy +03046257-6f712bf7b828c9e920fb6b84fca9d3c3.npy +03001627-4cfc78be98de1d2bd607f0b8430fb29a.npy +02691156-a3bcd8767d2827626f5b49394e7f4cdb.npy +02828884-38dff7c9994cda58f4273dc8988e4c4.npy +02946921-b45716cd72f1e9172fbee880b9f634b4.npy +04379243-1cba04d4679da07ef51f77a6d7299806.npy +04401088-ed71d2ed652b911e7f521a3dcd28e9d2.npy +04379243-b9e3e65aa754f3b49ccce4c6d5bb195f.npy +02691156-b7c11baa48456c23149f1a143758cddb.npy +04530566-f15c255128f2c9c6b7963b720a430c5d.npy +03691459-f904f64f961e9cddcd3e44ab53ae1e92.npy +02958343-3587008282540864673ddeabdcc8c6e.npy +03991062-5563324c9902f243a2c59a4d90e63212.npy +04379243-495db04c204196ec47c638c0eee4a2b3.npy +02933112-8fe70b11448dfeef2369c46027bce7af.npy +02958343-2a0a53917dde654c3196f09f71403d35.npy +04090263-83e29d672713f0da270e90bcf29dbfc9.npy +03211117-daae6d7f0e8d7e208a8be3c02effecce.npy +03325088-d8844694dff0986d30fff73f53312a3f.npy +04401088-427d255534038d47e5eda863cef11226.npy +03691459-e5c2ab51068e9f8b58ad8ba2f750cf1d.npy +02808440-8c989333427537ce44221bef0fa3c36b.npy +04379243-ba6992957c2e6e6df67676f416157590.npy +04379243-e65cbeed1eb687d514038d588fd1342f.npy +03085013-13c3acba1f43836a3123e2af297efed8.npy +03001627-eda8edcd64072b0db784faac204319d9.npy +03001627-c7739fa5e32a7218a5f9d52c12457194.npy +02871439-80386678689904d16421c9121bcb0cd.npy +04256520-c4ebd90eb8496903f4ed05effa0aca88.npy +04256520-e233f53558015ba4f05a611b5fe35f32.npy +03636649-2059087b746a931e6bc1922eaa6b6752.npy +04379243-c1df09878a7a4a81190e285a2cbc9c.npy +04379243-4cd0c4c75f124cc117b431cae0dd70ed.npy +04379243-569b338df880d560a71c812e027f94d9.npy +03001627-45127e6f4fb5cf568173979dc89222c7.npy +04379243-7e6fea75f410181855f9913e822d5318.npy +02808440-79ace304188699fd5fe7cbb6d6b5e421.npy +03636649-81bbe86e17196c2fd0db1e44373ee2d4.npy +04379243-2bafe9aa12aa1d3bfebad4f49b26ec52.npy +03691459-b0a331fd0d599fe8e69f17d076308b42.npy +02933112-6098dfbdd0fc78a321e96d7b34bacdcf.npy +02958343-d2efbf5a3b7ddbf94c0aa7c1668459cf.npy +03790512-ea01df8a5deb6b278e5369269261b398.npy +04530566-a2d4f32a82902118aaac2db0a60f403c.npy +02992529-c43c9123ed893de5a0eb5a85db887292.npy +04379243-10733a711fe254965d7786e1df78254f.npy +02933112-d17b46d9ad9378209c68640456c0e.npy +03046257-a545e60aa1f2e13bcc84fc85b2c06435.npy +03991062-61e5f9b2abfe02ac93271d2223fe04be.npy +03001627-edba8e42a3996f7cb1a9ec000a076431.npy +03211117-aaded29a2283bb4c4920a74a78f531dc.npy +03761084-a8574cd983b761248a5e8294bc48dc55.npy +03691459-a9d7e7bb4d72c52f1574d21c0c95092f.npy +02924116-f5636ed22f1a3daa193d7855ecfc1bd3.npy +02691156-9441549e323552f2f001dddaf44c449b.npy +04530566-1660bbd9c43284d98bfe41fc81907f54.npy +04379243-1fa211118fcf90d858df8eeaf3dad1c.npy +03691459-2d408222b334fec71b45df3fb820c9cc.npy +04256520-64f47c058d0a2da68bc6f322a9608b07.npy +02691156-541c19fe42806c4d26360e1e29a956c7.npy +04379243-d19b4bde0766723c9b3bb0ef2a08be04.npy +02691156-3109b3740ac1a056df55310efbf4c0e4.npy +03001627-59529dfd60b211a45277f07057e8ce87.npy +04379243-864499eb14b077b4e5aa1f8c960ae63.npy +02958343-2894449c2f1992bc3a65ca10b9ee2981.npy +04256520-1d86fbf39c3d2954222713fd18dc031.npy +02933112-a38f20793fbbd3d3ff03fd9a67a9cdfc.npy +02691156-959f28c6724979ef9a6e43b878d5b335.npy +03691459-15c6b5792b19af3fe99c48db5f195989.npy +03325088-356f8deac817eab7a0a07918e742ff41.npy +02691156-93c38745ac281f6b8aeaf14658928f6.npy +02691156-efc7d4fb87937413dc13452e3008005b.npy +04379243-e1c190513b084f4c4804b5831b58a04d.npy +03046257-cb6ee0f8931923cd4f262ad0a8c89c0.npy +03046257-94d692071e8404ebc0aaedf10d776af7.npy +02992529-c7407877d3325f7f391258277c122351.npy +04330267-72a0fcf0b41e788935914415372cbccb.npy +04530566-635bed8b6b180fa3e65273dbd0c0f949.npy +04379243-584d3ed9669b1fcfbb7ac4d22a68ec08.npy +04530566-7ba8d5a8edb7ab991f377e6c4dfe0096.npy +04379243-804a9b89e0279aff1ed1d681aa8388f6.npy +04256520-525c959a4a09aea164def4b29bf333db.npy +03211117-f124d85da3ef5ee5fb51920a0179fa71.npy +04379243-8129d4c51abc3356bababe11fcea8796.npy +02933112-1a146144063c778cd0d447e37edd880d.npy +02828884-38e8a36cdd879fd2d6f2f8f659863647.npy +03001627-4003f4046a3a5ed9297936c81e7f6629.npy +04379243-731b5127b72cbbd9b9a17f7cc0030785.npy +04379243-d6580bbf1220d39ede270fc3c23d78b.npy +04379243-6375351785793a96412608755666abef.npy +04379243-c8062ed073ce04058cbb8bac2032149c.npy +02691156-1943ee06ecb139819330265a9fff38de.npy +02933112-24da7fd5e33513814da5feafe6f1c8fc.npy +04379243-d2beb9795e88d3dadcfd6ca2b952d624.npy +03211117-f3d4cb310a6106f5e66202687a227eab.npy +04225987-393ca71bd734f3071082f2ea630bf69e.npy +03691459-35982cb980f6916c2633ff66beb9cf31.npy +02808440-c04531f473baa75def0b2fc3511b6fbd.npy +04554684-c1d4c8c438c4bfb346cde67a6a1ea328.npy +04379243-8dd1ca36888301919fb4103277a6b93.npy +04256520-93b4258c377ade381deb48513aeadf93.npy +02933112-9705e66769fe130add7092ed47061a36.npy +04256520-ae2c9a06d9f7076532388c13cc4a0ba3.npy +04379243-4b8e0b22664904c1c8b8dbae22c1c086.npy +03948459-6c805c53ada82e954e77d7996e16376.npy +03261776-3a6dd2e7dbcdc49d7eb37dc0a59a307f.npy +03001627-da7b1352978b35c1490ad276cd2af3a4.npy +03636649-e99793b871d27333d42b9650f19dd425.npy +04554684-a6f649b55bb9fdfa7a1aca5b147accc5.npy +03513137-92c11ff47a2d1a4f673a614c45f3afe4.npy +04379243-186f6c911a4255bc1b17743c18fb63dc.npy +03467517-4b006452e6cf43d53ac61a2f8346a8f.npy +04379243-688a2fcca4d94685a11f6bacf5c7662d.npy +04379243-b4c54426262f142fc16cddb2140115a.npy +04256520-530fc7ae6a1d6a40e830a5cca365799a.npy +03001627-5a7ad45fa4672684f63bf7d908efc575.npy +04379243-b86657d541c2e26a4197bf8bf6f07b46.npy +02691156-a153353168cd47869a6e43b878d5b335.npy +03001627-671f35148ef1cb2fc0806ee26b689c99.npy +04530566-99a27d7e2553c629b0828c4cf6b95ee9.npy +04401088-980cefc1df9b24458b13932a0c28e98b.npy +03046257-21fecb28d1c8ee8c6463df620b7b4cbc.npy +02958343-c44111ca55c697117fbfaeeb4819ffd2.npy +03001627-d892a0fddeb963bdff4bb1e34fb13b70.npy +03691459-54681e2434fdc9ccd747b49524a1246e.npy +03001627-a469bcecc0a03db7d40dff3e049589e9.npy +03001627-75f4282ca1df236ebf08050442fade6c.npy +02691156-28448469f5bce47b4ddd8a480b571bd7.npy +03001627-32303484de7f1998f8d44451ec1ac05.npy +03467517-414302b6fb93064d6b072a28b9bce334.npy +04530566-c9bb36ffd5ccf7584cbfeb2946087e59.npy +04530566-269ada03c39d200498a4434c6f79eefc.npy +03001627-4ed0eb4f4e7ea0952efff55e0bb2e42d.npy +02933112-1a1b62a38b2584874c62bee40dcdc539.npy +02691156-b2b1c1d5c757af8a7209009cfb89d4bd.npy +03001627-948f1555282e27da190c615a2115d2f7.npy +02828884-a557114149ae934819420b7669e7265.npy +04379243-e9a68d0ad5177d24ba5342d638d0c267.npy +02828884-c50e2c7a82ab0362c69be1660283647b.npy +03991062-f2599921c8e0a76ea4e7499e379fa4fc.npy +03211117-ab68830951b9a5a02ba94c8f6eceab22.npy +03636649-c8ba5b8ad05d553acd017fc6c40a6bea.npy +03513137-cdbefa5bb13ada4a52fafb0cab311e6a.npy +02958343-d4251f9cf7f1e0a7cac1226cb3e860ca.npy +02691156-d0e517321cdcd165939e75b12f2e5480.npy +02958343-382496958e58e9a0658e57fd275f6bed.npy +04256520-c63d2ed731595cdd8cbb8bac2032149c.npy +04460130-5495ec547c13d8f2de1c31612629d3dc.npy +02933112-3b3a1bfd87c87a184b499a9d711de5a7.npy +02808440-53b67010fcd56a163321831d2245cf06.npy +03790512-ef4bc4af2b7ebf42306928a0ea1eb003.npy +02958343-7e5b55d43322de49295eb8d2a941a3e1.npy +02818832-edf13191dacf07af42d7295fb0533ac0.npy +03928116-68472f6ccc7296ab86e51e6823d1498b.npy +02924116-9a5ffdbb89d171e5b5b0c584eaac6c4c.npy +03211117-1c47397db49047b9d35d1c787a8f626e.npy +02691156-b88fef1090e6d151b3f2b01de37c0b29.npy +04379243-401fe961ec7b0cb5dcfcef693e7ec696.npy +03636649-6b130799a53c2917cea97147b08cd8b.npy +03001627-b4827a7b42d68aadbeab82a04eef83b6.npy +04379243-e75f2a369eca1346b157bfb9ccdf274b.npy +03636649-a90fa89d0cb8ec989cd3f9e8648111d1.npy +04379243-d6d29b0c347f2ce23002761e7a3ba3bd.npy +02691156-8c1d67bf88f34ac55823df672991ed66.npy +04379243-adc027df0d7ee0c9ccce4c6d5bb195f.npy +03001627-e76aad9a92f83d70bda72093f9b5aa73.npy +04090263-487ef6821e82c9548839ade0cf1fb995.npy +03211117-e6bedde4571506491fde762a4c6848dd.npy +04256520-b2ea31ad8b8b3e19994626ba7fe8ddf7.npy +02747177-ec1c1aa7003cf68d49e6f7df978f3373.npy +02933112-992e569c61916848e26ab56647fa5b85.npy +02691156-6ca40d19374c9d735c5f85af1b625f04.npy +02933112-4b67001c30b3a68be4e346ee2650d150.npy +03593526-1a7ba1f4c892e2da30711cdbdbc73924.npy +02992529-be254a4f3097143fe0e25464307430b.npy +02933112-687a33b0fd4a906dc2185cc0ca1b306b.npy +02828884-875b1307c76566c8d0d4e85a15f02eb4.npy +03001627-11dba3a8d7b7210f5ff61a3a2a0e2484.npy +03691459-359d760f7d8fc091fdd1073b17e9e51e.npy +03211117-dfe2e7c66b4063f79a6b496c6e9f4c2.npy +03001627-533650991ca60fbfdbca69f936e89647.npy +04090263-d9180361e225bb418bfbe54b5d01550.npy +03337140-ab029c1aeeffa5a4794a354d0ff88088.npy +04379243-a358b5f98f632adcd1fbf79741fcd6d6.npy +03001627-bc46b7460e4476d351e0e6ea07e9e2e4.npy +04256520-615d9c2b37a3616ace8417aef1b7a422.npy +02958343-3b800720bd8d41657810f4dc287137e0.npy +04256520-f756d6d576a3e238f797b840852566c8.npy +04379243-76595f5c7689a4559ccce4c6d5bb195f.npy +02828884-162550a8510464d97881b8f7aa99120f.npy +03797390-57f73714cbc425e44ae022a8f6e258a7.npy +04256520-35eeee5f998f24e8a505985405786f0.npy +04379243-b41cc94ebd03eeb2593ebeeedbff73b.npy +04090263-2d49519d725de02396e5f13299458076.npy +03691459-94abce2eb2c9567da7729f9969cb563e.npy +04330267-3ed7ea7c49a32247c4c2cb2195d7bfe5.npy +03001627-c65f9af5b5a6cbfe5936c7265c890fef.npy +03001627-4c8cb8be444fd405bed1bd9593e318c.npy +02958343-3c02c18d64d3f13b8c988ea512260358.npy +02958343-b5b6b09711cbee6daa44bfa127abe4bb.npy +04256520-a10a157254f74b0835836c728d324152.npy +04460130-d143fcdf4e9810f13488053ccea5d42b.npy +03001627-ea7337dbfced9674d2844b25962c000d.npy +03636649-f228f6cd86162beb659dda512294c744.npy +02933112-a71fa3fbcd132c39cf44224546cb0306.npy +03085013-3f34b7f6ef1fd8e7891aaffa5a7c7cad.npy +03046257-e743856943ce4fa49a9248bc70f7492.npy +02876657-b362273df5596c7e7f095f36ba0999f4.npy +04256520-2a9da31660f0c0b73505e48e4fe20c28.npy +03001627-a1f46215051dec0871a782a4379556c7.npy +04379243-fa010af968a0e1635ba41eea807f5d3c.npy +04379243-4c15f432da3400ad2404817055fb55cc.npy +04379243-697e5edceaffe68e738e43095496b061.npy +02958343-12410830e8a5067c69576518bd9bfe48.npy +02818832-806145e92798a35f15dd7d7985e749c1.npy +04256520-f5ee22abc76f7491cc9651014a82e2b9.npy +04401088-8ec44fb44e4a3224795284068bb430b2.npy +03001627-fc3d4268406b396e71a782a4379556c7.npy +02691156-adb3ea03d7b954255e9e2656aff7dd5b.npy +02958343-a34260b8cdb1ec95b63de680261b9e1b.npy +03001627-572da8680677fe8937b2bb75885cfc44.npy +03790512-e033e7dc322bf8a133735c05ad7be6dd.npy +04401088-8f3250e029d561341b92a1339af2f7ce.npy +03467517-4899c1d7a3af5cc737058b1eaa7b4b1.npy +04256520-8a0ee11e68d4565d72e26fa14efa9297.npy +04256520-d0b06478f56a1306e8f8c11a24c52ebb.npy +03046257-448a81d7afd06b3d2a548038c4031d1d.npy +02691156-fabe8fdc617e3aca2bd098b9203af.npy +03325088-cbac6ded2160f1beb362845c6edb57fc.npy +03001627-5128a385e9c90443febad4f49b26ec52.npy +04379243-3439020f6fd015c02d51eba7952634c5.npy +04379243-4a3839f687aad9122d98de61f824e5b2.npy +04379243-3459eec8eb56fa312bac236fe109e385.npy +04468005-56687a029d3f46dc52470de2774d6099.npy +04256520-c6fbb991bf184331847d00e95a10eacc.npy +03467517-14f88fcb1e613fc4eb792814ca6b5bcc.npy +04401088-7ea27ed05044031a6fe19ebe291582.npy +02691156-65960aceecc9d6f88388594197e843d8.npy +02691156-bf5d6902e75fd8812296d88107d065f6.npy +02828884-e55f19a6d411966c6bf2e668f01c16f7.npy +02691156-b4a420a55d3db8aca89fa467f217f46.npy +04090263-117be2f79d591136ed9c5b25fef60d04.npy +04379243-8bfacae2de0067cfbfd72d7396bc040a.npy +03046257-19162323595891b955f46d55537192b6.npy +04468005-7d9cb763f622e2aa90f5fac3ff9f322.npy +04530566-e36cda06eed31d11d816402a0e81d922.npy +04379243-d3f4d13ab71856953f5dcc11a7c57129.npy +03467517-4e73161a7ec1b50e4616d9b0c69933ac.npy +04256520-a1b02adc96a97e176eb9b08c8a74d159.npy +04379243-366902c0009575664f856154cf68897d.npy +02933112-c5aa72cca5cafd3f842982c980a38094.npy +03001627-9e54053a1b16299153c5215ed09cc4b0.npy +04379243-ca2070bf7d1aa372cb922bcc33df0268.npy +03636649-cec61b6fb378925e498725b9a1405ebb.npy +04401088-c71acd79ec4cf1cdd11ec2c68afc26e4.npy +02691156-22d9a4a9290e8f09112a90660b187a10.npy +03001627-490384776503eea9e2dee6f9fbe318ea.npy +02958343-32189802f3d95fa46c56ebce3aa49447.npy +03001627-5af850643d64c2621b17743c18fb63dc.npy +03001627-7e9448da23c3387754e9211d1e7afbcf.npy +03691459-9916643790d32d0dc4529c39a8e542cb.npy +02828884-ae635fcb688b88c757411f16004b6df.npy +02992529-76781e8b967f98b5a0eb5a85db887292.npy +03636649-5a79339279fb7173fbdebca9f6788597.npy +02958343-6d01a15517fcec07a546b0c1c6a4821.npy +02828884-691ca19f8a2324652056b4bd5d870b47.npy +02828884-143032619a82710b2056b4bd5d870b47.npy +03001627-d66de4cc1dc6cf5e8f8c11a24c52ebb.npy +03624134-ef0dd0f2af9869325867e536d32c89f6.npy +03001627-2e9e0711c4f8e6c6f51f77a6d7299806.npy +03001627-b6ff694af011b45f4f52551bb6d0494.npy +02871439-70bbaab945da20bbcbe8623e8d104185.npy +04379243-3f036c403ab34bdac3bd24f986301745.npy +03001627-5229209bf66b6657b11ae648ea92233.npy +03636649-e8e4f730f9bb892a85245de9410e292e.npy +02691156-97a6bb84720f250122df1994a149e700.npy +04379243-d83cfb75c24a8a89eb0ce5843fe6b264.npy +03001627-672e20cc6ffa29d41c6aa36e5af1449.npy +03636649-e685cd3f7a980812e94026ea66f4d4bb.npy +03211117-8449704b3c3c290ec5243a0ab191990d.npy +02880940-7d7bdea515818eb844638317e9e4ff18.npy +03001627-e63546037077f0847dee16617fd6925f.npy +02691156-123ba1ebe2ee533ef0c45eff2a917cc9.npy +04090263-19d5298e49eb6e5a30b14dd156373f09.npy +03207941-b5ca6cded4b23f2455b2aedb5bd199c6.npy +04379243-7c793900baa4ca16371fff21f277e702.npy +02808440-56defbfbfd46b4533321831d2245cf06.npy +03211117-e52a477d9b54dbd5672efd73ea104790.npy +03790512-cbf639979de64e14739936b7765e22ae.npy +03636649-30464d7e164a40aa2bc52a80abcabb17.npy +02958343-b811c3c5ac8eeeb2f63ee8a34069b7c5.npy +04379243-d26eacf8d87a522647839bae1bc65257.npy +03001627-8191bad981637a71b356ab8b24c147.npy +02691156-7182efccab0d3553c27f2d9f006d69eb.npy +04530566-863fd298e6ea46a5614edc3c9b2489f4.npy +04379243-841f48a81cf3f066ac00fd1150223027.npy +04379243-7730689fb323f88555f46d55537192b6.npy +03001627-a13a7a1c82bafa56188f1f634a0f116e.npy +03636649-3cca977e9e6ae9e181a172d69c52a28a.npy +03211117-cc7bac4f85cbd7d68a04632e06812aec.npy +04379243-312a5be8c4449afa456cbf78e1e89022.npy +04379243-6240ad3b8776b5e88e4f659f0755a47a.npy +02828884-25876fee744f8f8dd45380eb90f62b3f.npy +02942699-9db4b2c19c858a36eb34db531a289b8e.npy +04379243-c75ad4217e58ef871833a34736708547.npy +03211117-a33702c33c345df57dee7bb3061fcbd3.npy +02691156-525446bc8f55e629151f2df200a24ac.npy +03001627-d02fc4ae6bc4278b68c4c9cb55925fb2.npy +02808440-2004425c4a997e33a7287f0d359a1a39.npy +03636649-3f22e6719decb1bb3a9ec79b9c5da99b.npy +04379243-5f188ef6d852a85c8d0180586cee2c13.npy +03636649-e655d36c391a57c156ca893ec1044405.npy +04256520-9e0071fda87df6892e73d126bf16e692.npy +03636649-7e61de32ddbb59c89450c010f9b3ff4a.npy +03593526-8b1781610ff164c7ba5342d638d0c267.npy +03046257-aec546edcda7c5abe579ef1e3d185e3c.npy +03001627-90f8e6e1694039c0142c8d1dd30ee99a.npy +03761084-30e4d5f28706a95abf37a318b55c6a3c.npy +04401088-6fe550e061e70579a05d3424fd8d541a.npy +02958343-2df225b8df2633c231141a7d4d06dc13.npy +03593526-5cb41c58e0bb0b44deceaec2593e1649.npy +04225987-980af78085bffb43d790b0d3f0ce898d.npy +02958343-4c3fe644e76bb94fb3cf5236f651a8e6.npy +04530566-bb601d5ded9bdc00746ffcbc44510229.npy +03636649-e529fc190753cc9df647dc544bb0ab61.npy +04090263-5e7afb318ff701583018d2d3c13a7462.npy +03001627-adcc6534d6db1ff9dff990aa66c50fe0.npy +03001627-fcfb3a50acf5e83ecc0484ea4f50062.npy +02958343-943be90f18274083becf71e2e014ff6f.npy +04468005-e52819162400a82a54189e414c6ba9c4.npy +03636649-154c35bf29fa227df51f77a6d7299806.npy +02691156-a0d63ee7fd87f93619ba010ddb4974fe.npy +04379243-6449378cb78f081b2369c46027bce7af.npy +03991062-e4b68a848bb9677e34c8ebd75c7d8f3.npy +03001627-28a0b2a5afc96922ba63bc389be1ed5a.npy +04256520-37cbc18323826bfb19fb4103277a6b93.npy +03211117-eaea42ae1a406492df8cce42a274b981.npy +02691156-89175682a6cecf548966fecb9138dba7.npy +04256520-54a08dff9191dff13462c3e6678345f.npy +03325088-3b0a1265844b0a54e7ec4274d0a48ec.npy +02876657-77be452b59bebfd3940806ade53ef2f.npy +04090263-3e4cc718eb6aa9e4559750dd149043e5.npy +04379243-905edb931ab4be1e27356ce25a15eb6d.npy +03691459-9f7eb24e82020dcf40df330a2f73b17c.npy +04379243-388c9f343896272813126e7abd481c60.npy +03001627-3c83d6ad882270287ad11050da24bb12.npy +02691156-910bd9a7d9ac4738d5c4dc314e25b351.npy +03691459-73a695a6323e1d38eb5f0682bcf1d404.npy +04090263-d1be6a2cebae5ed7609e2d916fa0da27.npy +02958343-2ccdd6d8db5a366f93680c5a9a367b4a.npy +02691156-c76f2214e133a81adbafc7250d0654e.npy +04379243-97af27d6dd13962fae9714d138f9ea9d.npy +03928116-899c7d740d89ce5740332412c5d013fb.npy +03046257-ff3923d3ee5855ae13b6a765d5fd3ff9.npy +04401088-5f600251394fabe6808ca88aece2e3dc.npy +02958343-d164a37bffeb5a83f04c8b6c3407554.npy +04379243-5c1d815561a7725496c29359f424ce25.npy +02933112-7b97739140eebfefaf8acdb77a4cc720.npy +03513137-7c3bf8abf7b2b41e172c0c1bc4c72a8c.npy +03691459-8d88dafbfd4200c772e8dfb640f12f2b.npy +02818832-a207c52399b289be9657063f91d78d19.npy +04379243-58fc0d5a44ebbf194f6edfbf4641cd2a.npy +04256520-8f23005418fee71819fb4103277a6b93.npy +02828884-9027bc9728f006bb40f0ac0fb9a650d.npy +02818832-290b083404ea24c87ff6ace05b36a5.npy +03642806-5a13f7551c20eb29f3ebfe51dc60263e.npy +03624134-891b987aff4eef786600258587aa4835.npy +02691156-56c827003a2fdb16853d2b3113ecdbb6.npy +02958343-91c12a0bdf98f5d220f29d4da2b76f7a.npy +02818832-a0078daa6d0328026ef2f8c390381ab2.npy +03001627-8e55684da4fb8219d3f6d823f04dd65.npy +02691156-b4cc2bdefd4f9ce13f4d6518603e8629.npy +02876657-e4ada697d05ac7acf9907e8bdd53291e.npy +04256520-23c4b23f2e74d6232fee6b7db2f5f826.npy +02992529-8959f06b36d90e6a7c4a9987d1ab61dd.npy +04530566-c3648d0cd141035428cf87eb5ebe5e6.npy +04379243-1952d19986c5f122fcf7c0d4b65182c4.npy +03207941-e7323270ebc99539121859336e292a5d.npy +04530566-7488e965278a8b8524e54dbd7430a489.npy +03046257-7608f3f2d484aadd5887f1f81e7530ec.npy +03001627-a2b55fd7ab49da518a049f37ab48adf9.npy +04225987-24e46e195f4907887a70e5e6aa241c88.npy +02880940-f09d5d7ed64b6585eb6db0b349a2b804.npy +03001627-9884421ce028e9b1d2ad4916ac26e560.npy +04090263-193e079f24ac1ded1153b2cafc57da88.npy +03928116-e99e6a956739d58f62f4bcc4369f8010.npy +02958343-ef2655aecd7d8f2b6fca0ec9a39d7a9.npy +04379243-eafa1680912b4ee3391e4d6c585a697a.npy +02933112-4bd1e17e8bfe8d5622309d9bc2301ff1.npy +04468005-47c0481747741fa247367565b9fdaec5.npy +02691156-6cf2f9112ffae7c3be54b70092ca256.npy +03948459-c5f8a50d7f32abef283f56573a59ff6a.npy +02828884-739d41c59dc387e575f9747ff6fb5e8.npy +03325088-f2c9422c2c427a8f3321831d2245cf06.npy +02828884-bf7342b225f836a9d2b12aa6a0f050b3.npy +03001627-ff143c09dbfb0e8029e513fd785f7886.npy +04379243-299b3728b46d7a4de343d70bc2971644.npy +04379243-ad86ddf54e0db02c5d91cd746759626c.npy +03467517-97aebbc8b63432d3d2f0cc036969ee4f.npy +03001627-69a7ed6a13ef4b2edf6cfab91d65bb91.npy +03001627-452115e132539be4daaaeef365d8f6e5.npy +04379243-683fd587db784b87a71c812e027f94d9.npy +02691156-fac4af109beb0108b4f192eea1889928.npy +02691156-48fed12884533a5fe48f6bbab67fa514.npy +02958343-ed6780486efd79a9fc3898548dce2392.npy +02691156-8c746468d3dcb6d3ff3a35e90542981d.npy +04379243-db20d1cc56356476a58a1de596e6d773.npy +03636649-7bd642ba9f7cb683fcb8d8c6d4df8143.npy +02691156-7f6af37cd64377e1cabcecce1c335df1.npy +04090263-14ae67574004fc83dd0a2071dde26395.npy +03636649-77883e18cc08859ddb1afe6c464e7652.npy +03928116-438f64dd9ff80bfddd5efa4c0e7932e.npy +03001627-9d28a066df22319cca2e16d6cd76503c.npy +04379243-cd2a53371cacfac49a3528690d225ee1.npy +04256520-d377dbbf7b198ad474fedb3ee91ea4c1.npy +04090263-cc353b464c22be528ae80165ba928e0c.npy +04256520-a875e8dc1a39c769440e386b5061b2f6.npy +03001627-e3d23dc47ddd9620c9be65dfbd21428b.npy +04256520-9d436dcfd61622d6199833105dc1a90d.npy +03467517-ae28c848f2655f8bea94ea0f135d0e2f.npy +03001627-7186f1e8dbcb3e8a116162acefe23592.npy +02828884-e1ce45ee8de4436655a9b4fa7594b177.npy +03593526-8661762e0da6a8a29d3d767e1bc88d65.npy +04530566-3897d265d993ee2a1fabf3cbd0fc77bc.npy +03001627-11525a18678f7ce6ae1e1181f20bb9c8.npy +02691156-62d03831457b2fee62347b4731688b0f.npy +02828884-6d08f3c059e674dfcb2a965e75be701c.npy +04379243-7bf5f689da285153583ff8a5fc7c1869.npy +04379243-6b276165b6118e85ad312873b158ac49.npy +02808440-41d90b22f1c6a4a083b345c7947a2916.npy +03691459-f75f60a086094c27e5096e2c6dd4fe11.npy +04379243-d05c4f1b47e37e574b3c42e318f3affc.npy +03001627-9bdb034f30c404edba1028cd22cb8779.npy +04090263-271e58c2650147829a6e43b878d5b335.npy +03624134-11c987c9a34457e48c2fa4fb6bd3e62.npy +04530566-1e3f014e8eba0db7fa575e221973fef.npy +04379243-77d20db9fe05302376e9713f57a5fcb6.npy +03001627-8830f76c748f09ef3e870ba5db422375.npy +03593526-f8f5f60f804f0cb32ca2d100d9fc2f99.npy +03325088-17025bbed6ac4e92f25bf4040d22848a.npy +02992529-558c9b7e854db7da21844676433a0aca.npy +03211117-5bace77f1df591e9241640224e45ebea.npy +03001627-f6810de4042cc5ce57bd4bc6eae9b341.npy +04256520-a8b0e2a953f3ab6a68b3e52c71552a50.npy +03691459-3c71e2ce15ec92e9c8ae2f680beb7e46.npy +03790512-c2d942244bae1557b37378f3c85478b4.npy +03001627-9978e73fef1857bcac6b8e58caf61f95.npy +04379243-49eda1b86917d3d7d0a96520c31993ad.npy +02828884-4cd4797320eae6f90dac09d2827796c.npy +02992529-a860adc078391edc6774046e1fe3165b.npy +04379243-995f33073ca76ab69856fa70a578baeb.npy +03001627-9dc454ec0b5b7b50e45ef4135c266a12.npy +02933112-365b6a92fc2f46294da5feafe6f1c8fc.npy +04401088-bf259988d2e8728c391790b8b8084f0a.npy +04090263-81807680baebc5975516c1e9dd717741.npy +04256520-12c6a146bde9f6f5c42c7f2c2bc04572.npy +04379243-a6947349fdaf27ee9cba29f8b9fba633.npy +02691156-db628662ba1cac04b627754c4259e985.npy +03001627-84d783ab90b79f8036b0f2a1430e993a.npy +04379243-a4d27a18402f6f4511c3daed4b8d9da2.npy +04379243-75b3ffb0c09ce8b5febad4f49b26ec52.npy +03001627-ee8208e26cffa9f8ba208e534614d8c0.npy +03991062-3222a71a73df75a36a808760ea50bdbd.npy +03710193-293698b318418f16635f2989c7524167.npy +04530566-91a124454518abb7f2ad837508eb2db7.npy +03001627-b9a7bbf1e0b08853bed1bd9593e318c.npy +04379243-7aeafb18b724738b9d57383d20e2e6b7.npy +03046257-a6b58e9bf4b74ea461e381b34d499d82.npy +02880940-d162f269bc5fb7da85df81f999944b5d.npy +04379243-109a8d453ce93a6fc21b51dd4113da62.npy +03761084-1f50be38c10cc2201c8302bff3c63802.npy +03691459-2629234a2fa847dd9b106ceb230ede0.npy +02747177-f76b14ffc2fe6c7485eb407ec5a0fadd.npy +03325088-38d17c83d5c891a2c36fb70296e45483.npy +04379243-b1d834cd686cb8b8477f06cc543186ab.npy +03001627-447a5eee395026fa8d09bc92d0fc6d3a.npy +03636649-f842fd7369833b91b7e3a72c32cb38c.npy +03001627-60186a5e4e1aee8daf8fee88d245152b.npy +03001627-a62bf8818c8aec7062a510b8f97c658e.npy +02933112-64af194c4c53040e492d9da2668ec34c.npy +02933112-510fa8653c10b0d1ccd0340812259a39.npy +03001627-606cb23f9a7f23ef51f77a6d7299806.npy +03325088-647209d564ed6d174b47d0a1f007bc8d.npy +04554684-969c60ef5f2c2fe696d5fa1ee6ada8d1.npy +03691459-6aab9afbcdb94edeb59e9758ae7f41a7.npy +03046257-f57ba7abc40fa531e8b2e9c72a02f109.npy +03467517-2e4ec0874ea34a50812ca0ac90db1c07.npy +02958343-a1e3c4be68cfe110d9e74b7f1cf9cf3c.npy +03337140-a369ef0e532948457283e1ee3c77e168.npy +02691156-7b39d993f6934a96b08e958a32ef3184.npy +02747177-5bc989c9ee00622278353166fcf5b850.npy +02958343-4e7d91a6e2300d88a3049d0dcf503cdf.npy +02958343-18244d93dbd2afbebda733a39f84326d.npy +04256520-61711ab3e6fe99ef1c6aa36e5af1449.npy +03642806-da0f6b3a375a7e77e963c7e7c24b8dcd.npy +03642806-22389f9c3c049ce757c29983a611b1c6.npy +03467517-a8a9da30d35cc70bd57700c05b1862d8.npy +04379243-9f035e68630d704b46fb9c38320df24e.npy +03001627-f106bc80265faaabf78fc6de5952fb84.npy +03790512-30f5eec1a7fbb5884fcfb655743e93d8.npy +03691459-16ea8ecabd3f373bdef52d9b75805a83.npy +03211117-32413d2f2103b3a5286e185ca42b30ee.npy +02691156-b10ab8efa0aed59e90baeef8ba5b93e5.npy +04379243-ec34ee731c9dd55758df8eeaf3dad1c.npy +03624134-80f0436251c2108fb6bde4b7e6c6613.npy +04401088-2293983c6f234d94e304974abc9afad9.npy +04090263-ab4fd00b47d9d6f4fb5c1b0f759e2bc1.npy +03001627-26421cc00c639ee55a5324f7626af787.npy +04379243-72cfb60a075369ab7252c133a7e17d94.npy +02958343-7bdcd746432bf123416a3426987b1133.npy +03001627-56902e76cb4f1039c482eb499cc8fbcd.npy +04090263-b27b78d3e1c97180fa9286f039319ff7.npy +02958343-f51555db645f14468bac13e007a6e9.npy +04530566-a0b661c93028d7de798832e32e32aae6.npy +04090263-eae96ddf483e896c805d3d8e378d155e.npy +04256520-a9439ca0eb112e7782287102d4d0c28e.npy +03001627-f1188bef2980d2c985b479b317175b55.npy +03001627-9b9cfaea2a7ba04c461ec9f1803b17a7.npy +04379243-e089dc57993ffcc72fd098ed2128156.npy +02958343-8c1664cc8771aa3fce95c44a0ed1e01b.npy +02691156-79dba7fc4ba0829d62b600da24e0965.npy +03467517-39a2bbcc322da804b78788f924c5f0e0.npy +04379243-527b2d1e964f056383be1aa5a5ab0c80.npy +03001627-fb847cd696ec711197f2016c3d6097c9.npy +04330267-60727797b710f68659a84e2e2b7fb62.npy +03001627-2621666fa21488a4e922ceea1248b9b0.npy +03691459-3bf8ec07e1643746b319b8417d912123.npy +03001627-d92f4a4f2faa545ed08f729a736c90d6.npy +04530566-f66bca54b97bf719b1bb46d2556ba67d.npy +02880940-326c6280eee2bf74257e043ec9630f.npy +03001627-bec151e32bbc7e9b28c54e8f8953f499.npy +04090263-213c8d7870b4bddf320c2b53dcebe82f.npy +04468005-3244c30d7fa72016dc14ba0818ee5cec.npy +04379243-96aff91d7898cb1358df8eeaf3dad1c.npy +04530566-57a8ccaf2eb8d6a3924d278e5faa7137.npy +02691156-aa780af4d9cc83c3669c7dec71cfc5b0.npy +04090263-cf72122ff9caadf0622bf4353f4bc7c7.npy +03636649-ad17118799f11952a3721d780ca17da2.npy +02808440-653dab02848c6090b362845c6edb57fc.npy +03001627-e29fb377ebf475c51b1a00a31bfed97b.npy +04379243-f28e030e715b9d3e318462aca9e62b6b.npy +03691459-4227748867df8cc020363e2561dd589a.npy +03001627-ed1816d4dee58c7ddc809959e304d48.npy +04099429-60e62b419220c21e1a18bc096aeb4c21.npy +03211117-15ccd76ba83a2e02b0f9d182eb000fb.npy +04379243-d1fab6f92fb0682763a371f6fe9862af.npy +02880940-260545503087dc5186810055962d0a91.npy +04379243-e86ddb9617b8c44758b3fd27263469a1.npy +04256520-3e499689bae22f3ab89ca298cd9a646.npy +03211117-af56bcebf21951faefc87a91fe7ba1b0.npy +02818832-af840a4bad942462938fba07665a5a0b.npy +03337140-551404936411078ce5d6e9371bb5c33.npy +04379243-8b8de5b5ce7fc61def9f898cda0ff409.npy +04256520-f76d1470e843601f14c803eab703899.npy +03001627-c3ebc70a348051e1af7c7ad2549a1b15.npy +04379243-cbd1cd9b5423f890beedb4c8fd29e2d1.npy +03691459-1ba39460a5e31c722a813544190dbe4a.npy +04379243-5f1ccf0974b862c6f0d0eca70b77de34.npy +02992529-dca3f5a8ab0b850c8c8e7e9e3310fb01.npy +03624134-8ded17ea250fa58dcc34b900bb2492e.npy +04090263-2d203e283c13fd16494585aaf374e961.npy +04379243-4739bfb9ab23e4b92a87c4cb5e925da5.npy +02808440-b5ebd151fc2625da54d7082b34825ef0.npy +03211117-c57bb5a71ebcece8751bb40f9a4c6ba5.npy +03001627-6a9dce6566cd61652b339ec555ba3bfc.npy +04379243-5dfb4f36101a933ae1f4ca4f393a5a35.npy +03513137-354b570e62b161b8b20f6e48f6a30cbf.npy +02876657-a1858315e1b17f57e1507433bf0da3de.npy +04530566-b6ce7ac71fd3e33617a96ef097e71178.npy +02958343-12cf05b9f5f2d2c195c8d3a7db4dbe65.npy +03001627-f4a2478ebfac3e56b0957d845ac33749.npy +02691156-75705b82eb24f5ae23e79e99b949a341.npy +02691156-f1df46c588524ee76aa3bf023a2b42a5.npy +03691459-58cdb18878bf9e42d00d418bbce73381.npy +04379243-1a8fe5baa2d4b5f7ee84261b3d20656.npy +04379243-1d332d00746e2dc0f8fe975c2cbdb85c.npy +03325088-114546cb7b19119da70cb86be490e5e.npy +02691156-fc2d2df18182df8c82a2a8a82be86fd6.npy +02691156-9159a77918eb86cf408508ea36928b08.npy +04379243-6ebd63203c1ba404f51f77a6d7299806.npy +02958343-ad45b2d40c7801ef2074a73831d8a3a2.npy +02871439-40f49755a7a7e10effcae7f0dc8a7587.npy +02691156-c0c49c529f1ac5d8ca8607f540cc62ba.npy +04401088-95e61ab6f817d7ffdf3f86c9fe70c0ad.npy +02992529-cb9e8cd0a29cbb26b6d41c42f7ade8c8.npy +04090263-124fa4277bd03c74359ad7d9ce49f504.npy +03001627-a021adf9bdfdcff68d12adb6778d2a90.npy +04379243-453e290f4425e0604671fddd657dec0a.npy +03001627-5402eecc67e489502fa77440dcb93214.npy +02691156-fbf6917bdd86d5862df404314e891e08.npy +04401088-84cff93cb8ed08e55acbb5d30672759.npy +02828884-8450be279a0ea0b555839db883c17775.npy +02871439-4784aa14cd3a65a1898bf206629dc8be.npy +04090263-f6e2f5d6b724d8f855f41a702b987e76.npy +03691459-c462e3b75f570a3b42227a2ba4dff5ab.npy +03325088-142ee2de14c410623321831d2245cf06.npy +03001627-ef76b9cbf76bad40586ef70b3cee4240.npy +04256520-cbccbd019a3029c661bfbba8a5defb02.npy +04256520-aef8e3f17370fc8ecc98452c8fce6b43.npy +02992529-e2ffd39f88dc381c3455cac94a339dea.npy +04090263-55fde587d83088b39a2ee232a197081e.npy +03948459-9d5e90c0d6e341093e63a7526ef5b080.npy +03691459-59b78ba40b16eafed6baaf394ad18924.npy +02691156-c087319ca6126c51c5b0cf694baa734f.npy +02691156-2bc0d99cba39f7adbbf3143b1cb6076a.npy +04256520-395e53e3fbd2e717557ab4b593540354.npy +02691156-2a895d17616bcae1f361e4786a4d3c00.npy +03790512-e553d75a3635229b429f1c522640e6f0.npy +04256520-ad0e50d6f1e9a16aefc579970fcfc006.npy +04256520-68f6b68bac9f5d64d929fe644a1325a3.npy +02691156-e557af9d5aa40f424d210d9468aedaf2.npy +02691156-494a1698eb82572c3df325aac2f73830.npy +04530566-8e06600c02764ee98aa3ca9bfd776ccf.npy +02691156-a991428cd388fa7278afdab27190395e.npy +02958343-f6e5c35314beee84618e9d35559b7aa.npy +03001627-24445a532ce3e18f7b5f4d129cc2873d.npy +02992529-ce0d1ea23002e463861d8a7d0e05bb62.npy +04379243-551bf4f010f155ea4718e6c48e1ed95d.npy +03325088-5ae7c06613656ce8db0923ddab67dd72.npy +03001627-d9ce33c5f448815d7062f2d72cde5c95.npy +04379243-3c4c8e7ebdb95c2089a886870891682e.npy +02992529-7434bc601d949333cd5ca8d1acb8ce0d.npy +04379243-c5143483b413b4ed6991c1a663897b1e.npy +02691156-8c42e3042a4beaa7d5c40787c7bb7824.npy +02933112-64b8884bcd36c6fef94d7e6d8577c8ff.npy +02691156-5c9b09738d7920f0546100d9c41f5274.npy +04256520-c4e36c36679f27887586d00bc0d54b2e.npy +02958343-957a686c3c9f956a3d982653fc5fd75b.npy +04530566-b090b42f3dc0e7a4aa7c6f19b4833a28.npy +04379243-630de8111b5299f5f51f77a6d7299806.npy +04090263-28444490d359fe49cb833b31b53d151.npy +04379243-351c0bb85c887df27ff6ace05b36a5.npy +02871439-d66cd9f08956a1627d1b264ceeb294ae.npy +03001627-39ac0b216df14eecd225e12279334514.npy +04379243-e9cbfadc69d199c6368aec320face349.npy +03001627-b0849a1c01da76eeffa41024c63fa9db.npy +02958343-9c35f00f81110738783854950b26f0d3.npy +03001627-48106a12bdc3f7d8f5ee22e800bb9145.npy +03211117-740c4c76185ae7ef91a491e8257bd6fe.npy +04090263-4e817fcc0fcf1ba0b2d09bc8d348e46b.npy +04530566-6c9020061d71b190a4755e7555b1e1a4.npy +02808440-544762f1081340bd3af30a3946d92feb.npy +03046257-6965979c0f35f7adcb51c5ee8218e4ec.npy +03001627-659fdef8de4769079c251b4a7838829.npy +04379243-38b0f5874f16c1264307817adcff8140.npy +03642806-679bb4a724b1e2bc3339d8259ddfa7bb.npy +03636649-b230c6d9aeca66e52633ff66beb9cf31.npy +04256520-24f03d70f686533d7583d8e3d877fffd.npy +03211117-bb284aaeb7ccb54b5c4dc8ac281ba59d.npy +02691156-989da7f7bce36747c6c291015ab44100.npy +04256520-44e151bc576b4b059a46f459dd13f5c2.npy +04401088-cb21dc07d0ca602b151d8b52c53b90.npy +04379243-14e5e4db3246dacff12d7184a2ad3430.npy +03001627-4ccc0a3cc38c41af666bebf1a1d4e946.npy +02691156-1b300fd9ad4050e6301fa0a0663ee996.npy +02933112-b1e2647ec67a6402d616724413b4089e.npy +04379243-90a1748069ca92df9667b9ba9d06c778.npy +03001627-fb6c81cc88761a927cf3afd3f215c3ae.npy +03001627-8bb9a20b7090c90bf2356faf7e20b90a.npy +04379243-f92b1c64b0306322de6ff974c28c2f8b.npy +02933112-6db5a05080eb2480f863ead9331efd45.npy +04256520-d5b99ed4075d9ad559497798da6e2013.npy +03001627-8c81ff18e04584547f409062bafc8e2.npy +03211117-aa73f1b28817376c6cf19e722198d69.npy +04530566-3bcfc7f00e9fb213846571d66928670.npy +02958343-adc6f0f3274cf92cd4f6529a209c5dc0.npy +02933112-7238faf31667078b2ea98d69e91ba870.npy +04256520-b913678e74f02db521f0090670ee931f.npy +03001627-611f235819b7c26267d783b4714d4324.npy +04401088-7fa841359a3dce3dbcb8492ce3867c34.npy +02828884-247227d258f2c239d4d8765e3910f617.npy +03001627-f6cb298705842600bd259faf16bdac27.npy +02691156-1367266dc0a07c925d4533028830a79b.npy +02691156-5c74962846d6cd33920ed6df8d81211d.npy +04379243-1c40ccb81c862cbf595d2b7814efa054.npy +04090263-c39040b055a5ba329a2ee232a197081e.npy +02958343-3a5357aba2201fb03f823401cb5b3c88.npy +03513137-2171c3694013b15177b4e19e75551fd3.npy +04256520-325003759d3fefc7615ce01bf34878f0.npy +02933112-22cbdf59fb7fdae277b4d8470453cb5.npy +03001627-71c83afeb7e203e1bb7d8446afd650f5.npy +04379243-d386586a2fef0389393a1ce5402b0d23.npy +03593526-724fb5eb32401b96ed681532841d3af9.npy +03710193-dd76ca1f36937b5e558d3001d2e30ac0.npy +03046257-e51d02a4b1ff76d2dcf98ea199a73d39.npy +04379243-42191edf2eddbd733def89b32cef8e45.npy +02808440-ce8ba9a23d9fb8ac125fa9990176f0d5.npy +04379243-87385a994745e92cbc052c28a9e28ccd.npy +04379243-15bcc664de962b04e76bc197b3a3ffc0.npy +03467517-a26782a7130d5b76cc5a6997e65650ba.npy +04530566-dcb9f686556399a51a57c39f178ee66e.npy +04379243-6183e3d4c73872cdc955e5ed03ef3a2f.npy +02691156-26e10058cf9835aaca8607f540cc62ba.npy +03642806-81bc775eeb14299279510444cc61f839.npy +04530566-dcb390b2e8e5093def84f4e0accfb14e.npy +02691156-eb60d49fd5cdb809e6a2524c335c48f9.npy +04379243-1805ca3ac2779a443eec26c23f5bc80b.npy +03948459-aea1db1c8c014314314ac38f6030684f.npy +04256520-b581f1d0e58ef9db584536aa725442da.npy +04256520-961a646cb33dc785b0ed39ef5ec2add2.npy +02958343-a5dc2526c9ef78b96212c8f6cd06e.npy +04401088-7a1eba075f17d7b0a456028305c31de3.npy +03001627-7f5d8154877887727efcd98cd5f24de.npy +02933112-d4fe9416de5e2a95b022c94235bc8601.npy +03467517-e175f500370eb8f9561dce3fe08634b7.npy +04379243-1b805da9981a6393f454e62143e2dffc.npy +04256520-fdcf1197a5bdcfc1ab610b0c94236463.npy +04530566-c8dcc1e4f2276ef1ca6895dabdbc0ada.npy +03624134-925bb684816592ce35f686496653f774.npy +02808440-5af2dea565f2cd7138da322e72ae3fae.npy +02747177-ea5598f84391296ad2b12aa6a0f050b3.npy +04379243-1040cd764facf6981190e285a2cbc9c.npy +03691459-f2bb5c899ac2de670eb1591edd539b.npy +03001627-1f1a9120cba6c1ce177b3ebe695b7c2f.npy +03207941-85d91f3e489df57d14b35a7d7cea7130.npy +03001627-174019d47144a9462fa77440dcb93214.npy +03624134-9968b313d498ba92bfdaede1c9f37e88.npy +02958343-306f684fa89eb73ee151bdef07e713a2.npy +03001627-fe57bad06e1f6dd9a9fe51c710ac111b.npy +02924116-56a660ccc0a78a5d9c96fa78389d2873.npy +03001627-d8e2bf1107567774504721639e19f609.npy +03691459-c6eeddeb0366b4b6cf584303d1a1b5a3.npy +04379243-58a9e0e6fc43ccc5db32b682f6360550.npy +04379243-28e64eefcada205fddf120185fc0b2a0.npy +04090263-81593386d69131c5228625d43be3e606.npy +04379243-1c70e72ac0eb77816349f6b5431fb3d1.npy +04256520-546a90c5b673720bdb01c957364e77d0.npy +03211117-dd724473b5eba80421844676433a0aca.npy +03001627-a487bfde2aa50faa6d7bcadc05e0f4c2.npy +03467517-9dcc9c7653ade6f363e148e250c0340d.npy +02958343-f92aab09a6a1c6556c23793d085f1519.npy +02933112-73789bb6c0286415db823df37b893ef4.npy +02691156-133937bd45f953748be6919d4632fec1.npy +02828884-807b854a7c35379af5779d217e69b7a8.npy +04256520-ce46ea86a7f7a77b3adc3470b30138f3.npy +02992529-2b48b14e226b131af3b2c084b195b056.npy +02808440-8f7672193b88c72db8724a732b3d4cc1.npy +04090263-c446a7135467cd83e906ff5bb78d7b1.npy +04090263-3a23773469b2bfa8c12463ed30107df0.npy +04090263-661ad35c5c3a908c6d1e04c7ae242f3d.npy +03001627-fe6b3c001a86d844d5767a0de8dd037e.npy +04530566-854728b0055ec423e4f0b6b21d3809cf.npy +04530566-a443271055ad0ebccc9f5b25407f3c72.npy +04090263-3b614a18f9c8eecbf0fea2ee98610322.npy +03636649-84d66f07cafdfbc4fcb8d8c6d4df8143.npy +02808440-b73dc1a43a1f4685e06a964c79aed206.npy +04099429-e04bda8655d9e606ebcdf982796b4fa.npy +04256520-be1eb41cc9eb4b04ae685ca100c909e8.npy +04379243-5d6b4205111991c879170a5f8beda902.npy +02828884-781eb96c0a6ef0b48a51001eb8d95d32.npy +02933112-763d3c4ebccee884da5feafe6f1c8fc.npy +04379243-45c2a08625ade6e5e50eebdd2d05baeb.npy +03001627-9b275819a433a9c733e4fde2bc371944.npy +02876657-2db802ef3de3d00618a36258eabc2b9c.npy +04256520-354c37c168778a0bd4830313df3656b.npy +02828884-b71a0cca7ac86498430b7446f9e1252.npy +04530566-bd4614ae4c709729f8527bdfe6691c9.npy +04379243-a364b8af9a8d28acdaf1a853214fa9f.npy +04256520-e86d2ddb1e38d2e082db9fca4b68095.npy +02691156-87ac28e0b2342ac19a6e43b878d5b335.npy +04379243-de90266b552fd26c2ebeb1e6a8111f53.npy +03636649-35bc2c88e20e099db8bed6beeaf025b3.npy +03001627-f1a1bb6ad29d703078d928ba1c4a6f75.npy +03593526-1a8f9295b44b48895e8c5748ca5ef3ea.npy +03948459-8c944c84863d3d6254b976bcc599b162.npy +03636649-427806f30c61059c22e05b5d2ce39e3b.npy +03001627-410146dc84b6196230fbe480cffda9d3.npy +03691459-158f8a4ceaa281ab2bf4f773fe0e622.npy +04379243-90cd6fd66e29d712486040c0d9e85846.npy +02958343-40f160e49a6d0b3b3e483abd80a2f41.npy +02691156-f04fbc2423b13da170832200321e72bc.npy +04379243-f2d39c20369e9c524b1c88aaac3e0ad7.npy +04554684-d5ad82f383a9536d46cde67a6a1ea328.npy +03001627-ce055b7a4cccc7e182db9fca4b68095.npy +03001627-24b5aa5ca592ca5764945fb936667f89.npy +03636649-46aaf3bca1d0a3e776e9713f57a5fcb6.npy +03001627-ff5a945aef7a68ffcf9ff3ee543c2925.npy +02808440-536cbcc72e3f648fb362845c6edb57fc.npy +02828884-e4b80a7e381c6ef0f4215050a7660e65.npy +03636649-54ad0800a524a96ee039576a17a0737d.npy +02691156-d12f7698698bbc8f9b10643ba761a774.npy +02691156-7b3ef304a0088b39112e53a423c9745e.npy +03636649-a172874df5369cea1e70766334ac46af.npy +02691156-6d52412e798efdeab87697d3904b168b.npy +04401088-30efef3eef4b37eb9ed75a6428ac0ca5.npy +04256520-58156edc9c54973014038d588fd1342f.npy +02808440-7fc6a3771c2018d91884c7a487bba311.npy +04379243-93f3d802ab5132d162079c4c0e1b031.npy +02992529-67baf038e83456967f521a3dcd28e9d2.npy +04530566-586154b90852a5c2e0a6b888ad6abaa3.npy +03001627-37645c4e5ddb142e89955e67129be104.npy +03001627-6e965fc2145df32f4d678187b8261d95.npy +04090263-124f09d314c2c229331960c3710d952.npy +04379243-b45217934564854288e0556a2aaca7c7.npy +02691156-19ff8fce1658f864ca8607f540cc62ba.npy +03211117-8a7712d5c8614b97974e278a62ec98f.npy +02924116-3ff98b31a921fd0f51dc8a1ad94841b7.npy +03467517-8dd7df733a5ba17acae98171fea031ef.npy +03001627-a32e7b7b9e2ec5c351bcd597cb80c1f9.npy +04256520-b501220805eab01a6599ee0a44605cc8.npy +03001627-b3ef15af53eff822423da7f4f4231bf7.npy +03467517-cd17325861bcf9d22b24594c4702f953.npy +03001627-369caaf3ee33837ff2c0848478a667ca.npy +04256520-69b501570e12c4a12c216c5e0f221195.npy +02958343-69986baabb9cfdd1b1bb46d2556ba67d.npy +02691156-97e58a98eeee184565d73e2944dbef1d.npy +03001627-a808d40b66123c7ae9602306ed19eab0.npy +04090263-d7bcb405e59d20a112b38b1d99376c0b.npy +02747177-a97bd9998d12467d7275456565149f4f.npy +02691156-5c63ad3688c623b1a787d03c28977672.npy +03001627-4c1d6b12b48a80b0ebd10747ca93b13b.npy +02691156-caab31ecfe961086bc0909d98a1ff2b4.npy +03761084-cc959a175b783b95de8982fc28ddacc3.npy +02933112-4b06417d98fabe3b4c62bee40dcdc539.npy +04090263-3c92069416189d7fc7b525efdf38a3c1.npy +03624134-22671e883ceefd85e41f3b9c5c62b1e7.npy +04379243-33c6e3b21a67b750e78d7b497732dce1.npy +03001627-9c88f3031c4a660da6fee8e2140acec9.npy +03636649-d2a4c36321c50c06d28b52ade6c7e48.npy +04379243-6688fbb6e3fb092eb1b6b0c5ddacb607.npy +04090263-ed502e8af9df3df2c933c3e835f6d18e.npy +03001627-1f8e18d42ddded6a4b3c42e318f3affc.npy +04530566-f45d51939d8ee9122698fe11741f2ba4.npy +03001627-263cb748cb81e69cc329e2758ab09ecb.npy +03001627-2ae5f2290acacd7fd5b24cafb84903c7.npy +03001627-b2bb0eb5670296ed5acd449a2ae99009.npy +04379243-b074b6460f46170660edf8bc2f5c8881.npy +02691156-873f4d2e92681d12709eb7790ef48e0c.npy +04401088-ce0d1ea23002e463861d8a7d0e05bb62.npy +03001627-94d55392edad30d35192e08e628ef9a8.npy +02958343-1c7a2752e1d170e099399ee63318a21b.npy +02924116-92417d3466ae88bd563e41b6f7313ed7.npy +03001627-2182398f0f8fdd81af7c7ad2549a1b15.npy +04468005-8944e940719c340b9954eae9164faecb.npy +02958343-631aae18861692042026875442db8f4d.npy +02691156-c9ba5885f6ffc835a8cba409c4409ba9.npy +03001627-387dc2c22bdf6d2a6df42853f67b5836.npy +04379243-d796405237a2721937251258858a7a58.npy +04530566-8a779f2127dee13b28db2e450917f8b5.npy +03211117-cb0bbe56efdc7c2590fbc3d35abb4728.npy +04090263-75bf3b1cfba045819e172a9318b5b7f3.npy +03001627-264322794651490ec0d3c02f7e255b2b.npy +03001627-b659a94c6643282f504721639e19f609.npy +04379243-c271d00152fb6363214a15a5a42c49c0.npy +02992529-49a51e66314253d3f2a0433fb7c53e0f.npy +04090263-66f804b1400a139ab5aa01b641366717.npy +04401088-29f27d4472a17e723fd445ae159c2cb2.npy +02808440-97f7ff0b07dc37c18dcb895d63e0dcc.npy +02691156-1db7bca33ba446aba5cac89017eae8d1.npy +02843684-2293faef03d23ceecc1908493f380315.npy +04379243-6dbfbee18b2e149c71a782a4379556c7.npy +04090263-38a906533b048ad8341b8a806253912c.npy +03001627-a2824df0ddb58c0617b431cae0dd70ed.npy +04256520-2ea00b36ccb8d3baefc579970fcfc006.npy +04379243-153d0c95cd2981a46a76e23e6f966dea.npy +02933112-c09fe6e32490f4511b17743c18fb63dc.npy +04256520-31ae964a8a9a15e87934a0d24a61231.npy +04330267-34c8bf6c8dc677995147c3e89e46a102.npy +02958343-91f59dc0d204dc64260a770f90456bf7.npy +04379243-f864677894410315ab610b0c94236463.npy +04090263-af877a0a066fa63ffd180252c91ed0f3.npy +03001627-df6a3bc55f86781218930ac69342cc5c.npy +04530566-c9d1159874c934f16f1b09a7281511b8.npy +04379243-2892423e515ee379530176ce07cad21b.npy +02808440-61a19c2b6dbab7be1291d1279f7bf122.npy +02828884-9f51e1e44bd439f32a0697dbc1a34813.npy +02691156-530540dc968b396d7f3805c1aec66f00.npy +02828884-71970f9a11b0b5bcd7262b1b986920e7.npy +02958343-a53f8a03871fd1d1c4e15ee0eb85afd9.npy +02958343-4baaabaced0c9e0ac0e3666c7d0ec7d0.npy +02691156-67c8fe06930cf8788762ebad71629f9b.npy +03001627-e821fb5eb1e21368c341afa383659322.npy +03636649-39fcaf51940333b46ab88e9b8b75d248.npy +02828884-879fec928fbb6ff36b95ce378e386482.npy +03001627-ef89cc3901e27fe0c5cedfd70cc18cf1.npy +03710193-c6bc72f24af5ef42531a9cd007e29075.npy +04004475-6120c9dee581013e940d5ff3114b57.npy +04530566-94ddf20a9a6e035e85f7a3de54751f1b.npy +03691459-a58fe03c817fd0311ad88f716ea80910.npy +04090263-ffe20b3b5f34fbd0cbc6ff5546f4ec42.npy +03001627-3586ceeaea45b3598f5bccb3529a48d.npy +03046257-cea1956637d8e28e11097ee614f39736.npy +03001627-dddbd223b3bbfa8efd93c2ac42357c74.npy +02691156-fa5c740ca9192b708e8131a047a07ce1.npy +02958343-1079efee042629d4ce28f0f1b509eda.npy +03467517-2352c23fe113d9c754ed8bc786bc3eeb.npy +02958343-a053946cd9048d46f200a72c9245aee7.npy +02691156-fbcc12c5530ab67cad659a74e36b6387.npy +03991062-e7bd0fe36857413d236f012e801e4d49.npy +03642806-7b4260884a1dfd76b080af510dd640b.npy +03001627-4b2ede169dcc83ce4591019e9d133858.npy +03001627-9d20e4d4637e66175836897f0d296c15.npy +03790512-5c0eaef35c2911ac1d7cf2c1f472233b.npy +03948459-fe62130ce6fcd9b77754fed890b42399.npy +04379243-94a458e0932f189f755454a26c190c21.npy +02691156-5bea928fa9b2255ca8cba409c4409ba9.npy +03046257-f904afa5730aee1ff4700e9a01318eca.npy +04256520-fc24d012f6b12036aa1f8e0da2ec8814.npy +02691156-b089abdb33c39321afd477f714c68df9.npy +03211117-f84f47c7ffe0e49e44175b4dddf5be08.npy +03636649-40e6433da380273d128650ca4a80c238.npy +04256520-36d4a1a290c541aa21d25a6a55757584.npy +02691156-10e4331c34d610dacc14f1e6f4f4f49b.npy +03467517-d3684d071dcb6bffd3193ed047bef161.npy +03691459-8684b67d71677ac95ab0bd3eb49f9a70.npy +04090263-214dd04f06d5683ed17373579e6fd9be.npy +02818832-ecc1de9c62c1dc0559c46748f8e9b30b.npy +04530566-389d122da973fd5cd812ac1676a22587.npy +02958343-6bbcd5608ddf871a4cdd04162f008888.npy +03001627-c166f67f391022d31205bd848315f04.npy +02691156-2b62a8a0bcac6f22e1873a3963e0d14.npy +03636649-8010191bdd123581a7e0a9557e913c86.npy +04090263-66b3e706e98f22c7324318e511b81a2e.npy +04256520-e75990aa494d4dc7371ea954c8939aa.npy +02828884-ba4ffdf3eed29dea9f8c3d2002c77ddb.npy +04530566-cfffdac8ecda7575de208b4547dba0e.npy +02924116-d88be40c27f7723237d34ce4e00f2504.npy +04401088-9e2169e8e8186a3a27bac6c74974cca2.npy +04379243-c37912d7dc6504e3b7977f4fd4002c2b.npy +03001627-8c4fea06a94d7ecffd61677456447e.npy +02828884-b8f462d89a31e95b777c3ba457301e8c.npy +02691156-257d7b5ccd3b5c7f7c5c969e221ece01.npy +02958343-1100f9eac1ca426a3dc399576707b67.npy +04379243-10b0d655bf4938eae1ab19b3beff6716.npy +02933112-606d50b144d8ca164da5feafe6f1c8fc.npy +03211117-5934ee46f6872adbf19c9a0272a2c26.npy +03636649-4d6bced89943df73b4edf02c99e16daa.npy +02691156-b237bc484545cb46d8f63fb451ae8aba.npy +03001627-4ae3ee61ebfd4d7bc05575120a46cd3b.npy +03001627-2b8e3e95616a5fedabf945c9a80683d1.npy +02808440-8113b0f14206155a74f9a02bc96d14ca.npy +04256520-1cdc625f58dc911518af974879cc252c.npy +04256520-51396ab24d97a1bb245495d3641f83a4.npy +03001627-81889ad00179daf8adb91c074e672e22.npy +03636649-4c1912cae9d53594fc26f53456c58834.npy +03001627-88bdfdfb2a8b94ca1b17743c18fb63dc.npy +03001627-d0cf0982f16e5d583178d91f48c2217.npy +03001627-a1e16e59abc3fa56bf0788e630e3deb.npy +04379243-e36a5e4069db8198bbbe32d7a5038eaf.npy +04530566-8cf34976d5cb61b0f8901acdb7280141.npy +02691156-f5bb02c0df184488e0b6c670e0e97766.npy +04379243-5fbfc884ac25001e29426a0f57e4d15e.npy +02691156-dc03e743739c4f87c27f2d9f006d69eb.npy +04379243-317d8dfc74e872832b70eac6546e93fd.npy +03046257-bebfc25c773a5528a7f2fb8267777262.npy +03001627-2b3da2a8773d2571c3bd24f986301745.npy +02773838-88d375bc79ef32532e50abc7a1305908.npy +03001627-6ecec258a1b6fe2a6fee8e2140acec9.npy +02691156-e88a8692a22d548e1ec438f11f5ea1c3.npy +02808440-d847cdb16cae06404d059d8c55114915.npy +03001627-dfc2328946b2d54a29426a0f57e4d15e.npy +03636649-9f4b472b57e4eb76376135b28de9dd8b.npy +03261776-7da7c2b10597af90b21450114b9ae3a.npy +03001627-8945c698ec3e9d1ad9deb3f829cc2475.npy +04530566-e219390e6eb152024d0a79ea230a0577.npy +02747177-ff2f13bc0b9d4ade19c52ba9902b5ab0.npy +04379243-aa79a19ba1fb3cd1febad4f49b26ec52.npy +03636649-91d0d5301653c3b33da8556a622a2ae1.npy +04530566-a728c32eccd560e69412a62cd6b1bf5.npy +04330267-d58cf869f92da04198253a3e4a6c1a73.npy +02691156-c3408a7be501f09070d98a97e17b4da3.npy +03211117-736c5f322277bd99ff21f7d46312e751.npy +03948459-fbf675bb44706dff867ea9c96b799755.npy +02691156-3d6b9ea0f212e93f26360e1e29a956c7.npy +03001627-a3ba66bb0fbded22c5beea20858a99d5.npy +02691156-85396c57cdbf919f83467b3671ddaea2.npy +04379243-f9a795649f679b578f3be993fec1ba7b.npy +03001627-c56bca4b7f353ad86debb0a33c851f8.npy +04099429-99314b704285c0ca16e3314677399d49.npy +03325088-39333e9f93d3d3696d0157e3e7a8917c.npy +04401088-caf0f73f4a609b7a2c4e8a2f66e4b8a3.npy +02808440-32704fd3803c02d7fe52ffd0e748a1ab.npy +03691459-91f570ca6702fe4abd1cba733b111584.npy +04379243-2356544fa047516126f51cb1aef0ea9c.npy +04379243-dc4ba419b9035c4b917b96045c9b6dea.npy +03790512-5df0478fd19f0c175af8505fd49bb4ca.npy +02876657-47ebee26ca51177ac3fdab075b98c5d8.npy +03467517-49be6209142d8d1bd12eaca0749d01ab.npy +04256520-dd50bf448cd6d69016e9e510d2c2a9d.npy +03636649-8a840a390cc8ba885089a13cc567dbd.npy +03001627-51704a889ebcadb72cee4bf5d0f11ffe.npy +04530566-8c62487a3593dc337810d5f988f90f49.npy +04401088-20e5a92f95731f04c4440dd41b08b3f4.npy +03001627-6b881cd27826bd6b97a79b27e081b077.npy +02828884-4d6b053f11e784e2a136ebdce43e4200.npy +04379243-539548613fa54b6725aae1be30d7ea21.npy +03642806-2777dfcee7d0f364b0d7b0d4230df8ca.npy +04256520-d44fb796a1772d5a490ad276cd2af3a4.npy +04379243-7c29c16650cc74bcd17bccae1d897a22.npy +03001627-525776b59266140381dff5c2e57ad46e.npy +03001627-43681f9356e330b36ac40071701c687.npy +02691156-4a27a6276e748777bc0909d98a1ff2b4.npy +04256520-2bf095743bd8f21f6f37a8be59c15bbb.npy +03001627-2a87cf850dca72a4a886e56ff3d54c4.npy +03337140-9053de990d7c71e1e4cf665cc17bc4aa.npy +03046257-ba090cfc159e1495a9575f4ef037dfdb.npy +02691156-839a950d0264cbb89a162c818d22a620.npy +04401088-7552cd75673834c9c8470fd239ba13d4.npy +02958343-9cdd8cd41303cbdc650bba674124a73b.npy +03001627-39f5eecbfb2470846666a748bda83f67.npy +03001627-983414e34ee6a7966aea2f18ee404fd5.npy +04379243-d9467c88e3e26d3c4b3c42e318f3affc.npy +04379243-ba08fa516347f4e6f51f77a6d7299806.npy +04256520-5192e47e1e8267068907728f92c46d69.npy +04379243-377d6044219ec8b3063f9bdb41a65e3.npy +04379243-1f116a581f9e15e01b17743c18fb63dc.npy +03593526-5e6c6769815668b817ba4f4092c6f41.npy +03001627-f891816329ecee93774476b2e205b9b7.npy +02691156-c05bb681e0ee27e2eea65ef742e4d989.npy +03001627-fbc560d04067a6b58ce66f12ba927a2b.npy +02958343-99311deac352b9a5873751b4c304dae7.npy +04090263-f0236f202fe3588a8d4ca42bc1bef451.npy +04379243-a1f130e921df44b037135011237cc916.npy +04379243-511cf6bce918c6738e0afce805a277dc.npy +02958343-e93f88a9beb9ddbeaff90a85d875467.npy +02871439-cbdc7ed6ba5aeb2a3a272da15f3c1cb1.npy +03001627-ed6c9f6d77831e5cdf2b21995cbbbc4f.npy +03001627-50faa1777b012058492d9da2668ec34c.npy +04330267-10f1eb0113a6340e35914415372cbccb.npy +04379243-c9ad84452fe0ece05ab833c88a8efb15.npy +03691459-43990d5a8ffd32774f074cdf0a32eafe.npy +03636649-882aae761370df14786810c22b062a88.npy +02933112-1cf9f1ead192b6c9824662341ce2b233.npy +02942699-39419e462f08dcbdc98cccf0d0f53d7.npy +04379243-65e7fd8d158658106a76e23e6f966dea.npy +03046257-afeb49c6ae3977cfcb87baa8bbd720aa.npy +03636649-b7716e735dc72358182649d086615bf.npy +04090263-43d4e6583cef197aafeed2d6e5e28a9f.npy +03691459-1d4ea80f49114ec0813621823d82b548.npy +02958343-b0810f509a3c4cf895cad68eb5eb0e38.npy +02933112-47fa0f6c9b9f019742cc639a26c5af8c.npy +04330267-fa759d830cce8dea7e4bbc5bb7fd2afa.npy +02924116-f7cae23060d52bde99ebcb8df4d39cff.npy +02691156-23eed87ac79f1b152f9c405cf0817830.npy +04468005-52bc6eae0a13f93751bd803a9a30b004.npy +04256520-2ee577ae974272dc9faa444e7f5fd692.npy +02958343-8dcccd3d9221f9a0d61b6a34f3fd808c.npy +02691156-a4f5529edc990706e719b5362fe06bbb.npy +02747177-f35efdf00062e177962bfd5bcfc9bf86.npy +03001627-6a7050042fbc77d5635418e95eea8a17.npy +03467517-16afb97fe3882483cf45555a18e7351a.npy +02691156-6271b0016c5fb3bd59d2e83012533b47.npy +02747177-b77e94ab409def2b72745b90f9692729.npy +03211117-10953ef61c72aacccd14781dae25affc.npy +04554684-226f73828ad8562f4c86b1fdc94892eb.npy +04379243-68c52fa67028fceb47637d2621d965b1.npy +04256520-79edc7c4e10a6fd8b3aef1eb2166205f.npy +02828884-5be09ade953eaf6ca6910e4922d61aa.npy +04379243-5d3d9689b1447e01febad4f49b26ec52.npy +03001627-4ca29321dadaae90a516b539b31607a2.npy +02958343-ad1db5ce98d385fdd1e15301c83686f.npy +02924116-867d16b7468cf4cf75ba84a155b61876.npy +04379243-d78d509ada047f34e1a714ee619465a.npy +04379243-3c886639d67798f671a70be9f12ce8b0.npy +03790512-81e1a6c5a4de9f8f7a1f4451e23d8e4d.npy +04468005-eb35e5c9c3d0b97058a624688564e0f5.npy +02828884-ed8401565e207665f155d75bbf62b80.npy +04090263-1c4ffc878b001a097e270f84701afcd4.npy +02808440-6bf87e25ad2b7e1cdd43f423f86ddbb9.npy +03636649-cf3407cf42643d3184cd259bd328e92a.npy +04090263-9e6ba8035db3ead6cc34b900bb2492e.npy +03046257-81be602470e4fa90b2f671e673cf292b.npy +02933112-530d7817abf9b54e73f47577531a0b51.npy +02828884-35ac96f483e073faf515c76790f82ed4.npy +04074963-a27dc622395c3648db8fa1712f9ee93.npy +04379243-8bfb5dbd48e6bcd5aec454eed44c3c27.npy +02828884-6ccec23049ae42ce2056b4bd5d870b47.npy +03211117-1707d858ffaf146e640578ae55230ebc.npy +04379243-611e834a83c63f50a8840b31c6de34ce.npy +04225987-e60f8e703bf6b7e8b267718342f3f316.npy +02958343-8b7b6c2a5c664ca6efe5f291bc2f5fd0.npy +04256520-1507432d805eba8dd773dcca82f4a71e.npy +02958343-14ace3e8d05f8d21a413908c0e169330.npy +03642806-c87bd5d0b4caa95de14be8c4a6dae8.npy +04530566-7dc72dc46c46410168ac0d25269a2c67.npy +03593526-3976bd1f61e4b5c95d878ba9ec3c0d6a.npy +02691156-ed7eb0caa75661addc82b8fee1057b30.npy +02924116-923dc3ec59c733a5fa07f5a050a0502a.npy +03593526-cd03a7bd6ace5432e7a3b2beb7306f11.npy +03691459-d2426b884d1108e8bdc8d5970acdf989.npy +04379243-5929d3983eeb8d5cbf96d22e92924ea2.npy +03001627-5cdf1e5cc2fdacedb01116e8ff585621.npy +03001627-4246c8c293c56ea34b3c42e318f3affc.npy +03001627-987122b945dcf1fef713f414dfd3c16.npy +02691156-31d40e6e24511386d6d949577c389a84.npy +03046257-41d0afa958bd0621dffd9a568a626d77.npy +03636649-dacef14e18d54f3857d60a3bdfb4976c.npy +03467517-afb2a038358c5f391fb05d58f51ec4fa.npy +02691156-535dad1777edb67bbc0909d98a1ff2b4.npy +04468005-649d1dd617a2e5284f62d2a35ec091f.npy +04256520-a2a136afb803eb35cc571cd3cf8f17a1.npy +02691156-d532a5abb756ebebcc14f1e6f4f4f49b.npy +04379243-224766e5a022785af51fa0238791f5dc.npy +02691156-ddf0e3053cb1ca8f5e9e2656aff7dd5b.npy +04379243-eb773e1b74c883a070d809fda3b93e7b.npy +03001627-c967b1e07ef7fc0bebc740fe800c0367.npy +03001627-e45fb6b81247cef0ad312873b158ac49.npy +04530566-6d2c856797bc246898f9d8529de7066.npy +04379243-87dda49474723fa816a2b5862518c93.npy +04379243-203d58d26d1546994b7b33169889d14c.npy +03001627-ca01fd0de2534323c594a0e804f37c1a.npy +03001627-9e8ba34b501945d1f4b6538438a0b930.npy +03001627-6e9b9e6dbef7d1d219fb4103277a6b93.npy +02691156-dd9ece07d4bc696c2bafe808edd44356.npy +03337140-4eddd7e49d6c6d044c3aee8e9d3a6ffa.npy +04379243-30a525c7bd5ee80192b396ed960b67ad.npy +02958343-1c7ddd2735778013ce50f18f6100cef6.npy +02691156-c8db76f18f56c1344c2c88971423d0be.npy +04256520-43720278eea721d27d18877f45b7c3cc.npy +04379243-e5a84d7ed9a5ce097f4557c0cd5f53a.npy +04090263-44ab011decde6fe4c41bc86ace512f24.npy +02691156-a839884fba87173ce25031ee39d82b94.npy +04530566-5a7635031cd518daefa33903c8f77ab8.npy +03636649-a2316a225facd3114f3443b22038d340.npy +03513137-ae8a2ae90ac11bd93d4e343a1ac21b93.npy +02828884-59a3fc2f98cc53cfa13c59d3c05ad9e1.npy +03001627-d4e974b1d57693ab65ae658fdfdd758d.npy +04090263-fddbba55cea838b9b2d09bc8d348e46b.npy +02933112-7ef23a05ff56687087cffb2975eab062.npy +03467517-fba2fc6f7ab8a62a93f0194265a9746c.npy +03046257-79f572f4428ad13cf54e1b6f41fdd78a.npy +03593526-3fc4784d1b2247306ded232b3f448b08.npy +04530566-da738558b1230b8288d5590328ce0ddf.npy +02992529-26175bc1827c3569c4b311ecb3af9fe6.npy +02691156-404714cf775f5ceed32761b337f8b72a.npy +04379243-29c4539ae1760a50c955e5ed03ef3a2f.npy +03001627-fbfdc8eed6598437b2bb75885cfc44.npy +03325088-9d98b2c3591441a83321831d2245cf06.npy +03761084-e38e26de9812e1adf5f79806bd65844f.npy +02954340-9673c2be589c2b9df0d11ae402ef940e.npy +03046257-a366005a5856c873202ce3547fa5ce9d.npy +04256520-999c10445b9126fabda72093f9b5aa73.npy +02691156-26237deeb192f83d3ada73811bb576de.npy +02808440-cf565a3576331f67433b4c9b207205a9.npy +02691156-395cb914880adc105b50b4451364cc2c.npy +02958343-bcf0b18a19bce6d91ad107790a9e2d51.npy +02691156-2cd9e40d1ccb1917228c3c30d65cabe0.npy +02828884-3a85b1fd831c15bbd2b12aa6a0f050b3.npy +04401088-f1b9de7276c1b07fe5562f06ed322f7e.npy +04379243-1599c3f78f521c0c3bd24f986301745.npy +04379243-4c529b6171aabea2e8058cf23f6382c1.npy +03636649-89cb9b2ad175b833cadf6344ec272e8.npy +04401088-c688e0c0830ddebed23d7150656e0d04.npy +02958343-ded68cb3b5318425bb164ad50a9faee3.npy +03001627-875925d42780159ffebad4f49b26ec52.npy +04090263-486e685875e840dde4b30fdd654658ce.npy +04379243-7c08d40119ea39923fe3501bb9e7193.npy +03001627-654ff4d929914b7ff91663a74ccd2338.npy +04468005-45f9f9a2991b3c0b76d9bf960443503e.npy +02828884-244955211c2f3b94b821b834431f4e0e.npy +04379243-9f097427c4d2bb4af2c0658ad22a9a9b.npy +03991062-30b3abdc25299028cc01fffc6fcc7b74.npy +03001627-e2dbad7996e7e13430c589758b4b5646.npy +03211117-5cbdebf9422d9858dcabaa2ad147fa73.npy +02924116-d7ce4cd86d8d7f1637da79b407550d26.npy +03337140-f8c3c4da6560cde54c3aee8e9d3a6ffa.npy +03790512-49edb54e97458de8d373c34785838ee4.npy +02933112-910eec62d3cf0936ce5d6e9371bb5c33.npy +03691459-fb60dd3c36439d836d74ed7e4da4b6ec.npy +03691459-8d55d634810b52f176f6deb1c78dfee8.npy +04256520-dfb54a98465dffeffcd08faf4fccd0f.npy +03001627-6744d53d1557cd2443dbb6421d614c0d.npy +02876657-d2e7e725aa6b39f0d333084c1357713e.npy +04256520-9e57afbc186ff5387c0c12d35fb75ce3.npy +03001627-a551977f078f362c492d9da2668ec34c.npy +04379243-3d4a592876d60a3c0f9df0cafd74e5c.npy +03948459-c2b8580d4087bd708480d5f7e7366fe1.npy +02958343-192fdf42f5a2623d673ddeabdcc8c6e.npy +04379243-a95df9c4372e860c73eb02f1d995d891.npy +03691459-86775c918b6f4fd2f149a4641e0b7067.npy +04530566-90d83e1dde32426407e66c6e74f5ce3.npy +02958343-a88baf98bc73649fdd61bedeefabbeb6.npy +03948459-664579680dc09267e1f2a1daf140ac9f.npy +04530566-e453412c14d47ef176dfbd72ad52dca6.npy +02747177-83488978efe02f562a1ff22c35676be7.npy +04379243-d7576f0e6f9acba7d261e17fa0c462a7.npy +03325088-c2a9e63c47166a75341d61f56edc2872.npy +04379243-11bf776fe946cb7af897d07ebee05db5.npy +04379243-233c3eace6ea1267eaf288f952624966.npy +03001627-5c92b3aad6c462514b3c42e318f3affc.npy +02691156-76851aaf721dcb63509012911cf74f29.npy +02876657-bb46957091f2a282cfdfe3f21f42a111.npy +03001627-6c1352ffa574e154ca2ed12df13a916a.npy +04256520-d100d576372b75bcc6b705e3bb4769f5.npy +03467517-bf041bc9abb1114597b6cc42b1ecbb47.npy +03691459-986bd3ba96016425cc0d3a65104f5927.npy +04379243-70e3188676407076c3bd24f986301745.npy +02691156-3ac64a2c67cb44f19777d69c8d47140.npy +02808440-22eb6e2af43e6e78ba47eca8aa80094.npy +02876657-547ace45594ef71fc867fe00083d17f7.npy +04379243-1f95c9d8e65c117343dbb6421d614c0d.npy +04379243-4a519fb8089dc7d248eaa510713cb074.npy +04379243-d9c75799ff9ff74664b3b9b23ddfcbc.npy +03211117-6f7689fbca875b034302674f512c0e5e.npy +03991062-9c0a4184fb751fe58f4d17a342e13fb1.npy +02808440-fcf3ac6ac5ca3738e6b3aedd6ba272b.npy +02691156-fa9d933674352c3711a50c43722a30cb.npy +04379243-7a0eab4d41f461e980fc8e4355cf787d.npy +03211117-4b85feeead6313806329e8c7b28434da.npy +02818832-7a4e07fb5701172c862eec8232fff1e.npy +04256520-9ef9ea0de3fe64d4e7e684d25d4dcaf0.npy +02747177-69ee57f4534eb475e9bfc203f193ce76.npy +02958343-b28d1b3e81f407571c02ebb3dd0baeb1.npy +04379243-d108dd323ed295991b17743c18fb63dc.npy +04090263-4bd456ea9809a296c60369962d1bf5.npy +02924116-7a275413fda13866f81aa5c6f39752d6.npy +04530566-f02b990da656df8dba71d80f7b736179.npy +03691459-4d1061e19f05e919a5e698f08af11df1.npy +04379243-71a7bcf52da934d0f008d8a3590fb522.npy +03991062-38c66f3168743604a2c59a4d90e63212.npy +04530566-294644520ccc2ce27795dd28016933fc.npy +04074963-c21ec53c8531344b8ef01232dadbdf7f.npy +04256520-f6190e61f116d159ca119b1ec88d8df8.npy +03001627-d1291956cb0983ee7085b4353236aad.npy +04554684-2d65189ff15fe1538a8c921f75bfa58c.npy +04379243-20765ccd89f9d915d200faae04ce3f8.npy +03636649-2d638c6b6b2feb9248da169d95204ce2.npy +03624134-6ebe2a22b8d9d70862a95b942081dfee.npy +03593526-b2e502425dc3f07bfe4f69210ea5cdca.npy +04379243-8a86e3045ac5fe7e1f335cc23d448de8.npy +02958343-3ffd5155eaeab76bb17445a1c29f6d34.npy +03325088-c02a4ba752dcaefce3f7a74e12a274ef.npy +02828884-9997397f29b90af470e359f3b1d0f6d1.npy +04090263-de0f9c9b67c5f5a6422f205de59ac7e6.npy +04401088-3a8b1287aed892ba5661e3450b04a6b4.npy +04401088-ecbb1c53e881c2b25f4e4793ed432bc1.npy +04090263-ca2bafb1ba4b97a1683e3750b53385d5.npy +04554684-c667f9cf4f72ef6fbdabe30acfd2c07.npy +03325088-daa26435e1603392b7a867e9b35a1295.npy +02691156-36d8c865f766e3e097872638b21438e3.npy +03325088-5a0e759e281cfac71250bcd0500910e5.npy +02958343-39ec376b0df877986483e7894702b192.npy +04090263-f3004f6eb2e5fb8eb7a51049b27f4bf4.npy +02942699-ec28a64bdf9501161bfbba8a5defb02.npy +02691156-d696c3119cae40323ada73811bb576de.npy +04256520-b15fb2ddfff73f502cf0d9a4f66100ac.npy +02691156-5d8583703889178a8bc354dd4eb23614.npy +03325088-912dc428abd8cca1c36fb70296e45483.npy +03085013-ef3d038046cab5cabeb3159acb187cec.npy +03325088-33f6b54f6b72e64c76c18e71fd49c4dc.npy +02958343-62032b070c02c6b1570673441ebdaf2b.npy +04379243-80ef50d3e67bfa8783ca982ecb7c4900.npy +04090263-d35bd51cdc04c103882d915ba9d043ba.npy +04225987-4e19d12d0924a2f58266b26a9b45059a.npy +04090263-f55544d331eb019a1aca20a2bd5ca645.npy +02992529-c87bd717c3640f0f741e88434245c899.npy +04090263-35b5cba53b629223cc2e8ce9ba1c97dc.npy +04530566-ff70051c32217b2df671917093bd361.npy +03001627-8f09ae17dedc43c6dd7640b87074419f.npy +03467517-a78c3356a5dca4e7670b811945485012.npy +04090263-fb6e8e453293303a4721599ec64bb469.npy +03001627-920af478601258e24762da3a3017ade.npy +02818832-6193a59df632dc4fd9b53420a5458c53.npy +03001627-9cd5f64caf7077ec3266c035d8afd13b.npy +02871439-2a3ce38991b93107275d003e423c59ba.npy +04256520-65dd8c9418c29ddba066c1f884f0378.npy +02933112-68257aab07479c64854a6619c08bff6d.npy +04256520-2c3a679d6640a93abd16d4490a10a752.npy +04379243-2ef5b582482d7d52cb71061323057eb9.npy +02880940-bbf4b10b538c7d03bcbbc78f3e874841.npy +03001627-faa6255bb4de99d90606ee5fb3c339a.npy +02828884-5856737e6fc90bbac1a25f36f85c3fd6.npy +03211117-ff8418d110a5fd5211ab369e12343c13.npy +03938244-31db3f4dd9d5944c3628a80a75ee02dc.npy +03046257-5972bc07e59371777bcb070cc655f13a.npy +02958343-d7b8287ca11d565bd9bd5ae694086d5.npy +02828884-4526eecda7ff1136ad5067eac75a07f7.npy +04256520-526c4f841f777635b5b328c62af5142.npy +03593526-dc9eca5831f9d6ad230584014222e685.npy +02808440-2f5a70ee78ed7cfaca581939cd410ca.npy +04379243-1c3317b33bfccab0824080f516909671.npy +04401088-2278cc8b5a50421613fcb9cbc590fba.npy +03046257-5d7549beabcc86af6329e8c7b28434da.npy +03001627-465c2cc6917e02fec681404257d94ad9.npy +02808440-7f5a3684f57a6fe754d7082b34825ef0.npy +02808440-8be7711dfc0c7e3a54d7082b34825ef0.npy +02958343-9167cb083368cc6be3d59d595daeefd7.npy +04256520-9f57f0155caf1c15404a78e172d68d45.npy +04379243-cf10ac71297ae632f44880b8ee951142.npy +02691156-ccca0685aa63308ed54e5c2e672a56dc.npy +03636649-925fe53d5075145981a172d69c52a28a.npy +03624134-b8648ae17fb9937949f73a97204d432b.npy +04090263-5105e493bcf5e63f75a82b88fe6e733f.npy +02691156-9f21e660ba62b9c8ac055f4f708c624f.npy +02828884-f1f14399ac9684df835bac7bf872f771.npy +04256520-a1262399c6c0ac93e84291b9d249a95b.npy +02828884-6b9b014c54423664a9bf865a81345d8e.npy +04530566-1b5e114692abf9a5fdbbffe94281448.npy +04379243-b2564957632c596c2ebeb1e6a8111f53.npy +04256520-42b13b1ac18724f84b3c42e318f3affc.npy +03513137-69d70c404f47b1f9b137667443c4be42.npy +03691459-9b9b41d3d02ce68d1b009b4923bf4541.npy +02818832-babeae78f6d2412a15dd7d7985e749c1.npy +04401088-cfdd44745ba101bc714ce1441b585593.npy +03991062-d56098d4d83f5976a2c59a4d90e63212.npy +02992529-aaf1159cdc4e6ce5b2ff1d6fc3caddc1.npy +03211117-225d37286bed9bb9dbf53b03c847b004.npy +02992529-5cc54b5db73e9e1e6decf1414eac2924.npy +02958343-5d385a0a87d0df4a51a95aaa6caba1d3.npy +04379243-f82a5f3c2a57655d825da2b9ec9c8c29.npy +02958343-881cf849fb2d003514d92936db4784c4.npy +03001627-357e2dd1512b96168e2b488ea5fa466a.npy +02876657-f0611ec9ff89209bf10c4513652c1c5e.npy +02958343-8e3336175a338970a9fe1734a6086750.npy +03691459-9c98e3576baa1f25b3150cb8eff8d9d7.npy +04090263-68a7652d28ddf2035488420adf4edfd0.npy +04401088-78855e0d8d27f00b42e82e1724e35ca.npy +04090263-34d2582f7fc79e07a5fc2a01ff709b89.npy +02958343-b554614b14148e4ec0ed6ec757ca50f5.npy +02992529-641234f284243decea95e61f66327e28.npy +02691156-a1e5e9561b501f2a19e06ee1b2e7b1b4.npy +03636649-9aff9fdad0e3555c7eecb4e0df212ad9.npy +04256520-c131c9feb56c6b7a6bb6bc0db07c71e8.npy +03928116-8ffd503645f31d6115ed47584b7a4537.npy +04004475-9c6e72feeefaf01390eb32e4b2b2efc9.npy +04379243-5667350dffa82263968da786c4da00c.npy +02876657-d511899945a400b183b4ef314c5735aa.npy +02958343-db432e9f280ffb1e3dd4bdc1dbab98bd.npy +02828884-11499e2fe78c7a6d73bc78c81dfbb18.npy +03001627-30518e2d6fb5dff259d9b12c05c8f809.npy +03991062-c4ac6a5f651d12c6c6b4aaa0b0f9d794.npy +04379243-cad4cd1fc0c0952e71a782a4379556c7.npy +02691156-cbc9d6ae9d22fcc57f3efc94c2d31dc5.npy +04090263-73bf687a44580f037f3efc94c2d31dc5.npy +02924116-3e0c9a10f8e200be17b44457cd291bcc.npy +02958343-ca7202152b84a70fc6a4281cffc3c014.npy +03001627-e0c76c1c82f12df4c1e1aceb66eee9be.npy +02942699-63c10cfd6f0ce09a241d076ab53023c1.npy +03636649-cdbb91da1b21cd9c879995e59bad3d69.npy +02691156-27c409ead0c4e34c9a6e43b878d5b335.npy +03636649-d7fb922f162360b5c66a63406f818460.npy +02924116-59f6907b10ed62e475dadc997718614d.npy +04554684-592e665fa7e0a2bcc9614070d3269898.npy +02958343-3506955660641ce61d693e0a12bd4ff3.npy +04256520-4997b2b6120f84e948eb521885c87e13.npy +04090263-e5cd986f028b4e27b91a90edeb58ed0b.npy +04379243-c9e9466f782d1b4f7fdd70657322b4ac.npy +04379243-1c111a837580fda6c3bd24f986301745.npy +02924116-72271b23f406c7cef8dc13cb78906875.npy +04379243-62b17d7d8fa7ad00f51fa0238791f5dc.npy +02828884-abf095439d2d7bdb57a8fa4c1cbcf3ea.npy +04379243-9c49b5339e9f3cfa5c6b6ad017b2e512.npy +04090263-c1267e4fcd29c63b60053189e2e21dd.npy +03001627-3ea6a179fdc3c01daac8336231c53cd1.npy +04256520-651270d31b03d1c12f1d01f48e42a6d3.npy +04225987-52ffc103719ae88ef0f40fbf85e100a.npy +02933112-386bf465df74b1321d860ee2ad2a42e1.npy +04256520-d6b6f8854bda98a6ff458e602ebccbb0.npy +04530566-b4ea73d8daa2789699c1d6f5c0b53b84.npy +04379243-b2b57e89a036970d22e5ecbe03e765d.npy +02924116-b7656d749dac1071f75f41eca7a019a.npy +04256520-67626389926740a08de89023dfc7cadd.npy +03790512-f736168c42267866eba25bbcd3786140.npy +02958343-545abd37dd50dad953536e7c905b301.npy +03797390-ea33ad442b032208d778b73d04298f62.npy +03624134-95db800016f8fb955d33831e71fa52.npy +04379243-5d8ea325e7182fd84b757d0f16894ea9.npy +04379243-53cdb2389fe5a5e5bc78bb6f3ca89e4c.npy +03001627-4d6c67174bdab63ff11cd7e1bac77b0e.npy +04460130-64ae93807abcaaa38cd8eb23853c009.npy +03636649-2140c6a8b4648d84f3443b22038d340.npy +02924116-7122ccbf7cf39de6cb239ba7670e0fec.npy +03325088-c33c3c63eff994aeb7a867e9b35a1295.npy +02958343-30f4b931145acc98a3049d0dcf503cdf.npy +04256520-9be24460d1f7d084b3c42e318f3affc.npy +04379243-f74a63793db25c8911fc2b865c2a185b.npy +04090263-a9e1e9c25f250b289546043a05bd4e6f.npy +02828884-9c69b56c5867afdf5d65e445b951c79a.npy +04379243-3931ce39e77a25a9dfefa992cb59ea0.npy +03467517-dccaa9555afddd96a5c8e9fc8b2242fd.npy +03948459-e9ae98d8679409f8f52692247799a350.npy +04090263-5f69d649d9036be626b78ab29e6b0231.npy +04468005-423da92d362700483fbd1495c921f279.npy +02828884-c89d4c95f1e7c950a805114916841d69.npy +04379243-79d0985603f7ff3be6c5cd45aa112726.npy +03636649-5cfe9300f102ad65fcb8d8c6d4df8143.npy +03211117-a18316fe31d3e24ed113457aa21fa2cf.npy +04530566-2de6a45649b392d2f7051f81d65f99eb.npy +04379243-6631de96600690d158c88d30f502a452.npy +03001627-61bcde763ccbfe520ab6214a789faf.npy +04379243-ef4e5099cb7c543830bbd4cddd04c77b.npy +04379243-d073f58c96c17aca95786b1c8687acc.npy +03325088-24d438e0a5966a8316f1e46eb2815c0b.npy +04256520-feedba483f628b8f584e3f372dd1a2d.npy +04379243-587143666166faf155fe0f12b5bf32dd.npy +02924116-2fc461ae4d2b416c3ec3fbbb89296dcb.npy +04379243-612caa5ea6c888c850cf3715818ccfe8.npy +04090263-180846dd3deda6785127e0873cfaa7b8.npy +02871439-7bbd940fe725689fd320119b2e676c6a.npy +03948459-42740af029297f1d9874fa4c7b1a4298.npy +03001627-9f3ff62527bf46f237b2bb75885cfc44.npy +02828884-6798771442c7d473f336cb889fb7c819.npy +02691156-7030044b49828f08b96ae1a0a8b84ec.npy +04256520-2d5cd8bb42310f3eb04cb542e2c50eb4.npy +04530566-fe8f54e34ccfa35f3ceaa5264772e8b6.npy +04090263-5c1d73e16d1a4459b5070c7ac310bcbc.npy +02691156-3069d990d52051eb3a34c2907e8f3f1f.npy +02958343-3ec7f0347638f7a891eea2fc80d4a25f.npy +02691156-b1696ffd98c753ccea88a0a7eb1222bb.npy +04379243-4126746447b424197fcb8ee54b1a951.npy +02871439-37e570eb9cc1bc7b50fe7d207ee3a1a6.npy +02691156-53d0eca7c8ab5e644c3a35cee92bb95b.npy +03790512-fad668ac64ccea1ab37378f3c85478b4.npy +04379243-eb00a4e8b33d257cad16260d4d73b56.npy +02808440-59630f5750ba5aa46935f7e0522b9fa.npy +04379243-c77ed43659f01a0cf51f77a6d7299806.npy +02828884-c6885d073919e897de9de6d8a1c444be.npy +03624134-c30f7e40f4cc1d52344cf8873eaeb8c6.npy +04256520-c0228ff42e79e272db039d8689a74349.npy +04379243-be971a899c96649262158b7ee658e910.npy +04090263-11126129151f3e36afb1ffba52bacfa2.npy +02958343-5fc2334bf83f4c0e3505c0c7d5679ae2.npy +03691459-dbe86be505750b8d9c92e8251d55352d.npy +03001627-9b94592fe0fdcc34492d9da2668ec34c.npy +03636649-798028b70ab2a1d529c726e7d66b139d.npy +04099429-c0d736964ddc268c9fb3e3631a88cdab.npy +02992529-bcf3ca7e860d04eaf0fbb92458462640.npy +02828884-2e78dad09566bdcecb2a965e75be701c.npy +03001627-79053fcbcb68e2c31528cf73b8bd8799.npy +02958343-9e5faa247753ad479289f0a3d35e8de4.npy +02924116-cac296959eaeca1f550f48125b5f584e.npy +04379243-db75ed97a5c5234e8f7d9678498f2295.npy +03691459-3db03a00661e6113f2a29b1958708a7f.npy +03046257-e78b66ad9fac907822b68de582c1281b.npy +03991062-247237dea2ef00f444c183864792bc2b.npy +02933112-716b2e87f41b14cf48d22c298c611495.npy +04256520-4b11124f5ccf051086708ca48528bc8c.npy +04530566-8877086211c9976cd27beaa6c9701d39.npy +04256520-bc0ef0dc1d69ed4c852bb95bccedfda9.npy +04379243-bca062605b3f79b9a75c3b311265cd31.npy +03001627-24a83977b422b081eedb66d04882750d.npy +03001627-df6157db2534b72a9a293c6471e6f319.npy +04379243-8ad01793daeda43dbd71cb387c4297a8.npy +02691156-6ca6c7920c62773073d96deff5ddb8e5.npy +04256520-bb4441db7c68a4cec7c8ce3bef5c2aa9.npy +03636649-6d14f1e95641dbb329a42a0444436860.npy +04379243-a860e5edcaec268e615bcf72f8385966.npy +03593526-9b77a0f168b2b8ea620c0ff8940a6989.npy +03211117-73669f92851d3b28eb34db531a289b8e.npy +04401088-8a56e999d75c4d6e8d1dabf86742ec3c.npy +03636649-e7ffebf4dd9176542cd2160e449d45ae.npy +03325088-aa53b268354b84a1b7a867e9b35a1295.npy +04090263-5909ebf625e0d04dfd6d10d22bbd142.npy +02924116-95e2cd84253aafbc1d272dd11937e8b0.npy +04379243-569e2fce2f1ab3be617e9d9aa36a8137.npy +03046257-413c5497de808d1a177ef3150c947f22.npy +03001627-95fe1f3dec357704e27790b0ec8671f7.npy +03636649-8b712f3a63bb01061735ea0e092a805a.npy +03001627-65b8c99a5ab7eb0492ea5a71c9e33093.npy +02691156-a660b01d17f929f54e61a0c2eaaabe87.npy +04256520-19f0a14207f4f953bb1b55ae5bd11e93.npy +02871439-f364a6a23f19c5334a60c1a189046dd1.npy +04090263-3c8bf6360e36d51874b27677f8e8f04.npy +03001627-804c35699b163b7756bc5724b6282816.npy +03991062-e7d1773d6278ba1ba2c59a4d90e63212.npy +02958343-fdcc09ad608e95b4b631b59d5abd1cf8.npy +03513137-cd7ecd4007cf6738807322bc19906e74.npy +03001627-e98fc1a9b608a0c1a8760470bc8702f6.npy +02773838-c5c0f63f94ddf4c258d149fbd24761c4.npy +02691156-a5215569ae825265ff3feb917a6004b.npy +02843684-ac090163657e31d08d6b0dc9bb200f8d.npy +03001627-bd0fab2e72b445bd1e722bceee6e83aa.npy +03001627-fd8c375d0a267d20283b00891f680579.npy +02691156-5de885a47cf8aae2951971f8370d9050.npy +04256520-426d75ae016abffbdfa8261e130bcc9c.npy +04256520-c6c8b57de92a243abb3f330b15ee1442.npy +02958343-86f1cbcda59640594dde7b6e74a2cede.npy +04256520-aa5fe2c92f01ce0a30cbbda41991e4d0.npy +03636649-674a0ba32db48cb6ba2cb2a05654d738.npy +04379243-5151ae4f84a800a189035c25f0dfeb63.npy +03948459-b1bbe535a833635d91f9af3df5b0c8fc.npy +03636649-c359b4c545e5ee3efcb8d8c6d4df8143.npy +02958343-2fceea2bce91439ca26fdd1a1e470de9.npy +03928116-b04647659c599ade7fb4fbe822d98e36.npy +03636649-1d2c6757217bb2797388d403c2d39798.npy +04256520-6660af5568f1fcea324a6d32f13e7cb6.npy +04090263-9e40b56e67c305db74e18e0e7a19212a.npy +03636649-9e3905c3fe967a4dc13933f92cd75682.npy +02691156-45c963d64b8ef3de37678474be485ca.npy +02691156-cb1aff81a3c6ef71d25fd5e3115979a5.npy +03001627-c95e8fc2cf96b9349829306a513f9466.npy +04379243-e5413a9305d52482ee1a5886e50e3f9a.npy +03211117-8f577d90510e94e09506335f6ccd62b6.npy +02691156-a1db8dcb7f1fcdd597190b73ffeacc5f.npy +02876657-860c81982a1703d35a7ce4c111af2db.npy +04256520-d1c09e81d31e38868cbb8bac2032149c.npy +04379243-3f74e2274140ec70705165b0e6ec548.npy +02958343-119033fe083145e22f31600ac759c763.npy +04379243-726a974620efd98c377b9297f3055210.npy +02924116-b778f89a3aaab26c8cd65eae2089c6d0.npy +03467517-f7f1f2430ff969e9eb2f514f87188941.npy +03691459-3855f5027ab422fae6ee52444763d57c.npy +04379243-82fe7fa7a6655955f51f77a6d7299806.npy +03001627-854f3cc942581aea5af597c14b093f6.npy +03624134-6a9df664a41aa590cc34b900bb2492e.npy +04379243-fb9e9c0767a92d2e923b3c05c4c4fae.npy +03001627-49748c9b987b6bc8dbd60fb6b8607ea6.npy +02691156-6341436b6a9df0c6683651cbc8e49e4f.npy +02871439-e445595fe6c85cf17f768772b7a990fa.npy +04401088-8fcae817c180d5224208dfa1c5fa1065.npy +02828884-70612bccd74c969476c40ae77a98137f.npy +04530566-d57e124826aabbbfc6cb0dfa2f14f9d4.npy +04530566-8c3148ee031b15446e0dbba30ac27e8.npy +03001627-7595d089aefd8ed5af7c7ad2549a1b15.npy +03001627-7788afe9baeb2410e8e9bfe58361d5c.npy +04401088-c589332137d854a1808ba9235495a934.npy +02942699-21f65f53f74f1b58de8982fc28ddacc3.npy +02871439-31a777c94501faee5ab608caed81de7c.npy +02992529-16685299c37055c2be40226527c9872.npy +04090263-a5e62a05ffed4b0231f639996cb3d35d.npy +04090263-816df97057a7df79f47439175208c26.npy +03636649-80650d082f6d45fc53fa79783efbc3bf.npy +02958343-5686e48a700bf4c989439bf55b857b9.npy +04379243-6c0ee01fb43f8f46c045ebb62fca20c6.npy +03467517-cebf1d6e25e40224eb86f11fe2a7a388.npy +04379243-99f50ca8fe9b541792ed85b04a73eb29.npy +04530566-8500272b43352ae6f844b7e844d01ddc.npy +02828884-c3d8c664906eb8e57b11ae648ea92233.npy +04256520-1f6dce83e8d582e9efc579970fcfc006.npy +04256520-13f5779fa224ee03490ad276cd2af3a4.npy +02828884-a8e987a6a6486b962d6c8e51365a5a87.npy +02933112-1e91ab0d6eb0053ac59350d819542ec7.npy +04379243-a21d0b3b4ae4436e76bc197b3a3ffc0.npy +03636649-9bb957d69a2c2369c0f9df0cafd74e5c.npy +04090263-937f3a803767480efb6bde4b7e6c6613.npy +03001627-81ba974369a343d3946b850f0cd29857.npy +02691156-7d226c520a29c7705e28caa3b26a73fd.npy +04256520-b32b7dd742f915581e6dcc1ddc222f68.npy +04379243-b9dae236a2dc3476ffd5817f210f277d.npy +03001627-8b8fa92f9c677b0713decb1a0563b12.npy +02828884-efd2d13058330e49d7f638b2b2e0564.npy +03001627-25ad35439836dd7c8fc307d246c19849.npy +03211117-f675d7c91d540e6bb45df535caecae62.npy +02828884-9452149917cb2e27f4fb4dee5181bee.npy +03001627-5912ba21e93d2c5b8bd10c3418cc648.npy +04090263-973181651497efa3230a4d129580843a.npy +03261776-763f06de96ae50d5823e88e264b80650.npy +02958343-1284876ac0e2371aa4dbb766064f8bbf.npy +03797390-85a2511c375b5b32f72755048bac3f96.npy +02828884-d9432798bd2aa338ad5067eac75a07f7.npy +04256520-8f6760875b37750b19fb4103277a6b93.npy +02958343-c59c26c90a724e84ce27281f3b76d1f5.npy +02924116-afdbf161d2482dffc39bbd7cd12a26e9.npy +04468005-14e70ba7f308c3ab1112c737944f1b6.npy +04401088-a2953e7ff6dcd4465af22172f09754fd.npy +03325088-b35cb57337d6330f76c18e71fd49c4dc.npy +04379243-ed5f0875b3615861a6c03a53cf0a14c9.npy +03467517-69ce55087f8ed69fad6d53c0f12828dc.npy +03642806-a2346fd2b76d58bb2aacdb6e0b5b6c83.npy +04090263-74b965dee85e951a818accd7207190a0.npy +04379243-954f39bdb27c54cbeedb4c8fd29e2d1.npy +03261776-99a402291dee883145e2a4e5729b970d.npy +02808440-a879b178b96ede50694afea2e3c77a94.npy +02691156-cdeb868930b32468f879f4163a3ec7b.npy +04090263-ca8c360dd014910ccc34b900bb2492e.npy +04379243-5633513a1cd1adcd9e9d84e41b20ddea.npy +02691156-4bb41171f7e6505bc32f927674bfca67.npy +02691156-2e389edb9a3c0496e1c255da0d1c1826.npy +04379243-647678ff9809303260eb699207aa149d.npy +03325088-50bf9cea0963f340ee0aa55e2c8ca202.npy +03636649-8e4d5fa2a1c91f036a9633583f89b17f.npy +02958343-7f2acaeb45b72793ce6183244062e7c.npy +04256520-8b4a2a614f7b2a9510edd100dffd8d85.npy +04530566-94aeb294adb9be58b05dfc874f00d5f3.npy +02880940-ce48ffb418b99996912a38ce5826ebb8.npy +03046257-88565e0eb863eb31426db14e2702705d.npy +03001627-1926843fb9da47ad8852b93498ca8c83.npy +04256520-839807049a0c29a6ea693790a1608aab.npy +04379243-8106aef3eb88f9e4578defb131c3ea1d.npy +02958343-31cfc24310109174b11647ffa4306609.npy +04379243-417f1c15c20966a54f5039bed03ee12.npy +04401088-855a8a4c39e8fe81a060e584e7409aab.npy +03691459-3cbeb01fae7fb6ec7238b5c2712646b7.npy +04256520-b593b430e799ac4af256e6841810978e.npy +04530566-19640fee71ffa82816581cd5751ca97f.npy +02747177-d828e4f441b150b460174b3ceb24976d.npy +04379243-82109c884a0e195714038d588fd1342f.npy +03001627-2b85487133b04a543f86d4a1692234ec.npy +02828884-6c47b6b082cdd9b684370b1677f53d8e.npy +02691156-b71c16266f1674cd884ccdf529614144.npy +02828884-408ef9729c48dd40bb273d6b4d49877f.npy +03001627-1eab4c4c55b8a0f48162e1d15342e13b.npy +04090263-1caf976f39c934f1589c07868201b17e.npy +03642806-67387cc47a39a4b1cd4fb35969ac8028.npy +04379243-c15b0b5f7d835b5012660c1de94a79e.npy +03467517-727fcc85add981325e683993f34d42f2.npy +04379243-bff0d461cd0fe835b67d6c1fd03fd403.npy +04401088-257ef557fee9c083324b3288c1587efe.npy +04256520-b0ed631f887c522519fb4103277a6b93.npy +03261776-bc404e52bfcd2038538cf6df9faa9b65.npy +02992529-6e6d7c2ffadc2fad2fffec7af390883.npy +04401088-79f11cd09522565fecb1ea9fbacd5278.npy +02691156-65b12fc357604a2587b2a887422ab97.npy +03001627-7f539a846e9e88f0d9fad8aba2c312b7.npy +04090263-96c96b2569853438663e90eaf6b4ca52.npy +04530566-25c736b7ca26bcb7bfccc00eb137e6ec.npy +03467517-35e77edd3ae6ad4993f0194265a9746c.npy +03001627-2576091d2540147a473f10e6caaeca56.npy +04090263-2621cca0eaf82143f9014984f90a7387.npy +02958343-4458ed2a746e61a3b11647ffa4306609.npy +03790512-cc213702fcec23677395d58407f193ba.npy +04379243-52cb81e736aa856cbea68008b6e5c5b7.npy +04379243-5a0c76bb4dd53d13a6c03a53cf0a14c9.npy +02691156-5c306ddfcc08ea1b230ac8907b9b7f90.npy +03001627-d91457217673528ef91663a74ccd2338.npy +04379243-912c044ef5e129522c98a1adaac88b94.npy +02691156-a5beb33ba75edd59485e40e44ec62786.npy +02691156-8df8e2580639b093c1006ed55bc1a3fc.npy +04379243-109738784a0a6129a02c88fe01f2b9c1.npy +02691156-fb9deec3a422b06b609e2d916fa0da27.npy +04090263-87f0e810c573b90c803b54e9738b20a6.npy +04379243-9287845470d119bb940b945d5ba9958.npy +02691156-c57409c95dd4bafba5a118bd15e6e34f.npy +04256520-db01af2b84f8a9f615a72fd59f390cc3.npy +02828884-389f2aa083a7d732f4b6538438a0b930.npy +02747177-d7394e554aff20b2f155d75bbf62b80.npy +02747177-e500097e7023db9ac951cf8670bfff6.npy +02958343-22c0b90fbda00bb9a3a61aa922ccc66.npy +02691156-670d455bf1bdaafdf577ff4de1ac394c.npy +02924116-dd63a0f6eb852d089797a4124a9f002f.npy +03207941-f8a673d7d5e0c410d48855885373053b.npy +04090263-8f48e9f97dc644ca8752becd01cbfbb8.npy +04401088-b801c4ebbc1149b34961b0d325e91640.npy +02992529-b7ab1b6f7dc5026dea8f4709e6949c8.npy +03001627-8f77a33dbdea3d19492d9da2668ec34c.npy +02691156-8686ebc30c07b53126360e1e29a956c7.npy +02992529-bc301249d58b89b638d913262f25e96d.npy +02808440-50c67260bb9322e8ebc740fe800c0367.npy +02871439-db6c5f944751d4a0eebb0db1929cfe93.npy +03001627-a2bffa12e0737e66febad4f49b26ec52.npy +03636649-36943f6afca6cbf518134b529d13e79a.npy +03636649-55eea74e6f73173b49904d779af64a6e.npy +04379243-731561e2626163e8a4dc6822aaa2cf2f.npy +03046257-e59e73bc340207bfe214891c68fa8e36.npy +02958343-7c651c4f55c5ca57d76439fb95cdd2ed.npy +03790512-d929925b54d82db139e5b34b546caf02.npy +02992529-177a44b5e36fe9856e10bfa9f3e32b96.npy +02924116-6ec626a0a5d7c9f84d44f5db04bf14b8.npy +04379243-a70e1160739fa533f820611afeab68c6.npy +02828884-437167659b0b5a8fce8fba09dd640742.npy +03211117-4744bc26253dd076174f1b91e00d9f2d.npy +02876657-681e91bbadebeac529471183b63392dc.npy +03928116-3c9b7b7fe4a349c618dc1e4c79721773.npy +04379243-c8b3d39ca53c0cfa4b3c42e318f3affc.npy +04401088-f4eda7905f55d1b382476058422e4a4d.npy +04090263-c0a429d6e4cc9d0366597c7d470782b4.npy +03691459-3c467fca7449a857a2b4d33761839e86.npy +04256520-b44d152534373752febad4f49b26ec52.npy +03001627-631807f69f02f1785532b747eb9b3728.npy +03642806-59c7c6a65cf462be43acec71ba42b6b7.npy +04530566-c78d6f5c908e2ff1b05dfc874f00d5f3.npy +04090263-6fcfd40ef3d8dbc1046a0002e847ad2.npy +04530566-13c289d915523f2348132c07d51cd81a.npy +04379243-d3aeb75da27b505f1c9acd0bdfdc9f62.npy +02924116-d9d1d7161c59786fb58d6ede2c134ee0.npy +03001627-92b81e84090fdab2f027786820c3fec4.npy +04256520-5e3be8a7a61235dc2099f9e22ca45b04.npy +03001627-d7867d215f52107ba5e8cf3aa1686d66.npy +04379243-963ead3bc27459b2f51f77a6d7299806.npy +02880940-dd381b3459767f7b18f18cdcd25d1bbb.npy +03636649-a1db02b6b7264b6d1cf9f632ab9ad62b.npy +04379243-f8f8ff7d9cfdd395765b19233e844344.npy +03624134-cb0eaaa84ca1be4639c78a1e40e247f3.npy +03948459-6de6e56c6f7d43692866658c90231a1a.npy +02691156-de776175878f17d1f4c1adce71073351.npy +04256520-ca8c140ca26c4d6cc9b96a88ab877904.npy +03001627-6b00fdf6062389ad738dd0d3509c7e47.npy +04379243-50505520611014b07298f1711edd69a0.npy +02747177-637a9226a0509545cb2a965e75be701c.npy +02691156-4515ac65d312fdbdb63361ca9ddfc9ae.npy +03001627-f9e8a5547d89615dfcce6278f5ffb13a.npy +02691156-46f9b86c1292366fadc12de54d203570.npy +04379243-3c72ddd0dca19bbedcfcef693e7ec696.npy +04401088-aef45c975ed647778768dbb598f40c93.npy +03325088-6136a19b81e5e70954d7082b34825ef0.npy +03636649-5f0a23ce527d0be52f38c0d2792fb5e.npy +04379243-a26897b681a3841aa81634d14a6ca786.npy +04379243-d3a5f7b56e3e6e1482e6c3a4e742651d.npy +02808440-8346416e382d3a3fccd0340812259a39.npy +04379243-2dfdedc4e2d10ccbce9509a520498ebc.npy +04379243-acf0ad26f9feff411191025061735ea3.npy +04379243-8143949bf6d5e294ff2c800153491d59.npy +02958343-f4c4bc930957be4951e9a28466112d97.npy +04530566-ed94229d6bb18b783f351db9d8c0e76.npy +04379243-6def73c13a40922d9274d508495753d2.npy +03691459-90143acb141fb1cb4292de5cdfae65e2.npy +02924116-f877396a3f529e21a71edfed1705a549.npy +04379243-bab86ce3e5bf3aac9715146e52a0621c.npy +03001627-f1933161d8b49d8dfb266533561ee98a.npy +03948459-3b4f6cf1745e0a44a04d2f46d86c50a0.npy +03636649-715be273074283557062f2d72cde5c95.npy +03001627-ebd73aa8ec2fea5c36c26b54df360d91.npy +03593526-20de70652a72eb4ae27790b0ec8671f7.npy +02958343-d5d47fe322179a83473f10e6caaeca56.npy +02691156-3b82e575165383903c83f6e156ad107a.npy +04256520-2bec1d8c0e8a1b3b7b98092cf509b83.npy +04330267-f8ee8e3ec6e56b8d5dc3653f8341633a.npy +04099429-731db7871e19a2efddf75684fdf930e6.npy +03636649-20ddd6039bb61e97fa01175e0dff0063.npy +03001627-1bcec47c5dc259ea95ca4adb70946a21.npy +04379243-734c761c6fd2b260b4c161851ed2b4e4.npy +02691156-f12eefbbefabe566ca8607f540cc62ba.npy +04401088-d740b0679a9996ae56acd5d5597a72c4.npy +04379243-d65624cccd27e85ce8f3ad90cf010c5a.npy +04256520-bed08d3f3d82bd2f37b2bb75885cfc44.npy +03691459-709864406b03fa2f880d754debc41bc5.npy +04401088-832d6075c8fafe4de862e3cac45aa769.npy +02992529-ce0ad218c6b19e76e7eb1b9b386befd.npy +02933112-595999124367c701de650492e45fb14f.npy +04530566-355f5aa01c79fe1458a8952c93ff9829.npy +04379243-3763dc87aed9fd73be6b1cdaab15028.npy +04090263-b38371493e6c31ba2e2849ea51389478.npy +03593526-e51c76a9d10593a9aa5b514b364ab62b.npy +03046257-5fd0cd70a717e36914038d588fd1342f.npy +04379243-fe57d6cfb3ba455fc35f1f8a8febbdc4.npy +03001627-a02d2ef9789836981bb088904f7cb154.npy +04530566-4f245403e6366d48fb3294f1e40c8a29.npy +02691156-3c7e4628a9ea201bbf3143b1cb6076a.npy +03001627-ea19940c812803d1383b5acc757bd668.npy +03001627-6da85f0549621b837d379e8940a36f92.npy +04090263-3e25cad3c3379be6bbfe0a3a537396d.npy +02828884-53e3f4b35e8c992e954bfb4cc0842c46.npy +04379243-68794d2e264ea2d75cf2470a6eb9a24d.npy +02871439-6e8a54f0f1d0c698b4dbc260302abeb4.npy +04379243-ff2b5b315173f3244fb315ce917a9ec2.npy +03001627-470ee88d9cabc6028be5ba60d0b948a6.npy +03759954-46e0c1b2e0635a111ef58b31c4ba0d15.npy +02691156-2176fa9f69e5e1dcca8607f540cc62ba.npy +04460130-6e87ad11e8c3c273af621148ecacc588.npy +02691156-480d027eea9830b511c04c8a3e94088.npy +03991062-da9efb2601fd872d2ef1c225dc7772c5.npy +03001627-41ceeeab52fd3ed3a341228b21d337a9.npy +03001627-98c78b59a5d97666dcad73f240f03a20.npy +02958343-9fc18cf33ac91041425b2c354eccabaf.npy +02958343-51d9af66315d76f9e6b335b85df4d203.npy +03636649-364ea921dbd5da869a58625fdbc8d761.npy +02818832-37ca2cb730cac30ea42bba87fb4a4a5.npy +02924116-fa7c1c950b99389e5deb3d7d530fe881.npy +03001627-2c03d0a4c83f0e89488017d48a7f7eb4.npy +04090263-31f4d647d59ecaaa5d0dded52efeb4fd.npy +03593526-c0d6cd0537d0fcc8235e3c816d887b3.npy +03593526-a2da2f83adf04371d680196133d8b70f.npy +04256520-69eaeff55a5a9c5568d1b9a1d97e2846.npy +03211117-f7effbc133537f0aa5d0c95600bf54cb.npy +02691156-ee92bc35ee989f59271b3fb2659dec56.npy +03593526-712db68c0889d82925e0f641bff885da.npy +03001627-38abcd9d3157f7fe71a782a4379556c7.npy +03001627-be67f51c3df7dd165b9ac5a4b39649c.npy +03211117-cf4c78178c9dc8c292df4681ccc21025.npy +02992529-3d5401f4ecab9be91aec2282dd8bc87a.npy +02828884-b773f8d5af2c1087cb2a965e75be701c.npy +02924116-5f67a64225eee1d28e7126bd2d50de26.npy +04460130-547e1ef6922840b23899914213d0efde.npy +03001627-7e4025dcdad5415386c701087a194026.npy +03001627-6a8f1dd7e0642ca4b367a648e9b173ab.npy +02691156-ebda573deda43034f2b0736dd4d8afe0.npy +04379243-6962c6b32fdd0a6d6b872683e72852e1.npy +03948459-17e9d8c1b7e7be20213f0776ba8707b3.npy +03001627-4fe3809c20606e5369d8d5b35c38db0d.npy +03001627-d3213947dec793de213c3458a0fe5598.npy +03001627-797ad20122fb300659810674e1df4887.npy +04554684-43f60a28b62b616573d8be0e464c51f5.npy +02924116-5809985c32fd5bcdd81b677cc22e58ac.npy +02992529-c0969979d6ff51f3db27d84853613218.npy +04379243-f16f939baeb7722e664b3b9b23ddfcbc.npy +03938244-6415c868620b99a061c93a6de3b6bd7a.npy +02924116-76f657e27f2aa86391a491e8257bd6fe.npy +02933112-90b901d37c751841c93205b4771d5663.npy +03001627-60d11f54c4d3e1d856232348d1bf86cc.npy +03001627-725184eebea99d42a49e2dd37ae1f85.npy +02828884-7cccf8e8ebd9454fe42c56c78fb88524.npy +04530566-2a301f7070178c028cd011e47ff1df1.npy +02808440-af592551a5f44e8e54d7082b34825ef0.npy +03001627-19dbb6cbd039caf0a419f44cba56de45.npy +03001627-a7bc0f5b5d73df73f51f77a6d7299806.npy +04379243-2447732fa2e0d8d870febc66c2c7f4f6.npy +03636649-fc8345dacde827e376e9713f57a5fcb6.npy +02691156-70e4200e848e653072ec6e905035e5d7.npy +03991062-9b1c55fbfa0c337b81faebbdea6bd9be.npy +04090263-6e127603e720af7855731e75c389c9d.npy +02958343-58a500adc776ffd5a9655fa3e976d18a.npy +03001627-2afa06a01a0a15fc504721639e19f609.npy +03636649-f72efa4574100c12a8930422448288ea.npy +02808440-11d2f19d44c24eb53321831d2245cf06.npy +04090263-204decf8bb9bc9e623c69c7ff0f71040.npy +02958343-3b41ffcb4bec60cc21a66e8dfcce514a.npy +02828884-f0daa96d0eb986adcf729faf809733b6.npy +04401088-388798a892636235d2a526c0a7ff71e.npy +04401088-af983238a3e47692f90d7ee51bc3530a.npy +03636649-28b50bd5aaee8c4e7384352a7758c897.npy +03001627-23b0da45f23e5fb4f4b6538438a0b930.npy +04379243-ec7795f1efb90af9f37db3b69001ec04.npy +02958343-e7b500cc55c8f13b4512af8eced68fa8.npy +03001627-d9a1f2e7290cd2c3baab0c7159046dc4.npy +03790512-33b1973524b81c4ecafb6b9dbe847b85.npy +02871439-964e866377b784ab58bb658c8a827077.npy +04090263-19949be9b9eca5c667a4cd2863eb1ca.npy +04379243-edaf24be15738ea2c5d1c45cadcaa3eb.npy +04256520-d2711d46aac0b5ed492a9f7c65daa58d.npy +04379243-b5eaf46797ada237738e43095496b061.npy +02958343-4bdcae58e18e4c94c1bbb501b1d87871.npy +02691156-67eac921334c130c336fa8434b94be14.npy +02828884-8ed3f1b59a74ac71f155d75bbf62b80.npy +03001627-d14d1da1e682a7cfaac8336231c53cd1.npy +03001627-6c0b7ec41053d2e463860398b0d16872.npy +04530566-bc4ab06257678e8db25f0198c2ecfb0e.npy +02828884-552ab19eab47725cb2a965e75be701c.npy +03991062-546025d656c166562887a88b1b446ef8.npy +03761084-a635200a9c6258cc1dc59d2adbe5297d.npy +02691156-eb5baf7bb88c1499873ec74c119307b9.npy +03001627-fbafdfd16d929c715b52e74a988c7255.npy +04379243-ed30d775da40ee9ebd907eb5031fe9ca.npy +02992529-d659d98d384e2c37e405d2e0f546cab.npy +02958343-373ddcf15e21eacc3cb72b063dc95295.npy +02691156-3b9c905771244df7b6ed9420d56b12a9.npy +04379243-1f036102a311fdc174813b7165294e91.npy +04530566-338e37f313d48118789eecd157794d2a.npy +02992529-38afc0467599bd6bfa13d53e5e4a7d2a.npy +04379243-edc14df2b7e3bed1b15370175a9d2c81.npy +03991062-f84d30238a4784b9a2c59a4d90e63212.npy +02958343-415c24869f57fec9d9e74b7f1cf9cf3c.npy +04090263-f1f780b6afd284d0764c65bdf1040995.npy +02691156-e1a8e2f93abfc7d590baeef8ba5b93e5.npy +04379243-aafc579804cc095cbababe11fcea8796.npy +03001627-8ce2e49ab9f58811610c2a68437007d6.npy +04530566-8e431fd55a7aca0b124dae0a32996c4c.npy +03593526-5d123380371637c330b9e09efbedfc98.npy +04379243-fe621b83750698a6855931d119219022.npy +03211117-fb92cb1fa04c2ba6bf1c304f780914c6.npy +04379243-445402730a420ee63190a57d5547dcac.npy +02958343-3671b83524f48dc5801b0db1d49ea10c.npy +03691459-2f9b00e9c1a1b00c47569806bbb7c5a0.npy +03001627-b2ba1569509cdb439451566a8c6563ed.npy +04256520-f2fbd71be2c50fd89fb1d3c5138b2800.npy +02958343-d157bd15ee2d92b0bda733a39f84326d.npy +03001627-e767b27d6625f905e9af7c2087a87b0e.npy +04379243-482fad8b18008ff8c6540fe6bc16d6f.npy +04379243-e3fc414b6b9b52ac50d71b436e21a7da.npy +02828884-28b9f2908f0cbb179c21c139c0613648.npy +03636649-892900c66731d9c473ab7b7128d466a2.npy +03001627-569500b7add934625090f949bc5dabd7.npy +04256520-ca7dc4294b1080acf256e6841810978e.npy +03211117-eb712261aec94a8ddf8fce61d01de43d.npy +04379243-7bdfc4bd3fde9066b0028474d8c979d1.npy +03691459-2c4d13cc64a679f3322f30a0f4208183.npy +02958343-e84eb770bb6cedf3bda733a39f84326d.npy +02933112-6ff13af4d409fd25c3c22f38f0cbdf9f.npy +02946921-4cc3601af4a09418b459058f42771eff.npy +04379243-6620b366c1532835789195d85b2f8718.npy +02747177-4dbbece412ef64b6d2b12aa6a0f050b3.npy +02992529-c3e0378cf861099ae3f7a74e12a274ef.npy +04379243-333002057d45adfa7cc56a6af4771185.npy +03691459-b96feb6abb039ab8c7c56d4a401463d1.npy +03211117-165531f6138b14eb107d63d06953370e.npy +04256520-8e9de6e848ed53a248cfc982ba61d3a1.npy +04379243-dd9782826dda1284b3104e94482ea9ce.npy +03001627-e275ae27990e21988d2d730aebe7865d.npy +04379243-24bf4d4382c6bbf0d99562b7e15abcc1.npy +02958343-10d388f6f578e4e8851f021b9ed69c58.npy +02924116-8ff82359ef1ab92e52470de2774d6099.npy +04379243-316a52439f11450355f46d55537192b6.npy +03691459-5b9b77ad6ce283a398e4bc44d45a32e.npy +04554684-360e2cb74c9c4d38df3a1b0d597ce76e.npy +04379243-dcae4e8f41346522e1448c25c538991a.npy +03691459-b7f4de208a1051e62a27a874411d1ac.npy +04468005-d12a8d45a7a6cb188593314c6dc5571d.npy +02828884-8b98dbc11c5d2fb7601104cd2d998272.npy +04379243-189f519f6cb7b8c516fdce62f5c06e29.npy +02691156-c0796e38ea7a1d9fbc0909d98a1ff2b4.npy +04330267-270e25863ba6098b0a04bc414beaa99.npy +02808440-7ce00acd26d3ce63125fa9990176f0d5.npy +02933112-acbc349caf76e6b171337fa12bff07ad.npy +04379243-3802e59d5a3970d5ee6f3ff2305dcb14.npy +02876657-684ff2b770c26616d3dfba73f54d35bb.npy +02818832-34292cd1143461a6bda4e7fc3e4df4d4.npy +03001627-7f11f4251d2faee4492d9da2668ec34c.npy +03593526-a3b9caa337ca7c8e6597d391ab6fcc1.npy +02924116-49e79427faf2694811d89826bd8e0670.npy +03593526-3e2dd918360309554b3c42e318f3affc.npy +03991062-38b2432c5a2be4c95d8d4d8a3cf8b294.npy +03928116-1f7301bb64526ce9d4cdf759998ef5c2.npy +02691156-4e4128a2d12c818e5f38952c9fdf4604.npy +03691459-8cc5a2ac83bcc120e7a1105f5e7667c.npy +03001627-cc5dea482768651ed0e93cdb469eb63.npy +04401088-d130a357978694bf58efc722b5cff71c.npy +03046257-247ca61022a4f47e8a94168388287ad5.npy +03710193-914fa58a47245909a0dcbb80c5a68d2f.npy +02876657-5cbf1e8f31bae4cd67d1cb27b1ca00d7.npy +02876657-d85f1862dfe799cbf78b6c51ab8f145e.npy +02958343-286ce4a8390b317f93680c5a9a367b4a.npy +03001627-b9ac31cc001a0ab72a64ba172c1ba615.npy +03691459-f57b269b91e369f07b646fca2237eb6.npy +02958343-f1b97d671bb93ad928044fe9244db50a.npy +02773838-e0eb0b7925869326aa7b926be24dab3d.npy +04256520-8a85b0675605ed8219fb4103277a6b93.npy +03001627-5e338c489e940ab73aab636b8c7f0dd2.npy +04379243-81fd25d9d26de497c34335c1a2a9193f.npy +02958343-706671ef8c7b5e28a6c2c95b41a5446d.npy +04256520-5b7b8b094a52794675543092060e57fe.npy +04468005-936eac04b6a873049954eae9164faecb.npy +04379243-e2a56bcdb18d820047ad57fbec8be0bc.npy +02691156-c950fc7d559f30016e86a8ae6e1f4d7e.npy +03001627-33aaad494817a6f4ab705559ec99536f.npy +02828884-ba8ce85fe8f294929126d89585a68a7d.npy +03991062-86dc5ed985f2efd268ce23faf6fa0bec.npy +02691156-37b413fb76f97e0a29ad19c61d540866.npy +02924116-cf2c392c427c5a287a4d6e5c691fbefa.npy +03624134-ac2ad0d425f80152ea88f776c5c6a310.npy +03001627-f854fa8ee2fb6d715936c7265c890fef.npy +04379243-6d5211390473c3bc3bd24f986301745.npy +02958343-4aa7fc4a0c08be8c962283973ea6bbeb.npy +03001627-5ca0b01dae9e3476f51f77a6d7299806.npy +03001627-cc5b5e367ad8eaf19fb4103277a6b93.npy +04401088-1e52452aeb4bacbd83156841b8188cc7.npy +03691459-60474fda23d64ef0debcce788b4a424f.npy +02946921-297b1ba8efcbb6a86128527957a7bb1.npy +03691459-1124d162420a75232633ff66beb9cf31.npy +03001627-66e37e1831d3e49843638dabe1eb5336.npy +03991062-45d80de406c4878b59c0d8b17a41b6f3.npy +02808440-8738c8df22c4847fad99c01a1a18d1c4.npy +02828884-fb861f0e4e7f528fccda8d28b44378b7.npy +02933112-53e5fe30d92d6733e6c5cd45aa112726.npy +04460130-88b8559c748d1d326eaa9b51f546908e.npy +03211117-ba5518af411cffd8cfe78be5b7b99c8d.npy +04530566-5edcd7984de7fd4b42cdbb9140b25a0d.npy +03928116-c1b63d9e33a7f3b1741447c6658311e.npy +04530566-c2d71194be5909a75f71e6fef75fd750.npy +02933112-594128786d7aacf26f2c2a3461eaa93.npy +03001627-3ab838f55e56426b35836c728d324152.npy +04379243-132f7a4ddfe7f230fd6ec91a99a73de9.npy +04379243-f6e56ad2fe9e6c30253be0083bb3c718.npy +02992529-88c3248ee6950fc3d24be492f98354f.npy +02828884-8ea569854b8dfc8022b74f7ed4070ae0.npy +02691156-4d885cb269ae88ccbc40166c69b12cc6.npy +03642806-cc67f6608c41743ec1830f8ca7a3cbed.npy +02933112-7a48b295d6c3956fa96fd0f479def5ab.npy +02958343-a55f4932b0f8a212402257734064a917.npy +02691156-4ed5983b7721f1da7f79d93424b708f0.npy +03691459-b14b479cf64c7d9ad77ea5e1afa5bfe6.npy +04530566-313aaf9d79105fea82fd5ed7e39258c7.npy +04256520-6b569ad307bc38c06eb9b08c8a74d159.npy +02958343-40e51788da97a9c7212ff4933c4abe56.npy +02808440-a14611b43f16f0fff0bee563b25a27d8.npy +03624134-8d3142e751030a211395331ebe4786cd.npy +03001627-d38a49a15715c46ec3bd24f986301745.npy +04379243-a3f86421758cec25a092cc351404fb5d.npy +02828884-14a73dd6b5d7ef35feea12256ad59f11.npy +04090263-7cb94f3b4bda0dd9783a7c2adc432e76.npy +03001627-a235f7c4947aab15bf40bda9de89848a.npy +03467517-408a8e1b51266b9ccc34b900bb2492e.npy +02691156-4875318127182dbd15aba2f83720a298.npy +02933112-7f137684240ee0d62fb11210723490ee.npy +02992529-2acc3bd87282a7e31da45817bd55c1e.npy +04379243-c92e4772e218f5cbef9e56a2aea1eb90.npy +03001627-9ddbf01abee716b39b0530265e62c9b7.npy +02954340-90c6bffdc81cedbeb80102c6e0a7618a.npy +04256520-3b37e15f2dfe0bdf55f9a00acc25f137.npy +03001627-f64aa038d1e21e0ad2ebe04c523a4739.npy +04379243-4c8472bdc535102870553da2430bcd98.npy +02871439-5357cb17dad20db549d28b1865273fb2.npy +02876657-8e20da9c3f63ac2ce902acf138e668e2.npy +02747177-8b0728eb28c1873938f21a3304cc4bdc.npy +03211117-5305858e5ce441d65fabfc69ee61b28b.npy +02958343-d76c9eb102316ac631a8860374e7eed.npy +03948459-4648980f23149150edfe35c9179614ca.npy +03001627-acf23f78322f00f219fb4103277a6b93.npy +02691156-d6edd8b0801a02baf7571913c73c0c78.npy +04379243-d4de4deff5410e2be499c77acfcee9f4.npy +03001627-4042faba97a901aa08cd647a48e605d.npy +03642806-5173aa7f75ff3cf1b55fde51a411949f.npy +03513137-8942f437af8771afa1702a37604ec6f.npy +03001627-bce5c7402feef6d235fce1b314c89aa4.npy +04530566-26bdd8852a95cd2d4e4ba49b2943b913.npy +02924116-904ca55b79821ff85dc6bf5b8d674d37.npy +02773838-f1c9ebc8417c029a4da5feafe6f1c8fc.npy +03710193-1e4df43ee2f2da6967f9cc18b363cf72.npy +03001627-2fc6eef6605be9a4550584dfc8970d11.npy +03991062-be0b5e9deced304a2c59a4d90e63212.npy +04256520-6315fad2852149fc19fb4103277a6b93.npy +03325088-d67146079abb59a43321831d2245cf06.npy +02992529-5101c0131cdf76d03f9d84f9a87a44e4.npy +04530566-c19f98f149ee5da8b1bb46d2556ba67d.npy +03046257-b0b7d5ad6219ef0ddd425da1a5e9a595.npy +03636649-c898f9b1dddbb8801735ea0e092a805a.npy +04379243-2a963bc9ad704e5f525b133235812833.npy +02801938-5208bc4450a16d0e4b3c42e318f3affc.npy +04379243-2f32966fc64688969a08db804545b684.npy +04256520-40df73dfda0e26ce442b5d6d90d0cc78.npy +03001627-dc0bc65e9181c2f698eb62961a525575.npy +02958343-dc9bb9540228dbd4a8977f240035577b.npy +04379243-5de8e8b5034ded6b707cdefe012d0353.npy +03001627-f90dab51bec2bcd1a3340564b56a7f70.npy +04468005-2085c9f2619ccb014b0b2e6e63122009.npy +02828884-ba5e47b9a08c33d1ad1f278e1513f3b7.npy +04379243-a42d138bdd78cfe640abe029c3c77771.npy +04379243-5d65f46bcc49eef08b378a8c4400c79b.npy +02933112-9a688545112c2650ca703e831bf56f93.npy +03001627-c04d0cf81d9d870a7aa0699f5d30fdef.npy +03001627-c41ece3374d0e860e32cefe0e484fed3.npy +04554684-c6f9e7650c898b017b197b8311051a3c.npy +04090263-34eb6b0af5ae9f26d957eaf7f4edb205.npy +04090263-c42fe5b663661e1b4b004f8ab4aaf710.npy +02828884-131edf0948b60ee6372c8cd7d07d8ddc.npy +03991062-5856212eaca6fa76d4665c9b5f6f833c.npy +04090263-9204db8d40b7fcd7fa45f4d7e1ef7d0.npy +04379243-f5f5caaa07335f4e5c3654528317cdb2.npy +04256520-c856e6b37c9e12ab8a3de2846876a3c7.npy +04530566-71fbcc8e65022567b031dd7b49fa6191.npy +04256520-f9f8f089be14d5b672b33dfe598bdd77.npy +02933112-a0dfc5cd7e2331e6166ddaef2c2c61ae.npy +02924116-28e81e16c2c1e2723720164441111d99.npy +02958343-53a604e4037c650beedcafe524c3dc4c.npy +04379243-72f98e4a45f971ffaa0fb4126a41efc4.npy +03938244-c1f39c4bcd931875f51f77a6d7299806.npy +02871439-89f1540881171ee3f4c4977ed0ba5296.npy +03467517-ea0cccc085a8c4214f99643b5c4dd7ca.npy +02691156-1492ab4cf7a345e34b6f686803e61ffd.npy +04379243-223fbcc813831d8c6e526771d2f7444e.npy +04530566-fd52c80ae21d19251e0d0f6bac6856eb.npy +02808440-aba9f8d311894cf539d4219710154fda.npy +02691156-f8038d33c212f81fe99ea3c41458bc01.npy +04379243-70e58cec417d5e1ec283ca2c9df7372d.npy +04256520-67711689ee7d8dd76b4675882670d943.npy +03001627-1006be65e7bc937e9141f9b58470d646.npy +02828884-3e850a85b7c0f82cad5067eac75a07f7.npy +03624134-5314b350d816db25fa3fe405f2a25e27.npy +04379243-a8713681fccb1d647ff6ace05b36a5.npy +03691459-8671e50787f3486e1ad88f716ea80910.npy +02691156-f56cde19efc8d428b03f97f6dc2a21fd.npy +04256520-15c66bed7e6bdf85160c7765c528fad6.npy +03001627-73f16e230ac102536e07666ce67ff5a.npy +04468005-759db14cb3d146c28a3bb66b1c21b5ce.npy +02958343-ec07cd8db8f2bea851f021b9ed69c58.npy +04379243-4fb0bfbe85fce25cf9a2c981b043f98a.npy +03636649-ea7a5e58c0462957edf4c948f5a7c441.npy +02958343-5a728c7371f8fa3f1e0401312b984eca.npy +04090263-609bcf41c9d33c04fa9286f039319ff7.npy +03001627-9850d225049f987e9b9f2eb77f5e247e.npy +04530566-2e620c48f90f6fb2f569f587daa38158.npy +02828884-be8fa5b70de21c9ff155d75bbf62b80.npy +03642806-3b2bddb0e8ff57c85831a0624cf5a945.npy +02828884-b358c31d1bcab88a26b5e3d0c65cd557.npy +04379243-e153f757330a4ea3cdd1f51ef2b8f2ed.npy +04379243-e296f2e967aad03a55f46d55537192b6.npy +04256520-a5d21835219c8fed19fb4103277a6b93.npy +03624134-5eac9253e2e8803b67b50160faec8785.npy +02933112-a4caf30bbf028b63713f083e39bce318.npy +04379243-f323d90dea57815e119555fc7462650d.npy +02958343-52cff656189850a2546b7395fb17f97e.npy +04090263-cc380bcdadfc3040ab49837258a1bfc5.npy +04401088-c13cfcc92e41e5a924fb403e4bf9a6b1.npy +04379243-43f1b98f950af6d04f3443b22038d340.npy +02958343-cf4c819d9deb6533108499aad0a89b28.npy +03001627-77eb55272e3c00f2cb774aa5a7f9653.npy +03513137-77cdfb9d433531c6a8963fe61f2bc75f.npy +04379243-ebece7c581e3a42c32ba69f5f654ada.npy +03636649-19acda4f74d91d908351668cf609c7df.npy +04256520-ea295fb4335e3499f51fa0238791f5dc.npy +02958343-ddea3123599a628ebecf71e2e014ff6f.npy +02958343-2ef03b91692d6dae5828087fef11ba9b.npy +02828884-e8ed5a53c78744aa600895f6141c10ae.npy +04090263-92a71ab8a9862a5452d6d9553235a14e.npy +02924116-e90cafea6e6d9054b129901f80d24b7b.npy +03001627-dd78c16d85780d6b413102507b68bcb5.npy +03001627-21f9dcdadcca16227ad11050da24bb12.npy +02828884-96fb3569c007fec46dbc2b0ff6fd8e0c.npy +02843684-24e3f96618446a3ee65b26d9dc163c75.npy +04379243-2ffcf26e3cff97ee40b4c5428883e585.npy +03636649-8b7ee8229a579ee135836c728d324152.npy +02880940-5aad71b5e6cb3967674684c50f1db165.npy +03001627-34dc6c4e022b380cf91663a74ccd2338.npy +02958343-bac6953b6866ec02300856337cd5b2e.npy +04379243-fac2aedc7b6ab4b93002761e7a3ba3bd.npy +03467517-7e78c9080d79e7d3c0177b7521e73828.npy +04379243-31c278a2aa2a490241fe42b98fee4b0b.npy +03001627-3d23d594355c65d9376f771510e6da27.npy +02691156-55fabcb7e7c11560fa6bb68bdba0e663.npy +04256520-1acdc3f794d927fd63fba60e6c90121a.npy +02828884-7e524d1958ca0348d6abb4efd157f402.npy +03001627-40fc53f1c111a19c7d3c9de9415fb224.npy +04401088-298ca71453baf6ee2a9eb0f146e94477.npy +04379243-4f64eee409e34b41aa8d36cc58ba1cf2.npy +02691156-2de92a57e410020cc231d70e1e0cc567.npy +03991062-dec28aebe77c1ec4a2c59a4d90e63212.npy +04090263-5da81098c784b512673a614c45f3afe4.npy +02924116-af6358f5b2bc3b2a859e9bc6b5cb2580.npy +03001627-736e9ee917f741193b908295ece2b069.npy +02691156-5dd2324cd6ebf52e293fdbda4e7beec9.npy +04530566-388c5175593b057a66bc841ba9cad258.npy +02933112-b67d58cd774ebeaea480742f4529182b.npy +02958343-c631ec6f38a5e1d7fdc1d9a76d31d55.npy +03636649-d90d20f02ba8fb9a6bd00d0eaa99c3c3.npy +04379243-ec9d241cddcdb149f5a6ec2a96a47435.npy +02808440-3b501fa442876e4860fe69425c98b781.npy +04379243-d46537f513283d6cdcfcef693e7ec696.npy +04379243-c479482694623359fdf2e93846e20960.npy +03001627-e53b07b648e8d041107a17cfae0b6df6.npy +03467517-dfa75192819d2b89d909dfebe054cd91.npy +04468005-e7934a1982f37a695c37515681ce1368.npy +02747177-bc0ba7a521f9c61dad5067eac75a07f7.npy +03325088-a360dfc51bae92cd76d20e73c57c9a03.npy +03325088-79b89dc3e5809c5450da8b99982a3057.npy +02828884-516f47d7763d1db5ad55477d55e7af82.npy +04090263-291534185aa7328217ae750b40e40d3e.npy +04379243-69fa3275d6aaf1dcc9ee6bf6bfac3917.npy +04256520-26d165613b7baf134b3c42e318f3affc.npy +03636649-47adca3b217160d4b0957d845ac33749.npy +04090263-99866ea1b82e18c982cb4f2e118e48f4.npy +02958343-d0bf09ffa93ba912582e5e3e7771ea25.npy +04530566-52ad452f1c63aee5a66bcb069f7626a7.npy +04530566-b33a673da4745b08b5ee11a06ae8ae58.npy +02691156-8341ff3b44ed2e30473f10e6caaeca56.npy +04256520-e8dfcea40c6cee9b990561fc34164364.npy +02958343-a90b6f926a6307ab31b57ba89dcc78c8.npy +03001627-9ee7a2dafbcc731319fb4103277a6b93.npy +04379243-e2022bd4d83dd6155a15b6547f08c8fe.npy +03046257-7e98d09503ee0f39ad2ec599df06ea94.npy +02958343-6208166202d795a2272523adb0c9ecd0.npy +04379243-e920d6df55f51b9d3abfc4d0a5688916.npy +02958343-93bb1cd910f054818c2e7159929c406f.npy +04256520-f6bfc818e9e265b34b3c42e318f3affc.npy +04379243-b90ea1e6e5574e5814038d588fd1342f.npy +04256520-a9317911db005724f19c36a916a93d14.npy +04530566-cb8a73c5aea2be236b26711d34e99cd9.npy +04379243-f3f8fcf3713f89847e2388e35557b84a.npy +04468005-691349d753698dd8dc14ba0818ee5cec.npy +04090263-d04048099296ffe4dd084a7dcd1680de.npy +03001627-21cd62313612a7a168c2f5eb1dd4dfaa.npy +02933112-150a5e3deaacaad4983f6ae6d409aac8.npy +02958343-2faa3cff00d98abdf5274507f44ab711.npy +04379243-3fdd61db58e5856c91c74eb018d3bfd5.npy +02828884-6e29c6e045daf2a5d201085e80edb26a.npy +02958343-82fdfc4ecc49072c3ffe0e5069bf1eb5.npy +04379243-50641bc54d5d41e2a85acc7b983a0d66.npy +04530566-c7fb35a9ca583715ef0445a3d98d3d35.npy +02876657-46910c75d17ef8554c6e2707eea5c15e.npy +03642806-34913d1dcde913848bd55eee82fc09d6.npy +02924116-a907154f61d0bbff6b418c7d9fedcaa9.npy +02691156-c207db490c4acde27b5d32a85e1b7987.npy +04379243-780479255b0af544ef56e80181daf078.npy +03001627-bec075322d514fc9f51f77a6d7299806.npy +04256520-cfec2302eb084b5c58f4eb05242852ad.npy +02871439-825fad19825ce9f9d42b9650f19dd425.npy +02691156-ca8e8a54b54b41eceb1a0518c224975f.npy +02942699-68f66f5ab594fd3cc2890daf3a9f7413.npy +04379243-78253ff57339985a28c0cecb7de2397a.npy +02924116-484d31fd95214ecc6bf3b18b8ca71a.npy +03001627-c951e7bd4c0cbce17ec5a98b3b8c425f.npy +02942699-e67273eff31fabce656c3a28e34d04c4.npy +03636649-d3e5c225e8ec17ece4a604577ef990de.npy +03593526-67b6b40050bdc870e43df8c9a38bf11b.npy +03211117-cc1611b5120b8aad9651cd1d591d64d.npy +04379243-9b02cf9719863b8e9e990e1185980a77.npy +04530566-7915c47b72e6d496e453885abe85c310.npy +04090263-6e700588bfb6de35f30e6249e336e80f.npy +04379243-a95828fa4607295674c8eb7e4d6198a5.npy +03593526-94235090b6d5dbfae76bc197b3a3ffc0.npy +02691156-e594754cc2a264d63da2ae40e7681e7e.npy +03797390-c51b79493419eccdc1584fff35347dc6.npy +02747177-e4bcc42ed5b66b22b491f065bc1219a.npy +02958343-1790131f5f74b1ed973aff268eb6b00c.npy +04379243-97e6d79058bad189ca96b2737246fca.npy +03001627-866aa287bde4cff9bfd324d8acaeb3f2.npy +04379243-3b7db1bbe9ca00204d851671c3f1cc65.npy +02691156-68a423eea131656b1e2b909763d0fd31.npy +03001627-fb8c3a832eec2ffe627fec6651ed13bb.npy +02958343-7a8f5c085be36a8052aa494042b7c9db.npy +03325088-c23d9166bdeec5e5b362845c6edb57fc.npy +03636649-382e40ed472250924f3443b22038d340.npy +04460130-4fc1268f6aa26fd76ec5e0e1e130ecd8.npy +03001627-ed3cc4a95e18b3fea19b492f7b035eac.npy +02691156-b7023a2bc0b1c28142edba76767f7bf5.npy +03001627-e564f393acf979683c2e50348f23d3d.npy +03593526-dc39b65c9ed54544debefefb2e8c0245.npy +02871439-5bcfec5fe326fff4e0deec465e890dca.npy +02933112-d3829c7b8afd0d2ef51f77a6d7299806.npy +03991062-e744d9040133cbf4bf9296aa16dd149d.npy +03325088-8571a28754a62b8ce163f4a7838826d.npy +02958343-9497f33086b582b7473f10e6caaeca56.npy +03001627-93dc91115a9002e1663fcfd6703c85f3.npy +03337140-e4f8db369e639af74c3aee8e9d3a6ffa.npy +03337140-27b87b953b733d8a4c3aee8e9d3a6ffa.npy +02691156-d3f93b6da62fae46a98ae8c73b190485.npy +04090263-48d5a68d2228359fd735fa1ab17311ec.npy +04256520-34a2341fbd255d82b8a06a6203bc49a9.npy +02958343-38e30aa86d7bd4e0574fbf5e869a42b6.npy +02691156-e66692f2ec8ea898874f1daffc45b57c.npy +04401088-590017c9eabc3a1cfe8474bfd438f6d8.npy +04530566-9408002c21ae222b27ac692756be9e24.npy +02958343-12de9c37c83992c66392cc95e1b05a28.npy +04330267-4979ab695941487a40b559ef47048b86.npy +04379243-bef84446fe50feccec7cbf3284585a40.npy +02828884-58a09612c838e441e7b89654b68b9e5b.npy +02871439-d8d8488a7a209ed2a74c2333655a11dd.npy +02992529-234d1646b21fd765ee45e1eced971f52.npy +03001627-45f9f54b9e7cf6897886c5f50906be82.npy +03001627-26a6ce644504c5fa22963ea1e168015d.npy +02828884-55da2d1d9250d41b800e0abb10f41d36.npy +02992529-308cce8808b076bff49084215d845d01.npy +04379243-51930b149cf6125373fa072a624ce947.npy +04090263-f5ffdd214cfa8edf94c9a8d7fabdfed.npy +03636649-cd389501a749d5b13b080c0097c00a32.npy +03467517-14ca31ac1b2801f2d57700c05b1862d8.npy +02958343-9ec13da6190ab1a3dd141480e2c154d3.npy +03211117-ec190042ef2f7aaef925cd3fbd303c2c.npy +04401088-4bef48f1c1b4a40fbdeec9c43546255e.npy +03337140-ed5a8f4ecdbe78fa15a34fa27bdf3d03.npy +04379243-e3fff8b83cf999467ff6ace05b36a5.npy +03001627-d23682341fc187a570732116fb5f6e1.npy +04256520-ce049a259cc2e624d5446ca68a7e06a3.npy +04530566-b0e8c331eacdc9bef3e39f2e17005efc.npy +02958343-4d2daaa14ab2f051bbfdd95a15649dec.npy +03636649-438e9c32633a7094056b9c3d62d1efd.npy +03636649-26f725bb6578936cd247b9308cd5c441.npy +02933112-45679a0d39b500533dd5cc05646564a4.npy +02828884-7b58a3e5d7f4dddcad1d789f3b2120d0.npy +03636649-37f318fc52f4ae333f534d0cf4cbfb4f.npy +04256520-fff199c067a6e0f019fb4103277a6b93.npy +04401088-1e8d859734efb73567a6837216666401.npy +04090263-1ddc9f25d09da805d957eaf7f4edb205.npy +04256520-766d94bac9ae085455f9a00acc25f137.npy +02958343-bc587f9680c5ea9b58be2d1dec5d09d7.npy +04530566-38b6dc2ce1e8cd05e8d6be23f236225a.npy +04090263-e4c32f0b48b6c4aa31fddac73d878514.npy +03636649-fb4783fb006f89e4d9b53420a5458c53.npy +02691156-29b92db18649b64e959a8a7d5a8a5077.npy +04256520-29f890e465741b7ef8cb9d3fa2bcdc0.npy +02924116-2a7301abb348191552470de2774d6099.npy +02958343-15d6cd7877c6601d9ed410a010efa019.npy +03467517-33ec10ba6e6e0de41ba258440d3e234.npy +04090263-3553f6cf76c2f9e1870906b5178d97bd.npy +03928116-89814e650a56b657663f013a9c68bf1a.npy +04379243-e4dc0ff7a1f3151814f68a949b9a6baf.npy +04379243-978936fc521780702c5b6d66521f20aa.npy +04256520-67b1d2a43f266f4bf51f77a6d7299806.npy +03325088-567eb00396cdb60214b35a7d7cea7130.npy +04530566-9908b25da1e19480b51edc80d299de94.npy +03001627-4f79d43b70f5bca3d082d95e9bd50b49.npy +04090263-8cdac72ba112e8f6d2c901959c439025.npy +03001627-421472e991acb24490267536df1b0cc6.npy +04379243-eda7058a8c6440b7abf529d72f4c9152.npy +03001627-2404a64c8736bcc37ef29b55d8edde64.npy +03211117-459ea1db4ad52f3d7b7c888d3626712b.npy +04530566-925f3de9b1256113538505dcebf57ab1.npy +03001627-2de04227fae28e70b6eb6f056d511fe1.npy +04090263-6ac3f88bb36968ff6797bd93e1caef31.npy +04530566-aeb021c1e1838706b44ca19ee8c5531e.npy +02691156-a5ca77bfabfad028b56059027b9b30d2.npy +02691156-33e11a7dec64dd42d91ca512389cc0a0.npy +02933112-13dbeeacdabce3b694658a0201ba0367.npy +04090263-ae221dbffaa89b3264279e248bd2a91.npy +04379243-7ae9c3f17c5f9c569284ac9fef3539eb.npy +03001627-23d76c249645228d1e23e0195c502f30.npy +03046257-627617f3931dd0476e1ae929b00acbc4.npy +03593526-9097ce398b9700a27e561f865dc44fc5.npy +04530566-c6e255195b9a8691ea9bd4954e1c8c49.npy +04379243-35aced569e5e1d869d10bf389452ce96.npy +04256520-4820b629990b6a20860f0fe00407fa79.npy +02924116-660e11eff2108a00f8ff821990890128.npy +04379243-df4593480b94850bbf6d78b1e39e2718.npy +03001627-45a355545e7a807a492d9da2668ec34c.npy +02843684-4566d6e03bcd174b5fd335a0d0b003d5.npy +04379243-77147f716a20028635469b95109803c.npy +03001627-2ac0a9cdbe7ab8a6ad484915511ccff6.npy +02691156-ae4a9574248395b671d03b466c72ce41.npy +03001627-9d0b25421c13008e35836c728d324152.npy +02828884-7c770e38383d59be279e896561802d26.npy +03001627-3757a60634d134da35836c728d324152.npy +03001627-62257f79605faa66e6fe3612af521500.npy +02808440-ff6b4c0016394ba83321831d2245cf06.npy +03337140-1c319fc6985fc7cdb8405ecc20044969.npy +03001627-2acd3a3e50e8e068fae61b8c1512b8af.npy +02933112-494fd6deccdfb5cd5051fbeeb2dff27f.npy +03636649-989694b21ed5752d4c61a7cce317bfb7.npy +04379243-24019c15c4707356bf96d22e92924ea2.npy +04401088-8b174c67bfa00f03df269b2c62a1bd4a.npy +03467517-3ef569c13f4ab5f83ac61a2f8346a8f.npy +02958343-381332377d8aff57573c99f10261e25a.npy +04530566-de0964254f4599e8666f23db664db86.npy +02808440-47ae345322c4add9f9c0f9cbb10e38a2.npy +03001627-2edba114d2e9454295bea7c29e873d16.npy +02828884-6f2fa876147a970c5acde0d39b1b9dba.npy +02808440-b6df9d21acef1e11b362845c6edb57fc.npy +04256520-b675ac4b668ace54bdcf8e3531f470bb.npy +02691156-25bd1569261bc545e8323edc0fe816a8.npy +04379243-6da4b164828c371824507e0767ffba7.npy +04468005-8d136e53fdd5adba8be7c8c5fdb9bd6d.npy +04256520-a8df97262f1f0a44e4975e87c20ce53.npy +02992529-57004d88e4deebcabec15cbb63c9ab60.npy +03001627-7fd10f44a20506ec1b17743c18fb63dc.npy +02958343-34080e679c1ae08aca92a4cdad802b45.npy +04401088-5ba2137f5131db06219e978e6e16d30b.npy +03211117-75237ff4dabf0e9592552ad7302636b3.npy +04379243-332ce2f8d9c3927dffb8fce670bd5738.npy +04379243-4548b28199a044ab19fb4103277a6b93.npy +03790512-d644ca9d10aed7cdcd4bec905df51d1d.npy +02691156-1667ab313638fb366cf1b4a8fc3914e.npy +03642806-a874a1d28852062ec2743f037f439af3.npy +04379243-6d2c75d89b0a5f5d8cbb8bac2032149c.npy +02691156-c7b2f5b125bc41056d07c55cf995503e.npy +04379243-56ad1b4f94a1d84ae340086172f20153.npy +02958343-9d3fd293f6b9e46f28044fe9244db50a.npy +04379243-b3d7407f79c36ee7367336fdf5bd5f57.npy +03001627-69e591a9769e03012c528d33bca1ac2.npy +04379243-37c932b30ce507c6510e28eb1584c355.npy +04379243-f5adf1351a56586719fb4103277a6b93.npy +03636649-25999cece7e71cdae8c9f1b00ff43053.npy +02958343-4571e0fbe9cfb5f8fd52c8b6dd37752d.npy +04379243-cf5a0589134088ba37e5c2aed7049b42.npy +03211117-1f76e392f49bc1cda6c7922fe9004961.npy +04379243-9afaf5ab87a889f67acae9ce58893de5.npy +03790512-6683e13507dde030f6435254228a9d64.npy +04530566-411da0cd0b0089362b249fd16295bbfb.npy +04256520-51912ddf693219c81c8aa60fc1bb8474.npy +04090263-fc2f5a2623b4373a83bd2c1aefe617f0.npy +02958343-f7f7b1b4021be11afaeea7738551d104.npy +03636649-57c1bc69df779d87bbc7a6acbd8f058b.npy +02808440-ee9261d9011255453321831d2245cf06.npy +03991062-4cb7c329170ef2d6179720c8796635a.npy +02958343-b059f09a0b26d4b5cfc78902445ccff8.npy +03207941-e21ac8931606e2a2d1b2557b80a0d3f0.npy +02958343-40a30a8e56fa4a6c7b48e36e31209b9.npy +04090263-85c46176f030583bb349bd01da88f0bf.npy +04379243-41101b30e8a82faaa640b0223e089df8.npy +03325088-41aee3c40e294f9776c18e71fd49c4dc.npy +04530566-bff4e5d71e9b695dc6a303e6239bc3b0.npy +03001627-e8eedd37cb054e37b59d74a7c956bd18.npy +02933112-5c80714fa7f21981bf2e25c697250b54.npy +02691156-7ee59463dc17ac6e3e3f3c9608255377.npy +04379243-84c9082a8cbd03e5e76bc197b3a3ffc0.npy +04379243-c29fc3e0096d399e8d4b2547f739c887.npy +04379243-363c9169b12de77e1d4c681138512bef.npy +02828884-9e4c82a76b6aff2bbeedb4c8fd29e2d1.npy +04090263-359ac7f4ddf3e7fbafc7bdb2f8d1ea84.npy +03467517-52d82d2d6a82571554b87c21f44ed61a.npy +04379243-1e37f6dad9bb5fdf2f05c3ceed4d6250.npy +02691156-29925f23c2050efa7def3dd22d9ef72.npy +04379243-72bf6e88fc05d48c2ebeb1e6a8111f53.npy +03001627-589829ef4fb0390e492d9da2668ec34c.npy +04256520-79bea3f7c72e0aae490ad276cd2af3a4.npy +03636649-a89562207e0d50a6704c1b723fefce78.npy +04530566-db3a31bb1fb188c727ca48a52046110e.npy +04379243-e439549f5da57f5ea5676001632ead27.npy +03001627-731d9114eecdeff93454e751432992d2.npy +02828884-9dec54fbded3ed1767680982183b294.npy +04379243-ad17445446e4fd3adcfcef693e7ec696.npy +03636649-cdab137a52000da1b0957d845ac33749.npy +03001627-2280197ac01a58912dbc66eac8105387.npy +02880940-c2882316451828fd7945873d861da519.npy +04090263-a0a36ea333e8a39319dde5f6d908cdf5.npy +03001627-1b938d400e1a340b17b431cae0dd70ed.npy +02958343-4e2ca20091449636599389919f6522e6.npy +02871439-6888506448a935ea96b6312669c8f92.npy +03624134-74379a5fbc4935cf3b2b25ffabe35ca6.npy +02958343-cdd58286e3e428ec1fabf3cbd0fc77bc.npy +02958343-43fc65dfe952a7f4cf6923c08156107b.npy +03001627-bca8b73b32108ad6d42ec7e303174a87.npy +02747177-a8f009b0b4a76bf663b2acb037dfbcde.npy +04530566-27540cb221ffee07983f0317c2c6f92e.npy +02924116-4be2483503d0f71c98c13d6112727de.npy +04468005-556a0b9a789abc71eb34db531a289b8e.npy +04379243-867b553b34a3399919fb4103277a6b93.npy +02843684-304394899d284fe1ec1e281e84d8961f.npy +02933112-462ee81a089208caf2f140388f79bf7c.npy +03325088-153159f63d195bf576d20e73c57c9a03.npy +03691459-2336a8ba5ba8a9f0ce029fab54b6cfbd.npy +03325088-58fcac9c816ccf08b362845c6edb57fc.npy +04530566-44858e0564cdf90e299482fc72b07ee.npy +04468005-ce8f672133804c3ddc14ba0818ee5cec.npy +02871439-fd7f43c0ac27aa33b2592439813a5d1c.npy +02992529-1e8d859734efb73567a6837216666401.npy +03636649-3993a9c841dbc35061294c3e9dd88196.npy +02958343-e09813b03bdfce83a23218adb697420d.npy +04379243-9d54c8a7ea484adea330b2d4b3aea8f9.npy +02958343-19c25429d34ce9748c844a5e3a5e1a93.npy +04379243-50894123f3f237c161062d371b5548c7.npy +02958343-45ff3c9bc849f2e33a2844e8778fdc6.npy +03948459-5cc23a432b1b88dbf5029f48ea6cff14.npy +04379243-43aef0e663e734b75dcc7ddfa72357b1.npy +02958343-e6b8fe458aba5b0da86ce1de1d1e7ff6.npy +04379243-33f24a72a875633297e755dddca14449.npy +02924116-65b4a6c8cc40ee0f1288426428f318cf.npy +04090263-e776209bfa7f2844589c07868201b17e.npy +04256520-4e7062e2c776db18dbbc9440457e303e.npy +04379243-a72b18ca7d4aec7e67cfebe3c2e9790f.npy +03001627-20fd21021f3c8e5fcce6278f5ffb13a.npy +02924116-d1ff40feaf0516c6388c858f142b8b6b.npy +03710193-5a81ffe8b9acace8e51d90f0237045d2.npy +03636649-14656fe47266b0eb88e7662971dc736f.npy +03001627-7ff2f20512e7ce8e572f8e1c1caad99e.npy +02876657-7746997b8cfd8d11f4718731863dd64d.npy +03001627-efd07df34c1f73cae2367b9e27f16a71.npy +04530566-a40a870c5abd8c83d84b8ba651dfb8ac.npy +02958343-abcabe3968a64d4f16abce8cb03e7794.npy +04379243-a8c9827810c66962f8fd14d222168087.npy +04468005-564df1a62306be1552af501dc2728308.npy +03001627-e20a22906784e3d08758c89c2f45caa8.npy +03001627-6df97f6b123be35b71a782a4379556c7.npy +04379243-6a53e24442be0a9598f91bb06151de8f.npy +04090263-7e225da92fcfb868eac137faa8adc92a.npy +04530566-325d1e9be246e1644d44f5db04bf14b8.npy +04256520-5fd7cd5ee43e0cf0eaf288f952624966.npy +04379243-e2e3f057399a2b41276b6f6d90ee3a83.npy +04256520-328873bf304530b01b17743c18fb63dc.npy +02691156-10db820f0e20396a492c7ca609cb0182.npy +04256520-b06afb4d11ee4eb9ce4f274577283b16.npy +04468005-2197384551252127ecb01d351e78a9e7.npy +02958343-a3e8a28918af7b07e3857ce739e6606f.npy +02958343-993bd3b6fe7c6e32cbb047938846b5c7.npy +03593526-472eba74eb73dcb9c5beea20858a99d5.npy +02958343-f1bcdbe16690a985ca92a4cdad802b45.npy +03593526-30b7bc199de66fc57eaeab1f0c9120b7.npy +03513137-eeaf3811af59e557cdc59d2b768bcb80.npy +03636649-ae50216235a96cffcb8d8c6d4df8143.npy +03636649-7daa2c16580e9f8ee055d2b52a9e17d8.npy +04530566-d10cd8bfe5eb85572aec0b439528eb79.npy +04379243-126b0452fa8b16bbf7ba6397f9858441.npy +03001627-c1c0b3d35cdef5e2f51fa0238791f5dc.npy +02808440-98a94630dd0be49444221bef0fa3c36b.npy +04379243-50336797d9a86e9625d9442054ff1a51.npy +03691459-c398c35b48c31188c73a379f25dda815.npy +02958343-813bedf2a45f5681ca92a4cdad802b45.npy +02992529-7af2a3d126ac5e44fdda95e9849ffbd2.npy +02933112-cd781f0ec08ba028af232a5661e85835.npy +04530566-ec51dbe499e88615a267c8b6fcca89d9.npy +02876657-8458e5a34c67958130f549f12038e49a.npy +02808440-a7d1d15be88c5cc133d742e03c58860e.npy +02958343-810476f203a99d3586b58a9b1f5938e0.npy +02691156-e4665d76bf8fc441536d5be52cb9d26a.npy +02871439-e9850d3c5243cc60f62af8489541547b.npy +02958343-de3280a89c7ccbcf946f6dc2df6150bc.npy +04379243-87935bfb0ff57aa4668ae11a7db5e82a.npy +02691156-960d086565fd36def0a9e4c23bc75c0.npy +02691156-8b3bccc84ac7d534d56132409b00c58b.npy +04379243-28f3844a7a3d37399c0ca344f487323e.npy +03790512-80011e85cd42668ad373c34785838ee4.npy +03593526-f17c8c7d510658a02f2318fdd66be40a.npy +04530566-24f5011d64dff5cf1c0f52f4ec8b820b.npy +03001627-7f2854516404a3a7de03ab2a27ba7531.npy +04090263-79ec181e02cfc63af4de29b99f103946.npy +04379243-5239e7c9a83e99762b6168eeac2194de.npy +03001627-51ec0bdeb8bd9b8d60eb699207aa149d.npy +03797390-141f1db25095b16dcfb3760e4293e310.npy +02691156-6044301c7b4c63ec90b1d6deb98feec6.npy +03046257-716802270b2a331ed5330d8b61efb724.npy +02958343-b05d651c17e9e626ca92a4cdad802b45.npy +04379243-679d57762f6ae711b282e6ae268fb5a7.npy +02828884-6953a491a4c74d42d5cec9a69bf229a3.npy +04554684-8797bf2bcd0c914dd6b976d6c56a2c0c.npy +03211117-4f11144acd79460b120322eac6386b.npy +03001627-a374da8227eca67b89014675a548cbb.npy +04379243-8f4c9f7f38e15d03593ebeeedbff73b.npy +04256520-eaeaa6879cb8f5193a9b2e04441ce376.npy +03211117-a0f10ade51e1adcd8b8d299c28ab08aa.npy +03691459-e1d8c419be35ee1e209a4a663fdfe000.npy +03001627-bd6a5c01b9c6f17a82db9fca4b68095.npy +03001627-1c2cad4df1697103a5139737ddc33fc8.npy +02691156-8b4309aac2f7f6b3b97c9314bd4647d5.npy +02828884-643cac07025f195750f9fc0e2c94dd76.npy +02691156-a0a7e673a1e1bca78699933784576e73.npy +04256520-3fc4cf00b8db1f03b086b372af6b049e.npy +02958343-2acbb7959e6388236d068062d5d5809b.npy +03691459-2240cfeefea8b69fb90623b288d5691f.npy +04379243-f7ced3de6f4c1ffb4e3935c6cee4b35.npy +03636649-c11e3e763402346f22c3a2386a9dfbe9.npy +03001627-bdd51e6d7ff84be7492d9da2668ec34c.npy +03642806-93958423b98be8b538ff1b6d120c56aa.npy +02773838-506a05b6ba66bde0b726426d6c667c7.npy +02958343-7dda382210dd768680e74058ee862f05.npy +02954340-40f0c6599f0be25fce01c07526cf2aa4.npy +03948459-4dcc11b6acc758b1429a1687ed6390ec.npy +04530566-620f33e5f326e3c642f9e27aaf0c47a.npy +02828884-c29ae4355b73ad302be4222736443739.npy +02828884-2d1ea225c279836cd67b3c7873295e75.npy +03636649-c9b4209f1a7e97cb90a9ce3e4b15521e.npy +04379243-a26046fbf2d7368cd6e1954365b10b52.npy +03593526-a217a3505ef6b67de6597d391ab6fcc1.npy +02871439-711126944f5bb83e1933ffef19678834.npy +04379243-5dd9ef055fe3582687ccf9baec60b534.npy +02958343-e5a3ffca76415acc33529abacbef3013.npy +04090263-5f0cb03ebd45ee7d735fa1ab17311ec.npy +03211117-5145c2175f9db9d3f0478431b5ad57db.npy +02691156-647576c71cff90b4ca8607f540cc62ba.npy +03211117-3ad5eaabf85f4b5cc4d320644a1ff105.npy +03467517-bdb021331b396851c09b3b7b0c2153f8.npy +03513137-ee4046b8154cf9fd5964bcdfbf477f81.npy +02828884-56a818c4e5891f1d39316df04169d12f.npy +04401088-e679783f54c36220b99a2cc4ddf0d3f9.npy +02691156-71222607731812fa5e9e2656aff7dd5b.npy +03001627-680eec559a71dcdba023804ba421cf6b.npy +03001627-77e7660d71c6f3befebad4f49b26ec52.npy +02880940-6816c12cc00a961758463a756b0921b5.npy +03001627-4b95e968966fafc6e0675251723e1e08.npy +02871439-9664d50fc1a03534d42b9650f19dd425.npy +03691459-88ae9338c167e8d5238ad1274d829e68.npy +02691156-d068bfa97f8407e423fc69eefd95e6d3.npy +02933112-1c898677c5b4291c847857e42f50ec6e.npy +03001627-31a77c04ac5df53e9429176ba100075f.npy +02691156-9efbd65b09daf8358b96ae1a0a8b84ec.npy +04379243-564b7a755e3003da64fad3c7b88e6060.npy +03001627-88842eadd96e5cab570b6bda9783c8ba.npy +04090263-d1508875426ee5f3d87c63d8b3018b58.npy +02933112-464e34455b49aa5c824080f516909671.npy +02773838-f872a64810c123a47abde6405e4d8323.npy +04379243-8a505843a90a7486dc2bb3ee5ca7ba76.npy +03001627-1ee30d218c8c730ecb01bc908e8cea6.npy +03325088-b8d46728c6f3b0bf76d20e73c57c9a03.npy +03001627-ef9f4de6ad345818b25f0e6fce03dcef.npy +02691156-2599e47b04ea7a32d872dc56d048665c.npy +03046257-990f4d12875bbd61b76982957f05710f.npy +02933112-85502157d9e253d411fc2b865c2a185b.npy +03691459-e854747b2165ffd6f8b75fa4030d2e21.npy +04530566-d55ce64040e0b3e4ecc9205d69d88837.npy +03325088-5aeed0c9db054c395f12a496ed94ff1d.npy +04379243-fe2e9385283b62922de0bc4fc4d02dd6.npy +02958343-3587079f3146273faf8b8a34d449f60b.npy +04530566-b044558b01dfb98d3d8de7c49284d3.npy +04090263-a4d4e316f6511990309d43c07397e2bf.npy +02828884-3a271805da4a65e06a5d67b8fcb702fa.npy +03761084-4df99b98a1f4967ddf3a1b0d597ce76e.npy +04379243-10f1b51f2207766ff11c3739edd52fa3.npy +02924116-207c332fea56649952470de2774d6099.npy +04256520-ef99fe2058dbf199a2ebd6ecc07363e1.npy +04379243-25640329444772c6c2e20ec62321c272.npy +02924116-9d212c62dd02d40a1255ac7e5ca8c148.npy +02924116-22a6553c141476e06824264d26b3f6a9.npy +02958343-1c5a350ea0f55f793fbce9ec40e1f047.npy +03636649-b7b4361b0042126ac7d17f1ea7477fc2.npy +03001627-f6096649f87c37f1af7c7ad2549a1b15.npy +04074963-8f14d5b24d2b798b16a077c4c0fc1181.npy +02992529-c978be9ff9bfb9c67d2c763bf3599a8.npy +04090263-e54b7a716399aa646a29c14eca4d216a.npy +02958343-921f87f3d9a4cb8ddb37d391409760c4.npy +02871439-a62b569b9b55a34d14067ffcfc2ba435.npy +03001627-675aaa5b883e2398d7f7a4c4609b0913.npy +02691156-dcded0031a71305c52d6957c59c3d213.npy +02958343-84e4dd1c6306a582a97e62e669e9544d.npy +02871439-b3d9b068be7786d52eedfae7df5d8c3c.npy +03467517-7b99c00792408061e9d9b43230155bd9.npy +04379243-1c1c9e7676dd618e6652506d959dc71d.npy +03001627-8f13ac6499dfcc83f381af8194aa4242.npy +04256520-7a3dd8889b18cc80f51f77a6d7299806.npy +03001627-f1d6552ca66b2e37713decb1a0563b12.npy +03325088-8b12d095112cbf23ac9cfb689e5db0da.npy +04379243-e603a4f0bc12522558df8eeaf3dad1c.npy +03991062-229cc8886a1f18fb9173fae9a2149528.npy +04090263-52a90db915a53200f0478431b5ad57db.npy +03001627-87c742a186ef731b464bb3035358ab7a.npy +04530566-6c2fffad4d28822c1d57de40f2cd04f6.npy +02828884-76d029e29ac2bb69ad5067eac75a07f7.npy +04460130-1b781ad3315b36510f233dcbf8432d5.npy +02747177-5092afb4be0a2f89950ab3eaa7fe7772.npy +04379243-2e0a396cc21ed4e3781e3b226aea8d4.npy +03211117-e51c13070dcd4ce25432e3a73fd1f7a9.npy +02828884-25d1aa23abd04998d4d8765e3910f617.npy +03001627-85f56a4d68ff8d75c3bd24f986301745.npy +03211117-e17da83890fca0b8290273bda7ed0d31.npy +03636649-926d66e2adb79d5b79cb09497d80655.npy +03001627-e4c866b5dd958cd0803d0f5bac2abe4c.npy +02828884-47c991f72eaa53c6a8737fcf23389014.npy +04379243-8db8568a21645abb2964e7c9f80f3597.npy +03624134-65c05c88c441009f5d0dded52efeb4fd.npy +02691156-916950e40ca7aabc8b96ae1a0a8b84ec.npy +03046257-1f9ebcee16d5164b62e575249843c117.npy +04090263-2348490cb8fae973b6792578a0d9ae89.npy +03001627-735b16d075ad6ce3d197f67767b32741.npy +02958343-ff64fc33b5d8f866d4ad6f63f570d711.npy +04379243-dc9a7d116351f2cca16af3198c99de08.npy +03691459-22654d0b3683df91650c44f51c50faee.npy +02871439-340df58fd886d4e504af6e1321617aa.npy +04256520-bfc6b2328c9c12bf283b00891f680579.npy +03642806-8faaabdbdf4764b3531a9cd007e29075.npy +04090263-272e1f3a719f2e35e2bb19fbad3e4596.npy +03928116-fbac1681358a4289dcf02ff10643ca8b.npy +04379243-537a02eff282b33df58bc14da5676759.npy +04379243-e6cd3e7a25cfb1c3593ebeeedbff73b.npy +02808440-a1c617c1cdc5553b3af30a3946d92feb.npy +03691459-a6216e99923da6988947789ccf4faf06.npy +04401088-5ff8806e12ef72e0650185da4813c6fe.npy +02828884-d8dbfb0f58a2df0bf1eac5a8cd36b62b.npy +02691156-cd846470dd7a135d29ca62020db7d733.npy +04256520-a39749334717e07098f49a8972f75c6a.npy +03467517-5c805aca7aa8bdd3ac61a2f8346a8f.npy +03636649-19654d8fe7090a887eaeab1f0c9120b7.npy +03001627-5563067c7c05518415aea01a869de65.npy +04530566-b032f7baa738f10ef1ec74085c31730d.npy +03001627-1e2ddaef401676915a7934ad3293bab5.npy +03001627-695a02a5620aae6e78eec18a8a3356a2.npy +03001627-497f67c006770b9f94e98ee4fdfd7464.npy +03211117-f82557870d71f3a11f9b5b6530d6e16.npy +04090263-50fa60269066614e70a30ad089da2cd9.npy +04379243-b3eb7f278d595307d2b12aa6a0f050b3.npy +04379243-11aee78983b57cb34138477d68528833.npy +03001627-99a16c86225e538d9e72cd13d3c26c66.npy +03691459-6ff24c5a5003a1a5bf12d1e914fa62b.npy +04256520-3b34c3ac871a2d40593ebeeedbff73b.npy +04256520-2d1dbcb6802bf2017879e882bea3b8aa.npy +04379243-6d78f55d24f1c4e714038d588fd1342f.npy +02992529-a434289b281e629b81139543c959a70a.npy +02933112-bb0255c8582c74c6557f50690310ce8d.npy +02958343-4489a777dd90ebcce28605e174815eef.npy +02933112-90ccd5fbb48ba3bdde650492e45fb14f.npy +03467517-176ceacdbc44bc3569da8e7f9a803d12.npy +03046257-6cd9f0f548979d5160ddc468fe733ed1.npy +04256520-3f8f1d7023ae4a1c73ffdca541f4749c.npy +04256520-b5655dbb1a19b94c14038d588fd1342f.npy +04379243-e02fbeb78d8936fb586ef560a3203b3.npy +03624134-df0a8c7d1629313915538488147db324.npy +02808440-aea6cef49fd3a6ab3af30a3946d92feb.npy +03001627-995ecc9f34e0dc3bfa2cf126b85e1994.npy +04379243-7f39803c32028449e76bc197b3a3ffc0.npy +03691459-3b3f46308f2ad119988b934ce1e16bb7.npy +02958343-5768ae99da7499feadca4990256df2c6.npy +04256520-90b3ec9b7f122e3ae677774c24ef850.npy +04379243-1d90363feb72fada9cdecade71f5dca2.npy +04379243-d673e7a605249edf7c1af3afc3f87aef.npy +03001627-4171071eb30dcb412dd4967de4160123.npy +04379243-577155d24ebec9833ce2d31ef93d6e81.npy +03001627-98547d9147a58195f51f77a6d7299806.npy +04256520-a98956209f6723a2dedecd2df7bf25e3.npy +02828884-272162e616a4e8e9ad5067eac75a07f7.npy +03046257-147df4e2a9af41fbf51f77a6d7299806.npy +03928116-6e549d6229e1cfff1420b81fa6c7ce78.npy +03001627-41e5e9ecb83b9a45504d5af97121b5f.npy +02924116-df89f05643f34c645cd2bb143228195.npy +04379243-38e90183c838f443b43753a53e4593db.npy +02958343-1cde62b063e14777c9152a706245d48.npy +02924116-3d2aeaffcbc6f0bc41cefd10ce5d6cc0.npy +03325088-38acce15053c16d3321831d2245cf06.npy +04090263-574e6f325fc821ad6314c3b6a3a65519.npy +04379243-a5634b2fbad2b88d5d14030c75181478.npy +02691156-18d55087d052ecc86b7bd17e458d0dcb.npy +04530566-9efd4dac9e4b1698876eb99526752ffb.npy +03467517-ba7ef4973b9c4f995eec6d8d24f1fde1.npy +02880940-ea473a79fd2c98e5789eafad9d8a9394.npy +04256520-ea9a266329617a165298386582afecd3.npy +02958343-d0cd9b6ca511c6b9920355ae987b66f1.npy +04379243-6c95f72153478de8b162cef80a91798d.npy +04379243-d0008b042256fb5f7ab911835312d4f1.npy +02958343-b40c9e44350f95aa1b9234e4ab67a3eb.npy +04379243-d5a78c5e48ade3e38fe22a5ce827e9fa.npy +02691156-cf96229978efbb488b96ae1a0a8b84ec.npy +03001627-18fe5de83a17c6b5876b399a99a15c0f.npy +04379243-e58c53d29aaee1fc8101accd22c701b9.npy +03624134-e6e452eb238659f61ce93adae4bc9483.npy +03624134-4bbde8accc3bbfb87f277d7152b6b3ed.npy +02691156-322e8dccadea03d3340b9c9d10273ac.npy +03001627-e62b187f6741283bd8f27b2e727c3511.npy +03691459-f289aadb7cdf59daa62fb160d742c45.npy +04530566-fdf4b58a27a3ac8ead83f267e8f0b536.npy +03691459-73fa71b650b99bc951d3c864cc68e22e.npy +02933112-5a2de91981d27ba3c59350d819542ec7.npy +02818832-3d14f0782e488c8bc19762eaa7ba40f.npy +03211117-9a24880343d943f7ec059109909662d2.npy +04379243-ab16eb9d6122a5fb41cf86c757faf4f9.npy +02691156-61bd590e917928f6b6ecbbb2e4d05900.npy +02933112-1a7b9b946e797ce59f8c3d2002c77ddb.npy +02924116-737aee2e780049ef887524da02be2633.npy +03001627-59fa70f195fd4ac6ae8c9d3b8c4b9bc3.npy +02691156-d80486b768083cd6ba0d990ae229b477.npy +02958343-ffbb51fcc3955d01b67c620b30c63392.npy +04090263-d5e99caa1d8e7c859133e432dd7411d.npy +02828884-8e25c33aafaade0ad5067eac75a07f7.npy +02958343-557413032afecbd4c627f7f719e1032.npy +02958343-52c589e86fd500cd4a42886683bb52d2.npy +04256520-306679647d906c39bbc7a6acbd8f058b.npy +03691459-533582fec17b538e60e1d7e27755edc1.npy +02958343-1f92e07294960629a39ce7aafdab8210.npy +03636649-aab336a18bb4e51fcd4910413c446d9.npy +03001627-9231ef07326eae09b04cb542e2c50eb4.npy +04468005-f34dbc7687edf0902be6b91d40e230f6.npy +04330267-355f5eea3905262d54665a4e9c906cd4.npy +03325088-ad63886b1f38bb16b7a867e9b35a1295.npy +03636649-fad026744a6abb1937cf479d4bb58d.npy +03691459-5bfeafef1be5f4f5bb476b1cb791329b.npy +03001627-b33a3b1627ad61eb8ca4809dcf42fe1.npy +04379243-4b57450a988be6c1f51f77a6d7299806.npy +03001627-1eb5613aa22df87b8ef9327f5d5c024d.npy +03001627-608b46b0f8f9eba81b1a986f753a489b.npy +02924116-a2178368fff2a71824e6f48def711dfa.npy +02871439-2efb3ad49fa103b1cc786970133d7717.npy +04379243-9d18858529b76154aa7cb30470f3273c.npy +02958343-3335fb305afa0494d3c820a40c219fa9.npy +04090263-278f6f0588771123f8edafa0d47e47db.npy +02691156-1530400ceabc1d7145ec485f7da1d9e3.npy +04379243-758f982c1aa6f5edd6eefa796d2f261c.npy +03001627-985b7e5b5fe997f0670cf6c75c1c5868.npy +04256520-2a98f28036915f805510d59f3ab1ed64.npy +03691459-f7a45911d01fe4a961775b840d882da9.npy +02924116-8e0e80eee17c86415a9da89784be865.npy +02828884-1e4c1fc02be62675f90c2728303e546a.npy +03467517-8ebc3d48afeceec752561cc0fb924c36.npy +02818832-b6ac23d327248d72627bb9f102840372.npy +04379243-39cf5ae2b497715a84253b2030fab070.npy +04256520-1f28f2ccce4940f2c6fe57159221338c.npy +04379243-ec5469035d19434f9ba80f08c401fbed.npy +04530566-92be906c57e20430fd87075a257732c6.npy +02818832-643621e32b3177d3f0fb3e3d2a0d34c9.npy +03467517-68a8bf89972cd337a77e8142614cdaae.npy +04530566-3038a5f927db994e6702681953f194c0.npy +02691156-af3863d4ce7dd92ac6f6da58b133bae0.npy +03001627-572cbd8b4cbdf7f1f91663a74ccd2338.npy +02691156-2495267afeb60584c3a35cee92bb95b.npy +04530566-7aaa404bd120be52816427daa1887efe.npy +02958343-92f697d036addb55ed576c2966428f.npy +03001627-997b0aaad2301a44b31fb46b2e6304f4.npy +03691459-9d180f7f43dff3d51ec48bc3c478566d.npy +04379243-41d280b7db61ebddfebad4f49b26ec52.npy +04256520-47362cb47416904b76e38b52d9aafc11.npy +04379243-f195ff52401da593344db0d9ed96427e.npy +04401088-e513675ffb2da709a060e584e7409aab.npy +04379243-7a5acf5f20f8cffbaf030eae870a2d14.npy +04379243-1bd138c3e54a75d32f38c0d2792fb5e.npy +02691156-f6a09cbb6d08feeec9d7d324d11034c9.npy +03046257-2d3306996a223a992c4f629232dbdb8.npy +03001627-95f8a62c031dbb8ff0f455e219813ed7.npy +04379243-9269d120ecefe48da2aa7d89ba9aea43.npy +03001627-662f95ed8d41a24bf63bf7d908efc575.npy +04379243-f48a955a73fa0fe79aad7644557603ac.npy +04090263-39c4214ab44383258a3dbbf31a87b8b0.npy +03001627-aa88b0f05470452f7ea323bc74055b8.npy +04379243-f4976e80b8533bcf85518f8659f21d56.npy +03761084-eccfbd9111c640789e11c084f781b48.npy +03636649-989a70bcea69bb4372a02c2db7bf58cd.npy +04379243-6c4c1465fe472cfd93ed8929b636c206.npy +02691156-dd65065e6e2d31d62e350437b1fc5163.npy +03046257-91d9bce8460a5cd010fe662c4b4066df.npy +03001627-43f762270b438fe618a36258eabc2b9c.npy +04379243-7f6ddb13d3b8c07c1c19e7863a1c200b.npy +04256520-622552cb1f5670a614038d588fd1342f.npy +03001627-72a40501ded8a8dd2c2f29cee8379a34.npy +03001627-507de496a9a77945e40b5e9eb4befc2.npy +04379243-4a27cb9384782ce33e95c55cb020b7e6.npy +02992529-73b0bcdcf57a8a7fe8d8ad3bdef6aca2.npy +02801938-a838d7fcfff9732fed315c548018de56.npy +02818832-6256db826fbb31add7e7281b421bca5.npy +02818832-ed4ac116e03ebb8d663191fd557d3a61.npy +03624134-208610aa6d607c90e3f7a74e12a274ef.npy +02992529-6907dd835a22c32f46895db2a69f45e2.npy +04379243-589f5927d37247564fad3c7b88e6060.npy +03636649-b668df78adedbd1735ea0e092a805a.npy +04256520-3d87710d90c8627dd2afe8d5254a0d04.npy +04379243-b0c37b379725feec97ed2c3bf3711e68.npy +02958343-2c3a5d170774da5ae4a44d0583e1bb01.npy +03001627-8098750b6089a9d8ad3a7d07aac2767.npy +03001627-dec5920f32fa546a6c518c577d808035.npy +03046257-cebb0e2be3b2cc1b474465268b958bdc.npy +04256520-2ebb84f64f8f0f565db77ed1f5c8b93.npy +03691459-73a337691b4015ff1ef58b31c4ba0d15.npy +04004475-d0ee507ba98a89525df8d70b74fdbdb5.npy +02691156-5e44d38e88458ab1e1873a3963e0d14.npy +02818832-10c15151ebe3d237240ea0cdca7b391a.npy +04256520-54ee1ef79b340108e5b4d50aea96bfd9.npy +02933112-2cb76d6aaac3c677bb60e56ad1645b95.npy +04379243-35dc5a90392dbc1563f26b71f9dca732.npy +02691156-b65ddb8f80d8fb562e38f6d9568202c7.npy +04379243-a1379276f75d137ac5ddf9f6c8e4b3a9.npy +02871439-4cf8fd9b396d0d24868bb660c8b7e409.npy +02691156-892ae1180c58b3e671d03b466c72ce41.npy +03001627-54f276860d9b00436370a012706ac174.npy +04530566-4a0cbef5bbb19d840b6c13818321d0e.npy +04330267-f5543e4b09f4a49a2846c469aaca3af9.npy +02691156-fbebcde2d8fbf81ee7cf320ab5761d45.npy +04256520-aa7dbd4acb4878c9620f1933fa113025.npy +02958343-38b2bb3bf698f38ac2920de4c5efc2ee.npy +02958343-9c7cbe5b36b7ae9216abce8cb03e7794.npy +04330267-c647966562bd62f45eb64c1003065596.npy +04256520-9ceb81a09813d5f3d2565bc39479705a.npy +03642806-7e5b970c83dd97b7823eead1c8e7b3b4.npy +04256520-13d3462293023fe71f530727405d60cf.npy +02691156-f7f915160c0e1f6f42bc0eea174f82b.npy +03001627-2936cfb442eeb0a32a673c8b84dfc32.npy +02691156-aff764398f14383eb87697d3904b168b.npy +02828884-c2516123957e1cc42283e6cce5561adc.npy +02691156-8463c1f30bcd9151b92527b70e93ee2c.npy +04256520-d8fa31c19a952efb293968bf1f72ae90.npy +03211117-981d4ebcfcd3c733701bcc8e95172446.npy +02828884-d406968659ec5ab87d55717abcc7106d.npy +03948459-9e1835a6671c1163fef144202cb2b935.npy +03001627-7fe836b46890d24a65ba78ad9601cf1b.npy +04256520-359b6d3d29b08dfe19fb4103277a6b93.npy +04330267-38978d1d3a97e57ffc6e457221b9271.npy +02924116-2cb165856db926fd851591e44f18a8a5.npy +02818832-31e0375f0776e4949c9245e96a55cc5.npy +04530566-ca129502c7b2b8186d54dce3f3e9f18b.npy +03001627-4848f84b015f1360e8058cf23f6382c1.npy +03467517-b9c10bf6fc2095f93f0194265a9746c.npy +04099429-59389aac7b1ea9b09b28f5f9cf8893b5.npy +04379243-7f1749643345953cf51f77a6d7299806.npy +04530566-728fa87ee84c5c2d2fc7e4ac493eaaf8.npy +04090263-9cc7d4e39b1fb17993d988207a39086f.npy +03636649-da8141b45da808199a06a7de97b096dc.npy +04530566-ad2c82cd40584b43fc4c78b4701b2fab.npy +03001627-d3562f992aa405b214b1fd95dbca05.npy +03636649-5fba90e6e30b503461bfbba8a5defb02.npy +03636649-2691d3491111def44674c364bb213983.npy +02958343-128ad72f92a3e96db96212c8f6cd06e.npy +02818832-48973f489d06e8139f9d5a5f7267a470.npy +03636649-845542d0f578a9db1ec48bc3c478566d.npy +03085013-a86e4fb88103550d4dc96c27c8aa82ed.npy +03211117-dddc8d8cdd6361e49c9fa9de1518212.npy +03001627-11040f463a3895019fb4103277a6b93.npy +02933112-bbdaeb32d4229d70c59350d819542ec7.npy +02773838-1b9ef45fefefa35ed13f430b2941481.npy +02828884-8553cd048bbdbc15ad5067eac75a07f7.npy +03001627-e4ce4c2a3709855450064625270cfef.npy +04256520-81a032241031c2e5f97ef3b999ddb957.npy +03991062-92a918828b34ab9372652f4081ec5a77.npy +02933112-9deca642cbf3e4ef49a734174fea032e.npy +04468005-75056755fb8f1fc92217baa3b8e01690.npy +03001627-71a52b54d732450bdd766137cdd5195c.npy +04256520-e93e9beb358d9fb8c397356311cbeea4.npy +02933112-4dbf616f15f8818ba3f600c356573d21.npy +04256520-c983108db7fcfa3619fb4103277a6b93.npy +02958343-f5a54f0cf2b575fa9fe1734a6086750.npy +04379243-1ffcbc064f473b7de7c13848b2d8f5ec.npy +02818832-42e4e91343b44d77c3bd24f986301745.npy +04256520-7c299b1e1374a538e78a749ef6aadd72.npy +02801938-52d197b32476156334b599aa7a6234d3.npy +02880940-d28f7a7a8fbc5fc925b5a13384fa548b.npy +04379243-f7bdfe5af3b26d1b5f06dd739e88c77f.npy +04379243-c9a3ea912a35c3e1601bea3dca268229.npy +02933112-ea48a2a501942eedde650492e45fb14f.npy +03636649-6ea3addd99f0106b77981b941eb4f5d1.npy +02691156-5f9d38e5e7fef49f7a571401e6605fc2.npy +04530566-5e6e9a61eb078041556f795d265590.npy +02924116-803848450b34284f41cefd10ce5d6cc0.npy +02808440-621f1f65eca6fe7fd7c9d85d3b7335dc.npy +04256520-5895b40b8c4d103ac60ea5009df4047d.npy +02992529-39e571ec1bcd371bb785a4ac4a0dbd73.npy +04379243-df74203c0a1585f9a29294366c3334b2.npy +02828884-38441b4582f29c8cb2a965e75be701c.npy +03691459-5e6d30de53afebe2fb0a4dd466ef3d66.npy +03636649-96e1ba69697ade7682db9fca4b68095.npy +03001627-c94f7f5ec96e10994231039830c7e1d1.npy +04256520-d7b69d5015110b1e2c5b2f528cea9dd6.npy +03991062-bad0dd72e36add64a2c59a4d90e63212.npy +04379243-65bb2d37c52ce089e76bc197b3a3ffc0.npy +04379243-83464126ed62ef54707cdefe012d0353.npy +03001627-32fcd056e1c474b84f5cfb5dea01f97e.npy +02924116-8357b3db7aab85a3e6f75728b7e2cf7d.npy +04256520-c9e41b8e7827cd963dbb061ded33aea.npy +04530566-3c785a132fbf152249d508bbe117085.npy +03636649-7d4d715c4812e42cc0f8577a553db1b0.npy +03636649-4843b9c8523a4affc29d936f5ac7e23.npy +04330267-fb05baf6da5b0856875c4d98e634f167.npy +02958343-16bd0438de54fc91b1bb46d2556ba67d.npy +03001627-6acb045fe11f7a81f771b7c5ceefa9be.npy +02992529-fa14355e4b5455d870f7cd075189ddd8.npy +04379243-3aa65a29330bb87f980f165bc2b4c765.npy +03001627-7726993e4b88223fedc32c5c9ec9f827.npy +03467517-a38684b166ce2c77c155f88004a92bc8.npy +02691156-45c4867cd4554e7cc863ab010b80d9ed.npy +02924116-da99c75df648834a34f4804e95b55ebc.npy +04004475-51da7fc000ddc4ab129e8b646eb2bfca.npy +04074963-55858ff5b407677f35a527bc320873ed.npy +03761084-4c9a1496692048922ec64b86eca750d.npy +02828884-456e373768179bf3f155d75bbf62b80.npy +02818832-a13de93c557a327c36d8dd30a594b2af.npy +02691156-16079ddc92f4c9efd677715e63c14038.npy +02924116-2f0663bd37ca4e0db1d8796911acd773.npy +04530566-508e6fc3b47590556be64995e9ed73eb.npy +02958343-d9049f432296ed36afe1d4530f4c6e24.npy +02933112-d6a55d2dece36ca0e3f7a74e12a274ef.npy +02691156-6d93492543d1087eb87697d3904b168b.npy +03636649-bda58405e4e3319d809772d66d13ee02.npy +03001627-5e4552935979a7a1c25c8c68d88e274e.npy +04256520-af28dbdce6ed8cea19fb4103277a6b93.npy +04090263-b6f2b71e726f5dabab97b3fa5a6b9e6e.npy +04379243-838b05234e648ae5db4c5469c0c1ba80.npy +04379243-7e27606e126c023d5dd94d7a8cf82d08.npy +03001627-d7b22da1174eade770bc652a18e29c3d.npy +02808440-783c3fc429a969b6dbb76013b759885f.npy +03001627-6a878ab386c927e6d1a63a2e2039ff73.npy +03759954-cbc023955a18d8167964ba700cd97f5.npy +02958343-7022a37dd7fc841ce98e65cfc071e8a0.npy +04468005-ade5ec555dc1f0df5706d1c54190f27a.npy +03797390-633379db14d4d2b287dd60af81c93a3c.npy +04256520-70e3bf6b0eb99dd6cdcf4980e386b48d.npy +04530566-dfd7315b7f8a07ca67585a906cb87a62.npy +04379243-4ef4f289b6c23719588e951dcb8abdba.npy +02808440-f0e4c180558694ff904951ea0800d3f0.npy +03001627-b9c0dcc854da8c7d60558e0a9a66f173.npy +04379243-ae5631ecb6ed463f5ad83814029a1a10.npy +04090263-5ce262d2d63b4c56357baa13baa16351.npy +02691156-ed4aab2d41d62b49895ae53d16ed9e39.npy +03642806-81ba52b908e4e1bc8ca8637757ac3f67.npy +02691156-ea6ccb2dfb61484caaa29616be3e223b.npy +04530566-d3eaeb69557892657828ce3c6ecfce8b.npy +03636649-5926d3296767ab28543df75232f6ff2b.npy +04090263-c91b4aa1105a0e506a34aa94ca8a3355.npy +03636649-92d7ce3f06a44aa582db9fca4b68095.npy +04554684-fcc0bdba1a95be2546cde67a6a1ea328.npy +04379243-ed30f840756baab042678d21fbad4632.npy +02992529-3dac1f92b3e13977d19f91734fdc72ea.npy +02933112-b06b351b939e279bc5ff6d1af2135fc9.npy +04379243-f5af26e3cc266932ea88b65c86e82a10.npy +04379243-8d247c6f6aaf805a2530bfb25087f2b0.npy +03691459-46bd2ce6ca3439c9c2687184da14e3dc.npy +04379243-649bcbf07f29fcae355d9ff291618ea6.npy +02942699-77096e9094680faf603e5a6a09a35395.npy +02691156-7f2d03635180db2137678474be485ca.npy +03691459-b9f853ae8b693ff91574d21c0c95092f.npy +04530566-1f5d3310cc5f9346f1d7b2f32e8fa69.npy +03001627-828d2c47bf56b15c49560f24b21df85.npy +02691156-b30bd72e684744c521b1ceea9c93aa79.npy +02808440-9269512d34ab85213321831d2245cf06.npy +03001627-8b005a01cf4ae50dab49dceef0d15b99.npy +03001627-e00291d775c572f5e8f8c11a24c52ebb.npy +03001627-3bb8e6e640c32a7c36b0f2a1430e993a.npy +04256520-642aba784c86bb67fff16555386d173d.npy +04379243-f70b502758db5927be2f6e4bb98bc38c.npy +04379243-72f46e20632f469c9cf718a4c796aece.npy +03991062-35bfcbb0af43d0d6980b4a4e82abb4ae.npy +02992529-e6838870d0138aa43b995d74ae757c1f.npy +03761084-70f55c83dccea88043c8f1cd479ffb1e.npy +03001627-ff2dbafa8d66856419fb4103277a6b93.npy +02773838-22065bf26a7da50a5c4dc8ac281ba59d.npy +03467517-9992c9f68e5c3e004dfe0ed95d7290cf.npy +03624134-9dc11afe70cf097e497c98fff4316992.npy +03046257-772f1ed7779459e8d835a15bbfa33167.npy +04256520-6024afce9a12fd87318b348b36fba247.npy +04256520-d04a6f268f16bae7d472d3bb6a889c20.npy +04379243-71fc8c7cdb48978282fa4d4f2c19b2ce.npy +03001627-408b8f2a75350af98ce66f12ba927a2b.npy +03337140-13d5f9d6a7464e39f0f01f1432a517c3.npy +03001627-a7ae914aba9eb59d84498bc295cd5a4a.npy +02828884-b20a0209355ef6ddfe6460d8d9bd16c6.npy +02924116-ffcbf6cb730ea266296fe052063ec1ad.npy +03797390-1a1c0a8d4bad82169f0594e65f756cf5.npy +02808440-f327905a8577d9adb362845c6edb57fc.npy +03001627-3fde6688ea2022cde0f6ee1aa6b96429.npy +03938244-c665ecfac697faa1222129b9e83640a7.npy +04256520-fab5f1daa52608365768db72e79a5dd5.npy +02958343-b52486fac51d119110c18c6084937a7.npy +03761084-90ba871e45aa1d10b8bdb4201eaa026.npy +04379243-4180532fda31d19b37251258858a7a58.npy +02691156-642e481ed56874eb19ba010ddb4974fe.npy +03624134-32d009edb5d9474c4e79e5d262243b08.npy +02828884-b859f6e61529db7b195c5c738f050b29.npy +04330267-8295e45a734c059d1f3d773b4af1f0c9.npy +03001627-2b82a928c4a81fe1df4cfe396cee719e.npy +02691156-35892510dcd7cebb87bf26680c510802.npy +03001627-faeb171add09f98cc8687ff9b0b4e4ac.npy +04379243-3b2855b73aac8d04d6686dc2df08cca5.npy +02808440-cc060d05ecc6b760cb6267f1b348aaaa.npy +02958343-efd87861810e35ca921cb81cb1632a5e.npy +04379243-11a1bb35960f02d83dc1643807625350.npy +02818832-6e5f10f2574f8a285d64ca7820a9c2ca.npy +04379243-4b455e9b8dc1380dbd508cb7996d6164.npy +04379243-7822d47b9ce66e5591a1a434bc319a99.npy +04090263-326eb76ab05669c55e9786b1603f45c8.npy +03691459-e76108274392bff53d91ae2b92426394.npy +03593526-31b0a01063a976104725f67267e31c89.npy +04379243-10e7056ac077a0f54a111702084d37d7.npy +02828884-2a050ecb95f2a056593ebeeedbff73b.npy +03636649-a3c4ce97b725fc2c5f57ce7e4ba40e2c.npy +03624134-65892e0f7f93129d14cb807a24b99e1e.npy +03001627-5edfec789343e0c3319f1c1eee46f332.npy +03046257-2022b303e954ad7ed603cac03886a314.npy +03211117-e7a14693e9c70577ac74d552b6a649aa.npy +04379243-a84f09300e4b1c1ac624b11e153a6d87.npy +03691459-8310e1e0a80ae09967964ba700cd97f5.npy +03991062-ea662c8a7f99d7d1b27dc9f9b9dc6f03.npy +02808440-3f61daaf0f87563b4ed5b40788f6ba60.npy +02828884-16549eea10c75d0f65d3152da5208307.npy +02992529-72d3c4148500a7fe1bf02ad5664135fe.npy +03691459-c6c69578203357f3e3bf55e5ac6083ca.npy +03001627-facd3e432232c27f245ac1812a4e4d0c.npy +03991062-febef99e371fbc27584536aa725442da.npy +03001627-4aa9b5829edec8ac4671d97b0fd17f51.npy +02924116-61d3aefd8450ab0b41cefd10ce5d6cc0.npy +04379243-33dcc9e237783c3c955824885d6e7dc0.npy +04401088-27b4f430b881e16ad6339cac3214b6bf.npy +02946921-f390f6d6418135b69859d120d9976364.npy +03001627-45220c3f4fba09fc665309339296e85a.npy +04401088-f5eb39c7d2e7452ee7ef9fff09638f8e.npy +03325088-75379bfc4f264daec36fb70296e45483.npy +04090263-ac1ad4d7ac10f3e1db6f3ca49e992ad8.npy +02958343-4d22bfe3097f63236436916a86a90ed7.npy +04379243-fe25a9fdbf70cc25f81ed792b3a38b04.npy +02933112-d7c671ead816afdda2aa7d89ba9aea43.npy +02933112-cb506ccfb07faa60f51f77a6d7299806.npy +02992529-8b08eb5ebea05e49a3ed2b429444c197.npy +04379243-4df3ce9b02b4765b1a8db2c23945f1fa.npy +02958343-676e3e6067fc1b065552c4ac8607d25.npy +02828884-f8a1b4d4b7813afe55cb90b2d132a49c.npy +04554684-8dee44b4cd1f34ac856e3ad6b24f68b2.npy +02828884-5b4cc3097e79fd316c262ba0bee45d20.npy +02958343-45d4fae3d107296728e9ca8e8fb04e0a.npy +03691459-dc9c9ce6dc9a771f500158c23c4c5a8e.npy +04468005-837c94e7125781e9978a4784edc632cd.npy +02747177-e6ce8ae22ebd6183ad5067eac75a07f7.npy +04256520-f78b75284089cd6514038d588fd1342f.npy +03001627-c93a696c4b6f843122963ea1e168015d.npy +03001627-8a1a39223639f16e833c6c72c4b62a4d.npy +04379243-fbf9b1f026a86d59eb5bc459c7142a3.npy +04379243-702cebffa33a19f019f079d1b712f46f.npy +04401088-128bb46234d7250721844676433a0aca.npy +02871439-ecb9b808a97c3b009725f8348364f5a8.npy +04530566-1175df3d5cedc3365c00e52236fed2eb.npy +02876657-44e45054f9ef4e251881e4573fc7a947.npy +03001627-73b96acec1ea41d1ad484915511ccff6.npy +04401088-342ef21b1ed9615685feaf23dbe1f454.npy +03211117-41bfdff7b99c13703f7e27638e63d848.npy +04379243-67e6cd9381c22b9045c6cb69e0968783.npy +04379243-1a80520ab14439ef79b3e1be3524f72f.npy +02924116-2f9c60f6eb0a4ac1b4b1329ea0ab3ba4.npy +04379243-4b4b745af2c816c28ffa76d198ce7f6c.npy +04379243-32bbf7d09d3acd4c339797c21e8801b1.npy +03593526-e571895508fb587a561dce3fe08634b7.npy +02808440-896808e1daecd437d72076e39d62f17c.npy +02958343-8a2d335efbf40060481c5c74462bb8fa.npy +03001627-6ad7e3a8e6f3ed1dd068cfb43a81fc7.npy +02876657-b1e5b106e6e25c44a4530e3038c81e85.npy +04379243-289f7178bfabe667550a2025ec9eef3d.npy +04379243-54d17ad404678720d0a96520c31993ad.npy +02828884-2346b4f87a4f683b92e6829c9c63f7e8.npy +03001627-b0c70ce8427da34d98e0d1738edd4f19.npy +02958343-c6978e2a0ef9f0df866f1a483075a782.npy +02958343-4359a0878f823f5b96e24f86f1144c52.npy +04530566-209213f07114a06a2b249fd16295bbfb.npy +04256520-37e4e81fda1f2c923a2face9eb30ef55.npy +02924116-98092c327e82dfa834ac4f8ff2084698.npy +03325088-2f44351ce849a8056f893b5bc716a3fa.npy +04379243-53f5bd148ec293f92f44039661980ed.npy +02691156-fca4c82b2c488d329554e5818acd6e12.npy +04090263-ed5e68fcb3a7be0c886fe00dcdc18c8a.npy +04379243-8c89f56df87eab907e5207b5eb59c49c.npy +04379243-e5567a82c577e8af83ab2e8865eef185.npy +03001627-c7e590c0390e8d5debe67d9b32c3ddf8.npy +03211117-6a85470c071da91a73c24ae76518fe62.npy +04379243-b85174a2ea03f4189cd431573238602d.npy +04530566-cce41dda51ef0335a413908c0e169330.npy +04090263-c9812d343e4e376c95ff232cd38210b4.npy +02880940-454fa7fd637177cf2bea4b6e7618432.npy +04379243-7462ac6e44457697d017709a3cfbb660.npy +04090263-beb9c8ac912c770bd5e0e036a4082b58.npy +04090263-b5afc3eef7f7213250b870543ad6330.npy +03211117-d3bd7aa1ebfa45fcfba7d64da57889bd.npy +04256520-6703a4ef8b0ce866a6fee8e2140acec9.npy +03636649-74dff8f0a865368b4a8e02787dff638e.npy +02880940-baa4d6ca9521a55b51d6f7c8e810987e.npy +04379243-1dce0f95df134fa6498e56bb9f3fbb8e.npy +03001627-aed911c2849ce53b707cdefe012d0353.npy +02958343-ebd820a0694086e81f0d59cde6139796.npy +03948459-a40ea0c5f83700cec0f919a9a9f1e7fc.npy +04379243-df297071493f894e79b3e1be3524f72f.npy +03991062-53f3285cbd0c4add1620f4d6ce4714f9.npy +04256520-9177c05744b77b6f6157c3a167984fee.npy +03325088-72861dc714b3dbe2b362845c6edb57fc.npy +03001627-e3a838cb224367c59fce07ae6c046b8c.npy +02808440-2962e044492c43f2921bd8a746d486d6.npy +03001627-38201114b7f2c48d6c63709946cf3bde.npy +02691156-fbe213adb802384db443c685f436f80e.npy +03001627-8b6f776954e65e7ab05550de345b6d0a.npy +04401088-1a9707b3e9d8345048891ddb73756acf.npy +04090263-2f2e30fde0c26bb36b2c8bb96250e4a0.npy +04379243-4a72468fa13c36cd2bcc0cde35567dc0.npy +03001627-5162651a4c6da72e8a5e49d8f4867e8f.npy +04256520-20f82d98b188f16cad885ade4bf3150c.npy +03636649-1d21fef4a67153dab76e29c9c43bc7aa.npy +03001627-114b563de051057fcda85f6a3e19b0a1.npy +03001627-96eb2c84ab3b8df0c175a98f27dc2236.npy +02924116-94e068a4c09efd6ae2fbdb7fcf40400.npy +04379243-6c4c3bfe275e66b1b75e606711562bfc.npy +03261776-5fbad7dea0243acd464e3094da7d844a.npy +04379243-49c0aaeed2f926e3f2cf6a9bef44d625.npy +03001627-b0cef14f184c10e14af957103f4767ac.npy +04090263-87a868bd1d4cbbfbff56a19447480f3.npy +02958343-48aaa1fcf8da645c68925c742a212a74.npy +02876657-4d4fc73864844dad1ceb7b8cc3792fd.npy +03001627-79bd56e6a44e5bf1a3f600c356573d21.npy +04379243-3037fac5bc67207e23fa92d98173c06f.npy +03991062-49195d1e985bda23bd9d6adb1ec203ef.npy +04256520-36f7e8086a8849fd5883ca9b41ac387.npy +02871439-184eb80b82bdd4e1159f1e6a557f2ea8.npy +02691156-55ce4fc0b3df0234bbf3143b1cb6076a.npy +03928116-a5e01dbc483964989ff9b70e6ed76515.npy +04554684-8405ab2d49b428b191219aad82abc053.npy +03636649-9cb61effca346d48eeed1ac073f42256.npy +03467517-d52f696ab86b354624933d5e1bb8057d.npy +03593526-3834ca6d4c3fda9d5b2ecd212557fda0.npy +03001627-d1ec6e9b8063b7efd7f7a4c4609b0913.npy +03001627-671d51da473849c7369a4f66bf103682.npy +04379243-268436b1c1750a1e14659d605ff53c6f.npy +02691156-265e6c77443c74bd8043fd2260891a82.npy +02958343-12909f5d613953b8b3c9b3f81618206b.npy +04379243-1b01ef65920c342323bdffac38e6b250.npy +03761084-d54fce16dbf7ba12b8f6d409bb3f1e7e.npy +04256520-294fe191a191f812917b96045c9b6dea.npy +02992529-f7fcc773249429a2761eb63018291094.npy +03790512-4548d86cf7f1c11ad373c34785838ee4.npy +03001627-92ebdd82509fd637593ebeeedbff73b.npy +03001627-f444df40dadd83e22cedd65b2f6d1fdf.npy +02828884-e86a2291d77b8ff9408623dbb138b966.npy +02992529-e9ef88d72ead910b8b431083b6191e2.npy +03046257-726c7cb702cade25ad1da5f59ea6f4e3.npy +03938244-4b351af9567719043a4cd082c6787017.npy +03001627-f66ea5e07a8ad9eb283b00891f680579.npy +04379243-1161ca9bbd655ca17b431cae0dd70ed.npy +02992529-8cac6df50c515c498be6bc9d57b6a438.npy +03593526-b517eed6f77a7a39586574d8cfbafba0.npy +03001627-2a79d429e9effa6de7c7920f6a65a54d.npy +04401088-89d70d3e0c97baaa859b0bef8825325f.npy +03691459-bb3667b3a72b0bcbad6ba00d22308a6c.npy +04256520-94463eb34be49887c3bd24f986301745.npy +03211117-816eabad5c1ca552744107c67e903f9a.npy +03790512-a19d4bb8fe4e70b9d97964d17de80d2c.npy +02691156-a2b6edd3f2f060c7ca8607f540cc62ba.npy +02924116-276002136efe5849193d7855ecfc1bd3.npy +02933112-70d390b1e9b3053a22ca415af010d9a2.npy +04256520-7c68894c83afb0118e8dcbd53cc631ab.npy +02828884-909fcd9e329cd49581faebbdea6bd9be.npy +02880940-4530e6df2747b643f6415fd62314b5ed.npy +03593526-701ea218827f9a7a733657da4b6687f4.npy +02958343-6969e9ed46acce2fa7fd25564c2e888e.npy +03691459-ff4bc6c329ec7bf8a0eebc16d3afb516.npy +04090263-5c1d62c9ff844458cac68db180607870.npy +03001627-a3688350b1556cbe65ba78ad9601cf1b.npy +02958343-d471c4f43f008df5c1bcae9def1986da.npy +02933112-785b58a111b0498b9572486e5a924845.npy +03001627-20964e03ef001d8910684e111251a45.npy +04379243-43ca66b4cebe3aab41c3fecef2f1308d.npy +04379243-499ab88b7bd33cb92466f73de2a564d0.npy +04379243-1ef6c2b9d413fb7c681404257d94ad9.npy +03636649-dac3843c8f77b34362a510b8f97c658e.npy +04379243-cb6c20669c6d1dea593ebeeedbff73b.npy +03001627-f4a0d0169abf306a754ec1f2eef2c6cc.npy +03001627-87f8fc2fdc88e4ca1152b86a40777b4c.npy +02924116-c352ab905d6f741c2913b5e01aca8e8e.npy +04468005-c7b805e1ebea97f0f4ad1770263e7f39.npy +04256520-93bd851dc5bb3527d437a7a1ae2552ff.npy +04530566-6b87ed6710a0fc8d8aae7c4db7244339.npy +04090263-6de1ce73a377df3633faa05410dc119c.npy +03624134-bf07ece7d3c0a28f9d40dc50674e6347.npy +04256520-1af92afe68b3f837f51f77a6d7299806.npy +03991062-2ab54e76c7fb6a3bcb2a965e75be701c.npy +04379243-96d3a59baa02d7a47d117016cd1926d1.npy +04468005-367c2b062bd2728e40f45eea058ceeda.npy +02691156-9b62f887f1839e5f4c3a35cee92bb95b.npy +04256520-a247bf1e595abd266080784e4b7841e1.npy +03001627-a1ef57bc2563ec37dcadf30d9ccdd100.npy +03467517-2376a95ba9a43414c94b36e9b7b92195.npy +03001627-f083f6f7e9770fb7b161f36d4e309050.npy +04256520-c0036465dcbeed6a912f115faa04d51.npy +04379243-a2dbd26e8a382509738e43095496b061.npy +02933112-57dc5950f0a7304d4da5feafe6f1c8fc.npy +04256520-23cb1d667213c3a7e897e87345fc323b.npy +02747177-2f1510cbda5a89e2bf3f7db9590eef44.npy +03337140-44d1045be6acb7e5920de219c00d1c3b.npy +02818832-ce0f3c9d6a0b0cda71010004e0594e66.npy +04379243-ad243c4ca5f44fb828b75d6c308e3c12.npy +03001627-e84b5bbe91e0636cb21bc3cf138f79e.npy +03001627-e9e7883a296587ed804722305621f918.npy +04401088-541cc8b3ccf4c799502122ac3599bb74.npy +03001627-2669d4df8adda44571a782a4379556c7.npy +02828884-c293f2fbc66af3dbf4fb4dee5181bee.npy +03467517-fcfa96b85ce4d6114e96698ef01e7360.npy +02808440-47f4bab4593437481c17aef130ed6213.npy +04090263-c8a74709a6a0724f96a9670983483761.npy +03046257-d322992d2c1df38b75119b5f9ee576b7.npy +02992529-ec39e26f8c0829b3413ef77469a0f9cf.npy +03001627-b89952c6f2dbc1aea50b88953d263a42.npy +04090263-c7f54b82e3b1682b65564d9c2ed3b493.npy +02691156-43abe330362164e99be82ec29531a70f.npy +03001627-5ef3e4abd4386c8871bc6030acc85f1e.npy +04256520-48484a86775668cc7e77281775c253e.npy +03001627-8778c23fd21bdebf8a80d99ff4e76c20.npy +02691156-66e60b297f733435fff6684ee288fa59.npy +02958343-dedd7ee03210ff8a1ccbd9e5bb82dd04.npy +04379243-b9fc2f624533bb8119fb4103277a6b93.npy +03211117-ba29aa5a87317ee09327b89c3431616a.npy +04090263-8ab72b47faa4d2d4b524fe86a5d055d2.npy +04379243-acf57dbafe8966f577fb15a8d7923976.npy +02691156-9fb0988ef701a11388170d426b6605b5.npy +03001627-bd41ed35fcfc0ab7b5e2296ee51ed515.npy +03790512-6309c20c1ad258efbb297232fe17fe77.npy +03636649-f01cf64f05572ac4b509f4ddcfa8ca1.npy +04530566-b791549dfe175150a7d88fdd8b14a0fa.npy +03513137-8f17e31867f1968969b2407ca5e1a9ac.npy +02958343-2f369806f69ba9cb55048eb8b7ed14b6.npy +02958343-c92ef17bef6471f72a9eb0f146e94477.npy +03691459-aaf32dcc3d51cdfe81757e1914c08a9b.npy +03593526-fed045d07c91bb2723901b5a0f119b35.npy +04379243-240ddf8b63318ef534506cc3910614fe.npy +04379243-4132539ff314f0654d1fe7f29df13cf6.npy +03636649-19388898dd69dd9fddc8e6d1ec6242c3.npy +03636649-869836fe379f585a732b621b679fbd70.npy +02747177-fd013bea1e1ffb27c31c70b1ddc95e3f.npy +03001627-8c3a4f26d6ea2c864a3bb1a89bb7ce84.npy +02871439-21e537b6d8b8276fd138a53ab0d038a5.npy +02958343-f70df58949dcb108b682148e4ffe282d.npy +03467517-e5ff4634ee6d00323f00d55155ebc541.npy +03001627-38f8b44fc8dac88ce3c886e48eaa6e2d.npy +04401088-e4a0f08d8a6d487ac9de9dbf8ea0d889.npy +03636649-48fc49989a124917cd4a89b0fee32930.npy +02880940-2e545ccae1cdc69d879b85bd5ada6e71.npy +04530566-da15ecf40742e9e46d813b270092aa6d.npy +04379243-6eddf598e4199497d684faddec3c0090.npy +03001627-3e427b76d051cb9ccdea755aedb6e3f3.npy +04090263-2a45063d7d03b865ebeab56de94a5835.npy +02933112-85f41119ca2bbde1dc1f6c4cdb4bb9b3.npy +04379243-a530dd6e10797f3dfa5f1c647c19b0d7.npy +02691156-ce2c4502b06c3c356abde8e1529c422f.npy +04379243-ab0393b07d2965ef79675bb6cb63c97.npy +04379243-d3b715e7d98bfe98658d908a2254f194.npy +03636649-3b5f0c01c2b914fc6f16f167d27a7dab.npy +04401088-180f36e0bdb9b33f53de6f45c4ae68a9.npy +03001627-d8358969dad764edbb6f5a9e4b6b8b34.npy +02924116-bc22e40a72a1fbbce99562689078395.npy +03001627-9b359e42a5bc98572085b87de8f7581b.npy +02828884-10654ea604644c8eca7ed590d69b9804.npy +03001627-a3260f0c8fddf11cf0f4992137d8f4a3.npy +02691156-f4a5b28233523a4e588ed1d0f708d42f.npy +03001627-2b90701386f1813052db1dda4adf0a0c.npy +03593526-bcb86164cb709371377f115011370864.npy +02691156-c781fcd64271dc15224d7b1b956e1382.npy +04256520-167088246175f31c593ebeeedbff73b.npy +02958343-85f6145747a203becc08ff8f1f541268.npy +04090263-d442863599da17d951cfdb4c9f126c12.npy +03636649-9d41e23f00d11d153033d35b49a20c8.npy +04379243-93c2221188b4948f79b2fbab4d71b78e.npy +04379243-38feb6b209579f6faadbf8208284c675.npy +02958343-90f85f62885afeec65ca154580c5c7a.npy +04256520-6645c2afd5af2cd2610c2a68437007d6.npy +04379243-242b7a0fa9e9c439b20aa91e9e90c311.npy +04379243-8b4ccdf057b895f888a682c7326c32d1.npy +03948459-d3baf46b6c8a162fa267c8b6fcca89d9.npy +03001627-d3302b7fa6504cab1a461b43b8f257f.npy +03636649-605ddd207eed0d81414aaa1b9210e59a.npy +03211117-d4bffa0adec5f9a73387ebdfbbe050db.npy +04379243-26b2a15646f6a3a06f1e07a56c129dfc.npy +03001627-c0e5edb2602a7bbbab3d781e4dcb85cd.npy +04256520-af6ae25b2e295c36d79b19c7c4f0e293.npy +03001627-b37c77a90ba66c92564339cd0fd02849.npy +02871439-f7b449e5cbbf1ad26402b8f491cd92c7.npy +03046257-f9c02d4ef3c07b16c0a61ad1cf92b694.npy +02992529-97669779da217dce4f37c101c765cd3f.npy +04379243-fa7a5f65c561d9d2fc43dee2a1d6272c.npy +03001627-5fd2483e98dc2ddef3c9c1464e55d580.npy +03938244-5ba3bd3907f4513636902d83e4cc385.npy +03691459-56e2ab8ad78040432b3bd152980e4b5a.npy +03046257-5a9ef9410163bb569100b79b765fc7b1.npy +03001627-fe47e7645f1080735f0277eebfd05be2.npy +03001627-95e1571acdd75922afdb9a672b7d3b8a.npy +03467517-e4a2c2b16b5425825d90edd33668a4c2.npy +02828884-459cad806518f195ba6d436b28fcddfb.npy +04379243-e7ed7eeb46e18296fdb9ebad3cf3755b.npy +04379243-44087c74e5ea66dede436dc05ae39dcf.npy +04090263-c65cf6b063e1a21025251b7dc26d833f.npy +04090263-dcc3914659963636b2c8bb96250e4a0.npy +03325088-ade333c657e7b1c2b362845c6edb57fc.npy +04401088-ab2e514557ecb359224096f37ce8c08c.npy +03001627-b06f26c5403c3e922e653f6e789d3d8c.npy +02958343-1254c6ad2b420879d7622e6da48b19e5.npy +02958343-48260abd4ff73f99473f10e6caaeca56.npy +03211117-23c99db82c910931e2c8e43c97ec5a85.npy +03790512-3388b8d2486d366ab19ce2dec0d1925.npy +04004475-37d9a0dfc5051bbe8d793f7f9f50b0c7.npy +04379243-6b457dbbd8d875afd3520bbaf4a08c12.npy +02924116-ff7348571fde88cd6c1dd93d4254dda5.npy +04379243-8cd0334f04368168b8025ff83c807f47.npy +03046257-33d36c060f80361b4b3c42e318f3affc.npy +02828884-6319038bd4748a03d2b12aa6a0f050b3.npy +04379243-db406d9b2a94bce5622d7484764b58f.npy +03001627-2a56ff0143d4e69fe6fe3612af521500.npy +04379243-d15135247c2f52ce420e437840bac4fa.npy +03001627-3e53710a62660c60c39d538df4c93695.npy +02828884-ddbcdce0db6aa00524b325c2195eaee5.npy +03046257-c15389c173fc1cfd415cd6d00346fc76.npy +02933112-47f477a8b67d28028f1735145fdf5c5c.npy +04468005-b5bdcbf79ea375158be7c8c5fdb9bd6d.npy +03325088-940eb228aa016a3a6d86099178635a1e.npy +03467517-e70d5369f840577593f0194265a9746c.npy +03691459-4949c92a3f0d0946f536dbb8b34a9553.npy +03001627-87cdc53aec65aa0ff51f77a6d7299806.npy +02828884-8277bffcffda5c4edab3d510e4b89249.npy +03046257-c0add30f5a2566165e29ce2c9d37b952.npy +02924116-6b4a68af3d9636b96076a0921edbd4d.npy +03001627-bc92651fd7cd9ca8cf68feb7ddf815ce.npy +02828884-f98b9721d2f5b3d7f4f81e1d4b32b45.npy +02958343-ec65260a83a395e850df5ffbac7e7f74.npy +03991062-22e28d8f92a632ef2dacb6509c7ddd54.npy +04530566-6ec5e181c6df65d9a7afac0aa00dd174.npy +03001627-1d9dbebcbb82682bf27a705edb2f9ba6.npy +04379243-c35f0f50664264d5e6a1cd9763fc2f3f.npy +02992529-388415634e1056942ab70120fece57c0.npy +04379243-78218e7cf3b5f6026e24b3256330e605.npy +04530566-77327d5b8b56083415a0ff0aad35ca87.npy +04090263-36846ef535bd195efa45f4d7e1ef7d0.npy +04090263-eb39683f67d5d2fcc648677bc9b1d6ad.npy +02924116-4191757df8aed75952470de2774d6099.npy +04090263-317353de88cac813d9e057a3558cbfd4.npy +04379243-813d7c5131f6369cb898f6ca189a940f.npy +04256520-978dcc1e9c3f9a3f92a31ec18c4e190a.npy +02691156-9eef6307dc504b88392b84e3285cce39.npy +03001627-b1cbca9a2646b6f1bf899e941ea0fe55.npy +03691459-4829f4099c72420351c3197f6363608c.npy +03261776-4262c3dbd68a5c14957b6a4f3924d982.npy +04256520-1f0f9a821671271eaf288f952624966.npy +04379243-6e31a64910fa5fdc9db8ad97fd392b59.npy +03710193-150ae00a9d9d07788ae1c1abea367249.npy +04530566-3216e49e5dd304956bed41d0253513f3.npy +03325088-5943e3c0ec6edcbc76c18e71fd49c4dc.npy +02828884-ae99771e1f77fd2fa9bdc22a1e02e82.npy +04530566-3da3c73abafe7a9eb9e86d477b879ac0.npy +03691459-f6cccbb93c35fcaed49b96b9f2811c7d.npy +03759954-86e2b5f2603db0ca6ef604d255267aae.npy +04379243-e8ed10a7666a10a1edc98d150672fbfd.npy +03325088-e6c895dfe3150772b7a867e9b35a1295.npy +02880940-18529eba21e4be8b5cc4957a8e7226be.npy +02876657-14588e373cdb9143ca972ee98a070b3d.npy +02958343-7dfe2b1451449501588556e812e00901.npy +02691156-abb3c5d793e4c26d7aeb2194e56698b4.npy +03001627-6af354d0e86b1d5ed77c4541cb2e97a4.npy +04460130-800f8586461b18c238cd8eb23853c009.npy +02924116-682856891ee0318bc2876b98c07c9251.npy +04256520-18e4ebaba8998410ae8c9d3b8c4b9bc3.npy +02691156-20d97069df784e19a80799ffaf21ea7d.npy +02828884-4a5f9a0672cf3a1fad5067eac75a07f7.npy +02691156-ddc14c7e0a228663796843908eee8f7d.npy +02691156-816935cac027310d5e9e2656aff7dd5b.npy +03691459-6c2a8b174ee60c241ad88f716ea80910.npy +03797390-dcec634f18e12427c2c72e575af174cd.npy +03691459-17f87baa813447ab9588e71e21de9f30.npy +03001627-665bfb42a0362f71d577f4b88a77dd38.npy +03001627-8a9d6ef075d5a0721242c827d7f16c58.npy +03636649-85f71a4724fa37c33d39d8012919dd25.npy +04379243-5f100571ffd90f8252b4875f731f71cd.npy +04379243-63cde6b5e85cae2bf4b6538438a0b930.npy +03691459-9d43e1b188ac816087d72888c0a9277c.npy +03211117-3ebda8146a84d7e64fceb9938a41179f.npy +03211117-eb2b450565c77e3efc7ff8f848d1c6c9.npy +04530566-9472a24df8372cd42e436d38f27146ec.npy +03797390-8b1dca1414ba88cb91986c63a4d7a99a.npy +04330267-bae2babb26dc352b20489998d734835a.npy +04090263-bb7474cb9310e33aa7dd22c0aa3913f0.npy +04530566-206c86e4cf614dd5d03c0ce6ad42cc93.npy +04379243-a9ac09540c655b08d0bdd07d0170f389.npy +04379243-19dc20a7065fba0501a7e3ae8c65473.npy +03691459-9cd16abcc7fa224ce029fab54b6cfbd.npy +03211117-c2d39973237252e85e7087f2d9a278a9.npy +04379243-7e2c9dca60e09009df1d847ee0a8f3d3.npy +02942699-235a6dd25c0a6f7b66f19f26ac490096.npy +04256520-32cde5adb86d540a2eb3768aa5c5fa1c.npy +03467517-a4274a5db19db1ed7c8a96b42661aee8.npy +03636649-763ceeaa4ce2ce1d6afaa22adc38077c.npy +02691156-aa5cdbe94abd2ee15042e5fc5b753f1.npy +03691459-7d75382b7b9e7bcfd88a3e0e92891ad5.npy +03001627-a3d1cc17aff08bc7eab55e294b4eea02.npy +04256520-9d5461070e008c453bdc60e3df3aace8.npy +02880940-b65cbede8f483d51f7de4d28691515e1.npy +02691156-a051219f3f444fadc5e2bf7b5a5f1c56.npy +03001627-8b6f6304674b1280d6cb6d27840b9d7d.npy +04379243-56daddb695e25fac341afa383659322.npy +04379243-5214aab74399556959f8e31ca87c470e.npy +03761084-1605a1923b99fe6bdb4c5469c0c1ba80.npy +02958343-aefcbac53b05ed5a27404deef339faa.npy +02691156-260288918550573dc9eda6e157b92d90.npy +02691156-81440fcd51052844af7d907e4e1905dd.npy +03211117-25913689394d86bd158b0b2e23af3d37.npy +02942699-17a010f0ade4d1fd83a3e53900c6cbba.npy +03636649-cb60159e291c3e5cfcb8d8c6d4df8143.npy +03001627-5fc6b04623ae6a9963ed57e35c972b4b.npy +03642806-72133503ddaf54483e725ee552a0026.npy +02992529-d4a038b20b1250d7241d076ab53023c1.npy +04379243-2053961ba985591af51f77a6d7299806.npy +03211117-6011d9bbe9b04cf7b6b6751f39e7b3e5.npy +03001627-49f3a28d33c34838d74aae0eb2ddb027.npy +03001627-3d442388af50f61138ae3771b1788e76.npy +02691156-21bf3d8201e3e41f93358ca8580664d1.npy +02691156-7bc46908d079551eed02ab0379740cae.npy +04090263-188c3d3b8da2b83c2d4090ebfdad3018.npy +04256520-c070cc8563e2b3d65d06d6b9708d8ce0.npy +04530566-2e4adc3992a773b1eaac92a15231622.npy +02958343-38334022b922a9d4e7540f431cab4686.npy +02958343-44cc90939a67b72c71778fcae3da6f00.npy +04530566-4e5b83181a13e0661868b1150be0eef4.npy +02958343-9aca55eb91a9b348ab7ba9bb57593f51.npy +02691156-24bbc1f5225969fb90b1d6deb98feec6.npy +02992529-844633a98977c10d9eedb085a3d8dd72.npy +03001627-206dcd879e5c3fe8df4cfe396cee719e.npy +02828884-38d4d7313a3698704bbe1e20736de8a2.npy +03593526-e74cb96c0fc30d03993afecc2c675915.npy +04530566-cafc4d2198b6531bd5527b961edeb7bd.npy +02942699-657a650215e453846f90fff80f29e77d.npy +04379243-2444551d00693a0fab610b0c94236463.npy +04330267-c586c25a121326bcd621f96e518e01fd.npy +04256520-2c1ecb41c0f0d2cd07c7bf20dae278a.npy +04004475-3660a8b78046ffc52f81cb887dc35578.npy +04379243-a78273aa10b2dfb0bc8d334f99e7f52.npy +04090263-da9069b1bef61215716e30105a919115.npy +03691459-e6e085e31c30925466bdbbf263e9429e.npy +03001627-9fae8d94a028e9ec2818b21315fe1bde.npy +02876657-6444875e3217bf891f5f48a891d827bd.npy +04379243-b5168a95f760cbefa22728b9e8cfa4dd.npy +03001627-1013f70851210a618f2e765c4a8ed3d.npy +04530566-21256efa0a78f86b4448fadc60fab7a7.npy +02958343-8e72ff1064eef473714e6c6511843d28.npy +04256520-c281babcc88358f31ff05e2259c2ba15.npy +04090263-a83bfd1065f7dc34176d7cd6eb76e767.npy +02958343-bbca92f53f04d80d8bb5c0bf5eec83fc.npy +04256520-2a027aef8813a131624a1aaab5ca52f.npy +02933112-d77dd358b31497aae2f840a8b8c7384c.npy +02828884-bbe3d0864b95faca48d057884d36455c.npy +04379243-69c74567d77a88fe5af397cf24be6deb.npy +03948459-6640a8fac8b624a23d2e4fbab0e82203.npy +04379243-597b0d10535c25d538f21a3304cc4bdc.npy +04401088-2b829a38051e6f8d1f6dfedaba98d5f9.npy +03636649-59ca30266fb153ba50f93b609ce4feaf.npy +04379243-1aed00532eb4311049ba300375be3b4.npy +03691459-614a16b7b994063af6d28508a7c94d33.npy +04401088-bf2a5f434972f11a690a03770c5de186.npy +02992529-d21231fb7d7f7337f521a3dcd28e9d2.npy +04074963-9d5f59e259057baa910a53622567655f.npy +03624134-3b1f7f066991f2d45969e7cd6a0b6a55.npy +03337140-58f68e07e47eac944c3aee8e9d3a6ffa.npy +04379243-59dd1eef8072ad8de074517a246f1e65.npy +04530566-6cc258399daf767ae1942965937d3cef.npy +03001627-e193b0d75fa674142b3e9b6eb52d35df.npy +03636649-fbd59db93e38bdafc8687ff9b0b4e4ac.npy +02958343-e00169580fda5461473f10e6caaeca56.npy +02992529-1621e08661de948d7532dfb76fa58e9e.npy +02933112-4b006b7a2215db3d284f6213916dba67.npy +02871439-8a5783031f99e9d5c8bec3671aea0fa5.npy +02691156-448bd2bcde027ca9e5d07633dda45110.npy +03991062-9a630f5e08e2cd8d61a095aa05632df0.npy +04379243-4643de4838d7048437251258858a7a58.npy +02828884-df31fdbbf7e3616b774561c9c1990536.npy +04379243-87b15b50b03054360cbb0bb881f838f.npy +02933112-6d42969890762ef2ec8eb53ffeeadc85.npy +04090263-8f268f9f187292f1179177d1cafed62b.npy +03001627-776cdc2ed288076882eddefc99ebacfd.npy +04379243-8653180e64d70a47b3cf15c77de45986.npy +04090263-6dcd7fbe37463ff38d4ca42bc1bef451.npy +02828884-6a11450577768f2747d4c7899ba36cd.npy +04330267-f1ce85e56633c1cabea08f0d71567278.npy +04256520-d8142324c33dfe7595bea7c29e873d16.npy +03001627-ac47b4d30b598978d5a4a04ac21f0578.npy +03211117-5bf10196a11a166466ebaa8e9b491151.npy +04256520-841cb38f7447dc698e4182295c92f949.npy +03001627-5d3cfbc8bae19e701f580a0f9153317f.npy +02691156-df411aa240fe48d5855eb7906a7a7a04.npy +04379243-5db59a8ae13705bd7843fb4efdc19510.npy +03001627-25196058a95b4fc3359e362142e70c8d.npy +02924116-c2909962fd25520a696975d93fda1bdc.npy +03624134-85ced924eedc6ff566b5b592ed1ddee0.npy +04379243-7e3022a7bd00eb4195b8ea6a366e14d.npy +04401088-500fbdefb58e261af2cdad303f49c9f9.npy +04530566-f4923b4ce88bdda3a9142e7277ee08f1.npy +04379243-d007026a83d6be854e48282b72e69035.npy +04099429-e1cb02a589e09aa193a67322c4cf7081.npy +03991062-870c7ddd93d5b7c524042e14aca574d2.npy +03046257-6080c5b09917c23830c7810cba6da248.npy +02818832-ae200f07aa45b3381efae51bb1dffa9f.npy +04530566-6f4a328af926532b642f9e27aaf0c47a.npy +04256520-7173c0462d9ee2a344949d7685cb63ea.npy +04090263-5b37d0eaee45e12cea768093544ea6d8.npy +03928116-2b8f0dc6c0bd6764f5072ee3ec9236b4.npy +03001627-9930f9ec8e2e94b4febad4f49b26ec52.npy +03691459-d088d0b4cbf1d8447b041fd2144f3532.npy +02871439-538ccfb554d8179bf3bc30c1c812e48.npy +03211117-4516c31dae48a0efbff4c0ca0d98b77.npy +02958343-791885fd798b1981c1006ed55bc1a3fc.npy +02958343-6d61759c3f8636f816abce8cb03e7794.npy +03001627-ed7b1be61b8e78ac5d8eba92952b9366.npy +04074963-49c6003c2248bdd1906ed109a4ea50d6.npy +02958343-df672140efe7b8ca89e9a9eee39907f.npy +04379243-4791914b3bcaf57efebad4f49b26ec52.npy +02691156-d2842bc324b3dac5bc0909d98a1ff2b4.npy +03636649-16249c6e2a76400dfcb8d8c6d4df8143.npy +04379243-61b80232d3aa0a409ccce4c6d5bb195f.npy +04256520-d053e745b565fa391c1b3b2ed8d13bf8.npy +03001627-fe20f6a58ca6c84c914eb005afa6475b.npy +03001627-b899182610c12c78ed88a55f92d81d7d.npy +02992529-d98df8313cf5e0a7814fa32b2a1183d4.npy +04099429-aca0df6bbdb0ef3f870a795cbbf52b3f.npy +03691459-c76fc96ad122a33e75f6e8ca4d589c7b.npy +03691459-5e71a80c6ac94e0177818a0572bf1777.npy +02871439-d0739d3cc5c3549eefd584ddda1b5aa1.npy +03325088-b3565dc2c1e46134b362845c6edb57fc.npy +02958343-4a5bd025a2500b3b3967c36b4916b4de.npy +03636649-a1a81e5d0450d463df9c597227d75069.npy +03001627-79e5eb7be94f5479696b74614952b2d0.npy +02828884-d7d6a7fae6003dd6f4fb4dee5181bee.npy +03691459-d4562a410244eca8823eead1c8e7b3b4.npy +03001627-95e5f6e550761aefe65b629e4a22f51e.npy +04099429-777aa6841e1306beb5a9f8d018fc9500.npy +04256520-1299643f99c8a66df59decd9cfc8a5bb.npy +04256520-dcba7668017df61ef51f77a6d7299806.npy +02808440-e90977d3e1c960ed904e03fa15bd73ec.npy +03928116-35259e9bb2669df79bad64a9c6516f06.npy +04379243-3016d678209377c1c3bd24f986301745.npy +04090263-a669193672e033f512b38b1d99376c0b.npy +03691459-11d9dd7b170216eabc4d71e69505510f.npy +04379243-53ac82e4ef6af3da9a5ac88c7195fa36.npy +03636649-ee3bf15041b96387fcb8d8c6d4df8143.npy +04330267-8974fdbcf6bed0fbf0f660d2dc5ddf2b.npy +04256520-3610635cf623f3f8917b96045c9b6dea.npy +02958343-51e74bc165f2cb21e2a6bd02594b7cd0.npy +02828884-5f3782702eb8f2d421b4fad85a658c.npy +02691156-196d35794f869816db6f03b6829a5891.npy +04099429-974472ca7b895f74c6f5c7c0f17e11c3.npy +02691156-71f718d82a865472bfa44fe936def6d4.npy +03467517-12e30808350dd945f4b498e11fb60a4b.npy +02946921-343287cd508a798d38df439574e01b2.npy +03948459-18598beeeedb20729a6e43b878d5b335.npy +04090263-2970d1dc154363735960f9d4a75e81d8.npy +04401088-fe34b663c44baf622ad536a59974757f.npy +02871439-957dd2b31285002b4d6ef9ab90177563.npy +03636649-454b7345c01c404b6d0fc9460109eda7.npy +03001627-9d229e34818effff07d3e3c7bfacb95.npy +03046257-63664307ac493090b129901f80d24b7b.npy +02992529-420138dffb14f929f0b45b4b4c7e33b7.npy +04530566-408cdd476e8bb202852ae095a967f0ca.npy +02992529-ac0a78736d78a5a5dd8524baa80cc603.npy +03790512-481f7a57a12517e0fe1b9fad6c90c7bf.npy +03001627-cc25ba35b3f6e8d3d064b65ccd89778c.npy +02691156-857350d3e780366537678474be485ca.npy +03001627-510fdcfcba1bc18ea1081ad712f6fb3.npy +02747177-22213dc6019c215a81faebbdea6bd9be.npy +02808440-d7d4367ef5ee5991b362845c6edb57fc.npy +02828884-f8dd3c18e0735bb4b2644d7d4d7ea2c7.npy +04379243-2cafcc8c772d4860c2d043ecbc42284c.npy +02958343-2f2ed1fa349d50f3bb15a692385994d1.npy +03001627-e41e8329ed0c0b88d93768e7b9b1eabf.npy +02691156-c5ff8a911c2780efc03676083f8f4de6.npy +02924116-f90cfb1b651090cc477d87ca43ed5744.npy +03790512-966cc24ec5fb927b22b51f1a980f45bf.npy +03636649-88257c5a48d94b1e2b151d8b52c53b90.npy +03467517-f6884341f0d6d2cd69a645978ae8c765.npy +02954340-30be60f95e2a3b47a6e67635b9d1cee5.npy +02942699-9e91f482b829c4d1e9fff7dfdebc774b.npy +03325088-ce69c6b309dc055eb362845c6edb57fc.npy +02808440-a8765cfb0701f015fe52ffd0e748a1ab.npy +02691156-b80131dacfa19f77337e02e3502c7536.npy +04530566-d214cdddcfaeb0cbcf8dc8d39d90900d.npy +02958343-4f54d7acc33111a56afa0fe12a1de326.npy +04090263-f5cfa769619f708bda733a39f84326d.npy +02958343-de683c906ed97d7456ca31471168385.npy +02958343-c617227027a05eddfec731b1d5d5cac4.npy +03636649-dfe800d8d8642e9647bc3701b998a7d5.npy +02958343-88aae5646dcad7062a9eb0f146e94477.npy +04256520-480cd721e7bbf720b0eeccd21a9bc702.npy +02958343-f3205edd456cf36feabc798aaf5f039f.npy +03001627-23babf1dd4209349def08b067722d9e5.npy +04090263-e49e18cbd48a2479cdbadd1af48b5cd6.npy +04401088-54b4288766d87dcf332f5e5df5b42874.npy +04379243-6e77d23b324ddbd65661fcc99c72bf48.npy +02828884-31f34cbd9385944181faebbdea6bd9be.npy +03046257-e5d21511678e9075b8b431083b6191e2.npy +03467517-c553d5d6a458401c8792f38f9bbb6676.npy +03467517-a4fc4b7d8d40790e4bfcfdb26b8cb2c3.npy +03948459-a3679104af613021912d826efe946a9f.npy +03046257-9f56b67ee6ba16fca05d3424fd8d541a.npy +03636649-85f8a8c585742c9b96a3517f50eeb9f4.npy +04099429-4bebae2aeb3e9c0d2ec5ae9242443840.npy +02808440-2231d841b91eb6d53321831d2245cf06.npy +03001627-28d3e0a4e4201ddb19ed4d1541e44f14.npy +03001627-9a3d7e6194b7a5bd3825a5bc524f67c9.npy +03467517-9ce5c54dfe145950156788cef4ad8bc6.npy +02808440-14b01ccd00ceb5e4a701ffa903c732b8.npy +04379243-79e3d485572b54bd9f2349486c570dd4.npy +02691156-5abba5b86814b98a9f4ab5ced9b9495.npy +03513137-3aad2f60419948f891003fe635f8d594.npy +02828884-2d80f237dfa7e73e5b7bc62e486d578c.npy +03928116-6f09b0176486be2a9c75eb4326997fae.npy +02828884-754250f866079c2083f64069b9b28eab.npy +04090263-f2e64c42370475cd52533bf53842cf9c.npy +03624134-a2288d5f3a44233bc40c6b891c4913bd.npy +03046257-8d9e42ef36ba9e5f7dd46011c41be2ef.npy +04530566-6a5f7a634b13ea7a94daa4565dd30535.npy +04379243-97e2ca564decce0b575f9747ff6fb5e8.npy +04401088-e5b629f4a5e7467066ccbd11a6ef0f68.npy +02871439-433136c9fa211d5867f7514c37b83a.npy +02691156-f36ac9cdcf15ac8497492c4542407e32.npy +03467517-740972191167ba363fc4ae76a96ac53.npy +02924116-c7881385a4077694f5057f866a21c1b7.npy +04401088-bbbca195cd6b85f1562c8e1ac545ef78.npy +02691156-30b514b24624da4fc1ccec171a275967.npy +03636649-92c2c146432ff304153c1c3f0c464db2.npy +03636649-84e870f2255d6b6efcd4910413c446d9.npy +02933112-5bcb725e26e521364c7384dbb75cab0d.npy +03001627-d417795442cb0f75593ebeeedbff73b.npy +03991062-3df897f668d419b978caa162a41a851e.npy +04090263-75ca1520edb6825d12b38b1d99376c0b.npy +02992529-ccf2058300cac188639e45fae4b57d2f.npy +02924116-1708ed19e3bfd07b2504ddb627974db0.npy +04256520-2860b2b5e16f4ae8c29432ec481a60b1.npy +04530566-96b27c98daf461269ff59e10e6ad1a4c.npy +02958343-83e537cd6bb435e91d1a964dea8a7aab.npy +03001627-6a73ce89c4a941ac0f947750540fb22.npy +04379243-5c2ec61293c30ee7bdba4e1fee183355.npy +04379243-1164897f678f3bd627e98d0f3d735480.npy +03001627-ebf1982ccb77cf7d4c37b9ce3a3de242.npy +04379243-16b72d74bcac545fe3eedd8db265e106.npy +03636649-fd26f566fe08c3dac64d4b10f9dc65a.npy +04256520-47c45ac7187a9674421b433358248213.npy +03593526-ae77abbf5ab4893da75d03186a0409e2.npy +03001627-4b904e1d68d09dd3e15e36ac023c5182.npy +03211117-36ea450f5d479481c795085b4d203932.npy +04530566-24000ec6bcb6ab9182b5804533e545b1.npy +02958343-7c85e6cf9c4f46e91cc13e432d5756b8.npy +02691156-9e617d72fabc718b90b1d6deb98feec6.npy +04256520-7d2032e1af7fb191cabc196a7f35f1aa.npy +04530566-df0f90c6abbfeaa0255deca950ace5f9.npy +03636649-1165e8de3cee9f706314698551cd43b.npy +03790512-6ea0a49bd27fa58b2279b76b11a9a16c.npy +03948459-49483669657caad2f6a222569e8730d4.npy +03593526-fbaee96700018ab3835b141fda2da5ed.npy +03001627-8dccb87a61e565cfd4713685ae50fa13.npy +04379243-4f38d59a7fc3010fd7483d79670cc91e.npy +04530566-31230e9a2e4d7cf7cf291a4a9f36cece.npy +02933112-56676ff1d9f8a1e94c61a7cce317bfb7.npy +04530566-e0190bd315d8109f542c6282a2a9329c.npy +02691156-fb06b00775efdc8e21b85e5214b0d6a7.npy +02958343-15fcfe91d44c0e15e5c9256f048d92d2.npy +02808440-71753adcff89e231b362845c6edb57fc.npy +02691156-8da50272a54dee98d972c9dd75ed77d4.npy +02880940-c399bfee7f25f0ff95aab58c1db71c10.npy +04379243-7f23cb04feb40ced8161eca940958ba.npy +02933112-273bd29d931bd255343edb005e0de5c.npy +02691156-b54d9c1ccb737eb6d972c9dd75ed77d4.npy +04256520-341ef2d97f0f9091183903d8843a24ef.npy +03211117-ccd03d11c95554bae4aef3a037da6f67.npy +03001627-6050ef2e6ac4ffae490ad276cd2af3a4.npy +04401088-2eae0713342e1103397d790c3d0a8fb5.npy +04401088-b4795b53530c26c58b13932a0c28e98b.npy +04401088-c7ec332bd52f939f04143dfe595ba79.npy +03325088-4be2cb4c94a4ae9f3321831d2245cf06.npy +04530566-92d7254e73fdab7289c6f1079da7a8d4.npy +04379243-1a417e4090ced738855931d119219022.npy +03642806-f496fa98fb41f6b1ea5768960d4a805c.npy +04090263-5d40add22ff7d14c77b7d0d4764c121d.npy +04401088-2682cb34e7db8735bdc7fd7cf135ade2.npy +04401088-98f0a229291ea982d670fbfea4c122db.npy +04379243-8f1934c5ca7772837d44dc16af152638.npy +03001627-4913388a4c94547a81806e3880250dff.npy +04379243-6a754d9c379ff246fbb20af1c3b4b0e9.npy +04379243-81c8ec54ab47bb86b04cb542e2c50eb4.npy +03691459-26363bb293e6c9e499db62650613bd48.npy +02691156-647a8f5c79b54910f6c0d5cf01fdaf45.npy +02828884-5c76331c2d99f3e2fc9d3ea96a9a9d1.npy +03636649-94f4c42b6db62c9688e7662971dc736f.npy +03001627-ebaf425ea2c92f73a3bafec3b56382db.npy +04379243-d1b34fc25b5ed4e42fa77440dcb93214.npy +03938244-f83e0334efbe5ac33c702793a783cff1.npy +02958343-b55112c3c09949846a0cf750aa55c4f3.npy +03636649-e4201614cb3590e41735ea0e092a805a.npy +03001627-12d7ca3c06faaadf17b431cae0dd70ed.npy +03001627-6b9c3d42724275cf7a5c8cd74a7bc29a.npy +03636649-aecfc0a531b67a478b424343280aeccb.npy +04530566-f193688fa17197f7798832e32e32aae6.npy +03001627-dd27edca07570d277ad11050da24bb12.npy +02876657-bcbc2c637bed89e4d1b69ad96276e132.npy +03636649-8566e44b5f1a818ff44a1c032c5fcdb7.npy +04401088-6475d2eb77c7ed5a59812638b595a4ce.npy +04530566-92e3343250e181e1428cf87eb5ebe5e6.npy +02876657-56c23ba1699f6294435b5a0263ddd2e2.npy +03948459-2091ab9f69c77273de2426af5ed9b6a.npy +04256520-679010d35da8193219fb4103277a6b93.npy +03991062-8d87b950d8e192f5f51f77a6d7299806.npy +03001627-fd2c754ca43457107d910d51d878f708.npy +02924116-50fd00d8c6c216ab52470de2774d6099.npy +03691459-27046cee7ae745e6d207241113bee327.npy +04379243-58b499ba308f9e82b4c161851ed2b4e4.npy +03325088-6b23fe58eecdc1946048f75ed36a5ac0.npy +03642806-3088048452f40a8965932bedd33dbd98.npy +04379243-8d44182e9916d617938da3ea2c9e0e4f.npy +02691156-5558a2511bd43caf2fc668af6d3ad0ad.npy +03207941-8bc3e5012c3cb5837f7408e5e4714afa.npy +02933112-1ee58b9b772b8807f51f77a6d7299806.npy +03691459-2c8cb15e2d973bc847cf5450436b1047.npy +04379243-7bbb0921945cb5fb45e2a4e5729b970d.npy +02958343-e866dd4d4bf1f1f5bbadf8db57668863.npy +04379243-8d05d40b15f933edc22013ebab50762.npy +04379243-7dea0c96340d5b9455f46d55537192b6.npy +03261776-98eb96633935d994c38ed9bce4ed5d0f.npy +04530566-1d5ff455b6ebd04e413559acd5524c40.npy +02924116-46858dcb18c2630478c6ad1c898f52db.npy +03325088-d7cf55161ac23e2b76c18e71fd49c4dc.npy +04379243-3929a118c5252a768cbb8bac2032149c.npy +02992529-ae0b011684a6c46c10bc2436075f6a52.npy +04090263-e9fdc6039ab91746580389adc8c1bb70.npy +03001627-63f6ff0ad9cf9d17adb532bf77da46c2.npy +02992529-caf0f73f4a609b7a2c4e8a2f66e4b8a3.npy +03001627-cc2639f8c584001a922dfe32810651d0.npy +04379243-c2369a8875367b56fab6e40cce6926d7.npy +03636649-ab53b6e7b2f87cb5c1935c9110af1bff.npy +04256520-8f971956f31d9faecb3a30f2c37c38a6.npy +04401088-693fba444859fb7d54c65e829609f393.npy +03211117-30b5026e1c3f8c8a93e4d36e0c61da87.npy +03001627-79030f846b4dee0f9d709998b2d6e774.npy +03001627-ea04a5915e3982aad7f7a4c4609b0913.npy +04379243-1a6d43aa7b5c4e1d1c6a34a68ab9e1d4.npy +02876657-72a9f3c57e40416f8884a069d9619eaf.npy +03636649-6770adca6c298f68fc3f90c1b551a0f7.npy +02958343-5ff285283e8ec610434fdb742d7e0cea.npy +04379243-1834fac2f46a26f91933ffef19678834.npy +03991062-facae3f0d92553bfbc5c4c571faa8806.npy +03001627-3cff2db42b3ba901e83221ad0d21775.npy +03325088-bdbe36608edfcb23b362845c6edb57fc.npy +03636649-857122dd5f5cb1b0a34f84d89d87830.npy +04379243-1d4e22bc8ed400fc368162d385acdaa9.npy +04379243-105f53a6471f3ceb4a420e3c1b966720.npy +02992529-4116965029bd24393423610e52061098.npy +02691156-e3d197bfb47ec943c9d7d324d11034c9.npy +02933112-a247a4978888e6403fe047712e43e185.npy +03593526-d1f9e06eeb9e5fe237af722b64576c2.npy +03046257-626c1a3c6fac65a924a6b810f75dc774.npy +03046257-35e5685d7c25ed8564c33a5741e8e076.npy +04379243-db302d0ac596b4e059db00799f9936b2.npy +02691156-b273c9007d1e364fca8607f540cc62ba.npy +04379243-fdd8dae63e8781414a803c33df86f3bd.npy +02933112-cdc2c14b62e110fbf8bf793ac0a3a901.npy +03001627-6d199c744b17d85953735b417976bbf5.npy +03001627-bf179410ad7f9f37af6595f7d3f20cf6.npy +03636649-d0650b751034f567457ba044c28858b1.npy +02828884-91a39f76430e6cca19420b7669e7265.npy +03001627-1e678fabd0622a1119fb4103277a6b93.npy +04256520-41c9fcaf5c6b83a61660e46cb2e4cc15.npy +02958343-5bb83a60fb8d5f45a1089359fc10d7fb.npy +04090263-9ce27cd793dd3da29ac0a7e766b7c815.npy +04460130-ce4acc0cd5f5a33cc4406905076c720.npy +02958343-3af1559045965b6f1f1bf16cb0b58c6d.npy +02871439-2f703181d8069cd0d42b9650f19dd425.npy +04379243-4e48be33083b8c70d810b14a81e12eca.npy +02801938-61ce681b67ceb94f4c2db8f2b94d9c39.npy +02747177-ffe5f0ef45769204cb2a965e75be701c.npy +04379243-3b0e4c443ff69840c3bd24f986301745.npy +02992529-a8bab81f66ac5d26acdce172dc618222.npy +04530566-11d9bfb57990eed6d674557449cdc5a4.npy +04090263-16308b7668753c078080f52bfb02d6bf.npy +03691459-76566bf65b49e49c864d68471e7fba29.npy +02958343-d1f100f660eae4548acb0ff76f4aec7d.npy +02958343-1e2f9cb6b33c92ea82381b04bbe0ce6d.npy +04379243-e41e3b1d11fdf7cef9c9f9697d1ec60.npy +04379243-46e1e82d296cceb389a52d0b0203298.npy +03691459-afe96f3cf256cbac81a6b6721af23c58.npy +03001627-e936176764be83d029426a0f57e4d15e.npy +02924116-7d0d3c8f823b3debf03a6fe18d6a133c.npy +04401088-9dc0c2ca8de18e28b4c18e3209e12990.npy +02992529-a19763322fe669cc7e51366b0cf7747.npy +04379243-8f05326e122a6b973eea2c65c18f73c.npy +02828884-41fe326e3decebd1b40f0ac0fb9a650d.npy +04379243-282d36d7ca9705f6ca421e9e01647b4a.npy +03636649-99ec967442fe35e46aea2f18ee404fd5.npy +02691156-cc68ac5b18674485475045ea78b20eb7.npy +03636649-872407329ce09557bced73c51e99f8b2.npy +03642806-e0cc767bf10134509fd6a63b3b6f6cd4.npy +02958343-9dd02330c7c4ec88ec455839e63f83dc.npy +03636649-3d26aa294ad1cabcfcb8d8c6d4df8143.npy +02876657-b00152d19e8f2b87b2d2b5b947dc0b8d.npy +02933112-906d1dc1a8e519868cb5d9909aeb1309.npy +02828884-444e7c5709eca2496f61afd58e50ae2.npy +03001627-662ecf4b0cd1f3d61f30b807ae39b61d.npy +03593526-3d7710926dc165d29d70a5dfc06759d.npy +02992529-bbd5005058f01a54909425bd531e6033.npy +02828884-826a100b907c3fc4edf84ea98391428.npy +02691156-a2de53a5de7ea01dd01b5600c06c528d.npy +03211117-a6985e8e32df69a7fe50497d5e2cdada.npy +03046257-6245999a79c5d853c31c0b92a775f88b.npy +03991062-88515725e87499c1e9dc847f63d339d5.npy +04379243-47e7fbbce59804cd30bbd4cddd04c77b.npy +03001627-56e51afd9d5c5fa38b7a92edf72424a7.npy +04090263-723162e8e15f4ac55d0dded52efeb4fd.npy +04256520-e80ade8966a54fe419fb4103277a6b93.npy +02818832-e1f93c13decef335e3c3d58aba901b14.npy +02828884-d34b04cb67bf2115c308e7dd57b5111a.npy +04530566-31ddf87b5ef64c9080c9c53be28cd7ba.npy +02958343-e92786612a9d60455dca6305fb9f97ca.npy +04379243-b12b2f12db92ed70c48d90eef8384210.npy +02992529-1847d3782970e60679510444cc61f839.npy +04379243-5d7f7ef4f2f2e99f1e923e5a90fc6bf2.npy +04379243-a7d1fb495c33316cfdbe2bf897d8a820.npy +03642806-8235de380bb100cadf5a805be6fefb86.npy +02691156-28402efe2e3435d124fbfb66ea1f14f7.npy +02691156-211cac5d62271583b85f0298cf43349d.npy +03624134-adf0a46e8a00693e131d8fbf069d5d12.npy +03211117-1412e61a9bc08ac4e6d9f3854f1baef8.npy +02958343-8237df29002d6cda20fc61a2a01df353.npy +03211117-a9432163d01a99f1d38b9064784c4b38.npy +04256520-12cae0fa5180fce64b7366b9d17acf07.npy +02992529-ecab7b7bfef8d7f423575ca8cfe7da9.npy +02691156-14d6bbabad3ad00dbbf3143b1cb6076a.npy +03046257-ce222cc498d073ec59fadefffed47ac7.npy +04401088-be7a560b2a6996558c646f076042ffd9.npy +02958343-296c92e4e7233de47d1dd50d46b1e3d1.npy +03001627-eba001ddae2ce5eed5d673747c0e3adb.npy +03211117-fc314f1e3325a47af287ec53a469521.npy +04379243-ea89750a67ae2335b9315f9098d51eae.npy +03636649-c60a072ba63c12cd8ae0d28389a2d006.npy +02828884-36583be1062e0f48c24b862f5ee36086.npy +02958343-746765dbc0106bfabda733a39f84326d.npy +02808440-fb39c85a8e31535b4c62bee40dcdc539.npy +04256520-d5424df6acaee9762d19175e7d19b7cb.npy +03211117-6bf634a79cadc9851b02cde7e81f0fc3.npy +04379243-f82e5554f1c877a1e074517a246f1e65.npy +04090263-9e3d8792aba09939855b2b6b2e96290b.npy +02691156-32d9fe9366da899b90b73cf2bf8fe3d1.npy +02691156-218caa58819e10d1fe40308d822f996c.npy +02958343-5f148a8b824ed7e72a9eb0f146e94477.npy +04256520-fe45a0e02430b195b6f5fb02f36f9480.npy +02958343-e7e94f8dbbe8c1e9784da3853aae78cd.npy +04090263-d8c06e41fedbf387e5a528a89590d5ea.npy +03001627-383ab6330284af461fc4ae93e00c18e5.npy +03001627-4e3047842ba1a384d2b12aa6a0f050b3.npy +02808440-cd55a6a2d57067df3e49f3a2a35ec8b6.npy +04379243-ae4367ce28f1e5d96917161dc6c05572.npy +04256520-d7af346415eebe008f36404f302c9440.npy +02933112-b31c1b94a2badecf43d2fa0a85ff9354.npy +03001627-533e0a52acd257bef27383fc5a5a711c.npy +02933112-b92e2c18c0eeb8cba80ff03f6dc10926.npy +02958343-eaf664eaf6b27cd1905f30c879d154be.npy +04379243-e7373d97df1216af869f35aa46529daf.npy +04379243-6d311facc6387a7fcd1233d74066ed8.npy +03691459-ca9ca5c5dbc82019e6bc953d57dcc636.npy +04090263-afc13a1565e027c5d735fa1ab17311ec.npy +03636649-3259e491870a8c49eef5d83b671bb264.npy +04379243-1686831b1e585dd9729c5ef452d153c3.npy +03691459-19ec27b0dc5e478e2a9eb0f146e94477.npy +04379243-2bb1bb0516d7cee747839bae1bc65257.npy +03001627-d2b9e98373e96afec8d65ca96e6b18ef.npy +04379243-54108a40e3e2f09b940268b86285118f.npy +04256520-3c61862eca2f0979febad4f49b26ec52.npy +03325088-426ae1a946daed5f76c18e71fd49c4dc.npy +02828884-8ad57afa55cebfe0dad433a29cb627ea.npy +03642806-9fa387d7f442b96e75e60c00fabe2744.npy +02958343-650238554cb16926bda733a39f84326d.npy +03001627-88ba4696c25632507b6a13c9370327f2.npy +03636649-9f0e6bc1fb0a97a6db493a050f0c45fc.npy +02691156-46d2373fa05a4876bc913a3935f0ae10.npy +04530566-1abf3b20f05ed8ea902d6f4ac8edb5f4.npy +03636649-a72410196463086561fc247a18f47792.npy +02691156-eee96e21bf51ee6ce719b5362fe06bbb.npy +02691156-db02eb57817e4b4d22362be7f5226e91.npy +03325088-653ac1e615b18b19b362845c6edb57fc.npy +04379243-64a7fae36a56705e3ae0df12be078c7c.npy +03691459-2cf41211ffafa4ea1f9f3ce366e030fb.npy +04379243-6373c7a17a41666219fb4103277a6b93.npy +02992529-da1fcb7a374f9c43397c13131c65cbca.npy +04090263-f82762004d55da3d265b6d46c677f2ac.npy +02691156-895e49f92ff5003032611f2edb791b8c.npy +04379243-14b250fe1e9d53beb97452240e92ab9f.npy +04379243-ebd353db403531b4257d13bddbc14c41.npy +02933112-da5d7b5dfa92abdace5d6e9371bb5c33.npy +02871439-7087c34ea40273ea734a703453e2dabe.npy +03691459-ecfb9655edf2b5297160646d65ba4383.npy +02747177-49bff2b8bcdc50dfba6cf6cbb9f4c2bb.npy +04554684-5947c6f05f5f74437b3ec0bc4f26f615.npy +02808440-9a2356d30def73186b448b8aaebb705c.npy +02924116-5ec24e802eb61e624d429997b4e3b64d.npy +02933112-595a8444c362be66b8803f6649e6cb9b.npy +03001627-6d54d175396e3a99b1aef914f6383f94.npy +02691156-8b0d9118e9e7dc3f95c9af648ce95367.npy +04090263-aa03af3233ff0be207c113ba65e29ca.npy +04379243-f9597fd50738ba45ba5342d638d0c267.npy +04256520-7606f7f0a8d6434f4b3c42e318f3affc.npy +03691459-4bf9f2ae5f3b32e5d74f2f4a7f5598c2.npy +04256520-f2458aaf4ab3e0585d7543afa4b9b4e8.npy +02958343-543a6562ae746ed45daf03c341f7f599.npy +02880940-68582543c4c6d0bccfdfe3f21f42a111.npy +04401088-e9ef88d72ead910b8b431083b6191e2.npy +03046257-a8cc05a9ec2e678d5eb2784f19b3d21.npy +04379243-899f815eaad62b56d8cad143689f8b51.npy +04379243-a41b3ec61751fdce6c28547eeaf2a8c9.npy +03593526-365d864e8c58391e62a510b8f97c658e.npy +04379243-581d698b6364116e83e95e8523a2fbf3.npy +04256520-ba6c0baa0a122f8ce2aa36c9e5ae7ae.npy +04004475-23fcaafbeabc092f921e793cb951210d.npy +03691459-19a8736130ef822b93dcf5e22ecc3f5e.npy +03938244-20655268b1709c8cc75ea4b124a227b.npy +04379243-59ee80e3af7a4e3df4b6538438a0b930.npy +02691156-46829981c5c25285bfc0a2c490b4c222.npy +04530566-194ea4b2297cc2ce90c91984b829ab51.npy +02691156-3b31e28ac1eb36fe1eb4be4ad34a6dbd.npy +03642806-bd879abd9b5c15d75d66db82418edc83.npy +02933112-23e3c2a2f61ddb2986d53ab0fe94e911.npy +03691459-5501c4caf22a5c974533f2e74542acda.npy +02958343-c24892528799ccf486b4d991d5310067.npy +02691156-72e68e04a203c96d873ec74c119307b9.npy +04379243-abef0c609ad3e9c2edea4b985280bcc1.npy +02876657-688eacb56a16702f9a6e43b878d5b335.npy +04379243-de2f120b21e228c2e6c5cd45aa112726.npy +03211117-1e9d554d26d4195f37ec10b15648a127.npy +02880940-188281000adddc9977981b941eb4f5d1.npy +03001627-3526528270d5f3f766268502c798b9af.npy +03636649-561853e6377361196afaa22adc38077c.npy +03001627-374e76e8b8357e5f796d422781cbc933.npy +04090263-6169b7bdb2a76d471ee416ae4351c7b.npy +02958343-d373922da2a6c73b616f13ee256019e3.npy +03593526-2886e2026ed9da084b3c42e318f3affc.npy +02691156-51f24c13e4af3e06b6e5b4d7b00c5b3.npy +03001627-3f7417590f1bcfded5c89ecb06d1099b.npy +04090263-12df496292b5c016f9489a342636086b.npy +03691459-4ba818da340a4e5d60647a90a03914e1.npy +03001627-13bc03eca6aad4b2d7bf6fb68df7f786.npy +03928116-887687ab426ffdedf7406d785bf36110.npy +02958343-ea37a9b97e092552b927782fc69a1fbb.npy +04256520-a6e9d5735c36b80ef4a06efdbafdd7ea.npy +04401088-e97033321b1930ed4391592096b033ae.npy +02691156-cf17d0ce34f09f572722fc1bdd7e0e51.npy +02933112-2b80c8d68550986bc59350d819542ec7.npy +02954340-8b2951e32e0906bb5f6cb4951755315c.npy +03001627-8ac2d831ebeab4896b7c7aa09852a4e0.npy +03948459-68cf8f5e1bfb9ff8e71e857afa9df271.npy +02933112-23b8cec330bc7699c59350d819542ec7.npy +04379243-c2b9613e2898f3381c7afcd6c011dc9e.npy +04379243-943d786e2df9251ec76aead7da70af41.npy +03759954-514024b4a66a57d592ecd319dfd8c5d.npy +04379243-dd35a3f0ba7c5f2e73ea70c16ec9e2b7.npy +03001627-6730f663d0e012506f525e79a05bbcb3.npy +03691459-b24c25a01d69adbcfb14bc0c4e180ab9.npy +03001627-1c45b266d3c879dab36dcc661f3905d.npy +03325088-1f00e3c311882a8866279f6cdc4d0486.npy +02801938-2d8bb293b226dcb678c34bb504731cb9.npy +04379243-82271bc614a76c28890992ddacc04113.npy +03691459-85eb14c504232ad1bb36a678453013a7.npy +02933112-39b51f3a6e8447c3c8a1a154de62786.npy +02933112-7e2e24fed142bb20310af74324aae27f.npy +02691156-94b0675bb9f2a7fdf8a8bda5d07839b5.npy +03001627-8577be35989634fb925bf1713cfe05c.npy +04379243-8cd6a33e6ba794419cd431573238602d.npy +04379243-53f6531e2fc2d31ab2c2cd006d206129.npy +04090263-249e0936ae06383ab056c98b2e5e5e4e.npy +03001627-4dbddd8f3f658821ad484915511ccff6.npy +04530566-df8fdfbda6e15f38fc740ecd0dc695a2.npy +03001627-c7bbb1dfcac15f43e33c1bced7bc2a7.npy +03046257-aac0d032dce735c7ded4c23d05709216.npy +04379243-ddc404bc12e45dbfb4e3935c6cee4b35.npy +04530566-dc0d90ae6a41e0acf68668364a569266.npy +02691156-e387c8d826cbbdd68a8dc9dc46f918a8.npy +02933112-8e42a0d11784c74fc6a5c971c030877d.npy +03001627-58f44c0057ae64b525633180ba767a60.npy +04379243-2ad85522947a9cf5f4ab13f4b49ac318.npy +02691156-a4462b31326da9493ea703383c665f30.npy +02992529-692e46bc27bcdcebbdc2330c91f5a859.npy +04379243-22c4449df36e20a025ca952293bf3fda.npy +04379243-cdbe8e456a3e3202c55161a63fbd109a.npy +02871439-e88b3fd502ab3316d42b9650f19dd425.npy +02958343-2f503625718536ad5d9d397842621b7.npy +03001627-c24ac9257d6392bcf284804023c6c8a.npy +04256520-41b02faaceadb39560fcec8f64d76ffb.npy +03513137-dc10f3b2b8cf3c8f3a0407ebaf7dd3a5.npy +03636649-46b8bc4b5b2a6094d46763ec4d902968.npy +04379243-c277ca4a9195df2ffebad4f49b26ec52.npy +02818832-e68e91ef2652cd1c36e3b2fa8d1eb4eb.npy +04530566-6dd448ee6a2288ff5a680bf43a0499b7.npy +02691156-7f4a0b23f1256c879a6e43b878d5b335.npy +02691156-28da27a6bebc81df62b600da24e0965.npy +02691156-1d269dbde96f067966cf1b4a8fc3914e.npy +04379243-4d45859eaf2627f5ba350d190cd1c00.npy +03691459-44ec5df88564c859e180a1a604561d3b.npy +02933112-878383dee814d727fd2b139960f72a73.npy +03636649-bb3c2fba4e1b712357ddce8e42aa6e90.npy +04379243-8c4d7014c59f619c2b1c5715bfc0f094.npy +03593526-c5351c4aa1011866cef8c6985387af2a.npy +04530566-ad251b2cd68290a41c9545c3c7193d55.npy +04530566-5d301491ba435b71257fc1c453f165b6.npy +04379243-ee00ed62953f4bd280afdc8bd41edec3.npy +03001627-d708c7ed9201ec45d29e20ec5f479208.npy +02958343-1151e7cd24f5bd21ccbd9e5bb82dd04.npy +04379243-c733e81695923586754784b56fb4c23b.npy +02691156-5c8b6d47313dae4fca1f1143bb6bc17.npy +03001627-8efb37e93b208234671d97b0fd17f51.npy +02924116-290387f7da9b702941567ce9c420c236.npy +04468005-35abd22f4961926f196c433756c6bebf.npy +02828884-e4f68fb5bdfb68e936a9515582552983.npy +02876657-ca2341f33cd4995dae7fdc0845a47bf5.npy +04530566-d19c003cf7dbf111543941eaaf04581f.npy +03761084-146d5859bbd8d629bbf88898fc491e0c.npy +02958343-61f70557b8bda7422ee0f9a97b71d505.npy +03691459-b0feef9f599d41cbb3d8c1107f6ae528.npy +02691156-bb244dba6323f80a126bd036879e7101.npy +04256520-aeb5447d59fbe49add7f28fcffe810f9.npy +04379243-1fd1d459e79ad6c1c3bd24f986301745.npy +02958343-97b9c8ae37e6480e1912cbd26ffcad1c.npy +02808440-eb7eae7aebd087323321831d2245cf06.npy +04379243-a48942e0190d14a5a8930422448288ea.npy +02958343-ff3c8e21a48ed17cc1bcae9def1986da.npy +04468005-3bc4944779090cd3ff790997f2048517.npy +04379243-6e96a8c237b549b6e3f7a74e12a274ef.npy +04256520-45aaa81cb6b7f1585e7dcc6fa9b3c324.npy +04379243-4d54165ac08d47dc30bbd4cddd04c77b.npy +04090263-177d48f6f156193bdcdf952acdf10f.npy +02808440-2b655690268f451a11fa1d2a0b030f17.npy +04256520-8169b36ef1ae45ec19fb4103277a6b93.npy +04090263-8128e1bfcc18d4769a3e2fa8a8e389f2.npy +02871439-dd1d4a486f7cdd8a2381fb852817e4e7.npy +04379243-9004a7d87a62e40111310cfb881ab9a6.npy +03001627-a06c4c2f4634ccb1ee928ba0d9f88258.npy +02958343-9c4a3879c71df693af0f25977186b501.npy +02871439-959b3402f426223bcc88311b3d194337.npy +04530566-b3aa94c4aac0534ec34b1b7198ff8321.npy +04090263-b84fadbc6f41cd0375e4eff9f26b7ac8.npy +03046257-4833383d30f7526fe30738a8d635be29.npy +04554684-52c23e4a42c5f058ffc6e457221b9271.npy +02691156-821309c2037b49135fab3f99161dc2c2.npy +02691156-c1aa42594ad2d80e4c3a35cee92bb95b.npy +03636649-b479c49366c4d5def2cdf09737c19aad.npy +04256520-b79a15077c4a662719fb4103277a6b93.npy +03928116-512b54ef050a7b4a11cc56dc4129a22d.npy +04379243-1b2dc847e12c32d4a430f20b4b0a337c.npy +03991062-ee0e42b157a8d8554d226702c1bfe9e2.npy +04530566-212a323fdfc0d8e59399f7cdb64577ad.npy +02958343-fbe6ff98196a8ddf1992fbc3c9e8b937.npy +04379243-795baddfac35711a30e44a4c4faa2773.npy +03001627-ed53217c9a4443b8a4ad5308cbfec5eb.npy +03001627-54237961055ef73782db9fca4b68095.npy +04256520-64702fcd98b04ad21206ff076758ec85.npy +03001627-1190af00b6c86c99c3bd24f986301745.npy +04379243-1b7cabb894adef68939793f922933b6b.npy +03636649-e0a99ab7c7a0d2d4e59f529cd1b6faa8.npy +04379243-4bbf789edb243cafc955e5ed03ef3a2f.npy +04256520-d31fb17a6a6515d5febad4f49b26ec52.npy +03001627-4e15234057b863dc659dda512294c744.npy +03001627-9897713e0efb2942f51f77a6d7299806.npy +03001627-b16dceadabff3976dec8d69f9356ec51.npy +04530566-e93d2ab44861bbd32a4947824596dce3.npy +02808440-8a7a7e70aa8961f4edd7686549ee4484.npy +03467517-57286d92604c9ebea3d3eb77b119df6d.npy +02954340-ed352b53b17b6119e762cf5917cef4ef.npy +03001627-7b01e2a03e614eba4710269d4bc18736.npy +03467517-1157ee852f69a82376d05024fabfa1e5.npy +03001627-bf8e44b58d2d95f45c6cb69e0968783.npy +03928116-ef752c493b9a41b21fd394f1bc0bd850.npy +04530566-85dbbed13875a3a2b90142192ec795d.npy +04379243-9b923ffa07f51fab2032a1fc189d2617.npy +03001627-2d1ebd7356968c0919fb4103277a6b93.npy +03325088-4c3fe77fab3730caec944ac16e6ab528.npy +02808440-c11ac2c84d7e8566b04f97563601480e.npy +02933112-7d9b7a4412d9f373c59350d819542ec7.npy +03046257-38c78a9f3f676878dda58cf2744aced9.npy +04530566-6067d0e8dda0b78c4628573ed5739806.npy +04379243-853c3913ba95570ba2651abaf391628e.npy +03001627-6b719f78721d1eb742559566b871c978.npy +02924116-992e27c87064000a163e670ececef2b5.npy +03001627-7885f87669b8fbc73f7e27638e63d848.npy +03001627-bd504539074e453721a08935eb37d792.npy +02691156-c69c73793f459a2c3d4b1f38e3dfce4b.npy +02958343-b812523dddd4a34a473f10e6caaeca56.npy +03325088-334025201d6536fcb362845c6edb57fc.npy +04530566-a5fa8ae8f743d5498052128bafa4f7d8.npy +04379243-785a68eefd1035f468661782af60b711.npy +04530566-887be2603a56d8acc13b4b8de5611825.npy +02691156-bbb8ec10b86465356630654359fc97d0.npy +03593526-d2f113f579d2c4c9b7e6746928016c6b.npy +03691459-82f1e500df50302e26870852082c4c6d.npy +04379243-63d1427d86f62c45ecc46197d5349c6e.npy +04379243-93bb999fd7e586199fd83fd2ba5fe30c.npy +02691156-c14cb2e75415dba59a6e43b878d5b335.npy +02924116-dc0601024a535f5c51894d116f1c652.npy +03001627-308b76aac4b518a43eb67d9fb75cc878.npy +02828884-89cb6473e1b3882af7436fe692c24f3e.npy +03624134-35233c0d786b5956d25d105fdf500c48.npy +02992529-f75e6866c8965374f1c81a6df84170c9.npy +02818832-50b21efadb3692347b0284d1ea60f713.npy +02958343-25d92177ec6bd745deadc9ca0263db5a.npy +03928116-c625f1771e40e374e1c27dfba919adc5.npy +02933112-a477a301e1e1a67fc2185cc0ca1b306b.npy +03001627-3eb9c5fb2a7ab54d490ad276cd2af3a4.npy +04090263-170574550b1b5c12fd0c2683cfdf8b6b.npy +04090263-4b5668e651a6a9664a4f87aa9a31cd70.npy +04256520-683fbc39025b9b75e71d6290824c2748.npy +04379243-7356817f2b175b80f7088fd42bf47c7a.npy +02828884-50db85e4889831dff155d75bbf62b80.npy +02747177-bf4e08fe5e07373ade5ce145a809def2.npy +04379243-80d80b73981eb265b30ae4347e74f709.npy +03001627-95d6aae8728a0aed70e95b2fd46626d.npy +03636649-6e3da73f16586dc56bd3645c59279a16.npy +02958343-d47353fc60390df85d918097f81825e3.npy +04379243-2eecafccfce0a14546407779dbd69b2d.npy +03593526-64a0985a86bbead9fe9d8ee1a924ac2e.npy +03642806-92702a4de72aac3e20685b5a7e34b501.npy +04379243-35803ad1072c4221e8b2b8dc0c816caf.npy +04530566-810cdbec3687a16e122e1a230357df67.npy +02876657-9a777a5f3701fb6b940806ade53ef2f.npy +03325088-ee2f338a166b799ebca5df27f3ec6373.npy +04379243-5a2c14bbfcd9ca4d68f8796d69d0c486.npy +03001627-88376e3d3a23d263de29d28278a34a18.npy +02747177-9b5eeb473448827ff155d75bbf62b80.npy +03636649-caf410661e9311299dd0351f01396cda.npy +03001627-be373cf14b9f9b77bb01e8d0bddd5702.npy +03001627-384861155b7786fcb21bc3cf138f79e.npy +02773838-cbc2328cadf8dc573394926146371698.npy +04379243-dfa86ce9f892793cf51f77a6d7299806.npy +02958343-42d960259838027461c806d3425b088d.npy +04530566-501154d9504b62b9da27170f98feb295.npy +03991062-f8b3230c97fdaa97beedb4c8fd29e2d1.npy +03636649-d08164b754c2f139b93e96f21cf0da86.npy +02958343-4c2412cf0f720bb9618e9d35559b7aa.npy +03211117-fa7324388797a2b41143ab0877fec7c3.npy +04090263-85cd554c3681ba40a24fe41bd648bb1b.npy +03513137-1d1cc96025786db595f577622f465c85.npy +02924116-8b7d52fc3a771047d0ecfe587dafa03.npy +02808440-215352e586ec6aa0b362845c6edb57fc.npy +04379243-7eeceefed2b3aa2794f3bda96cf548cc.npy +02933112-b29f2d0d278e938914038d588fd1342f.npy +04379243-1bc212abfc3ba87ae5c3f1a4056686f7.npy +04379243-8eba29bc85c8c830b4c161851ed2b4e4.npy +02933112-4cee2825142a64acde650492e45fb14f.npy +04379243-a1419b0cf5fd0c2c47fe5b27e60471f.npy +03001627-ea389bc8d94f87ad95db811b45a94857.npy +03001627-2c795b27253f9ada336961c9971d866b.npy +04099429-93d96c35e4a343d1f7e86418b9396c76.npy +04401088-719a564d600f1ab38162d5a2262f4a8.npy +02747177-330cdd681a0890b190fdbeabcd02777c.npy +04379243-96dc43fe4cfe5668cdb6b5e54fc64b6a.npy +03001627-736ef1325209503533d93f57729688db.npy +04530566-d8a72e6a9f34ee36b571511eb0f92ed9.npy +04256520-34bbfab80042b25bc1bc03f4ef8a4411.npy +04379243-62f75f68a559cd9c5edbe4a62f5ee3a4.npy +02958343-bebfba98a5e97c6180360680c1602c7d.npy +04379243-684ccc0f629ee45cab610b0c94236463.npy +02691156-bd6966d7d0beae75f5c7319b71bdce6e.npy +03691459-4ef6b09f9a8e1fb233ed13d3bda59480.npy +02876657-1ffd7113492d375593202bf99dddc268.npy +04379243-3a1a6dcf1900fe42bdeec9c43546255e.npy +02828884-b6de66042941f5691301e24e9e27a9c3.npy +04256520-9a24fd0d36ff856662e682c9809bff14.npy +03991062-5b5fc2f78d935628479e6e44e41a0562.npy +03001627-c10b1973a0d692ef910979f825490a99.npy +03001627-3b25f03d2f7be870fff16555386d173d.npy +02818832-f2c35e05e0759d2d946f8fe474296fc.npy +04530566-8fdc3288bd73ef58a127697b1776e4b1.npy +04379243-c49e9c8c1306d3a4f09a2b323d5dc94c.npy +02876657-e5a5dac174982cea2dcdfc29ed7a2492.npy +02958343-c54586fc90acb4d0a46498323e7a9af5.npy +02691156-42d9f626ba4bc61516c4bdb2c8eca27b.npy +03948459-43b1fefe6b13b3e849b3383f0d8ed83a.npy +03691459-fa09acded526a0105b1433436fd82800.npy +04256520-8c9cb8a85aa36620a5f9d52c12457194.npy +04225987-1ad8d7573dc57ebc247a956ed3779e34.npy +03211117-1d628bde22788cb74161e123a102b12b.npy +04379243-a04a7efb21f799f4c8bec3671aea0fa5.npy +03636649-dbe83cbb4cd5113c14038d588fd1342f.npy +02933112-4d36c59bd32fd885aadbf8208284c675.npy +03691459-b3f76f7361b123f5b3878cedd8c8fe6c.npy +04379243-4d873bf1a658dcd523eb3ad3d378722a.npy +04256520-1d4d7533d453ace4dae12f3947d07dec.npy +02992529-a9d358ce2d54d95e54c7ab6aa5674ccc.npy +02992529-55698d990b8147e33c7b6ed91d531bc.npy +02933112-233612a657bbda534da5feafe6f1c8fc.npy +03593526-e390d119024d6de9aca4186c3b7dd23d.npy +03001627-317a2cc9f3b54a48283b00891f680579.npy +03337140-9404bf7671ce9cc52871cc0b3cc1a485.npy +02808440-d7bfb73072d8a3fb54d7082b34825ef0.npy +02691156-72e1cdcb882b6993c1006ed55bc1a3fc.npy +02933112-836fc8edc0414fdd9925b11f2b3f86ba.npy +03337140-4ecbfec208b1aac12f84cb7932f866fd.npy +02958343-6e1d942233917ae996c458818630d123.npy +03636649-fa9a37d95fa8c6542beec56b24479ed1.npy +04330267-3586a28ad9ad3aa8230584014222e685.npy +04256520-27f8e4a89307406614038d588fd1342f.npy +04379243-5eba36c416524db2f42a90fe4baf4591.npy +03691459-529f3a898bd030f558b060a361031075.npy +03636649-13a20b16bb59fdc712e1ea5343ce0273.npy +02958343-22654a0cc1ba382c4eace6243432632.npy +04379243-fb2191ec35ad66da30bbd4cddd04c77b.npy +04090263-c2acfd34d7c030f5dce23741b366d6b.npy +04379243-6feac0a35c8f8626e73947fdf756a329.npy +04379243-506a09d327936cf8e2e6aa5366c8ffc3.npy +02691156-6ba642ca477a73db4c3a35cee92bb95b.npy +02946921-5bd768cde93ec1acabe235874aea9b9b.npy +03261776-a9661a8bb610d902957b6a4f3924d982.npy +04530566-577acbe57ebdcbbdeeb8eb76c515e836.npy +02691156-a4ca564574e55f1a66cf1b4a8fc3914e.npy +03001627-57cc406d478167a6a6c03a53cf0a14c9.npy +04379243-f41e9600bd8bcb92716a0dc6cbf69f91.npy +03001627-uca24feec-f0c0-454c-baaf-561530686f40.npy +03790512-7d75e8200565ffa7b37378f3c85478b4.npy +04379243-5b54a7ca6d758fa1e12186cc8c5022c7.npy +04256520-def69858279a9b23f841858369432cc.npy +02958343-d28ad2ed7b1ba665b1bb46d2556ba67d.npy +03001627-58ad41e336942bf3c5243a0ab191990d.npy +04401088-a801c5a24131f1842ed91d160fd4ae97.npy +04090263-da7f89368a80ce9e1f2a1daf140ac9f.npy +02691156-ccd448614257253cbc0909d98a1ff2b4.npy +03790512-ccefa6fea8b7a57281eb6e0cf97c3b0b.npy +02958343-2cbcc226b4f952f29e1c4d21c8ecae7d.npy +02808440-99b04530c2640e38571be7eae57ba8b5.npy +03001627-f9d050a51da1f3ed30bbd4cddd04c77b.npy +04090263-f1f0a765def9499c6a2345809e2bb169.npy +04401088-bf11938460e160c78190e4bafebe046b.npy +02691156-ed1a5c9fac829d17a6766282ea8c438f.npy +04090263-b85aa72e2d253f34e38850a3ae501b7a.npy +04379243-eb379b2b95e76502e258d1c3e7302e7b.npy +03211117-b6bb7bb5927798724161e123a102b12b.npy +02958343-ef966d85be54c98ab002e5b0265e7e9d.npy +03636649-9d66a6faebd46b1d68661782af60b711.npy +03211117-815060a9c109ff4659de6f0155fa4014.npy +04379243-dc291fbd5838138a833924252d812d1e.npy +03046257-780ce22d20547cc0f028fb77e2bdb0c0.npy +02691156-4eced94670d10b35e856faf938562bd0.npy +02828884-a7366461245f831ea764a25163affad1.npy +03797390-b88bcf33f25c6cb15b4f129f868dedb.npy +04256520-6580148c3214df2395ca4adb70946a21.npy +04460130-75ffcdedd253c62aa86cbf46be15aeca.npy +03046257-612f3199c6212e55a5aad165050e534c.npy +03691459-8d437b97fc1cc7bae9bba7108b76f097.npy +04090263-9445546f0d348b2ddd0a2071dde26395.npy +04379243-1799a85dc6eaaf48d25222e04574632c.npy +02808440-d8d89fb14672b3893321831d2245cf06.npy +02992529-283e3f79ecc4b74d1e4e60ebd003a0c9.npy +03001627-b9e9eb2d09981218d3c5964623f1547a.npy +04379243-9d5ffd7cc6f9084abd790f9b668aa24f.npy +02958343-7bf6249a031b5095ddd41159baaa3ad5.npy +03001627-6584413da69096db65ba78ad9601cf1b.npy +03001627-4707a1494196ef829917ad57402f53f1.npy +02828884-170b01ba7fc575aaad5067eac75a07f7.npy +02691156-112ca5420188df4bd90bfc986bc4c94d.npy +03001627-5e6d8f9275fc311fb7c42e403b7689ad.npy +04379243-22e3a5a8d22b268593ac14f56e1bb33b.npy +04090263-67f67bc8e340fb23cdbadd1af48b5cd6.npy +03991062-c78c54d03c727cbfdb497067d6c15d08.npy +04530566-4f16bb70a2c3ca48104d2711f226a055.npy +03001627-d7f35cad0f4ab17788dcbe86402c7c15.npy +04004475-12f86fe69336131b71df0fdd633b5540.npy +03636649-e35c7cd183a6de4a8bd5065c89cb7063.npy +02924116-1ccd676efa14203e4b08e5e8ba35fb4.npy +02933112-d0aee9e36e73a88a11fc2b865c2a185b.npy +03790512-818a641ccb945f6ecd03ad51b6badc3d.npy +03636649-f77e6d8f251887e9fcb8d8c6d4df8143.npy +03636649-6e5a9f4f1f0ba4a7beb83c64f2162734.npy +03636649-230c9e3d0e423ade7b7adc4c6de912f0.npy +04379243-5e5f15626f1f230bff7e95552a1d6a0e.npy +04256520-6ebad671c5ccfee94c02d21d2fa4d397.npy +04379243-98f00281db9a43aa6430c2c15987e4cd.npy +02691156-da26509e7d1864a162b600da24e0965.npy +04530566-724b7c80ebd318cd5a7da3f7c33cd566.npy +02958343-bf52cda8de7e5eff36dfef0450f0ee37.npy +02992529-f63a0d0c33f7a0c69a83e6b4ae8b154f.npy +04256520-3af6ec685a6aa14e2f99eeb199d54554.npy +03001627-c48bc68a100e8c24696b74614952b2d0.npy +03001627-bb04dc0b336abf4b263915c09bc4854f.npy +02958343-892266d574578810afe717997470b28d.npy +04090263-94bc0758fb14e8de104a9760d2a92bd3.npy +03636649-c78f6882973e616d2102429c788ba90.npy +03948459-4acb6494e3aaeb39998978df244b5bd.npy +03001627-522960d8c4a7b7f2e8f8c11a24c52ebb.npy +03001627-75135e879341721c1cf9f632ab9ad62b.npy +04468005-578ba0e5871fd931b8e562d273208aea.npy +02924116-259d331ad47b2fa7e96a4e289c6e6e0d.npy +04530566-553a28a8cadedc9344046d4d2ed11860.npy +04379243-b1cad66b13e1a1e7714531f0291497fd.npy +04379243-b17bfa9db55c2d2e4702663c3b3faf8f.npy +03636649-76da74f3a8f15fe8bed8734977b26c06.npy +04379243-11b110b37b1cbfd6bdfce662c3df88af.npy +02747177-269b2573816e52dad2b12aa6a0f050b3.npy +04379243-a18aa2d20d516333daf1f22b6daf05ed.npy +02828884-d46ca28fe271ef7bc5a208307819a3a1.npy +02818832-4a63f649cfb18cae67d352f95551668e.npy +03636649-28186fa2690df5daefe905a3f9856df5.npy +03001627-a0654bdfc12e9e1ac64aef1ba2bec54e.npy +02933112-28195efc838cbb6a4da5feafe6f1c8fc.npy +03636649-4b031808cc2b126243dbb6421d614c0d.npy +04379243-676d05aaaeecb8a04b3c42e318f3affc.npy +02958343-ea0d722f312d1262e0095a904eb93647.npy +03691459-2eb05cd394f94bf7944366528422e02.npy +03001627-be0c5a0e91c99e804e1a714ee619465a.npy +03046257-663e8f056e9ea81772e0da953d900dd.npy +02880940-89bde5319b8a7de044841730d607e227.npy +04379243-4b8c1a30a11197a831777a3afe490d7.npy +02876657-b95559b4f2146b6a823177feb9bf5114.npy +04530566-67adcb4dd6d1b51f3a2bf22c38d431a9.npy +04379243-7a2a0c5175ea17d88101accd22c701b9.npy +02958343-e8eb095ef1b65f96e26cab0dd65d60c6.npy +02691156-9f40666fcc14828abc2db24227b9dabf.npy +02876657-2618100a5821a4d847df6165146d5bbd.npy +03207941-e726e6409dc3921ff622709cb80f8ca1.npy +02924116-2359865685fad6ab1bc59ed4ab44a78f.npy +04379243-f2ac49e7de8898d6782db34fbe677487.npy +04379243-93cdfd14889492dd91a4fd87fee47737.npy +03624134-c19c47736309bed2ede07437dedab44.npy +04379243-c29137d144c96b17febad4f49b26ec52.npy +02808440-b23e03b24683b504cfc7935acf134396.npy +03337140-5e00f3509af8382c50cd753c91f38465.npy +04256520-d5a7ef075ff5e17a29f849a67b494905.npy +04530566-6db27ae2c9cf722d1743d8ffcf66c439.npy +04379243-9e84d2ed1fc4a0efc772d43f7a27a1e.npy +02933112-97b415cd78587de5fa29682ba98e856d.npy +03001627-59126ed88bf7735b1817f13b030c6f32.npy +04530566-2c68972ae4868355a6a720afea6887c.npy +02933112-225e398e99d98995b0c71e21a9386658.npy +04379243-273b600198cba2f840363d9858e1b6c4.npy +02876657-cf7a79435eb5b1bdb0be98650cd7fb6f.npy +03928116-c9fc3fc5c6cd686a5a2f45519a421de9.npy +02933112-2cf613433894022dc59350d819542ec7.npy +03325088-f0c7d88a8ee66e2ec36fb70296e45483.npy +02958343-a59c142ed6850a26ad4bd5fc1269475a.npy +04256520-b19003d682594a71d37a26a6fbb1c7f.npy +04090263-e21bcbde60deaab7716183d105fb8ab1.npy +04379243-23b43da125fa4dbd755c957ccb0117e2.npy +02691156-9cbbede82cf4f7e463a33dad5001f8d7.npy +04379243-5dff67091a2f7ef1ab988fe471b1bd06.npy +04379243-13b744116e4f23c340914702d8ab1d37.npy +03636649-a2fb35f872225ab2f6cbdab9ae1f93de.npy +02691156-b151573056013eaf71d03b466c72ce41.npy +03001627-96929d658ba1a01211ffd7c4e1c9d12b.npy +04460130-f3b26a49739b20a08b7e02a440eafc36.npy +02691156-d1a887a47991d1b3bc0909d98a1ff2b4.npy +02924116-9085eef376a744f5f88b61e9125676b2.npy +03761084-f8a7646ad61d3d24a44340bf227e40.npy +04468005-3b79d8815ec492076ef2f6739437286a.npy +02958343-b17d638e7def9adbc8a6c4a50ada6f9f.npy +04256520-6c74c7ab655d540dfebad4f49b26ec52.npy +04379243-41ffb4ec3d22e9dd9e7e7bd5f870f40d.npy +03636649-9113ec0bd742c5c5e86e8111763264e.npy +03001627-65e770a8307a9332e68b0e385524ba82.npy +03001627-37ea477f2b894c6ca72559fc4f86f700.npy +02808440-ee2b060177dcc12522f427296d72cac2.npy +02691156-47a40ce42bb9077579dc7d843e2be5ed.npy +02958343-554a04784b2f0eccbc513bbf92336c2a.npy +03948459-557f644e37dbbf8fd11c813bb72a58f6.npy +04379243-306cab12f4dc8a47f51f77a6d7299806.npy +02691156-9a878c5f0bfbd964d470a0056f762381.npy +03325088-832cd41e86b6820869a59c3b42f34f2.npy +04379243-c4621b03630247f816baadb9e8e34df7.npy +03001627-a14c7700cfc99b03ca6910e4922d61aa.npy +03337140-8f1fb3337da58dab91c352d02061b3f7.npy +03948459-44f2f626a4c73b216314c3b6a3a65519.npy +02871439-4a9731874f7472e2a3017456b64dcf36.npy +04401088-10a1aa2255ede06589b4abee87a908b9.npy +02880940-804092c488e7c8e420d3c05c08e26f.npy +03001627-79317a7ee8c26288ce265ed390193062.npy +04090263-a413fd3df8c6a915fb5c1b0f759e2bc1.npy +03948459-1f646ff59cabdddcd810dcd63f342aca.npy +04379243-a8840b65c6dacc627984fb9ec7e40829.npy +02992529-ae819b81ba34165dd6ec95d8e6b9f557.npy +04379243-16001e59100b03c5fca0560918d50ea1.npy +04379243-5b4a3107afc425be60ddc468fe733ed1.npy +03046257-95abdaa7c190243b75c7b38519066811.npy +04401088-6609f05bbe9c49172cf708d3028fb325.npy +02691156-ae857883c77d156b71d03b466c72ce41.npy +02933112-42689fe4a481168276e9713f57a5fcb6.npy +04379243-209e7d26bf9421cc9959d6de6fec7ffb.npy +02808440-b6ad2af249e6f779df87b9c01eb0d775.npy +03325088-24b8bfb0ce76421b362845c6edb57fc.npy +04256520-389751629226a005cbde89e0c48a01bf.npy +03593526-3e79d011230224283307b6a54feea334.npy +04379243-33c9515dc8f887bc664b3b9b23ddfcbc.npy +02924116-8fbfd6ab27e1b3436ca2b6e5474aad11.npy +03001627-a27db3ddc9bab11a5fceaa39a8353bde.npy +02924116-d68bb8e6b2c612ec8b645746fb0b699a.npy +02747177-415cae243e110f5cf155d75bbf62b80.npy +04090263-ffdcd1ea957aef3dc5e86946f2168706.npy +04379243-6d0ef6312f8af87a53e946fb2184f0c4.npy +03001627-b4bbc9d05c1872239abed18a788c862a.npy +03001627-11e0f0dfd3d0b22130ddb6ead95f49cc.npy +04530566-d00fe7ce177483ed5cb65f793213d431.npy +04256520-fcf030593c0bfac4f13ce777d031b4b2.npy +04090263-91fd0f24b4865bcfadfdd35441a4b4ea.npy +03001627-3a51a83963c167c422e8a95d8ef092f.npy +03991062-4616a444bbbf7858a2c59a4d90e63212.npy +03790512-f0c7043178a8a2fc52ee90e577613070.npy +02828884-c56c65eff860855def9373d49bf935b4.npy +04379243-d4063d86f6b2d27cd5b312abcf74b469.npy +04256520-4fa6c9c06efa1fe14156f0e87c6858f1.npy +04468005-62012118bf9486daea52501e96cfb14f.npy +02958343-b1c6a021c1c47884c9463ecce7643e8e.npy +02818832-1edea7d187858e2630b07c64830a47f3.npy +04379243-a1be21c9a71d133dc5beea20858a99d5.npy +02933112-34850728ad9af669490ad276cd2af3a4.npy +04379243-9046b2e610065fe5a5d95e73eecd308a.npy +02808440-c0b9dade20bdf5eb17bd6af98d7f8e7.npy +02691156-b725f44502906a42dc5a5a67e94552af.npy +03085013-d6bc3855da47fbc842e76de3842fd93c.npy +04379243-187804891c09be04f1077877e3a9d430.npy +04379243-3a990272ef4b83ca8d3e8783b997c75.npy +02691156-489d3e4cc3d790a0ca8607f540cc62ba.npy +02958343-8b8f4f12e5b142c016abce8cb03e7794.npy +03636649-579387a47297e1f4276206fae5d3c473.npy +03001627-6fcb8bf770b8606697e2a21b8bc2d948.npy +03211117-52e60434725b8bf8f0975d5dbdd766e.npy +04256520-a5a855d1b710641ba90692240cb38ca4.npy +04090263-12ccacc72630c2a4c4a6c34a09e62a92.npy +03691459-8f9c393fc17d1cabd77ea5e1afa5bfe6.npy +04379243-c9da930b808c18d0923ef79fcb120ce8.npy +02828884-dd1a375db7015e0ad6983f351200ac6a.npy +02808440-5406f6de80a4bf84fe52ffd0e748a1ab.npy +04090263-ca13a3342c397d68952d52701459b1f0.npy +03001627-96c019b564eb9cfbf3c9c1464e55d580.npy +02933112-350be7f9f7eaf2667dcf5135889d9f2.npy +02828884-e108673170d8f781d40c07d3c15cc681.npy +04379243-d58bdda16e6bba6f796740c80be6053.npy +03624134-c66c2c4dc16813a4feec58e9448e8e82.npy +04379243-17bd2a95d2c691326fb8d4cf06fb5045.npy +04379243-99f9eac72f5b4df04d31637b346f5216.npy +04379243-b14c4d5783a339609fd4171283f33ca8.npy +03001627-78ba9e32a9a5c276f69d13812ce67f33.npy +03001627-da5aa9fe015114731a1272c8e47f5670.npy +03710193-7410410cfc1684d19df6f10c48eb6cee.npy +04256520-c09ae0a971165afe4fb315ce917a9ec2.npy +04530566-f728f7efb5612cfe6be14c19eeda8326.npy +03001627-5bc916f8b9d0a7c6b40f0ac0fb9a650d.npy +02958343-d8879578d668b458cf899c77ac8ff2f4.npy +04379243-478cc8d5c72f2823d2ad39bada7a0a.npy +03001627-ea572cc193b804399c66df0f068d2a36.npy +03797390-b7e705de46ebdcc14af54ba5738cb1c5.npy +03001627-98b698b0253d933b72dadd9292b51ceb.npy +04379243-b9c5de845a1f5ccf23f93d9b8d14f53c.npy +04530566-37b4b837ca7da6a4561fc06c3ebd59d2.npy +04379243-e07c83841b933e74c5facc3cc8dc041e.npy +02691156-523f5360c3aa35b5e1c77ed807ff5c62.npy +04330267-e72944489018b7b39360ca51ac4aef20.npy +04379243-e0bf1408425c886da159545213d74ea.npy +04379243-2a8a8ffd2ef41cef20768660cf080d12.npy +04379243-a0fa360b6e9b22196db2ac45db35c175.npy +04379243-5844a7d413c48b3eb9ea118461aa8a00.npy +04256520-64895a5b618e8a6fb40f0ac0fb9a650d.npy +03691459-22e8cd8675ab57e26d2f7f4796305f20.npy +03211117-32be865d1baf7eb9ca4aaad7dc0e3a16.npy +03636649-86bcb422f12d4d17446ab9475f488764.npy +03211117-c16f53ea58244af7d5297776dd9015b5.npy +03001627-67d3a3eceaada710e400ee8c5c49a7eb.npy +04090263-afda81e011c79d183978e5bb605fb72d.npy +03691459-4e0dee54cd02258eeeb8d422649e5f2b.npy +04256520-8d5acb33654685d965715e89ab65beed.npy +02958343-b44b09bdef8fa2209473806fbdf65cb6.npy +04379243-12193ca7bef40d40a84aed1cd93567b2.npy +04256520-e92822b0b73f0ad6976792e9f0f98e95.npy +02828884-8bcf6b5dc0c19e6cad5067eac75a07f7.npy +02958343-a74409e07d1a9e1a2925dcb663974b0.npy +04379243-7a95843ecfa6e5b7c21dc5ac5592089e.npy +02933112-3d326cbd820a49443a9bf8c718fc345e.npy +04090263-c888076f7b8cb125550a87cda3436d95.npy +02958343-7a226f6c9c37c8f7253c03b7df20edd5.npy +04090263-792adfe42bcc28b36b12c93c965d90bf.npy +02924116-c84de00e45935c77b049a4dd81126be5.npy +04330267-7c3287c18d2cff672e57a20276f6e9.npy +04256520-a6ac0716e7f056579f2349486c570dd4.npy +03325088-e762df4624be42054c62bee40dcdc539.npy +02933112-1ceaae0aaeeeaa1e5a8eba5f6050bab.npy +02828884-2cce7ee3c360abbad2b12aa6a0f050b3.npy +02801938-769f607f748898c737ac8d648045f9c5.npy +03001627-510a6ee3bc0a0669c8101121c12c3f9.npy +04530566-8c0199fb20e7d4d391347c63d1dae43c.npy +04379243-7534b0ffb603e3c571a70be9f12ce8b0.npy +02876657-ee77714471b911baeeff0dee910fd183.npy +03636649-2ee70ee71a0b7caeb15194162f658e87.npy +04379243-5e83bcbf2cafd5663087f84b199fd297.npy +03325088-a8a40aa426ecf89754d7082b34825ef0.npy +02691156-c47954200b78fc32f677dde7945cba25.npy +04379243-832bcb192b80378fdb039d8689a74349.npy +03001627-933902ec014c6d487135fc51795b4038.npy +03211117-91db88d4d0956e92a9a12c50dc330a66.npy +04090263-4125cf5a6e85244f2bf266a8f0187ce5.npy +04401088-1e597e56b6b2fef6c331b59dc8938ad.npy +04379243-73ea0e595fe794dced787bd949919203.npy +03001627-5b38b467c20ac734f7c5e1744a5e6f5.npy +04090263-59b69d23c7a2f9568f12efb4f632da7.npy +03001627-51f1ea91a1cd7370b3fdb1a7c9a60207.npy +03001627-9ee4b9c97bcf4b3715dec43ae6a12831.npy +03001627-674122da19a75d9bca86e527b84d8854.npy +04530566-1d6d57f489ef47fca716de2121565fe.npy +03325088-c04fd0df2310b7653321831d2245cf06.npy +02691156-70f330ba02ad7a05bec2ed99cca9acdf.npy +02992529-e0d9622225e1361883b4bc86420ed21d.npy +04256520-2b69e899da0c15cfb40f0ac0fb9a650d.npy +04379243-4386633c2d2a1a2c5fceaa39a8353bde.npy +03948459-3da97809eca46f35a04e0afc178df76.npy +03624134-1897adf19953756d91687e259c21528d.npy +03001627-a1555d448a9d6fa0666bc0b629562709.npy +04379243-d6f8a3bdcd20146929e4b5aa807bb4e7.npy +04090263-6ce72fcd06e465a6cbc6ff5546f4ec42.npy +04379243-89fe1ff1b8de298752e8ff799642884c.npy +03001627-956dec7d9cb7d078a9fe51c710ac111b.npy +02924116-8b95e9545df064536436916a86a90ed7.npy +02876657-9012b03ddb6d9a3dfbe67b89c7bdca4f.npy +04379243-a797546d87b4a03bf4b6538438a0b930.npy +03046257-e75539f66fe4071e4858278d1f98c5a.npy +04379243-7b5544ecc31bc609a8e4e5c9426fb9cb.npy +03211117-9abd70906336af9c1c209b1cd3e81587.npy +03636649-790931b57e9513bf661713a114fc5367.npy +02691156-692797a818b4630f1aa3e317da5a1267.npy +04530566-8508ec8efeedf4a41ff8f5b5b24b7b46.npy +04256520-b23656fc9bf32eaffa22474bb826a278.npy +03046257-a0cac1c1e4de1434f51f77a6d7299806.npy +03001627-88aec853dcb10d526efa145e9f4a2693.npy +02691156-3039adb37c192644f8c6d04d97f8cf7.npy +04379243-f9e126d15c5761b29af4053b8815b239.npy +03001627-9e3dba0e6fd3408bf382e154aede1b6a.npy +03001627-713d9d23bb3eccc17fb8cf8a85dcfe23.npy +02691156-5e9129782c45b26992e39b8eae3e6b15.npy +03337140-1709429729eca32ed477567e8c8a6c59.npy +02691156-f5cc091bacb338c6951971f8370d9050.npy +03325088-b963d7abd99a0f9df94134d46393e640.npy +04379243-15490f254e6e226835cf289fa8ad7115.npy +04090263-f36f38edfbde85c73a04e41b7ea7de8d.npy +04379243-126347c2c4404eba96a3517f50eeb9f4.npy +04090263-e6ff26a9ad6f6321ec69d13496bd4a34.npy +03928116-c86b1da5558ff70a9949833630526071.npy +03467517-1416788a22ff5ffb1082f2ea630bf69e.npy +04225987-d4c042d11f29dffa1082f2ea630bf69e.npy +04256520-c06ec5cdf3500b6c965332f7444deb03.npy +04379243-3817a222e96acc4ca78510b72d2281ea.npy +04379243-7edb9183dade5413ae685ca100c909e8.npy +04379243-e692a96adb18ae3fce101336817a135f.npy +03691459-68d5652dfb91b82fa2b4280235a76885.npy +03790512-8a5175f5b9be6f34e91fe7b067344e07.npy +03513137-d8b02a2ef9de06702e85eab6bca44d5c.npy +03636649-ed323758d0f61cfe6085a0a38e2f255.npy +03325088-7bb78658b34e569933264edfcbff9a7.npy +04379243-6eb19c354c19e759d5883ca9b41ac387.npy +02958343-3da0d2ecb594ceae348b30181b0729b3.npy +02880940-ed220bdfa852f00ba2c59a4d90e63212.npy +04090263-36dee5893da238565dca6305fb9f97ca.npy +04256520-9895736717c559ad48d8ff57878739ca.npy +02958343-aa5fac5424a05c6be092951e627bdb8b.npy +03790512-42b5ea257418825b5c11b538bde9e3f1.npy +02958343-259bf3c89b0b2152c1f18a2d53a6674a.npy +03001627-bbadf45aa419015c7e4d369f13ed434e.npy +02958343-6d89098a33908cbd77b59844decf6d46.npy +04379243-1ad672c0a138f8ffe286a7dded929c2a.npy +02958343-8e05e4f955eaf140ff673973a435017f.npy +03211117-1d9f55b1651c5190a3f4a96ccd277d49.npy +04530566-6a65cd6bd6897cbb42df9eeba89a416c.npy +02933112-8093937b9072e92afab6e40cce6926d7.npy +04090263-98f15a80dc5ea719d0a6af9bfb470a20.npy +04379243-8d35df98a26e8317a193550461f84122.npy +03325088-73349e2e4982b3aac36fb70296e45483.npy +04256520-7e7c1aca9d7ce7f2f7628281ecb18112.npy +02691156-79784107e5be61a562347b4731688b0f.npy +03691459-79267b91b523933d73e1b2d018c0512.npy +04090263-45f3755b324a97803bce1f290fbeceb2.npy +03325088-b53baa693c98951e589577ccf07b31e7.npy +02958343-6232fe1824a6d1775b72003cd427d0c1.npy +04090263-efe36ad683de3640a5aad165050e534c.npy +03710193-f0d2c4725d7c5bd037aa26bfaa1093ed.npy +04256520-6262bddcd8bafdac3bec56bff764ba78.npy +04379243-c11167eda66f60f219fb4103277a6b93.npy +03001627-df7735e2bce09a511f98c0761af40e04.npy +03948459-254c2310734d6a5ce3cf43faf3d38113.npy +02924116-e9c2ef4bf977b1b8d8b621afbb58ba75.npy +03636649-df4e44114543e805fcb8d8c6d4df8143.npy +03001627-810cac0d137efb1d21bdbc0445d9f748.npy +04256520-e4c4c35bffae3ea375a82b88fe6e733f.npy +03001627-8b54af871a3ac77c492d9da2668ec34c.npy +02933112-b8e019587c8157041a3b39b07e4b3d0f.npy +02691156-1896f1f8724aff33b7ea0a7ab024f81e.npy +04256520-15d2efe697d229aceaf288f952624966.npy +03001627-9505568d7a277c7bdd7092ed47061a36.npy +02958343-1f8aee726cbf44c23d27832ab9ea6d92.npy +02691156-a61d4ad108af6eecca8607f540cc62ba.npy +03211117-4a8e7bab0b1bcf77103e42d04ec345ab.npy +02691156-5de2cc606b65b960e0b6546e08902f28.npy +04379243-c24b7a315dbf2f3178ab7c8b395efbfe.npy +02828884-3bc45b4fea81c02463b2acb037dfbcde.npy +03636649-456a6dc3d369a749519f3f3e6cd6d1a6.npy +03001627-32788564558e513f7628281ecb18112.npy +04379243-a13c36acbc45184de76bc197b3a3ffc0.npy +02958343-bb3c68db5dc0052e98b54df7430097ce.npy +03001627-a122cf5d1e23e88d72a5c49c981e6593.npy +03001627-b60fb4126e9e7c2aee3907b60a74e8f8.npy +03001627-e2ed8de5542c5fcd215a29c5523c5fad.npy +02691156-7fa1d1bd456f0fdf6e68e46a69a2d96d.npy +04530566-33f7a4ca412285334616fd0dc3d5279.npy +02828884-f2916fe6d5f06678ad5067eac75a07f7.npy +04379243-dd6e80140b3462f4a1b2e810c76f942a.npy +04530566-1c7f49bab676187480901e43af4435c7.npy +02828884-1dd7409c95d59d0da192483aa282f8e5.npy +03325088-1e5712458907fe06b362845c6edb57fc.npy +04090263-2d34668468d0b542612389706438d0e5.npy +04379243-8c2ec4b15289d88cc5d1c45cadcaa3eb.npy +03001627-3795f02c9818a7213b407f4857c15d98.npy +04379243-2f3557438a95798fb76e29c9c43bc7aa.npy +02691156-dbd0efc89242cc9318de900bee20377.npy +03211117-771a0b1638955f3946f539968f885949.npy +02958343-28fe2af4fd6ab3848772afa45900d07f.npy +04379243-1ab0b879f52e7cbe958d575443776c9b.npy +02958343-c4941d6a2266813c3a2b1a2e5e169910.npy +02691156-5ab5f03340921fc8b96ae1a0a8b84ec.npy +02924116-f350f3e3bfea76429afb67dd284d342.npy +04379243-cf46448f9ef495c81d022067655f6c16.npy +02691156-70ae0521d5ca428d7b3d3cfb30f2513e.npy +02691156-cda1206f9460ece9868255f726935f63.npy +03624134-24052727fc20af3723323642c1ad333d.npy +02871439-d70d80e5855785a761b9fd1751b9fcb.npy +04379243-36f771a41910dd89fb713eaada66481d.npy +04401088-6f725c21e92ae3e8dfac5fb05629bdfd.npy +04379243-38ededbc1b3693cbb9aafffd8edadb6c.npy +03636649-c6755ed48456490d2744bf8869518694.npy +04379243-a7809c62e26301e08850ff5e612b6198.npy +03085013-56794ac8b1257d0799fcd1563ba74ccd.npy +04090263-299416940399c3729d05095e3aff5e6c.npy +02871439-80b9e4e048733c2916421c9121bcb0cd.npy +04090263-78dd4dc65639258cd735fa1ab17311ec.npy +04330267-f16c01b6daab26e5f05f8c8f732a9858.npy +02691156-260305219d81f745623cba1f26a8e885.npy +04379243-1328dc6429d179d056f6ef8b6ca8f4cc.npy +04379243-cb1cf4ec74b4aae217923568dcd460b1.npy +02691156-22d36043ad59ef026edd138a394f7c4d.npy +02828884-6aae683396bc08eaa4b1640fdb2c85c0.npy +03691459-c0de25758444d71f77818a0572bf1777.npy +04256520-7bc386f19f261758664b3b9b23ddfcbc.npy +03691459-7f1be3e7b6adeeae9bb399e812556da2.npy +03001627-68b88c0be088c21d5e0096fb2d3266a.npy +04099429-fa07813a89527d195d1df55cbe0874aa.npy +02958343-fe7c536197065436b3030c76de18d16a.npy +02747177-f8b449eee1c8775fd2b12aa6a0f050b3.npy +02924116-13339384a87e3557b1626da45836ca54.npy +03001627-df28bda265e0e5bd2d282edce951a03f.npy +02773838-f5800755a78fc83957be02cb1dc1e62.npy +02691156-856a4d86ea105d97be13ce34aa7c0c1c.npy +02958343-8fc2691025a48e21381a9e1cee6d0b00.npy +03691459-a34c80e1f6175711c9d5b08933b9e0c1.npy +03790512-e1dbe3832c41e45a8f23c5d2712dcf1e.npy +04256520-523daab7896a34ed65234765b3a00e8c.npy +04256520-1c2fa78dbf2d2cda9e02fc85f824870c.npy +02958343-d1e2f84cc473956696e59b6a2c87ca55.npy +02691156-352a8e4f2023b029dcc75fd1795fa3a5.npy +02828884-35908dced5e46b32ad5067eac75a07f7.npy +03001627-9aece6c6436cde6fd9ac1bf1eddffd24.npy +03001627-ca5d7ee5cc56f989490ad276cd2af3a4.npy +03001627-114f72b38dcabdf0823f29d871e57676.npy +04530566-7c4ed531d1ecacb156258bc213b2f9c6.npy +04256520-afd1b4501cbda28814f62593b9237aa3.npy +04379243-5740806aae21635034943af333340cd2.npy +02958343-c8fa4fd7fc424121932abeb6e2fd4072.npy +03642806-57f3409e6f6c2dbc73baa2510487646b.npy +04401088-657fbd67af945c39d9e3837723c05057.npy +02924116-831d5d480526df85f991e1d909fa63e3.npy +04468005-7a8919f9d2bd7b2327745e9b6b461e93.npy +03948459-46093a3a5f168491e1f2a1daf140ac9f.npy +04225987-d041334fe322ed211082f2ea630bf69e.npy +02808440-97cc75a511c0e11b54d7082b34825ef0.npy +04401088-2d3208fa267160862c611effe1bec8cf.npy +03636649-a911474d0fa043e3cf004563556ddb36.npy +04530566-61eaa4afe332ba113547ed4d05d19f04.npy +02691156-934e5dbb193dab924d02f09e7a1a5b28.npy +03636649-a7f67a2088ce033f3ec7ad443e0ae81e.npy +04379243-1fe806fc0004aae877845ad7d2ecfba.npy +02691156-95f7a9754cba79469a6e43b878d5b335.npy +03001627-87b576eaf04f1b62305e886266e302e1.npy +03797390-546648204a20b712dfb0e477a80dcc95.npy +04090263-5376c38ea63848d643b0dda994f793ec.npy +02876657-9d2d3a8d1dd877c1101343fb67a1d189.npy +03001627-c98b7e1952c2c7bb85f6153ed2033a1c.npy +03046257-57e7fc194e77abd5a8ca6a1b83e76dec.npy +02924116-c2c9e1682f395fb051894d116f1c652.npy +02828884-ccc1d51eabbf589ad5067eac75a07f7.npy +03593526-aa638e39c28f3a184800dfbcda5cce3.npy +02958343-52a1d23a09e38c4d50577cf04f3bf74a.npy +04090263-7d2adefb8872fb564d73c4d754d3623a.npy +02808440-591906b60da78a063321831d2245cf06.npy +03001627-4159903eaecd9560fdac1e69603928f.npy +02691156-56ed0ef0864d18c2f5c7319b71bdce6e.npy +02942699-1cc93f96ad5e16a85d3f270c1c35f1c7.npy +03636649-5bbe3658e49eece0b49beb995c4209b8.npy +04379243-fd42924378694d9c2554f2f6bda30622.npy +03001627-22ada577361ed0374b3c42e318f3affc.npy +03691459-c73bd84347cd8fc9599d9c8430d600ff.npy +04379243-df38d8c2f3b36ff76e4b69f8ed4dc344.npy +04379243-e7c9af90b186c098490ad276cd2af3a4.npy +02691156-d64f391dee878277bd46d022fd7d80aa.npy +03001627-dada2389e96606307aa7cd663df90f18.npy +03001627-e467cfa616850a4a990561fc34164364.npy +03467517-83c5644f07ee55906f29623db019b549.npy +04256520-192ca330a80532471b17743c18fb63dc.npy +02747177-5982f083a4a939607eee615e75bc3b77.npy +03001627-a724a8b2ea1ef63954a8e7cfdf35a7ed.npy +03001627-796903c53c6de2025213cec267286d18.npy +04379243-ea367e390741fc38dcfcef693e7ec696.npy +04401088-878135eab6ae9aa181471a5ba59fd0fa.npy +04256520-f813edee6c5acaff4fb315ce917a9ec2.npy +04379243-aa97318224630a33f51f77a6d7299806.npy +04379243-25fc395dc873bb478a252571106d569a.npy +02880940-3f56833e91054d2518e800f0d88f9019.npy +03001627-7e7c1aca9d7ce7f2f7628281ecb18112.npy +04379243-8654b644c766dd23d1dcc55e36186e4e.npy +04256520-113a2544e062127d79414e04132a8bef.npy +02871439-dc4398c59766b2e8d42b9650f19dd425.npy +03001627-764866604b035caacd0362ae35d1beb4.npy +03001627-776c1d1857a4ea3d853c3fc864dd58b7.npy +02691156-a231f85d38f2b52154eefcdc602d4520.npy +02958343-2f0ca88dc76e39a7ff1370452e3a0154.npy +03001627-6455bf241fcbe3a03adc3470b30138f3.npy +04379243-aad4591952dd151189485cd87f37f89f.npy +02992529-5e5c0391952208e81213f8f7891e7fa0.npy +04330267-18943947ce3b8cae8a94168388287ad5.npy +02958343-473dd606c5ef340638805e546aa28d99.npy +03467517-e15f472709c535382c8ae424ae73c66.npy +02691156-958cc8251e6f7d8fa9b2becd26dc2fc1.npy +04379243-f37310698d465cf8c8bd09537246ca3a.npy +04379243-229af4d0700b3fab29f2e5c9212b176c.npy +04090263-ad0bdb0b1b0c8077b4cdad9a5bf52dd5.npy +02958343-edb2ab8a1d7e20f36436916a86a90ed7.npy +03325088-839b652592f066cd31ee592be5c5c0f1.npy +04090263-8690ee57423c0e591f3140bdc5d4932.npy +02933112-19dd35ef180808c38f1735145fdf5c5c.npy +02946921-b6c4d78363d965617cb2a55fa21392b7.npy +02691156-28711664a9d08bae46322bce65ca3756.npy +04401088-ae942af3b88d07af2c557fc696108818.npy +04530566-13a9352a47bab8c98cfe472915a175bb.npy +03642806-e555880523dc11425b440d1b0fe8ea5c.npy +02958343-2be8bd6b150a9fee97df6383472cc5b6.npy +02958343-2fb155f2d36541b5e3bdba9430565083.npy +03001627-124ef426dfa0aa38ff6069724068a578.npy +03337140-8b3e462e8050e8f8e4e346ee2650d150.npy +04379243-a79ed851896a40d8c10555abb2efb430.npy +03636649-5a957ade80507541ff2c92c2a4f65876.npy +02876657-2bbd2b37776088354e23e9314af9ae57.npy +04460130-a0cc96c45bc569d9ebc1e59456a1eaad.npy +02876657-1ef68777bfdb7d6ba7a07ee616e34cd7.npy +04225987-95c69877104059fd1389cf37af584e4b.npy +03593526-bbb981cec11e59771fc611122dc20c0a.npy +04530566-707f009ba421780c2af11d59b11e0199.npy +03046257-d3676f524d86dc1d6463df620b7b4cbc.npy +02691156-b7b94613ab6076a2a959294e5fb80cf8.npy +03211117-9740d1752c70a41350577cf04f3bf74a.npy +04379243-6a31302378d14412d42ec7e303174a87.npy +03467517-ff18697f9ce909311082f2ea630bf69e.npy +04090263-7b6a6e33903b1639a5772249c0d44247.npy +03046257-8e0c621551e9ace310eab5c01cf505db.npy +02691156-1284eb71b82f6794207f77cc6c79e3d5.npy +02933112-178529522942bd9e11fc2b865c2a185b.npy +02828884-6b9d09fcf8998360a36fa9e07c662628.npy +02808440-8a79f6c9e4e6badc26ab2d6bff19a0af.npy +04379243-15647d8895f78f6096a3517f50eeb9f4.npy +03467517-1a8512735ed86bc52d7d603c684cb89e.npy +02992529-cc3f77485b8a18db562c8e1ac545ef78.npy +03636649-9b0c6f3ee4a7965644b289cb940133b8.npy +02958343-b156359022f172578c844a5e3a5e1a93.npy +03001627-39c2f4690aff8f049a45ed2554d2f93e.npy +02933112-5984042b95305aee4da5feafe6f1c8fc.npy +03991062-707224831466c848368b14e48c164a6e.npy +04530566-4bcb45bdbf0309201d2d2f3b717d35d5.npy +04090263-931f74bd98683d493a04e41b7ea7de8d.npy +03938244-adc12b60e048f81b283b00891f680579.npy +04379243-61c9711cf5308ff98d4b556335cc5d64.npy +03001627-d9fe499372f2156fc0d328376073b25.npy +03642806-7d2718656efb3920d1954a7ac233ac80.npy +04379243-905ac0420ec18c415aa4c6e8ff29695d.npy +04256520-86ba626309daedc8e8f8c11a24c52ebb.npy +02958343-cd24768b45ef5efcb1bb46d2556ba67d.npy +02871439-c007d1b4972f70102751be1fc72418bb.npy +03691459-16e0041bffa976462d563c85edb49108.npy +04530566-8c611205ba2d189068b6f3ae18faf6b7.npy +03001627-c47b50988fef70c9220c18114ccfb3af.npy +03624134-e9280056548518c0ce7c7b3554aba2f8.npy +03001627-a3aa7e473a8059133087f84b199fd297.npy +03636649-d450da2cf4d0b79bb20310112468976b.npy +02808440-ae1a11d1ca89ba26e863737836cd53b4.npy +03001627-fc7b535acdde11f4aa3e869226c9586e.npy +03001627-1c2caacac14dfa0019fb4103277a6b93.npy +02933112-124cd036611b65b514038d588fd1342f.npy +03001627-fdd21f7f2ca9f0bcbdcbca499b446e89.npy +02691156-e58010dd5766e0ce78f081615c34707c.npy +03001627-2ab159f83754a93ea6c03a53cf0a14c9.npy +04379243-d4b3c13ec756196f94b77d9f59f49ab0.npy +03211117-b0cc3e614afbe6546892efe917403e6c.npy +02992529-11f7613cae7d973fd7e59c29eb25f02f.npy +03797390-9278005254c8db7e95f577622f465c85.npy +02958343-857a3a01bd311511f200a72c9245aee7.npy +02828884-d7025b55fe15337ed7c5502d4a22edf5.npy +02808440-a44b0784e8f0c72d8a1b2423d95562a8.npy +03001627-239c363cbe7a650c8b1ad2cf16678177.npy +04256520-afdb8885328a9e1e8cbb8bac2032149c.npy +03337140-220844159a323ead4c3aee8e9d3a6ffa.npy +02691156-f70e5f2568e927147d755f57c8fea340.npy +02958343-37887931377037621f71e734a2d317fb.npy +04090263-99cd8bbe5b2f92fc643ae903098a314.npy +02828884-f397f583f459134030c983bcaf68f0ab.npy +04256520-b50c0ff1aa497809afbd772c78d05c2b.npy +04090263-ad8abb01ee9066b425c01bf8ef97ff0.npy +03991062-56d1efaa9b9cf0a85706d1c54190f27a.npy +03636649-4e0aabe8a65ddc43e019184dd4eea7e1.npy +04090263-a4ba46bca40afb3722fb813d47b359e3.npy +02958343-53d9995a0b94fd37428df271ebc70bc0.npy +02691156-6826af6513566b12f4aab844bf68e35e.npy +04090263-4aa568a12086e742fe773002d2182b7e.npy +02924116-3d5cf6ff4603cfbdafd9b08701d71980.npy +02992529-20e5a92f95731f04c4440dd41b08b3f4.npy +02691156-1026dd1b26120799107f68a9cb8e3c.npy +04379243-316863fc4ed4dcf7251178be84deb2e.npy +03001627-131abb0b13d6c5b97f0b1e4f6d35b0ba.npy +02691156-af188ff4bc1ed0693faf1ff99e423b8.npy +02958343-90dc895f52bdd3a748d3485197509ddb.npy +02924116-17fbe76eb329ca1f481aa8b5531c68a9.npy +04090263-c40d62605e84c6beba1d8c8cfb70e106.npy +04074963-759c3e99588cf5c7a25c3f3b8b3a059a.npy +03046257-51184ef0d515b5f2345b53c800e94980.npy +02958343-6dd48d74d8bc67e7a7fd25564c2e888e.npy +04090263-b3f0d3a6734e040be658483f9f1a085.npy +02958343-a6fe523f0ef082a2715e04edb8af9c53.npy +03636649-d456beea1501f278f70220cd6be776f7.npy +03001627-bdacb728b23fc758fc0035da39bd5e1.npy +03624134-b61c9b5f29ad581c860a45e027159a9a.npy +02801938-adc09c0ed058fe5f4725f67267e31c89.npy +03691459-400fb89ed6cc3d2bf1acfa9a5200e941.npy +03046257-395ec392bf1764d8eaf14273fa406ffc.npy +04379243-8e5bc7946066f431ada975aaf86ac85d.npy +03001627-8e581e01a8b742214e3003b3c5dcc179.npy +02691156-faa361f642620bb72def37e9c0b35d0e.npy +04468005-5a7c58285f656a47ada7c0f51e9fb493.npy +02808440-3121fcae458eebe383797e9920834fab.npy +03001627-103c31671f8c0b1467bb14b25f99796e.npy +02828884-ca4bb0b150fa55eff3cd1fcb0edd1e8f.npy +03325088-a63d9ab718a0427fc36fb70296e45483.npy +04090263-8ef53ef4767baf0d9af0e0a4fa12498b.npy +02691156-556363167281c6e486ecff2582325794.npy +04379243-8d07df2bf706cda58c5591114064d173.npy +03001627-2a1184b04dd8f30e3e92f39ce48d644.npy +03593526-3bc220b749489ffa89035c25f0dfeb63.npy +03593526-d20501ada9005a3fbd16d4490a10a752.npy +02691156-9a3b5fa35243504124f575085333a65b.npy +02828884-e6a3b8946b66b83065ba78ad9601cf1b.npy +03636649-93a984496599a5b82b151d8b52c53b90.npy +04401088-4f3c84ef24e1fe6f3b41ed175964f6ee.npy +02691156-fcc2023fd98e157f2d99c69702933ca4.npy +04256520-cd5f02ca40330f18febad4f49b26ec52.npy +03046257-7c1296df0dc164abc114ce436933a33c.npy +02747177-bf4dd114b53bd8f0d67352166d8df9fd.npy +02818832-a7d64e6a7223641733b13410d81359e4.npy +04379243-e8c92eb88e60460e9128f82277957970.npy +02691156-789f032dccc6092977b7d0d4764c121d.npy +04090263-d945ecdf7613bfe0c7da109ecb5068a0.npy +03001627-7fc52894c0d1e26dc433ba3e0e025e8c.npy +04379243-8e33e392d91ecf1c668ae11a7db5e82a.npy +02933112-c21853b4876b7078684b7bc3f8a9aa55.npy +02958343-1e0ada2b1891ea39e79e3bf25d5c768e.npy +03211117-d1fe596d83fc231ef300ba2413f318b5.npy +02828884-b2ab0b13c344132ec569803a3242d4b9.npy +03001627-601cddae7aca083a2db431502a680805.npy +02992529-7bd9b1b1297013ed65f78a217bb320fd.npy +03001627-3ab0a1dcb23aa0f620bea10952746d3.npy +02958343-2c1c8c4aee1e79d52aa494042b7c9db.npy +04090263-b1a6f690b8ae5ee4471299059767b3d6.npy +04379243-2eb503dde3cc027d86c701087a194026.npy +02691156-adee8f091d7cc677508af777f11ed409.npy +02828884-a8be828647ebc817abeb67a6e14a6d65.npy +03337140-de40f8e4834666b94c3aee8e9d3a6ffa.npy +04379243-44e4ff8c96e5864742d23b95defe1ce5.npy +03467517-9aa333a858848cb685a8bf3411bdb83e.npy +04468005-987bf24137c0d0d2c9b18c469e002c35.npy +03001627-a0d662f047378406a39cf424b6103cce.npy +02828884-d94b57d9a5d0b3732056b4bd5d870b47.npy +02691156-2b96f4b4896962473eb731541f9f8d.npy +03636649-d8d129b1a07b23b7a738de48265832af.npy +03636649-d87a2d766579f15e38b27a25d1336579.npy +03991062-3306b6e41cd1e40e7d257f312237d3ef.npy +02933112-584de35ad1e27820365f491f6e3dbc3f.npy +04554684-50c639910aa3d75f29d8eecf3827c486.npy +03991062-17235acddd0fb5a6cb2a965e75be701c.npy +03636649-8425fcfab0cd9e601f0d826a92e0299f.npy +02691156-3f9cab3630160be9f19e1980c1653b79.npy +03761084-ba6d0df5585528369a16c253ade435df.npy +03211117-70df1655d1e766ece537be33cc045ee9.npy +04090263-6d4bb384945e1a95d5388e4d9f5e09f.npy +02808440-6c122d48d254276f3321831d2245cf06.npy +02808440-c45f6c706330e9bf3321831d2245cf06.npy +02691156-e2275ee8d6b175f2f446f92b52bbd82a.npy +04401088-7ab7f36fa3523a1a33c7b6ed91d531bc.npy +03001627-2249c62788a52c61613f0dbd986ed6f8.npy +04379243-75aaea3b26362e7a659dda512294c744.npy +02747177-6a1b359efc20cd1aaec6ee5ba573fa6d.npy +03001627-81c291ab8abc1d0172b24bdfca058442.npy +04379243-3d7a9a28bd6b772a878cf98f645da333.npy +02691156-f40467cbad9ca466eb7d375d58cb985e.npy +04256520-2b64dbb623899dec7bdbd1926dd38bdb.npy +04379243-a414a3468a40d91027a4a1658277b4d4.npy +02691156-52a6ae9074397d5f65f50257ecdfa5c7.npy +04379243-ae632e7cfc0bd3a861687229b61f22f8.npy +04379243-f624b401d623b74a87b2f182070d92e2.npy +04379243-e809af47a0255110855931d119219022.npy +03046257-afd459e16aa2f8f438e5ac608a19dac.npy +02933112-634a4ad6496e20dbc3ea9e7b2ba79cb1.npy +02958343-263e3ee9f0182cc48e35db9103756ad5.npy +04256520-2e12af86321da41284e6e639680867d1.npy +04379243-966cef675324e416cd415550f639925.npy +04256520-adc4a9767d1c7bae8522c33a9d3f5757.npy +02691156-cc0c7bf3f0f598db2a9ab3cbfdfd536c.npy +04379243-e8c01f71fd941af11190e285a2cbc9c.npy +04379243-bf2a153556edcdc96325dd85752d9221.npy +03938244-757be11305637a815b68a464a9cbfadf.npy +02992529-61e83782d92bf80b7548281e465c9303.npy +04256520-4198c7de2a9f450bf07fee5fc5c45ee2.npy +04379243-66d7c4e6ba6c4d415963245f0923337f.npy +03761084-2ebe8d4adde5172dc4ffd3331f849437.npy +03991062-9c00e85febb3950fbd353c96f0f6d633.npy +02958343-f7cca46c4c8efdc6fa5eb13ccb8cd2c6.npy +04379243-ba444152722b67444b8710a3469971b1.npy +04090263-df0c9cef42873e71d2888692adb4769e.npy +02958343-bacf0105f617a750becf71e2e014ff6f.npy +03636649-44e442591f82cd4cab0ac374f450cdc.npy +03325088-82c9b22a5f1f0999b362845c6edb57fc.npy +02933112-429536832f2f4e1abfbd6f1ce8dfb216.npy +02808440-fa02ef26c333e469b362845c6edb57fc.npy +03467517-f1a405948649acf919dabd0465d1d64c.npy +04256520-aed821e5939f74a461bf0ba277ea473b.npy +03001627-7ff1b0ac88baea05dbbc9440457e303e.npy +02808440-bdf94fe1bef0281b362845c6edb57fc.npy +03211117-f4097db6ad343f90d551435517f7f18d.npy +04379243-770f6ebf01b135e556938a56df3469d5.npy +02871439-aeaacd2127e9f88de8bb25231731c25d.npy +03593526-65d3ab62e8fc9f2fda564dc72444286c.npy +04256520-35d44bbbaa9763a1b1b2d85ddcddb619.npy +03513137-8018b307a127ec8d4051b6e037481c7.npy +04090263-636c6b4415df67c5a5aad165050e534c.npy +03001627-53a442e47743fa4f457ba044c28858b1.npy +02958343-ffbebc7c9a32a6f88ec8762dea278247.npy +03593526-4c9e762d331457997ed8de38e968d714.npy +04379243-3b68fa3c60e1cfb7745a5e8b6205e3aa.npy +03001627-2a98a638f675f46e7d44dc16af152638.npy +04379243-ff49113c1bda893155c5c4533d35b323.npy +02808440-29081c2803a3c83b362845c6edb57fc.npy +02958343-229d52c6df86197bc33d84e056f4fd5d.npy +02691156-ad66ac8155a316422068b7c500584ade.npy +04379243-5562593c6448e4856402b8f491cd92c7.npy +03001627-a4d7d4203cdec5dffebad4f49b26ec52.npy +04530566-a53312711cd84c9fcfea3d4fc15719ea.npy +02958343-39201299cf83ec2577763486d77d1cb.npy +04379243-8e637b52c16d8874f09e0399552c33e5.npy +03211117-64f160a87582cea38a57abd4646e319.npy +04090263-a979bcfe6e057e87696934ac57f77b3f.npy +04090263-32e4f161682231ceb785a4ac4a0dbd73.npy +04330267-93ebe284d3d0f9d65e723252788c3d6e.npy +04379243-8d29772f3fbffe408fb9278cf94ef5eb.npy +04379243-5ec773b266374121e8058cf23f6382c1.npy +02691156-6a47f4d30d54771e8782c935066e938.npy +02747177-ca9c8771ab1ec28920de219c00d1c3b.npy +04379243-a06be76ebccfceb91c8935ddaf3dd9f5.npy +02691156-1560968d05cd8887cc14f1e6f4f4f49b.npy +04379243-db454c99849016f8febad4f49b26ec52.npy +02691156-e6e8f0e244efac73da2b0f839aba40f9.npy +04090263-8a1275efcf36b408488d77a033721bf4.npy +03001627-5fc3b7d677788b486cd47753062bdba4.npy +04379243-7d6ad371f7037a6679368d1198f406e7.npy +02958343-9511b5ded804a33f597505fd7d99b613.npy +02691156-463834c3aa682c281883411175051361.npy +04379243-6c160b3f23bdb1af1832c6620d562eb1.npy +03938244-af515313df72452f29dab95fdd4a19d8.npy +03761084-15ba6dd7a9ad8b12efe5f291bc2f5fd0.npy +04379243-ffc2c7813c80d8fd323d6bd8db8de5b.npy +04379243-e67046b9860feedeec7cbf3284585a40.npy +04379243-234e44f27b5a2852500cffceffd2bd2b.npy +03467517-87f6b43385dc55702d9fe04691733c67.npy +03636649-8fe1766aa6997b0f899bad344dc01f2f.npy +02876657-323705d1a8505cdb498751cf10995c30.npy +04379243-ef7ff0018b4041ad577f990873b69f82.npy +04401088-a4910da0271b6f213a7e932df8806f9e.npy +04379243-8df9eb57d6f6bf7f490ad276cd2af3a4.npy +04379243-1270e7980d2d69d293a790c6eb6d2ee5.npy +04379243-57a27a7ce775e13197ff8153b678d004.npy +02992529-c1ae3b758aa9ea5e6dba92a4e2177102.npy +02958343-9c27cdc4feb2fa5d4244558fce818712.npy +03001627-ee484fb2c1e4e611a0dcc52ca811e565.npy +03636649-9f6c2428e0cd344d157d629c9921fc15.npy +04379243-114520b78a1726cf86de8d6734d81fc9.npy +03636649-8bcbfeebef5df95fc664c3d4e2d59341.npy +03636649-ca75df76115441abc516ff01c2593ee9.npy +03001627-58b3e0d46af2019bdd7092ed47061a36.npy +04090263-27fc3208942d136b92cea77f96988ae6.npy +02933112-ab096629bed6f8e0f51f77a6d7299806.npy +03636649-ed45838f0c557b778a0c77569eaa010f.npy +03001627-769df6463d9f566e1bdd2be5d322fe48.npy +02747177-a09482e9b131164ead5067eac75a07f7.npy +04379243-49f625856c796254d249abd69334079c.npy +02691156-d5b78307fd9a0764bc97347c46fe15e1.npy +02933112-17ba4ef76444e74b4da5feafe6f1c8fc.npy +02933112-40d4200a071b555c5588a2543ef0b0b4.npy +02876657-9a70dd116325eb2df6b14e57dce52ee1.npy +04090263-62586a8eabb2a67a609e2d916fa0da27.npy +04090263-6ef67d1906344eda9905a3939c890ad2.npy +02933112-6d5049bc983aa8b4a805114916841d69.npy +03001627-746ec5c7c0ab8924fc1f58a995f231d1.npy +03001627-6721f13f40f706c31b17743c18fb63dc.npy +03691459-ed80a69f448cb9a7205b075c6f63f661.npy +03001627-b4b65ad3117199a2e8b2b8dc0c816caf.npy +04379243-e39d56046b309a64229048a9abc3ab6.npy +04090263-3fba044c23facdaefa45f4d7e1ef7d0.npy +03001627-49434684366778973002761e7a3ba3bd.npy +04401088-3d5401f4ecab9be91aec2282dd8bc87a.npy +04530566-58f13d9c96d702c72d5c18abc132bda5.npy +02691156-d130dd0c96152140bc0909d98a1ff2b4.npy +02691156-d45809b73a371efd185b376619557c95.npy +03261776-2c6f04001afcce7ded85c3dc02bada79.npy +04379243-8f059d82a5c37104587d0dbfbd9ca24c.npy +03001627-d621bfa4a44a98e3829e1f3c4926c485.npy +04379243-a0445e4888d56666b9d7c2fc41e80228.npy +03001627-a366bbec303662a3ec545e4e9c852271.npy +03001627-7727d0eef3eeb3ba73b2b620da30da86.npy +02828884-7c5bebe21d2f9232af268f6180933aa3.npy +04256520-c293fb5d58a88ce85b903ba10d2ec446.npy +04379243-aa122afea2dcf725db039d8689a74349.npy +04379243-b1c7003075067621682d288075fc0dc1.npy +04379243-80af0f92ecf69f69f5ff054d67d5fe35.npy +03046257-1896aaea4625200be7b657772044425f.npy +03325088-64050bcb4cffb2d176c18e71fd49c4dc.npy +02933112-9a0d2ef1f31fee42b022c94235bc8601.npy +03001627-2fed64c67552aa689c1db271ad9472a7.npy +03691459-b8092ccc834f31b9d69825aa8e687d85.npy +03001627-297d3e472bf3198fb99cbd993f914184.npy +04090263-766db9eda4efe6aaf7bd077790d66b82.npy +03001627-a09091780fcf3af2e9777a9dc292bbd2.npy +02992529-280c7836d6302b4bf3f8467cb6fe657e.npy +04256520-337165c7708f17314038d588fd1342f.npy +02691156-a4ea22087dec2f32c7575c9089791ff.npy +02828884-61ade658bb475cc6a992c1353f8a88ef.npy +02808440-40aa0697e18dba1184dd6c3274cd9823.npy +04379243-616894d973384f358be590460e3754d8.npy +03001627-a5f300f3975497fa9dcf2183c858e6e5.npy +03337140-a3d4da412ce4ef2f4c3aee8e9d3a6ffa.npy +03636649-dc78674611170676a87391c8bef1a77d.npy +04379243-25672204a764515578439215682e01f6.npy +03938244-953d16ed7eee84d32d7a27ffaafaaddb.npy +03991062-37ad5cc6e0357defbffe63c069324d61.npy +02691156-ddb9b552868e8c61334736c27ce16882.npy +02818832-6ff38c09b9ab4dfd712f5f94eaf97217.npy +02958343-3220cc9f67cd763af63ee8a34069b7c5.npy +03046257-3c4c2a5b991508adf51f77a6d7299806.npy +03001627-f4b6bf9253918b52944d8f8e13d63fde.npy +04530566-1f1fb65b78e0f6ac816e21307f82dd39.npy +02958343-890e61bfb197190e6382e1684e46349f.npy +04530566-246335e0dfc3a0ea834ac3b5e36b95c.npy +02954340-2f347d95d4a2dae3e762cf5917cef4ef.npy +02958343-8e145be3c332199dd6821061f4432a0.npy +02773838-6881468dd51c214922022e93ae2b2b5b.npy +03001627-9a864d5de972a8c7cb686b8b855fed61.npy +03642806-c8309234b360aa2c747803756378b292.npy +04379243-b0910467658fa43f7fde87eb01f5851.npy +02828884-6550c93bce51b9b4719088c8e42c6ab.npy +04379243-30b506e5e1fc282afdfcfddf24fb29ec.npy +04256520-3c389c01263d2eaf2b3e9b6eb52d35df.npy +02958343-89431ed41e43bbc816abce8cb03e7794.npy +02691156-807d735fb9860fd1c863ab010b80d9ed.npy +02691156-7584ab1da1ae2778300ca77569ad3884.npy +02958343-6a06a8905edb576edb976bf16d451bb2.npy +03211117-ef7ea1a94404fa633c1661cdd6e9aee5.npy +03636649-615019f5899e2aee8120bc4dfb819859.npy +03001627-484f0070df7d5375492d9da2668ec34c.npy +03001627-b2d6c064af0c735f1783a44a88d6274.npy +02958343-751a2e8afd998768fb8f6150ea0ae369.npy +02828884-8fc8fb14df48da05ad5067eac75a07f7.npy +02691156-98b5a3a8e2ab94ccce19d55bc5e6a406.npy +04379243-db00e248dce5fe409cd431573238602d.npy +02808440-d5d3d361bdf7245e75519658e0efffee.npy +03211117-aa99cc4323af7144e7321f25048c6142.npy +04225987-f9efb1b00b79c035c1cb365152372fc5.npy +04530566-b5290cd73084cec0283f6ecb26ba2c4c.npy +03001627-cef1f5c49e5de64f593ebeeedbff73b.npy +03636649-41caf27a559755fafcb8d8c6d4df8143.npy +04379243-63ebf8f4f1e63fb0bc85ae0034c4dd9b.npy +02880940-524eb99c8d45eb01664b3b9b23ddfcbc.npy +02691156-5c43f5436b308ed89a6e43b878d5b335.npy +04530566-a83a9d54e0680aca640afc71da6e41a1.npy +03001627-42e1e9b71b87787fc8687ff9b0b4e4ac.npy +04256520-b8f0f62a95143a60c5ae767f471fad27.npy +04379243-42756ba88f851b6e3c8d0fdfb1cc2535.npy +03636649-fec5f9c209e09dd9d49b2e04785f8492.npy +03001627-4387affd3bc4509a36b41ce3eef1f5be.npy +04554684-9ac5425b6c547d3d99373190f2d703c0.npy +03325088-bf3e6eca3beeb5e89f5dacf3fb5f1b3.npy +02933112-8b35178a614ee2f462023490a1e05c18.npy +02828884-ddab02e0fc2921caf46518fccab79b6f.npy +02828884-3ee044d00523169dd4d8765e3910f617.npy +03593526-ded8dc705001ffd01261f7393ffee2ed.npy +03636649-d231a8b21aeeb7d78749901456352d5.npy +04379243-7c77974a20ec2629d8f27b2e727c3511.npy +03001627-9e6564dce4cc128efc24661f5f8d5d00.npy +03001627-43a275d9bd008a64bb0085d0daabdaea.npy +02958343-ba1a26acae4b773431141a7d4d06dc13.npy +02808440-3c16de8249619580fe52ffd0e748a1ab.npy +04330267-287fd6b1b61269907fa354dc1b904bdd.npy +03593526-d0240d785e39c7ef8da95317eef6e82a.npy +02691156-6705821a6b32fb3eca8607f540cc62ba.npy +03001627-736589cbc46fe6b059f8e31ca87c470e.npy +04530566-62b67cadf45841ab82b5804533e545b1.npy +04530566-badc6f1a2c19f724f3e39f2e17005efc.npy +03991062-f1c17606d5952d9225ebd1cd0b422e32.npy +03001627-270b86f1c341d7fc98d5fc0473d00a1c.npy +04090263-800299ba59951df3527ce7c85e81fc57.npy +02691156-27e6fe140e6e668a3881254c11db28.npy +04401088-19bb5e75692793fd45df661aef5d0a33.npy +04379243-996096692592afa91a0e159a720dabf7.npy +04401088-9728d42d4de74ff69ae0ec37bea5341c.npy +02958343-8d1ef0a2c958b23f22aa128014a842c4.npy +02958343-fce2b933f93d132f4f45033b2f001552.npy +02828884-1aa15011153c5d6aa64b59533813e6d6.npy +03001627-80f96250bed47b4f52e9aa88ca53e944.npy +04256520-77a56bf8ea88336019fb4103277a6b93.npy +04330267-bb5533538179f6c39209092a6c03f1bd.npy +03001627-7661a325724ae00acd0362ae35d1beb4.npy +04401088-ffd186dcf855e13e26479a182158bae5.npy +03513137-777497c94098014818457223b2b684b3.npy +03636649-60d1a7bf1e70c526befa8f2022732db1.npy +03001627-be43e61912136b5710f438ee952d42cc.npy +03001627-975d6db745442a755634c21965ee6bab.npy +04379243-f4d21f925b703fb7e46b767696592d01.npy +03001627-38d623b46d07a93fb7d9d23574a480ae.npy +02691156-122776d17b6a118086da73d36506db6f.npy +03001627-4356ef46fbc859a0b1f04c301b6ccc90.npy +02933112-8cfbb0ecb20361e8a7cb178ec63a7c4a.npy +02691156-7713f76f4ef99f19954990879891d2b.npy +02828884-9b41191a915c09bc669f4f2ecf8fba0.npy +04256520-90506850596aaa99891fca5db446d193.npy +03691459-d62a7c344c62875f9a0cc1a6d8beba8f.npy +04256520-b1f4e7cd4a1b24b4e086fd45e580f116.npy +02691156-79e06d1fe2e217b2cf67c0b63878e138.npy +04379243-3af91fd634a5ba759c0ca344f487323e.npy +04379243-2da86dfedc2620b61001738bb075c8ce.npy +04379243-8d4693c04d684e61a3430e4fb40c91fe.npy +04379243-93078952823dddaa5e56625f6688e473.npy +03001627-c4d1ccacb82d854b5a395b344d6773ac.npy +02691156-5869e6c3e9d2748e5ff3feb917a6004b.npy +04090263-8c4b9320b44f674ab09afb04c84cb438.npy +03691459-485a778cb7416a59e810658c16fad24a.npy +03636649-7fc85bf0b0989f864f3443b22038d340.npy +03001627-a78d31c9dd3cea02f91663a74ccd2338.npy +04379243-.npy +04530566-c0c1dce07f56384136da2d0ca22ed9df.npy +04090263-a85ac77659985978d43bb185feff0470.npy +04379243-7aefbd0f95e0e9653b09cd02500a89ae.npy +03001627-40a32b11861df98133ec62ad9f83dbff.npy +04090263-45f97261ea66fefd302ca88f2e083254.npy +03001627-8a2c1a7b282b9bf528ea9c4c28e5ce40.npy +03761084-5a933873658018998312881285c04cb3.npy +03691459-5ea9cb9068520d3bac80666502f7b62e.npy +04090263-ebd426ae34b743f4a50ef3fc203c6ba0.npy +04379243-867e978b82c313693002761e7a3ba3bd.npy +03761084-5874b21cb167217f4d9ddb9a204e75cd.npy +03991062-28129ab65778341d2e18cb49f02ca304.npy +03991062-d919a2a0e84382da148a76a78b10eb5d.npy +04401088-f77811bd35b9215dfd06b6d6f44d62dc.npy +02691156-a39940973102985635fc197bbabcd5bd.npy +04256520-9bcd5c2f575295283cd8f469f840fbd8.npy +04379243-3fa4d59a29c3b506a5e91f4d594e20e6.npy +02958343-6a8982bd53a9bea726149ed5e11fe70.npy +03211117-fbec33bb92e066ade1f2a1daf140ac9f.npy +03001627-8a26a4d0726014065a4867cafb45a61d.npy +04379243-b99bad700049d8f7cbe3d3c1931d32af.npy +04379243-eda01b811087e2f17002d0c486c20865.npy +02691156-388c9b9f1cf24ff84e61a0c2eaaabe87.npy +02876657-c6442bba98ad3dcf5e912b2d2934c0b6.npy +04379243-844199875fab83dd1b17743c18fb63dc.npy +03797390-5c7c4cb503a757147dbda56eabff0c47.npy +04401088-71fb433e386a5547f63375fea17cbfe4.npy +02876657-58279e870f4aec6963b58f539d58d6d5.npy +03001627-ca3670f77268f899febad4f49b26ec52.npy +03001627-73374d8256f79089c308dc58cdbda034.npy +03991062-63313f52b9b69592ff67c12005f72d2.npy +03691459-cb356bbfb74abea2c6573f6ede3fd543.npy +02924116-a549a2bb2ec82b3d7c76a81fb3030fee.npy +03001627-63da17eda9d415b5319c5e90e9cc9126.npy +02818832-d65ddc26ea062a2b9e4965f0106e00d9.npy +03642806-d786b5399e27a82978522e02fc65059.npy +04090263-e3dae8ffcbcc498c935777dcb8deec2d.npy +04379243-e777df6ffb40e3a1853d412328e7e7a6.npy +04379243-ecbb5a30557f659b2c528d33bca1ac2.npy +03938244-b422f9f038fc1f4da3149acda85b1964.npy +02808440-f1772937648f0a1b602f79528bf8e63.npy +03624134-ae7a91523600106259bc1c849ab4dd16.npy +02876657-738033cec99efcf2890766cd24d8fa7b.npy +03691459-46ac6f60aff34c5fdfadbc4d6667b477.npy +04379243-f1c3fdbbba8e36bf62a510b8f97c658e.npy +02958343-9586fcdd105347123ed4cb179e56ad61.npy +04401088-280a42d54e91c6968a02f6ad0818c761.npy +04090263-3592149d9f069cff276c3d558130f8b4.npy +02958343-62fa029fb8053560a37f3fc191551700.npy +03211117-f5fc954736b06be15fd06491ae919ea3.npy +02691156-ac4774b7a9fd06d55e6724a7c6e30991.npy +03691459-88c752eedbb2e133f7f12bd413763dc6.npy +02876657-2fa757f584a3be31a7ceedb2540a32b0.npy +03001627-631e102e9a689339b0ec386df15ab64f.npy +03761084-bfe33a2e7906a28f8405745f8a74e13b.npy +04256520-b3b659db2b29e8201dd80053668dcec7.npy +02828884-2eb289d5829907b9e6ad3e1a394e102.npy +02924116-642b3dcc3e34ae3bafe1d4530f4c6e24.npy +02828884-729c336995af1f96955a1fc933a0f899.npy +04256520-79170ac3bea792317984fb9ec7e40829.npy +02691156-81596cc38eef8260ce9e5ac45c67ec22.npy +03001627-aaba865e99c23e7082db9fca4b68095.npy +03001627-a680830f8b76c1bbe929777b2f481029.npy +04256520-8771f9b7cd6b7c81e724074e69c062a4.npy +02958343-9ab8a24e82568c598c2c132c71e94f7c.npy +02933112-1d898bbd8bbad8f98430b7446f9e1252.npy +04530566-c2d83f3b8665638c664b3b9b23ddfcbc.npy +03642806-2d38fa685e71721986a7e0484f5238e4.npy +02933112-b7dc1e9a3949991747d7c2aae1e5c61.npy +03001627-32c35f86754c0b4847307542345b60c.npy +04379243-f30419ee8ff3edeaae04ebd863e388a1.npy +02924116-139502837db81fafae3dfcb7ed2f0b2.npy +04256520-2c2265c2a9f3c886d0250e0e48027a4c.npy +03642806-a76724964bc58c73ec00b83eb025362c.npy +03001627-9d177c3174439ae1a48e53188865c070.npy +04379243-cfefed4429defd86febdb1f263373824.npy +04379243-2148ddc7d6228861e4dd86e9188294f.npy +04401088-81f527c62191bcd465c46de8aef92580.npy +04090263-cf36df80bbcbc74a6f8398adde24f538.npy +02992529-5814df537b8f1bcde95cd0dc8c2f0e83.npy +03001627-d2597d18fdc3594e1dc59d2adbe5297d.npy +02958343-f31eae8f1f64638c2a9eb0f146e94477.npy +03001627-4eeef58f4015cf74d93768e7b9b1eabf.npy +03928116-7da48dc86606fdec616c08e4715af963.npy +04090263-c4f3ee55952e49ae12b38b1d99376c0b.npy +03211117-72b55fd0ec85d68164ac9dbe3ce7e6be.npy +04401088-f7cb2d921f246c00cc8eea03ea8843cc.npy +03001627-a8f6ca4151f966f5c2e24dd3e5cf2d2f.npy +03001627-ff8efd10f5e6c5c7c6c0380e62f2644.npy +04256520-8a9630332c2cb42644ac83b3e97ad658.npy +02958343-a9e8123feadc58d5983c36827cbbba97.npy +03211117-777a8a1c887779f47ac59aba6f9a1449.npy +04256520-17770580d5c314ea268f063686455b81.npy +03636649-e8e2c055f8ea53a144638317e9e4ff18.npy +04090263-4c883b2d79225a06a5aad165050e534c.npy +02691156-965d457720def9a490b1d6deb98feec6.npy +04379243-9d80e026c9935fa9ea4fe6fd890fcb78.npy +02691156-29b3b168322ac49448d2ba4615e03b21.npy +03001627-c3b6c4563e5f3dc4166ddaef2c2c61ae.npy +03001627-573a615f3496ff4b9b9f2eb77f5e247e.npy +03636649-4cf8166bbaab7c816fd1582e84bf3110.npy +02992529-5f919ac1f790280f563028cebd5782b.npy +03001627-35e77eed59e1113c22e4620665c23c97.npy +02924116-414bbe39e41a8a378e60a499e73975be.npy +04554684-bf1fc3ec1617fb0064f9059364710e5.npy +02691156-7de379891610f5feaf7dd1bfd65143a9.npy +03001627-30d3b99aabb3ce1c4adcf948bcaafbd8.npy +03636649-1a5ebc8575a4e5edcc901650bbbbb0b5.npy +03642806-c0c055ba43c3528a3cb4d5b227cc213b.npy +02828884-602f39fc7534bc4a162bf7725b3fab02.npy +02808440-35a0eec62047815f7454c09d6230a4d.npy +03624134-60d54b7d23edd00b9ed3084b435bf82a.npy +03211117-7dd5b5e5fbb63466ce4aeb2e2812e0bc.npy +02933112-8415b7cd04f981d94692707833167ca3.npy +04379243-5f4ce562f8ebfb00a9f598bc574004c2.npy +02691156-f6b7f7695d091b9bc0909d98a1ff2b4.npy +04379243-4e928377ae98ed8d99e8bf807e902261.npy +03797390-275729fcdc9bf1488afafc80c93c27a9.npy +02876657-5ac30e855ea3faad8884a069d9619eaf.npy +03001627-58891b4cc3fcdd7622bad8a709de6e5.npy +02992529-3d5c17c3e60a168bdaab9d410eb59af2.npy +02691156-cda3cd7f140fe791ed137f17a6d8e3c8.npy +03001627-6ebfa5329b0d1439d4ea3f4c41b1b9bb.npy +04379243-f1b10865243d1ebd77cf3bb06f394ad.npy +02933112-8714a704af18d44b11a97ee9284a563.npy +03001627-1a74a83fa6d24b3cacd67ce2c72c02e.npy +04379243-75c5b314933c8bccea896321ee86caf3.npy +03636649-98636fb562413a10dd999d2409f5212c.npy +03991062-b565a82e10bf41d2131cd41ab5cc1dbf.npy +02691156-2aac22a33893fad8b96ae1a0a8b84ec.npy +03001627-b3194efdf2b8031e8f6e9f07be105c48.npy +03991062-18387bda93f1b17e36b0f2a1430e993a.npy +04379243-178eced0bff71d3653e946fb2184f0c4.npy +03761084-c5143f702625a10dd99265061a435799.npy +02992529-342ef21b1ed9615685feaf23dbe1f454.npy +03001627-d4d9b991ff7d31e8c8687ff9b0b4e4ac.npy +03001627-d57a11d2272f0d9f9c5c7365bb502b0d.npy +04379243-9fa0a6c2c9d102cf2bfb1b91e3f49afe.npy +03593526-5c2079f8089b0419ca2de9a00262030f.npy +04379243-bdd9dbe62272e25c48d90eef8384210.npy +04256520-a25fbfb1c72811d86e4d44229ea605db.npy +04379243-c35a14f84985f92a9856fa70a578baeb.npy +02691156-de1e70fefcabfb6f79be89de816ea2e6.npy +04379243-2060a7a8bc18a63b1cf96a5dc33e37f1.npy +04401088-9cc581a6c5d0b8fcc14f5d127de947a6.npy +04379243-4229653c43599d726ed8927720f5e445.npy +03001627-36ce26e70eace0a3d9b53420a5458c53.npy +04379243-17f3a2945d6550cbf7628281ecb18112.npy +03636649-746b82746c6a02cca5f600ed2cf472ac.npy +02958343-aaa31209c049647d190d02a746694d92.npy +04379243-8d2aac03aac051bedd3adf3090c701f7.npy +03991062-65d2760c534966f2d2b12aa6a0f050b3.npy +04530566-924eeaf6f203fb636be14c19eeda8326.npy +03001627-f1f8e16d23d3a0ba95f2719038c22311.npy +02958343-a583ea14f9da98936436916a86a90ed7.npy +02958343-d1acd4916d3d3b57c48db2ed8f5e994c.npy +02871439-38be55deba61bcfd808d50b6f71a45b.npy +02808440-a969cd5e93fd389b3321831d2245cf06.npy +03467517-7739bbd9890d0e47965378fe06bd3c02.npy +04256520-4b7785695ead572e175255c493aea87b.npy +03636649-f274cbff23bda61a85024815e816c655.npy +04379243-3125b833a365799ac79619984c97c1ff.npy +03046257-6a34103b8186cfe1490ad276cd2af3a4.npy +03467517-32a337387527f39193f0194265a9746c.npy +03001627-678ae2d4a386f4e4d0250aa1ac19fcf9.npy +03001627-e955b63a4bd738857178717457aa5d20.npy +02924116-cbe2cb74dbfcf7fc4aa94fe75fa150ae.npy +02942699-97cd28c085e3754f22c69c86438afd28.npy +03325088-1f43546db1dc2912f38c4a12750d961b.npy +03001627-e696f4c7cd88b8b52ff834514c92e8fd.npy +02924116-83bda5045aca68671db751af8df870f4.npy +02958343-913b747502e92aa34d1780ed2b3fe073.npy +02876657-c5e425b9b1f4f42b6d7d15cb5e1928e.npy +04379243-94fa2ca1212536d84a8050bb0dd3c541.npy +04379243-701dd3ef213c653b39401293115e30c.npy +03046257-4baba9e85a3ae76bb030c2da12a8fb31.npy +03001627-3109a0b9f9bc5fecb4cd1bd556007aed.npy +03691459-4f42950d660bffcdcdd18be3aeb2d66e.npy +03691459-6be15f4f6dd64490d747b49524a1246e.npy +04379243-3a6a01d03f28cf83664b3b9b23ddfcbc.npy +03710193-a4c11b601dd4a63bf8c63fffc82e8907.npy +02691156-b6dc4ddde769573df551b6c3f174499e.npy +03001627-5607b02869c1f8a019fb4103277a6b93.npy +04379243-e0f8fc5dc186a597a636371b2023a251.npy +02933112-703a95f9e0f51654f51f77a6d7299806.npy +03001627-8830354625df010037b71c02ebe8cb4d.npy +03636649-1d963d5c54613202b0aa15078ea6f391.npy +03001627-60ec0611befb7102dbca69f936e89647.npy +02691156-3feeb5f8ecbfcb4ba8f0518e94fcfb22.npy +04530566-c6e127fca727e2be3d312efac35b8a09.npy +02942699-7077395b60bf4aeb3cb44973ec1ffcf8.npy +03325088-45374c209823108c1036b9adf51844e6.npy +03593526-e4a868a10e10dda4befcf48d5b3e17b5.npy +04256520-52dd0fac460adb45e2879d5d9f05633.npy +02933112-226873c8d34e38286d53ab0fe94e911.npy +03001627-c7da2d72f9927f1881dff5c2e57ad46e.npy +02876657-970027a2c9f1de88c123147a914238ea.npy +04090263-54e1ce2402c4f754aca4b8a57632be04.npy +03325088-13b0cdb40fdb8e3c979c556124bee033.npy +04401088-a41e693828a65064e565c13e00bdea3d.npy +04379243-718df0ef71586a6ecccd93cbd8dfdb84.npy +02828884-5f8f2518fb850b544bf6fb242f907340.npy +03001627-f39d429ab98d5323a1a6556bd50a3110.npy +02691156-d5f4e2228e3fadd2aa6a832b9db7452f.npy +02958343-2881a09fc1f3d2be9dab4604fbb1a7b4.npy +03691459-acf4fb74200b838d874179120554c44f.npy +04379243-d151d9f45d8b14536cd661fb5fd95741.npy +04379243-28001cb70c38f19cf32b6091d9628440.npy +02691156-ed738ba28cd73714bb0f4bdf8821663a.npy +03001627-2137a8fcee12e72d19fb4103277a6b93.npy +02691156-4b4782c572fa8b11a20c7111a5d0d7fc.npy +02924116-9ec0c9cf9d90433035dc35aa11c480b8.npy +03636649-d54d7977d760f4c3bd16d4490a10a752.npy +02958343-1a56d596c77ad5936fa87a658faf1d26.npy +03593526-c369c35d54a88e56fe572c9a3e59d718.npy +04530566-d2d3ab44415a3d3fef5e991e1c32e94a.npy +04530566-52fb0261b905147d2fe023c7dc3e5231.npy +03001627-a58f8f1bd61094b3ff2c92c2a4f65876.npy +02691156-c6bcec892954942a83855ba2afe73b0b.npy +03790512-e7c8dd1efb78b8baba85a673915bd3d.npy +03001627-95e2f1fb6be241b4742728b30848ed03.npy +04330267-b94b76056a072784685e443e0ea51d93.npy +02843684-7f9bea8d412c57cccd777fa0a7548d4c.npy +03467517-401ff6021157dee293f0194265a9746c.npy +03001627-71b01320c8e9dd60f7628281ecb18112.npy +03691459-5f525c37469b0437feae521e94848af6.npy +03001627-d29d2c5a1b35b85b40f0ac0fb9a650d.npy +04379243-fd8cffbc99f7388e4f2b9e837678be87.npy +04256520-4742de1edfb9462a60fd51b2fec8dcce.npy +02691156-71bb720c33da689090b1d6deb98feec6.npy +03001627-e82136f5c8b2c3156cdce1333d517d16.npy +04090263-a1a89a8cc3557d373fab9f1733a68f6.npy +03001627-cc811f0c28012f493c528a26a44a30b6.npy +03691459-e2dc092a4ef62c09d207241113bee327.npy +03467517-661c603f9f7645f0d50e84209ea2fc33.npy +03991062-d61c8ea9eeb02397dfe9cab879fd37e8.npy +03691459-33d9a210df86a437cb3c1170309e6b12.npy +02828884-dc4857179ccd30ad5067eac75a07f7.npy +04530566-564d88a1c49ba742473f10e6caaeca56.npy +02747177-fa5f703728fd7d5ff4fb4dee5181bee.npy +04379243-4eae659d4bc093465f675b8d0bab4126.npy +03001627-a0f6ec9aede1d9039bad36d0a57d0adf.npy +03001627-657790bc7fd16326c132086242d50af2.npy +02691156-5da145252e095024ee738cc95b5ae8e.npy +04379243-6a311b1416a53f87697ad7b0fe6813db.npy +03636649-fafef4866d1a74f3fcb8d8c6d4df8143.npy +04256520-d2018df95fe894c388acc944857403a5.npy +04090263-7dba6294173994131226a6f096e4f8c8.npy +02691156-d0614abb68caa5ddac7f1a00b76bd166.npy +02924116-d0cc83d6fded7f1cc98c13d6112727de.npy +04379243-3cdf9215a9cf0ff5855931d119219022.npy +02773838-1b84dededd445058e44a5473032f38f.npy +04379243-ae2a8d605b8c4090acc95948d4efa8e6.npy +04379243-ea4fbea57b0b7b677c0ffcaa63ee0500.npy +03636649-2b194d6bed8daa82c0b2dda5ff15ea28.npy +02691156-a9b808a446c498f475df24d58e852c90.npy +04256520-a92f6b7dccd0421f7248d9dbed7a7b8.npy +02958343-17c08a4bf8224f47473f10e6caaeca56.npy +04090263-a1f65f97e61094e1202be79d8b285c1e.npy +03001627-2f0a94efe6d1da7f8616812464c86290.npy +04379243-b3a77356e56d7c9a2820d27b806f8454.npy +02691156-35f43f566f2f14651713426437a9f7cd.npy +02691156-1c2e9dedbcf511e616a077c4c0fc1181.npy +04090263-262510dc5b4cd7003d48ceeccdc87fcf.npy +02942699-22217d5660444eeeca93934e5f39869.npy +04256520-fb12015e8f705d901f8d8332ee17945a.npy +04401088-1b1aaa9a95ae964746becd46a4907f38.npy +04379243-e4f206e9aee482a15510d59f3ab1ed64.npy +02958343-36c4d31969a8c1111a31578ee9a364cd.npy +04379243-5b546ef5de5d10f3ecc9201d3d846bc1.npy +02933112-ac980e21cd4f41eed5076afb08856f4d.npy +03001627-3b472a135aefdc2943a0e2e54f038a60.npy +02933112-455a583e41579db14da5feafe6f1c8fc.npy +02808440-124807f04a76c484c62bee40dcdc539.npy +03211117-faa79bebcefea4256a4b4e0348cf692.npy +02691156-b253d5dd187679c74a9ee9951c24bdb0.npy +03636649-3d82ed43806901b4df9c597227d75069.npy +02691156-e090eb003856ed12ffbd931fcaa69140.npy +02808440-906d00e5cdd0f23437b3df14b1086ae1.npy +03001627-ac84a2eff5e6a64347598b39fd1f6465.npy +02691156-36dd57178402cdf2afd477f714c68df9.npy +03624134-8f61777bf6b57fedc13545c5b1a2e607.npy +04379243-9825c19c22c97af2aff4f3612743fea.npy +03337140-9633dbd1bb8c11134c3aee8e9d3a6ffa.npy +02828884-e8480e72fb656057656a19d1d18fdbac.npy +02828884-b274f40cccd7e067f155d75bbf62b80.npy +04379243-42018e077cb76cd3948fd22ef0eabdf1.npy +02958343-afeb58fbf8c45924cdf21e49b4ebfe68.npy +03001627-c570ee85ecb0e514492d9da2668ec34c.npy +02958343-f7c84d18011f76fe5e18329bdc55fc9.npy +04379243-a333abca08fceb434eec4d2d414b38e0.npy +03046257-313da995b26c1ab2e18cb30f79057c27.npy +04379243-14146d1e359f998b19b278d00a891f19.npy +04379243-410ad32a9cd5377458c429c80cce21ba.npy +02828884-e7536c6b13e44b9df4fb4dee5181bee.npy +04256520-af9245138b29dd19c8687ff9b0b4e4ac.npy +04379243-d458bc90f183605119fb4103277a6b93.npy +04379243-2d1d1b66d6e268d8c67c3af5181fac2d.npy +03593526-483b9263192747a3a4c322790a683350.npy +03001627-bae518da1e709e83596f70d1d7edd4bc.npy +02992529-21056b8560bdd1a9f63375fea17cbfe4.npy +04530566-1cd39434382e08ab8510ad9ae6ed36b6.npy +03636649-d982697f8c20b769aec118775e1a3eb4.npy +02828884-6152fd8b7b5b10df436455e65b78c0e3.npy +02871439-31a1fd4a86320f332c45f75322191dd7.npy +02880940-782aa72e7f14975b39d764edb37837d3.npy +04256520-bdd7a0eb66e8884dad04591c9486ec0.npy +04530566-a9737969ac039c9323dfd33205b06c1a.npy +04379243-24672a92667a51885878d4300758f637.npy +02691156-8383c4706c60ea2fc1006ed55bc1a3fc.npy +02691156-a0359a8d86947a2049fe495b383f9f0a.npy +02691156-e8de6c58f4a772d771d03b466c72ce41.npy +02818832-4290c1a305f46cba4cc1952ae0d6e81a.npy +03710193-4d1064364236d92dba999a2694e75319.npy +03001627-2bcf0b0586570ffe6c63b8b48495261a.npy +02691156-3c109726e03fbac4ace5721ccacba16.npy +03046257-1926de4988741ad81b17743c18fb63dc.npy +04379243-627f4b1f48b6190b9341eeec703c4d4f.npy +02843684-a448fb21ce07c5332cba66dc6aeabcd4.npy +02828884-ba8e193569ea391efcd6646576d2dbbc.npy +02876657-bfe7d0102dcd0deff43af5716b936459.npy +02691156-57c4a88a7b2e10f14c971d5c531b9d1c.npy +04468005-ce0cdf24724d4339c74aaa8fec0125e1.npy +03325088-d185710a223fc5303321831d2245cf06.npy +02808440-30d2a4ee211c4383125fa9990176f0d5.npy +04090263-f80ec2ac6f6e851bca7250d90eb506cf.npy +03513137-8d50220bdf7be7b92d356a2793fb4d69.npy +04379243-6686819cbb40a3502aa2b411702b495c.npy +04401088-6753572868705eacdd043998582f5fa.npy +04090263-1c6680f257e5c97498e6e8ec38d9445a.npy +02933112-4f53f0d00d3491f35eea3e3d89293379.npy +03691459-c2bf199ce5a022a1126d510cb8dd3d9e.npy +02958343-383a4d1ee8022e9a61fd7e090d4d0d45.npy +03211117-a568d8aaf2b587a2f27bd2175000097.npy +04379243-1d825a5cd1884610b08fe058d24e7e61.npy +04401088-52d1db0a460723949582767760266e88.npy +04256520-6c50fa0b3f1bf58e178548484b14e6f6.npy +03642806-6d88f11ac37f07a86a7e0484f5238e4.npy +04379243-17fd058dc352b9d11191025061735ea3.npy +04090263-17e2291c6ef778034b349e4b3dd5565e.npy +03797390-3d1754b7cb46c0ce5c8081810641ef6.npy +03046257-b6fa9b0aaadf6c89a1b95b258b5f7139.npy +03790512-d9ae53fbacf92182b37378f3c85478b4.npy +03790512-e24b42fe6296c613be23697565633b75.npy +02958343-bcc3a1e280cb9153618e9d35559b7aa.npy +03710193-31f30fad514955060d6908d0bcf26ba.npy +03593526-c795ed7d374e893964558a1c6a2a9f11.npy +03624134-4b57d6d81db28f8ccc34b900bb2492e.npy +03513137-73b749a0704ad08398ce5d19cf9bd7c9.npy +03001627-e642ac79a2517d0054f92a30b31f64e.npy +03467517-ff82ee8b58b03dead5ba605b3c01b057.npy +03636649-46dc3daf02f51d09490ad276cd2af3a4.npy +03593526-e81b2e879acd96f5664b3b9b23ddfcbc.npy +04225987-d303055e96cd59949da15808191f1405.npy +04379243-d578287c4a9452efa9af104529ef47c3.npy +04379243-7b50357760759ad58a70042c3e4356d2.npy +03636649-200fe239e1eac6a2651636b7e802cd3e.npy +03001627-fc131dfba15fafb2fdeed357dfbe708a.npy +04379243-7f29e2e6496ee99aeca1c556848f5db1.npy +03001627-e6ec608ccfb38d6247928239f46b6ef1.npy +04530566-f61132a535bd608c85f7a3de54751f1b.npy +04530566-eddb01638a0c8be89c9cb44b983e47a.npy +04090263-501312760a03072cd9deb3f829cc2475.npy +04090263-556be45ad32a1f18726ef46500f4c772.npy +04460130-b7600836218f2556e86e8111763264e.npy +02808440-e1bbaff08c5309a6412ac8cccf0c180f.npy +04379243-c7872212279d59eb540291e94bc8ddc3.npy +04379243-9e408f772321bb1920768660cf080d12.npy +02958343-ba03db3866faadf0dd27b2ba4335b978.npy +04379243-df166b0407fef7ae4b3c42e318f3affc.npy +04530566-852a4a82f02d64fb31205bd848315f04.npy +03467517-3bca4bb40d2b8cf23b3435cb12e628d5.npy +04256520-3477f074d38e57821a61e560ab9e3736.npy +04379243-10b5723ea035cb047464e25da6d2e90.npy +02958343-e333b5c405fbbb98457cfef9186c20c7.npy +02691156-9759b89377e9d3f454eefcdc602d4520.npy +04256520-6cc0e9deb3b519eba347d2a9b736d5f.npy +04460130-2ecb6add2316f940ffad7221e3cdb3ef.npy +02691156-1a9b552befd6306cc8f2d5fe7449af61.npy +03467517-e22fb9fe7451af10afaf9bf875738c30.npy +02691156-f3463eac7325b600d01b5600c06c528d.npy +04468005-b4d66e95bf17f53e9954eae9164faecb.npy +04379243-a8ff038540e5ef35daa3ef8c2a95fdb6.npy +04090263-c2ea3ff598b98f3f4528f6465fa2466d.npy +04379243-8e07fff2ae8a542051ef8c8b1fdb41ce.npy +03636649-2f345ba66e683c2bc5a208307819a3a1.npy +02958343-d482029701573b9a43fb5689d5ce14d3.npy +04379243-4ebcc39496c64f0a50566f53e37b2171.npy +04379243-b9886dd3c4a651f3664b3b9b23ddfcbc.npy +02691156-82e50255f14e7d9e60c9b6e4c75a092a.npy +02958343-bf523e37ff88cb10e23d60a1b706b44f.npy +04379243-53ff581b91740efdfbf96e9694161951.npy +04379243-5be46c0c35d3cff2297936c81e7f6629.npy +03001627-e08add655395ce8df51f77a6d7299806.npy +04090263-d16ba2810dd8489cfcace4d823343363.npy +02933112-381d0eb848eaaa07eee615e75bc3b77.npy +04379243-bf81d46925ba8ef7ef6c510e24348d3b.npy +03001627-92f79b8e45269847f0efa341b439d741.npy +02691156-a0c9b929b9a57fc8f0ea53ad10b4d47.npy +04379243-1f8205bc25d4d5f21771ee930e861b13.npy +03636649-ea02a7933158caecfcb8d8c6d4df8143.npy +04379243-f585560965413925d706ecb3379aa341.npy +04090263-c6567e2f9896825b49352dd33f95cb9e.npy +03938244-cac45c821aaa15e577ca5eb24dfd03ad.npy +03636649-1874da9ffb42f3ee990f8ee13a15ddf6.npy +03691459-72ecb9a2d25458ba8b4cf2c9fe044514.npy +02992529-bf15900bf5afb946b35f223cefd97829.npy +03001627-7ec876482b8d80ce5a8ae8f7c307d01c.npy +04379243-48dd6b701f9909da6a8a13d57e4d05f0.npy +03325088-2b06f6839c637fb54d7082b34825ef0.npy +03001627-2b6cbad4ba1e9a0645881d7eab1353ba.npy +03991062-4a2a3ef283ebab579e1e8b2486a6bb4a.npy +02958343-692001fd91d8328ef421855cd210fbe9.npy +02691156-d004d0e86ea3d77a65a6ed5c458f6a32.npy +02876657-1349b2169a97a0ff54e1b6f41fdd78a.npy +04379243-1bc8eb160194017cde26427f80dbcfad.npy +03797390-6c379385bf0a23ffdec712af445786fe.npy +02958343-fff64da26715b520e40201fea1ad0f1.npy +02691156-c80e8a74a31c6156bac66f0bb664359f.npy +04090263-e55bc0a1b57acec4a7dd22c0aa3913f0.npy +02958343-bc7ca9eec356ce21ad32396cbf7f43dc.npy +03636649-6dcbc7efc9369de386a5dcc6ebde687f.npy +02958343-b56bfe0649294ebecb02238be5da228.npy +04256520-babdd63b18d73a196625bd63cef94df1.npy +04379243-3950da9e4a5083d7b4fa97f642d1a681.npy +02828884-132231578d6084cacb2a965e75be701c.npy +02933112-6e03d2f837cfeb8ee75ac485a81d5fa9.npy +04468005-5ddf4835ed5640e942e61fccfc5d24ee.npy +02691156-222c0d99446148babe4274edc10c1c8e.npy +04330267-cfa1ad5b5b023fe81d2e2161e7c7075.npy +02958343-f94003409831db21f2cdad303f49c9f9.npy +02828884-5fa51bc60906cc548270ab5c6ee87257.npy +02880940-fc77ad0828db2caa533e44d90297dd6e.npy +03691459-405db2cef5b41756fa16d3c3138134ae.npy +02691156-ed35478403ae873943cf31d2bcc8f4.npy +03001627-3c17fe56ae05d51620768660cf080d12.npy +04379243-279c8601278e827dab610b0c94236463.npy +03001627-52f0514f5c38bc96f51f77a6d7299806.npy +03211117-8ec017a94a41b097b1b11b582321dc3a.npy +03636649-5eefe57de9ad8b6114038d588fd1342f.npy +03636649-873aad4a222d541a91c2792fcdc1ca8.npy +03691459-9fbb43c7437c1bb8a2ec0446d32ce69.npy +04090263-a4001adbd9f3443d3a9a4f49cc5d8efc.npy +02958343-970ebe02365dd05bfd7e1079f2e4956b.npy +04379243-af2feda1ed22097d6200682ef9a0dc75.npy +02691156-57a57f639a3e636d914c075742032f6.npy +03593526-85ad6844a52ec08cdf7d84aa9195db06.npy +04379243-9daf7804f32079f7b1973049b9d84541.npy +04256520-9ac58aaf9989a0911f98c0761af40e04.npy +04379243-9b042d709402eb968dd711af5650bdcf.npy +02691156-ee672fc1455b9fc43523242fdf9b75a7.npy +02958343-6d714f7b7170a581da8e502a3c6cb4fb.npy +02958343-fc521be0cb604c1aee4687e8f2543e.npy +02958343-3776e4d1e2587fd3253c03b7df20edd5.npy +04379243-89cb658542b25e1f4671d97b0fd17f51.npy +03691459-5f9d75a41d264b9bf4fd8600b18b879c.npy +03001627-fc6129a9310ba34c645311c54e2f9bdc.npy +02691156-8da05b28d9b2e2fddd01eabba9d45203.npy +04379243-9bae37b85e2c71ae62158b7ee658e910.npy +02818832-a84ff0a6802b0661f345fb470303964a.npy +04090263-7a2904413d538525bd337aeee16061a.npy +03001627-9191445d1c215cf09a8ef44e1d2c5b75.npy +02691156-94981062a6f3748844750bbcfe7b8fee.npy +04090263-1a6aab87fdd90323d810dcd63f342aca.npy +04256520-56cafcac4df5308d35dda488a4bbb1e1.npy +04090263-32706617176faf4a32dee48b245ce100.npy +03001627-bb48377bba20a712a45aa09d68b87656.npy +03001627-99d5fabe3b8258ce9d4d5dcd2cc33826.npy +04530566-8cbb360233696342309e1bb5976741f2.npy +04379243-20ba57a048c518e5732649bffe80ba61.npy +02958343-34d28083d9f0c31fa2e586b3e41e79ff.npy +03467517-4e982d5baec36536c86b22832615248.npy +02942699-5265ff657b9db80cafae29a76344a143.npy +02992529-ac6f6437f9e63981b6d41c42f7ade8c8.npy +03001627-63b5ef650f1020eb7fa0ee8efe00d1ee.npy +03624134-47f56f25d4582327cb77d096d6538915.npy +04090263-e65080fac483ce98f0878b58b4e887bf.npy +03001627-8da97531717192fc3215145fdcd9052.npy +02958343-787a38da42c2026ec29f776eec462c6d.npy +02691156-9afe827a622d8ca28699933784576e73.npy +04379243-1370db5c4f0b84026aa35752fcfa44c0.npy +04379243-938e3529b774a91fcee558e7a5a02ad9.npy +04090263-815a2488eff62e6ce641b9ab504917bf.npy +04379243-23acbe1f91d445f91ca1c7e576bee6b9.npy +04379243-4faf91d6e511e153b20565fa9224214d.npy +04379243-94c98b1e67618bd234943af333340cd2.npy +04256520-828940d7035de09f62e682c9809bff14.npy +04379243-1804dd6f5c827c1a4bf8d5f43e57b138.npy +02808440-b47731bf94a8f64bd765b52819c487ba.npy +03790512-b767982d38b5171e429f1c522640e6f0.npy +04379243-2e7a728b482bd2d453e946fb2184f0c4.npy +03001627-53ea833512f2235319fb4103277a6b93.npy +04090263-2762292f3f5629fe12b38b1d99376c0b.npy +03001627-f40332e31675a54d492d9da2668ec34c.npy +02958343-e1134a7e936b516fb1bb46d2556ba67d.npy +04379243-aad7eaccc93471d6ab610b0c94236463.npy +04530566-6189947ef21a4f4b7f6ea2f642fdf12a.npy +03001627-7eb7574764b397c3e87e9b3f41906a3d.npy +02691156-4a11239139c5f81762b600da24e0965.npy +04090263-ed939aa2573fc0fd3b5abd28a9df8c72.npy +02691156-e218bb755f35da1bb4cdad9a5bf52dd5.npy +03001627-60c328c57efb2a69820018801b237b3d.npy +02958343-2a2a1822fcf96394ed3696d854eee1ec.npy +04468005-814e850ce8c5498b5f73a346378dad81.npy +02992529-bfba0e8cdd5462e4fe103fdbd20df6.npy +04554684-71f26627a3eece3e151c656115fe24ee.npy +02871439-8007cf8349381dada5817f81a1efa3cc.npy +04379243-edb32ed999f08ed4a12cedd896805aef.npy +02691156-737629e185f4c45f99f30106e678cab1.npy +03001627-3a52c8cd645f40b4670786463e520f4d.npy +03691459-66baf7b7b4ce43d7e50f6aaad9a07bc.npy +04256520-572da8680677fe8937b2bb75885cfc44.npy +04530566-89ca399e4ab129a60014fe834c82238.npy +03001627-5e598a82d584211d2681d406cc3868fb.npy +03636649-aff71b0d462342aa4bf6dad97590bf33.npy +02958343-17bfc66c6bc0a99d68c415156b102065.npy +04530566-d0e7102863fdb18fb90142192ec795d.npy +03001627-64c80a33436b8a84541e733f245fd038.npy +03691459-217733447f1ec818c066b9622c005c53.npy +02933112-bbbd4de3e7ab25ad80d6227ff9b21190.npy +02691156-5011e352793d063f26360e1e29a956c7.npy +03928116-79d07ff15dd24e398043364ed41c1a79.npy +03636649-26bb7229b024a8549b0c8289d51d981b.npy +03636649-4916f793d87dd184d42b9650f19dd425.npy +04379243-53bc49f45214d8d6ea73a64ae4344bc3.npy +03790512-ce46af9eb70d91e2b37378f3c85478b4.npy +04530566-5b542fec3cd96c872e28b2b96a4985ba.npy +04090263-39219da571e93e9825c70fb1df3f879b.npy +02773838-133c16fc6ca7d77676bb31db0358e9c6.npy +04090263-bb46900b4f00ca7292659aea259f7c91.npy +03001627-e22e9f5088838675a72559fc4f86f700.npy +02691156-1435b52348569ce1bd46d022fd7d80aa.npy +02828884-b7c366d9ad90bb8a847d09fbfad470bc.npy +02958343-29b714c4aee36c9d6108f064aff2426d.npy +04379243-df39a8c8b7ce47a25938488ff499d96a.npy +04379243-e94ed46ede91eafa50f1b9873bba60ae.npy +02828884-2d1e8858446d1a32d2b12aa6a0f050b3.npy +02924116-1004ae81238886674d44f5db04bf14b8.npy +02691156-5ea68e6edd123801ad75fc64c51fb188.npy +02828884-e2be5da815f914f22250bf58700b4d8f.npy +03001627-71b1134533fb33f489452a0032ea575.npy +03636649-375c6cce56f3967ed323d15bd4f8b2d.npy +02691156-b9c8536f91ec3bcd3aff44a57f77b39.npy +02954340-6f93656d083e985465bae2cb33eb4baa.npy +02871439-6ebfa572d4501a9b680acf911e95b6a6.npy +03001627-cbe006da89cca7ffd6bab114dd47e3f.npy +03001627-575cb36c87cd4896c5ae524fbf4f75e1.npy +02691156-4a300ea7cbe3ae58a42c49797afd1f5c.npy +02808440-c1b1aeff3537eacd3321831d2245cf06.npy +03759954-c7dc827236dd6d0f67964ba700cd97f5.npy +02933112-ae20b4fa1b552b62614d87bbb5364f6a.npy +04090263-2193f3624198ede23f0af1eceae2dd4.npy +03001627-aa300965dead4fa33f09c790ddd20f8c.npy +02958343-1641efa5c92514d86c4f4dbcda5f2fc0.npy +02924116-dfc6fa5fce5d47cfc42dfacd196ded31.npy +04530566-bea0e3452120318b8c954439655c356e.npy +02828884-5a074a3422d783cbad7b4c3c92e50b84.npy +04379243-14f3de4c23d535e92c528d33bca1ac2.npy +02691156-58d23c8bf0902cc590b1d6deb98feec6.npy +03948459-2db5da73d177fe773ffeeaac0d1e84d4.npy +04256520-a7be35f955f8d45419fb4103277a6b93.npy +04379243-2e7cb2cbfbbb4d002ee19ebe356c2dcb.npy +04099429-c236c7fef78dae828457d30df312d8bf.npy +04530566-66fcc3b9b53e0564d619719db5285416.npy +03211117-fa48bff74086eb8ad69923e104170fc5.npy +03691459-f4308c030df7d027ced68ac20944148.npy +02958343-1f416598fe329a88b1bb46d2556ba67d.npy +02958343-f33b310ba5e68b82becf71e2e014ff6f.npy +03001627-893e3f15f023e9abdba08b82bf5c2f3.npy +04401088-893ed9fc527a8329d3fdfcd95fe3518a.npy +04379243-393d3977af188cd7798c257640d6867.npy +03211117-ac81f325fbc993d3eb42617d0a1c53b.npy +04379243-b3b8817a8b781fce2e4761573669341a.npy +03211117-b0952767eeb21b88e2b075a80e28c81b.npy +03636649-555152a8e9cdbbe41afedc87fe387fe.npy +03642806-3dd1b4cdc6d3b33f676394b063daab40.npy +03928116-4b18f31c04e6d31e76ef7e6bccf9fa31.npy +04468005-88c8695f2796d660dc14ba0818ee5cec.npy +02808440-4a41317b5baa2d52c658b057b1ffe06f.npy +04379243-f17661552a06bf85282d5d529f9dee5b.npy +04379243-824e0f5fd086565a4eee3420590dc822.npy +02933112-8e9a51408589448bc59350d819542ec7.npy +02992529-5ba2137f5131db06219e978e6e16d30b.npy +04379243-edbff6864a97cd6aa1b5ceeca96f6fbc.npy +03001627-aa412e95e1f9c047d9b53420a5458c53.npy +04460130-c2a2b8c3b9884d5095c46bada0d9437f.npy +04379243-8fdb0cce840b2977d0edc2a586731adb.npy +04379243-89bfd0ececc5a00b6e861001bc3826a.npy +02691156-8eeb9f69fc9ef1b0b45fd154bd3b6957.npy +04256520-3a62563bdb750b988b83086412477462.npy +04090263-8fcd6435e32af3f729454b854b87bde8.npy +04379243-b699dcd9de34b5023002761e7a3ba3bd.npy +02958343-692a66739b9ed5e14c88b7369bd6883d.npy +03001627-5d9906be39e2ee012f24668c019c448f.npy +02992529-8ede5d8c00e10a2ff35554ebed2bf2.npy +04379243-e1bdefc225831db150fa82c2f036109a.npy +04379243-43deedd337b00bfcf84b0be7f50940eb.npy +04379243-4fa88f9362f216481b99c25df49800ad.npy +03001627-40567b0166658623b80ea7d1a9683df8.npy +03001627-92e2317fd0d0129bb910025244eec99a.npy +03001627-a20760333defff73d2ef7d159eb54508.npy +02808440-a46408e74eb7430893a9c38d07133147.npy +04379243-3a0bb4b6c7245e0435836c728d324152.npy +03467517-2c2fc56385be92b493f0194265a9746c.npy +02808440-99ee0eaaa7511e2344221bef0fa3c36b.npy +03046257-8d127c73436dba6741ca67b3a986966c.npy +03001627-d7e26a070ee3b35cdf6cfab91d65bb91.npy +03991062-7a931ec996edbfeacb2a965e75be701c.npy +03691459-91d876c2c51a81797ad9e38d6dd6575e.npy +02958343-5dbed4f17ebc271a3aac79fb478fb6b.npy +03636649-4b7ba911d5504501b320860840f0eeef.npy +04379243-5b621e5fe06ebfc7b71f7e05ca67f031.npy +03991062-10433e5bd8fa2a337b00c7b93209c459.npy +02691156-830f3e14a8882ea0f4fb6842b3610149.npy +04379243-15fd9085d9aaa0fa43ed4f51d7ae210f.npy +04401088-75d6dd4112038b8359aa4ad538fd90de.npy +03691459-2d53b9798c7ffe7a6e55c6c7c80df9dd.npy +02828884-cc5d0040931906ae81faebbdea6bd9be.npy +04379243-1fe846f8b74b5fc66b510e987fd42f59.npy +04379243-d1b97ecf63191e19c19a59cdcb309b91.npy +04379243-9b2ee4ca099fdcebb4c161851ed2b4e4.npy +03001627-ea5c19a6ea9b13719fb4103277a6b93.npy +02958343-d9b2fc71e809140bbe40bb45ea25a041.npy +04379243-5aa3a0e7ef40f2d385c2318bffd77ab.npy +03642806-7d9e5d105941adf17dde8647dee63fd8.npy +03928116-96a3da8cbaa34575ca5363ae2c24c8a9.npy +04256520-d255253a4af43b4d4cb1d8db6be39c65.npy +04379243-982e83068fcf2f26a0b169584d4ab1c8.npy +03636649-78dc5a0c38d5aa2fe59f529cd1b6faa8.npy +02691156-cdb17eb7b14c83f225e27d5227712286.npy +03001627-8afad2d7f30c9f02ebeb1e6a8111f53.npy +03046257-46320beb087955da408e862e5daf1757.npy +04330267-298fc1492df14dbc96c91a9093ecb199.npy +02828884-ad9a12cce63df1c9870f22c94729669b.npy +02933112-187f9c840611133b7fa41e06a7f4a88.npy +04256520-3637b0d6db204c0414038d588fd1342f.npy +03467517-8f974059b8ddb17b40dcbf42c0e79c66.npy +02958343-af834c760bf3c75043f0e92e826556b8.npy +03211117-8bd568244e513b09c3a0fa8ea839ee26.npy +03001627-73379ebbbac81af13ee8e30b29f70dfc.npy +03624134-a683ed081504a35e4a9a3a0b87d50a92.npy +04530566-bea93ebc1fa965ab34292139f0435d74.npy +03938244-f3833476297f19c664b3b9b23ddfcbc.npy +03636649-6e268cddf895c20ffcb8d8c6d4df8143.npy +02691156-e841e17e3256acf38699933784576e73.npy +03001627-6a5ee2ac74c81e9d470412e9b69c8933.npy +02871439-b07cf8ae0b87b01ad8c063432abc4bb9.npy +04530566-39b7b83a42af6d83ad0582c282e8474.npy +03593526-76677da63039c6d9e6a735b744b69aa4.npy +04379243-3ea744a70049d4edbd069216df40b64d.npy +03691459-4d74d8c3df7a85051d225d751745cd28.npy +03337140-4a914da1b8325f1fb2029d92310f4aeb.npy +04090263-7eaed6f53420b4ca51cfdb4c9f126c12.npy +04256520-945a038c3e0c46ec19fb4103277a6b93.npy +03636649-a7b9dc38c80e86fbb13604bbce4eb6a8.npy +03001627-e507b4d0aedf8451504721639e19f609.npy +03636649-708aa847cb730f07fcb8d8c6d4df8143.npy +02933112-2bda2392d5715d16c59350d819542ec7.npy +04090263-4344ea073ad91f7ed87c63d8b3018b58.npy +02691156-a799568755357be8a07b3b853565360b.npy +03467517-904838f2757b1534b90a4f86cdfdcadf.npy +04379243-4a3641784a9ecca04fa8d6439169bda4.npy +04379243-8cc6cd529cbd74b5769cf9dd5d8f2768.npy +04090263-8978ffe2b8b770c363e66191800dfc8a.npy +03001627-c65cd2f7588764872b70eac6546e93fd.npy +03636649-6c0b3b0c6bc6eb97862d7667d873e591.npy +03001627-e6c11fed9469141ace8fba09dd640742.npy +03467517-fa82872eb8c9017f343b0b12983b9982.npy +03211117-e46e45f94470b45ad1924b802935a37a.npy +04379243-5e8f470250f92a0f597976c675750537.npy +03001627-19ce953da9aa8065d747a43c11e738e9.npy +03046257-f18450425e69b37b76e9713f57a5fcb6.npy +04379243-894e095c7036c8411933ffef19678834.npy +04530566-c2b394de8407988bb538a15c6737824e.npy +03001627-47c33af88f4926676213fd2f62884e62.npy +03211117-e6585f8ce05ee27cf8bee374511267d3.npy +03001627-f5490bd0c64cd42b9ca5a26dad9fbaa.npy +03001627-49110d0e41bb90b8b8e1b99345a5afd4.npy +03046257-ae570b0ec2b265cd14621506c22882a0.npy +03337140-80f1221d6a11a5dd4c3aee8e9d3a6ffa.npy +04460130-759121663da89b5e7cb17ae4c4c3b9d7.npy +02924116-4273a55343037d40fc319b95010c3346.npy +03790512-90a521e0def2631fd5dde04c96fd8146.npy +04379243-30c88fa790ac14f750d31060ff1b5551.npy +02958343-f045547c7c6e5d0ae74479f4823fa2bd.npy +03642806-f8028a9b5e095caa8051d8192a80578f.npy +04379243-8cb5ae6c0998479a8cbb8bac2032149c.npy +03593526-1c17748268b02c1c8da95317eef6e82a.npy +02924116-98b171ff0df70474ced1f1f28cdae790.npy +02691156-9dbc0aba1311e7b8663e90eaf6b4ca52.npy +04530566-e5ede813e9f07ee4f3e39f2e17005efc.npy +04379243-66517b894b9ea3ffe22ea6d770699e4b.npy +02958343-657ea4181e337213fa7c23b34a0b219.npy +04530566-daa873aacd7960d61d2d2f3b717d35d5.npy +02958343-36ba5d46f034ec58236804c5ee26a2ab.npy +03001627-d02eda9e00688d71d0c63a304a95442d.npy +04379243-1d06d1bc8f10c45ab1732c7d45a02ba0.npy +04330267-44fe1c2abda6a722e793cc5433bece89.npy +04074963-2c6493d31849c15a75f1efca97bee05a.npy +03211117-b6070e5c314eb16033fe3b9714de209e.npy +04379243-a9aac9089791465d30db3da8ce2a0a12.npy +02958343-3ead00eade22d0aeb376886260eb15c1.npy +03211117-3057eaec13a196fd5b244f7c2ed32e73.npy +04530566-3de0aae73a33188ecc8c5a250a07787a.npy +02933112-bfec781e562e1dde3eec26c23f5bc80b.npy +03001627-2bbf00f0c583fd8a4b3c42e318f3affc.npy +02992529-1105c21040f11b4aec5c418afd946fad.npy +04379243-8d0563a9920592d10b3ff08c68acccf.npy +04379243-df5b55da209637624b3c42e318f3affc.npy +03001627-33cd8045bfb42e53dca072a2e97c1839.npy +04379243-82a60a0aaec8d532150d30262f9b49dc.npy +02691156-ff52c059efaca3c1ca8607f540cc62ba.npy +03001627-4e8d8792a3a6390b36b0f2a1430e993a.npy +04090263-5c76d759674869d559db9878902bfe69.npy +02958343-a4aede8e488db95220363e2561dd589a.npy +02933112-6c4fa2f9e7e938a15cc8912051dd9ae3.npy +04468005-f2560eb50ed3fd09d248376edfe1878a.npy +04379243-e97106cc8bd3ef5730bbd4cddd04c77b.npy +04256520-21c071912ffe86fdf564f8e3eeb8449e.npy +02871439-e481fd4e0120f72875ffdbace36c25f8.npy +04530566-704aaee1bba4d220179fa02faff22219.npy +04379243-f4ce170a6abb80b081654cb17c02fd.npy +04379243-d157a0598ef5c33416e09341cb9bfb7.npy +03797390-9ff8400080c77feac2ad6fd1941624c3.npy +03001627-990d8c0c0008081fff2c92c2a4f65876.npy +04401088-bf2f0de18abd3bebdc858d428f2620a3.npy +03001627-c7087db2f1ec6e62acd2bb6205825cb.npy +03642806-79b420b8fdf6a37db747d76ca5db985e.npy +03001627-e5f381dd81cca6a36a348179d243c2c5.npy +02828884-e7a18e21f877b039f4fb4dee5181bee.npy +04379243-ea98f80f4a663d7bdadcd309a90928c9.npy +04090263-55fe2a8c65c9f24424ee6c77dead162b.npy +04256520-b1cfde20b5b0194af91663a74ccd2338.npy +04225987-11aaf89382b3a4de983ec12a2b33f18b.npy +03001627-751b12c6e22386a49a195befe1c2db74.npy +03001627-c0e667218359978d94ba68807fec4bf4.npy +03624134-89c6acb3635f9a85c15cf6e5ad80f2da.npy +02828884-7f6db7a3f529949601104cd2d998272.npy +02828884-ba6348031c6f0a795213cec267286d18.npy +03001627-cf662e6564c5c3c5ce60514f9a637ce.npy +03691459-403649d8cf6b019d5c01f9a624be205a.npy +04379243-7cf228b6fe5c6c596c342cf382162bc7.npy +03928116-613cc0f0663a29cf1ef241de847b5ca2.npy +03642806-1312ea502b4e9b51701c1f58e22b85e8.npy +02992529-27f7ab052f3fce42b35f223cefd97829.npy +02808440-77e53f8e3e624a1cccd0340812259a39.npy +04468005-65bd12f0cc488e76202d683f37bb765b.npy +04256520-4c29dcad235ff80df51f77a6d7299806.npy +04379243-13e19274b358ec867aa3000697a75d55.npy +04379243-4b687008902de4543e3a599e79b43485.npy +04379243-3d8616a9aa4a8c87cba9038a9140d5df.npy +03991062-58916943ab7cf2b4a73e364671ba824.npy +03325088-99e55a6a9ab18d31cc9c4c1909a0f80.npy +04379243-9377b1b5c83bb05ce76bc197b3a3ffc0.npy +02924116-a54664830fb18ba48391de56a6a5b902.npy +04090263-20d48326842d7c601274aa253a241db2.npy +02958343-cb9577139b34703945e8a12904b50643.npy +02958343-88a814d2107f882d3d30c6f269d07627.npy +04379243-13cdbfd56085fc3af51f77a6d7299806.npy +03001627-48ae43c032e9f89737f67f4322e8d3d0.npy +04379243-40b48121d1879be2ee0605a41c3320d6.npy +04379243-6f13be4d995e55b25ed28ed911e69310.npy +02992529-f9418c13ca82fb887f75fa9740df3aa6.npy +02924116-685c9ef95d3e779aeb0efde6945afda8.npy +04530566-327be46d4b15ba2aa79c0870e481d9eb.npy +03001627-6af8d7bfa508b8d23759750e8db40476.npy +03001627-b1f5b155f8e080c765ae658fdfdd758d.npy +03001627-10991b3b01cc6cc99982a4d6320875e.npy +03211117-ed90f61317c3d3598435a9b7d922cf3b.npy +04379243-5d10c947cde5f37f2e7ed79f4f48ff79.npy +03211117-a5c6d3b9945df19dc534b4cdb1fd80d6.npy +03001627-696bafb55dc14fa4638f48a6603fb3ff.npy +04379243-7a415346ab7eb481f8d77b3fd14416e3.npy +02880940-92f04b8d36c98d18221d647283ba1e26.npy +04090263-c514a4eb146d84163a04e41b7ea7de8d.npy +03001627-8e7714615a4b1e6f82390c5f604e0d9b.npy +02958343-19cd3489f05d203f9ed410a010efa019.npy +03211117-21e8d146503b0e72d9651cd1d591d64d.npy +04379243-e2121844a25d93b2c3bd24f986301745.npy +02828884-280553e975d6b79fd2b12aa6a0f050b3.npy +02691156-7b1d4aff088fa3736e0f3d76ecf4a53f.npy +03325088-61a58b21c73a7f7db362845c6edb57fc.npy +04090263-59ac1042dbfeb36e51cfdb4c9f126c12.npy +02958343-846f4ad1db06d8791e0b067dee925db4.npy +02828884-6718a5b3f89a5d8844c3e89e175ff663.npy +04090263-477f00b10a859851abefc916dc2adb50.npy +04401088-27c4bf6a96c6439a86a04ec9e4169973.npy +03636649-6a635b75306512b3fcb8d8c6d4df8143.npy +03593526-badbcf9d64bd24c868c6661a48aa297e.npy +04379243-6e08e7ef76b1c27027f02aaa836b59f6.npy +03691459-46de1dfe54a261b4c7e1f9c70054d66b.npy +03691459-de68b68a234de1a0ea2f8efb8b3faa3.npy +04090263-b5c1dcf4ccc0b8aca74fb613494614a8.npy +03211117-d53e94b52e0cd47f71dd5d95c394249c.npy +03991062-91e6349193ef212d14b9fab7373cf259.npy +02942699-3b5838e660e2eee27f85a81aa54b70ae.npy +02924116-92bf837e546da42abc7f39bf011e847f.npy +02876657-1a7ba1f4c892e2da30711cdbdbc73924.npy +03691459-bfe4ba1b06404e4bae19bd5568e6325.npy +03001627-b2c62e5b20b34fad5844a4d0ab925627.npy +04530566-75991571412e7ce74059b9174ed51649.npy +03001627-cbf829a6c4df229dfebad4f49b26ec52.npy +02924116-a74020b26b3a942a6c2ab21b9089d9eb.npy +03001627-b351e06f5826444c19fb4103277a6b93.npy +04379243-30335a7b507390407689cc8768f5250.npy +03636649-5493cc3e023e9e6ffcb8d8c6d4df8143.npy +04530566-58b6ab987872ed42f36dc23129445ac0.npy +02691156-408af35642971375be13ce34aa7c0c1c.npy +04379243-a3f060a21d7a29bfe5b095b06da9076.npy +03001627-ba9b35c49d861f7f4e994a4c55e56a4f.npy +02958343-3a98adfdc309cca9cec94038e2141ac1.npy +02828884-6a78bd21ec72d396f155d75bbf62b80.npy +02958343-84498085850b19d11673e1c313348a01.npy +02933112-359fbb601801fa9b5588a2543ef0b0b4.npy +04256520-8494a1f6985e8173bcdc50d6b73788ae.npy +02747177-97e3b7b4688c2a93f155d75bbf62b80.npy +03001627-8f1a661dc1048e36297936c81e7f6629.npy +04379243-481e00e4559705c616a2b5862518c93.npy +03001627-51733b725532817ac8687ff9b0b4e4ac.npy +04401088-d79b59ea51a9d80c483afc91de6851e4.npy +04256520-4cb25759388ec29935fd302efa96f6d6.npy +04379243-4aab0e569f1dc3bc8d7e9f13fd8f661d.npy +02933112-a62c9f6091337b5cd5382f3f8f33a9f4.npy +03991062-5d567a0b5b57d8ab8b6558e44187a06e.npy +04330267-2c0c7a289d37157ecd8f3fe9ca2145e1.npy +02691156-69d471ccfdf9e55cace8f9c62f7ef839.npy +02691156-b97446f1c30c0ed7b13143dea57f5eda.npy +02933112-bf57fe6a331137c2abaf316e4a957cb1.npy +03337140-b91dad01a72aaf9f91c352d02061b3f7.npy +02691156-c7c5bb658cafcc7c67711f7c205c5b63.npy +04530566-9d3f9edb3fe0ada39bddaef1ba7e1752.npy +02958343-673ee096916a5440a96c7d9d13cfe9b4.npy +03001627-923bce0b230f5a1a2c919c0510a0815f.npy +03797390-61c10dccfa8e508e2d66cbf6a91063.npy +02876657-807ef57d3d9d13eeccf25325b962dc82.npy +04256520-681f7af0ffc7e220db6d2ff65cc5b310.npy +03636649-8304e6daccb18c2de3855de370260f05.npy +02958343-556ec1ccfcb79f08a7fd25564c2e888e.npy +04256520-1f75847dbddcd34afac76e6fcbdc3631.npy +02691156-a367bcfb5d26801a848c716e284f561f.npy +03636649-1e10f920ed440021cbded0430ad5ccf.npy +02828884-fd38474cc1c62274f155d75bbf62b80.npy +03513137-385480a2554374862cc4218c4be3f082.npy +04256520-89045848f586c0a729404a50338e24e7.npy +02747177-75dbeb01fdc7f265d0a96520c31993ad.npy +02958343-ddc5e41245918030f014feb3e3bb3ace.npy +03211117-27107e057772be0d6b07917e9ad0834a.npy +02691156-f963bac7f45473cdb33bc7516e53285e.npy +04225987-212e0563473156e255483301a044235.npy +02946921-3a7d8f866de1890bab97e834e9ba876c.npy +03991062-47adc9b7d6d281662c528d33bca1ac2.npy +03691459-82b56b6d371031ab7c8813aa71327b73.npy +02876657-5a58f9c3966c1248a7c2417f4b260d59.npy +04379243-c8532b5928b242d29ccce4c6d5bb195f.npy +02691156-bc92b144ec7029782e7c68eb5d1b9123.npy +04530566-3e5e782373516ad760ddc468fe733ed1.npy +03636649-21a4556c02678fd7e59f529cd1b6faa8.npy +02958343-9a556cde3d153c6230e527480f210909.npy +03642806-2416c2fcbae368a7b95c83f902f3aac0.npy +02933112-66a82a157f4a1c9a22e05b27cb30bde.npy +04256520-430d315cdf5b3ca7963845a6a5eacb6c.npy +04256520-c5dd746e08121f8f71a782a4379556c7.npy +04379243-bfb8531870be8be971a782a4379556c7.npy +02691156-dd465efdee6a57e966cf1b4a8fc3914e.npy +04379243-cf9ed2af8cb3085917b431cae0dd70ed.npy +02924116-a0ff4e261a0d8875193d7855ecfc1bd3.npy +02828884-c023275b1a68d6432056b4bd5d870b47.npy +03325088-7b6c6838bc4bd4d33321831d2245cf06.npy +03642806-df624231ef05b83d54c7ab6aa5674ccc.npy +04379243-44d6debd1db8c2e57fb0dc5c3ba15465.npy +02992529-3d5d7e610fc235cbcce71a7ef3de6f04.npy +02691156-41aafedd84a6fa7490baeef8ba5b93e5.npy +02828884-2a45727df039318ea46a4c5f3c2363fa.npy +03001627-c5479437882e03eb282d0900e186958f.npy +04379243-6b1a24847e5b666de3b5d4a92fbfd4bd.npy +04256520-14658bfae450e891b89b974fa14a05a.npy +03991062-d69e25b85eee67d06b99047335b63e1a.npy +04090263-27c9d26c58200a1527be842e82df28b3.npy +02747177-8e09a584fe5fa78deb69804478f9c547.npy +04256520-a731e2ceb44d59e1cbc66df5fc1969c2.npy +02691156-43edf9f02a027ed162f11c7bf54cc1ed.npy +03636649-676ec374028a24db76e29c9c43bc7aa.npy +04256520-71a4f27e4c6fa0a1362d127df6d94eb.npy +04530566-51537c56f71ec82acfd826dd468a5497.npy +02958343-5c997a7c241190937cbd61b2affd051d.npy +04379243-52c72274af4c7e19910979f825490a99.npy +03928116-6060bfa3909185f78ce35a9a4af57797.npy +03636649-f01358d4f45cae23ce670f026edf07e5.npy +04090263-a299aa2fee9a1d297ca8eb6ffcff94f6.npy +03691459-3a7b68f7312c16f1e9bb042b8623f922.npy +04379243-43b0de9be0df3ecf51f77a6d7299806.npy +03691459-704d0b362588638aa249f8489bc060dd.npy +04379243-c0a18b8e41041386e1a698146efec195.npy +02958343-6de0b37d14cc7c7393680c5a9a367b4a.npy +04530566-c0f619a710e4cccd15c8f969616647e5.npy +04256520-c866adf9f2d0bdd9f3598efd14e493d5.npy +03636649-94f9cf8754e2f080fcb8d8c6d4df8143.npy +04256520-77090c15f738bf3079da6431b0766445.npy +02691156-f087be2dec869154acb63dc32be3cb01.npy +02747177-b2e03341b4648a3d63b2acb037dfbcde.npy +03001627-11c8f43ef796e23941e621b1a4bf507f.npy +04379243-25136703ff8fe0a8a27b22aaa3daadd6.npy +04379243-f10f579a973af061fc527605fed20d9c.npy +03691459-6d24eaf8aa3c362fdb6f3ca49e992ad8.npy +02828884-b73da1e1a2f2f549d4d8765e3910f617.npy +02808440-2ae90c52820a705a16af3198c99de08.npy +04256520-dc2b5f9abce70f2b55f9a00acc25f137.npy +04379243-9c62e14436f27b6c457ba044c28858b1.npy +03001627-dfc9e6a84553253ef91663a74ccd2338.npy +03211117-bb5b1f086ec0012d2e80bae93fb41fe8.npy +04379243-f25cf833c2200fef239d0ce9a68d2afa.npy +04530566-75aef09a516f59da49f73a97204d432b.npy +03636649-101d0e7dbd07d8247dfd6bf7196ba84d.npy +02992529-b4795b53530c26c58b13932a0c28e98b.npy +03001627-6124a2bebfa255719fb4103277a6b93.npy +02958343-1fb16b5399a4b3a710bd1697bfc4e3eb.npy +02691156-1818597d398db8f7f1f82f6fc8747b8.npy +03001627-78e1977bc5f0f4041552c6ecbda964b.npy +03948459-429202f8d250310f8a937c1a7380813.npy +02992529-8e3e1213e47661506457f8736d1c9e5d.npy +03001627-c8963b0930306a61781cbff504e4168d.npy +02691156-ccfe789ebc77be87e71a4f02883f26bc.npy +02828884-9a3310c20959245b791985eda7619303.npy +03001627-f12a3ffbe0f8b5076253bf0968762241.npy +03001627-c8938f54fecab41e77cd061c90fcdb44.npy +04530566-aa741f0f7784b791e99164b294d0c671.npy +03001627-584ab19b5df1fe697daabf84de73fb1d.npy +02808440-af1626daddb7a607b805ea9e53402739.npy +04379243-4d14547b54611e9bcf1ee9bc9708f08c.npy +04090263-6bf9cdb0f879a8f894deaa9fff391d41.npy +03928116-44001374b5037d9373a1732868f719ba.npy +04379243-2da4d3085b438b4f35836c728d324152.npy +04256520-a613610e1b9eda601e20309da4bdcbd0.npy +04401088-fa21f65c051ea2577500d68c500fdb4b.npy +04256520-82aee3c5088d005414038d588fd1342f.npy +03624134-88251eef61ac727945fc4bc75aa67159.npy +03325088-f705e6e60a4d9ff576c18e71fd49c4dc.npy +02946921-adaaccc7f642dee1288ef234853f8b4d.npy +03001627-7a8b8bbd24974013327289c00b6dc9ca.npy +04004475-8af6cb411190ba2df20c09ee03883555.npy +03001627-48429b3467c7185060fcaed6cc231482.npy +03636649-967b6aa33d17c109e81edb73cdd34eeb.npy +04401088-7afdaca858bb0a964a28575f3344964.npy +04460130-9024bb81d726d584dfda46c9a34dab22.npy +03642806-5515081bfe708008edf29b343d09db45.npy +04330267-cbe066eb10e871454b3c42e318f3affc.npy +02808440-5395c36e4449a364a0986899fca7913.npy +04379243-1f0c62f30be6f19aa6fc75a75fb8d65e.npy +02808440-bdc71b9efd77276f9f39bedffcf91275.npy +02691156-6d119be1286c7b129a6e43b878d5b335.npy +02958343-296a15d4e4b903db94b42287616a3ea7.npy +02958343-78471673cb8ef99f78ae9714eeb937af.npy +02933112-3d8183c2f6c0003bc59350d819542ec7.npy +02958343-193ec1089f0a98a36518e6cd1fbc5fab.npy +03046257-15ba3509f1dbe068f546596ce7364503.npy +04379243-8a42ddd769a999a9e6942c5426df6055.npy +03001627-e792a2d799d79bc1b249ecc7669d184f.npy +03001627-bd4fb5e30bd993727eaeab1f0c9120b7.npy +03337140-53af35fe75337509bce0d8d171e7e87b.npy +02801938-a91387fd7e02ab1fe1642713fcd8a902.npy +04379243-b19e399e93447dbdd2dd99b484971e89.npy +04379243-760f49288c2691b5b4d1176ea5549480.npy +04379243-2d12d4984230e79a4b3c42e318f3affc.npy +04379243-a56200b624a644f7df6cfab91d65bb91.npy +02818832-2b692b1963908c87a792c81933e4614e.npy +04379243-51d386439cb748c54f2b9e837678be87.npy +04090263-55821f1ee5efcd6280c2e60c312b0f09.npy +03001627-955ee3a20ba242414580ed619ae2daa1.npy +03325088-be6b8a7eeecd8e572101dcac4ed75d3.npy +02958343-1a30678509a1fdfa7fb5267a071ae23a.npy +04530566-337381e4b5c11c4f8c9312de4e9cb8a8.npy +04530566-853edd2a09215d83aad3e4869fb7b555.npy +02933112-6b984c6b1e49d9dc59f8e31ca87c470e.npy +04256520-73379ebbbac81af13ee8e30b29f70dfc.npy +03790512-bae59e64a50d3aa2f68f798d07e007b6.npy +02924116-9348a737cfd5f36f30bc176d97eaf5ed.npy +04090263-47dbdfdcbd971cd2203f35d9b3b48203.npy +04530566-81358250f7b811e73c70f7afafd32393.npy +03001627-be1e5985324b401be92225287f8225f7.npy +04379243-6b43cb708670013d2a475baffed905d.npy +03636649-78c87f00ebe9491e2cd2160e449d45ae.npy +02691156-853dc1e740631bf2ffa79951b9f955a3.npy +03337140-352dee789cb5b1c64c3aee8e9d3a6ffa.npy +03046257-d295c1b6b9d134a65f7f2cf289fe662b.npy +02958343-46adf74e07a86c55e370ad7734071a37.npy +04090263-5de2a57211e47dbd1f56bd5c23e00f1d.npy +04460130-b88387c316d85bf6544a7584e1bfdef4.npy +04256520-1712200bca469561d20e3ea5765d7edb.npy +04090263-11549f435b7454563571d7763ba5a413.npy +04379243-b08dc9e0fd675e6664adc666ed4e2ec1.npy +02876657-d297d1b0e4f0c244f61150ce90be197a.npy +02924116-523033507a9eae1eb77d370c8664bf4c.npy +04004475-ef5296fc06b736d038e6072b52bce43a.npy +04379243-f469759b2790b6cf6c1a170c83f9532f.npy +04401088-170f4eab739637f2a101047bb63a1772.npy +04379243-369b720841edc539611a3acf20a3c963.npy +03001627-8e9812ad9e12d467679c9e94dfb2276d.npy +02958343-5e014eb2bd03daab9fbe97de4a41d527.npy +02808440-a375d94c02f2924b550584dfc8970d11.npy +02828884-2902b377edd4b48aa3a0c1cc16d124ad.npy +02924116-97e9d6aa1011555352470de2774d6099.npy +04530566-6371cc04f48161ec43b0018b6edb5e48.npy +04256520-1b5ae67e2ffb387341fbc1e2da054acb.npy +02958343-8b049c92888475f67c3c6f82a395b347.npy +02958343-9dd5fb440759181035fea498c4ba7c5a.npy +02924116-1582c81bf7dff678d26b2d2076566bb8.npy +04330267-64f6f5a386e63a1d5eb64c1003065596.npy +02828884-dd86f9095341d19af155d75bbf62b80.npy +04379243-b266c6e40c1e976ef3c6b7a01c418f2d.npy +04256520-1b28eabac10276cb7062f2d72cde5c95.npy +04256520-93d943320472c9fc599dcc439b161a52.npy +02958343-ec67edc59aef93d9f5274507f44ab711.npy +04379243-d187561a6b0cbd0acaed5ce7390f30b7.npy +02691156-953baa426dac775bbc8c4428ef1dffc7.npy +03001627-d0500d229baf05b0e83221ad0d21775.npy +03211117-421ad85cbba562878fc3447f3635506f.npy +03211117-198eebeca7243399ca5ca7089655f058.npy +04379243-1dc7f7d076afd0ccf11c3739edd52fa3.npy +03001627-2ae4f1392d44ca24654a275ea978255.npy +03636649-2161683c44a7dc356bd865f153842b49.npy +04379243-35705c4e27888e5d27b31bdeb5f5c79.npy +03636649-5eb0e18b12f4940d6f97b7cf7ff5d41.npy +03001627-45f32105a1d05455bc996a5f03fd7bf5.npy +02992529-ed0f3e1d20fc722bb0478ec258b0ea3d.npy +03691459-5027b6f6c32b0d28daf9b9aae267bea7.npy +04090263-403195be81485468d10b86bd6e8bbc34.npy +02828884-30d3152964e13201520d2a054af1eb24.npy +02958343-86b488c74b27d70ace27281f3b76d1f5.npy +03001627-96a19b41f440040426f59f4497a464fc.npy +03001627-76283716a2c6586e266d673a6188bf4c.npy +04379243-5000e001c72cebf44f60f15da4c665d0.npy +02958343-2fe7e3fc47dad6c7afe1d4530f4c6e24.npy +03001627-37a0959115e6fb4ce7c7920f6a65a54d.npy +02924116-c87efc4c88f58fb3cb1288ccd7a59563.npy +02933112-4e31ddf3828a40f3cd525309aaf63a44.npy +03691459-2034f891fe2d1e79bb51f8b36601764d.npy +03001627-3c408a4ad6d57c3651bc6269fcd1b4c0.npy +02958343-38f403b915d950d3ce8f4a5eeb103d2.npy +03938244-db211dc89ca9e40c29dab95fdd4a19d8.npy +02933112-d7fe270a81b0f21c3fe047712e43e185.npy +04379243-e6a89aaa226b116a60885f79b3a5579a.npy +04379243-45acacde58d7717aaa7cb30470f3273c.npy +04401088-758b9da6bf573838d214322c26aa0cfd.npy +04379243-5a3789ede7e60884e35c5921850b7bf.npy +02958343-30f0ba361010ea11e66cabd11ba41eae.npy +03001627-58a8f29ec056a19f71a782a4379556c7.npy +03211117-dbcc94dbf216e37588bef8ce0a02fc04.npy +02958343-aa9cb692a7ca1070b2d2900ee0ae7e0.npy +02958343-5a841a8269d3560d756e18912340de0e.npy +03001627-87991eba27985f3a417a8f1d2c94eaf6.npy +03467517-feab270427cee00a24eeca91f583600.npy +04401088-d9d06d2772ecc526c0dc3ed657ab97f0.npy +02933112-5294d0d31a33e67912de5317fe5b354f.npy +03211117-b11d7ae45f5a84de8641d137e7c33076.npy +03211117-fdf5375eea4c3858498a04ba00344041.npy +03642806-689667fca044e15b941a99145cf33e72.npy +03337140-ca206dfa66c21cd728b0a3696528436d.npy +02958343-ece361a95a2ede4e629cf5743e29cdb3.npy +02691156-84de1d44d8795d5876817284cd40c7c1.npy +03691459-de5a57d8fce504ced747b49524a1246e.npy +04379243-b70483396e091a75808b6f0b77e3bec3.npy +02958343-c8bd4d0ac34266ffaaa232d0915adae9.npy +04401088-ef2472e661320b03e324fbf60278e45a.npy +02933112-a0beaab9a8c2f0954e7d60def15dcb8b.npy +04379243-90cd6a48cf2789a9b430d97a45d5824.npy +04090263-d81bac8b449807bab7b81b671e901c39.npy +02958343-9c0f4c3c72190a6ebda733a39f84326d.npy +03001627-7fa4db28bd803691c91adfee365fdcaf.npy +03691459-1499859135ccc6b267bde58c681df405.npy +03001627-e4c84068e4c56e53bf8b9d530de7a108.npy +02691156-b07608c9c3962cf4db73445864b72015.npy +04256520-9b88f0839b22b33022fea5173e5c6318.npy +04530566-5e0e9215f91c163d7c513e87d3f6c6c.npy +04379243-3b082e34a78a3c23100d4716c7fbfbed.npy +02992529-e2d49d74845ff0207e1c85c5c15da7fb.npy +04090263-20468faa3d66dce03cfd5b33045bf719.npy +03001627-e00b802d5b93172741052e43309393de.npy +04379243-73157856beb04619eda877ebd51b3abd.npy +04379243-283e5cbc29b92fcc8cbb8bac2032149c.npy +02808440-693b8a150f9e844e50539bb73fa8aaff.npy +02958343-8680d89294724815d9976212be28e1b.npy +03001627-fb858b9e5f2b3e1043dbb6421d614c0d.npy +02958343-49b67421f1aecb54619e733243629008.npy +02992529-8a62ea56cad1ea25430f38f25519fb5.npy +03325088-882d5e269c44830976c18e71fd49c4dc.npy +03642806-13f5cbc78856f977927930e64238782e.npy +04379243-43f2e83d015469c71ba2f806cba87b47.npy +03636649-71090d1b424b4b4b29eb9d04ea723179.npy +02801938-955ee4b78f049d9b5af4278cc885a78f.npy +02691156-3b5b8a2384e8850d185b376619557c95.npy +04256520-8659f0f422096e3d26f6c8b5b75f0ee9.npy +03001627-e6a5c9fdb609d00a5ff6fe84f53e00a5.npy +04379243-bf9df04aea08b0f0f51f77a6d7299806.npy +03467517-62f77c35b213ce976ac47c8f9e87947a.npy +04379243-2b6fd7a94ad69b019ad1212263439f22.npy +02691156-444d67950ff9a4cc1139bebb00fe5be8.npy +04401088-c6ad139da5e0799c712cb59213324f9d.npy +04256520-aa1da8200477456bab610b0c94236463.npy +04256520-a0c9e23365a3516dd60ef9801956a8d9.npy +04379243-ca77f1d8d0151975901e3cd572b4fe52.npy +03001627-932bb63e4525d57b3b8dea4a358cbf0d.npy +03593526-7dcc9324c5c23029bc54d7012755d50c.npy +04256520-2ab2a7cdbd8770318f17764fa642770.npy +02828884-f5f8c8e5d2de751f63b2acb037dfbcde.npy +03636649-853c5ea3c279b9e9f7887b5467c02fc8.npy +04090263-4315071df41d5766a7ebb24c1614411d.npy +04256520-4d33fb26aa7baeef88dcbe86402c7c15.npy +02876657-7bf5bbcff98f3d272561bfd89201eee3.npy +02691156-460f2b6d8f4dc18d565895440030d853.npy +04330267-994e7339a67306d75eb64c1003065596.npy +04530566-b9c516eec45c825979283d5c77809cc1.npy +02691156-e8ceb64406509714e5dcd47593c60221.npy +04379243-a877ec39efb4c8cff37af16b2893f1d4.npy +03211117-b05a54988fb28d20d0b341c1c5648015.npy +02942699-5334cfe15f80099f15ac67104577aee7.npy +02691156-d276954441de1e878a3d2bbe7d58317e.npy +03001627-8bdb589e5e0e7f57b04cb542e2c50eb4.npy +04090263-5f68ccfe85cba73d2a23d93958262ccc.npy +04379243-6b1b63af6ccd71a1b129901f80d24b7b.npy +04530566-2f0acfd47622a8fa419fe456f622e6b2.npy +02924116-294c7bbfbc67edf72232a4c7acb57248.npy +03001627-58867a00409c47c0813a1237d2827540.npy +04379243-35e033efcf79391ef581ec61f9db71f.npy +03991062-990903dc0a1b416681faebbdea6bd9be.npy +03991062-9d7710e65ad393114b3c42e318f3affc.npy +03001627-a7b9f9e341c74b8d57ddce8e42aa6e90.npy +02691156-f59a2be8fd084418bbf3143b1cb6076a.npy +04530566-5e9890e2f4cab96dbc6cd96a5e6546c.npy +03691459-dc8d31790da3b1c6c06fb481fc51ebd6.npy +03636649-3533b9eff82f2f9cf22140029982c6f4.npy +04554684-39e2a2eac45d9ee9961469926610c5fc.npy +03691459-bc547d63373a98997dc4f6934317af74.npy +04379243-deb8b5c0baed637625f61c02205f9a5c.npy +02958343-b30efada80553a1d202258c0423dde73.npy +02924116-7d9109eeba6fa218ceeb72b524f3e0ca.npy +04225987-87115860707b0208813c2f803c03ef9f.npy +02828884-afe3b299132016512056b4bd5d870b47.npy +02958343-37a75534a7a006ffbda733a39f84326d.npy +04256520-9d5815f9ba8f0ddb19fb4103277a6b93.npy +03001627-4c0d8f04f27f96284417bea8868af4d1.npy +03001627-b884ff155c4117a7508dd48e67ad44bc.npy +03046257-70e6d9a58bec336898d5fc0473d00a1c.npy +02958343-e5d6df012b219fa6a7c4dca3ad2d19bf.npy +04090263-157c2b391f7a7dda1a857c47fd0ecdc3.npy +04256520-28e246db6ffc3497384b87f5fc9c7afe.npy +04256520-8b62bb92edcede30886ee1269f93c784.npy +02691156-64dbeac5250de2bfc5d50480246d2c40.npy +02747177-.npy +02958343-70e27da90dec2de49604bf8c981ad1eb.npy +03001627-2de1bd62aef66dc9bf65e1af50b5b7d4.npy +04379243-a90e18bb9bdadf6a6d8b4dad28688a76.npy +02933112-a631a1a99b21cd92b87eaf81a9afbbe.npy +02747177-e91da0c5c59ec4c8cb2a965e75be701c.npy +03046257-6d12c792767c7d46bf3c901830f323db.npy +04530566-368dadba3b837dd926be51fab07b7ec6.npy +04468005-212b58e8aa6ceadc196c433756c6bebf.npy +02691156-7dc614fd957186cf216b327569dd806e.npy +03991062-b00fc3306eab53e0459a1ad9a3821e02.npy +02818832-2b8633b9bdb72ea215dd7d7985e749c1.npy +04004475-90fc6f7b0b84755796348cae6ab0021.npy +03046257-341c76da1822e1793a86a6fba656f58b.npy +03001627-5893038d979ce1bb725c7e2164996f48.npy +03337140-5ce6aa474b597edb4d3a0a56bdd58a7d.npy +04379243-99d03f162477263b22996d48badb33c9.npy +04401088-82aeb34ab6fa282766148e8aa85ea356.npy +02933112-6ab14d89360d0a55ff3ea34d08547895.npy +02691156-72a74e13c2424c19f2b0736dd4d8afe0.npy +03001627-f4a0767a3d7039c38a841ccdc50a763.npy +04379243-aafa8e4293eca14d6bb54533c16c8fa.npy +02933112-87b62cc2f0368983824662341ce2b233.npy +04256520-630d612af74628053b28ebac0b25d03d.npy +04379243-4a4f58b882325236f6e8f2cf4a97051f.npy +03001627-f00c1688bd33aae28cbb8bac2032149c.npy +03991062-7b0e40cc37ff733d4437e0a6aa050dc2.npy +02691156-c91e7b5681d8aeadb81009266e6622c4.npy +02924116-cb39ceab50b3c984bcdd0fb2fc18a716.npy +03001627-268f73b8f57676a71732dfc96352c472.npy +04256520-8426b07a7f599d011a3b39b07e4b3d0f.npy +04379243-5d7631230b4fab707934a0d24a61231.npy +03001627-3d66c60796d59662ea693790a1608aab.npy +03467517-ed1ca9a829715b78a71985b33d2601e3.npy +03001627-f6988e6ca8ed9261492d9da2668ec34c.npy +04090263-f6fceaf62bdb85c05e9786b1603f45c8.npy +03001627-398c1d570b642b6cf91663a74ccd2338.npy +04379243-79ea27001d37617b4f7c5e1744a5e6f5.npy +03938244-ab60bad52d6244db86052e834fbd2c4a.npy +04330267-9bc1d272c82f528376a2788017b16c37.npy +02808440-5841ba7ec3f334dab362845c6edb57fc.npy +03624134-481f304ae81616c54e09ebaf49b0cb2f.npy +03948459-2acea60043da129a5a003776cb72cb3a.npy +03593526-9d1a07991391ecec6b7154919b02cbec.npy +04530566-7e35bae76c10fd7968cdca3005c2cffc.npy +04530566-9798a8da8fb83d63847c4e55bb965ab0.npy +02691156-d5f01e2aa54bbf28ca8607f540cc62ba.npy +03691459-457c7205d3a193c01692dd4d739ce02f.npy +03001627-b13a4df698183bf9afb6676a5cd782b6.npy +02691156-57f30880519c8270e58d21f41272cdad.npy +04379243-30cd6bee25352baed5857f15f877a4e5.npy +03211117-668f2602ee2cd581a312d1c0842a5165.npy +03948459-50fcbde9d69020130a1f1f44ddfeac.npy +04379243-df7f8b7ea0e2c4ee55f46d55537192b6.npy +04530566-782b29db43c02f7442b917ff8145b491.npy +03636649-e5e9ff118631c2a3ee088de33038f12a.npy +02828884-1167fd85d3dc7c8df4fb4dee5181bee.npy +04379243-dc1645a2d2b61e5950794366030f78b.npy +02924116-32cb1cec0bcc12c7c6bf3b18b8ca71a.npy +03790512-49b7ec863c4599aabd1734e75169b9e0.npy +02691156-a26639a06e2ae1ede7d756565593b850.npy +03001627-29656461b26f620ff3c9c1464e55d580.npy +04090263-e59086e0a9bf161b170efd05fec8727.npy +02933112-4b2e20535d3ecd016b7154919b02cbec.npy +04379243-da09745bd5be34b9aaff8bf395bfe94.npy +03691459-a1c80145373d98837dc4f6934317af74.npy +04090263-8456aa006d740061bd8fcb0281cd4d0a.npy +04379243-cc554812025dc498e7ed5b5b11f935c9.npy +02933112-47ffa354257d2e3b20f4d1b537b5ee90.npy +02880940-38d2122b2aa05f92e1b9b7b3765e2bea.npy +04460130-1ebb17d0790e384844e2f9503fe415b5.npy +04379243-2c0b0f0e9ac21f6ca1a2ce4cc65d552c.npy +03001627-9ec08262ef59d69d6412cccabcef91eb.npy +03001627-fa0e922a339bc7dfeb9a9ca952f63e23.npy +03467517-32969766a65974e9e52028751701a83.npy +04379243-69ec86dbd4df85e51ee2805756841071.npy +02828884-988d4a7f08e66aa3d42b9650f19dd425.npy +02958343-6d618b1cbb187baf6c6f7354ef18ac49.npy +02933112-2175d15f93051f0bc59350d819542ec7.npy +04379243-6d4e96c31d1b1f9d16aeb5e4ffcb8813.npy +02871439-bfcced53e67cf63ad80f4eff3307724d.npy +04379243-3dee82c33d65b74a99e8bf807e902261.npy +03636649-f6a7d85ccca5e5e34a6ecce2eeb45768.npy +03001627-4b3ddc244c521f5c6a9ab6fc87e1604e.npy +04379243-f5de3fdb7c073f48dbbc9440457e303e.npy +04379243-fccd86d2aa3c565334aff3344c00890c.npy +04379243-bd12dca2d655a093bda72093f9b5aa73.npy +04530566-f65e78e69d1d5eac465721b273720f4c.npy +04379243-34ec5656afb6860af3c9c1464e55d580.npy +02691156-6509073d1ff37d683d41f76be7f2e91f.npy +03001627-cc8066a5107a2bf5926f2c1927eee8ee.npy +04379243-b15ff00cf3ec4dda14038d588fd1342f.npy +03691459-74d27bf812f4a7d83a2dfdc3f38ea6c3.npy +04379243-ac747a86af391b9548f9d76a105d8448.npy +04379243-c472e242175ecc75dea0c7d7198f1b0c.npy +03636649-8e03bd383d8696a7ccca59c0649ee0d0.npy +02691156-f88906b677e97695f4126163bc622a34.npy +02871439-8eeacd5e91d7f70e9881fc457f8cf42.npy +03325088-50090633b32bb6adb362845c6edb57fc.npy +03593526-bc6d5b787a1672cec8687ff9b0b4e4ac.npy +03211117-8c4a886b6b2c8d94d7f301df5d83f77e.npy +02958343-6d8da7ec9ead6677701c1f58e22b85e8.npy +03636649-53afad2e573b26b141657e31b569b105.npy +02808440-e7f07d51b5261395ede9471c962dd6ba.npy +02924116-3ae82c64c5c9c0b7ab26c897f52b5439.npy +04330267-df78913fe9070bf682b4ca3750aa2fb.npy +04256520-9ab0a81e580dc1f4f008d8a3590fb522.npy +02691156-5515a62182afd357f2b0736dd4d8afe0.npy +04090263-25d950a8c7fcf04b57855ed10703bbe0.npy +03691459-a6453864512f46dd747b49524a1246e.npy +04379243-7efa6d2ff959183c3002761e7a3ba3bd.npy +04090263-581f03521f0253636d75fedffe6398b3.npy +03001627-13990109140043c919fb4103277a6b93.npy +02691156-739c8cadb1db6db39a6e43b878d5b335.npy +04530566-1317defca6e05d78e9fa15608cc1561f.npy +02958343-3c685bf24a135262e88791d6267b8a1a.npy +04379243-6a52c7461aa23233c2e50348f23d3d.npy +04379243-4fde6d734ef8490336d4accc80b34c1b.npy +04256520-e62a984beecfdd9a695c69bb6f9606c8.npy +04460130-aec546edcda7c5abe579ef1e3d185e3c.npy +02876657-dd280525cf000bc3a608634464309a70.npy +02691156-1c673748703c99207f1f82f6fc8747b8.npy +04256520-fdb3ab843f2a244eb9b4a0bf4166f120.npy +03790512-803f90199731098552ee90e577613070.npy +02691156-a68e67e5fa7ae694d9a7daf2d70e57bd.npy +02958343-988108a7536d686824065b218dc1b5b9.npy +04379243-5a38d21dd30f52e972463ee0ec4cc614.npy +04099429-e02e5bc1a52b63523df4fa4547276fc2.npy +04379243-d634c7577c8bc1f0492d9da2668ec34c.npy +04256520-e61751c485c937fa717300ec93e59c63.npy +04379243-bfcff8d45de2f950f751d8c0e5773abb.npy +02828884-557899ea369eedd4cb2a965e75be701c.npy +04256520-fe602b7929307607e59b39f8355b80d.npy +03797390-b4ae56d6638d5338de671f28c83d2dcb.npy +02828884-5dea347d55e0704d1992408f320d16dc.npy +03211117-871dcd6740ed8d2891a7ac029a825f73.npy +02933112-3824d4b03e74afe0743d4e4333af43e6.npy +02992529-bef91c1804ec226e5b1c02ea3a290822.npy +04256520-2528b8f7ad0a177e1491843220e463ea.npy +02747177-6dae7248443fdad9f4fb4dee5181bee.npy +04379243-e6cb8965b985b8a07eec403e4de3e723.npy +04379243-1f8ff48858b1d78136c236fff3cd03ce.npy +03593526-d31eea002a8dbbd744f73d1b4abfedac.npy +03636649-c89d854d5c61e751cdd3c867acb77e12.npy +02880940-709778e5ebb67e32b396efafc0d0d8ac.npy +03636649-bb0ab5c460ddbd65ef3a269219210793.npy +04379243-a9b81cb82f73f249f7248d9dbed7a7b8.npy +02691156-ed73e946a138f3cfbc0909d98a1ff2b4.npy +04379243-5fe3476df92392e1397aad305ec14786.npy +03636649-f41fdea6ec38439193b00be700931140.npy +02876657-d74bc917899133e080c257afea181fa2.npy +04256520-4781d90373fffdcaf9aec59741c69cf7.npy +04090263-46ac5939e2eb53189a3e2fa8a8e389f2.npy +04379243-201833c55354f1a2d1d1bb832a2f0352.npy +02691156-e3c26c3920b93f36eb7fefaef8eada2b.npy +03790512-47054c1839830834a88e8cb97b773125.npy +03001627-2c2fbe0622220e7cf51f77a6d7299806.npy +04256520-22ca96b824795ba8ef188758bf2e3a30.npy +02958343-eb40501934995e1a6560c47a91b4db1.npy +03691459-d80f344b9de3e280610652dddb029059.npy +03001627-b2a658572331c578340a1d09e918e861.npy +02958343-db14f415a203403e2d7d789814cae761.npy +03325088-486fd6e4809c8c59b362845c6edb57fc.npy +03691459-c4ca7f58c6144e1416eb1b6d0ba9133c.npy +02691156-8af46946b9b2b3aacf0820a704ed425d.npy +04379243-7f1019432a168f451512cfcf562674ac.npy +02958343-1a3782ae4bd711b66b418c7d9fedcaa9.npy +04379243-89580ac98637f985c3bd24f986301745.npy +03928116-638cfdad8f5f9e0989964e04888bd74a.npy +04379243-55d2be43d71717e1f4b6538438a0b930.npy +03211117-5a9951b9945e67566d260179aed5cd80.npy +03211117-87882e55a8914e78a3cb15c59bd3ecf2.npy +02924116-38ff0caad9fc3437cce85fd33c4e1aaa.npy +03636649-80e9c1d6499b6a9689ab11a408196888.npy +04379243-99a43717f3487aac63fba60e6c90121a.npy +03642806-fdec2b8af5dd988cef56c22fd326c67.npy +03790512-6921ac96d7bedf7bd5dde04c96fd8146.npy +02958343-cdec84be0cc9364eecfe83f5db813c4f.npy +04401088-234d1646b21fd765ee45e1eced971f52.npy +04256520-1fe1411b6c8097acf008d8a3590fb522.npy +02924116-cc8bc88b246896e92f8244e4db35c973.npy +02691156-7a97d3dadc608b4350f01eb2b12b0a8.npy +02958343-86d5ba5d14672ae7becf71e2e014ff6f.npy +04256520-3af5eddf5022015788dcbe86402c7c15.npy +04225987-36221454034311a4fcaae723fa352fe6.npy +02828884-50612adf11f22931d2b12aa6a0f050b3.npy +03991062-1a1a0794670a2114d6bef0ac9b3a5962.npy +03928116-e3d5f6dbff73a7a5e769f0986786b881.npy +03001627-3db18530ff6bbb50f130e9cdbbb1cf40.npy +04379243-e9d6ce5bdae4462aa187e6150daf1a0.npy +02946921-e8c446c352b84189bc8d62498ee8e85f.npy +04530566-24ce8f07f05d14bfb274bf54d5e89093.npy +02808440-1dc36bb29702c28b3321831d2245cf06.npy +04379243-9d547457c4404412635469b95109803c.npy +04379243-cc8e9d46def8065c5fc367a00ce4b49d.npy +04401088-68189c0fdca1a8744db121a0d72356af.npy +02828884-b3c8573a2d8b0a14c347936f40ef6857.npy +04530566-60ecf4adf9e115f91eff78a25c58572c.npy +04379243-49e0fb5a2318e4c1b0a15036380e635e.npy +02958343-325ce7d1af0e0621221f497d46720397.npy +04530566-3b8c16861667747fcfea3d4fc15719ea.npy +02828884-273c618c2d24a562ad5067eac75a07f7.npy +03001627-b7aabc0069ea63e096d5fa1ee6ada8d1.npy +04256520-5e0fa460af0e5e898223ee0bdd50697.npy +02924116-acdd5984ea1c11d3d687ba8afc125512.npy +04090263-5ffa1a012a2b18fc83b41d2cfd151bad.npy +03691459-10e079ff34f99777bcb3fc1376c3a85d.npy +02747177-889768abe1e56957769df73d7c60d904.npy +02924116-4ece51cc1786dd0a7a49a4f3f2ced32.npy +02871439-a392e8e541daf1d9b33454de94308f9d.npy +03001627-5ac8b44ff77e5490c8687ff9b0b4e4ac.npy +03211117-14add565ff90153855f9913e822d5318.npy +03636649-dc6c499e71d04971d22730b0728b2fc9.npy +02843684-b4449f8b823bdba634e9af37b2b44021.npy +04379243-5c8668d215fd79079a037b4abf810691.npy +04256520-523516236632fbc8c799384bc2c5517c.npy +03797390-e984fd7e97c2be347eaeab1f0c9120b7.npy +03624134-7cfcd09e09a697f3d870ada59aadeb87.npy +02871439-28af0f5a5e055917b52c730840dc727f.npy +04256520-26d36969b0ef62b1c2c449c0c0579ec3.npy +02933112-9460ebcbd28a8cb7d5a4a04ac21f0578.npy +02958343-7c7e5b4fa56d8ed654b40bc735c6fdf6.npy +03636649-6ccb43088eda061dbfc838749f053cf9.npy +03001627-413a7b8c5de6dd4ebb7b779fe99ae983.npy +04256520-776e86412e7f3c6dffb78a7278f8e374.npy +04090263-f955bfc9ff0d300cbd2411bccc731f79.npy +04379243-c8662ebf433759bd4bcc3951a8858950.npy +03467517-b2f7148aedd45f2e48067bd564571c7d.npy +02958343-31998170afc1a0b9d13bda570aea1f6d.npy +03642806-519e98268bee56dddbb1de10c9529bf7.npy +03001627-bfc6b2328c9c12bf283b00891f680579.npy +02828884-7b17313f2c00178b2a4d67a8ec314d2a.npy +04401088-a53b3ac989d9e6f35f8a15a7cb97bf7a.npy +04530566-49665c3dca5441d77c0ab7347b9e831a.npy +04530566-72d110284cdf597e68b6f3ae18faf6b7.npy +03991062-ddabcd35f817876272d7be5a06d0679f.npy +04379243-bf3b3076b1f43b8a855931d119219022.npy +02933112-5217e7aa71d06df2921dd903dd0b8b17.npy +02876657-948e374b08979da230612f5c0ef21eb8.npy +02958343-d9deccd1a5dcd5d1b7ad70a0cfa5f7b6.npy +04256520-8aa7651cbe3651d64af957103f4767ac.npy +02808440-68f9ebf8529d567ab362845c6edb57fc.npy +03642806-fd54faba3bd95b6d6d59d46ccb8deb56.npy +03467517-590110ef2859bc70a3063540dfdfeebd.npy +02958343-e95d4b7aa9617eb05c58fd6a60e080a.npy +02933112-3332c4ac1fd931d01586ac387fea1cf9.npy +02958343-17600a4881b1ff6a5c14de0cb75f4d3e.npy +02958343-51048ab1eeca5e8dee79ed7216eaef91.npy +02933112-11ee3844cf96c7194da5feafe6f1c8fc.npy +04530566-aca0172e1b301b8b60c68a106ad561fd.npy +02958343-298e8c0d9ce547b4e1e2aee44e822aa9.npy +03001627-f73dde8df5d0e5c7f91663a74ccd2338.npy +03691459-52e710a9bb750e3235cd53a06b1d2317.npy +04090263-596c401bf2ea21e55e9786b1603f45c8.npy +03991062-bcc3ae4de443d29b1b70317901324056.npy +03636649-a0963082bcabc46b762a4fefad9c8461.npy +02691156-f8f4cccabf7ac33b199dff268d0aba38.npy +02828884-2830e62e4c5fc707f155d75bbf62b80.npy +03636649-1c6701a695ba1b8228eb8d149efa4062.npy +03001627-bd7566c32259e41b4c161851ed2b4e4.npy +03001627-4e5c18c87a10f050e7469a3f8248f48.npy +02958343-1e6e7bfb08b6b44d615949fb78ffe44f.npy +04530566-fddb69f72a853e2f8ff5243f1df2529.npy +03001627-44b0b359d2eab610c2a3b7c9bad24907.npy +04379243-827af0ff0d9eaad196a3517f50eeb9f4.npy +04090263-71d9d636a30ed1e7d6a22172ba0f0af7.npy +02924116-1aeac7d5572ece389cec6ee5e26b0519.npy +02828884-7f7956f11a1fdfd0d81202a54291c0af.npy +03948459-f3f6678898938575575e33965575974.npy +03991062-486eb0ed2f97b9fcffc6e457221b9271.npy +02958343-797804cd4594553156b22cefbc2dcb87.npy +03636649-ea5ae3cfd142c3b923f93f957094a824.npy +03624134-9c7caa0ce8694300ab448fe46134225e.npy +04379243-30e12322c7e23ac358db0ef36af1d3c5.npy +02992529-5cf5bbb8f745033195c9a4bc0e92777e.npy +04256520-724ee53f18ea8e77cc166099a6fe7573.npy +03046257-108b7ee0ca90a60cdb98a62365dd8bc1.npy +04379243-18be1556eb4da5af7ccf848ce05c84be.npy +03642806-7bdac195f81588ff743bd44138e7d2e5.npy +03211117-75617d66e4d82ea2318461dc09ee739c.npy +02828884-b1adfb9857fc98fc28fbd1dd69384cf9.npy +02933112-73c2405d760e35adf51f77a6d7299806.npy +02691156-db0c0fc7ce05d372311e3590f044c241.npy +02958343-fc1840952ac878c99b63159808b36877.npy +02691156-f1210d8f895e40b663c15773e7567372.npy +03001627-6abdb0b46d2a3fd02813aa30be7ebdbc.npy +02933112-140c308db70cd2674da5feafe6f1c8fc.npy +04379243-57754ca0ec4fce12990d726e600161b7.npy +02691156-521b82ced564aa2c8ee17de2c75c8e96.npy +03593526-f84313fa79e1bbd3d826e39f6130227f.npy +04379243-d3c31829b1295d0abf22a5ca4fa4678e.npy +02828884-531658856a6347b1f4b6538438a0b930.npy +02818832-bf6bc80cb11e131362cc0ece5cfe0d88.npy +04379243-e0e00d2012c4306117fcdb9c02a9e950.npy +04090263-5de8bdd7f586399ee0685d22b2927984.npy +02958343-d21ffd4838ff2ca75a30f4aa03635c5a.npy +02880940-5b6d840652f0050061d624c546a68fec.npy +03593526-6e97b8fd720790455ca1f314f1afc186.npy +03790512-c1acd4ce749a46a6dc2693ab94b1f3be.npy +04379243-3fcea883442d7e5bc0f947750540fb22.npy +04379243-3f9b11fdf6d5aa3d9c75eb4326997fae.npy +03001627-a9ee7abdaba4ed6c14817c31e6492a06.npy +04401088-692e46bc27bcdcebbdc2330c91f5a859.npy +04379243-69d4ba3043aee963dc2bc8a782be94b8.npy +02691156-4ee420a617a2bb40bd4fd4a5b9107dc4.npy +02691156-f13827d156628467b4cdad9a5bf52dd5.npy +03467517-a7f449a1f2cd1f1693f0194265a9746c.npy +02828884-5a383d9a0e67caed4ea8cb420cbb292f.npy +02992529-69b74f6c66dc2adf5a627be422951096.npy +03001627-295a3bb2aa43b691ed2d43425218e827.npy +02958343-98316f2e772d60587e5e3333f4cc9f83.npy +02691156-f2975fde05d9d63eeea0c0561850e04e.npy +03001627-47a661b489119b764b3c42e318f3affc.npy +02691156-ecd19c1f74064962c6603e997b54421a.npy +04256520-c80c48b901ad94effebad4f49b26ec52.npy +03001627-86a25532f255728fdaeb838d0771f3b5.npy +04256520-3bc7d4d59503cc92c1a25f36f85c3fd6.npy +02876657-8f2b8d281413a8bd5b326e4735ab9003.npy +04379243-ed45493414f9214687694c57464ff1e3.npy +04379243-41283ae87a29fbbe76bc197b3a3ffc0.npy +03001627-ff9b59e29b547dd504721639e19f609.npy +03001627-7238d2ade707fd1e6c63b8b48495261a.npy +03001627-2acc2a87aef7cc559ca96b2737246fca.npy +03001627-afbd7d1e68be93ac35836c728d324152.npy +02933112-c5212968cd5ef1dc3c6e7539caf3791c.npy +03636649-60697ef538d1372f5bc104fbace43d56.npy +02691156-98c0c90dcce8f9ee3ba77af508a192c0.npy +03991062-f1dfb16470f5c7e22553e89eb4de13bf.npy +04401088-fecfbab790d979a25d560b84ad8d9e87.npy +04256520-aadc03f6499b5ec5b60747861a92b009.npy +03467517-86088a6aadd3e08963e148e250c0340d.npy +03593526-cb9b25b587bad917e6085a0a38e2f255.npy +02958343-7825218160564f137039b7b9eba2e0f7.npy +02933112-d410c925c5e8ebd65b7f630bf166b499.npy +02828884-a4c8d232f7943e61af8dca8fa046a737.npy +03593526-d3e31e11258926104d38ef17af2f7d70.npy +03636649-f1cc6b6fa75bd67ff51f77a6d7299806.npy +03001627-e56087cd55cce8b4f41a4361d0ca9bc8.npy +02691156-48cb2de06f46cde25ed29e0a9f14425.npy +04530566-9c4d83025107322b2aed6a9a322ced74.npy +02691156-e4bdcd6baad501ab2a8b9d468136b0a1.npy +03001627-df59c2ab638e5bf47c4b9c3e153dc1c0.npy +03001627-ba3b1064eddca7212d19175e7d19b7cb.npy +04530566-31f7c298ea24bb99847c4e55bb965ab0.npy +04379243-f73d62321bd0a5b7d42ec7e303174a87.npy +02828884-4fb9527f357f37f99dac46bde4c69ef2.npy +04004475-71bc31bea1c38cc22e90f5e9b0ad48f4.npy +04256520-b16b22f49cfd1d2541dc8e09670d2b5d.npy +04379243-82f5867145f64346a9cf1782d21bd9ca.npy +03691459-a88fabb4286706afbb9b205a4c97698a.npy +04379243-bd4662a53f8efdd955f46d55537192b6.npy +04530566-5b6044746e12fb6733b68f5ec4e8a690.npy +03636649-9af0807b146c564a45c4ecb2f4b73702.npy +04379243-72cc0fe296b9172617271868b642acd3.npy +02992529-a523f6e5662f8f178ddf0e44d13d17e3.npy +03211117-dede15a6e1d27b9bd2458bf307c1dd72.npy +03636649-e1fe4f81f074abc3e6597d391ab6fcc1.npy +03001627-f3e50f6d0b7b293035836c728d324152.npy +03467517-13c12d297a29357919179b9e5a0c010c.npy +03001627-5b1d0dad82acd6e5893104fdda835c64.npy +04256520-2fbf971de875a1277df50de84a56e505.npy +03636649-b54f6d30b6edd7f1579cea75b38cb7ce.npy +02871439-a96c3d0ab048b72d1e678557cfa9c9cf.npy +04090263-87dfac7fdf6e81bacbc6ff5546f4ec42.npy +03001627-9527b62eaae8f007259ae7b2899be714.npy +03337140-3a40cea19ff1dea4ce5d6e9371bb5c33.npy +02924116-5271016b64559e2141cefd10ce5d6cc0.npy +04256520-f98615e51a596fc5c05575120a46cd3b.npy +03211117-cfe8df98fcd4964d9d58cf21d5faaa2c.npy +03991062-70a30729c23aa5ab5425a71c247ca5d1.npy +02958343-88a476c48a4cb5e72d0c578824da8af5.npy +04379243-c547a17e35360322fd6501c4dd41b22d.npy +04379243-ade4f7281cc55e016fad58965decd164.npy +02691156-41c7470ce9ecb74b6f9423fcc87803f2.npy +04099429-b66ae0c5ca74decf613bdc6883aa3f40.npy +02691156-5ac00867c7d78b1690b1d6deb98feec6.npy +04379243-ea3bcd9e6c4205031964126395b17c2a.npy +04256520-40cdebefbd3bc2634c7384dbb75cab0d.npy +03001627-a09a88c11d0b27368821ad3452f1c8c9.npy +04090263-e0513d1ceaac23ad341b8a806253912c.npy +04090263-fccd8e7b6bb1a6eea1ce1dd4c7e01188.npy +03001627-4178fab56c04a32ae8f8c11a24c52ebb.npy +02691156-d9eaf9c7d58279dc9a6e43b878d5b335.npy +04256520-22b11483d6a2461814038d588fd1342f.npy +03001627-811c349efc40c6feaf288f952624966.npy +02958343-532070461b869aa7468dbcd58a793b1.npy +03991062-7aef12ad7f602053d4d8765e3910f617.npy +02691156-c1c341e597c01d3814a46d7ec44fc258.npy +04379243-2367a0e01767df36dc40b058754deaf8.npy +03636649-a1f602d18e9c0f06733c22d8b8e1c33d.npy +04530566-6313352481b445a8ecbbed03ea2b4cdc.npy +03211117-dac4f4f039a9467f46d83d16be057f3e.npy +04090263-a262b6955756cbea34250dfcf5a9a6d5.npy +03710193-a1fd2eb471c5b5345a3d5de8976cd08.npy +04379243-e7c8486921138d5c7ff6ace05b36a5.npy +03928116-6a0839a9bd3c10b7f2c5403cbf111281.npy +03211117-a536c6a5f1a118feac653254a68e1397.npy +04090263-58e1eb81bae67052c79f92df566f8c6b.npy +04379243-161be2d2421c18154e61d5e9018b6ba9.npy +02828884-77fd0def3c3469adf155d75bbf62b80.npy +04256520-d6d69d04e3c34465e9fa215d22832290.npy +02958343-307e83044ed81f6c473f10e6caaeca56.npy +04256520-cb643270a86e8fcc19fb4103277a6b93.npy +04379243-60c0cb7599fddb50d3d709dbfce9caca.npy +02933112-1fd36ae1d93b6f3fc59350d819542ec7.npy +02691156-611c65a9a9099c6121e570d3da54bf9d.npy +02808440-b450fdd06d466db83321831d2245cf06.npy +03001627-80e45b0a5fc1d3ed68bbb8e471856979.npy +03325088-9b68d5578e58f8c46d0157e3e7a8917c.npy +02880940-be8a2f8460a963426a6acc5f155f864.npy +02933112-3e858a898accc14132f8567794723a79.npy +03467517-e3f45b5945315a939526648647837830.npy +03325088-227084bd966b704d50da8b99982a3057.npy +03642806-6a9cffdd120720a6512143cd347a4650.npy +04379243-ced7d80d220dca01ce5b275ea2158e2.npy +02924116-5eecd4415ae176b6c6bf3b18b8ca71a.npy +02691156-cccf4d96e0e3d728c93b40751084c22.npy +04256520-882d5d8f49e52e81a53276bbe109327a.npy +04090263-32d410088758f9bb89dcfda443251892.npy +03642806-56517e22979b563460ac9d6174947ab2.npy +04379243-523ac3575244c7f3a130bbab7337a0cf.npy +03642806-cb6ae19022733ef1956ad4a5a9b8400c.npy +04379243-c31fb1b1dc95160d8f893d87da13e049.npy +03642806-cc0535a34cdc7d676bf98d15712168f.npy +02691156-a5cd14be786fc8175e9e2656aff7dd5b.npy +04090263-12ad493bc65380df1ec84866750af1e6.npy +02933112-b399f7819e05c8bd492d9da2668ec34c.npy +03001627-21e0ce3ed3e9452c93271d2223fe04be.npy +04330267-58caa0426be5f71f41965be83b7745a.npy +03046257-f7f1df271259f793ba0661808286ba45.npy +02958343-5503658520e08b519b58a6529594c9d.npy +03325088-92637cff21142487d84d1b7b18d6e7c7.npy +02691156-657439efe649f57f47f8deec944763f7.npy +04401088-f6679591247bc328afb07a946d621b3c.npy +04379243-b62798e1d1075115e870ecf4c364a4c9.npy +04401088-dacb3f6f6b0cc7a52b1abd641c06dcad.npy +04256520-5f5c4e66f07fc2695c0be177939e290.npy +04379243-a342324aeff75ec7983d269bb8e4ede9.npy +03001627-a4d7c8b97066cb74f63e8e405d49b8ce.npy +04379243-80e1d8c228dced88ba6d62b5b05dcbc0.npy +04379243-fe20b0cb9c6a922d58df8eeaf3dad1c.npy +03991062-6ba49cb9ef1992a2a2c59a4d90e63212.npy +02958343-445185842d893b6978fe949fc1419876.npy +02691156-29fd29045703ff18b4a8b7176ed97248.npy +04090263-ab379b3916c45a78710c119014476e8f.npy +03001627-2c4d7d33ecb486532569827d39fc0af3.npy +04256520-7ab86358957e386d76de5cade2fd5247.npy +02933112-8cf41a94663c7fe24da5feafe6f1c8fc.npy +03211117-9ff60c2ab8d5a15abad8372756ee3232.npy +03001627-bd1787066323c7a64424fc4d3c9cb157.npy +02958343-dc3c6748e5f96cee9b3f352e6fa9112e.npy +03691459-d1274fdcd4f8a611fe10244ee697dc96.npy +03636649-d385523f0cd93d48d6084fb53091249.npy +03938244-24b7f744e060522993450a6db2a946b4.npy +04256520-7d71922494b8788ce10ddc5f810dd417.npy +03001627-8d1616ada1d6f239d1f4836ba5ad2863.npy +04090263-39eb4b7bb1d93d94437724fec373d206.npy +02691156-51c0b132806335051592a2f89cfd307e.npy +02871439-5793619650b38e335acd449a2ae99009.npy +04379243-fe4984dbd32e69eca4ba22b64b537bba.npy +04379243-214e9b1346a498c0f51f77a6d7299806.npy +04379243-68bdc363716f181c61b4bfc684868124.npy +03467517-d37d82695b935e59d57700c05b1862d8.npy +02828884-27fd962813feeb26be25fbd47cafc694.npy +04379243-11fcb3abf0a487b9c3bd24f986301745.npy +04256520-964887dfda95963fb0957d845ac33749.npy +03636649-ce8a14614b85a8fbfcb8d8c6d4df8143.npy +02958343-7434c137695be0eaf691355a196da5f.npy +04379243-a3d5d0122b01f7be62a280769c3934a3.npy +04379243-e02925509615eb5a4eaf5bbf36d243d4.npy +02691156-8996445c6d2407c0fb5c1b0f759e2bc1.npy +02992529-1727e7aeb3d159a57f521a3dcd28e9d2.npy +04530566-a88f4ec8440e412c92336765b86c93d9.npy +04090263-1205174a90e130bf595b6fcb838bee85.npy +04090263-41c55010eb7ab373a4dd752ddde80fb1.npy +04379243-9f7a8670a87dbde9b50d0c6a0c254040.npy +04379243-f741f1bb6a7ef8ff7916bf6f8da94ee5.npy +03636649-3a0edfd418e020b97f32712aef0efc5a.npy +03001627-26638126794a48d9b0957d845ac33749.npy +04090263-7ccf43d35755a35976ad064d1c5fdd7c.npy +02691156-f9589c9b900fd33ef23c3116d040903f.npy +04379243-780799646ab0a19b589fc18f8d1e43a.npy +04256520-63484c8326f8fe73cb922bcc33df0268.npy +02691156-2d43bb802a8faf0bce15d210eb57e565.npy +03593526-1febe89e0336d5bcee106795de609335.npy +04379243-5689abd8ba685b3e72075e8b19ae0485.npy +03001627-280fe2696faf0f3a53e14f34c202d656.npy +03001627-5e706e87ca60bd19ecb01bc908e8cea6.npy +04401088-e2784eee13f340f2195cb740f5da17ea.npy +03642806-6103fd8c11413be975e42c1faa1148bb.npy +04256520-fb88e94765c2b3e9f16b2a6e0465cbb7.npy +04379243-b08e0a90b1bd3f0879492e1986fdc4e.npy +04379243-e88b21faa1d937f3695cf5feae151847.npy +04379243-32d06518fd07df9bcf004563556ddb36.npy +03642806-9f4a0de5fb60ca3e1ec0c47eb137bcb.npy +02691156-5d2f0bdbd08be6fa3105bdad0abb9e24.npy +04379243-14ae5631e7dfa10430bbd4cddd04c77b.npy +03001627-c04c13649c4cbc5ebed0f345f50b6a5.npy +03001627-2892ab19f2d3a88a3ee8e30b29f70dfc.npy +03691459-de5ecf353cace18574b0aadaa58fdcf7.npy +03467517-a628f408f1062c0649788b38f0ff60f2.npy +04090263-c1d5a68f196d647fb5070c7ac310bcbc.npy +02691156-b45e5b92bb4623ff151f2df200a24ac.npy +04379243-45722fed3a3035fc59f8e31ca87c470e.npy +03593526-de61c6f2300249f45dc9e54641a3f5bb.npy +02747177-af8ae2bd4ec21bfe63b2acb037dfbcde.npy +03001627-5e2003b18752e5f82f809039658ca52.npy +04090263-ea2d9117c341df9377b7d0d4764c121d.npy +02933112-d88116de5721301298fc1d0403f6ad0.npy +03691459-7e3e0b648aff4aeb6a6d1e86c6266511.npy +04379243-e1581daad0ddbbe4465d230735fb8831.npy +02958343-2ccaaa66525d7f095473e57e894e0ef5.npy +02958343-2262d8b1d5fc79b67211919686015200.npy +04256520-9af15fd5baed25b64b3c42e318f3affc.npy +04401088-cfeec23a9ea66a5021844676433a0aca.npy +04090263-281790c93c1f8876972d2a72136fdc80.npy +03325088-3dccc5e096aa99e4fe2ecb70903654e9.npy +03991062-2a7d62b731a04f5fa54b9afa882a89ed.npy +02958343-a6a1c91c92f86c463a93df79ef2b80ef.npy +02808440-f7c8d4e57a30918944221bef0fa3c36b.npy +03207941-14e9d064fe9d247127787a85c3bfabc6.npy +03636649-e4258a09db0c03bc97bc1a2d2578970d.npy +04379243-5cf6612712d8ad26c5c86021644af7b5.npy +02933112-5b08e72cfe785f4912de5317fe5b354f.npy +02691156-879a8f69cd931fe9f64801ad2940cdd5.npy +04530566-d5f0a8785afc39120dfe072b77502f8.npy +04256520-374fe2584abb594da094848ea4d06501.npy +02691156-edd9f45c7c927032db5e5b1ef1010d8b.npy +04379243-1d98ebfb72120470283b00891f680579.npy +04379243-d1611599e3dad7292f4c88fd91c6b1b.npy +02828884-7c33a6f55768b7acb97ad864945165a1.npy +03691459-5a59e8590b3f12580275d4a88484513.npy +02924116-ee672a58bf542ea464bcef064272eebc.npy +04379243-98108861d6d5235017b431cae0dd70ed.npy +04379243-739a97e0e3c446c15255bb0d3c16575.npy +04379243-7a8653592db2dea36518d4b6acd71be6.npy +04090263-72e4b314e45d67bdf371f38ed06fa82a.npy +04379243-9c510bfa2304c78480cd53d4e54e1fe.npy +03790512-7b4eb8cbc470d0d6d5dde04c96fd8146.npy +02828884-fbf16da56e709e422056b4bd5d870b47.npy +03211117-184a3f58220427c39fd28cfa9e6e405f.npy +04379243-90b0880e3c85c133cf7ff48fd8d30a70.npy +02691156-76788a2758e938f435fc197bbabcd5bd.npy +03001627-38732a2b4c03e7a8b7a8bf5e3604ae72.npy +02933112-444ff46c1275b83fefead98a255f706f.npy +02828884-1b9ddee986099bb78880edc6251fa529.npy +04379243-c712261a32a0efca4b3c42e318f3affc.npy +03593526-b828d1859065e0e4cdc03f207b7c6c79.npy +03001627-f1a1c9f231d2db078a8a3348259a374.npy +04256520-771a9729f19fcac4bbc7a6acbd8f058b.npy +04530566-5da7daeff2b24f23206066da291e8981.npy +02828884-5ee7a51ae38eda6b26b7fce5a7fdd285.npy +03991062-dab9d3c4afc644764732d159b629c6ab.npy +04379243-641f479a3b90e659282c910029b5cf54.npy +04379243-339b9707363c16d895341c0dcefceb68.npy +04379243-608ea98ce4a80a61aed393947b9cb125.npy +02828884-c20409a88bc98bc8ad5067eac75a07f7.npy +04530566-19b29e973ad05c71e0a1fe48a8d148cb.npy +04379243-22a67cefe94bd5eedb402a46aa8f1779.npy +04256520-a053322861de88a21725b4111480fea8.npy +03001627-b34b1a7cd8b645829d0103304b799f18.npy +03691459-24e25e63d6871f884358473f5b9be205.npy +03642806-7da4f6dcda3fc40db1ef4670cf6c2a91.npy +03467517-5df08ba7af60e7bfe72db292d4e13056.npy +02924116-d68a726ced8cd11848c6282fee705e22.npy +02818832-ab9e57b316f43962b738ef7a6757633a.npy +04090263-ff84eb89a2c7e1b55cd168ffead8840c.npy +02691156-53011f6c40df3d7b4f95630cc18536e0.npy +03001627-3aab16309520fb21dc0a8cba62d9a78a.npy +03636649-58e0f2ca80931a77e99f6f079f038d.npy +04379243-ba3120844f785a1430730ba8faffbad9.npy +02747177-f2c7e1b8112282dbcb2a965e75be701c.npy +04379243-b8411c6434b79e59d6686dc2df08cca5.npy +04379243-c27a1c6a26642c907ecc778b34d42f32.npy +03001627-1d9bc60209572861473f10e6caaeca56.npy +02924116-cfcf79d337e79438c98c13d6112727de.npy +03948459-cb4b38a0535101f2a39dc4a567ce225f.npy +04530566-efd174efe9130399be7ca2216dc1576a.npy +02801938-133d74f10a0401317773da01b1ba21ef.npy +04379243-b3cadc82852f5f5381901288eaf14401.npy +02691156-3948ac8a29ae42c761f027f2a55df6ea.npy +04256520-65c32eacefa3f4fe2058afcc28d23393.npy +03593526-1a01c2d7705193b4917cb569753af492.npy +03991062-d0537f977c7442aa2e51995ed62a7d39.npy +02691156-8277c0294461b76e8405970680284869.npy +03261776-e33d6e8e39a75268957b6a4f3924d982.npy +04090263-f0cdfecc69f4beb7fd434dfa483c57fa.npy +03691459-f7366c0025b2eaabf5fb60584950565b.npy +04401088-93d617cb7bf7558671fd17a89eb6aa70.npy +04379243-7eafe1321f7d566c9654713ddaad32c7.npy +02992529-88c64c14d4b6ae5aa7636d58d56f8570.npy +02828884-1ebdf871b03ae445f4b6538438a0b930.npy +02691156-db5fa6a73bbe6d35ca8607f540cc62ba.npy +02958343-eec2ea5ac4e048836a2345809e2bb169.npy +03642806-8834560018510194d8caaf6298f89d14.npy +03001627-7ee09fdece7d9142afdb9a672b7d3b8a.npy +03001627-5bdcd3d77e1c91f78e437a27fb25efdf.npy +02958343-da59928c982bc34a2a9eb0f146e94477.npy +02958343-ca6baf5768bc105ace827f20895c88ad.npy +04256520-470bc951c8b9bb5b4ea6967a5607d572.npy +03001627-a8e5e4016c44f896b1b3c8adf02d88.npy +03636649-a37695d83a39adb52866fbd701f50f71.npy +04530566-4ce56405f7f67d3c38cd6a6c9620e96d.npy +02924116-e311aaea6c2662e7193d7855ecfc1bd3.npy +03001627-e8fcc8054e445a0c20768660cf080d12.npy +04379243-c3732b612ee72d7f1071105723d4cf63.npy +03001627-7e7f1989e852eb41352fc7e973ba7787.npy +02933112-8f39d603e733eb58fcbe4e14ff0c4707.npy +03001627-6731a24561fe44839b92627dbcf8ae26.npy +04379243-910db4c45df40b67d3e19c2bbe0ed38c.npy +02933112-c7418e21982dcb508c2f9e4176bfe555.npy +02958343-3ef364afe692557edd344a2b29517bb.npy +04401088-e2ffd39f88dc381c3455cac94a339dea.npy +02933112-be1978696eddc1e980a88936375f2ef4.npy +04468005-44fa6c544b0e67ac4c4a58bade1fd64d.npy +03467517-4614d233c54498408f3f9a4bccfe246c.npy +02691156-2c3df6a4d0ddc9a69725372054c2f091.npy +03001627-9b6f17ce2db29c4c9ae35d137ece64f9.npy +03001627-e59cc0fed1520985b21bc3cf138f79e.npy +02691156-fa27e66018f82cf6e549ab640f51dca9.npy +03211117-d206f9b91dbe5693cc5743e8d662956.npy +03001627-f8c5604f39699e0fbbc2b2aef664ba29.npy +02933112-ac7935b217aeb58e19ca41cdb396f36.npy +02958343-4cecc9df9c777804816bd8f64e08b2bc.npy +02808440-8e22e5984d5149c835e1d1ee0e46a9dd.npy +02958343-ea58938dca17f3853c9cf79df3851b10.npy +03001627-11d4f2a09184ec972b9f810ad7f5cbd2.npy +04468005-bfcea023feb6fbc15c636c73fb4546c.npy +02958343-2dd2a5154bcf52c2aeebd3372dbf7ae6.npy +03636649-c2e2cbcd1cf9a5bcfcb8d8c6d4df8143.npy +03211117-a0383e1388e74ad8b0851ce87f32a267.npy +03001627-976f1a2aa3224af329d2a9b1cf0c2446.npy +03001627-4365a4d98c9b979019149a7f35de06bd.npy +04379243-1ad008783272fee4c3bd24f986301745.npy +03636649-df0823f1c81eb6bbfcb8d8c6d4df8143.npy +04379243-dd276ac55465f51e1457f3eb061a2fca.npy +03325088-c15d54b2a98d4debb36717b39afb6ad8.npy +04256520-82927175fc00ca7e593ebeeedbff73b.npy +02958343-bc9cd53b74743dcc8772afa45900d07f.npy +02933112-b8300f2e4a8adf9b31de0931bd5b560c.npy +04379243-9245ea14da5198b64b21175170c559e7.npy +04401088-ed004bce9e457ab037c7c775913296f5.npy +02924116-69233ecfef5d67e1c00633847c439a52.npy +03207941-a5a6b467cc0e55eb159fbcda62e85465.npy +03001627-4f520217376a00ac3e4dcc9f0008b73e.npy +02691156-b356ef92a2052648b8494b55ada518dc.npy +02958343-de6b2f1796b1887d84e2301109bd5b05.npy +03211117-ac06493582be880388c7562a134f5ac2.npy +02691156-6a861b7cf2552818181edaa32d7673d8.npy +03593526-26795095a52c788f664b3b9b23ddfcbc.npy +04099429-9b75297c580ff937b61ce5beb9f92726.npy +02747177-a23c4789341aa242cb2a965e75be701c.npy +02828884-d34e91db39030275fc94591f6f745953.npy +02808440-4d7ce41fe16725c5e346f79b9a86790.npy +03991062-478bb08c9de3c176a2c59a4d90e63212.npy +04379243-bccc9bc81809cc0d31a3de62b78a7245.npy +02871439-4552f6002e96cb00205444155ae5c84d.npy +04256520-43e3fd98669121eb826fc8d57346a2e4.npy +02992529-7f41f4b186fdf84c7ecaf377af2046d6.npy +03001627-5c70ab37293d81911b17743c18fb63dc.npy +02691156-796bb7d6f4d5ce8471d03b466c72ce41.npy +03797390-c0c130c04edabc657c2b66248f91b3d8.npy +03467517-8b8b084109eef6d81082f2ea630bf69e.npy +02958343-7d7af9263109f8aed4fdf31cc2d78fd0.npy +04379243-25bff1399600790bc3bd24f986301745.npy +02924116-ea5ac377dea6214c9a54987d702a03ac.npy +03337140-3d35053e01610058ce5d6e9371bb5c33.npy +02933112-94883014b900c6d6647872b8585e132f.npy +02958343-10e15fd62309a13d1812324a4c0d910.npy +03691459-fa37905b884bdb169f69aafaa5236e51.npy +03001627-60a1742f1cda02ecce5a69be7dc7d68a.npy +04401088-a262dd4b61d374c8b91c0e89daffb776.npy +03691459-f4ecacfd4fd61afceb34db531a289b8e.npy +03046257-64de924c24fb12968b48a6a0b4b6d38.npy +04379243-cebc20baf900f828147637a0471f2f73.npy +04090263-d08bf745e6f7e4b14aef47a2c7bc343b.npy +03325088-f5b60361fff872a676c18e71fd49c4dc.npy +04379243-a568d1602f94c814f8a51dbffe0021e4.npy +03337140-b8e0513adede8586820018801b237b3d.npy +04554684-da021d3f1eceeea49ffad002249ee384.npy +04379243-bfaa1c23d2622422ad16260d4d73b56.npy +04379243-a98482ce1ac411406b2cda27b9d80e15.npy +04379243-569095c884b4361f77161ca74d215eee.npy +02828884-f4b6526b744290ee5459024571014ce6.npy +04379243-443eca86041e57ab1e99b149cff6a230.npy +04379243-f39e46c8468ba7f07ba6f8f10959534c.npy +02691156-ab9e9045e6c7bc6537678474be485ca.npy +04090263-7fc4dd8163f4a67d6327d46d93c637b.npy +04530566-705df680888e17ed8841beb2e0280e42.npy +02691156-11d2af04fad0a7e2ce19d55bc5e6a406.npy +02691156-6456e87ff00e31a96efa61580a088aac.npy +04379243-cb71e1cf52531981593ebeeedbff73b.npy +03001627-741ea721bf610a9b9225fc8da7ab1c1a.npy +02828884-f5ca026c6cb2b06b56be5749887a17a3.npy +04090263-6646f169a45f40bfc510111f5d1cfcfe.npy +03636649-9b8f6e93608fb244aec118775e1a3eb4.npy +02828884-ac1b9a34ed8450bb2644d7d4d7ea2c7.npy +02958343-9803af6123238620247a5be450795511.npy +02828884-57fc8345fc8667a4d2b12aa6a0f050b3.npy +03046257-b9814ed05c91121edc6e40059e75ca86.npy +02958343-83f205b7de8e65e517f9d94e6661a9ab.npy +03636649-ab02e202accb9b4b65b77a565916c7f.npy +04379243-d330377051e6180319fb4103277a6b93.npy +04379243-3a8b062c50c0a5b7977a08097a2f2d7.npy +03636649-7cb828eb3b8e424b1e88064118b89a3e.npy +04379243-a30eb4a16f30f29498648daf3d784f2f.npy +02691156-43e078c68d2fa3b4d5d30e1306d90d74.npy +04530566-8b5ccc3b1eba2c9bdf921d807a1adbf.npy +04379243-f9573b0425b08a38f673eef39387003a.npy +02958343-2b0207d7f6a6f23bf0ff8cc77ea4c273.npy +04379243-b6457c273fca48f8b5b7c35a8e7396f2.npy +03636649-5516c456d95ec0df2de0bc4fc4d02dd6.npy +03001627-b67aacec8e98edded0b19424de5f7fe4.npy +04530566-b5a1facfd0a023251e6afa6efa6add34.npy +03211117-cfac66fe0cec664a8069dabf6dffa846.npy +04256520-1f899a4f5418158f6721e288acfdbcb2.npy +02691156-da67955425ffe66071d03b466c72ce41.npy +03691459-563b0c299b32e73327ac18a9705c27f1.npy +04090263-2e3256b3de213e7ad87c63d8b3018b58.npy +03467517-3ddfc6cbb08d60b393f0194265a9746c.npy +03642806-6227e7dd1a391e8d54f22ce0a3592d5.npy +04256520-91ceafb0b1b2008d98223ee0bdd50697.npy +04090263-32909a78138cab24d4f4334cc3aff513.npy +03928116-1b76644af9341db74a630b59d0e937b5.npy +03325088-92bff24b0c36862e979c556124bee033.npy +02992529-625e2b043a61452b80d5f0084d375f75.npy +02691156-329987191cce68bfe64acd170567d820.npy +02871439-bcc620a199d0155e6bf60d91b08331aa.npy +04090263-21d6c28c11dfaa72fb5c1b0f759e2bc1.npy +02691156-c9be9f07f5ae7c375d7629390efe0a2.npy +03001627-971539fb57b476d5c40593250b73d0c7.npy +02958343-37a7f79b9eeb5096b11647ffa4306609.npy +02818832-6df4a4c52c90d70d438e4ded908f7146.npy +02958343-4618489fc34c3367323a23bddac1281c.npy +04256520-30e95358ed817addbaa0f6b191f18222.npy +02871439-d486f1d668cc1376a3fb70cdc0074f48.npy +04379243-7364fd26628b7f6a3e0881f7de9a6e52.npy +04090263-3d7dfeb58c481e88e16974ffd95b0c65.npy +04379243-9d547553b8b68c062f3110a733450426.npy +02958343-bcc3625a31bea6cd6a2345809e2bb169.npy +04530566-adbbaa33c52c3b0d5c0be177939e290.npy +03467517-1fbbf4450cb813faed5f5791584afe61.npy +04090263-d5714c28b82df83d8d5783af2345d2c1.npy +04256520-1aa55867200ea789465e08d496c0420f.npy +04379243-2b8ffe339a50f0a5f51f77a6d7299806.npy +03928116-63bd5dd05e693b762cc8c3d5fbecbcf1.npy +02876657-48202d357e79315e45891653421dc140.npy +02691156-7b4b931c5b6f8167295338c0e33a082c.npy +02958343-261f4a30328cd40960a676833b21afd4.npy +03691459-c805f5a262130e6cb4f6b6fae7a188ad.npy +02828884-98fe81af9b74e4c278d386bfa54545.npy +04379243-35e62b9c23928bc57f5df2bc47846a54.npy +03001627-7a338e9b13ae5da3245e874042d8b8db.npy +04330267-e3d4640125f5eabce793cc5433bece89.npy +04379243-2f8395ded89cf84f40b4c5428883e585.npy +04256520-302fc57b3d180ea4733824eae5cd9ae.npy +04090263-345179cdbb6ac9da4dd752ddde80fb1.npy +02958343-bc803cea33d77530a5038167d6f08983.npy +02933112-927ac18cb336cfe3df289a3ea5d3a440.npy +03636649-6d52f0b6141dee194a200f5f1797d729.npy +03337140-b6e0738a9b5b4d572fcdb68f2467747b.npy +02958343-a4b793df04e3bdb11fed6082009db27d.npy +04379243-75b0a926c795a110dd965e6a8387505b.npy +03593526-3585601ea0abfdfb409421506a05b6e1.npy +03001627-71aa917674beaa2926d044baef0e5df2.npy +02691156-47006ce926cd5519b3f2b01de37c0b29.npy +02992529-5f4c8cb8b3feae768c641604807c82a.npy +02933112-146c3a9cbe3d8f703fe047712e43e185.npy +04379243-74cca53996772272e91a460ae1e88b96.npy +04256520-90275a9eab184067e2ca61e91f2755b7.npy +02958343-b21bc9621960f418c330b66f68c70be2.npy +03691459-8a3b591b72d0f5326d9bd07411a71e3.npy +04379243-f6497e9f02f50c98c065481f0c2ebbca.npy +02828884-3461cf51ad90f09ce3dcb92695647492.npy +02828884-e8ff891162fa20607572046550aace88.npy +03046257-2f570bb2ab6bcad896d5fa1ee6ada8d1.npy +04379243-ecfb5ad31b6e40b72b70eac6546e93fd.npy +02691156-f9d30b24d9651ee476c772fd813166d.npy +04379243-4ce0cbd82a8f86a71dffa0a43719d0b5.npy +03325088-fed454953dfcbb4bb362845c6edb57fc.npy +02942699-9b4953f653bfdd40ea41ceac179ca4d4.npy +04530566-70e4afbe0fa15ef3bc1624bd222f607e.npy +02958343-56dc27e4374cf87132eaaf3b7c9989f6.npy +02828884-95096288ad7e0777f155d75bbf62b80.npy +03001627-e803b31e2185d0405784b22e1081a3e1.npy +02933112-c7a7a1254c5d98b8449f1c29830da6c6.npy +02691156-ab2f47cda3622573c231d70e1e0cc567.npy +03593526-7797bf6a6f3f4a809e9e01b160c24e12.npy +04379243-3250cee2b00f2bfc9141594c44ac35a8.npy +02691156-7175100f99a61c9646322bce65ca3756.npy +04074963-dd110b09266edec5fdcb551a4a7a3f9f.npy +03797390-9fc96d41ec7a66a6a159545213d74ea.npy +03001627-38444677513af4e7bc41009043d88b0.npy +03691459-221a981adf503875e17b9e33c097dbff.npy +03691459-62021776119f573bc7c51d4ea74651a7.npy +04090263-397b2068e029945216b34c3751bc447d.npy +03001627-2b8380ed4b779be7af7c7ad2549a1b15.npy +02828884-b625936e3db6af6318df1fa50d2b64c.npy +03001627-39d1a6007a4a29fe492d9da2668ec34c.npy +02924116-335795e7ab1cb5d84d44f5db04bf14b8.npy +04379243-573922f28958f34446bb945d4cb1ad55.npy +04379243-99224e792b7a7f7bb98f36033d4304b1.npy +02691156-26f8a11864fd6bf7b68211fcc7956ac6.npy +03797390-9426e7aa67c83a4c3b51ab46b2f98f30.npy +02747177-4c89f52fde77d653f4fb4dee5181bee.npy +03624134-28f21da67a53771772c447ef6e5cffc2.npy +04090263-84ad561ea0b15621e33e9d99abaf3052.npy +02691156-558d3d7e6e78f2d941756cc47b70ca20.npy +02691156-aafbf69ed97274cd462a084c3c6d8557.npy +04379243-d956062bec339ab6c67bebb34dbddc1a.npy +03593526-396534e7ea5b33c482db9fca4b68095.npy +02808440-311c8d3738490a553321831d2245cf06.npy +03691459-ce90cf5be2ffbf92505e438c8a36b3e7.npy +04379243-7c07ffc0147bef7df3c9c1464e55d580.npy +03001627-ecfcc42f2386ef37f51f77a6d7299806.npy +03636649-e8006513d5f46d79e738f481f8560d58.npy +03001627-260f65e1b1baaf7c7b707c797539b200.npy +02933112-221d442d733de66144221bef0fa3c36b.npy +04379243-7a32aac4ead10e0bf51fa0238791f5dc.npy +03001627-4f6a5769aab5de542b848a53a7028d2e.npy +03467517-6e8b6c64b425ab9fcf31738f69fc886a.npy +02691156-32a2723086f770e9233d80f3ecb7c6d3.npy +04004475-63ef3350b84efb4b5d45f15f95346a04.npy +02808440-2cc413a8680b6269b362845c6edb57fc.npy +04554684-7da46c2fa47deac5f509767312277f4e.npy +03636649-7474deb91f55a63840719e09f7e71f01.npy +02958343-963a4fdf819cc5ab3174b45571ecff3d.npy +02958343-698cface060385ef9113c2c7a4e97ab.npy +04225987-937c41b3d0d3a87fad1f278e1513f3b7.npy +03710193-17f741662540b2f08990d2712ce4d993.npy +02808440-414688637cd72b6c7685118aff98cc67.npy +03325088-c322cfc79e07849bb362845c6edb57fc.npy +03642806-7ebff305b2e93504239603972bcd2e7b.npy +04379243-5d24567426a614ecfd726e98b98fb36f.npy +02958343-7b0ed2e4d59ad5261d5011bbe723eeee.npy +02958343-504793ed2da6cf7eba3e2415e22cd45c.npy +02933112-3f51197359289bf839d3717288022c20.npy +04401088-bfba0e8cdd5462e4fe103fdbd20df6.npy +03467517-db5e01167c49c793d5d673747c0e3adb.npy +02958343-648ceaad362345518a6cf8c6b92417f2.npy +03636649-f2dbcc8dd8a7c604865a5ebd0b487fe6.npy +03636649-b286c9c136784db2af1744fdb1fbe7df.npy +04379243-9171bc27d62095bfe82a8550427833e4.npy +02933112-4768d015c33de0acc6e4e9360ed1cfdb.npy +02933112-721bd0402e92e339c59350d819542ec7.npy +04256520-e68c603dc62dbbe5a1281b4d4bd889d7.npy +04379243-4bf6707d8cc11c0fc631e7eec6a153bb.npy +03001627-5a3ac1ba6f751bed79368d1198f406e7.npy +02924116-60d958a773186c31f4c1adce71073351.npy +04090263-dc263bc31beedb09589c07868201b17e.npy +02691156-c380dfb1b098757ace19d55bc5e6a406.npy +02691156-ec03d76cbd50314f5c7319b71bdce6e.npy +03642806-471005df47f0b4a6625cbbe81bda8c5c.npy +03001627-d990c996a67bab91d9233930731da67.npy +03211117-5286df5fdb7ab5cf403c2939fca0114.npy +03046257-b1267cecf443b88f4b3c42e318f3affc.npy +03467517-7f3f5c9953fb7e0a6cbec6f3d994a573.npy +03001627-a4ecc0a3d68dafd44925bc492489de9c.npy +04379243-54ba7e77a2bf5fe3158b7df020486ff2.npy +03001627-4c6c364af4b52751ca6910e4922d61aa.npy +02958343-29043510fd903bae457cdd14086d7361.npy +04256520-d98731f20d3de9c4d9b53420a5458c53.npy +03001627-9a0571ae6169a6ebfebad4f49b26ec52.npy +03001627-60328528e791d7281f47fd90378714ec.npy +03636649-8e8f964be5bea1068616812464c86290.npy +03636649-8be8becbec0d42b799e70de063b51884.npy +03001627-fc557cf617e03564da733bb42d274ff9.npy +02691156-1cc3ebbadfe69e8011f5789deac2dcac.npy +04379243-fb1b4b6d51cbe29967d783b4714d4324.npy +04090263-a4d20d766e6bdca4b0659fe8776130e3.npy +02992529-609321c1351a955c1e1f8455cdf1c0bb.npy +03513137-bde25e25b138b1f75d21ec234969aa2c.npy +04090263-a6984e79681321d7665e26d8660e8f05.npy +02691156-1eb1d7d471f3c4c0634efb708169415.npy +03593526-fe575d606cdab4ad713f2e93cbeac35d.npy +04256520-3681d113ea4b98546609f3f8aaad34cd.npy +03325088-69c012fcf92a926414b35a7d7cea7130.npy +04379243-9eac41860580d9ea8a75ef32ea6ce62.npy +03761084-e0d08b4c03d1a0d36be98452b3c7a6c.npy +04074963-33f2d5cb9df739a0cf01bc59d215f0.npy +03001627-e4834c88847b288648d8ff57878739ca.npy +03636649-5bb0ad1e0c9432b2dc6493177a28df03.npy +04379243-fc9116a6ee32b9b79223fc014b68160f.npy +04401088-c145f0b0f18d4afe99aee91747c9768.npy +02818832-9e0733f8515335ba9a87002a4eeaf610.npy +04530566-d841f12d8e22039f56f77b6bc6731cda.npy +02924116-5798b82280016ad3a2181d7deaec8f2c.npy +03001627-30dc9d9cfbc01e19950c1f85d919ebc2.npy +03948459-8efdd5a6333179619f433921788191f3.npy +03325088-33135d27972e8d496c5fbe25b434bf62.npy +04379243-b267c88cc2a3cdbf48d189f942cedc62.npy +04379243-41590fb9de5414f244b154f79bdb5bdb.npy +04090263-dcf9d53ebe90d9a85f14a92a8b55f317.npy +03325088-cc060d05ecc6b760cb6267f1b348aaaa.npy +04090263-9ed34fd8df53c865cccd2ea14d020703.npy +03001627-4fa95ea95b42125be5c1abd833032715.npy +03001627-31ea40d2624b40a17b431cae0dd70ed.npy +04379243-c3884d2d31ac0ac9593ebeeedbff73b.npy +02691156-d24e6c81b5261fe5ca2bd098b9203af.npy +02871439-50fea70354d4d987d42b9650f19dd425.npy +03001627-1eb8558d0f6885a1268ecf2838ad6f15.npy +03001627-48190d05babcbe2c68b95f9576f01a6b.npy +04256520-f0f3a9b0aed5ff1cf1c0e03f321d0b20.npy +03211117-5ecf4a1f273ae695729e474769d21582.npy +04379243-5b06d5db4da42b96492d9da2668ec34c.npy +03001627-3885255ca5d75e69da2260dc4a1fc2c6.npy +03691459-5b2afef3206a153db06d0ef27244d1aa.npy +04256520-dca66ae8a95f7f70552a7b4f3448af2e.npy +02958343-4c6aa3e7a8130295b528c0abff96f586.npy +04090263-b4f152116e77505d202b6e2a481f1de6.npy +03325088-234daa663f5f79b7b0957d845ac33749.npy +03513137-fbe830888a111027b20f6e48f6a30cbf.npy +04379243-a8473c68f6a6f9ad7a1efe7ddaf6952d.npy +04099429-55ac6badaa420c04a19c2099429852a.npy +03001627-bce6cb5f92247eb6844690e7ee348ec2.npy +04379243-252fa50674207d749eb332cd2d2a300.npy +04379243-631028ddb76eed4dbb0085d0daabdaea.npy +03325088-453557d8109ff422c36fb70296e45483.npy +03001627-4bdbecfbc925219157915a20ae9ec6b6.npy +02871439-484a99e5ec7ba9f4b2029d92310f4aeb.npy +02691156-40278c4bbf6c1f3d9642905e5096dbcb.npy +03642806-a96983022f36a0a83ad38b993d9e745f.npy +04256520-ea9aaecb6305da9ff51f77a6d7299806.npy +03211117-a51ca49763fafecf8f25f3eae9fd9c7b.npy +03593526-32e863f0d34384cc7ad908dd9229dac8.npy +02828884-7ab9419e7bfdc80ac51268fdb437a9e.npy +03761084-6aa4b136ec94b46472a38ac2b8f5cd48.npy +04090263-163101758687bfdf30d6a7e7f84a00b3.npy +02691156-ac75db84aa4e72e28f21c6f032637775.npy +04468005-3a1614d8da39aa2a8be7c8c5fdb9bd6d.npy +03001627-f9cdefd31b167f95e8f8c11a24c52ebb.npy +04074963-e08c8823d837fceeb2b53d011d5b25b.npy +02691156-508fa09e7df177e7fee8021c81c84603.npy +02876657-701ea218827f9a7a733657da4b6687f4.npy +03001627-d3ff300de7ab36bfc8528ab560ff5e59.npy +02691156-df25be12ae47d2517ef7776b3bf5815c.npy +04256520-390562a0a7c74cee19fb4103277a6b93.npy +04379243-aa3a0c759428a9eaa5199c5eb7fa3865.npy +04090263-552e31db6701e0b7381178c6c47f7400.npy +04330267-6265be481c953acd8c159f8d5e761b17.npy +03001627-dfca4eae14e0bb541f6399f392c887ea.npy +02880940-a9ba34614bfd8ca9938afc5c0b5b182.npy +04379243-f7a0f1e7e03fba8c9628f611995a13ab.npy +04256520-9b5b636b4b412d33d93768e7b9b1eabf.npy +03046257-25963f5a66bab37529a60d6ab40898d.npy +04530566-5e65f519b9f5361e657a96a9bceb8713.npy +04256520-c9f83c2615326e7aff04196502786921.npy +04256520-e68e91ef2652cd1c36e3b2fa8d1eb4eb.npy +03636649-6b10584984035b088314f68ce9e12e4c.npy +04379243-96a2a4c8e6b988d5676612319c6a30c3.npy +03797390-64a9d9f6774973ebc598d38a6a69ad2.npy +03691459-311354773f4c016ee1e724fc0e43bde4.npy +02871439-22cc76cf032e93d63f200afe6e0af4d6.npy +02828884-522f8c069a76c21fad5067eac75a07f7.npy +03691459-d06efc46aa999fa21574d21c0c95092f.npy +03001627-12c2b7080b07146a9d4d5dcd2cc33826.npy +02747177-ca901a3fa7a02f07912bc5b1ad60720.npy +04530566-73be7ff2caea7fd47c173089abc6401.npy +03636649-edf15d323abc7333cf66a9e192dbe265.npy +02691156-1c16739bbf3fa7c44276157eea5f8676.npy +03467517-70d9a5d0330abd9df4b498e11fb60a4b.npy +03624134-4c632e73e331063a942c72c00d252030.npy +04468005-7ae6c3c5d9518a5e982c7c6a3539d1c.npy +04379243-28447e9816bfedd268a2b8e2b27b7d8a.npy +04090263-8c151b8df929ec9616cf8b1cd2155e02.npy +03325088-b0f7fc62dfea232f14b35a7d7cea7130.npy +03001627-4e358c2dc0513971f98c0761af40e04.npy +02958343-952160c39258af7616abce8cb03e7794.npy +04379243-b491449d06aa40cc82e6c3a4e742651d.npy +02871439-e4fa76351e8733d3d810b14a81e12eca.npy +04468005-f046ee2a338501aa1ea6661badd5a5bd.npy +03593526-c637b5e2387eec7421aff7e1274fec72.npy +03691459-970ada2dffb5ce49a663d9823c133130.npy +04530566-9a0c149f5c47207f22252c899eb7861f.npy +04256520-11be630221243013c087ef7d7cf00301.npy +04256520-bab33dad5baa7983ecaafbe064b13083.npy +04090263-9dd91ae86cb9914678cf950c87657866.npy +04379243-ccc9cc45699f95f21bec2e8246842c2a.npy +02747177-46bd9fb29f0ad74151f881addeefe983.npy +03211117-64a769a9a884d63f802380d5ccf70dc.npy +03001627-697cfbe6e043136b737a00f007529fbf.npy +02880940-a73d531b90965199e5f6d587dbc348b5.npy +04379243-b254462a49aa73df51f77a6d7299806.npy +03642806-d1388dc83fa45da33a8222bbf59f8f16.npy +04256520-db49ee0d87af106f2de0bc4fc4d02dd6.npy +04401088-d21231fb7d7f7337f521a3dcd28e9d2.npy +04379243-77c74742e9504005a7d0cc9b15400f65.npy +04530566-6fabf91638fda8bcce1decf313ece97f.npy +02933112-9b33a5363695ebc3391e4d6c585a697a.npy +02691156-e24be0487f6a3a92d4fd6e0556ecdd3d.npy +02747177-63adebf24a1de9ecf91cc5a18046145f.npy +04379243-7cc444f165a22b80cb2a965e75be701c.npy +03325088-272582c1e1fd8a7876d20e73c57c9a03.npy +02876657-3f6dd828b9880456807c41acb554a82.npy +03001627-27f4207dce674969c3bd24f986301745.npy +04379243-e0aee89fa986647257256b1738023f7b.npy +03001627-9695267b69d145dea14bb1d7e401bf06.npy +03636649-656d25df742a84877e44e3c724db889f.npy +03001627-73aeafc0af4f1a62e1c624539dfec6c4.npy +02992529-81ad8af206d6b21b89b367279b017ccc.npy +04090263-a15719f77035596aea1c54714433d676.npy +04379243-ba8b2d50ab955e94beedb4c8fd29e2d1.npy +02933112-69949f47106c9140391e4d6c585a697a.npy +04379243-783f84e17b53447de76bc197b3a3ffc0.npy +04090263-6fa6eb2479a09474d87c63d8b3018b58.npy +03001627-34ed902dfa2d8eec2cafe1b125cab8fb.npy +03636649-52783aa89adf06f3250c527721570ba0.npy +02933112-2441395102a132354da5feafe6f1c8fc.npy +02691156-206a4bec609b727566cf1b4a8fc3914e.npy +03691459-61c61c893164dbf275f6e8ca4d589c7b.npy +04530566-e5524ebe2d9f1e8c47caa6b5f3c46e10.npy +03001627-78505373e756b214a3af90debe5fa17f.npy +02808440-2a57aa530ef82b91904e03fa15bd73ec.npy +03001627-38afa26a419ea3abed040525648fc6d7.npy +03636649-bac7b2c006c9cff76739a7caa0c577bd.npy +02958343-68c72623c8d32451f44e15caa8fd94b4.npy +03001627-4f061233795740bb411c679938d00104.npy +02691156-ddec69970cbc4d29112a90660b187a10.npy +04256520-f8519e593fdb348ab3d135d7fc8306a1.npy +03001627-64952439f8d9e1da9c0c9824ccd078be.npy +04530566-6a5405246814b82281c5ee986f4484ec.npy +04379243-82236bf856dff003b8fe77caf901462.npy +02958343-afb36ab0a7bb906bd95840a0da458be0.npy +02828884-74983e99e7606eb114708467db3d00e2.npy +03001627-701551efa4f1f4fe3e478b26cb10ebe4.npy +02818832-96bf3b5230681dd9e595fd37db7104a.npy +03207941-dd4cb99f1f210b196e25f3efedf6785f.npy +03325088-6555b55b9782e592b7a867e9b35a1295.npy +03001627-a6f280a490010a1d593ebeeedbff73b.npy +02958343-4e42e2b6986a3d86a20249b45c17a5c9.npy +04090263-fef082ee4cbfecc4a65322353bdd17ff.npy +02992529-24f3752312dccca3e23b34f33128879b.npy +02691156-d39075b8eb890a898deb28944f3f72ef.npy +03001627-226f096dbce49857bdfa5e0753fa3240.npy +04225987-6e76a333d9fc9a2972e15b580d9a5b3.npy +04256520-cc5f1f064a1ba342cbdb36da0ec8fda6.npy +02958343-f414e36d6daba864d9bd5ae694086d5.npy +04401088-4133d764b4ce5323a44bdc236120a21e.npy +02691156-527975c6c0e1c426ca8607f540cc62ba.npy +03691459-767f4a63260c8419e279011f622f20b0.npy +04530566-d8b92646ee0cad39866219ff4a62ebc4.npy +02933112-53d1e4d3a815840b7753393bcfa5f775.npy +03991062-fa3a58bb2806913ac77ef7a50d334603.npy +04530566-43bc1dd4f4d7f07a84f7e91f7eafd792.npy +02933112-6d54014c7e0847376bad80b4002b9511.npy +02958343-2a887d0b865d8ab4dfb921b4cd0b4571.npy +03467517-fc0dbc2ff44c860ed57700c05b1862d8.npy +03691459-49c6597ddbc1196be50209c399f9eaed.npy +04379243-7fef7125c14e0fc3b3ec4062c13aac32.npy +04256520-312ee9c8bc6ecec5ce59ea70152320fa.npy +03593526-93fa7a1e2aff0b84154dddaf2978e13f.npy +03001627-d107532567ee3f316663d1953862c637.npy +02691156-694da337c806f41a7209009cfb89d4bd.npy +04379243-291e43df05fba9b53d36088e1ac945e3.npy +02691156-afc2efb530e899634d4cb1c2a5e48b7a.npy +03467517-34874708b51c7ed493f0194265a9746c.npy +02691156-c31bdeebd8d74a7dbbf3143b1cb6076a.npy +03325088-cd0b16a0ee7ca94269fb38085fbc320c.npy +04379243-83b8e64089968ae8fd3feb4581507302.npy +04379243-998d6e318306153c3d67fb6c1e0f28.npy +02933112-ac11c66661c8f95825b0a60e00f47d7d.npy +03593526-40f0d91382abe04b2396ca3dd50467ab.npy +03001627-c709aa613431c0538a653a9f65a410f6.npy +03691459-65425eebdd205119b128e24d154447c.npy +04460130-26e099d5d7040b03b96aa5dc23c036c.npy +03642806-343c090b2004dfb0910bfefeca21d514.npy +03513137-64010c4042824e03b13741399690655.npy +02818832-d3aa611e639ea0228998b3b64a143d42.npy +04379243-ffa875f5e2242d62d13de1e342854aa.npy +04379243-48cc2f299fb1692288c3056e77bac805.npy +03211117-58eac12dcadab8bd6ff188b4687b7936.npy +03636649-c3277019e57251cfb784faac204319d9.npy +02691156-bee504b4909890df1dfabee9ba27dc70.npy +04379243-b8efc08bc8eab52a330a170e9ceed373.npy +03001627-942a10a33418205819fb4103277a6b93.npy +04554684-9e991b898c6362977123ef821e961857.npy +02876657-dc9247034a68285efea8a3df5e20f054.npy +03046257-c154e48d36e44c179e8f28fdc2cf9ec9.npy +02946921-a7e0a5111234031fbd685fccc028124d.npy +04379243-30c669e02f875ae6668ae11a7db5e82a.npy +02828884-38403c071594b1cc749694da9ceaed25.npy +03928116-818575447bfc6dbfa38757550100c186.npy +04530566-703c1f85dc01baad9fb3e3631a88cdab.npy +02958343-7272b7e028737097f200a72c9245aee7.npy +04379243-62ae9ded861138be9d2be74cfb51ade1.npy +03790512-d08e47404f0fa3f6a05d44ba0445fced.npy +03991062-2d890efbb22ef27d72652f4081ec5a77.npy +02876657-d3b53f56b4a7b3b3c9f016d57db96408.npy +04379243-9eeea5f7b030ff6ac155f88004a92bc8.npy +03211117-f9acfb901156d3b7dfa29c60bc1700e1.npy +02958343-24dc3903b254fe41b448bf2dc92c4fab.npy +04379243-a3db8fc07fefad03db984b8f0550fcd4.npy +04379243-ad50c756edb20111e76bc197b3a3ffc0.npy +03001627-d7db1353551d341f149c35efde9de588.npy +04379243-14ba2a965791a003b37e6e0c89177ef9.npy +04379243-2330e9debdedf9ff99284d844aba7576.npy +02808440-cca20dbad3faf4343321831d2245cf06.npy +02828884-287475ec16f5b7477b636e5c31038bd.npy +03691459-84e6e1fb56eb60e918d385624fdfc6d0.npy +02876657-ee74f5bfb0d7c8a5bd288303be3d57e7.npy +04379243-3f31ad5e9cf3e51fa6255bf8e0b4ea3e.npy +03001627-244eb71b1dd140dc6f64461f0eb7cd69.npy +04256520-f34cda8bde3c79709829306a513f9466.npy +02933112-c65b640e9a3838f91d76d38b3dec9476.npy +02828884-fd359f64dda4e753870f22c94729669b.npy +02691156-1af4b32eafffb0f7ee60c37cbf99c1c.npy +02933112-d33e54d1880f70c310cd758d9b7cf.npy +04379243-50b076e7917c1297cfb87ab5efe3dc31.npy +03001627-1b4071814d1c1ae6e2367b9e27f16a71.npy +02924116-84d920a145b5487154d963fd62c89fef.npy +04379243-ead13c29c385832eb4c2969e5244fb83.npy +03001627-9a82269e56737217e16571f1d370cad9.npy +04401088-49081a0c0cd4ad32166f3c6af52a7c59.npy +03636649-81e42a3f9e13e1e52beec56b24479ed1.npy +02880940-c25fd49b75c12ef86bbb74f0f607cdd.npy +04379243-c52a6a569770d1b39ccce4c6d5bb195f.npy +03001627-5202edffd4882c252192179b64411b43.npy +03624134-8f0e77eb8d646ea8aee6942381ab7f9c.npy +03636649-da5db67a2385d5e8da9baff5f5368802.npy +04256520-9ec7016d6978216c94fadb3555028734.npy +03211117-95df08344f4737e078785e24320d5ee9.npy +02828884-f44b93dcbf00d80acb2a965e75be701c.npy +02992529-11e925e3ea180b583388c2584b2f0f90.npy +04401088-ccfac9fefb0326003f548cb8701b2293.npy +04004475-52574afcd545b512a370c653486c68e0.npy +02876657-ac131ac1bbe3dd10846564a8a219239b.npy +02828884-e0e2dfd6ed0880a6d6421fd2aa576b15.npy +03636649-9db87bf898efd448cbde89e0c48a01bf.npy +04379243-8f9f4ac0dd2734d77ff6ace05b36a5.npy +02933112-3105e7ff7fbf3e423e72cffee9fc75b0.npy +04090263-71f31b9a96f1b312ddd7320ddee77bde.npy +03001627-d0d3585a2c4579bde290ca81b042ebb4.npy +04379243-2c72d9ccd9399fe8968731dfb1dc1f13.npy +02828884-ebc20661d9e103334b3c42e318f3affc.npy +03046257-849413d99fac88c48cc8fdeacb50bc7.npy +03001627-f350621fba76ee29e7b1367d085b7e66.npy +02933112-1548461b13adc0d0c59350d819542ec7.npy +04330267-1e2a3147e365744f41965be83b7745a.npy +02924116-2f9aecaf8c5d8dffc90887194d8d151d.npy +03211117-4440935e5e566502250bf58700b4d8f.npy +02933112-1838f9b62a102d704c7384dbb75cab0d.npy +02958343-94c0575659c6cdf2091b4cb93147ff9.npy +03593526-a2da98dc3d78788435836c728d324152.npy +04401088-17072ff9ec47bfadc3fd2392bc923b2f.npy +04090263-2d4ba3b93ed69bca2bf266a8f0187ce5.npy +03636649-923097cec128ae77469cbaa3d6420fb4.npy +02843684-cfd6df4bf7abeb318ac033353d37592a.npy +04379243-5771d5a3084b3ca3a2d7b309863cb1b.npy +04379243-7807ff57a21a0ab8740c0058fed336e9.npy +04401088-b18f0d53dd3db1999410a04d09c14d1a.npy +03991062-ac9b4ff01655e74c67a2f40ab335eb08.npy +04379243-28db458b524dc934f2c9082debcece6.npy +03691459-e878e519af882f493fc48162942e3418.npy +04090263-ce43c7f0642a72a25e9786b1603f45c8.npy +04530566-20e8718d1c6d5a665a525c461820c6b3.npy +03046257-428647629e3a9906f0df3cdcd733f686.npy +04090263-5076565550186d3a1f23c99243882ce8.npy +02691156-eb85e7d86e2ef861e7cb9c477e2b7be.npy +04256520-3a053bc6997155674ee2933c1153f63b.npy +04379243-10506aab1adfe9f4eb7b988bf4f0d1ef.npy +04401088-976a8d10e8423f8d8f15e8aad14ff29e.npy +02691156-862f246e54900f48ed4212b3ec7c4371.npy +04379243-6349f0d123ad1ca62ee5d388bdaf2f.npy +03467517-aed378fa2803c946dede9e8b66028607.npy +03001627-2be29f8ad81e2742eaf14273fa406ffc.npy +03001627-360a12c8666f5f764c6ca0d259b5e0f5.npy +02691156-a60b2775f1955153ca8607f540cc62ba.npy +03046257-7830949f6069c4fbf546596ce7364503.npy +04530566-7dbcab223200092feb2c303a0e0d287b.npy +04090263-c41ea087ba71931967a4cd2863eb1ca.npy +04090263-43c51dcb5c9c812ec1385c8c0f4d3915.npy +03790512-2fa098eefef49c8c85b48ea6a7114159.npy +04401088-4458a5056f633fa13abacfd1353cca42.npy +03467517-5dcc689f1472b2c7dae24eae11385498.npy +03948459-f6d74e48206fca39a6e43b878d5b335.npy +03642806-9b4ab67eb448c49c11ced4a54f2e6229.npy +04090263-cfc172b9164357ad42a9381145738f08.npy +02958343-35a32cbdfd9e7ba460ed0d611ab79ae0.npy +04379243-4967c4df72373464622e43c0e0591de0.npy +04379243-1fc4b8f3fdbb5cca12464df1bb7d5f0b.npy +02958343-fc28356cd7948b90466f54ef02e60f2f.npy +02924116-dd21b1599951d4bcb84877c61813ddb3.npy +03001627-e605d3ea3be01ac3b11a97ee9284a563.npy +03001627-e4384c55342db206713decb1a0563b12.npy +03001627-6690683366993cb1d42ec7e303174a87.npy +03001627-22575f5719f3eb3d23bd3a8c035c98ff.npy +03001627-4e664dae1bafe49f19fb4103277a6b93.npy +03001627-b80e1766b45076ff492d9da2668ec34c.npy +04379243-6e13d5d26a0c53e13a66b6fe2c876ded.npy +03593526-809d15e11cfdbe10a2ee63b46530621c.npy +02933112-fc5b7d19b1ab1e8bd0504a433b7a549.npy +04379243-5d53ed3005f4dc6856786b90799c4fdb.npy +02958343-dee6d83ec808d673c4e77c640c2391c7.npy +03691459-ba63e6e1bd33064a90146e2a0489a257.npy +04530566-969c3262a594bda487a9e46bb7812fbd.npy +03991062-f7fd1967f8c15bbd52492ca5b5b3a7af.npy +04401088-4c9760ac0bbd2003151c744078238922.npy +03636649-e4df4ee697e71902f95e2a1e9997b85.npy +03001627-381782d3562f2fe0302dea4b3acac371.npy +03691459-1ba62454cd137945337410fccb2e7331.npy +02691156-e6236c5ec784a48111dcece1819895c0.npy +02992529-eb58b011745519194fde46457697d80.npy +04379243-2e86b383f43bcb1b66dc6ea1ac82d91f.npy +02828884-54c05e235c8d3a4cf09874e0e8a75195.npy +03636649-cf5b6127ac18e85b6aea2f18ee404fd5.npy +04256520-c0b61d423f449b3c6f37a8be59c15bbb.npy +04379243-6f317ae1892ec6e22f63d70fe82e78de.npy +04379243-133686fa1a2136092c280c3b5abf8255.npy +04530566-d4079a1fa9c5eee8a3599da6d4b3696d.npy +03513137-13da2cd827cc8b9f99976ddcaae4d11.npy +04379243-2e61f5b4f26b890cf27383fc5a5a711c.npy +02958343-7f7bec6423847a583002e98d41e915cd.npy +02691156-8bb827904cd9acd36c1cd53dbc9f7b8e.npy +03593526-ac40978140155f2e5d878ba9ec3c0d6a.npy +02933112-c4fc9ac6e45a8ebc90546f5d45015351.npy +03001627-450b4a6b6afa6280d5a910bf1c23bf18.npy +04379243-d4fc029d3836221b76e9713f57a5fcb6.npy +04379243-733722cae46eb715febad4f49b26ec52.npy +04530566-9de5e010b46919293bb25e78abe7f382.npy +02942699-cef23409b1a030d516fe5320f9715eef.npy +04379243-2259e09ebd0ed2befebad4f49b26ec52.npy +03001627-126e65c55961e5c166f17d3ad78f5a62.npy +03001627-e3bc0a03103cf84e7a471a654ffbc436.npy +04379243-bf06de9143b2e36190eb1f8a00f61726.npy +04256520-d644ef328d35d28ffebad4f49b26ec52.npy +02828884-bf0b9b88be76628440126a5bcf48fc87.npy +04099429-7f8f5ba0ab543cd99cc7053a5669450f.npy +02958343-45563d97886d68eb12d484f58f506441.npy +02871439-e4c42bcbba4ef5b09a2d4f7bacd6e0d8.npy +02958343-1e17510abe8f98bea697d949e28d773c.npy +03467517-8b61adb73d6349838014d29eab9ba665.npy +02958343-7b35ba084bfb741780e98029b8cda1b.npy +03790512-c8a99ee61a2003308b543692e5ab59d9.npy +04256520-4f7392168ffafb8aea91375557c834d7.npy +04530566-e82e97e22066a75d798832e32e32aae6.npy +02808440-4bba4847c53eefa43121505b9493314.npy +03046257-9973f62eeb03fa9b6e259a0b666e79d.npy +04530566-9848322f786fc6d9eb2c303a0e0d287b.npy +04530566-18a4466173b31541a66c1707a338712c.npy +02876657-1ae823260851f7d9ea600d1a6d9f6e07.npy +03211117-2711433532f6d1fdd7426bda0fe4ebcb.npy +03001627-376b0c463a2bb625c036371d3ae886e1.npy +03211117-78c2861ca4574a8fd9deb3f829cc2475.npy +04090263-bcf362f325cf658e282dd3b430ec2654.npy +04090263-84735b7ac61d2ed023c69c7ff0f71040.npy +04379243-974cc395f9684d47c955e5ed03ef3a2f.npy +03001627-9189415b98c9981cc2b6cd34eca9d8c1.npy +02691156-78ceee44d207e826c87f6dba8af25d8b.npy +02828884-c36cc90d01f21180c3c8317b7074dc0.npy +03691459-c3180cdddec577f2e17b9e33c097dbff.npy +04256520-98f2d21c4dcac477f7628281ecb18112.npy +03001627-5fc3bee56e8ceae26fa2cfca412075ea.npy +03790512-bcbcfdad5e0e1d9ba88e8cb97b773125.npy +02958343-48863925f0e70aafdf8e4da0a37cb43e.npy +02880940-11547e8d8f143557525b133235812833.npy +02924116-c9fe4ffcdd6c5ae1f4704cbd27fa6eb5.npy +03593526-1c0a264dfbbf285cafe995003c9eaf93.npy +04256520-9bcad07a9c2e8e13490ad276cd2af3a4.npy +03467517-2d31ac290daab56a4e96698ef01e7360.npy +04379243-b2d64a218b373b0456d80c2792e1f42c.npy +04379243-5c3932413e5433e0f51f77a6d7299806.npy +02924116-c68284aa7904fb4d5e2fdc02779b5bdb.npy +04379243-45da524a32676350b5817dafa1567392.npy +04256520-fa877c7d428253515e4b35ff1ea95f37.npy +02933112-54daf9093eabf27a34d6aa31914c287d.npy +02933112-e5bd1675d43422bb61706e18472540d6.npy +02871439-71b87045c8fbce807c7680c7449f4f61.npy +04379243-5c5f434f9ea8bf777bcb070cc655f13a.npy +04401088-3c244a5e76cec2cf6f108f2b64e6593a.npy +03948459-abc7a1373f4b30291adcc40d88daf7c8.npy +04530566-a755dbab93afbb3a1a05bdebf75f301d.npy +03001627-a75e83a3201cf5ac745004c6a29b0df0.npy +04090263-2757f06b6b4d3ca3f02ee453ff283e26.npy +04379243-9e5926bfdc7f01749e65a3d2929a9516.npy +03046257-969841e102fe5e1c2de0bc4fc4d02dd6.npy +03636649-20e1e4849339e64f5077539b37310c29.npy +02924116-e205f10f3b2dbf0941cefd10ce5d6cc0.npy +04468005-7ad6c009fe02d1845f73a346378dad81.npy +04256520-83a7b2e11589b4cc5fc6df6674be3b9c.npy +03467517-3c125ee606b03cd263ae8c3a62777578.npy +04401088-48a2000b54f4fc792a56a29c6d979b82.npy +04530566-71aedddffbb7b1befb4a964cf6619fc2.npy +03001627-ef544a816432b0a78dabc11b24766ce2.npy +04379243-7eed749ec4a3e391289014a3a9ce92.npy +03467517-fc003660554be7334dfe0ed95d7290cf.npy +04401088-addf767a669d9732691c3af43bf5f97e.npy +03991062-b3a1437b16fc2b5b88650557d3dcdb73.npy +04379243-482123c5f097d29f278d386bfa54545.npy +03325088-12eb51d74f30c3c054d7082b34825ef0.npy +04379243-5783c7479b89f76b0783d9ebb200d10.npy +03991062-4e5172f357714b7f78caa162a41a851e.npy +02958343-3476290a1220338ffa975bcfd21f6dfb.npy +02691156-3716ed4fa80dbf5f41392ab7a601818b.npy +03001627-8ad5b0bd9f1297e5492d9da2668ec34c.npy +03636649-cbea72b8621f99703394926146371698.npy +02691156-eb8fe6d82d195ab5bc8feea465aa74f2.npy +03001627-b8e40ffe5c8e61ba3c8d0fdfb1cc2535.npy +04256520-262b2e2a13c8099d60f888b4e2fd3e4.npy +02958343-105dedf1b70c2826b2dcc642c86ae8f4.npy +02958343-4d8045997209a8cb1bb46d2556ba67d.npy +02992529-2435be698167b2167120841458f79dbe.npy +04256520-3c0dd3719baecf3319fb4103277a6b93.npy +04090263-6e1572214d2606dbcf7516eda265328a.npy +02876657-8ea8ced5529a3ffa7ae0a62f7ca532f1.npy +04379243-78ecba6d2bdb55ba9174750cc2a009c3.npy +03636649-f34d9842b68f0b59fcb8d8c6d4df8143.npy +03001627-5390dede41d523f71a782a4379556c7.npy +04379243-c15f3a4903ca16b98c0a2d703f217201.npy +04401088-71899992cbb987ed5baadcb81f14fd84.npy +04379243-1c259cf6c1206aadb6f6d1d58b7b1311.npy +04530566-512251a635bd548f3463d0a80e47bc52.npy +02933112-da62a2f330280273896f268d8862011d.npy +04530566-8851329ba7c3394d41556f795d265590.npy +03211117-518b97c2a0892aced88854fc3e3ce05.npy +04379243-45b23ac79688170893ba1eeaf62819a2.npy +03001627-ef018d0bcb3d4c89601104cd2d998272.npy +03046257-a294c351a2225ddf6b0c35068783779f.npy +04256520-bba610163b83053514038d588fd1342f.npy +03593526-353709f2c6862ac56bc258c0f0234be0.npy +03624134-e6b5462b34d8809529b0445cdc28e4cd.npy +03636649-3e9ce9f30f1999ab45bb7680f88b3d99.npy +04256520-3b72c4223eb452168f5c37fe197319e1.npy +04256520-b23dc14d788e954b3adc3470b30138f3.npy +02933112-6f679ca92bfaca984da5feafe6f1c8fc.npy +02691156-a4678e6798e768c3b6a66ea321171690.npy +03001627-120735afde493c277ff6ace05b36a5.npy +02958343-47fcc0e1aee36584b1bb46d2556ba67d.npy +02933112-5fc881594598fd937eee615e75bc3b77.npy +03001627-a976138678aa74d0d9ed5cacfd88cef9.npy +02691156-f9505b01e3ea959cf9700e397b8b4e4d.npy +03928116-1f0153042cceff37d20e6bdf4e0f4a18.npy +04379243-9b8e7652eac8daef33e6ceca7fd89911.npy +02958343-d862b3766583ace6c2aae5fbcd555ab4.npy +02691156-543412ccea0db2f8f37f38dedb2f1219.npy +04090263-ceee9df336427c427e1ff5b356a80cc6.npy +03001627-a6d282a360621055614d73f24792753f.npy +02933112-181716a7a34f2708c59350d819542ec7.npy +03001627-2ab2ec342a3b2a45c242632b2a8c3129.npy +03691459-57412ca31eeb15bf75fa5879e0c49e00.npy +03001627-51e27bd3ee95338588d458757d655e0a.npy +03001627-b29d302a87099d924d8777315ca26f7d.npy +03211117-3e9af28eb2d6e216a4e3429ccb8eaf16.npy +04379243-6361a90210b69a9590a2e9c21353bf7d.npy +04256520-61cedacdae156b4dcbae681baa9e61e.npy +04379243-adc1d752f04c338bfbe07b96393f97f7.npy +03001627-7250e86b4feb699aa08cd647a48e605d.npy +04379243-fa3dcf1562e5f60829e4b5aa807bb4e7.npy +04379243-8c878bedb8e052041944bfc1093ee4d3.npy +04090263-198bf0b56e9235a11afbc27572ea3d1c.npy +02958343-9698be0fd3516f01fbeda5389ab05f5f.npy +04379243-161da97088255c645ff9646ea22eac1.npy +02828884-d77f648c6df22a05c6510aa63622330c.npy +04530566-8682988328acbc62b8acbfab1478caa1.npy +04530566-44571992d18375483506f52bbfa5b648.npy +02871439-2f30f402c00a166368068eb0ef40fbb1.npy +03636649-646031cc994df3be11fd25b4ef1afe87.npy +04090263-4edb165109339c63cc4d8251423f62a2.npy +04379243-dc5a136f23bd3f31c710d14956729baa.npy +03001627-9c3d7b65c739a618285330f26226f8fb.npy +02958343-1c3c8952b92d567e61c6c61410fc904b.npy +02958343-3154c3dce06ae7e216abce8cb03e7794.npy +02880940-817221e45b63cef62f74bdafe5239fba.npy +04256520-62e90a6ed511a1b2d291861d5bc3e7c8.npy +04379243-6dee2382e2c710fcdb266b832300e6da.npy +04256520-1e4a7cb88d31716cc9c93fe51d670e21.npy +04256520-1037fd31d12178d396f164a988ef37cc.npy +02691156-579187a52086b0a63690bd3a9fab7134.npy +03001627-48b257f80c7434cb56f6fc4b4ce1db04.npy +04090263-af1778e415b0e0be20fc54d2500eb7f1.npy +03001627-3c0dd3719baecf3319fb4103277a6b93.npy +02924116-1b74500dc5d2a6547c02d07bab7b395c.npy +03593526-edb8e199485be4e968747a7f12307bdb.npy +03211117-692db5a6fb6cea2174649592553d1a1f.npy +04379243-18cea57b061a65e5a346e6ee1c343985.npy +03001627-7eb842de7ad4cbad3e329950ec40f6dd.npy +02933112-43552fecbd07876acac27d617fa518f5.npy +02958343-7f198a2357dec222f98feeb6b46f3cac.npy +02958343-ace409d84c89d7258a0683934fae3156.npy +03642806-942156d763bd7e867cff7d16e20f126a.npy +04379243-704f75e32974f0f9d5316414c56bc1a8.npy +03636649-aa4720a899ddf5456a5c4fd998d89f43.npy +04256520-cca6e720741a6d00f51f77a6d7299806.npy +02958343-ee0edec0ac0578082ea8e4c752a397ac.npy +03337140-c6c6cea3ab70a9fd4c3aee8e9d3a6ffa.npy +04256520-71fd7103997614db490ad276cd2af3a4.npy +04090263-3c9b810025d7167fe641d7676ac20451.npy +04379243-d9ed9f1577b22330aeba6a38e5ba02f1.npy +02828884-ebdcd5f64e44ce0cb2a965e75be701c.npy +03790512-c52be51c1aa7cc9752fa4ad29a1236d7.npy +02958343-924599eb8b6aa6429ed410a010efa019.npy +04256520-6658d651878eb023c7db9c21ccfbc4a1.npy +03691459-b703762eb7b1fd39d0cd692038573317.npy +03642806-39b54fd684a4ed3e6f0a9a10dc885e17.npy +04256520-3582dc0c828ae4b1febad4f49b26ec52.npy +03759954-b86751a9f75423dcffbcf74570805a6f.npy +03938244-ddf0c95f168e43f2283b00891f680579.npy +04530566-70b7ef0d69c7013473965669ebe40616.npy +04379243-d533837495d31706d4bba81d85a6a53d.npy +02958343-cf3a2894431c55f43b5ec9bc4ed9097.npy +04401088-c7e4a425cebaa04bf9c8feac0b33491e.npy +02924116-bd8d7b8ad35df2d52470de2774d6099.npy +02808440-be9496165cc6322244221bef0fa3c36b.npy +03691459-108316842b17210394a42262667addbc.npy +04379243-e24979696e6b8e7060edf8bc2f5c8881.npy +03790512-11b1e520db0bf1a1d5dde04c96fd8146.npy +03325088-78a7613f9eeb866ec36fb70296e45483.npy +03001627-79401adba0311d9b19fb4103277a6b93.npy +02747177-71f3b101a6d47811cb2a965e75be701c.npy +02691156-d1df81e184c71e0f26360e1e29a956c7.npy +02992529-d130a357978694bf58efc722b5cff71c.npy +04256520-6aac93deb58a35f56a3237a661a9fa9.npy +04530566-f3a1538193bfc54fad3766494450e53a.npy +02958343-1714b6e57c8c4983fb1aad5dae793ff4.npy +04379243-2a80c95b4bbcb73d87ed2480ebb0f3d2.npy +03046257-681a251290c5b59583f01376c92cdee4.npy +04530566-b38a6ed1bb88dc6ccd57b018370ca909.npy +02828884-cff15ed24c45878b3567b82c74e275b4.npy +02958343-e308a6e4472658b618e9d35559b7aa.npy +02992529-a4d81a74a416b88948637414dbe9de8d.npy +02992529-e862392921d99119ee50cfd2d11d046b.npy +04090263-db396982ae541ac97f5c403400264eea.npy +03001627-c7f607892513a2f787bf0444104341d5.npy +03001627-5f06664b4eb0af4c352fc7e973ba7787.npy +02958343-48071634bdeb66e271a126804ae24042.npy +03593526-cf65c7fb56850194490ad276cd2af3a4.npy +03001627-2c2a5f5a8931fa0822f0b32ec619eee6.npy +04379243-d60a87c721416783ec7a87c695ada295.npy +04256520-499242b0da957d1e33f2b52ebeafcf18.npy +03467517-65b6279a17e7ace2df17c838e7147b58.npy +02691156-31b75f20c64b03ff6b7bd17e458d0dcb.npy +03636649-699fcda4f4e9166ec5eb7aae719027b2.npy +03001627-9efb86c07170d7e897ec301178d1c7e.npy +03001627-94b779e6bdf6c3d171a782a4379556c7.npy +02992529-854ab60bd57d3d6d2f412e1bfcc51526.npy +04379243-6b8b6d09fcd05c1819fb4103277a6b93.npy +03001627-e5b8d52826245f3937b2bb75885cfc44.npy +03001627-8a2a0cad888b871eaa84c578b771896d.npy +04256520-49b2df85a32176c8e47780c3e225251f.npy +02691156-1e8c56bac4e66672e85e222f6559b47.npy +03691459-d6f0a0ca6446eab0c0b5947ffe18a468.npy +03001627-b6cd2d8af74226a3cd8b5e03f65e1405.npy +04379243-acde36e1b4c14b9aec2d07c46434bacd.npy +03211117-4d033564f0dcb412afac285245c66df0.npy +04468005-ff41a3016d0ed18552318481004055fb.npy +02691156-da1acb401541235be4d2773f0358b43b.npy +03691459-5820d7ef5c9942e6d49b96b9f2811c7d.npy +04330267-72508fd1bd92e1d39c436f89fdc07cfa.npy +03636649-3dda46a537bc16e689ab11a408196888.npy +03001627-250e0d866303abedfebad4f49b26ec52.npy +03001627-b6b911aecb417295e8f8c11a24c52ebb.npy +02946921-bb487f4b77abbef0a8d976d1bb073663.npy +02828884-6194e1897f8ebb17b40f0ac0fb9a650d.npy +03325088-70ba2ae5080de487b362845c6edb57fc.npy +02691156-a4cbb0489a3a680eca8607f540cc62ba.npy +04256520-fa5a0b7134e3e9ecb04cb542e2c50eb4.npy +03928116-38900730fdf8d22b8377768c43f7783c.npy +03790512-d165adb88d2e569552ee90e577613070.npy +04379243-18a9c13c3999e9c186abe5555a3b447d.npy +04379243-4ea4834db898a3f58cbb8bac2032149c.npy +04379243-2bb9537b798dfda490ad276cd2af3a4.npy +03691459-2edc94885c4ba7ad2d563c85edb49108.npy +02691156-3b0efeb0891a9686ca9f0727e23831d9.npy +02691156-895ae296f701f5e2ee7ff700fef7cd22.npy +02958343-b27c818401f48e5220453276fad563e4.npy +03001627-e4494542ab04c033e6fe3612af521500.npy +04379243-79d992df7306436da1ed581c544d9fd9.npy +03636649-6283ad834ec0730720efab7988749bc4.npy +03001627-f2e2993abf4c952b2e69a7e134f91051.npy +02691156-eb658ff31f0becea1d0f8853f6d023e3.npy +04256520-1149bd16e834d8e6433619555ecca8aa.npy +03790512-d82165e9ab3cbde7eba25bbcd3786140.npy +02808440-51ac21c5f5c10583b8724a732b3d4cc1.npy +03337140-bde6f229cd9fc1aaadd6705c8c483552.npy +02992529-e0ccc0cae4dc414cb4e7b68321c9d305.npy +02924116-b2fea5e98eafe6014edf4a0df1fbc500.npy +04090263-2a525d9178f347ce5ab27081157ad594.npy +04379243-a37bc9fad75b6def3087f84b199fd297.npy +03691459-461441f5606348f3d88a3e0e92891ad5.npy +03001627-2a2ef361fbe78f1e9f3cdee390cffc8e.npy +03001627-795f38ce5d8519938077cafed2bb8242.npy +04379243-e2c7ca786fc4b050a8a813669d8b4f2.npy +02691156-e283e3825d66a985b87697d3904b168b.npy +02747177-caefb14d743df2d69c3870d54ab64b77.npy +04256520-b351e06f5826444c19fb4103277a6b93.npy +04379243-874d1890f62375ea30bbd4cddd04c77b.npy +04554684-e51ad19bf1dc680b525bdb2a29d19760.npy +02933112-c031c55d7ff5bd7d824080f516909671.npy +03636649-c58b04ebb038758ba866d377a1785e37.npy +03261776-1f66f8c897bfa84b8c08913777779fe.npy +04379243-18c7c6eed722b9761f8d2643b5438b70.npy +02880940-d5b3fb99c8084a6c5430c0f7a585e679.npy +02691156-371a609f050b4ed3f6497dc58a9a6f8a.npy +04379243-1fe2d919fb4685ea93271d2223fe04be.npy +03001627-8654342caec219e07cbc6cda01aaca49.npy +03001627-e5ce7b150310f288b04cb542e2c50eb4.npy +04401088-60df2f27d33f3f472eb2c67660ce4f3.npy +04256520-930bf61aa004692c1834dcb2b62a80a.npy +02871439-ea1a28f0b31f1be34bd9e0690b0b191.npy +03636649-108a5262552050dfa9370719b830fc2c.npy +03211117-ad0b349657fb807d88d19ffcab9e20eb.npy +03001627-be1546c576c7c189edd7ee0476a331f6.npy +03642806-ddf5d6d855c2aa5d1c644ef3ab0c8ffa.npy +04530566-9bdb0cf464f5c65956b5365bdce185d.npy +03593526-8f7f15db817b3a1982db9fca4b68095.npy +03991062-ce008e86ab858be7ba90901a608c6cb.npy +03991062-3cce39eff2128c34ed390075067c2702.npy +04379243-32c4e455cd92d2a3c3bd24f986301745.npy +04090263-d90b571a1259cef1ad51de5d9ac9dcd2.npy +02691156-e85cd06b4a14d3ffbc0909d98a1ff2b4.npy +04379243-2ec254595840417424754d384796666.npy +02828884-17d8e07c30ff1657d201085e80edb26a.npy +03636649-98c6cea5f2d3ea28fcb8d8c6d4df8143.npy +03325088-a7c12a4d02bf3614378f7f7b635ccd96.npy +02933112-779cda069c3b6338824662341ce2b233.npy +04379243-229d510bace435811572ee5ddf1b55b.npy +03001627-ce2d77c8b0436db4f5d0dadcce96e179.npy +03636649-fd1371c24e12c16251d6edf97cc5502d.npy +02691156-d4dac019726e980e203936772104a82d.npy +03001627-e8788e6f0292f503f4b6538438a0b930.npy +02933112-7759a26614f6c4fdf815c17ff5624f52.npy +04379243-c5faa34d589240b859d0a47cd36512.npy +04379243-b796639ea7368f3bec11953b27b8a03a.npy +02871439-ee7049259da1bcbbfaf46ebe96d4859c.npy +02691156-52e7f93d592622a9615ba7bf3620290d.npy +04401088-a120a29467045d34c3f199bb1cdfc734.npy +02958343-244a8476648bd073834daea73aa18748.npy +03001627-33e436e30da86f3bc5beea20858a99d5.npy +02691156-a9b95631bcbefe9ad225a1c252daae25.npy +02691156-53eee66291c47a91bc0909d98a1ff2b4.npy +03001627-550fa302257e193ec93d39652bbb58f.npy +04090263-17bb6d46e1b07ed789cff8e09537ec10.npy +02691156-ac39424c7666c318cde5b07c0f09692a.npy +02958343-f60779c934ee51eddd1e15301c83686f.npy +03046257-cde7dca42588ba9c93d604ee670f39e7.npy +04379243-d2d5b8f99d977e353002761e7a3ba3bd.npy +03636649-f9bed8743eba72439a4cbf5d3b79df06.npy +03938244-f19f78894858d57c38bf051f9aef03f8.npy +02958343-cab3b584786dda8c85c68dc758ce6c5.npy +04401088-427e06d425b901be5c0be177939e290.npy +03593526-7b0b4571876644fcef76898f881b76a.npy +03593526-b67d4f4361affd4d664b3b9b23ddfcbc.npy +02958343-5cad9a0e7e69c6dfc427f8508e3d634b.npy +04554684-da0179a5b68f13586a6a687121d74e50.npy +03624134-fc40e3685a99eff084db38829945aab.npy +03467517-ed2823c4896d692ed5ab54dd668fd99d.npy +02691156-bc3b68407bba00d92756c2c914ecfebf.npy +03948459-abaf150fbbcfa58e9f433921788191f3.npy +04379243-9dd63148e5b0a4f79eaa55bb236fb6e1.npy +04460130-3defb00d43c0ebc853b60a2c38c44521.npy +04379243-161a209c418646444b3c42e318f3affc.npy +04379243-1ab2ac2a0af6bf36798e7d16c343c306.npy +03325088-495fc62a822f66116f893b5bc716a3fa.npy +02958343-ea529cacc239f82989a8ac0e4c77f4d2.npy +04379243-6bf058da5c3835b415ca6115a4467dd6.npy +03046257-f2a47fbb788c05953ddbeec164af367.npy +03797390-dfa8a3a0c8a552b62bc8a44b22fcb3b9.npy +04379243-1e6143253f8f984735d95c26c81752cf.npy +04004475-3c5a8a2262dc3ef1ab4efe44a581aee7.npy +04379243-6081fd59c46769fdf4b6538438a0b930.npy +03211117-c4b636e2c361be9dece694d60a812f12.npy +03636649-36a1e900d1b4d4b287b2013bc93e747c.npy +04090263-d8e7abded14c00cef02ee453ff283e26.npy +04099429-cbf630e17e0dd6fa8db04a0e4b407440.npy +03636649-446f8c76eed76c199df50b7f68c99baa.npy +02691156-46ae88cad17edca7ae7c0d0e12bd33da.npy +02933112-4dcec5b89f1e9e4915dd7d7985e749c1.npy +04379243-ed59907918516bbb4c24aa998833ed98.npy +03642806-9e5daedde75196487548281e465c9303.npy +04379243-bce2998e60345f86ab610b0c94236463.npy +04090263-cfd06e58d354213c8f2a8ddb5c970b6.npy +04530566-cab0b302a23381adcdcba7385a96c2c8.npy +04468005-f91686b42d529db2dc14ba0818ee5cec.npy +02828884-b4584ca6fe22a0be599937922ec198cc.npy +03001627-8ec79ed07c19aa5cfebad4f49b26ec52.npy +02958343-1f8fc7a787f254e6428df271ebc70bc0.npy +03001627-30b0196b3b5431da2f95e2a1e9997b85.npy +03001627-8bba3f2eac551ada2c0e1e24bb9eb3ab.npy +02933112-6336b5516cc8bd50635469b95109803c.npy +03636649-8e78283cdb07db1fb33cda5c8e604e7a.npy +03001627-72713f2b894ad2846d16cefc94cf3648.npy +04256520-527bc61087456aebbf27ea70a1a65d9b.npy +02691156-8264f874bc7fa58ac3d9e92d9c33325b.npy +02808440-97a2ac7e8ada9d981f003e83c2518be8.npy +04004475-bbeee5ffecc0f04c8476f77a9e6aa3bd.npy +04379243-bf3b9638b7be27bb4c26a0d2e78f0aae.npy +03513137-d7a860627e8ba083ec3df6ee3b84fcd3.npy +02924116-378c6395b62df11cdc6c67d3cbca448e.npy +03991062-3c73f2f15c10d253f2665ed92bcd1166.npy +04379243-8eed35fd5b777acf58316b27df6c8e87.npy +02958343-6c5c45f7a474daa9a134736201a79843.npy +04379243-734a664e9d0aaa1230bbd4cddd04c77b.npy +02691156-c6306d07f28bc5231309643a94d8a5f.npy +02958343-b31c2984546d2746becf71e2e014ff6f.npy +04379243-f27b818a99bf195f76e9713f57a5fcb6.npy +04379243-296cfdd6b347a8e219fb4103277a6b93.npy +04401088-8e00be7402a612e17d6b888b4eb1ac9f.npy +04379243-8ac4d93e65b9d58d9b937d98d58545fa.npy +04379243-5690d17b330f73adfeb8ceb93793cb5.npy +03001627-4fae9528f1403fd0f9702e673573a443.npy +04379243-1c123801cd052c833bd248747cb27ae2.npy +03001627-474b82a849e5064fa9dea4db53ba3dd.npy +03593526-3cd46f573c68e5fcfd41ffe96f6ef4b4.npy +04379243-d820b240ee17047fac51268fdb437a9e.npy +04256520-8daffd33afca5e02ca8dac6d3025a7da.npy +04379243-933096cbd0f7ef0aa73562d75299fcd8.npy +04530566-e49935adf322de2f77e672c4996ec4a3.npy +03001627-5c4e1a58eeb3171dad8af6714b643432.npy +04256520-34878cff5db772bad810b14a81e12eca.npy +04379243-9184aa5ef68a383918c27c564e9b3b91.npy +03001627-58616932b0e7ab6d78b03575bb54dfd4.npy +03001627-97396529412ab7602f81cb887dc35578.npy +03790512-e55e06e7a84f49e2b37378f3c85478b4.npy +03001627-cf24fc2d10f8da31283b00891f680579.npy +03001627-d01321ae63ae0b40ad1f278e1513f3b7.npy +03001627-903e861a95d6a2d5a6db47a0a040d0ff.npy +03636649-7d097f4b38f0a8a65b6c7da997b0e5e3.npy +02691156-775f06502261575c26b390daf74a4b00.npy +02691156-a3fc9ef9f611a783525e60273896d30a.npy +02747177-78f8bb00a5850aaf81faebbdea6bd9be.npy +02691156-cce565137003bb39b2da68ec42b2eaf6.npy +02818832-3a627c3fe65325ab052788001910919.npy +04379243-1815c6431b06dfb4f008d8a3590fb522.npy +04379243-471f9b50c57b07056abfacdc918044f4.npy +04379243-50da3e6b87b52ccc99e8bf807e902261.npy +03467517-16d9563fe86318cdac496d9f900602fe.npy +04090263-6ab8bee75629e98d2810ab2c421a9619.npy +02924116-7f0f12b1280c47ebe2dc67b821479cc4.npy +03001627-98a1f8651c962402492d9da2668ec34c.npy +04379243-e993ddaf6d03003071a782a4379556c7.npy +04379243-c5d499a443ef70906b882130fa92c175.npy +03001627-2b5953c986dd08f2f91663a74ccd2338.npy +04379243-83ca8d37a6f44dff1652fb73e93ef5e7.npy +02958343-79aafe31e4f2677b1f0fdc8ac183f8b.npy +02691156-b9e6298004d7d422bd46d022fd7d80aa.npy +03211117-bae43dafa75f827f4375bc8943daa105.npy +02933112-b4130f8f597c8f38986f688b80d667f0.npy +03046257-97fc20eff457b57fe6fe3612af521500.npy +04379243-f476ea8dabe53bb8efb94709f30ce0d2.npy +03001627-ea918174759a2079e83221ad0d21775.npy +02958343-91b636d0c4729cda1d9cc9d194c8533.npy +03001627-40e9fdb477fc0c10f07ea52432becd0a.npy +04225987-abdc4a823b1f78c397f47f3057557cbe.npy +03325088-3814a29d435de3db54d7082b34825ef0.npy +03642806-b36c5ee8b04b4b0243cecf206f8bdb34.npy +04379243-da2f2572b10c0ed8f1783a44a88d6274.npy +04256520-c37d49d715cc4d2ec7e48270ba1490a5.npy +04256520-89e00bb2b82e9e86c036a40816608369.npy +03636649-d682bfc447413fd167a9bb855340227f.npy +04379243-d2f811bc37858425a63ceecddc308b25.npy +02691156-cfc075c635df8a7a94b9c9a92aa36f8c.npy +03636649-60fba8438739f3cfba9ea396e14c59f2.npy +04530566-4fc0f4f2d29a463cb1bb46d2556ba67d.npy +04530566-36123091df7600dab1f22ce939b4db68.npy +04090263-c9b36427b66414de42ca7cc070f21ed3.npy +03467517-6c438af8d57d047cdc6782957fd2f5d2.npy +04379243-ab8cdc829a360d59339797c21e8801b1.npy +04090263-2d310466453c3e42fa596c3267b95876.npy +02876657-3bf6160225cd15453a762233fffc49ea.npy +04379243-f1c17621d394670b48d1a35afd3934.npy +03001627-7eb4a453070b3f090d1267f8054d8a8.npy +04256520-382d5ba8f3f89385debd258f4352e626.npy +04379243-b052445a4de3c06a10c0c01485abc473.npy +04256520-810e4815b0ef6f1314038d588fd1342f.npy +02691156-f7c11b5e07e9ccab3a116bc3efac4e3b.npy +04379243-d9744ed1255664e7b0c90fa5479c8a6.npy +03211117-64c23d38d98f7529811348287b48cb45.npy +03046257-5437b68ddffc8f229e5629b793f22d35.npy +02924116-7fbc3347e024ac2f3cc48ad84c73863d.npy +03691459-f98620e647a77e1f8b5ea808b63cd2a6.npy +04074963-775230183193fb9c39054ca4bd28c2fb.npy +04090263-bd1711225c6b87332e60a638a5e115e7.npy +04530566-cdfe819679f7c2e2916576b265053633.npy +02691156-7664f3809169e998a4ee0fb6a51564c3.npy +03001627-a0a01b87633d31061e6becdb5008d9af.npy +03001627-9c5b246616974299f1783a44a88d6274.npy +02828884-360d9cc763aa370320768660cf080d12.npy +03593526-8029c2527230111aad1d789f3b2120d0.npy +04256520-c4b2bd128c424f361b02cde7e81f0fc3.npy +04379243-e64f3681d7c76bb743638dabe1eb5336.npy +02808440-5634cbd9ad6317b444221bef0fa3c36b.npy +04256520-3513af0a9abe4b48f13ce777d031b4b2.npy +03001627-8ef2d2d320e4f3479e3ca99089143c61.npy +03513137-fd861e0998b5acddb20f6e48f6a30cbf.npy +02880940-46d014209027ec188e74a3351a4d8b3a.npy +02691156-2d7aff5577ae7af0d8ff6111270336a9.npy +02691156-d617ffca7890b33eeb9d949e4b90f4af.npy +04256520-7b9d9c738c6042ad1c2c02171f63f02f.npy +02747177-90669f582a8fccc5ad5067eac75a07f7.npy +03001627-32563c1b8b31667bb6695fcbbfeb161b.npy +02958343-9d77d4c959974035fab60fc805223a73.npy +03001627-b455c3037b013d85492d9da2668ec34c.npy +04379243-ebfe93f04bd040ced98bf80379cd1d6.npy +02958343-4a23138e9dc20916147f7a82b2d95068.npy +02880940-aeb7b4bb33fd43a14e23e9314af9ae57.npy +03636649-4dde6d694443a488edb5be732846826.npy +03325088-f4f6333e2342ea4276c18e71fd49c4dc.npy +03691459-5b3bf009f0dee3f01ad88f716ea80910.npy +04379243-d31b0d2a41051f2c7b79156a61ad4c01.npy +02828884-c3531b822720720bf27f378f9a625c3.npy +02691156-a3927542339a2c491b1cc145b0144991.npy +04004475-6039a39331a844138796ffe7637b86a0.npy +02691156-6ecf2dd001e3b029dc53c0dc42fb387b.npy +03001627-541746ddb47aa2af4e186c8346f12e6.npy +04379243-9c9554e0883818c9febad4f49b26ec52.npy +04530566-51f002bbc33e4b34aff407511d7dfc96.npy +04379243-5e3f91e841bf74d240cb0a485b0065bc.npy +04468005-7c35b5da555b7a0c3b2a9f4a86c95221.npy +03001627-b9382558b6b4e858ce5de6b2dd443a15.npy +04379243-6e9e8100ffa2a7fb3b1bee6df796f998.npy +02958343-b8f6994a33f4f1adbda733a39f84326d.npy +04468005-54538ea15381fb87175776dbca7c7036.npy +02691156-e138a98d82f3aa692142bc26f72ae44c.npy +02958343-56a3f3d118f350a516abce8cb03e7794.npy +04256520-4f6ba19d62789d90d71c0b5c63bf171.npy +04379243-3b569be398a7e56eb4d174e5c61f344.npy +02691156-dbee200cebd464779b0ed23034a67f7f.npy +02691156-fc76d0a9da7cde0bef5ebf5f74916182.npy +03001627-bdd29e651e5f6fb2b079317292bdc5d4.npy +02933112-6e5ac40051b3e17b697129c0aef9e5f7.npy +04379243-5ee4cbe45bdc4cd571a782a4379556c7.npy +02958343-3500ccddade6926233307cdc293a210c.npy +04379243-b8cc89f8dbffe099a2da1afa391f92db.npy +03325088-9ce16ab9b4bad6e2b7a867e9b35a1295.npy +03001627-2c250a89e731a3d16f554fd9e81f2ffc.npy +03691459-9f4aab6206870d5deb34db531a289b8e.npy +03636649-91b7d2915bfede639b3360f500ac52a.npy +04530566-f226832ef907984fd8d4a0e4fc199475.npy +02958343-730608de801837b495b02c654da6c998.npy +02808440-549663876b12914accd0340812259a39.npy +03593526-2d5cccc84167c652b5918a323a1320cb.npy +04379243-7dca56442a9756a2e38cad80f0be5c63.npy +03938244-94e39fb5f01f15118998b3b64a143d42.npy +02924116-636f88c563c889147a69fd1f16c84fc.npy +03001627-89b05900bf1df4d8c8687ff9b0b4e4ac.npy +04256520-f1a09674a12a3aa7297936c81e7f6629.npy +04530566-d37263bdd876ddf6f885c09aa3e51c57.npy +04090263-33d90fc45cfadd54cc273c614d275d95.npy +03001627-d504ebe36ddde74cb5e61088d6c054a1.npy +03001627-670c7df7c840f78bcb7547c95fbdff26.npy +03001627-8a21b853c8de77f0c8687ff9b0b4e4ac.npy +03691459-9b4d3ead5066a6c5844e9c5caa6d29c6.npy +04379243-bd9758dc06e3c2a01e4317813b39d4fe.npy +03691459-5578446e4a13451a6c7c9dba2abc9f8b.npy +02876657-59763dfe99084f0440ba17ccf542984c.npy +03046257-312304e53430a5afc1f818f3a4aae3be.npy +02691156-90769434f2b588c1b675ec196a869fe5.npy +02876657-591153135f8571a69fc36bc06f1db2fa.npy +04379243-ca43d45909245ceb4ca2c1f43556033c.npy +04379243-78ccb410de7bfd821f8d8332ee17945a.npy +02691156-80b8f4da6b77eb66d208f79049825a82.npy +03790512-fb3e72a17d45156eef7c0039cbd1871c.npy +02828884-530b1267e70cf134d4d8765e3910f617.npy +02691156-66cd9502b63e8a97bbf3143b1cb6076a.npy +04379243-492de0f32fc58c83297936c81e7f6629.npy +04090263-7ce9eecd689e432892cea77f96988ae6.npy +04379243-1417875756d55264ab94214c753c8efe.npy +03001627-eee352c9cadd79cedb1051713db42252.npy +02691156-fd425567d79a43d14f8a08a5e6b028e7.npy +04401088-f9023b680f219f7c363111a4e20c10d0.npy +03001627-2c052f5541d4d5689b2d7f86be5d0083.npy +02691156-f89b085c37779a5997517c313146c4ab.npy +03636649-dce4bd10d499b2f24b3c42e318f3affc.npy +04379243-87accfd64238d29845511d16be3037f3.npy +04401088-e870d160aab8a55f1a696e9ae9fac3ba.npy +02958343-95d18b69c9624a05473f10e6caaeca56.npy +04004475-d918b4b7498972bdc9a1694d5d1efe00.npy +02691156-5cbe5be753b5c7faf389d19fad321c37.npy +02992529-9952f0dc41b20fcfdd5b23028b480cc3.npy +04379243-3512806247a9e1ae4ffcc2bca1c09e9.npy +03325088-6909b927f7712ee7f235ab3c41aeb5b6.npy +04256520-9eaaf854334b3bca676de9b6e111da8b.npy +03001627-6dfa9675d27b5fc134f6a34e269f5ec1.npy +02691156-fb2204e98090448ebbf3143b1cb6076a.npy +04256520-85bb20bc97b61c17261770c74651d29a.npy +04379243-a8fa391882414febad4f49b26ec52.npy +04256520-96ee3d286bfb909a204812d6a020ec9b.npy +04379243-f1b42fa8b6b48e927c34b035140384.npy +02691156-8a47b24f85a0eafa12234b062bc6c471.npy +04379243-763737ea91a58b0360eda59359536e76.npy +02876657-42f85b0eb5e9fd508f9c4ecc067067e9.npy +03991062-297999156841f16ade98d10ab5975b59.npy +04379243-5970844b794a55a736d8dd30a594b2af.npy +04090263-1c231bd6dfbefeba6bd753a4bc3410c1.npy +04379243-8a98eb9c64d878dd419786e9c37fabbe.npy +03325088-b89336e1f0e8aa3d76c18e71fd49c4dc.npy +02992529-ed53e90551ef9cb7118f00b061390b2.npy +03790512-9dd4ae1c34af4766b4f2746c8140d6d6.npy +02876657-347f9f4a04cc00841fba588fa05a3c38.npy +04256520-89f4fca1f562f9103264e1c4b42b3e14.npy +04530566-4b7642b98790bd4a58a8952c93ff9829.npy +02691156-f2f779b4f12ea6d67209009cfb89d4bd.npy +04401088-5f4c8cb8b3feae768c641604807c82a.npy +02828884-9113be55eb8ddd8ead5067eac75a07f7.npy +03001627-3115864130f4e8188f56c17c21b5509b.npy +02992529-959975a60ae104c48780444eaa02106b.npy +03636649-b2347fe81bd2db6a4b3c42e318f3affc.npy +02958343-460f7950d804d4564d7ac55d461d1984.npy +04530566-491a1618a4891fc73d1328bfe2caad0a.npy +04099429-1ab4a282a803461bf3e918c6494ec5fa.npy +02933112-30675877e822626e3fe047712e43e185.npy +03761084-c261ced82d435328c5b43a3b554f31ab.npy +02691156-87d764f79c2f3af24c2c88971423d0be.npy +04256520-8ce496ed6befb8db78fffc86da230525.npy +04379243-eecddd2b28a9e59866f379f51753f72b.npy +03325088-efb3a634efc20f9a4d4b39461684fdf9.npy +02992529-396fba35f02a9cc9bc1f690a77fffa14.npy +03001627-191360ba29f3d296ff458e602ebccbb0.npy +03001627-cdfe4ea9d00ce861f77e1de7c7a7b6e7.npy +03636649-a654df55875a2104d663817442d5278.npy +02691156-e15f4c98857b67e41e287f9f679ab620.npy +03001627-2b8c678b99f7b2807ea88ba060407992.npy +04379243-45a09b1ce3111e4f22f4fabdf1ee0670.npy +03001627-e916dfe829b5b3daf4b6538438a0b930.npy +03691459-337db7fe63aee7512d97367ba974aca3.npy +04090263-eca3075b0b976054f471dd2a9b3b53b1.npy +03467517-46354939c9eb3e20d7dd3e22ab50af23.npy +03691459-1aa51463dac23d5cc9f08ea7a19d874e.npy +03991062-3f9f732d2921e37781faebbdea6bd9be.npy +02828884-550b7b205e57c3b2315d0535381646e0.npy +04379243-ad26e8e474d42a4a79b3e1be3524f72f.npy +03001627-738188ae01887d2349bb1cbbf9a4206.npy +04468005-83806f7ea055359cd0656aee7124fe30.npy +02843684-3ee8b741d2a93a146faea4ea390b4428.npy +04090263-faf37c99fc99b88ba3e868f66b3e92fb.npy +02691156-f1b407dd7f610bb1a266a0298675ed53.npy +04530566-591d1b833b9ebfe798b8c800ae001b66.npy +03001627-1997d5827caf81df67d783b4714d4324.npy +04090263-4d355e20ad1b6eb6e7da0b4c2db4425f.npy +04090263-8deda7d1c75b33676314c3b6a3a65519.npy +02808440-49e43bbff6765f95d16ed9439ea3f1a5.npy +04379243-3f21494d8a34df8481a172d69c52a28a.npy +03001627-fb381061e67388ba80360680c1602c7d.npy +04256520-4076958da964edb95ff61a3a2a0e2484.npy +04256520-39a922f31e5a93bdc563fcc2752ece39.npy +02933112-7910e29e5285fa1a178e7d331e641179.npy +04379243-17b2481d38b84b334c37b9ce3a3de242.npy +02880940-a83b2eb519fbef17e922c0c19528ec07.npy +04379243-c74bad51457fb0faa0ab1d82ef09f78f.npy +03001627-80415f427a9368227678f114ae956b82.npy +02958343-7db943b676cd86d5729c04438af8eabf.npy +02828884-80d62612758f74d4e8a5546ad55c2a41.npy +02958343-5c4bb9e23c6cd8511371f3c322b54f2c.npy +03001627-a037d4ba135bea9472a38ac2b8f5cd48.npy +03691459-fb6bb656468452fb22d1a40e420084a6.npy +02933112-7e0483b10eb6ae141620773c2aaaa465.npy +02808440-9db2b3689da207ddb9cf447f0a2a43d3.npy +04256520-dbe7ab8fbc9429c2cf40e78cb31675ae.npy +03337140-c227d03fbea989c6ef93db01ab079fcc.npy +04379243-aca4c523f999de86febad4f49b26ec52.npy +04379243-dd0c4018a8b310edafaeb6535dda1ed.npy +04379243-5a3e5f0fff5a7220b4ca2ef8c032d07d.npy +03001627-a6507d76e88e9d68c28a12683f5d3629.npy +04379243-758df6055459cdf6cf58a1b90d479c9.npy +03001627-107caefdad02cf1c8ab8e68cb52baa6a.npy +02958343-c4a2e92c4b79ef3140273d3a78e6b502.npy +02958343-f9f6c13367f93890657766c4624e375e.npy +03691459-e4edc21690f623a35587d8c9be86464a.npy +04379243-174832b73cd6d91c9856fa70a578baeb.npy +03211117-d1718f74c964b34e234c2f2e8f2fe6da.npy +02808440-ba86184fb4bd46a23321831d2245cf06.npy +02691156-d9a263d86ae0fa599751c7a6f15617f4.npy +02992529-725cf43af935ee023832db239383a26e.npy +04379243-43fcddd5232a6021a56e8b79ca4e2911.npy +03001627-a5abf524f9b08432f51f77a6d7299806.npy +03211117-56dee4eb44b2f0e64a6b6d001599a1e5.npy +02933112-4b80db7aaf0dff0c4da5feafe6f1c8fc.npy +04379243-6f1985e1c09aa1be7dd7d23ce6ceed2e.npy +04256520-e3b28c9216617a638ab9d2d7b1d714.npy +04379243-9c0485519f34076a486150a9b7f2cf18.npy +02808440-449e90cbbe310030b983088451bda93b.npy +04090263-5aa0e518413524436ea2d3b1b25fdbb7.npy +04256520-4769bb2062392beb453a4adde9273930.npy +03948459-c045c2df9649384e58da2ab14df356b2.npy +04090263-156dbdcadae5e010337b0188275140f9.npy +04256520-dd4c87420882a7e6dcfceb73ef9b6e3b.npy +04379243-2e8500336964ddabcb51f8085cd316d0.npy +04379243-d1a0b26d98ee4a877fa6d07b5977c143.npy +02958343-863f9284eec4a256e9d8921ebe6d5b8e.npy +03636649-8b60bb548c0813a7e420612cf7bb547c.npy +04379243-bb1ff02f14d1cdd19ccce4c6d5bb195f.npy +03001627-5a3228a34ec0572b4b3c42e318f3affc.npy +04256520-5cc8f84b9b53b30bdfa4ff010b8b9d1c.npy +04090263-9c70690a9d79a4d412a8e5e6e6618c8e.npy +03636649-1b0ecf93a4a36a70f7b783634bf3f92f.npy +03467517-ce3e563f291d1b3311a3eda9aff2873.npy +04379243-e10181e68d41be9a75f27865805fd94a.npy +03691459-6c31773432190681f46dcb5d9d87ce1b.npy +04256520-a3feac5d875f764c1961e650f3cfa396.npy +04256520-447856e1071e8b83c036a40816608369.npy +04379243-65cbf486ccc5afc53002761e7a3ba3bd.npy +03691459-c50c27f14da0f7fb86785c91e1a79038.npy +04256520-ee71654238a92dabddcbda91db0cadbd.npy +04090263-6e0e38455b33bbf7632bedb12ff8cfc9.npy +03642806-e5559cd005d5c4942a7b0c74c5f22fc4.npy +04379243-b7fa4e123bcf7457ab610b0c94236463.npy +02691156-9a266b3a734e374687bf26680c510802.npy +02958343-ba9097cf9c836c0f2a9eb0f146e94477.npy +03211117-795fab6a3c23c0779f8445dce6fc950e.npy +04379243-7cb4211c4a8dc2cbad5067eac75a07f7.npy +03211117-2bb72bc8157a2d8dd5f7c62c7dfe63f9.npy +04379243-766fce6fad5a071bc5beea20858a99d5.npy +02691156-d7a2512d9d8ad4c8a18e0889038e4fb6.npy +03593526-41fcf346a7b3ceb75337cdc4b758988c.npy +03046257-f63ad6dcf847c2f95860148f7c2404c9.npy +04401088-c95b7121b6408df49fda13f2ab6d2b41.npy +02691156-d708c311bcd60e61c9ac656f0c2edc4b.npy +04379243-75f2bc98aecf198974984b9cd0997a52.npy +02691156-f39985959d394f8c863ab010b80d9ed.npy +03001627-631671b636ab97d4da41a38d2e317241.npy +02958343-b06c5da878580bec3c0146ad3ea2d7d.npy +02691156-35131f7ea7256373879c08e5cc6e64bc.npy +03691459-efb33523a6be2e105a31d91ec836a511.npy +03642806-773e395af8222f5a7ade0e7a3afdc8.npy +04530566-c00a8f1dc19a0e5341213ed93def741e.npy +04379243-64ffb47735074fb128ea9c4c28e5ce40.npy +02828884-8ccb3bf7c49c24c0d4d8765e3910f617.npy +02691156-37f251fbd5e094348139630c61d12904.npy +02958343-eef8e5bd46755164eb2d90cf3f6fcb8c.npy +04379243-33b56fcb0b86e914c3bd24f986301745.npy +03046257-dbec11f4a9869cdff51f77a6d7299806.npy +02691156-b2960c2be8fad9dac140e34b6af37a1d.npy +03691459-bda24b02920f91d1887e8faf8f33b0c5.npy +04256520-f2446f65ba438c2119fb4103277a6b93.npy +03624134-b382ba6ce202434bd3802c3145f560bc.npy +04090263-4dff14f1635e9abeb1e00d60b0f9cc70.npy +04379243-7f0aaa160a9f024e492d9da2668ec34c.npy +03636649-2da9d9bea10d936e23c0d2e0152e91b5.npy +03948459-fe6368e73425bdc8ea70d2e1ac81279b.npy +03636649-1ac102f4a452771521e935c3c465f9f.npy +04379243-6d580c3fb8702ceaa864ae08f4e79056.npy +04379243-20bc1ce03f5996bf9ee02475d7f98585.npy +03085013-e2cd4218113ddcfe75b627155369ae7.npy +04379243-188ce43d9c8caabc5213169cc9897a9d.npy +02808440-805f3d85487a6e523321831d2245cf06.npy +04256520-a65534c7545a4b3a19fb4103277a6b93.npy +03636649-b95719df909773fe65d8717db5192d1.npy +03624134-8c2a7aab604336ebb1ca50cbadeab92c.npy +04256520-49d6f351e82d186b366971e8a2cdf120.npy +04530566-9a9bd517b3d9c60f9e23f6fc87a31098.npy +04379243-759cb93134fd5efde76bc197b3a3ffc0.npy +04090263-a4ad8e643348a9ff3f217b945a063dd2.npy +04379243-963f0a74420659066c09be1a24173c83.npy +02828884-66aade9f5d8c74ae924bf081da6f024c.npy +04379243-7153026411fbb33cae685ca100c909e8.npy +03642806-80523db48cdfd058b9e4d514e1e82b2b.npy +03001627-u481ebf18-4bbb-4b49-90c9-7a1e9348b647.npy +02924116-7cb9f004d48454e18cdfa422d76ee8.npy +04090263-339ae95cab075926c1fb6fdac33c3f5.npy +02828884-ec3b32347c823f258c2b40655482a651.npy +04256520-cd9ef0c92376e604963cdf8b01c64c16.npy +03337140-c06792fff0774954492d9da2668ec34c.npy +03636649-89ed63af13b79f3ef42a90fe4baf4591.npy +02924116-2dca337ba2d9d12a0fba45aa212129.npy +03001627-d571022446bdf81ee83221ad0d21775.npy +04379243-c4b5ed6c9ae1ec5e8c54ec820a9ed1cd.npy +02958343-7c421b6417152aae473f10e6caaeca56.npy +04256520-c91ed7cebef758f935836c728d324152.npy +04379243-12fa3eea2b02ab9e931178a47d29b194.npy +03001627-c47f71319ead4eb8a4fb72f4f3b0e317.npy +03001627-4bc5920f74bbf6412acd2bb6205825cb.npy +02924116-f413b641dfdbf6317f8c317a43ebc941.npy +03211117-c2b4ffa6f1911d4cd1ecbd6620e3fd17.npy +03790512-d54e0f22d4604d741f24b86004bccc4d.npy +04090263-be55b1a477c465226f8c560cfa1fa0c9.npy +03001627-330d08738230faf0bc78bb6f3ca89e4c.npy +02828884-6accdfe97ecfa9952056b4bd5d870b47.npy +03001627-1c17cc67b8c747c3febad4f49b26ec52.npy +03991062-ad200681b4a58c30de24f3da4a0e8540.npy +03001627-763bccb675b7439ab9afb6208cab1d.npy +02958343-7a13aaf4344630329ed7f3a4aa9b6d86.npy +03991062-b84f95f09345b864a249f8489bc060dd.npy +04530566-fd255f604c44b9cf497768bbb615071b.npy +02691156-1628b65a9f3cd7c05e9e2656aff7dd5b.npy +03211117-2a08ac484551337a90eb6645edb4567b.npy +03001627-2fa044df89ef13b0e5c1abd833032715.npy +03691459-37992f1a3a6eb8abf398d0c5832df00e.npy +02691156-1cfada8b8ad2428fcabcecce1c335df1.npy +03513137-d8736fc5b77ac6d26e686498ed562f91.npy +04530566-8eb481ee0fa4f55bf9d742d7f0246fb0.npy +02828884-349e1bf46f54c4f267efa971ab69a8e9.npy +03001627-f35abb8246614d7ff38854b09cdc7cc5.npy +03001627-e2acc4d276fda3d77d70172a29ade99a.npy +04256520-75a451559a48b42f6e525b37bf033529.npy +03001627-7182f94bdd17c0ecd6bbf317cb591f56.npy +03001627-fb369c50dc8fdcc5ff2c92c2a4f65876.npy +04225987-5aec8d7745acbca498c63cb68f11df34.npy +04379243-63b5d8f4fcb29b12d0125a4a81c5d058.npy +04379243-7807caccf26f7845e5cf802ea0702182.npy +03207941-276a54bd18473b58703939fc621a3e37.npy +02958343-b6f76fc67324911616abce8cb03e7794.npy +04530566-ec4a394fd782e66b749227c7279794e.npy +04379243-7602875276e42d1990eb1f8a00f61726.npy +03636649-596ac8748f6c946efcb8d8c6d4df8143.npy +02933112-2d1b4c33c0a40653c59350d819542ec7.npy +03325088-7bbfca0420c26d692db5d63410b93a87.npy +03001627-7fc00af759f4382c48d90eef8384210.npy +03001627-5e685e076287215be8f8c11a24c52ebb.npy +04379243-d14a4b797fec250b83768a4ac1607d73.npy +03211117-33083674276c5cf5b07a27512172330.npy +02691156-de5cade3966a1dad94946b454cd190d0.npy +04379243-46a07944ca646df01ff8bce0e3352d0c.npy +04530566-6c2c2ce0215d3f979b3523fcb9cc5680.npy +02691156-d21c556af88582754c3a35cee92bb95b.npy +02954340-61437489633f5d167c35d3c5d3b1fcf7.npy +02958343-fc99fdfd71b5662a669a6bfc71569d.npy +04256520-fefb2c5e88d7e647eaf288f952624966.npy +04256520-6aef3ffcf683005263cc440c7caf3d76.npy +03928116-214ddee55941f803a94b8a2c7c1e5b8b.npy +04401088-fb050aca4d5f2573cf1d3d11d6121bb4.npy +02958343-510df40932e79779a324deea8acbeebe.npy +03046257-d5cf322e44690c0d6030431156406c3a.npy +03790512-104d1e5422e79ff667691228a451173a.npy +04256520-8bf3680dded4772ff51fa0238791f5dc.npy +02691156-73fb8c3c4530ed4bbf3143b1cb6076a.npy +02808440-a0c19e3a7fddb5733178fd967888865d.npy +02808440-f9fe136c1738dcb1ec3cc26553cfa06b.npy +04379243-34d82982f75a6249ccce4c6d5bb195f.npy +03001627-edef00af1cdfbe1419fb4103277a6b93.npy +04379243-debd06d3176a5b728cbb8bac2032149c.npy +04379243-7d0eea8581ece273820018801b237b3d.npy +03636649-ebdc97f5fa29b1dae6597d391ab6fcc1.npy +03790512-c6fbae9bbff2829db3a2525d53af0903.npy +02992529-3c244a5e76cec2cf6f108f2b64e6593a.npy +02691156-4a837740b388aa45d8ff6111270336a9.npy +04379243-669a8114b9a602c2febad4f49b26ec52.npy +04090263-dc9a54a41fbd77314aef47a2c7bc343b.npy +04379243-9e2cb89de5564d7c1dc5f68d8d7e8ab0.npy +04401088-4157af4a11fda8ebdd3d821abaa89276.npy +04379243-1a2914169a3a1536a71646339441ab0c.npy +04090263-4e699ed7d6b3e556d3cd5c5355c4e1f6.npy +04330267-44d882d8627163957a35fac374dd53e8.npy +04090263-f42ef3273a8b4cbbf4f70c928a738b3.npy +02691156-eb43db95d804f40d66cf1b4a8fc3914e.npy +03513137-77266730e34800638d23b8b99c98bb6e.npy +04225987-dcb9a62d5ef76f389da15808191f1405.npy +04468005-8a147e233c90a5d52470de2774d6099.npy +04379243-2642d805c53e243d629f73b53bd7a234.npy +04530566-4fbc7c634bd4488798b8c800ae001b66.npy +03211117-c65b30c8ec2833692d56866e214da3cf.npy +02691156-3d2e10ca9a5db964dc398f7f89f37ee6.npy +02876657-3b956918a41da89c325e6e8eb2c67fd8.npy +02958343-d9838c0fcfd30659d9f8911ce020a037.npy +02747177-3be3e86b2fad511048d5a1386787189.npy +02691156-32edb6ba5788dc12d8ff6111270336a9.npy +02691156-229cd78f9ac3e77c8b96ae1a0a8b84ec.npy +04379243-7722e83d837b5bfcddafe9b591eb9ebc.npy +04379243-cc3cdaa52b4b96fa55f46d55537192b6.npy +02992529-8fcae817c180d5224208dfa1c5fa1065.npy +04379243-7093cec0f1eba67e11f3f1bdf34ac930.npy +03001627-47fc279d7f0c2a492d9da2668ec34c.npy +04379243-5040f8f3e2293db448e116352760c52d.npy +03046257-738dbd4808eec6c5472c1918bd40698f.npy +03001627-c877660e0ec15c0d22be63590e183603.npy +02958343-5c04452276a26b80d97e5ba4dc9a93c3.npy +03001627-643e55c58a248949b24e615f75a5a1bb.npy +04379243-f8f22279842d9b8bfc6d85675a0e869f.npy +03001627-d1caa22978e516655c31590a2627247.npy +03636649-46811f96fdad80cf912acc8c54e7fc1.npy +03001627-3df44d30265f697e7e684d25d4dcaf0.npy +03691459-fc5315b04ff094686d564e28438f8cbc.npy +03001627-2fb9c50ebbd98075ba5342d638d0c267.npy +02691156-e09c32b947e33f619ba010ddb4974fe.npy +03797390-a1d293f5cc20d01ad7f470ee20dce9e0.npy +04379243-e28af7dd5593fe6f820018801b237b3d.npy +03211117-6f3c489407842f81c36ff2417ee947.npy +04554684-ded40c1866a00ea02b5631520b7d94fe.npy +03211117-9aea8bba40aa793d9429f6a938b3978d.npy +03085013-6b8b2a80a834a297590e6ac98d4b27b0.npy +04379243-d7b56f61904aca6b7422d2e1b1d40882.npy +04379243-376c99ec94d34cf4e76bc197b3a3ffc0.npy +04379243-6f934779da945914bccaad2aa3926367.npy +04090263-c18b96da3e1c8a2350780f5a8c844eae.npy +03001627-6e1fbf46f1d0fb73d8cc7a9b2448f97.npy +03001627-37aa434da4ef00038b424343280aeccb.npy +03636649-dd818b0269b1aa15fcb8d8c6d4df8143.npy +03001627-e28a52d8864870b222ed3259ee7e608a.npy +04256520-34e10b72cfc4f36ad8e004adc6acd545.npy +04379243-4f7497a449c2e4a56b9e47850f23a791.npy +02691156-3fa6a05b62169e0d2350d07acbcc057a.npy +03636649-37aac1913201b058c02170c33e00ea64.npy +02691156-7e75688f4b185d4193a78ffd70737098.npy +02958343-9a2854600f24017949b12cf3977a48b.npy +04379243-e18d2ccfd7e0da86bc22c9f90939338.npy +04379243-246b26ca99193386668ae11a7db5e82a.npy +04401088-d932fb5d06d5e4f8da8c8a88ff86c5a7.npy +02958343-dd37570a8876c4a4a513de4eb79b310d.npy +03636649-53ae95290cca57d430c35ecdb9dea035.npy +04379243-7d6102f23f51764d2ed4a731510fb423.npy +02958343-5bab0881b7a18b12733269057ed164db.npy +04401088-c3a90bcecce7f4817b6fd5468f603b31.npy +04099429-d6c905e92a1da84fac912b2d8003cafc.npy +03797390-928a383f79698c3fb6d9bc28c8d8a2c4.npy +03001627-753c5b7f6ee56a77d73237b8afc2f0a9.npy +03001627-c0cdfbbf3a80105fa8699b6183baa203.npy +03001627-2a197b179994b877f63e8e405d49b8ce.npy +03046257-22a1e55050bce5c3b441e189e5a85c02.npy +02992529-25eff75e43287223f1cb19f636b1c2bd.npy +03211117-9c23caf872048374ec8285b7fd906069.npy +03325088-1e2e11043b3d67d76621db2c3226f08.npy +02954340-9c225cd8f50b7c353d9199581d0f4b4.npy +04090263-3ca8b397052d4da818336d317bffd215.npy +03001627-2ac88058053d5c2671a782a4379556c7.npy +04379243-1345a6b69c9e7330427e34fb2aadd7a4.npy +03211117-cc4b7dbffb52fdacaccd68c8aac6846c.npy +04379243-ccec9e173fb41a3323eb3ad3d378722a.npy +03001627-59b79461f64a41c3d225e12279334514.npy +02924116-6934ae6c15afd23ed687ba8afc125512.npy +03797390-1dd8290a154f4b1534a8988fdcee4fde.npy +03001627-f5b08ab02727922b738dd0d3509c7e47.npy +03001627-fb912528e642f6ea7c7cfdf5546967dd.npy +04460130-5bae6e286a9ce96de6bffcc6da770837.npy +03325088-7d44ccb1ef1ddb483321831d2245cf06.npy +03001627-9cd0529b7ce926017dbe6b236c44c533.npy +03001627-b19f85fcd46f456bd5cba62773b8025b.npy +03790512-450aa58cb4bcd8a34d8ad024e30db0d.npy +02691156-f07028f2080aaf4e75b90b083ed202b.npy +03691459-cd451b74570bd84f44dc88afcdcd380.npy +04004475-ac2ea2d41c57d1075999f9ba82d15928.npy +02691156-e039c9760ca026cc6aa3bf023a2b42a5.npy +04379243-3bd1fcc6ef50264112126d1916209079.npy +03001627-c405857cd7d8aa04d225e12279334514.npy +02958343-1c351358afff1cc582e5e3e7771ea25.npy +02828884-32563c1b8b31667bb6695fcbbfeb161b.npy +04256520-5259557e17d437954c90f2ddc14dc59b.npy +03001627-4422c64dffcd8662eaf288f952624966.npy +02818832-b9302be3dc846d834f0ba81bea651144.npy +03001627-a67a09662c39430bc8687ff9b0b4e4ac.npy +02808440-c1b69f70751648a0b362845c6edb57fc.npy +03790512-832c4a316c419228b37378f3c85478b4.npy +02933112-9c87aebafdb4830ba5dc3fef8d22887b.npy +03790512-58705c949dd5d944d9d3572bbd9cf789.npy +04379243-fe7dd4f6b988123bd810b14a81e12eca.npy +03001627-98d1fb12c3354d341e67ee2399c63faa.npy +04090263-d1e786e052c26ed3cfb3f4d4e98ee41e.npy +03211117-13c8048199d8063c6c6253deb0c008d9.npy +04379243-f7dc5f5fde343cc5c955e5ed03ef3a2f.npy +02958343-c41fc68f756437b2511afe12ef4fe731.npy +02828884-39904b25a6d2f13ed4d8765e3910f617.npy +03337140-2ffd2e6d1a55bdf44c3aee8e9d3a6ffa.npy +03001627-5566ad94be22e7b5d85141a9ad5b3597.npy +03636649-ac662716b87687be71e364dec61013a6.npy +03001627-df609533cd186278398c7598b0d2e5d5.npy +03636649-12e8d8176f2bd111978e8f21c8f49a92.npy +03001627-a990ac870ac807c4d838ae16242881dc.npy +03001627-efefba3f45a9e16dd64ad79e5981cc8f.npy +02747177-ada5b924669c5bf4cb2a965e75be701c.npy +04379243-96fa9d34fcb17ff21fc43d5b32fa230f.npy +04256520-d15ccf2af52a95f619fb4103277a6b93.npy +04379243-92fed8fdc8f881d2dfda46c9a34dab22.npy +02958343-a5a6c94b8a93c11b679506fe2f937c34.npy +04256520-855a071aeff2351a593ebeeedbff73b.npy +03636649-c6612c884c025a48f647dc544bb0ab61.npy +02933112-eb2843ff62280f5320768660cf080d12.npy +02958343-acdb7b476fc5a1ca96f65931c8819eb.npy +02871439-80276f2c816c9e2342fe42ef24970417.npy +02828884-99cd1d8970feddbaed98cca8f0ccd5f7.npy +03790512-77e00aae33f3ecb4f5724931a8c2eb52.npy +03790512-f5badefe2a054ff7d1cdd91e6d9c7a4c.npy +04256520-8f4ba17b19d2d5a0ee50221b2a22a6a4.npy +03211117-b86af5698f9a04a4d0d1157c0bfa4669.npy +03636649-e0577be012414515fcb8d8c6d4df8143.npy +04004475-ca6ffcb4cdf260e62f5798686b2c3330.npy +03642806-2926c35f9f2b8c7556faf77ac8662d5b.npy +02828884-51c60589bdd1ed73d4d8765e3910f617.npy +03337140-49c97ea1b6f4d3c9b5418cab1c661a7e.npy +04090263-35f7e2c8a6c9072eb43c84780cf56b88.npy +03593526-7bf1c516ca16d0c02367de4cd267ca0c.npy +04256520-7d4d8e65979c28c1f8d4231017d95f74.npy +03001627-b162f52f6a1ac00e519f3f3e6cd6d1a6.npy +04379243-54b4555dacd9fc16e1eb1991fb37eb9b.npy +02808440-c97d74e85fb248e6bf258aa99523f66b.npy +04256520-9770f3e5ebc261794f15b22cc208bec1.npy +04090263-1d69667fdee51c20e6fe695987d47043.npy +03001627-bb9bc0e6f8ec17bb7b07a77641318a82.npy +04530566-332d072efa23ec9ae89f0d5485194c5.npy +03001627-d64a812bb87a822b8380de241b5e0725.npy +04401088-98eab6b7dee0d64519907bbfddac6b6.npy +02958343-490812763fa965b8473f10e6caaeca56.npy +02773838-e8039f73cf912ff5e8c69fd29511206a.npy +04256520-d54be63f3df4a80aafb1dd61dbf468dd.npy +03001627-866d6243ed67de2ee0a87b67b4933300.npy +03046257-368d9126e2053bd4815b2b467e8e2eac.npy +02828884-6198e40d0055c59fc34a45b74d0027ff.npy +02691156-ac76572656c1e36ea79176d3c96ca1af.npy +04256520-17b1927dbf59786a45b09d36414f81ec.npy +04256520-2bc178dc567eaaa7e01b76a0b6e5fec5.npy +04379243-76f4352b12cebc55685756818b5a05e.npy +04379243-452a33df06b678c6822b5ad61b22977a.npy +03642806-e9e28a11f71337fc201115f39f20d1ff.npy +04530566-6e0f329ced87d7a3c9cfe13d43d30dc.npy +04330267-27e067d588f8fa27ae410fdebd404ac2.npy +04530566-80e8c7703883a40c9e4614310319ea50.npy +02691156-a273a18b004c209c90b1d6deb98feec6.npy +02818832-7afc224d6b6cb2e4a82f8da544827cac.npy +04379243-5b4997ae8d1e46fd16a2b5862518c93.npy +03636649-ac2a766efbe869cdf51f77a6d7299806.npy +03001627-d081ce6cdafa416c8687ff9b0b4e4ac.npy +03337140-bd86234b060b77857a50afc9c93f8a50.npy +04530566-c600a1ae674cb65c335aeab2c20177db.npy +04530566-f89a76e638ecb1aec79d3cf109867c13.npy +02691156-5bd746709adf5b3ccffae3eeba6126e6.npy +02958343-9c846ae63f5fbd9a16abce8cb03e7794.npy +04256520-5e217fd0fd2b1ce7d3a80acddc1093d9.npy +04379243-3581d1bdd22e782a855931d119219022.npy +04090263-3945a1d805dfde6a989c6c7df583f91e.npy +04379243-4bb8e7499f9c5466a341228b21d337a9.npy +03691459-c117b031376d3c12cd5cc02ebe46ffbd.npy +02691156-48fc59725119ac1133de69c9cd670995.npy +02808440-56fe318a9d7fb0503af30a3946d92feb.npy +02691156-b7bd7a753da0aa113ce4891c7dcdfb1c.npy +03337140-205bf6a78db9e112e7ecdbe73ef4323c.npy +03636649-f8bdd98f53fd851ec1537287b5c50d9d.npy +03211117-92e757e989dab6225ad009ac944c169e.npy +02958343-8364ea0a27342c9d16abce8cb03e7794.npy +03211117-bca2b66a9ef701bf585db0bff5175f74.npy +02924116-9178a769f38b01e8245f1bff867e8982.npy +02954340-c7122c44495a5ac6aceb0fa31f18f016.npy +04256520-58915b74af8f69af5213cec267286d18.npy +04530566-2ee1a459db90488826fea6918e74b120.npy +03001627-cb74cf36ff8fcb8d61d7edc67034608e.npy +04379243-192812aa4ad73d2fe6c5cd45aa112726.npy +04401088-645c1b7e5297cdf567b9bb226efd81df.npy +02691156-241648add391b8d54d210d9468aedaf2.npy +04379243-351057418704d299f51fa0238791f5dc.npy +03001627-6b38324cb8beedc5ca86e527b84d8854.npy +03467517-96af19353b4e3f44bc461aab61d7a636.npy +04379243-b1a156c751cb960f270371af13f7e37.npy +03001627-1ac6531a337de85f2f7628d6bf38bcc4.npy +04379243-f9d405eae2dd08fd12439bb9f264f4d9.npy +04379243-a9a618507a691298febad4f49b26ec52.npy +02933112-55b945bcc9d3525be005c5c244da3c48.npy +02958343-72a35a471514d6299e317a6cc797b629.npy +03001627-986e49bd8314d7424addf6a5f8726274.npy +03938244-7d9cb088956a9c4993e60794f9200b7.npy +02946921-56dfb6a30f498643bbf0c65ae96423ae.npy +02958343-14d47aa57151ae4baa93570ec0c0afff.npy +03211117-a6ce00ec813199804e2b01a3e0fd3197.npy +04530566-b3baa99a603abe4415aeee24c2916cad.npy +02808440-5b7d8d0f5c9ac09a5a4742c0584c3335.npy +04090263-9c0a483ea22323c78ca4596df3cbf136.npy +03001627-8f2cc8ff68f3208ec935dd3bb5739fc.npy +03636649-26cdef36773542454d1e14997920b517.npy +02691156-de29a1335c332a5ef7bc9a344bb7bae5.npy +03001627-45c998547946bc4d6a88c250a18c2861.npy +03642806-62b25a5e3119b8409023147b38c03c9f.npy +03211117-f89e49aa0058323d677ccd99bc42875d.npy +03001627-4909c59d7326a2e6217eabb7c57f6292.npy +02958343-4d8a4808e9bf605b11647ffa4306609.npy +02828884-b09f17c66d25a38cf155d75bbf62b80.npy +04256520-52f6fbe3a36a4d1f19fb4103277a6b93.npy +03046257-8c00d87bcc8f034aa1b95b258b5f7139.npy +04256520-1613148b579a747814038d588fd1342f.npy +02691156-2a801b1918ef23f1121ca0b13e917b22.npy +04379243-53afa98f1de6af6d810b14a81e12eca.npy +02691156-26830050c44b5a8f9cf081e9d8a0b57f.npy +02933112-29ce2b045bc6111912de5317fe5b354f.npy +03636649-2ed8dcef657845be4a8e02787dff638e.npy +04379243-89054836cd41bfb9820018801b237b3d.npy +02691156-d1b407350e61150942d79310bc7e47b3.npy +03001627-a5df9c511f51228f19fb4103277a6b93.npy +04256520-61d93b7c3e83541c81dff5c2e57ad46e.npy +04256520-2e17fbc8ae8989911751d30f076514e.npy +03636649-92c74371acbdc4b1b8e1b99345a5afd4.npy +02992529-30d54e046b9abe8bf1cb19f636b1c2bd.npy +04330267-b6a2fb4fba91d35099762eab905e5e24.npy +04468005-210891be5182a77a74b43df14d002c9d.npy +03710193-168b842e1b905547e5ffa6096479cd83.npy +03710193-b079453fe8d3f43ac51268fdb437a9e.npy +03337140-71da51493940abadce5d6e9371bb5c33.npy +03325088-d613fbb4f7e4cf6a9ba4d8847eef9270.npy +03001627-cf80306fbfc886095213cec267286d18.npy +04379243-e1d8f005e47f3a4ead01cc66cfa1fb80.npy +03001627-f1645567130e99a878268642d8df40d1.npy +04004475-70d90d42d01ec9c479dab49a427a6afa.npy +04379243-c613e4469bfeda17cc4256bed53b2ee2.npy +03636649-571027d7f9639bfa7d7103fc1114c50f.npy +03001627-d0fad7458cdb5178d3f6d823f04dd65.npy +02691156-61c804d4751079962df73a6189a3b87.npy +04090263-b0417ea1c8623f189c5408f4f799fe72.npy +04379243-2f1a310ca0fb6b0177e131ed5f0fcc86.npy +02828884-9891e489f1f4dab52056b4bd5d870b47.npy +02958343-191f9cd970e5b0cc174ee7ebab9d8065.npy +03001627-751667777ff0926ab03957cf6f6ea666.npy +04379243-b825cc91b6257e73002761e7a3ba3bd.npy +04530566-8e8a38abbfa3ddec942654e703edf3c5.npy +03211117-d9bac9c418667d2ba62bc668cb34e698.npy +02933112-132185edbe4f2c5fb4c161851ed2b4e4.npy +04090263-3d5bdd3fb1f4ac0e12a8e5e6e6618c8e.npy +04379243-2aa624d7f91a5c16193d9e76bb15876.npy +02924116-f30209622ad392b1dca398a9db6025b3.npy +04090263-6e4a5a5577d06899498dc39a5b1a1c7d.npy +03467517-af4e80985f965bb091437d7de92c7dd7.npy +04379243-5884f7c8367ea46c7c6c78d6efdd12ae.npy +03001627-fb056f0260d4855d36c8b9bf2576aca2.npy +03046257-f82e94171acffa9cb3914c1351b16c4d.npy +02691156-1e9acb74ad09ba97192ddbe75f0b85fe.npy +02691156-afcb946d2d36a77abc0909d98a1ff2b4.npy +02958343-6a737d71a4c4d81958943aeb17f0d326.npy +03691459-361a97dfbbcdd820b182f50d8877b64.npy +03001627-67bee683e394395d84ea893d074ffaa1.npy +03001627-11358c94662a68117e66b3e5c11f24d4.npy +02828884-1480fa8916f31b6d3c77a85180cab6b6.npy +03001627-fd9b63c23342e57045b799df37b9f05.npy +03636649-57dfd0ac5a78c9322f841233486fac2b.npy +04530566-52492bb52701aa4eac05cacef62577ec.npy +04530566-47a07536cc3ff3219c42421cfc900873.npy +04379243-273b31cfb08c2f2aca9e6cd07e5806da.npy +04530566-7400be7b247ce021be99fd8a5f540d8f.npy +04401088-89019c955310bc56eeb3fafe1bc8c07d.npy +04256520-12ae9aa6900536aaf24f0645d0949356.npy +02958343-575266906372ef117cc922af3684d251.npy +02933112-10c14b0cb76f87584da5feafe6f1c8fc.npy +02828884-80ac9f2999087c868c0a51976aeebbec.npy +04379243-668fc6063bd05447e4bf96d5b836adbc.npy +03001627-2fc85613e0c1fd7c6ff6a1869fe2467f.npy +04256520-eb3b29fb1782c83de8a4454323586e35.npy +02958343-95d8510258f7f919c9be4fc52f26b7f5.npy +04379243-4b237530ff7c8c064b2ec20c30ace65f.npy +02958343-df7c767eba9455f651a95aaa6caba1d3.npy +04379243-1c4192bcee62e018a4207c8c70da88f1.npy +03001627-a4ebefeb5cc26f7378a371eb63283bfc.npy +02924116-6cb8d31ae40d5cacef2ffd8d8b11b2c3.npy +03211117-6f7bbbc83183a93daafac0c8d5992bd.npy +02871439-2a9acc146f7310b1492d9da2668ec34c.npy +04256520-9625852787b360bf20900f5b6ea8b024.npy +04379243-f64617385056e0b1beedb4c8fd29e2d1.npy +02933112-92a1e771eb621c14c2a5a06bb7a05e87.npy +02691156-bd48d0beb5d1acf1d2106c9042f1bde9.npy +02691156-5c3e308093e9f287f019a51d1a3b2e07.npy +04379243-9fd065502f87d1f4c2cd59b38b35eb54.npy +03928116-26aefd556e434170fc33ea9eb1363feb.npy +03691459-9403368e6a0bebf5664c61db46dc2c9e.npy +03211117-85d0ff09690c539cfc727671f5682283.npy +04379243-8b54150f56e59a91de9149d4acef1da1.npy +03467517-36145d7338b0dc2040c20797381ee39f.npy +04379243-c7ff0afab4b7885a52160ba64fb535b2.npy +03636649-fd074c0819b9934f73b8ea30c1700f67.npy +04379243-2e9be34fe47802b217ffa9a4ab48724c.npy +02808440-d34d1113a1125ac756abb3039ae17c7b.npy +04330267-83341c37c4f58ebeb3abbd2edaada094.npy +04379243-1c2e9a364b82f14fb9a0f5d18f1ce54c.npy +03636649-ed6f57c8e550c60d39adae6ec56b2451.npy +02992529-d72b00ba0cbe10a1157f4a560c24391b.npy +02924116-71ba773a665447b583c8e6d5420def84.npy +03593526-1c73c8ff52c31667c8724d5673a063a6.npy +04090263-c26b1d42bad81b6397fd8ef0d14ce047.npy +03001627-dec4d499ce2ff518dc732bd0305fe3a3.npy +04379243-ea559127f7f21405372d8d157558385e.npy +03636649-f8534299ecce5c16eaf14273fa406ffc.npy +04379243-af057970729b2cb255182f299fe41fdc.npy +03001627-d15ccf2af52a95f619fb4103277a6b93.npy +02828884-83e7c29954256530e2c4291819b46f29.npy +03636649-981e7c99ee1fbf91fcb8d8c6d4df8143.npy +02958343-76f35efa4083dc6a4d31b03e74c723a3.npy +04530566-87e1eda2a99c713d4fbe64e9d0fe42b6.npy +04004475-d44c19fe6b01e769f040a28fe9ae7.npy +04401088-afa806973174e442ac4f72bf08dc79a6.npy +02808440-357e42ec5c66861cccd0340812259a39.npy +03001627-78261b526d28a436cc786970133d7717.npy +02958343-f9b9b12c6061d32ab910dc0e33e50abd.npy +04379243-4dc3e9e293450817d3dad974dc098fa1.npy +04256520-b6de66042941f5691301e24e9e27a9c3.npy +02958343-389cc4b8b1e28d1770905bc56bbeab9f.npy +04379243-b4b5eedfa5c159e0d4e369d956a06b76.npy +04090263-7b0889c55d482cdcf0fea2ee98610322.npy +03691459-bc611920d1608f96df172f74754804e6.npy +02808440-f37c6c427d253657bbf140c61ceddce2.npy +02958343-c57c11cbcb97f74058c27e607f6e2d4c.npy +04379243-fed87d16ece9ac0ad42ec7e303174a87.npy +04090263-35976b05836b249552c3271e911ffe19.npy +04554684-e66739cb1df7e6e92da2064a99bad66a.npy +04554684-a4773b8eac98c358cc9b47ce449d317.npy +03691459-1f929c099da1f3d890824251c0961f3.npy +02691156-b1dfa9a6274688cd29ba25678ec45698.npy +03593526-3dec5904337999561710801cae5dc529.npy +02992529-9e302a3f21a992c0bb579d1d8d989550.npy +04530566-6824763a090a0b2fd942f20c59bd7ad0.npy +02958343-4a6dea7ffa04531cf63ee8a34069b7c5.npy +04090263-60035e734229f5eb19f2faa30e245eec.npy +04379243-cfa823ee81496f5912b57997414c1d71.npy +04379243-66e49590fed26b4b8a6a1538ac23319d.npy +02691156-6b8bd13bb6c2589db61f9d3f64979662.npy +04379243-2d8fd94c6aeb5be2beafccdad931a74a.npy +02958343-5fb19e8ecfe42bd170bc1eaaf2d60138.npy +03001627-cb1986dd3e968310664b3b9b23ddfcbc.npy +02876657-9e274df011a9643c21ec51d5b72ac4e7.npy +04379243-7e15b41158aa0bf73542594e05cedc89.npy +02871439-c91abdb369f0e2a1933ffef19678834.npy +04090263-226917d478be80f3542283b6fc64a8f9.npy +03046257-4b317124cfa511b7e26be0306b963c93.npy +03001627-ad64210b56ed1bbf9096ff01c3d5022b.npy +02958343-5695a98b66b2b9a9c81ddeca50aa3117.npy +03001627-41f3a12d9f29f204dbbc9440457e303e.npy +04379243-3f94c1aa9254356579b3e1be3524f72f.npy +03593526-65bec5b1e02db6573543a074b9dea19b.npy +04256520-4c044b514ab3e0eb6eb9b08c8a74d159.npy +04379243-50e269a6c3f3b558db19fa16d5cba023.npy +04379243-ad41461d3fa9b483f6bf408264db131b.npy +04330267-e55fbacb7ca1262814de2a9aaff52ac7.npy +03691459-eb8f035d56539657f90555a83c8826b.npy +04256520-3d164c442e5788e25c7a30510dbe4e9f.npy +02691156-6cfea839d3dfe358bc0909d98a1ff2b4.npy +02992529-b9f67617cf320c20de4349e5bfa4fedb.npy +04401088-202fd2497d2e85f0dd6c14adedcbd4c3.npy +03001627-2b1af04045c8c823f51f77a6d7299806.npy +02880940-64b180d51c6b8cc1e4e346ee2650d150.npy +03001627-97131916969631a379a212fc9db8be5e.npy +02691156-e16f9cc7dedcacdb9b0435532743fd43.npy +04401088-e4d794e92cd098d740dec81c6722f67f.npy +02933112-7328b4c001a249ca39d3717288022c20.npy +04256520-ce424dd12ccad62575206c207a147264.npy +04379243-5d30db5c8d27e120a653489f44e1bf89.npy +02933112-14e2319299a434b24b8710a3469971b1.npy +03001627-e8dc06c3d01d6592f4b6538438a0b930.npy +04090263-3ed4ce6dee76fc90180d8ddbbbd9bd3b.npy +03001627-37ec57f6376fce6d19fb4103277a6b93.npy +02691156-2d43c1430df8194ace5721ccacba16.npy +02958343-1ef8f98842f2a388a4dbb766064f8bbf.npy +04090263-f21a0e54ed515d344110c565e849308e.npy +02691156-6e66c96067f3c631ce58b9b5a8f9e3b2.npy +02691156-1c93b0eb9c313f5d9a6e43b878d5b335.npy +03691459-481d17e1ab933142b868767ca39f1cf9.npy +03046257-7e6fd9692405db19ae46613afc6454.npy +04379243-ece7f04700c5767a4cbf9a02e3342127.npy +03001627-9e9e6025f821c2bdb6d6d1ff246c4885.npy +04379243-e2f632abcd84c03ae7354dcb6082ee59.npy +03001627-8f0deb6b599006a22cc460e9d064e57d.npy +03928116-b42a05bd28f090b3ebc1a7ae7c4c250d.npy +03691459-9a37a34c652c33d37b46c73cad9e78ec.npy +02933112-3c1f9b42e848c740c59350d819542ec7.npy +04530566-5b1552a30341a3b27ac692756be9e24.npy +03001627-489391452ccb38e4c8687ff9b0b4e4ac.npy +04256520-8ae5acfaf2b115382d19175e7d19b7cb.npy +03636649-fea629edc206a49529fbb534b2045025.npy +04330267-f65123e8c8b2fb93324d4e93d8b9cf3d.npy +04530566-481e13e24905af01ba1e7c529a2559b5.npy +03261776-a501174de50bc9e675bdc2c2f4721bcd.npy +03001627-effb1b260f100f5919fb4103277a6b93.npy +02691156-8ef4637cb349584420c6a28228acb628.npy +02691156-562a94308f7bf09b8aa0062ef5480a6d.npy +03636649-19d4c28ca3da609a5beaf00da5b709c2.npy +02924116-6b8a93184bd984cc8b89799e9a2e578c.npy +02691156-66bdf712963b9a17efe0d4e1eba2e3af.npy +03001627-2abe8d5b5d29ff52f7628281ecb18112.npy +02691156-b74369cf3556cc822fa1bda037a5a7fa.npy +04530566-bb248dedd82b2f28deed0e4a55ad5dd6.npy +04379243-8cd343b3adf5118d7fa29a3ea424473.npy +03691459-acbcfec18a26c4583247f812f2eaa97.npy +03325088-382b1b947fba964dc1def5c6acc12bbc.npy +03001627-5edb33755a80aded3da27ece6ae88fff.npy +04379243-7eac5c3e4a8e4e086e5b9257c4084ca2.npy +03991062-1dcd1b5af8e876185894318693217d52.npy +04379243-788a2ae90158f42af4b6538438a0b930.npy +03001627-b6d43a52bc2eb8504d5af97121b5f.npy +03636649-bde9b62e181cd4694fb315ce917a9ec2.npy +03761084-eda35c1f6db60a9557b6140a0b345e1d.npy +03467517-bd1705d6d87fc81f6505b7589f976309.npy +03046257-a8b354178a8e4bc5a7e57b3c1c645a2a.npy +02958343-a4017ff2cc8b9150f4d6a46019767b57.npy +04090263-8588b43940114af7eab5ee569c9de1b1.npy +04530566-b093af9dabb14b70cfd826dd468a5497.npy +02691156-87348bdeb8bc74139ebd7d1067b13a.npy +04468005-fd47a012475b88815392bb73ff1a60c8.npy +04379243-7d04f5a75055273af9aec59741c69cf7.npy +02933112-643191e8ee56104e424f8f8e828c9ab9.npy +03211117-ccd6958947505b34f9f3c6290096f50f.npy +02828884-66670424b72dc0beefe2ffb03223403f.npy +03325088-1c684a5a113c4536b7a867e9b35a1295.npy +02933112-a4c79586ed938b5ecd81cf227afdf993.npy +03001627-f58ac8ac63d5a52d19fb4103277a6b93.npy +03761084-400d1bc76504769c1d5ccc40b510e4bd.npy +04379243-1f7ae7a902f453b39dd0cb4dfd5b80bc.npy +04099429-1a3ef9b0c9c8ae6244f315d1e2c21ef.npy +03790512-5e4fe8a57130744dece0b0a75f5fc9f6.npy +03001627-a7f911657d2ac259177faed93fef7451.npy +03211117-f6515d1343e25bab8913de0e5cfdcafb.npy +02942699-b92acfcd92408529d863a5ae2bdfd29.npy +04090263-76fb0e79e77923de9932cdadec1db39a.npy +03001627-c8420e434b1680edaf7c7ad2549a1b15.npy +02924116-b6c7700eb147491883b8b9c448a35518.npy +04256520-359e995834270ead614871b18a2b1957.npy +02818832-3d51b8ad6b622c75dd5c7f6e6acea5c1.npy +04256520-4e3f1e4f1fc88029d028c2e338a88f09.npy +03642806-18fdfff5acc4eb28e2720b34eb9e71b9.npy +04379243-f954f8a605974809dafcfea63f0b694f.npy +04379243-2e3e46e427b45207765ee729adbdf968.npy +04530566-8742b1778f2a6e7deb0cc8797c62d3c8.npy +04379243-dc537055864526217d970cb50eca3a9c.npy +04401088-2435be698167b2167120841458f79dbe.npy +04530566-9e4f7b6ed7936401af2bbb4162e3123.npy +04090263-2f9d017b565a274f2a1ecc02c3ced6bc.npy +02871439-ea2a60c496731ab087ef0846c4705cc1.npy +03797390-24b17537bce40695b3207096ecd79542.npy +03207941-21ee412299f40368df0c25a5c4f4cf31.npy +03948459-4c152610b23bc4db9a6e43b878d5b335.npy +04401088-dea7ce7ab01c08dfd4ea3f4c41b1b9bb.npy +02691156-ce12e8c1a5f5ce1df58f507a9f1e3e03.npy +04379243-370e911bb0313e0cdf76e252f60565c3.npy +02876657-5d6b5d1b135b8cf8b7886d94372e3c76.npy +02933112-663c290dd2e02f03e3f8b005c90fbce8.npy +03001627-40acea1827a81a774f7f6d1fb681883b.npy +03691459-21127c6f6f4a28fd4bbad62bb35c0a72.npy +03001627-a32febea4a0ac30171a782a4379556c7.npy +03001627-69735def3b0f009eb098f5649ee97d24.npy +02691156-4ec2aff45e8c495a667f1f26ed74631c.npy +03325088-2781a072e2645ccdedf1aa83ea962bc0.npy +04379243-97610f0edc786956d5cc62720ec8273c.npy +04004475-142a8e6cf56b63b2f31b18e68eb944af.npy +04379243-6ef3a3de6152b19be513a3136ebdf08f.npy +03211117-144ab629198c837eeeb8d422649e5f2b.npy +02958343-891b06955bdd04a7909e2381adbddb4b.npy +04530566-715699f07f8e59a1620e7892e762134.npy +03001627-e76f7d88022a0bf91b17743c18fb63dc.npy +02691156-d4ed7de4aa7799f066cf1b4a8fc3914e.npy +02871439-e1f316c10167d2a54dc4e0eac00a09cf.npy +04379243-5325e56ec7dcfdfb83130614d8020b3.npy +03325088-5940435f40a189a4b362845c6edb57fc.npy +04379243-db247fa7a6d2ae45aff7c08b060f5ed6.npy +04530566-4e3cd4d3b11584dda70cfb3232f40c6.npy +03636649-6b837caba2f63098360a9d5ff73ffdad.npy +03636649-b9a8cb27dbbcdb2a404a436d0f18c82a.npy +03691459-40f8addfc03b2b1e4d0c24eb0094dc21.npy +04401088-4a81237a7fc743763992b1138bb05b3c.npy +02871439-fabbfb00c3d698a8b022c94235bc8601.npy +04090263-de0bb836ad8b5a24fa9286f039319ff7.npy +02992529-98f0a229291ea982d670fbfea4c122db.npy +04379243-cfd0fa8a6d9ee06e6456cc507eb8f5c1.npy +04379243-8b0f94dde4b772d41ca25a4447d3477e.npy +03467517-3492e05bb96d5c8093f0194265a9746c.npy +04379243-37c76d4830a4968b719d8721fec72f0c.npy +03325088-d0c1d926a69a0d186d0157e3e7a8917c.npy +02933112-b261964d7c920a4cd8a45f471fe2ac0.npy +03710193-12839e81e67dfa88bc41bf82aa0f2714.npy +04530566-4b501c73f3cb02c63438e17bc657daf1.npy +02691156-bd91c1eca592312048464d2edba1bcf0.npy +03467517-8f4b1f242bc014b88fdda65f2c9bf85.npy +02691156-fe00bf68a2cd32b6dd455eb19d4d269e.npy +02958343-f8dc466677c26ac6f63ee8a34069b7c5.npy +04256520-8cba819b9a56da95b91b871e750ca615.npy +04460130-2af6c073f8b0ece92030f08aa0abc03e.npy +02691156-36a5bd4ca6a0b191532d23702363f9a5.npy +03001627-717e28c855c935c94d2d89cc1fd36fca.npy +04379243-d8c35b0ed66cfafa426c7177f78cd656.npy +02691156-6ce399fe42d54815e4406b3bf37e6ffe.npy +03001627-e1791ff04ab8348fdb63e6ea2fd66753.npy +02924116-b5fd5589a7e2b45a550f48125b5f584e.npy +03001627-18fd8342fa5d1d4f5268b70948af88b2.npy +03001627-40e6fb27aeb9c9ab44f999802029a79a.npy +03467517-2028861c76471591c64d0082475b0472.npy +04401088-d51e5d7eae216c9ef1cb19f636b1c2bd.npy +04256520-1d8716f741424998f29666f384be6c43.npy +03325088-1db4071178f5818250da8b99982a3057.npy +04256520-340daf71c78f53ac593ebeeedbff73b.npy +02958343-2254e63f695a1cccbbae182929bb7dd.npy +03001627-4acc9de888c0a73dca6910e4922d61aa.npy +04401088-57056c8f465dd1aec03bc4569d70377c.npy +03624134-4e0f2c48c02815e3f461fcc2f3999efc.npy +03928116-8edcb709ebd1d09e5f3d43a486973313.npy +04530566-b1a080228ad8a7c6eb2c303a0e0d287b.npy +02958343-998aaaf6624deca41548d161b5bc02.npy +03001627-aac5882aff90763affa93170c5cc3d58.npy +02942699-935fc76352a4d5fd72a90fe1ba02202a.npy +03593526-3c70ecd8d8c92f7b2ff65fa033da81db.npy +03636649-33b77c66e1f849b790c4e2a44fddf755.npy +02808440-816cad16553dbb004f2d909c705c7509.npy +04379243-868d86e47bcf7c9d1dd03d3141d85a03.npy +04530566-50ec883d9c1f715614edc3c9b2489f4.npy +02958343-a262c2044977b6eb52ab7aae4be20d81.npy +03001627-3b5364e2f1624ef992979c651b40698c.npy +03001627-d30e58a2361785683fb0851e9bc87551.npy +03691459-77c70fcd8ebcfbd4c83db093c68b1d7b.npy +03001627-c9f5c127b44d0538cb340854b82a069f.npy +03001627-1be0108997e6aba5349bb1cbbf9a4206.npy +03991062-6f4d7b8e06df314531b606c8e4dc32d4.npy +02691156-5e6c986605a2817ed4837a4534bf020b.npy +02691156-103c9e43cdf6501c62b600da24e0965.npy +04468005-1d4be24ba28946152470de2774d6099.npy +03211117-ff512c4ebd3f9e27f08984f51debc075.npy +02828884-2c6c50ead2551d51a0e159a720dabf7.npy +04379243-ef29c3dcc28f4e314785a5d3b6c47521.npy +04530566-43ff0403af233774a245ccf922912805.npy +04256520-227a9255c15c267aa5c25aecef10278f.npy +03928116-e6545f30f7bb6e2115426084cee9d242.npy +03211117-a990477e9c1bcaf4a70518e25ed617a7.npy +03001627-5b9ebc70e9a79b69c77d45d65dc3714.npy +02876657-2d1aa4e124c0dd5bf937e5c6aa3f9597.npy +03691459-792be08647d7e0fdd4221fb0ed444ec0.npy +03046257-b0251e1b5ca130eb50dfe5d3d82f3d77.npy +02808440-673e5bae900225783956bf2322987dd4.npy +04401088-933d5c217d9c01789daa2bf0c68f794f.npy +02924116-f9c9cb740629615426479a182158bae5.npy +03046257-b756ddadd752021b4a9073afd3cb57c.npy +02691156-4bae467a3dad502b90b1d6deb98feec6.npy +02924116-f2e8854ee4d0c7bdb55c3d293b3b9a94.npy +03001627-825bd436471f47457ef29b55d8edde64.npy +02691156-ff7c22a964a5a54e3bb4b8f3758b3c41.npy +02958343-e3b306ad8f7297817a81f08639c57244.npy +02691156-60b5f5da40e0dd33579f6385fdd4245b.npy +03001627-6189b30ed01f7bfa5692a9640d6947fc.npy +04379243-680a106cb0098e7fa71c812e027f94d9.npy +03001627-efc684ff4dc6ff49ccd42a2d6eea63ed.npy +04379243-7813370035ee02eee0c5923879d79f21.npy +04379243-809af89dca17068ea0ab1d82ef09f78f.npy +04379243-e921675e5dddf58b30477f27f55db318.npy +04379243-bce02d42bfab37b2f4f06a8cc0f0315.npy +03691459-fb86950be1b0ced7760a6b24be218cf3.npy +02691156-ea06bef342fbfd4236f3a2343a8221f2.npy +04090263-c92c0ddb2c729589b6dee66cb1bf8e00.npy +04379243-de205371514307babc2e0a60f47fe031.npy +04379243-981f5f50bd8821e8d935bb36a3b0560c.npy +04379243-5b2c4198bb1be0373704a45f4027ebcb.npy +02808440-b425065d760552afb362845c6edb57fc.npy +02958343-17bf28a8d9b5a7ccb5e3401710af905a.npy +04530566-6a43eb690d0157bddeadc9ca0263db5a.npy +03211117-3b188e87ba5f109e377cf79903309074.npy +04090263-42c6d1184ae147ce6e00f130b3bd101c.npy +02933112-3ba62bcd5394d5504c62bee40dcdc539.npy +02958343-900c32b154c0dced994a3466f8481f8a.npy +02691156-e50f001069380884b87697d3904b168b.npy +02876657-3d295fccf7d4e4dfd317c475f024f3b8.npy +02992529-338c3f116cd39022a40276c99b77cde3.npy +03207941-b66bf349bacc035437b2bb75885cfc44.npy +03948459-94d1e4013b9713ecb97b7b911836b479.npy +03001627-1c199ef7e43188887215a1e3ffbff428.npy +02933112-86d1c6a6a2278e7e1b17743c18fb63dc.npy +03691459-40511e6769c91cbcd3dbdb797d2f78b5.npy +02691156-c1260a89eee28413f2acf00738ce9d0d.npy +04090263-9ed0aa906ffae0c26bcd32c43682e841.npy +02958343-10fda5aa525f6232be8100817bfe3c8a.npy +02958343-a9876012922192273a8cad69dd295a56.npy +04379243-cdb13917ddd5fec6f712b42a5a217e5e.npy +02691156-40a828b10b1b092bd208f79049825a82.npy +04256520-7c8dfc67f9d03d02bddaa551be7f3f7d.npy +04256520-1c912a8597962f1514038d588fd1342f.npy +02691156-89f21747e6403735d9e1375411b582e.npy +03001627-77cf4ff8297014faa6fee8e2140acec9.npy +03624134-73dd7fb60dd52b85ed4efc1a1dc582cb.npy +02876657-27b9f07da9217c89ef026123226f5519.npy +02691156-f8fa93d7b17fe6126bded4fd00661977.npy +04090263-d47fb169bef4420bc4e8ec0d6d668411.npy +04090263-18e5827d2cfafd05d735fa1ab17311ec.npy +03761084-81e961930e6ee5fd843f813f752a5e35.npy +03001627-68fab23a050707213436bcb4a3bd19ad.npy +02958343-b5367bf3cb07b8ea593fee7ac9114e04.npy +03211117-4ee9c39b1f77a29a9d5e963395eec7e9.npy +04379243-86e6ef5ae3420e95963080fd7249126d.npy +04256520-5c54937316aaac98c563fcc2752ece39.npy +04379243-40b9f144ea6f35659928e3bfce70611d.npy +03001627-b1d4d7c5aa13b0642a3f8f484e6c5c4f.npy +02958343-72f6c3c3078ef567dfb1ee6a4b12bf8.npy +02946921-ace554442d7d530830612f5c0ef21eb8.npy +02691156-6f72a0d86494b551a834b9c8bfc8647a.npy +04256520-a0646924dec3b2c97348ac642586ce23.npy +03797390-6661c0b9b9b8450c4ee002d643e7b29e.npy +02828884-69ab287543b3a04a7e3b0132a2f87650.npy +04379243-5c6748b094725d9af008d8a3590fb522.npy +04379243-3279edef6a631940ea41b93204b74265.npy +02691156-66ae19841350ac2d4ba2821676102936.npy +04379243-f577193ba408f5eba71c812e027f94d9.npy +03325088-19fe41f0a0b6bee2979c556124bee033.npy +04090263-c4a5c40e5fcd1727a2bf3fdefce3fd4f.npy +04256520-90aa5fb0cac28bfbf91663a74ccd2338.npy +03046257-ea7d8d3f6b660e8f9f1a71e46bbde97c.npy +03642806-3dc60bce3e8d3ece3077dad41839c251.npy +03691459-3490844946e68402e47833b310955a9f.npy +02818832-d52149ba05e9efbfd54014b91baf8631.npy +04379243-1ea28bffca73c3d44b8710a3469971b1.npy +02958343-e4886a4d0c6ea960fe21694bd5f519d1.npy +04379243-b2aee339ca0dfe94de1b0b03ca051f02.npy +02691156-c58e9f5593a26f75e607cb6cb5eb37ba.npy +02828884-8d4693c04d684e61a3430e4fb40c91fe.npy +02958343-68b62b9b9d49f262b12ea83455b0f44.npy +03001627-ed948a3d2ece4b3b71a782a4379556c7.npy +03001627-7e5a6a86dc490f7e7288e3849fb636ff.npy +03790512-4a2f0b20ef680347395d58407f193ba.npy +03790512-f1693f82a326cb8afe11eeaa72c8aa36.npy +03001627-1f3336163f11015c1a7069a11c22548c.npy +03001627-3469b7f0709ed90ac681404257d94ad9.npy +04330267-9a5ece8646e88468877a6b14ac3aa8fd.npy +02691156-9c916b72d9f9f93b9f2700a6b7be99ac.npy +03001627-511c6fc6d3881b4ae43df8c9a38bf11b.npy +03593526-947cf0b19783a119154dddaf2978e13f.npy +02691156-96168894d7331c75acf77e718d93f3e1.npy +03001627-2a5abe261ad074f1c6fca4cd59d9149.npy +02871439-9cef7572697b44ede98e4da245e0b83.npy +03001627-19f597c6dbff03c114038d588fd1342f.npy +03593526-a317ac0956d4e885535deb3b0c692a2a.npy +04256520-b337556f36a5e1bb9a2041f674671d05.npy +02691156-fb68077d405c233ef879f4163a3ec7b.npy +03001627-1d1b37ce6d72d7855096c0dd2594842a.npy +04379243-b1a1d78a2736dc2755f46d55537192b6.npy +04379243-33b9bc49338800e87dd2ad68f72eb830.npy +04256520-c9241b6f755e7134f564f8e3eeb8449e.npy +04256520-b6cbabb92f1d0965de85c11d95003a6a.npy +02808440-3ffffa5a05b2254d4ee769ccec97aa83.npy +03046257-4af34d709f39ab8e76460fd7f97d7f44.npy +04379243-e69dd1a9bbeb62523002761e7a3ba3bd.npy +02958343-e20b8a9c388eeb012c8b6ee41d7d5d62.npy +02958343-2961e679a651dd5ad95ed6bb7181c98f.npy +04468005-d985e5c98e8a97989954eae9164faecb.npy +04379243-acbc99e153b9d4d419fb4103277a6b93.npy +02691156-c1b5dc92221bcdad5fc84bf2b9ef981.npy +03001627-3d390c6f1051295d9501f2fa226917d0.npy +04530566-6c687a500aff678ad83f267e8f0b536.npy +04379243-4d3cc502d4444c848cbb8bac2032149c.npy +04530566-98a9c16aa2c6030f7d962e3e9892f8dc.npy +03001627-179b88264e7f96468b442b160bcfb7fd.npy +03001627-c5958d1f079b0be47b8e25a5db8c2573.npy +02691156-19e2864af4f6de438050e8e370967931.npy +04379243-61cb695902f7905e7afed106527393f6.npy +03636649-6af800e7bbdc5f21735ea0e092a805a.npy +02933112-e16c0191973a25f02d63c890dc92b5.npy +02691156-e3de366a0cfb59ed38294c37c250d7cd.npy +04379243-e08d1cd0dc7dc73db9d7c2fc41e80228.npy +04090263-cd6cbd60e8f7cbcbe378cd9d51dc5be0.npy +02691156-bf93f4dc64eff22b4d4cb1c2a5e48b7a.npy +03467517-b35e8f73d68885059e25703eed62525b.npy +04379243-b0d7e13b20b190afaf1a814fb0f45a9.npy +03001627-9281f52d6c5908987ca6caab209ed3be.npy +04530566-99b36b2d2174f061ff8f632f1c753803.npy +02933112-9a2c9e5bda713668674056261e8e6523.npy +04401088-2fe4f1ea84cf924ea4d4dcdfc6fd3059.npy +03001627-4566839a362c5c223ec13b32c4d64f06.npy +02828884-10a66ce0a6b469d3b2cb19fcedc32ddd.npy +03001627-1d7fdf837564523dc89a28b5e6678e0.npy +02958343-ce63abf6d78ea5bf4f39b2731f699e34.npy +02958343-b8cee2711b84bebb425b2c354eccabaf.npy +04256520-ba5cc31429d4c97479c67f086ffdd34.npy +03513137-d25312c53aa9ded3b57cb9238c4c8e81.npy +02808440-259a1fec7969d3e3501f3c19b1676682.npy +02691156-52ef4ccb24accbb295673ce3194af95e.npy +02876657-ab6792cddc7c4c83afbf338b16b43f53.npy +03001627-ec9f1fc13f2e4ae2c3bd24f986301745.npy +03211117-a6fe1a137c076e51d404da78b2c36d5d.npy +04468005-d76e81f2dfc3ad9162c75ca00b8927f2.npy +03790512-e792c49e0e4b2872d83cd5d7c4553c91.npy +02691156-8c6ab402ad29ff5c3b9dffcb3e0245d9.npy +02691156-47e48c70040beb9c8db97d9bc169245.npy +04379243-41264bc3d705a6c1cea003eff0268278.npy +03001627-8f226d6b3089d3b7bca860dd9b04c52c.npy +02828884-e31212e9f9f5888effd5817f210f277d.npy +02924116-eb5b4205ad06d6a17dca29b91e24dff2.npy +02691156-b481294a2692419cba5f6626ebfdf87f.npy +04379243-1a9bb6a5cf448d75e6fd255f2d77a585.npy +04379243-328e8b5e3419c66c493f7199d76f57a.npy +02808440-450fa1bb2cc0ee578c0a569dc2eaa6c1.npy +04090263-8872698c6eae3a8ffb8c26d5226415eb.npy +04530566-34b77143d6313e3f717ad2ef4c4af2e5.npy +02958343-2faff2861e87020a4d9558e8f1b57178.npy +03636649-e15960ae59486c464ccb9dd377d00737.npy +03001627-2276d36a40335c19215045784774049.npy +02946921-fcd14e7ad72bfa70471c65fdb52b88b2.npy +03207941-77ddd857eb3c1460121859336e292a5d.npy +03001627-5af36cc3a98642019fb4103277a6b93.npy +04401088-467ab7ee9487525b13e4f8e4c4578272.npy +04401088-61424998613d67b75ef3453134070b3.npy +02691156-b3066d613364710797020a1f4453e3a4.npy +02958343-85d04dc3f455bc56ceb5044e1e1e9739.npy +02992529-bf259988d2e8728c391790b8b8084f0a.npy +04256520-c53ec0141303c1eb4508add1163b4513.npy +03513137-57ffd28975abba38480514d7f2edc0a3.npy +03001627-557542994c02cffce83221ad0d21775.npy +03642806-b14ceb94c7930ee55054cc2bc9eccddf.npy +03636649-9b7d490678f2c9db3d2be70e06ed6b30.npy +04530566-49075ee8db9d66538d1140748efc85ed.npy +04379243-40b55c0578228337f521e1d72c94993.npy +02924116-1ca19240b42fd2f049d40c74f2720fb1.npy +04530566-d3de6c76e6d96f7fc5fc3eafa9cdfb3f.npy +03467517-6ad792f9321dfb82aa0c867d5b070a5d.npy +02691156-d64caea6c332861bcc14f1e6f4f4f49b.npy +03001627-6e21df8cb8db3819899718fd4553951.npy +03593526-4d392c12240cfe352150a45ec52bcbd7.npy +03001627-a919152f07e9e0d0fdef1c01cbd4ae0c.npy +04379243-c083552372e71f9c7ee217c21e683487.npy +04090263-2b44f7b45ac72b24683e3750b53385d5.npy +03001627-7e097351b98060b8a8dad913bb47fe00.npy +03001627-3ae2857e04641093b0957d845ac33749.npy +04401088-6b9cd9c72e69fb81d8630b8390e34e0d.npy +03636649-f530508e27911aadabd4ed5db7667131.npy +03001627-4f467dcef4a710a5911016bc0ad99a16.npy +03636649-b8350fcf08ff0b2ca950bf8f33cff658.npy +03636649-d378c508566d68cb48d2aef7552b65e3.npy +03325088-83c9c0a13e3bb6c76c18e71fd49c4dc.npy +03691459-18abbf4da8320e69438aef443c33bffd.npy +02691156-32a547e29d66132110b2a26d47842033.npy +04379243-28912046d42946df7db48c721db3fba4.npy +02691156-ded529516b4362c9f019a51d1a3b2e07.npy +02933112-7a9feaea9793b570fc9d1bd1b5b90d13.npy +03593526-79a582343eece9c645c7a8e7c70da8b1.npy +04530566-f7f62b9657aecbe77f00b68989ad3ebc.npy +04256520-9a1b39f920863964b3c42e318f3affc.npy +03636649-aa5ebe13f6d51761d197f67767b32741.npy +04256520-dbbf72729fafaf3737f67f4322e8d3d0.npy +04379243-d7da105cbde6ad8ad027f5769c5504b9.npy +04090263-509f0edd2fd65d5e213f0776ba8707b3.npy +02958343-3a48188e012364f8921cb81cb1632a5e.npy +03001627-74c06950e3f8d25157f40ff86fe708ff.npy +03001627-2592e69aaa2344292463e74275a0e3c.npy +03001627-cc1b4eb1a9164e04f06885bd08de3f64.npy +04379243-9e99421220d92f1da8699b6183baa203.npy +04379243-f00992135ebf50a9339797c21e8801b1.npy +03691459-c3733b26c3fa23ce2633ff66beb9cf31.npy +04530566-1a2b1863733c2ca65e26ee427f1e5a4c.npy +03001627-98e1936d3f25389bc3c6a889ee0bd115.npy +02992529-8da5c29d14a1003d23247d005da93d43.npy +03593526-ffc7e98720e71017b3878cedd8c8fe6c.npy +04530566-9ac6483c969f1120b05dfc874f00d5f3.npy +02958343-99c2ddb7e6169412cb9ff477a2867fc.npy +04379243-765d6e5ebce3fe25aa11adad6b2a69c.npy +02924116-a3601225009a1f63481aa8b5531c68a9.npy +02691156-4ad92be763c2ded8fca1f1143bb6bc17.npy +03001627-7aabc57856fc6659597976c675750537.npy +04379243-fcc5717aca6a3be188bda5f1df0be8.npy +02958343-1f167c74bca9ec83622a8f038ee88042.npy +04256520-8ed3fa69c808741a42e1bb4fe264125f.npy +04379243-c68407d2f752ae71ab2bcc3443271151.npy +02958343-3ea2b72ba08a2e8097df6383472cc5b6.npy +02933112-be4c2bb409fb8374b5f72e2923ab992.npy +04090263-6aaca4e199c1f84f1087ca95a9795303.npy +04004475-4c7a10fb9bf4905d983ec12a2b33f18b.npy +02828884-48f517497df57a2c2056b4bd5d870b47.npy +04379243-940dc92bda153346eaf14273fa406ffc.npy +04256520-de4e483a1587da9fdb24ee630144f57f.npy +04379243-83e669596e491dfe20070923ea969bd1.npy +04379243-35f7655867f9223d82db9fca4b68095.npy +02958343-83098846c82db490a00a2bd11cd80551.npy +02871439-b7b5978bbb72747f9a2615537bdd5695.npy +04379243-2fe5bbb0df6925d1f12d7184a2ad3430.npy +04379243-1db1bfaa8eca186e9295484d295fcc9.npy +03001627-2de10784fa2655d6ad01ec966c80ac91.npy +04530566-573c69987f0508d210572d5e96d039f0.npy +02958343-4a423ae9a28afe3588cf40718544e7cc.npy +03001627-4f24a67f85e71e144719088c8e42c6ab.npy +04256520-55e0dfba8cc226871b17743c18fb63dc.npy +02747177-af7a781f08fdd4481faebbdea6bd9be.npy +02924116-8df1feb988e51609db7aa9f86faf9bd0.npy +02691156-802cbaaf1a51cf38c863ab010b80d9ed.npy +04379243-fe0a8440aef8f597a6656391f7752a4d.npy +04090263-c42ca534ab455a778625e5523ac2ce12.npy +02992529-2c03ac9bbb3d918411f02c4c36ed7f25.npy +03211117-19a4584a4d29778a78585e33b915d9a5.npy +02691156-f24daae76836e249f0878b58b4e887bf.npy +04530566-cf254a334ba1af0aaf96425967f2d458.npy +03001627-516c4adba7205cb43e9bdff70754d92c.npy +02691156-48c4e5e2c2dfccc7a68efacd2d601104.npy +03636649-4aee1567027d9dd14357a62465045ec4.npy +04379243-bdb5a2a25223d1b645613f5c2df1029a.npy +02691156-69d7ae2143c2a2709c6df67fce5fa25a.npy +02946921-788094fbf1a523f768104c9df46104ca.npy +03001627-18e5d3054fba58bf6e30a0dcfb43d654.npy +04256520-1670f9ce4de8a548d08f8c5dee475682.npy +03928116-c554d50fe22d9fc57e8f7075286950f9.npy +02958343-f044724a6fb07ec73b294ac02412e874.npy +04379243-1671665cd0e2ce05660aaee3010d2fe2.npy +04256520-ca6a71e5ad6e8964ad33b69f9597739.npy +03467517-4b0c7381c4f2c5bacc34b900bb2492e.npy +02958343-a4d535e1b1d3c153ff23af07d9064736.npy +03001627-70a2b281cd8d59a52d19175e7d19b7cb.npy +02933112-3106e06eb594238c59350d819542ec7.npy +02828884-2731687dd460a263d8eae9bce48bbeed.npy +03001627-632bc741220bd52e51c4deb11af7079e.npy +03001627-d528a94f72c994f3e8e5fd5b1798c97.npy +03636649-69762de7892483b64fa8d6439169bda4.npy +04401088-b490aed1d7d9a42ec4e2c9b051d6a014.npy +04530566-6367d10f3cb043e1cdcba7385a96c2c8.npy +03001627-66a36dfe1cfd2d17b40f0ac0fb9a650d.npy +02691156-61fe19a62a786c96950d2b3eef73a70e.npy +02958343-491653e537f1a701697b84068abf146c.npy +03797390-8aed972ea2b4a9019c3814eae0b8d399.npy +02958343-e337e9940356e866b82298c7ee2fcc7.npy +02958343-5389c96e84e9e0582b1e8dc2f1faa8cb.npy +04468005-5dd69dea0b94b9abb216fb38ac0eb009.npy +04379243-726ffd1d94bf5c0558df8eeaf3dad1c.npy +03636649-50f14b490f3f4589f51f77a6d7299806.npy +04379243-fc9910fa6262cd4e1125c64abbb51ddf.npy +04090263-791efe6841d0995a1d9b004d9d8d2781.npy +04468005-40fcd2ccc96b3fbd041917556492646.npy +03001627-c043285da4600e168a5e49d8f4867e8f.npy +04090263-3238588ed960920c400c7ace1cfd742a.npy +03691459-b8b54d43aabf84a67aec59a4d1722658.npy +03325088-7ade4c8d7724e56b76d20e73c57c9a03.npy +04401088-d050f7389538de04ae0591d02e40f07b.npy +03046257-b750e23ba662cb4fe0865a0bf86de287.npy +03001627-9b8f69874b502bc2742728b30848ed03.npy +04379243-ffe4383cff6d000a3628187d1bb97b92.npy +03636649-b2ed0a4a8caa5139295966c2452536a6.npy +03046257-a1a8a811f5260ae675aa7f24a9b6003a.npy +03001627-9e19e66686ed019f811a574d57de824a.npy +03636649-e9f83f1d54e959bd35836c728d324152.npy +04090263-f8a772a405e76adcf02ee453ff283e26.npy +04379243-8c0999396ba60e758738e7290b6f3237.npy +02958343-7f0f750d6ca959b6ac5eab1f4e9b0f1a.npy +02958343-ac85727971fe63dd2c67ef33d7521ade.npy +03691459-b8410a2c19a50aa88b04a17db360913.npy +02958343-4dad98955a47e81a8b3877a62f2cbe1d.npy +04379243-e8599df1d0465e3811f3906fc1b00350.npy +04554684-6bb2e6f20f189167d48855885373053b.npy +03001627-d2a48ffb6d25f88dfb0eb7e753c06942.npy +03467517-71139bd2ff6c4257280ec2e5049bb369.npy +04256520-8ce7a3ce304220257c071b4859b99983.npy +04379243-98feac40e78b92bda1fe796dee2910f3.npy +02924116-1b8d1c5d1b463a23193d7855ecfc1bd3.npy +03001627-dae8b3ac69d80cf1b94e60a139ac4b1c.npy +03636649-a8d6e75a7d2712f3fcb8d8c6d4df8143.npy +02691156-3e4b522e38ef9a781b5928ecfc4b0684.npy +02691156-4204361e3781952a8e951223a21e1fc1.npy +03046257-78b20642a66f421630cd51d117004d92.npy +03001627-3421ad5a45b85f7a4b3c42e318f3affc.npy +04401088-27f7ab052f3fce42b35f223cefd97829.npy +04379243-48baef3ab18d2d43d2afe8d5254a0d04.npy +02691156-5f6b6f649b419cea71f4784575c35350.npy +02691156-8fe406a829c40c933b353a5057e248f5.npy +03046257-c422e03b825d5e0046043f7519b6b4c7.npy +03467517-6a2e66511506a517a716de2121565fe.npy +04256520-c29c56fe616c0986e7e684d25d4dcaf0.npy +02691156-5454ef3f1e0367f38f92ff0dbc52d7eb.npy +04256520-1908750cd67208e0c4f370f57df9b202.npy +03642806-11654b536fd6ed67616b0fada7303ece.npy +02992529-16ac60220ed738901cfeae953cc2339d.npy +04379243-2563d1fd68ae9d77ac803318d4b3b4b2.npy +03790512-74a3df7e06713f4a48272812609617e2.npy +04256520-304db04f545f53b021bdbc0445d9f748.npy +02828884-bbdc34eb50c32ff7c6e70747a64ccaed.npy +02958343-7240a21ee34bef83dd141480e2c154d3.npy +04379243-d256323d2b756b9e76bc197b3a3ffc0.npy +04090263-8bf221c8f17b152b2607a47034bf62a6.npy +04090263-4faa63f17be98cbf1389e18ca61056d3.npy +02958343-d9e58ec3ad748aae2051f6248df99d19.npy +04379243-d94de64641651a2079b3e1be3524f72f.npy +03001627-d324baae6630d7c8fb60456da917147.npy +04530566-37ea55e2d023f9ae9588e71e21de9f30.npy +02691156-32fb1aca48b3a0d197eae247c9b1df47.npy +04379243-fcd4d0e1777f4841dcfcef693e7ec696.npy +02958343-cd67376cac9f989151008e496c6cfd2e.npy +04330267-f490138e211ad6e9c3c11bfa5a6c7ac9.npy +02958343-c6b98edfbb65320654b49557f8ea8b42.npy +03211117-be89d32290b9dd4aba27b59766aaedd9.npy +03337140-474fb0ff79e036b0820018801b237b3d.npy +02828884-639dd737961f1806985ef0bf52b97bf5.npy +03001627-d015bbb45833955537b2bb75885cfc44.npy +03691459-7317a113f9999e28824aa039bc530c36.npy +03797390-15bd6225c209a8e3654b0ce7754570c8.npy +02808440-1acfdd86f8d48bb19750530d0552b23.npy +03001627-834fe65aac9ea9bce589b08489d157d.npy +02958343-56b6c950f4c5de80ce27281f3b76d1f5.npy +04379243-3dafd09d21c9ca607d55378e40c7c3d9.npy +03691459-3575177296452c98f149a4641e0b7067.npy +02691156-efbf3d4c8877e7dc7ce8c809505eca2f.npy +02924116-f4e25d681ad736eb52470de2774d6099.npy +02876657-44dae93d7b7701e1eb986aac871fa4e5.npy +02958343-3c1ecfc2dc88c1919214bcda3ade39f4.npy +04379243-6571fbfba919ac76eca66eeb3eb4982e.npy +03211117-f3ab112671b02010be54ae8147665701.npy +03337140-84e7061f807f8f7e91c352d02061b3f7.npy +03467517-5e452914684ea7fc398707f20de9db08.npy +04379243-11f1101ba2e29206cc963bba1556032a.npy +02828884-9897a75c64a369d458c73770090b865.npy +04379243-49dfb00ce7ed1602b05fbbe21a0097ea.npy +04256520-983f0b9bf020010159f8e31ca87c470e.npy +03691459-3e21834bd08c078963de47aaa413f122.npy +02818832-9249fe17635540b594ad6c58a4781766.npy +04530566-849c8b9c0acc91b6ed4404549c4013f5.npy +03636649-d73b4313372ca6e1a6a7b6e78d8d5bcb.npy +02828884-e01c283efd6a0d2120d53ceb96ec7d24.npy +02958343-2ba7ea78b9b6e2a6b420256a03f575c0.npy +04530566-9e653d3b0b8f8c6b28f998b2aa4c5983.npy +04379243-c3134ae6fd6691d7db039d8689a74349.npy +04379243-e6bc7735ed67822e60a09749bdad79a6.npy +03001627-3276361e9e651238ac4ed5495364a497.npy +03761084-87bae84777fe8b702bac1bcdfc2402d2.npy +03636649-d6db6a800c1ac87bcd783766d090e665.npy +04379243-e36e90c1db6bf1d5470412e9b69c8933.npy +03691459-c7d423c4d63ae4dfa5bf0df4639be0b0.npy +02808440-62f4114f43f07786b362845c6edb57fc.npy +03001627-badfcd24d9b640fdf74aae127b28c047.npy +04090263-99001b28e4fc6bdcfa9984f75a870c1c.npy +03759954-5889d83902a9c2c478a2ccf0e4d84b2.npy +03001627-9f8708db66a4ff07f4b6538438a0b930.npy +03624134-171c19d5205fb3291fc43d5b32fa230f.npy +02958343-1166b049a7230db9f50f5d46dfed0533.npy +02843684-45c547298f85241b959ad2f80f4dbcca.npy +03001627-cbaca6a6edfa2d512b520984c067934c.npy +02828884-ba58fdaae9a5520b421b60451f2f74f3.npy +02992529-68b80d0086322ea33615136d92a66ba2.npy +03001627-7b5b032a2cddeebc54d7082b34825ef0.npy +03467517-ef1c22bd3b74953689f0379846507dd3.npy +02828884-5d88fc00adb325e6f3a134eb65b35f7a.npy +04074963-7852a457e59fd546d26c2593d1870bdb.npy +03046257-5e10ee8a39ff0e519f1a71e46bbde97c.npy +02691156-136c2b868c5326dbba5db366aa3ac475.npy +02871439-1d3014ad5c35944f9af68b4b3261e1f8.npy +03761084-4ab6c77bf27d4c86b8776ad71dcaa161.npy +04379243-a145bba4e4409bcac905813b9803ef0d.npy +03624134-b8fe56eeed3951392f98be9d5bb04d17.npy +04379243-614f1c6f5e0d2372ef5f18853edea926.npy +02933112-975884e7d9cb74ff39974e6e2bbe1adb.npy +04256520-8c69c0bafdf91e85c05575120a46cd3b.npy +02933112-9b34b5983bd64409e08dea88cca8641e.npy +03001627-e3b625f979f3a32fb591e8fb800990fa.npy +03642806-7df09674bc991904c78df40cf2e9097a.npy +02958343-7c72e179b251171d4d1780ed2b3fe073.npy +02880940-b195dbe537993945e4e346ee2650d150.npy +04256520-a409a2548e7cdac7febad4f49b26ec52.npy +03624134-c1ab7029de67351cf97a65c35ea619f0.npy +03467517-d685415d4fcd3205a24eeca91f583600.npy +04401088-c3c5fd4ce226ab0c4694b8455e89054.npy +04379243-ac965c2d5c68551be6c5cd45aa112726.npy +03636649-a5423069e30181a019655a581ade300e.npy +04379243-2cdbe6c91dbe4fbabc7589eefbdbc3c5.npy +02691156-d0ab3ed71a4ac9319d1eb836604648db.npy +04530566-feaf5c41e664348220dfe072b77502f8.npy +04256520-75f69b9fc22c4c04eaf288f952624966.npy +04379243-7dfa5642ccc2b8fe5e2a5c16927ff414.npy +04256520-4264fffd38596e3a60f888b4e2fd3e4.npy +04530566-ac5dad64a080899bba2dc6b0ec935a93.npy +02958343-906e2e532b7156b612be63c74304797c.npy +03001627-323f0787810ef9a285a030bdc6cb9884.npy +02958343-ee975a7e62edc7996a2345809e2bb169.npy +02871439-b6264b92d0cbd598d5919aa833abb5a.npy +04256520-c88d26d20803d385e8f8c11a24c52ebb.npy +02871439-f6c0d095a49f5880fe1a61f05bc63860.npy +04530566-e3206eef4da407e7c08fee43ebed0bfa.npy +03046257-c74cef5d18061c5b5dc7f4502a6f8c8f.npy +04379243-eff2f84104e78435d6f4cef762589739.npy +04379243-bfab799cd63b345e232dbd6edd2fe625.npy +02828884-338fc00ee5b182181faebbdea6bd9be.npy +04090263-75008b972144b426b8eced526ddc241c.npy +03001627-18f2f833d95ad137111c729c2fe5f751.npy +03797390-645b0e2ef3b95979204df312eabf367f.npy +02828884-a1276733811a864b99cb1d062b75ee73.npy +04256520-c5380b779c689a919201f2703b45dd7.npy +03001627-c0689f191df5cfe1c785f06f424b9d06.npy +02958343-23bfcd49917919006a34aa94ca8a3355.npy +04379243-aea8be27a9e5dcec1158f00955d38a.npy +03001627-331ddb6fd9c333456cbf78e1e89022.npy +02818832-ac97ffc6b6ef238382c3b56998e08a4c.npy +02924116-60c830af5fed1ca5193d7855ecfc1bd3.npy +04379243-c2a33328b7df204e1754bd6e58ab2748.npy +03991062-3f7d866f4e28e8014b3c42e318f3affc.npy +03001627-4300fb717f89c832d42ec7e303174a87.npy +04554684-5f8991a5039ca4385c8adc541f88498.npy +04401088-71240556952395e0925bda4660525f97.npy +04256520-23e7767edf2f861e58c75a3520cc91a3.npy +02828884-9663627be99d2e27d2b12aa6a0f050b3.npy +02828884-fd2394a5f4d05d4c331bc7630c8705e8.npy +03948459-2137b954f778282ac24d00518a3dd6ec.npy +02828884-f3db005b33b9f8916cd47ea628d8cef0.npy +04379243-c86d75f3408c7ab5a6b3538efbf4faad.npy +04379243-b52f6dd58875030ead5067eac75a07f7.npy +04379243-51149acaab6049d05938488ff499d96a.npy +04401088-dca3f5a8ab0b850c8c8e7e9e3310fb01.npy +03691459-f0d27525fa81798d982acd4b5c0a58b0.npy +03593526-ed3c75975804636e34a8988fdcee4fde.npy +03001627-f9c4baf01dbe6c488616812464c86290.npy +02691156-256626ea73837e032625b83fa7422e2b.npy +04256520-b64277db98afae7f8efae927921987d4.npy +03691459-2dc57057c96ae0f74c24a2a9e289662d.npy +02992529-ef2b505068cf120efe48f52a0ccc160d.npy +03593526-3304e9400b2d610a69eaff4d4a8a103.npy +04379243-cced836d07325938f51f77a6d7299806.npy +04090263-511dbae3805dad80ab5938f464bbb85a.npy +03636649-f673fc77f397a061d49b2e04785f8492.npy +04379243-bcdf93ab467bd7d84fb315ce917a9ec2.npy +04530566-4f8e847d3453f2f17301f2b895d332ac.npy +02828884-7e8caf5bf2eb1a61ecaa3c66b0328b42.npy +04379243-2ef28aca6afaff1d88863f114bcd9f80.npy +02871439-ec882f5717b0f405b2bf4f773fe0e622.npy +03790512-22ae98e613bb8e188249f134aca4c817.npy +04530566-ec8d021a7d3816f2e46fe97e5f3e2c98.npy +02691156-571cfb1da3d5b3704b5910188444efc8.npy +04379243-9c12fada31224bdf58c4e7e56d799d97.npy +04379243-31c090b23f52bb61208c8c852ee795bc.npy +02958343-21a1f2a7b7e671826405999d829064fa.npy +02933112-9b1175f3e0b7f0938ab7e957399ebbf0.npy +03337140-a5626b08c059654b4c3aee8e9d3a6ffa.npy +03636649-f567bc1dd416ebc9dcf2183c858e6e5.npy +02880940-5bb12905529c85359d3d767e1bc88d65.npy +03790512-1e664c94e932ece9883158c0007ed9ba.npy +03001627-c24b79602fccaf603379c738ca193530.npy +03636649-a48ee5668d042342eef5d83b671bb264.npy +04530566-20286f6d7aa7a853b48c6de5e38e3312.npy +03691459-aee6f0ef9f8a7c13b54cfe6aa07c2036.npy +04379243-460a915796f36eaa55f86bb3ad320a33.npy +04090263-e53badb78702d54e15b3bff1113c0f8.npy +04090263-568728cb599dc18880c2e60c312b0f09.npy +03001627-9eecb9726ab34ae0492d9da2668ec34c.npy +03948459-6fafe3b82e6e07de460c5cf20e4c5e41.npy +02691156-640c9b76fd75aa94d13ef00338ba8c52.npy +03001627-9a83000e9128d677b04cb542e2c50eb4.npy +02691156-49aa625393dbd1a4d443895deb2f03aa.npy +03593526-bcf5a4b764ddeac759f9892433e1b1f4.npy +04379243-a927b0088531dec823500a5b036df62e.npy +03759954-fa06eacff134fbcd59a6208793b9dfca.npy +02818832-75b74fce7335d1122c1fb51c278f01a4.npy +02828884-24eac2668c9f241fd2b12aa6a0f050b3.npy +03691459-2edb8ba1a031b3f5ce029fab54b6cfbd.npy +04256520-f144cda19f9457fef9b7ca92584b5271.npy +04379243-9e3586331eca79e48a5e3400c9c8f4e3.npy +03211117-bdde8a0134ad5283340f0692b6ac89e8.npy +04379243-f46fe188be699e5c593ebeeedbff73b.npy +02828884-2cd9593e8b7f0560d41e37baed87521d.npy +02828884-3eba7b7b2b1d139956f6fc4b4ce1db04.npy +02691156-b46455f82ad28fb595ff232cd38210b4.npy +04379243-eee08384e4f5c338a6ff78107fd2d715.npy +02958343-448efa9c287dac40a1523482d6af89d8.npy +02958343-4d24f5e0f3f394c030e91498c0369393.npy +03636649-5ffcd5bc4f1548181c7f081cf615f39b.npy +02691156-59f258b7aa7c1f7aa7d0c1e4eb8db7dc.npy +04379243-8b319bad7b3ff1b2ea60ed8d67a889c.npy +02933112-a268283b0fab6092eb835f4eccb92a70.npy +02876657-39d4723b8ac197d4dcc91b6bf08a2274.npy +02818832-d934090d6e0be2746121178eafd002fd.npy +02871439-34d5923ee8b8a6333bb4a1304fe504d3.npy +03211117-2049436c2457a4203087f84b199fd297.npy +02958343-4ceeed48d1a48d4ce09e4fc69d1a2697.npy +03593526-3e82203bf2cf0c81e6597d391ab6fcc1.npy +04379243-580e48297791fb394e684eb336479e2c.npy +03325088-f76ee8c9af6323bdb362845c6edb57fc.npy +04256520-e1662c8dfabda9e76eb9b08c8a74d159.npy +02691156-ed50758d8792491314777db9411e4949.npy +03001627-2bb65d6612027f18591999955e20a6d0.npy +04401088-cd1739ec8797049072f1ebe52d9b9daa.npy +02691156-aecd996b2ec3832771d03b466c72ce41.npy +04554684-8340c44f09408180d122457e1745c167.npy +04090263-8cab7fcd543a1d0a74e18e0e7a19212a.npy +02958343-f73858d58e6371f7d76439fb95cdd2ed.npy +04530566-2d702653fd65092cd3ac8c766eb7aca3.npy +04379243-6bc7148a5138aa6765eacc25f128a1c5.npy +02691156-aa70737ddaede2e3368d7e7849f8df62.npy +04379243-18e73a715023714691829b477862aff6.npy +04090263-94a7069ee4d637de40aa5b072f9ee3d1.npy +03467517-8cc7d40d73be99c9d57700c05b1862d8.npy +02828884-28ccec6ab49631e4e0f41fcfea9716c3.npy +02958343-e625eb804f2fb6caa26598ab726b7540.npy +03593526-e57f67c2da68cf1d6bc258c0f0234be0.npy +04256520-e4e0f428fcaa01bd19fb4103277a6b93.npy +03001627-e6e00a7324357c7dbec105fec16416d7.npy +02828884-5cb02fdcd0f1cf5d3d06403e6871e4f.npy +04379243-9bdb8268baafde1f44c642950fb4550a.npy +03046257-182760a92182873b4cbbb913355f84cf.npy +04379243-40ad41340725a2477251178be84deb2e.npy +03001627-e1e2a1aa3a6cc913eab1a145ba6f6383.npy +03001627-2b2510922e763c2443b0708c694aaf46.npy +04468005-65507a0e35c02ed24e971947186deba4.npy +04379243-33a3aaf17cb7d0ea351aa299020a0e0c.npy +03001627-6cbed10088dfb841e2a5f8edb044130e.npy +04379243-91d47945645a1039eaf14273fa406ffc.npy +04256520-c73d63f9080e84a91b17743c18fb63dc.npy +02958343-732ed918e2bca89ae6e1c83427eed339.npy +03001627-e4602d2f261da4a314b029b11f36ab2d.npy +03691459-29faf5a7c444df58a1fabddca717cbad.npy +02691156-fc6decc887f6d8a0bbf3143b1cb6076a.npy +03001627-22af872ac796ed26ff8d7c1096fae070.npy +02808440-352453edb5b6f8b4a485efa4c77b16eb.npy +04530566-6cae5a0551aca4fdb39afb07adb2a544.npy +03691459-b16d2f432bb57fc76dd78e11c421d52c.npy +04256520-f2bfa61e1a8894dd1071797a42296ada.npy +02828884-6512b58401c7ea51ad5067eac75a07f7.npy +03001627-f515332dbceba51120768660cf080d12.npy +03001627-8a38d65b4909e79d727e9f790cd597.npy +02691156-7edc7e17171b488bd33efe8cc2e2bf98.npy +03513137-2a6f4a2ff5e11b264dead5f22c05efdf.npy +03691459-b044555289c7439f4c40f34de8f3bdb8.npy +02958343-33395dcb83b43eee21e570d3da54bf9d.npy +03211117-c28d66941e2005cd11ea7f12f22c0e84.npy +03046257-181d994ce6c150df9cd779a86f74ad9d.npy +04530566-54ad30894e9c74f28abdeb0a990504a.npy +03211117-956f4464a0c344d621c6aa624f82ef1.npy +02691156-f04b62deb7737c86d37636af9c7bcc34.npy +04256520-1d878962087fbab2350c104b3ba8ddb.npy +04379243-f06857189fae823f35836c728d324152.npy +04379243-cbc2d0b1d7a64ffd2ce1f2e292dc9c31.npy +02828884-b380b855aca5632dad5067eac75a07f7.npy +04379243-f6b3638983b0effaf3bf08ec218707d.npy +03636649-1eca42abff644eee57a48b78ff77644d.npy +02958343-6201a29763c2256a2bb5796f842ca661.npy +03691459-3db832895812dd37230584014222e685.npy +02992529-6753572868705eacdd043998582f5fa.npy +04530566-84b75e53176c9f1fe1e2f026632da15.npy +03001627-48d44532ffcdd4a2fc30bf6907b3dbb9.npy +03001627-314f567d460a88c7ad02e4a3aca566f.npy +02992529-980cefc1df9b24458b13932a0c28e98b.npy +04379243-5a5d896489318c0279c251b4a7838829.npy +04090263-55bc5e1223f4868646862032be5afc61.npy +03001627-4199756380f14898e8f8c11a24c52ebb.npy +04379243-f86c1da9ed243ff055f46d55537192b6.npy +03211117-840dfd5a8a5ad3f31db54d45f574231f.npy +03001627-e67d503940c1d95b73e5f839658fc536.npy +03001627-a95df2063ec98e429e6aed0cfb3be6d6.npy +02958343-3a3f3ee1eb027cdca413908c0e169330.npy +04090263-9a8186e85c80d89541deee31792586bb.npy +04379243-b5d5db47b33a9186ffac3d5f2301b75e.npy +04090263-149adc06e4b1404940232a3c75f1f92a.npy +03261776-2b28e2a5080101d245af43a64155c221.npy +04379243-a4b09d3dc36ce23bab4d0308b2ec6512.npy +04090263-a58beed0a033875567a4cd2863eb1ca.npy +04256520-f736f06f8fd04e1119fb4103277a6b93.npy +04379243-fa259703a9f28b1c62d7d9f5324445af.npy +03593526-88160fcb6c1eef2c35ac4a6a37bb3b6.npy +04401088-62314ec7373898059f7477e2986c440f.npy +02691156-cb55e0710b727bf62e36a049ed2b7f88.npy +04379243-b4ee137cd86d7e3a6afaa22adc38077c.npy +04256520-1d3dcb5fe999334f83de73f58b2fc4ff.npy +04256520-a007a3cd5b8ca7fb19fb4103277a6b93.npy +04379243-681c53daf7810b9f92d5b25c536d8044.npy +04379243-ca6c07357ba5125b8e2adb29857f8a1.npy +04256520-402c270ea6fd4754d93768e7b9b1eabf.npy +04379243-94df93e1c5f96c1891bed99343331f7c.npy +03001627-732e0abfbd4d09858d775f6f7c8f1b0d.npy +04379243-fc8768524737826190e7e9cd4c47f9dc.npy +02933112-9eada38b3a65963e30bbd4cddd04c77b.npy +03593526-7def6a25e235f2deaf0245cb9d7ad8ee.npy +04090263-461684f261c66471e3bdba9430565083.npy +04090263-bb8ffd0d313c3e33202be79d8b285c1e.npy +04379243-ab8f7cd2ba798e33b035d20a1a3ca345.npy +03001627-eda9dd4d0d18c3f2296420d5ebe64c52.npy +04379243-26adf340ea5d552d3c5e1addd9922bf2.npy +02828884-110f199f516657c1473448e3f3f73bc2.npy +03001627-63fb3c970f0051c730bbd4cddd04c77b.npy +03636649-26ce3db3122afe74a5f600ed2cf472ac.npy +03636649-bc49fe3559e18fcb7d910d51d878f708.npy +04379243-3820449f17744298847dc1a0820caba6.npy +03001627-384dc36226d1d4deb7f1aaa55af02518.npy +03001627-a2bfec12cf53f198d810b14a81e12eca.npy +04379243-7105bd044f464358beedb4c8fd29e2d1.npy +04379243-be81240ed3cb8e5a7d8864caa856253b.npy +04256520-7b8a8776c2bd135694e14fba4acebb36.npy +02871439-4c773fb32c39ef14891a7a8a744cd90d.npy +03001627-c7a87dff6ab53f3b7490c34ba5d2779.npy +04379243-ad6317f2a90d71f6f4b6538438a0b930.npy +03761084-3a78c8e5c361ff554a44340bf227e40.npy +04379243-cd44665771f7b7d2b2000d40d3899456.npy +03636649-a708a75b3727b12fcb8d8c6d4df8143.npy +04090263-9a6c8702a8f5d01ad6945707de93a7ab.npy +02933112-b592fe51cdda66394692707833167ca3.npy +02958343-c0db588c8c816cd2dc668d3d64c871ae.npy +03001627-1022fe7dd03f6a4d4d5ad9f13ac9f4e7.npy +03636649-6267ef99cbfaea7741cf86c757faf4f9.npy +02828884-3f49fe14826172dff155d75bbf62b80.npy +04256520-2cb0f608feed6256165ce3a6b1468e1.npy +03325088-a37a43fd956d1ea73ec0850b5880d3f.npy +02747177-a7441227a374ee8cad5067eac75a07f7.npy +02691156-1bba3fb413b93890947bbeb9022263b8.npy +02691156-4a9f55420d17c815d37636af9c7bcc34.npy +03513137-e176a78b82a5add0de8982fc28ddacc3.npy +02828884-3776c500e1654d55c50517751ed5f28c.npy +03636649-b88ca09d13a5a472e3e80050b31d1851.npy +03001627-78952b099c650a85d42ec7e303174a87.npy +03001627-fdb00b6e3c3a8c6e9e7154e1e649e020.npy +02691156-8383e10a1d1faf89c7749c7e68c22ddc.npy +04379243-eb097732d3f31469aa11adad6b2a69c.npy +02942699-58e9faa223142b7fd5af42f3e1f05e3f.npy +02828884-2356e0b210f85371f8fa66012789e652.npy +03046257-a1671be5957cfd688bb3deb7fab7c9b7.npy +03001627-8e19d2ec95c45186a6fd617b2ff5d2d.npy +02958343-5d62b276cf9582e2473f10e6caaeca56.npy +03001627-4b7f260d832c2776a7b43f93c63d6e63.npy +03691459-59ed437f426da7c8c3eb2e07e7561a08.npy +02828884-682cb02cd40c9fa412b60d5939b55d61.npy +04256520-1dd6e32097b09cd6da5dde4c9576b854.npy +04401088-ab96be5a6e3827932a6d73bcecfd73da.npy +03467517-a5e2f05386e4ba55a894e1aba5d3799a.npy +02828884-4e3e67fa22620b82056b4bd5d870b47.npy +02958343-7c9136f3fdbd6c5938948312b270283a.npy +04379243-89827ac677337629ab610b0c94236463.npy +04530566-759c3321f016c1cf7cd1f8dd6fbce8fb.npy +03790512-f26c108283f42995a41f6474541ac161.npy +03001627-4231883e92a3c1a21c62d11641ffbd35.npy +02828884-a77b423dbe9f9a34beedb4c8fd29e2d1.npy +02691156-9bd8d0fa75bc21c5e3375a6b96a1d765.npy +03691459-bbda555f0874e9d5b35234ceed4dc815.npy +03001627-cc3d9160369d09845e61ef8e2af97499.npy +02691156-55f212ad58883877ca8607f540cc62ba.npy +04256520-199f330c7a4880b84b3c42e318f3affc.npy +04379243-3273b3eb8dfbbd8e6942c5426df6055.npy +02691156-1605bdb8709be6773c4d876662ed7ef0.npy +03928116-cbe392ea073dfc763fbcdcb4c54d4ba8.npy +03642806-a9aaa5daad084d18cb5b7dfc5966f56d.npy +03636649-6e1fe96adbb5ffba8bae2d07dadd1b5d.npy +04379243-139e0706288b7ccf1657aaca7aaa9a5c.npy +03001627-e69e032ca0bd60a4febad4f49b26ec52.npy +02818832-c9eb8864f33152a3e09520ec2bf55884.npy +03513137-69ece333c6d386ebbeee9a165d0dbe2.npy +02691156-e96cd99f545a4d22b0a339fc52929deb.npy +02691156-a6afd80fa3d70682ca8607f540cc62ba.npy +02808440-529eb2a106db950ccd0340812259a39.npy +02946921-3a9041d7aa0b4b9ad9802f6365035049.npy +03001627-319115572f7aa81d06ed06732b21e08.npy +04256520-c0580211c63f4fc9cd3f9e8648111d1.npy +03001627-639a10b856336f1fff2c92c2a4f65876.npy +02924116-a5f52fc53695fe9897d0a7f777e9238.npy +02958343-58f447ce8de6b9794c40f34de8f3bdb8.npy +04379243-12a5cc49c75b93af5b4aea6c98f52b6e.npy +03761084-a13b51c46b590287df75fdd4632be672.npy +02871439-f1181054abd6ab38335e5968fd22399.npy +02933112-6478d877795d2214f51f77a6d7299806.npy +02691156-d441a12b217c26bc0d5f9d32d37453c.npy +04379243-c72f97d0b25e030db0892e337a99f42d.npy +02871439-fb1a15143f6df0b35d3dc7a81f13d5e8.npy +02691156-85462aa8b58d5a1ae753c4c9af8a19d7.npy +02876657-495dea92a04b43e6be9fabb33de62010.npy +03001627-78446e1cc15f757297936c81e7f6629.npy +02958343-5351646fca246bc989c6f1079da7a8d4.npy +04379243-ae1cc74a1db83b0e6ab95c4e859970.npy +02958343-884014d60de73249af551becaeca18e5.npy +04379243-8b972b066bfdd7c44f016493aa9fd9.npy +03001627-3a4843e09b8dcafae6c5cd45aa112726.npy +03513137-82e027e4b43fa602f99976ddcaae4d11.npy +02773838-e49f6ae8fa76e90a285e5a1f74237618.npy +03001627-4d3bf8ef55b4e4fcdb66736e6592e424.npy +03001627-d670d3919c87c91cf1783a44a88d6274.npy +04530566-9b5077b81457cfc2986bcbcf53ae184f.npy +02933112-202ea0a26125f716ce5d6e9371bb5c33.npy +04090263-30a009a1877c9ae282a52e2a06478500.npy +04530566-1dffc8919a03627ecc015b9f8906f7b4.npy +03636649-5828e8ad9fd14a1cdb1afe6c464e7652.npy +04379243-881756250fe9a7fa5fceaa39a8353bde.npy +03691459-213d39983b0a865d1369827a16f97392.npy +02876657-f03f9704001d2055ab8a56962d772d13.npy +04379243-a96eb4bdd69c103dd293c20958d173d3.npy +02691156-ddf4aa5f68f89616bce962d6c4b37336.npy +03001627-e88b094644e1e80d8f2ca82d6e1c314.npy +02691156-723a86a2b266109d1fc43d5b32fa230f.npy +04554684-dbd0ba5a349a8849fb0f1b7266d79466.npy +04379243-5a945b9e86d60a4aa75d03186a0409e2.npy +02880940-d98455f19960f99ed684faddec3c0090.npy +04256520-92be674b2edb7f54d18c447b567dbc27.npy +02691156-14282db0ca4238429a6e43b878d5b335.npy +04379243-61397fb909774541e3c62e8199fc6b89.npy +03001627-e279758e8a5b6a8d492d9da2668ec34c.npy +03001627-3efa8030c71fab9055afe589a9f09982.npy +02808440-c4f40a208cc903b18faaa3c714890be6.npy +03636649-9adee08c737c7c134c6deb9ede0648df.npy +02958343-6ad0379c2f24581a1c0f83a9278e7dbc.npy +04379243-6777c68f2b62b581b3f89af909332a40.npy +03001627-428bd9c7c8a0a6bc7ff6ace05b36a5.npy +02933112-88982fc3cdf5d2b212de5317fe5b354f.npy +03467517-3d65570b55933c86ec7e7dbd8120b3cb.npy +02691156-da9c541228a171b7ca8607f540cc62ba.npy +02808440-32a286ab7be40cfeb5c63839abd9baad.npy +03001627-dbfab57f9238e76799fc3b509229d3d.npy +03593526-7775947ce2333be398910e50f05b8001.npy +04090263-5b2fc9e582dd7052d957eaf7f4edb205.npy +03046257-48784197e358000da239e7f1ff51b07d.npy +04379243-e74841627e110e98d9de0de5dc66ab1.npy +04379243-ca82beca43a3b9b59ccce4c6d5bb195f.npy +04379243-83dfe7d2df18ab58fcd4910413c446d9.npy +02958343-cdc8453c63ffc13e20f29d4da2b76f7a.npy +04090263-c1b9ec727b9ad093fd0b1d4a6a5da4f7.npy +04379243-7d7510e6bafe8d2aaab74c2fedafd.npy +03636649-441726d957d718a137b2bb75885cfc44.npy +03001627-df487c3660e7030dc5ed74d70201d4c.npy +03636649-97c26d66399ecdc973b8ea30c1700f67.npy +04468005-d5ed0af28683130b4b0b2e6e63122009.npy +03001627-4133e9d231ca52c6a16baf954c1d99bc.npy +03636649-67a087a3f917c3a7cf004563556ddb36.npy +04256520-fa46769b0817a8744f52551bb6d0494.npy +04256520-d3a8b906f6909b0252899f0b4e8d8ae4.npy +02958343-42af1d5d3b2524003e241901f2025878.npy +02992529-e4d794e92cd098d740dec81c6722f67f.npy +04530566-d04816fe3c531b66f647317afa6ffdd4.npy +04256520-e2c68936d051b926646568c803ce68ef.npy +03046257-b13b3f7b09b6534ce02c475590efce0d.npy +04379243-567ca6e5eebb09f87d0efae8dc996b9e.npy +04401088-a8d72bc949bbf361d8dc338f42ea38e9.npy +02747177-501154f25599ee80cb2a965e75be701c.npy +02958343-b67af8c92198eab432e9b7d6df5ccd43.npy +04401088-7a2a5b36831f45501b670e8e7f0f2c3e.npy +03636649-1854bd4bcf32ca32e95ee7559a2a873b.npy +03001627-f0bd1732f37da50c7000797f53fee6e4.npy +02691156-ffc1b82bec23a50995b8d6bdd18d56e8.npy +02808440-e34833b19879020d54d7082b34825ef0.npy +04379243-a8fd0c73fb6214cad56c79d3df7792df.npy +04379243-2f33abdfe147813e44949d7685cb63ea.npy +02691156-bdeb0a21cf1d602962347b4731688b0f.npy +02958343-948827c3833b8ce26d709900f94f0df3.npy +04379243-d3624229f0310175658d908a2254f194.npy +04090263-1ef4b49ad8b4e51f1dc5248baf82e0ba.npy +03046257-c764e7f423ea0b0251dd279724dd0c.npy +04256520-20b601472e40f47b17b431cae0dd70ed.npy +02958343-5be0fa6b0bb7a281a170b3adf3b6f220.npy +03001627-e30b412be565a1026efe57da6d3d385e.npy +02691156-445404a75a0ba2ab1fc43d5b32fa230f.npy +04090263-546acfcb08d2af05be90eac69c95aeea.npy +03467517-4a3e5c774d15a35c1082f2ea630bf69e.npy +02958343-5ea6bb423b1600141d225d751745cd28.npy +02691156-c12362906beecc796059aeb39e538eb2.npy +02828884-2480c05ad2b4969971a782a4379556c7.npy +04379243-39dba8b2e416449a19fb4103277a6b93.npy +02871439-33b29c9e55250cc57f0bdbbc607f1f0e.npy +02876657-41ab1142420916e374bb1e92fd01dc00.npy +04379243-29d2c8d1297d9f5c9fa24672a35ae8bb.npy +03211117-9ef960721520d46a922e9adbedbcd67.npy +03691459-46acc0258b449d18f01503c3476a4944.npy +03001627-26da81dbdf7784dddb984b8f0550fcd4.npy +03001627-cc6840207c0cf55db30e42459dcb06f.npy +03642806-241ec8a746dd1cfc78f71a335ebabfa5.npy +03211117-d85f501bf76933c609d7d8d27dbba7f.npy +02992529-e691c8f0fd7d64d7ab0b172d4dea80cd.npy +04530566-27d5c5d0dec7b209124dae0a32996c4c.npy +02828884-3ef52655b95ea7828d1fe8cdc415f4c5.npy +03001627-b8bf7e161cbff74066ab323d8f805a57.npy +03636649-cf9987efe529a5c538b27a25d1336579.npy +03211117-bbfac23f57b5fbd820e867fd9fb7164.npy +03691459-240521f502e491cd4eddc7a5aaee958e.npy +04379243-20b72612211287d43002761e7a3ba3bd.npy +03642806-1d66c26055573243a0efaa0482f35281.npy +03593526-be91cefe6cd75c15ed7e8845633fd652.npy +04379243-2fe5e4d8a871fb861b1a00a31bfed97b.npy +04530566-e4717ec5f7e12fbf07aa2d157764a08.npy +03046257-99d0eb7e23df54864d46ab71b147ac5a.npy +04256520-601bf25b4512502145c6cb69e0968783.npy +04090263-377289b4275551e83624215edd93853.npy +03691459-acc5b71d898d510f1ef58b31c4ba0d15.npy +04256520-d87a4ae5c2a768d4283b00891f680579.npy +03001627-71e139bf13970c94492d9da2668ec34c.npy +03001627-34bda4dba48231b97a90098a7525b367.npy +03001627-5a3fe2c1f1e2009e762ec387b772e9e1.npy +04090263-af06013159ad2e45cc34b900bb2492e.npy +02958343-c179735c4d9f65d7d1521952154c90ff.npy +03790512-1a48f3b3c0ab0fdeba8e0a95fbfb7c9.npy +02808440-7efbe90c9685e23cede9471c962dd6ba.npy +02958343-752a3ce746670be176ad064d1c5fdd7c.npy +04090263-1a8c91b4803b3470f9c75ffd2648d7cd.npy +03211117-762b30a37bb098ebe7db3cc5ece34048.npy +04530566-98cbe2b3e62879058e3175d49fbb0f30.npy +03001627-19cbb7fd3ba9324489a921f93b6641da.npy +04225987-8310154df085baf3e3cfaa4e6977fab6.npy +03001627-92175cfac21b10e76e5b9257c4084ca2.npy +03691459-16245718c786456b35949989d0ab81d2.npy +04379243-680414bc3ea1e9a67ff6ace05b36a5.npy +04379243-772b0908f5aa09c687d3d93a515ee29f.npy +02958343-7e7f0637d6798113ddb4014f0e8d0dac.npy +02747177-816d92c78f85f5002056b4bd5d870b47.npy +02808440-b6fb767050949172ccd0340812259a39.npy +03636649-2f46b8a15b15439d713f2e93cbeac35d.npy +04379243-3398658268644c2539eff6a5994f7472.npy +02808440-564813720bdb0cd93321831d2245cf06.npy +02933112-13aeab12a8ccdb244da5feafe6f1c8fc.npy +03642806-367fbaea8743ec1cc98452c8fce6b43.npy +02924116-75e1a6e156e8373b193d7855ecfc1bd3.npy +04074963-b9714784de07ad31cae0e78ad4bea7bf.npy +04379243-ba0cfe7ad9775de3276b6f6d90ee3a83.npy +03001627-a374415a1ccc05aa283b00891f680579.npy +02992529-adf64019f7a54162550c9b1b1c5f7e5f.npy +03211117-d5ae3a2aeb50a07e75e49fe23848bbe5.npy +02958343-3eb545f745d827752e4d5bd853781216.npy +03636649-211a5b7347645a99967cdbf1c849239.npy +03325088-31b197f507561fe7c91cb0beedee33fd.npy +03636649-43b59fbc4703d7d1c8e6d2030713566b.npy +03001627-b0531a0d44fc22144224ee0743294f79.npy +04379243-2bc37c326782ecfb9bbc8ad5ece3c1b.npy +02828884-65f6f33358b798892056b4bd5d870b47.npy +04256520-f1ae0c66488c39c8ecf6d12e1f8958fc.npy +03001627-99e4c4b39b75a06b30e06a011e63236a.npy +02691156-16f67f87f414a5df26360e1e29a956c7.npy +02933112-b12fd3c4e5912a7dd8b510632cc84b8c.npy +03046257-4dab14b822fd4a06adc5f5aafedb1c38.npy +04379243-41056728cbfd7aba9f8c3d2002c77ddb.npy +03001627-5b6a608c22d77fbcb04cb542e2c50eb4.npy +02992529-d51e5d7eae216c9ef1cb19f636b1c2bd.npy +03691459-3ff2ce8b7432b5d6feae521e94848af6.npy +04554684-a339c3e29128a402c8e4135ffa0bbfdd.npy +03001627-72d7299f4a0a542c76f992c4dd795e91.npy +02992529-ed71d2ed652b911e7f521a3dcd28e9d2.npy +03001627-699fb3293e219808599dcc439b161a52.npy +03001627-5fe56a4a9d5508c3b2373df00b89e5d.npy +03991062-5044332515e02a2b78caa162a41a851e.npy +02691156-b53ea9af10f2a151bc0909d98a1ff2b4.npy +04379243-f28874ee319d1e2dd3bd10ac60e54bc9.npy +02691156-bc86e4461bd4c955a34fb3db6a11a22d.npy +03001627-33774f1314ea9b504b3c42e318f3affc.npy +02691156-9a847e8c8f9c0acbbb05fba9fce1c1e0.npy +04468005-d26eb320ce4753d03ae1361afc45ac52.npy +04256520-2c7fd96b46b2b5b5efc579970fcfc006.npy +02958343-afd73137221d690761c6c61410fc904b.npy +03211117-e38a7ba01d45953ccb7547c95fbdff26.npy +04379243-15bae7fe612add11bf899e941ea0fe55.npy +02691156-7b1859e6b57bb6621c795eedd7ee6db0.npy +04379243-ac646aa05a0ae0e11b604216cb6e7d3d.npy +03046257-1d5a354ee3e977d7ce57d3de4658a486.npy +03211117-9711341338f550145b778a830599543.npy +02958343-894e186c1224c14f86590219e6a70ff0.npy +04379243-3d7f82a1bfc5e1ee9dfa717f86ba8028.npy +03593526-537670c883cc57f730612f5c0ef21eb8.npy +03325088-291eba55363e33cf979c556124bee033.npy +02691156-1d68bc47a558ec9b266eb575093ccace.npy +04256520-8951dddfc3cd6b08e8f8c11a24c52ebb.npy +02691156-22ced10a5d20b1c1fca1f1143bb6bc17.npy +02691156-d6cc7ffd165de05e2e2de556c136fbc8.npy +04379243-e8dedc79c201f076973f95b50a1641d3.npy +03636649-9cfefdc1e63a3c2535836c728d324152.npy +02691156-5d7b52a58c667ca835fc197bbabcd5bd.npy +02924116-6718e0455f3ac9a4459eff669967d5b0.npy +02747177-ecd9af137b451664bb46eebc96453b8e.npy +04379243-8118d53cd86b7aa6436e6787c76ef3f0.npy +02691156-94379090010cd6bb874c9ce092a813ef.npy +02924116-b73fd7769a870f7e52470de2774d6099.npy +02933112-39db396f57ec698cc59350d819542ec7.npy +03325088-cb80870b4c80d9c4b0bf85736b51ccfc.npy +02691156-d2faf50d6d88dd0690baeef8ba5b93e5.npy +03624134-5c5e4a7e5670eace44841730d607e227.npy +04468005-b9257fc9ef316cb56d99dfe91d90e769.npy +02691156-f40fe7461dc4e3396b7bd17e458d0dcb.npy +04379243-5a6c1cc3731fedeb55f46d55537192b6.npy +04256520-8f05bca2d46582483b28ebac0b25d03d.npy +02808440-5eab643d440c4a4bab78f79703f1828f.npy +02691156-613bf91bc5c201e115392a14b2886d23.npy +03001627-451458fe90bd0f4144f23566597ec464.npy +03001627-2195099b0295f692afca3357bb07ab96.npy +02828884-fd355d06238853c7f0d9805ad6c2059c.npy +03624134-82ebc48a41abaad2e72c243118d89f07.npy +03636649-a04e341e7dc206edfe10244ee697dc96.npy +02958343-536b6629c4f60d07e78002a96f52ef26.npy +04379243-75a824a5acd71051bb29ecbc4d013bd1.npy +02828884-a0ee85921d1bcfbd81faebbdea6bd9be.npy +03467517-f430d1ecf9ebbf23d57700c05b1862d8.npy +02828884-df6fd36040a5719662701a18243b45d3.npy +04379243-9f76504d9b551e548c37cfe791015e2f.npy +03001627-bab30539155767a59f422d8258cbffab.npy +04379243-f4b5313a0bc95a48da7c128b58fc7554.npy +04379243-3f5daa8fe93b68fa87e2d08958d6900c.npy +02933112-7eca681f6174f1ce12de5317fe5b354f.npy +03636649-6c33f42a0f97360143dbb6421d614c0d.npy +04530566-b6eefb8fe960df93d4dd83fc93961e73.npy +02691156-40192d0e50b4d2c1f27a705edb2f9ba6.npy +03636649-f7b3550d5e59934595bea7c29e873d16.npy +04379243-a034755df11115a1a71c812e027f94d9.npy +03001627-6ff87a46571c52c4f4b6538438a0b930.npy +02828884-f0b85200702e4739391e4d6c585a697a.npy +03337140-1e22bb0b68275ddfce79c0972693d245.npy +04256520-7b3bab9058f7de33fab6e40cce6926d7.npy +04256520-24bfcb97fb60fab7e812c99c6645894b.npy +02691156-ca16041e31078463afe21c1ae3d91b49.npy +02828884-8b677cef30fba873240c1f0f1e25335.npy +02924116-d3c35d123af3c8e826829c11d9aba173.npy +02958343-40c2b97577b43161aaafd94b9f216ef6.npy +03001627-1be38f2624022098f71e06115e9c3b3e.npy +02828884-b9b708af97a57de481f502b2c7b6ba78.npy +02958343-3462d5da3654b52d4a47c09276b7f6b1.npy +04090263-c802de6725483fd9ab66079ce2700442.npy +04379243-d5a3401380fdefa0f51f77a6d7299806.npy +04554684-a94bec767f059a013bf7bae2651d2cf.npy +03593526-5a4af043ba70f9682db9fca4b68095.npy +03001627-6aa86c295de207dcedad5734e2d87ca2.npy +03691459-483c63155f2be7a8983b2cee8fd0fb3e.npy +02876657-b35081bcc11ff7847b8ec2c9a49686dd.npy +02871439-2f8f1d7cd9f61a07b1edbf57c29e5fb3.npy +03046257-166bd86229867093031b562a9def0c1.npy +03211117-6437fc773d50e93b5c915b36bc455bdf.npy +04379243-aaaba1bbe037d3b1e406974af41e8842.npy +03691459-f4b733690a0fae8ff357e7c4167f3100.npy +03636649-80931bba35ec76db7088591b1a3e2750.npy +02808440-49b59c49ceed072491b664dd7cf765a4.npy +03211117-e70f6a81158cfb213a762233fffc49ea.npy +03001627-b1908805f05c6f47f51f77a6d7299806.npy +03001627-95317d46812e4ed4df5aea2392d894b4.npy +03991062-27d804a7d8ecf4ed148a76a78b10eb5d.npy +03636649-fc8cfb4ad6730207ad90876bf5435820.npy +04090263-722051c679217db6f436d0d7fdd21532.npy +04401088-144d8038c1688e37ab3dd76bf33b0f5e.npy +03325088-c46661274623b6cb3321831d2245cf06.npy +04379243-8a1687e286cb0b6f9f2349486c570dd4.npy +03001627-357f1c031b1bdfb3efaf604fa2300241.npy +04379243-cfeb699abe1b76c9964afc371e247bd5.npy +02942699-74ebdf5a3cdf33ebc6966f67e1bb9e90.npy +02958343-46befc634315de3f1ccbd9e5bb82dd04.npy +02946921-7bd05573c09fb0c2af39ccaab9314b14.npy +03467517-2f9bd6e61e038d8fd4b4ae2ff4c58b57.npy +03797390-659192a6ba300f1f4293529704725d98.npy +04090263-cb842e500cebf07a87856c3f95c33cd0.npy +04256520-75e62dceb6fc577e593ebeeedbff73b.npy +02958343-bbc2f2ffeec425a38eac574d099cd5d2.npy +03991062-440a38d6a90a5243de98d10ab5975b59.npy +02691156-99dc4702d20942da18e0889038e4fb6.npy +03001627-269539368eeb8ba95d99e410bbfdd132.npy +04379243-f621e2ad900ad48535836c728d324152.npy +04530566-991b0f19022a0233bb97258c2be2acca.npy +04256520-3c05461b9f6330efc61d98cf72b72c17.npy +02843684-7f53db3b31fe08283c2748dd7bf1793a.npy +04379243-276e35b78c24f8b2127787d2c89d5a93.npy +02691156-f9a8c5ae39362284d538ebc793e748b2.npy +02828884-e2cf4a7357cae6ed2dd04fa3e4c2a53f.npy +02691156-209bb7656231011d7965bced3a0d8967.npy +04379243-3b9b877ffac13289b6536581b321be90.npy +02691156-e55224bb456066c618d508b491dafd46.npy +02828884-6a6aba2dd0491b99cb2a965e75be701c.npy +03325088-ed8a6218e467e8a676d20e73c57c9a03.npy +02828884-616f9d109968982ced98cca8f0ccd5f7.npy +02828884-c327cf2527737f7ef155d75bbf62b80.npy +02924116-6ddf96982bc07456813f04ea98c97256.npy +02924116-2cf0cccfc228d92fc98c13d6112727de.npy +03636649-738646252a89e865bc5cf22809274024.npy +02958343-4acc28685ab111b672601793664460d.npy +03001627-947dfd74fc8b2e60643b321651a8f917.npy +02933112-a66122ff2d0e4bac6ba14bfd91a75020.npy +03691459-c3280f7bc5fa9ff28a0181490cb73cbc.npy +02828884-1998e800a95bfd18edd7d0866499ad97.npy +02958343-275df71b6258e818597505fd7d99b613.npy +03624134-23d7c17ddf80cd5549f73a97204d432b.npy +03624134-118141f7d22bc46eaeb7b7328341827a.npy +04090263-bb3f4468dc88370c9caab46c14deb892.npy +03001627-43569dc880494256b40f0ac0fb9a650d.npy +03593526-decc21646f053418df2fa7eaa812363c.npy +02828884-cad58af144b615b674a3201fd136f855.npy +02946921-2b08d2c26d1fce3afe34061aca66f702.npy +03691459-53856db6d2a2873c80ce1b5d66a0b782.npy +03636649-1a48f00729981afbc01ff6a6aade8d2.npy +02691156-52151d6a699ed1acecae07472b415b97.npy +04256520-eaec2a137b0858aa599dcc439b161a52.npy +04379243-a7ef45d86ae5b496a97f238e46bc2221.npy +03001627-6921b41c2f6916e2bea04b36c2ada3a3.npy +04256520-ebdeea981de34c1b2d19175e7d19b7cb.npy +04090263-2f2f7819edaa4ab7fb47f041a00e8417.npy +02876657-dacc6638cd62d82f42ebc0504c999b.npy +03467517-5852a24dde24a8ef93f0194265a9746c.npy +02958343-d4f88e7219c4b9417b5adf84ce6f7865.npy +04379243-50d898f6d1c05cee2d99129afd32edf4.npy +04379243-59e1afdec89de9442b70eac6546e93fd.npy +04256520-68aa553c520fdeada30a92122fc999e9.npy +04379243-23d1c6e2e35cb252bb85b5a298d72ac7.npy +02808440-cba294fd8320a4b13321831d2245cf06.npy +03691459-fe613d2a63582e126e5a8ef1ff6470a3.npy +03691459-98ad42e08a991125f0ea0ee719f6dcd1.npy +04379243-8a8934756916a42855ce350c1c834503.npy +02691156-bc59a1d1f959b6f9b2acbfd8323f804.npy +03691459-d956f40d4b3cf48f7889725d46ad23.npy +04530566-db01f2f8cff7b7e1c517f0fe59ec7ee.npy +02933112-bb9ac4b110f7ed3815dd7d7985e749c1.npy +03001627-d66b701631851e7b4b19d2c99e22ffe0.npy +04379243-cd27c39dc711626d7e9fb8aa5670f37.npy +02876657-365f8a3cf397adf66e71bbd43f7f5d20.npy +04379243-b0264f893f25e10ec955e5ed03ef3a2f.npy +02924116-672173207e1cd8a8c567c0a983faf2bf.npy +04256520-ad7dd9434ad5f61db759217db94d2883.npy +04379243-3ac209693a4e89c4a4b99739648f763.npy +03797390-a8f7a0edd3edc3299e54b4084dc33544.npy +04379243-b323d3002578f5f3f6cabe1df6f4c9d9.npy +02828884-feb6a23a5e25abe459af9a18ecf57ec3.npy +03211117-d5eaa13bf0dae2fee2e6b284e4b0319f.npy +02924116-b60af2693c12f6181afedc87fe387fe.npy +04530566-cdd493581ed137c5a6dae8586082d789.npy +04401088-641234f284243decea95e61f66327e28.npy +03593526-94b833e6157f13565ca1f314f1afc186.npy +03001627-e5d285ad477a33a27eaeab1f0c9120b7.npy +02924116-6886edda8e86aa84af02ff7e690e1b0.npy +03467517-faefd0da82f1606d9e0d303f663a5614.npy +03046257-3c5690e5ecfe5f0afd9cfa6c7f5305bc.npy +03001627-11b7c86fc42306ec7e7e25239e7b8f85.npy +02992529-db1f83761a7a19f6d0c7ebb68662b4e5.npy +03001627-640f61579181aef13ad3591a780fa12b.npy +04379243-8fed49d9a02124903002761e7a3ba3bd.npy +02691156-e7ff46a15ae32ede7480441c35610069.npy +02958343-2b08d1ac4111542f3a2b1a2e5e169910.npy +02801938-3071896180371f53eab2bd7322386ffd.npy +04379243-440b50a6bd10d00eb000f20a5153622c.npy +03001627-90587a80c1e58a7ecd447b0bcf9cfb5.npy +02958343-37c5ac3d5b34761add75f724c0ccbe00.npy +03001627-d4d18aea46db0b4d42e792292462a0ce.npy +03624134-b60d44263ebdfbb24b7644126b1d71e0.npy +02958343-9901e5d7520df242c61cbe35764dfac1.npy +03001627-550dd11407c28f9f3bd04286517a8395.npy +02808440-46bf8401785b96e336d8dd30a594b2af.npy +02828884-b6410fb9ca3cad2170a97514aa270017.npy +04379243-6aa865b9e1e9384d40ed3786e46af8d.npy +02691156-8db0b83cee14e1e5eacd58bc9fc5db51.npy +03211117-93b288efbbffff30c1dae5936fc55ce0.npy +03691459-b4e360a10bed4677aa0022295937af95.npy +04379243-c734ed1d590bba80df6cfab91d65bb91.npy +04379243-794f6c8575cb9828b44aa1973fabbd64.npy +02773838-68b7ca73de30ad6df2197da8dec8488d.npy +04379243-fbee497d2941270d79368d1198f406e7.npy +03001627-30e8a82eccb30369e3ca99089143c61.npy +02958343-441d0b3f687e3721fed6082009db27d.npy +02828884-54239ba1b945460ae4409e4832196128.npy +03691459-3fcff447f43c75c3ea3d2e9efa07ccad.npy +04379243-f078a5940280c0a22c6c98851414a9d8.npy +02828884-783b224ec9a89638736ecce7d21f395e.npy +04074963-80701d854496d6fe67a964feaf6ebeb.npy +03001627-470d626518cc53a2ff085529822a7226.npy +03207941-35617fd7ece26150ffc6e457221b9271.npy +04379243-910a506648c64970a8737fcf23389014.npy +02933112-33ad208b1b1468bc558ef7f77265c6c3.npy +02691156-e52f809111bb75692b5a1d128057b6a4.npy +02958343-24c46b3a467bb4954b1bdab82d834140.npy +02747177-b6fa6b957d2ed982e4612a77ab3114c6.npy +03001627-79862d8abd869cf6b3a8888e78d004b3.npy +04379243-57b68a9891773c89d27b31bdeb5f5c79.npy +04379243-b20204ca63c530fae3f7a74e12a274ef.npy +02958343-3a6a1feb338c884a8079d5a13e411210.npy +02691156-9b09169e0a2b8650dcadc22bf3c23ace.npy +02924116-2c10db171628f11c462dc6b25a076dfc.npy +04468005-7578f09ea13f2d04ed79a511eb448339.npy +02958343-d3f5e04481e69974d1521952154c90ff.npy +04379243-ea45019340b754c155f46d55537192b6.npy +03691459-e0c6692e0af5dda1459a1795a6d0c69f.npy +03001627-6bd131b9cc3e8b97b2ce8575669c9dbb.npy +03691459-7f448ebca95a536f40e7eb33087f3287.npy +03691459-2379915c82c2b2d02530f02db7e9157e.npy +04074963-4c78551ab00fb1873fbe480a485feffd.npy +02691156-7bb1d2f8be9593b3cc14f1e6f4f4f49b.npy +02691156-3c9d577c78dcc3904c3a35cee92bb95b.npy +03636649-fd5f6ab819910a66dc7f95a5a82e36f7.npy +04379243-a7164d4766ff0e1b4ff124faf2d8d947.npy +03636649-d6d7fb290b69e985ee2b478fec745c0a.npy +03636649-dd40743536da78a2bf964fc57f6a7d6d.npy +04530566-aa695b15cb58096f36aafa2ff65e6955.npy +02828884-448010b6066f3da3b069944d084e877.npy +02933112-e408c939829d0353a6490b68274665e.npy +02958343-4bb61e5a72bea4506ca2b6e5474aad11.npy +02773838-a55b721ea5a29d7f639ff561fa3f5bac.npy +03928116-a9292522fb6fbb987de45a8ca0837da.npy +04090263-5c28fd7c3d261e1b3e243aaa4500940e.npy +04379243-3ab6e079e4af17401a53162afec5ca5e.npy +03001627-376079d4c844328ad6eefa796d2f261c.npy +02876657-758fb2cab125eb6b153b368d6f14e275.npy +02828884-d73143a767890e26505bbba2c4eee722.npy +03211117-37ed0bdf52f2eaa83c5474c35497dc65.npy +04379243-12ecbeacae03825ef211221ba01b03bb.npy +02958343-c8a69b3e40337ba8c44c06ae133f875a.npy +03085013-485e300538ca1fc9f1e852be2b9d80e8.npy +03636649-ec449d7c89e84657cf66a9e192dbe265.npy +03001627-d36de0f850783d8fd6b3090036b71698.npy +03991062-31923669954ca57025ebd1cd0b422e32.npy +04379243-4d8abcddafc52ccc95e7043c2fdf14cf.npy +04379243-b977915b93e87cbdd724c69102d5ef2.npy +03467517-8f59fee745f1e37ea5c8e9fc8b2242fd.npy +04225987-e314be67e02df59c520f00c860557591.npy +04530566-6c99359667a1b49d657a96a9bceb8713.npy +03001627-2c67f62020ca22927297db8481c2b16b.npy +03001627-bcdcb4928e07e4174a623eb2e3317415.npy +03691459-f8b0dcf0788e775db98f9e89101e3f14.npy +03001627-81910ec49fc4951330e06a011e63236a.npy +03001627-9f1a83a9fe6ce47afe74f7508ff628ce.npy +04530566-713861441f4c7110b7b1411b0ad3bd0d.npy +02828884-972e0e5717676e47d201085e80edb26a.npy +02828884-89f810f17284aceb85ef4356ea4ff622.npy +04379243-6c4cb518c38c50c9939c47ac2990d9c1.npy +03624134-1460eded8006b10139c78a1e40e247f3.npy +04256520-6ed77417302eb83832a1c3052eaae289.npy +04379243-ea7ca8c7d68c1f62660d2c57f39fb65d.npy +03001627-6cf7fc7979e949c72dc9485cd94746f7.npy +04090263-c9e4c1b4cdc45601dde078ce46d9fe3a.npy +03593526-869a98e1ef4fdb543c8d0fdfb1cc2535.npy +02958343-79c9b9b6e2cb15a2dc1f7c6230f38f00.npy +04379243-2d018cff733a8e176870e413ec7729b0.npy +03928116-673c3f77f3702338a1845d2858b500eb.npy +03001627-29b3a8cb9595cbe63b7fe46c7c128390.npy +03001627-5aeefb539699524044b2fa2cac0778f5.npy +03691459-ed06c596dd9b9cf3dc99793862c889e0.npy +03991062-4e377c970b6dcf4347264d6335395c04.npy +03325088-d62a9031fc6961833321831d2245cf06.npy +04530566-a6d50000249d71cf70c8aed16b49b164.npy +04090263-f0cc8d1741f287fa276c3d558130f8b4.npy +04401088-b02d8e0fb3ec903b4a952171144f2812.npy +02691156-a7394a6f2dcf8e9b3cbb132878a747df.npy +04256520-f4370eb6449a1e8e191682d3b3321017.npy +04090263-9b9d03274e856982c2c44977d8755d41.npy +04401088-9fd7db6d334e6acab29f572d1167c0ed.npy +03001627-2f4b0d6e2faf22d68c18ac3fe1584a6.npy +02691156-4a9d28a5f272853fbbf3143b1cb6076a.npy +02691156-6c613c1893bf7f9ffae8113cc147b3ae.npy +03467517-a10303f8b98342cedb6edcc84d526a7.npy +04379243-26ebcfb2ebd8345f14b86d5282eb8301.npy +04090263-154c779086865eafe906ff5bb78d7b1.npy +02773838-2ca6df7a5377825cfee773c7de26c274.npy +03001627-6de012f3ce256e9930c7810cba6da248.npy +04379243-660deb63defcf872e76bc197b3a3ffc0.npy +03790512-6611e5f5092d1ac1104831d5b063e54b.npy +03513137-17969fc40964dbe0288d8f1144f7979f.npy +03467517-153e7883f6cf0e66d57700c05b1862d8.npy +04401088-ab8243a880170c00cca1221aa4c4f70a.npy +02958343-b4110c921adb2c40bda733a39f84326d.npy +03001627-d561ff6788ab46517b016084e2ae95e.npy +03001627-ec637164befa6a016bba96a850a0781f.npy +03691459-f996317de417329b1574d21c0c95092f.npy +04401088-5bbf52512a45bddb7525dc2f981e5489.npy +03928116-fd2d4458a90405c0b60747861a92b009.npy +04530566-c2eb256cde2dbb93c17ff170974eac43.npy +04090263-9b59affd52c33944c6c1e54aa8170142.npy +04401088-9952f0dc41b20fcfdd5b23028b480cc3.npy +03928116-604b2240f6e827d21995b51f9c4e1836.npy +04401088-9b608bcc7e62c3e2dbe1e810cdc7471d.npy +04256520-903dda9c731b73acf661d29029f2c819.npy +04379243-8f0a115dc4c1c183f16363d52e74cddf.npy +02691156-22829f20e331d563dd455eb19d4d269e.npy +03001627-36f4f54d500dfcec9969831eec1821d9.npy +04401088-a860adc078391edc6774046e1fe3165b.npy +04256520-164f50d574036cfb2ff0fced1c150b31.npy +02924116-cb6defc2b3478f2223448236beaf8ea1.npy +02691156-2677c3793143e75766cf1b4a8fc3914e.npy +02876657-9c8d90ef60e0b37fd317c475f024f3b8.npy +04379243-fc1fff82a7c97884fc5e332306225be0.npy +03691459-46b229154ab6434177818a0572bf1777.npy +02958343-c1daf553ebba8c07e4b68d3b17c43658.npy +03636649-79861fc79f8dd8b478b03575bb54dfd4.npy +03691459-b02ae2bb9756acdc5587d8c9be86464a.npy +04530566-20c2e1a09d00f51294daa4565dd30535.npy +03642806-1497a7a1871af20162360e5e854659a.npy +04554684-933dc825712acc8ab5a3b8119a3da34a.npy +03761084-cc932ff79453c009a6bce7f3d1dfedad.npy +04379243-8aeb236e281bd5a4f51f77a6d7299806.npy +02933112-ce9c5aa7a4016f138c2f9e4176bfe555.npy +03624134-81d9a6aeafadb719ed6e4dd9aa9b9ab0.npy +03991062-bdb680eafe46baff3f7e27638e63d848.npy +04256520-a157ab590ef0f9b6dcdd187a6a5d68ad.npy +02691156-3902709d4b10903579995cc5afab9d5.npy +03636649-3834d7f376879c03eca29403b7226aa1.npy +04379243-f674a5a3c9c5c7c781faebbdea6bd9be.npy +03001627-712415ce3f126dd921bdbc0445d9f748.npy +04401088-aba1179bf8b62c812a6d73bcecfd73da.npy +04530566-68f118940e88df383ac122c0078b9b60.npy +03636649-120f940d4c32c48df51f77a6d7299806.npy +02958343-b4f06573afbb3c1d9a997e8df355a668.npy +03948459-2eca5fa283b317c7602717bb378973f1.npy +04256520-9fa4f3e75f6bcd89b758c822519f97be.npy +02992529-c6f62eb51d1750497dbf89b54afcec5d.npy +03467517-d7e1b36ab46e2d9130f83c7e8a7d80c9.npy +04225987-58ade10f7f87edc6e860048d7ced02e3.npy +02808440-bc990a3fff60a55ea64e5c46abb30c70.npy +04379243-1e5f3bc86bddd77f700e86b51ee00536.npy +03325088-d4939c7a314174e276c18e71fd49c4dc.npy +02691156-a0095db392a8b520884a857d19f7439f.npy +03001627-469d04bcf9576a8b8cbb8bac2032149c.npy +02691156-c7df0d3a924147a49a6e43b878d5b335.npy +03001627-c2b898dd5601454d626d7e3d07da8352.npy +02691156-1beb0776148870d4c511571426f8b16d.npy +03636649-2e5a58c43539442a6858978be907b0c1.npy +03001627-fe9467d48dc6b3491dfc750afa3f442.npy +04379243-e407b3cb5cbd7d4fe0f0631862fa9bfa.npy +03211117-5f248c8e804af22f6436916a86a90ed7.npy +04530566-41d1856d2e24a738b4624ce09086ad45.npy +02871439-1b301a8217f3b0ae13b18ba49b3eb9b4.npy +02958343-406ff3d73672bb2b21669bcdba443569.npy +03636649-85b3f0b7d9968d79664b3b9b23ddfcbc.npy +03001627-55bc1f325928f28c738dd0d3509c7e47.npy +02958343-6fd9b065c795d915473f10e6caaeca56.npy +02691156-df990580230f0254d21176457f0be3a.npy +03325088-b2a3d57b66ec42f350da8b99982a3057.npy +04256520-28940687b3516d6e8dd711af5650bdcf.npy +03337140-ce20ad86c7e6e0a16c8051be410ba0ef.npy +03001627-cfd2b4a2c8398220731d11154716a6b8.npy +02924116-afb664bf0c6e3311b2da04cd324f7af6.npy +02946921-c4bce3dc44c66630282f9cd3f45eaa2a.npy +02691156-cbdf611a2146031823a665a253ac8cae.npy +02691156-ec4cd947eb2ee3103554ccf8c30febe7.npy +03325088-78412afa26ae9e4d76c18e71fd49c4dc.npy +04379243-82d1c45956b00636b7b774bdb9e14e53.npy +02691156-44e08106211ff2596ed8c57a1980bb26.npy +03001627-747667ef89d03f0dc79b7c4f72055bcf.npy +04090263-8f4a280e59ed5fe859360964d7fe1813.npy +04530566-69c4fbba77ee7891a3c3bb12365964c6.npy +04256520-7cc630a72eca68c0457ba044c28858b1.npy +03991062-9bf2153c2068fd39a2c59a4d90e63212.npy +04401088-c28ca490e5e7d104b1508bbfb8b56edb.npy +02958343-719a65d25f0f97b22935bed12a852dcf.npy +02691156-a6aa2281ebfd822e9b2acbfd8323f804.npy +04379243-2d22f3f0723011548aaae3d020f5ddf8.npy +02808440-7ec638ee1fa35cbc125fa9990176f0d5.npy +02691156-3a7e396786751f544c3a35cee92bb95b.npy +03467517-ee434f96e8398084a9edb43ba009e64a.npy +04256520-450b2b913495b73e9069b3c9aa123329.npy +04379243-7c7e0d1157c727371c7fe5be55ca5cfd.npy +02933112-13a42286f65c8b559f8c3d2002c77ddb.npy +02691156-471f072ea9d51f639d92b4de623f5639.npy +03938244-5429faac916362e185bc264270ae0601.npy +02691156-a849d4325008fbea85dfb1711fe4ff6d.npy +04379243-5026668bb2bcedebccfcde790fc2f661.npy +02808440-ef39099e75d450b46012ae9c733eecc.npy +04090263-7bd6db14ec6c37efeac2c9f41d1276bf.npy +02691156-758b67f9af18602715aa5b227c027ee0.npy +04090263-2cf699bd28ec65dca58b002039bd187f.npy +03001627-4d6107c32c75ad6b9f4b4145f6688869.npy +04379243-a5230f3ef20e6d460a7085510f65cd6.npy +03001627-9233077bbe6926c239465fa20b0ba7fb.npy +02933112-31590e22b5abce1191c352d02061b3f7.npy +04090263-b26c0df3e57ab7a298a1a2453e72ce7a.npy +02924116-a079073bee81509552470de2774d6099.npy +02958343-b51d8c15d8f603c350937622ac92802.npy +04256520-793aeb3e33325c491f4fac9ac5e71796.npy +04379243-a00b79f779bbf4d7bdfce662c3df88af.npy +03991062-6c683fac62caf6c23b0674ad753b6090.npy +03001627-a6afbf5a5eaafec74ccf4672ec1e7efc.npy +04379243-73bbc651e2d6eb22ea65c47b660136e7.npy +02876657-1b64b36bf7ddae3d7ad11050da24bb12.npy +04530566-528689641a6562e7bd7a55708242b1bb.npy +02958343-ce375f51744396e52a9eb0f146e94477.npy +02942699-b42c3da473bb4226dbe4bc54590e1d59.npy +04256520-a8395165dee1adafe0c381fdfcdec36d.npy +03691459-6e97134cd7dc3067c24c52be855c1525.npy +04379243-5b109b578e82cd4f40ebe9b2fa95ae8.npy +02691156-a34a6611fd6b2451690ce339b831e7e2.npy +03790512-13a245da7b0567509c6d15186da929c5.npy +02801938-f8a8501a980f1688d5f9523b8b36563f.npy +03001627-7139a30ff80da3a6b12dfa50fc9e07e6.npy +03001627-35053caa62eea36c116cc4e115d5fd2.npy +04530566-dd4b3fc340bddb7f70adfca72a15271b.npy +03001627-73b7d6df845221fa9a2041f674671d05.npy +03624134-1f8d5050facea8cb7e0660626012c911.npy +02691156-e430f24c3125997339cb1b92881e8e76.npy +03636649-be60fdf6e4c9e45fdac42bdc1d2df4a3.npy +02691156-53f0e2f6671346ae5ff3feb917a6004b.npy +03001627-9368cd9028151e1e9d51a07a5989d077.npy +03636649-e8568e17d0fc6418e6543556f230fe9c.npy +04256520-732f5f4226ceba1e593ebeeedbff73b.npy +03001627-b9f80c27c118564a9a318f18e43edb72.npy +04379243-d63496bc51de5d77e3837ef7356e7613.npy +02691156-5d022668941c6559b0ed23034a67f7f.npy +03001627-b718fe66075a7c952af70677c0b21b90.npy +04379243-fad62f2339aefa8f9d86e5f05f1da2b7.npy +02691156-f680ee392bad2dca29348d14ca881f7d.npy +04401088-83dedc1afeb57e199edca1fee171b669.npy +03593526-f8ba5c5c9530a2d43dddf957f22bddb2.npy +02828884-9b7b628bc8cc7463103d45b529610c5c.npy +04090263-6e4ed358feb31feb27c767f081f1365a.npy +04379243-38ad5333308ec5b5f4b6538438a0b930.npy +04530566-eab41e8a5c5fbdff151300a2afaaffe0.npy +02924116-4293b7b9281953e74aa94fe75fa150ae.npy +02808440-d8c81bf718d534776b448b8aaebb705c.npy +03624134-c4851aee1af7d874cc34b900bb2492e.npy +03046257-f2d0906afe91c7ceff3e00f1a386bbd4.npy +04090263-973a961200eb14f1a64fa3a308f2f098.npy +03642806-9728d5d4ba7fc664aa4473b82fdc5099.npy +03001627-e9a16aa9d2ffdbe174cc0d9ee0d1e8c8.npy +03797390-d309d5f8038df4121198791a5b8655c.npy +04256520-e09005010542d8193d28966b7ef7a935.npy +04256520-3a44efd1fd14ea66dfa4ff010b8b9d1c.npy +02828884-8c6057a5258539fef155d75bbf62b80.npy +02691156-91f3ccba290da90671d03b466c72ce41.npy +04256520-1d19f508f104e881a239479de51795b2.npy +04379243-bbae4abbff206a2a14038d588fd1342f.npy +03046257-1d476f6d585baf62e1292650537a7c1c.npy +04379243-2e5d2487b7e1b708e4f659f0755a47a.npy +04468005-ece4c9bf30e601575068939b1e366148.npy +04256520-1193da9a06f87fd6a0064771a6f2cf3b.npy +04554684-6e606fb36a1fa72370011ebcb36fd95d.npy +04256520-4e25ae1d1ce18c4a40ef1c8b63a628f9.npy +04530566-f4aa1a1c7216fdfcd3d8a17e1b074875.npy +03001627-d50c5777a2727679b247f6fe3b8f7af8.npy +04256520-e8342d53ae929341b6feeb62eb9d939b.npy +03593526-6488a88563cb1f3b2dcb7217e1ed4196.npy +03691459-3b6f73cc36cdabd2b3b44ad99a214777.npy +04379243-16aca29aae2d252cb8372f06f79c32ca.npy +02933112-e22f10f551cac7fc6cb99ff1a702c4e9.npy +04379243-3d6e337c521f73f3fe222bdfe4498489.npy +04468005-923313c1b085c415706d1c54190f27a.npy +02808440-6f1c542f24b8e50554d7082b34825ef0.npy +02691156-4a21d3920b11cdbf1592d7a04a86fa53.npy +04530566-7aeadfeb93825b387b3c166137b0d772.npy +04379243-1d6e0462e30692d8492d9da2668ec34c.npy +03085013-fb6ee1aeefa551e188e2183678696c9a.npy +03636649-d1dc19013dca2182536407ae4270b9be.npy +04090263-b65ba6d3f77ede2d79aaabe4686a1aa9.npy +03337140-ccefab3547696e1791c352d02061b3f7.npy +04379243-e2930bd9b16db2a80d6227ff9b21190.npy +02691156-9267c510247327a2297d46b42718e32f.npy +02933112-7941cfe08a5288337a3bc7b2417286c9.npy +02691156-6a242ce20c44e82bcc14f1e6f4f4f49b.npy +03636649-e7b9477eaf6e2b64fe755e3418b63110.npy +04090263-8e27088dc71b89f9faea005b8f19889.npy +04379243-337479a0afb08dc91933ffef19678834.npy +04090263-74b14a0da86ff0b6e1f2a1daf140ac9f.npy +03211117-e4f34d5f5cc64a85f2e5d34c7b677bc4.npy +03991062-620fc0a4a978ebf870e620cd439a45f6.npy +04530566-99102724561012729ebc23acefb248a.npy +02958343-a166f97f10557feae7a7d875eac9a93.npy +04256520-4b139ceeb56ca3a1991d32d5bc1065a5.npy +04379243-db9458fd1459982347b1b3e368e511da.npy +02924116-6a202c870a278b131db751af8df870f4.npy +04530566-b1b5e16d0c96f34c46b7a006accd201.npy +03001627-537c7bd16e8a00adbbc9440457e303e.npy +03001627-a7154b3c2b2a0641a9fe1734a6086750.npy +03636649-6d8cb53f3b1cd94a4da9b199f21864cd.npy +03636649-3e7ef877f826230dedde7b5a5ea6d004.npy +04256520-28ce909659a826d1599dcc439b161a52.npy +04379243-fa719ece51c607383f3fb2f375c18a84.npy +03046257-e37eff8f127dbaa9902a571380e15334.npy +03691459-67967d0213be8b199fa004564ade09f8.npy +04554684-8fb4749a25eca524cba07fb2573fff75.npy +04090263-a4046d9996609d50b8b37cfdf060fff.npy +04379243-fa4d09b10928d8322685733c782593df.npy +02691156-ee0105d05a5007ab827afb33b6d5eec6.npy +04256520-15d59eaf24645f501030665054ebb2a9.npy +03211117-ff62121443345bf76cff78602fbd834e.npy +03636649-2ceeb17225f4e460d493bfe20f94b6ab.npy +03001627-653c0f8b819872b41a6af642cfc1a2bc.npy +02924116-8abad4c89c0a7333a6a511745136dc32.npy +04379243-16ecdb0dcbd419ce30bbd4cddd04c77b.npy +03211117-8399366b1dbe22edcb349a60fd15aa15.npy +04401088-407e5ee21fb23fd92ffe71e0e78fe3b7.npy +04379243-1f2fe0bf66eba0b03968da786c4da00c.npy +03642806-7a4342f61ed7b153341aafe10fd0cbd4.npy +03001627-54f13fbf4a274267a50b88953d263a42.npy +02691156-2c9e063352a538a4af7dd1bfd65143a9.npy +03211117-d5b088ccd7d1a7ba8e2d66cbf6a91063.npy +02958343-8fdc090f498ddb39f63ee8a34069b7c5.npy +03001627-cdfd278e8b1c11bfc36d58d0f13497a0.npy +04379243-45b4df78e3cec0d99860e9353bb52a1.npy +04256520-8d91786e13808f73e4248277d408e4b7.npy +04379243-ebc82e7df36f6e9a33963916b86d221f.npy +03001627-4cc17e003a26a3d5eea9006d9d8918a7.npy +03325088-27588aad5d5bda1fcb6036d6e778885f.npy +03325088-e8d35278a035f50d14b35a7d7cea7130.npy +03001627-17b77403b80de623f1783a44a88d6274.npy +02691156-165c4491d10067b3bd46d022fd7d80aa.npy +03467517-913f3c90f5b78256e98e318d424a4bb9.npy +04401088-74dd744f5c5b9d132fb56cff2a0f826.npy +02843684-a36e1456c6d68281132a08135eefe76d.npy +03001627-d6dd3de6d6ea6d0b1931ace01cf1b948.npy +04468005-3df90286fb1158115ae1d71af1bb3fed.npy +03467517-cd80049dc2c99ce0f75374472ac71de6.npy +02958343-8c2430564a8e3a2354277bd8a941f068.npy +04256520-f05f6b3e7c0afdb352fc7e973ba7787.npy +04530566-606b512701e71ef6fb80910115d3c39f.npy +02924116-42aafaab0612f10dbce4c69e4f1ee611.npy +02933112-acba82ca76cb0201774bc00c294ec5e4.npy +03636649-8cc8499cdf11e9fc1735ea0e092a805a.npy +02808440-e37fc3b3ec688a44a451f23dc98be5f0.npy +02958343-a49041daedac3ecf2fdea40a56b4c57d.npy +03211117-df35d335e76abf5618ba239e198ef2ba.npy +04379243-1f267da10062622092018116c595a95d.npy +03211117-ecb3d57cc0e8018f3f6b4923416758fd.npy +04401088-2163366f7c3a7a0e6c63b8b48495261a.npy +02992529-17d4ef9fa59ede481cfeae953cc2339d.npy +03211117-d9b7d9a4f7560f6ffa007087bf0a09.npy +04379243-425ccd56a558a719754784b56fb4c23b.npy +02958343-d000ef0c691489c9801b0db1d49ea10c.npy +04256520-ece3f9c071f7ab04bbc7a6acbd8f058b.npy +04379243-5fe429691ecc5f0311e6fe968f9f8b0.npy +03938244-7c1194c82d28663d7d910d51d878f708.npy +04379243-63ca298a0bc7dac4d1f4a577576ffb5d.npy +03790512-86b8e4e5ed18fe082a45a87054fa7272.npy +04530566-93304640e3a2a60d611cd70ef25f5235.npy +04256520-664a84b65396e168707aff99601b0e71.npy +04530566-c6e36ffba5630fcd7301f2b895d332ac.npy +04256520-93b421c66ff4529f37b2bb75885cfc44.npy +02828884-6a237c1e61fe2bba8490246570868c8d.npy +04401088-72e61015d1e4fcee8739b6dd0f9695f.npy +03001627-9343df9a7ed6cbba1923501fcdd899bb.npy +02691156-a9545fac33430c6062347b4731688b0f.npy +03797390-c7ddd93b15e30faae180a52fd2be32.npy +04379243-314f35827359105d6faea4ea390b4428.npy +03001627-ff546450fb0bd81f6e7c5546c1dbd220.npy +03001627-c5d880efc887f6f4f9111ef49c078dbe.npy +04379243-92bfb87451cca049febad4f49b26ec52.npy +02958343-9e52d425db48a33bbda733a39f84326d.npy +03001627-b9908906f1e1f65b8e800d2aff155191.npy +02828884-ca21ae1c48c020db1a7fdfcca5768f88.npy +03467517-7eac9185f94e7be35fd682b25025f90d.npy +02958343-5e4a1ac9bdce2766473f10e6caaeca56.npy +02992529-901a0180abe1011b3c629b56d283e7b8.npy +02880940-e3e57a94be495771f54e1b6f41fdd78a.npy +02808440-47f169c6aeebd2665f9b40f981270a7b.npy +03001627-6f70a7948c59b49943da6ec23cebe068.npy +04530566-7bfd756573de367176098e230fa177d.npy +04379243-7a22339a0b7dd26aee088de33038f12a.npy +03624134-8d777e28695e8bb1b036a5cd72ed9d11.npy +03636649-551bec14757bd4b27b79156a61ad4c01.npy +04468005-9c1dd6638cbb2ca05ac4d0d3890f2d0b.npy +02818832-e7d0920ba8d4b1be71424c004dd7ab2f.npy +02958343-5ad82d706e57607ce4b68d3b17c43658.npy +03001627-9c68011042990da3abe36bab1da1fa35.npy +02801938-9d0428e82fee9fba50da8b99982a3057.npy +03001627-2c14e910ad4173a898d5fc0473d00a1c.npy +04379243-98bab29db492767bc3bd24f986301745.npy +04379243-4058207a9467712966a503e0f1ab5917.npy +04379243-9a1312e39df01dc1d44683cb4ca416.npy +02691156-9c7395d87c59aa54a79f2ed56427c6e6.npy +03513137-709348783d9c30c970290a7176ca24df.npy +04379243-cd0581de9bae7c6c7d1aee311ce12c70.npy +02924116-f08b481b079d9c18ad19b94b8069bb8b.npy +03211117-ffa987a79bc96e869e23f6fc87a31098.npy +03325088-a2a6c837e09bffcd76c18e71fd49c4dc.npy +03001627-2bf1fdef16967a929753496ba23f2183.npy +04256520-e3992b75b446fb5af7c7ad2549a1b15.npy +04090263-18fdbd5f5448e1eb9556d0a8c8dea494.npy +04530566-bc9448e22c2379d487f08fb94cd2785e.npy +03046257-332ef2906bb304e8b0aa15078ea6f391.npy +04256520-a841d5d39c5ddbc28ec45320afaa5d0a.npy +02808440-44bf3d065ab35d43b362845c6edb57fc.npy +02828884-94bd6118c10de515d201085e80edb26a.npy +03467517-2d767b3fbb8a3053b8836869016d1afd.npy +02958343-83f26e6b8298c3a0a134736201a79843.npy +03636649-7603ca578be87f24b48d582908a164ed.npy +03001627-6e9a3650b8ff39a02dae74041d029566.npy +03636649-1b35827236954b2bb6436276138aac1.npy +04530566-d8ea840a28472e04954c06f15cb2b5c8.npy +03691459-58d0623bfc9043965c3fc20f066d524.npy +03001627-5042005e178d164481d0f12b8bf5c990.npy +02691156-47fe79cbf9d6ef36dc3607950feada54.npy +04460130-92e4cc97df1ebe141203ec4ca6ccf208.npy +04379243-d5d7324c2233d6edf51f77a6d7299806.npy +04090263-18b4acd3b0809e6fc14e2939682bc455.npy +03001627-287bce5664e168fd744dcb8aae5f2395.npy +03001627-2a28a1658e9b557062c658925896f75e.npy +04401088-16ac60220ed738901cfeae953cc2339d.npy +04379243-a713adfd7d82df5bebf5869836d37497.npy +04225987-463434d2fcf567d56a93dc68b4021dbb.npy +02691156-1c27d282735f81211063b9885ddcbb1.npy +03001627-7d59399c37925cd7b1b9d9bf8d5ee54d.npy +02958343-8e7475bb6c54d39f398bc3e9fa82bf3.npy +04379243-40a402e1d949364a104ceb84075e40d6.npy +02871439-5f1abf912782e0d7350be33372161c1b.npy +03001627-3d267294b4a01900b04cb542e2c50eb4.npy +03759954-e989a2cffc4d967bd80ce3f2fd66be0.npy +02958343-398a791990b106dda5a4c80d90b70728.npy +02747177-2ce9c6ec2d071187ad5067eac75a07f7.npy +03797390-896f1d494bac0ebcdec712af445786fe.npy +03001627-ec5d90a37ec99980e2b417d08f69e019.npy +02691156-6459a6977cce8f8789b0d69aba91f1ef.npy +04379243-9928c36919730b927c077130cb57dad.npy +04379243-d7d732d0ad7537eb610c2a68437007d6.npy +04090263-782f3821e6b638d6fb6bde4b7e6c6613.npy +04379243-a31867914b71ac40d776c08b6a3d0a38.npy +03948459-ca012a47cf5efca23f9d84f9a87a44e4.npy +03001627-dfa7aa13ee696833593ebeeedbff73b.npy +04379243-16f603525c5ce57b23f7198a00163bb6.npy +02933112-45039a5ac0912f8523d871b44977a702.npy +02828884-68d603f0483f4f869bd9ce04b3b1fd54.npy +04090263-76d55781aaac09f918b61860f81c82f7.npy +02871439-959c45c154559acc6e1ae929b00acbc4.npy +03636649-99ab3dce10653cb7f4525a0066419a00.npy +03001627-cb78334a5ad9517d7a31dd5af93fdb5c.npy +02958343-bf652fdb40c4cb3696ab9df3b3d7537e.npy +04379243-82e4990a3a9290f33ffd3a8003988fa3.npy +02691156-6e5810d6fc96e4a7db73445864b72015.npy +04090263-253bf52d80c11314c7d00c29d97b78a9.npy +02691156-c0375c2ce28292d9a179137acc8d4437.npy +02924116-2ddf7274d729c372c98c13d6112727de.npy +04090263-e6017a1e15095b4e6314c3b6a3a65519.npy +04090263-4929111d16135ccf613792009f64ab4d.npy +02958343-d09039d34746615fbb164ad50a9faee3.npy +03001627-2cf7ccf97b09187fcb7547c95fbdff26.npy +04401088-3ff176780a009cd93b61739f3c4d4342.npy +03467517-ef4fd97b0605d39d3f1082c2ac460e88.npy +02958343-36f17730152ac28116abce8cb03e7794.npy +03624134-102982a2159226c2cc34b900bb2492e.npy +04379243-95a7581a491d3706996336ab975e6575.npy +04256520-ebba3b7239bd43cbd4fd21ba7448467e.npy +02691156-53edcc6832e776dcca8607f540cc62ba.npy +04256520-3eb9e07793635b30f51f77a6d7299806.npy +02691156-d01da87ecbc2deea27e33924ab17ba05.npy +02933112-d3759f1bd6dc9652f51f77a6d7299806.npy +02942699-73b02fe7b4b2e45f74cd541b34c6124.npy +03325088-bd23c02e78913855b362845c6edb57fc.npy +02828884-3b7fc97192e483ebb0bf045ee98272fc.npy +03991062-5091d2d8b43472ad4182a764d1311955.npy +03948459-a2ae72e791228034e209cfa3a83f54c7.npy +04379243-a54eeb7ca4dfe0bea71c812e027f94d9.npy +02942699-e9f2c58d90e723f7cc57882dfaef8a57.npy +04530566-24a0d85f723fed2d7f332834f123f44.npy +03636649-32a196685d10bfcad7811c9daa943fef.npy +04530566-30cf2b36478a21ee701c1f58e22b85e8.npy +04379243-fb91ba29b46a519f8f37c398c1a74a0f.npy +03001627-94464e51e6f3be07f9443c9263f2354b.npy +02691156-7cfb337744133ea1bd46d022fd7d80aa.npy +03691459-9785f01a6ee36e6d874a6a37ca17d9ff.npy +04090263-4a9c2632d6055fed735fa1ab17311ec.npy +04256520-8e61d151220b5397970d4dd67731c543.npy +04401088-112cdf6f3466e35fa36266c295c27a25.npy +04530566-d45f39e14c365801892294bafc22e040.npy +03001627-a1734a851af178bee15475f0b1eb22aa.npy +03691459-d337b40eca9f87259fd3da8ff7252b25.npy +02691156-d220ffb04a5ff31abd46d022fd7d80aa.npy +04379243-ccf3a20e438ecb09384512f195951058.npy +03001627-8daeb5877bba8cf5936c7265c890fef.npy +03001627-36843ea8984df5a63719086e0b4ab8be.npy +02691156-530d0edd6e2881653023dc1d1218bb2d.npy +02958343-d2b847baf4a6d1a5ff1370452e3a0154.npy +03001627-22fe855981e97ec5a1bada754e9e91.npy +02828884-c541d59409647408ad5067eac75a07f7.npy +02924116-98ab95c8a34196e1894431539dc5c19c.npy +04256520-1dab0c0c72f9cd6f593ebeeedbff73b.npy +02958343-7c0bad8b2b62cb7c673ddeabdcc8c6e.npy +02992529-f1b9de7276c1b07fe5562f06ed322f7e.npy +02691156-cd9062c0065ee3a4727e0d1e650e3b69.npy +04401088-6adb3426ac55ba827efa8dff0d683ef7.npy +03001627-c16a1a47bf34a84d157e7edaf1e3e602.npy +04379243-e3cb6cc8df6f7390d1a63a2e2039ff73.npy +04554684-cccfe2cec3069c449c72dfe3cb318a90.npy +03001627-3d57e65ff4cc42df70a7748e958c62a2.npy +02691156-8ff8f3c845e7ae8443afdb9c81ff2967.npy +04090263-809d2439412bcdac896cb6094e2801d6.npy +04090263-ee5aede335490e0f76b7c600f9352862.npy +03636649-295ba9410657325f9d7f638b2b2e0564.npy +02992529-41f5caf37dafdecc5dcb6feb4bf8ce13.npy +04379243-a9a81543d5297d13dc20930e6fc85682.npy +04256520-deb0889d902f08bef51f77a6d7299806.npy +04330267-bda4558e0312ccc174dae1b41226ef1f.npy +03001627-2a1d80a0aa67ee7585d33ad8f24c4885.npy +04379243-5aa83cb8217619d9ed8de30c53213f6f.npy +03001627-ce074e18e988a481d082d95e9bd50b49.npy +04379243-272a4cf3cfff3eb1e173cee47fbaa88.npy +03046257-5ffbd3bcc935279a8cbe149774a11d9c.npy +04379243-e35775e1f550d3d65339eb67f6086a2b.npy +02933112-47344f869d6c12e486d53ab0fe94e911.npy +03001627-593f7c848e6246ad8c37cfe791015e2f.npy +02691156-e431f79ac9f0266bca677733d59db4df.npy +03001627-5f30af30db19dd23afd330d4b2aa45c9.npy +03001627-5c247c042e5fa6077b712dacb1db0737.npy +04256520-3c30c45a5ba3b535f564f8e3eeb8449e.npy +02691156-54066a3cdb79ac8fa5cbab5aded19a14.npy +04530566-bed3fb84c9b876f930d7c2b672980ace.npy +02924116-c7547c076d6c51d752470de2774d6099.npy +02691156-6fe837570383eb98f72a00ecdc268a5b.npy +04256520-470dd8c92aa1b9ba593ebeeedbff73b.npy +04090263-783e6e45a8b4125b29ac2ce4d16a7d50.npy +04090263-389370f7e03b6312eb73ff4c9e061b8e.npy +03001627-5b0e833cf2ea465e42bd82e95587d8af.npy +02691156-461891f9231fc09a3d21c2160f47f16.npy +03001627-f93bbb0ae5d66c075fb57c89160d1cb7.npy +04530566-3d33ac667a885a1a7856807e3e4b01ad.npy +02958343-7b067be3aa39b1a124853ec273f6c1d2.npy +03001627-780aec25d416fa07ca9b40e76e725878.npy +02808440-3bbf438a17d77cbe3321831d2245cf06.npy +03211117-f3a03a173932c42b4b9b715645ffbf22.npy +04379243-b1850a02aafbca6aba18ade30e563d37.npy +03001627-6af67c2dcb4c38bc67f0a77fbca7cda2.npy +03046257-4ca5e78eadeefd8651c1709f78d865ba.npy +04379243-9f56c17cafc1ba35bcf7c2310bd3f83.npy +04090263-b6cd61c71fba44d512b38b1d99376c0b.npy +04256520-4cd5a2a90a9bdd5eec2fdb822d0e9d44.npy +03797390-7d6baadd51d0703455da767dfc5b748e.npy +04379243-2b1684e4cb37d9e8ab541fe336214393.npy +02828884-4cd23aae912b7de019fb4103277a6b93.npy +04256520-6a62d0d3c8eeda396ba836372832f055.npy +03001627-e94089cce370e7d1aae894b47cf9777e.npy +03691459-82b9111b3232904eec3b2e05ce8fd39b.npy +02958343-45f0ea3cd0df8624e341b5704aa568bd.npy +04225987-792953b4101753c6ed3696d854eee1ec.npy +04256520-725041f78f7c4274515d5d6477915e98.npy +02958343-93942ab3fc970415c596a26318046886.npy +03337140-c328da20f2af4eb14c3aee8e9d3a6ffa.npy +04256520-b53bbce3774bba2f5ade1effc174de.npy +03636649-7a1d06ba4fec22e8dac42bdc1d2df4a3.npy +04379243-645500232eb286aa8f6d69f1a6681149.npy +04379243-4bb4904b8f4c7f8b0e5927ab4191382.npy +03337140-2731349879db84fc24517c38da518f49.npy +04090263-d05f6ac929eb1019f5cbed688a0bb106.npy +02876657-7f5db4889a433ce5e7a14f6d159dcd47.npy +04256520-4c6f6eb326716c8fc71d1873c074ffe5.npy +04090263-3d0b35ba89b8c600efb47d8e2c9f3b57.npy +04530566-d7fc7ed59558b7b3f3e39f2e17005efc.npy +02691156-6859dc976c0528a831fec775e1dce6b3.npy +02691156-67a6b5b12ba64c529a6e43b878d5b335.npy +02828884-d23ca8dad2064c4ad5067eac75a07f7.npy +02828884-d3a5134df6cd94e2e8db995f7899d418.npy +02828884-621c4fcded12fff2d07d128adae16ff.npy +03636649-5c5119a226e1ce9934804d261199e1bf.npy +03001627-6ec4d5fa96861bcd70311dea98ba710d.npy +03001627-8d2a4106de2e0e9f952334e469766710.npy +04379243-6a3e7d05a7ceb4e1a3df3190f4f32918.npy +02691156-c5143d3be7f1d0eb27745e9b6b461e93.npy +02828884-7c3314a24702128d19fb4103277a6b93.npy +02808440-5bcca919768845bdd0043cfa915003ff.npy +03593526-3879379848c2c0c55b2f23b9c7b146a8.npy +04530566-dcaf4238da8ef379106f24d0bacaba69.npy +04530566-6737f75bb87e3cc0847c4e55bb965ab0.npy +04379243-8d9e1624c85dc88621bdbc0445d9f748.npy +03624134-7e0ea29ff4fe153fee2a04c68bc263be.npy +04256520-b6694e5bb51f8861f51f77a6d7299806.npy +04379243-bc6646a52843dd63474659fc572ff56b.npy +03001627-ce1237c5ad42dd7b737a00f007529fbf.npy +03001627-d409dbda0a34a953c9020fbe6b2ff6.npy +03001627-a2eaec61c28670a459b42406a4cdc4b3.npy +02924116-54de13044a09529b3b16ecf86da2e780.npy +03001627-c54aa12a3d8c34e2efacb264ebf1ec75.npy +04379243-335bf5e7f636ea198be1375d26d1cb89.npy +02876657-46b5318e39afe48a30eaaf40a8a562c1.npy +03001627-3a5c8d46fdc6793b956abdbfba57903a.npy +04256520-53812514f0d50568efc579970fcfc006.npy +04090263-74a38b74bb57a2af6a405aa597e7fe24.npy +03001627-fad907934656c52ba1abaa6eee3840a6.npy +02992529-4a7c0d263fa0cc119553267f4c8c48a8.npy +04256520-f01f6f88519a58e0e015ffca2672af29.npy +04379243-1abed35643d34f60afed86cbd9fd5335.npy +04379243-f5f7ce79ef61e0ff3f0ee3307f850b4c.npy +04090263-a51c1dcbed07d1de27be842e82df28b3.npy +02924116-9af22616a6b5b59326fc4e4686c940b.npy +02808440-9a4d71b2741f45f3afc9f2442d869509.npy +03001627-e72bad036bcc04ea3f68fa735d443de2.npy +04256520-3ce2794845ba4bff5c63d035d2a7c889.npy +04379243-b7bd6522f540436c23500a5b036df62e.npy +02691156-f7110ecac70994a83820d8f180caa23a.npy +03001627-82979f3a00ca7b5b0003dd98e70da8e.npy +02691156-729aa8cba8e1398a43afdb9c81ff2967.npy +04379243-b61984e31dfb04c1d1d031a1b745cd85.npy +04468005-45920718b96cb262ddbeb5a3d249400b.npy +02933112-c11449b64486b4df4240b2500b599345.npy +03636649-7b53493f7944fcf2b691e708071fb777.npy +04379243-2e2a612aaeafebd5ea23ec7dabaae1fa.npy +03211117-bdb87409ff3ba876cfc4c39af557e76e.npy +02958343-ccccf7342390d139ff1370452e3a0154.npy +04090263-305a895b0b06808b9d5aeb7097eddbda.npy +02691156-39ae262853031e42aedf20f7099e25c5.npy +03001627-fd5492b732f41dc3f7628281ecb18112.npy +04256520-5d9f1c6f9ce9333994c6d0877753424f.npy +03046257-4d804d5f4e5d87e88d84bad46345484d.npy +02933112-1ff28690a2ba31e4da5feafe6f1c8fc.npy +02801938-5c3dcc9b312de5b5a5d9ad16964840ab.npy +02691156-b174db77afdcdd055b2a16b1d9c48e6b.npy +03001627-52d687e4f4c59dd72535b68a1251d8a8.npy +03642806-a01beb9be51756f3a507c96c993b141e.npy +03691459-3dc77d756da1ff5eb3b44ad99a214777.npy +02992529-bdcef95e8efb2665408f0e810863705a.npy +02828884-c104f4e4a21ef8d42c29915205c35b65.npy +03790512-8bf620bd023c602b74f7bf9c15b075d9.npy +03046257-31d2d0a213bc09b33c2e50348f23d3d.npy +02691156-bc2c90ea00831423908b15214255bff9.npy +02924116-af060666a0e474adf59ad08996c77e8.npy +02871439-d841664bb8c7b842cbf15a79411ef31b.npy +02958343-fe860c6a74a86905468bac13e007a6e9.npy +04256520-22f89fd9e2a9f1a6bb6bc0db07c71e8.npy +02808440-61a7615cde3ec86a2cb48639eca80132.npy +02691156-5aeb583ee6e0e4ea42d0e83abdfab1fd.npy +04090263-4d772170bb26d40ea36c408ff083fee3.npy +04379243-9aa0b98bdeafacede76bc197b3a3ffc0.npy +03948459-74264c103701bcc23baa63499ddcb388.npy +04379243-3d7101bbd994e2f5296ea8292ef2edbc.npy +04530566-aba35304010a7ca093f1a6337ed3a54c.npy +02828884-2e2518a8a2f335ae76bc197b3a3ffc0.npy +04379243-23506d31a9ba77201b54d8d0b255b88d.npy +03337140-3bf437403138e6c9aa669fbe8e7a7c4d.npy +02958343-1ba30d64da90ea05283ffcfc40c29975.npy +03624134-ae7744b9e5bb5a11e9ff7117715adddb.npy +03211117-3899bd2eb8f9e9d07e76a21e51d48a61.npy +04379243-58bfcc581879c121b20808ae6de0ac93.npy +04379243-9ff98fa1fd750053cf853995b84c068d.npy +04256520-45963319edb54bc0dcb4d348d782a96f.npy +04379243-bd14692fff933409856ce0c2a704bc40.npy +03467517-a7c0bad6e907cb8793f0194265a9746c.npy +04379243-cf2ea610fbafece363944951133f1c85.npy +04379243-bef379d51df02d5fdbcb30b4afc25496.npy +02747177-37c9fe32ad87beccad5067eac75a07f7.npy +04379243-ecf3f077d30540fe5d5ac0a8c21f0bd4.npy +03636649-3c4d8c4ebe9dedbc2cd2160e449d45ae.npy +03001627-1e0580f443a9e6d2593ebeeedbff73b.npy +04530566-135a15f938c824ff90e2484c52623a2.npy +03001627-7e2b07c0ebc5781a297936c81e7f6629.npy +04379243-7e1d0214a916543b37b2bb75885cfc44.npy +03211117-7467b25f70675892d50c22be0354e623.npy +02924116-3858580452682f43ac1817b697e11672.npy +02828884-f57c2037fdae635b29a9b1ca9709749e.npy +03046257-32ace01a69fa498e177ef3150c947f22.npy +02958343-e9c5e6d46c47129c5b72003cd427d0c1.npy +04379243-6d09606aeb54b55659a44e6453790000.npy +03991062-dd2f38a2acf5334781cf48bf3eca784c.npy +04401088-c56262f4a6a7fbe5fcae16e8230396f7.npy +04554684-73425393306ec8cf46d396f47f99de3b.npy +04256520-98f43bc0ca2c510ea12caf23554642ba.npy +03001627-d31ab2866270fb1c19fb4103277a6b93.npy +04379243-8a63086a3c861151ce2bbb5a9dafce04.npy +02958343-3c97b002e510db11e23d60a1b706b44f.npy +03001627-4607280c3a4286b7319c7c751f273141.npy +04379243-214374134d21f90354482522828e74ae.npy +04379243-c2f870eebd0ac7494719088c8e42c6ab.npy +02958343-791e45f93e9ba58071a126804ae24042.npy +03691459-57b8d08d37d835995d0dded52efeb4fd.npy +04379243-fb4d877cc4f2c63b20768660cf080d12.npy +02691156-300a0c78e402decd7e67bd3e242c324.npy +04379243-f84b49a7d9e6f31ae0c8359faeb78bbe.npy +02691156-ffce3c994052ffea339b6c8cc24f619d.npy +04530566-61df71a58a9d0161202de8d12c6f7633.npy +02691156-ebd991666f177f8f575bf8a4b14be4f4.npy +04379243-8574daf4d23e75da042d36b1c1b84.npy +02691156-2705c3edd082f0987f1f82f6fc8747b8.npy +03797390-3c0467f96e26b8c6a93445a1757adf6.npy +04379243-7b411de42d4960eb6e25f3efedf6785f.npy +03467517-1860264e320c7979f4baed97c2afc4fe.npy +04379243-b48d04aae94702504b3c42e318f3affc.npy +04256520-d7a7bb6725ac5248febad4f49b26ec52.npy +02818832-f6d07714c090b2afc6c1b30c2119b092.npy +02828884-1ea895308f2aa98f966097adcefba56.npy +04379243-83248f27f069f0fc8312881285c04cb3.npy +04090263-313c2f35e1c461219f433921788191f3.npy +04256520-8f71670ddaa954c963860d683ccd0da.npy +04256520-7b76ae65480d1312538c0715f23f94d7.npy +04379243-1949b4cd6b88fa0713a5873d239ac557.npy +04379243-9823679747e563b4d42b9650f19dd425.npy +03001627-60cbca441e3f062444ac83b3e97ad658.npy +03761084-ed20db84209663b0c22f3fca4a074c25.npy +02691156-e59c4f290d8585a862b600da24e0965.npy +03001627-2b4f2fc77c47056eaefb25a27e962525.npy +02933112-e4523c675fb6a103d08b0f17fdc8a28.npy +04256520-b5c6ede83e55d05048f174663905cbff.npy +04379243-54f4d28ee9986b329a1a0970b4896ca3.npy +02808440-e3779000fe8c6805ccd0340812259a39.npy +04379243-3a7fb4cf118c30d36f3d2b1b15fba494.npy +04379243-dcf246280361e20d1bf2b66b52bf6885.npy +03636649-b0a3cf1e09f7a3591c1ef519b9196b63.npy +04379243-22add506f2a09c8dab93f6188b226527.npy +03467517-5d27923586133803ba3161efeed0ecec.npy +03001627-228d5702c588fc1cf7628281ecb18112.npy +04090263-6af8538d532e44237b1f1d03ed22f671.npy +04256520-c474bd0e12d386dfe25bd42000b74e3f.npy +04090263-7bef98c5eb45b13c6c1e54aa8170142.npy +02808440-f1395152e42dbbb33321831d2245cf06.npy +03001627-ab62680f067bf94dd6a6b5838ef6b356.npy +03001627-e04ceec8711a6027a6e27bc066049db5.npy +04256520-a32e10cb422cca67eb9f96cccd63af6f.npy +03001627-31fc10f348cdd2f77f754cef9da1323a.npy +02958343-2bfea38242ba63cce77aa0b62eed1492.npy +04004475-79281796bae975956751803240e2d3aa.npy +02958343-1104f0924e03f2b6fc5886e868449015.npy +04530566-3f3912cf68cd28eed7259ae7450dc47b.npy +04379243-a47fcd8bc5aa29dc998473a1ceac4e95.npy +04090263-f79014425f660bc4d93d9e447c233c3c.npy +02691156-7206b1f248826f2398b39d2f77aef0eb.npy +04379243-2eb880249672bc2386b647696ec80093.npy +02828884-b997659a319cae6369923f7b2ea9aba.npy +03001627-79be636f7f6b66724fde46457697d80.npy +02958343-12f2905dc029f59a2479fbc7da5ed22b.npy +03467517-77f178a2b61cbd1e76d05024fabfa1e5.npy +02828884-46cfcb7eb682d16d2b12aa6a0f050b3.npy +03001627-dacbb2d9dad289b1492d9da2668ec34c.npy +03636649-99d884a5b3a6677bbebfb887e83028e1.npy +04090263-9c4ba5d99727de4f737477c115ad5b33.npy +03211117-f34958255486228cd174bb92d075f795.npy +04379243-606b2e47238b02178c37cfe791015e2f.npy +02808440-295ea26696a0e45b3c5aa738749715da.npy +04379243-5db80b2854ccfb6ae2b372d25f6c9482.npy +04225987-2026cbe0ebbe1153d975109d955e6652.npy +04090263-5b1434e9b907eab76bcddb6c0dc071c3.npy +04379243-adf574f947f00bdd548b2639ebc3e759.npy +03001627-ef4e47e54bfc685cb40f0ac0fb9a650d.npy +02958343-26d201a532879a60a7fd25564c2e888e.npy +02691156-b7f6e94ddb5ecc2366cf1b4a8fc3914e.npy +03001627-83d3b40a6ff6a04af4b6538438a0b930.npy +02958343-6749e5a1458ead5abda733a39f84326d.npy +02876657-30c6b5511ff09ac33526ea1c3de37e7.npy +04090263-3c10faabf2ff5415ee72fba28fa8d35f.npy +02958343-1b94aad142e6c2b8af9f38a1ee687286.npy +03691459-1ac22719af776fcea2626afcc786d93.npy +04530566-7d2194fb89c42da8ae5c852356538a5e.npy +02958343-206e39a5f67f4a4a81d0c86cc18e6647.npy +02828884-3e5f4d788fcc628f442b181d72d9d1e6.npy +02828884-f3e13747a652b96bf5fb97c1f9661c61.npy +02933112-b184de34d988236464a7317444d5a8d.npy +02933112-1b92b53bdb962de337aa612844f43db0.npy +03001627-fa6a5806956d82aaad484915511ccff6.npy +04379243-1d19305840960acde220a4c1303a51c.npy +04090263-8c9e592c95f95e7c9a6e43b878d5b335.npy +04099429-ca746c12c01a09b58db04a0e4b407440.npy +04379243-94ffc8179ae6bf8ddcfd6ca2b952d624.npy +03636649-bafc295a6ffcb375c3d3652f80cdec64.npy +02958343-192bc73d5825bfc7bda72093f9b5aa73.npy +02958343-14330011009dacfed49701eac14326ae.npy +03467517-2ab76c46285aaccc6505b7589f976309.npy +02958343-92a718b74a2e5e84fd2d6c7ed5a8dbd.npy +03928116-934d437cf82c0de5cfb9b585aa85fffd.npy +03211117-e1d73ee44f1d2422b5fb024f65f6da.npy +04379243-2a88f66d5e09e502581fd77200548509.npy +03991062-1a03376343b2e4f0c27d3c9a6f742a5e.npy +02933112-4b75b3d199523a91f8d6a4359d6a181b.npy +04256520-63e8ec717a68181fae1162148fdbcc5f.npy +04379243-aa96fdfe679adefb203eb08a0c3b4355.npy +03636649-2ac3b0a04514988e8c451c71f65d5dec.npy +02933112-bdb118e2b6c9f4d712de5317fe5b354f.npy +04530566-996c90952cfff5b24baa0720a34ff704.npy +04530566-67dd862f05f659c71f98035449adc4bb.npy +02933112-5f44807953f9babdaf31a22c7bed177d.npy +03001627-3ff53879d12a2259cf004563556ddb36.npy +04401088-1621e08661de948d7532dfb76fa58e9e.npy +04256520-2554d1db5fc9ebe525f8fb09254b26f9.npy +03211117-d59cbf752abeeb17f1a5dd559b550d68.npy +03001627-2c251c2c49aaffd54b3c42e318f3affc.npy +04379243-6c06faf4538bdc00b9e8bdc9c4a49aa2.npy +02876657-a118d15a0c74091e3ba6f328e4cd62be.npy +03636649-c4e8a6d40f6433928eb8d149efa4062.npy +02958343-17926c1ef484b73e6758a098566bc94e.npy +02691156-d5189c00524f662c79f9bc8b647dba0.npy +04530566-1c4ea31563b54bc8b77192b0405b4a6d.npy +02876657-cbc1cbc9cf65e9c2fd1d6016d24cc8d.npy +02958343-525c1f2526cf22be5909c35c7b6459c6.npy +04379243-5472624a2a130443e70021280aa1db1b.npy +02828884-b8ae866a44a272bead5067eac75a07f7.npy +03790512-a7554de7ada3163fbec38f8cdf3f0f2c.npy +03211117-538eebd970e4870546ed33fa3575cd87.npy +04379243-19b46cdd0a44286823eb3ad3d378722a.npy +03642806-ec3223edbdef2db93334fb6668ccd834.npy +03624134-850cc847a23896206cde72e597358f67.npy +04256520-1a9d0480b74d782698f5bccb3529a48d.npy +04379243-ddeb44a5621da142aa29e9f0529e8ef7.npy +04379243-7713f8a266cfcb1ee31752932c101137.npy +03790512-4fd8e8522a431781924dd6806b28c0a2.npy +02992529-fa1088998ad523edf85a324c5324329e.npy +02808440-275005a67aba33ca9d97e7b300a8d98b.npy +04379243-719c8fe47dc6d3d9b6b5a7b8c31557c.npy +04379243-e7058b820e66c9249cd431573238602d.npy +02933112-cf57b6a6baeb421c8c180d5d98aa66c6.npy +03325088-e7e03d363f0bb22376c18e71fd49c4dc.npy +02691156-e3fd510add7b1aa3c19eb6ab3736de88.npy +03624134-1e198106fd8339674e5a4dd299df24.npy +04379243-5ac2020b6b8e2c5c8e5e60055b9b9f67.npy +03636649-bb04811d84ec072130cc41b666fd9890.npy +04379243-f720b36f39f9dc0e5582a46a1071249.npy +04401088-2488bca663eab268d53bf953feb52e3f.npy +03001627-8c7d2eab593269f8607566378b3d8827.npy +04468005-7670f8aed98c8a653015b0b4292af7d.npy +02691156-6fd578ff0ad4f6e8203936772104a82d.npy +02954340-5eb9ab53213f5fff4e09ebaf49b0cb2f.npy +03001627-3d32d89db2286377e63c6421b71f17c8.npy +04379243-e7eec2839ea91f07df6cfab91d65bb91.npy +03001627-b371bb691811acae68d92632b2a01360.npy +02691156-f58a26c915e7a1dceae7a0fa074b4a2a.npy +02691156-6422d4a9c5b5b8f350361148ac946a05.npy +02691156-87d37c43f41871fb4dd260a1dd3357bc.npy +02691156-a61bb94e08709f2bd0734afa0d357999.npy +02933112-2a3a3bf0878f1fa4c59350d819542ec7.npy +03642806-a4eb5dea7eda6ab58e5480b52f7861ca.npy +03790512-3837c8ef573c2a7b360cf6eb12fae4.npy +02808440-dd49561080df1a3f798df87163b1956c.npy +04256520-605b9827489d47a14038d588fd1342f.npy +02958343-6cbadb3a39216f12ac6dec6f3725ccf.npy +04530566-19cbb5d8d74f8813e60e51f454cfc3c9.npy +04256520-2862150fe6816499130963f0203c947.npy +04256520-4ed87061082a0ecb273e86fe77f08a50.npy +04554684-6b5bd7b97b0fafb83bd5bed2701d5593.npy +02691156-3692c62cd29c6f1378a64d47db225ea2.npy +04379243-bc4167ab0fa22678e0fcc90cf126de96.npy +04530566-b7f288e9187a72ea5d3426ee101e9f8e.npy +03046257-e133ca5fa7e49536fc5a6a6856432614.npy +03691459-348d289b6a08e7b44884161c20b458b0.npy +04090263-c89488a80cba5fa5870906b5178d97bd.npy +02876657-b13f6dc78d904e5c30612f5c0ef21eb8.npy +03691459-39318878f6e98ed2150eaf7a4ddb8bec.npy +04256520-253ca4f655355b6f8bc1f8036e08e44.npy +04379243-1e588358e4681e1ac3bd24f986301745.npy +04379243-31af0afdf9d7bcf7855931d119219022.npy +04379243-5f2b41b50439518be679b7e0ecf5c9b0.npy +03001627-9c0c0e1a83243dde6f283df3449ca535.npy +02933112-7f416248bb57f1c0598f1102685df4cd.npy +04330267-f8c7e054fc46898a41965be83b7745a.npy +04379243-a6c91690dc96de97f1c28c9b4267c8f3.npy +03211117-88be1603c4e07fed6418651cc29befff.npy +02828884-4de8d632bae6b3719e76a83ca837d918.npy +04379243-47008a5646d3d84d85969b141e43f51.npy +03001627-d57c9aac973c3722197c43c7dc584772.npy +02691156-46d4d453ceac2f5c3c3b254d8683a766.npy +03991062-be681177e9540e4be4406b3bf37e6ffe.npy +02933112-d22fae260519b9cc52051c3ad59857ed.npy +03325088-a61075356271eb72979c556124bee033.npy +04379243-c65061bae7f351e419fb4103277a6b93.npy +03636649-c263fec31c8d33874f51382fa3549a00.npy +04256520-3d863a4eb22c548e9d4d5dcd2cc33826.npy +02958343-2cd119ce9ec61f1af63ee8a34069b7c5.npy +03001627-6ae92754a0a90af09eb811e8e20749ae.npy +02958343-669974eb491f2bf7f8883e486ec8cb7.npy +02958343-86fa16c6da908e6b44221994b043fd86.npy +04530566-68dc6f43a895e7e143909b9ada90aa22.npy +02691156-dfdcc024d1043c73d5dc0e7cb9b4e7b6.npy +04468005-3149e8ae0b352b90b2faf16541f353f5.npy +04401088-2c1cf34eb46756c1aa8ee930afa0ad31.npy +03759954-273e1da4dfcf82443c5e2d7fd3020266.npy +04379243-6fa2751d57a4ee44490ad276cd2af3a4.npy +03636649-fe02f6594ed8b96ae85a3dc26b76b2ae.npy +02808440-1e454ec01708c3b24c62bee40dcdc539.npy +03691459-65688eeafdf06f8752e2d18963a75b4d.npy +03325088-98aa4c5587088c4430397be0cba58a16.npy +02933112-cb9c0c90b5c6cc9c189d4f3a6cc879f7.npy +04401088-fe553cf733e29a349426aa93c5c54668.npy +03325088-3c38d1543ca1b63a9bdc22a1e02e82.npy +02958343-53502c15c30d06496e4e9b7d32a4f90d.npy +02958343-ef3ed9f139571826ce27281f3b76d1f5.npy +03636649-d6fb6984306d5197e96d94a67d9df99f.npy +02933112-7664b9208a84674926a555721514c9d0.npy +03636649-fd15a43ef545096fb6f5e7b313e4eaae.npy +02958343-db216ae493f303f35b4953d8add91f.npy +02958343-fe3dc721f5026196d61b6a34f3fd808c.npy +04530566-10212c1a94915e146fc883a34ed13b89.npy +03001627-11347c7e8bc5881775907ca70d2973a4.npy +02691156-d2c7b95823938833339bd6b570381585.npy +02876657-c1ebc4254a9f43823c0d2e0152e91b5.npy +03046257-ee6489d2d306ca11f04a4560b57187d9.npy +04379243-c3c467718eb9b2a313f96345312df593.npy +02924116-dba9527c3318d060973f659238edf3c3.npy +04379243-616a8ac7d1667a062c1a544eca74c954.npy +02691156-912d89d2d910a81cadcbeb54f3d014e9.npy +02828884-5207969c5c38875a6eca3a103e1326ab.npy +03046257-7a7d7bf03278d81854bec7a9a0a11b9.npy +02933112-bc1bca3cce664ab11fc2b865c2a185b.npy +02808440-6fe99f67b888794254d7082b34825ef0.npy +04090263-66c92d4b4cb90639fb5c1b0f759e2bc1.npy +04379243-2b51c3e9b524ddf560b5fd678a94e9cd.npy +03636649-45d24c9106f2cd7614cd86cb97af8937.npy +03636649-701dd0ee2f3c86502feae54a926ce14f.npy +03636649-66b98bb2b9d34431ec7cbf3284585a40.npy +04379243-da2a145da58d39c7aa5ceeb306445170.npy +02691156-a19a5a459d234919c1ccec171a275967.npy +02691156-29c0b705d6368b6ef0483511b875f0d2.npy +03046257-40f7ac90780052f99539294b73a00f55.npy +04379243-a49d69c86f512f5d28783a5eb7743d5f.npy +04090263-403f8de536d9842222b13c48c34706de.npy +03001627-182c47283b90d8b2d85934de5898f0b.npy +02958343-e0bf76446d320aa9aa69dfdc5532bb13.npy +02933112-93ee050394f3b15e3c8d0fdfb1cc2535.npy +03948459-298d300e70d6bf24e1f2a1daf140ac9f.npy +04090263-a9af1bb4648a448c8ff23e7e19499284.npy +04090263-f0bf5f36ac0cbb2b1a77229b9f90bf5.npy +03636649-fa80490adfa79863aa9da28fb4d9b628.npy +04090263-69e470b712063a2212b38b1d99376c0b.npy +04090263-9301403c048cc8a3fbd94d73a34fbe80.npy +04379243-675c225ef7bf4b4b3db912a90d289dfc.npy +02808440-7e6b409823580827a80d0ac32aa1e5ef.npy +02924116-f7c66493e877829eff8a739dd4de4368.npy +04379243-24b27de7ebb852ddb472f782e8890df8.npy +04530566-42b1b67e53c9a8ad14de76bc030c9322.npy +02808440-8b42485c93c122643321831d2245cf06.npy +02958343-e6581335186f5f6d8f01b3789ded1e40.npy +02691156-572cae68af04663cb145cb2b20ac87f8.npy +03046257-c2a14e7178f4153cf100868565cc78ce.npy +02958343-3ae62dd54a2dd59ad7d2e5d7d40456b9.npy +03325088-9f6a53de1239fd6f50da8b99982a3057.npy +03001627-44689408a7d879a664d56d7ed347e929.npy +04379243-746ceaf694d85eb5d5192f88466da1dc.npy +03001627-502d0f698e20af83de03ab2a27ba7531.npy +02691156-2349e4b9a4ccbd97bbf3143b1cb6076a.npy +03636649-2054bfb594262929a89fa001ff6369ec.npy +04379243-f76bddb92341f2a8a8a7283d9841addf.npy +03001627-30fafef5c734f926781ba0fdb47276df.npy +02958343-77a759df0166630adeb0f0d7312576e9.npy +04530566-2212a794bfca650384d5ba37e7a649b7.npy +03001627-50afe00f341993ae7d63360731b4227a.npy +04099429-c55fcaaf3301f97e978efdfd2ccd8bdb.npy +04256520-4e37752b33506d0313dd6eafe1477be1.npy +02828884-cb4389a968257a7dd2b12aa6a0f050b3.npy +02691156-23616b4d03c5bac61232236eecec447b.npy +03001627-5ceabffee1c333293002761e7a3ba3bd.npy +04379243-326342c53d6b26bb423d2dbc3b38c389.npy +02924116-6fc6b7d388c5665e455762fa3afdf17.npy +03001627-1861715e59337785dd7092ed47061a36.npy +03001627-a4b14d0f3cf8a8d7b37a59fbad57ca4.npy +04256520-f16d8f18e03669308f00a5ba54aa8088.npy +04379243-51b4537837adf046fec95a1eac04b338.npy +04379243-612117acf07984468e52a975e7251969.npy +04090263-6bdec3364b44e8d8ec69d13496bd4a34.npy +03001627-3aec502173e565d9f7628281ecb18112.npy +04379243-1fdb34aefd1d6eebb4f9aaea3b860d10.npy +03636649-d12558a4b1dec5ab37b2bb75885cfc44.npy +03467517-9ab3ffd9fb12633227849fd89ddd1d7.npy +04379243-e857e87654e3807e201a7d6fe269f8b8.npy +03593526-ad035d236a8fe58bc8f30866a59f8bdd.npy +03211117-caed0c8c10f5738bafe08eb441adfc09.npy +03797390-d32cd77c6630b77de47c0353c18d58e.npy +04090263-ec0706775e0585fe4c82ce83dca284f9.npy +03593526-79ee45aa6b0c86064725f67267e31c89.npy +02808440-e15eb12dd12574171645a90c3364810c.npy +03211117-cd859f728ba259b0eb5d382c7eb13b28.npy +04256520-e9e54de1814ccae5bbb6a513934583ce.npy +03001627-d29445f24bbf1b1814c05b481f895c37.npy +04379243-7303502cf80ac41481f172e682de585c.npy +03636649-b4b15a84b9067f94a75d03186a0409e2.npy +02924116-314eb222862a53c7249d7c2e6eb0a2ff.npy +04256520-d9ed3fd60f4d42aa5f75bf17509b9bf8.npy +03636649-2871a6c7eca55e63d0482422df1ad01d.npy +03991062-304438fc83a3d9b237ab51e1f8240a33.npy +03636649-b2ed672f1d7c2a34664b3b9b23ddfcbc.npy +03001627-8d2fd4b9c583e1e6a12cdfe22cdc2f5d.npy +02871439-ebb7a6ef91d05970e3ada376097bba33.npy +02958343-31546074e22ec0b69ce1b0be9ab0ab75.npy +02958343-7faf7e8c2f383eafca92a4cdad802b45.npy +04379243-f27eba536ca8d428eb1f243bab39fb29.npy +04090263-3222936b563fbccddb83191ac0ff763a.npy +03001627-c5637356cfc865b33ad3591a780fa12b.npy +03642806-cbbfa8d8eff7a681797b57ae3deab1be.npy +02747177-c21d8f5641be31a285cac25b72167160.npy +04379243-90d08564f19279ce714531f0291497fd.npy +03467517-ecd53707110dbc208d8778ff441ce85d.npy +02954340-e823673c1edd73fb97c426435543a860.npy +03636649-a87825df690f900c408d050f12518231.npy +03085013-657c0de244576d26add3e496533730f.npy +02828884-469235b1160c6df1bd44b6fcd3e363b9.npy +04256520-828a2a981ec78e7c14038d588fd1342f.npy +03001627-668c488e900c2ede62a9eaa32bfe99c4.npy +02958343-cc8b44ddf6ec80fffd8e7b05498794b9.npy +04530566-fe7b7ad843678dfcd8c527d4042f291.npy +04256520-725af978a11bb5c383a0857b7b9398b1.npy +03001627-48bb4afc8cf90b4664215ab2598fd5cd.npy +04379243-9d0c9d8e03fa4f281a67ed3cdf707521.npy +04090263-b7f7746fc15d67343571d7763ba5a413.npy +02958343-46726bf3daab9d14b1bb46d2556ba67d.npy +02691156-ec2ceb5d65007bacfbb51ecfb25331aa.npy +04256520-fce0ca2464802f5ab0474c2e080078f5.npy +03001627-a65cd22689f14147f155d75bbf62b80.npy +04090263-f8ac577e9f60ccaf3e7a62ab2a088af3.npy +02691156-dbdca81a0f9079096d511e9563e4bbe7.npy +02958343-5d2e6410d4fb760befdff89bf9a96890.npy +03046257-ae4bd519ca0158d1624540d1cf03ba7c.npy +03001627-d4a2a7d81cef335cdf6cfab91d65bb91.npy +03948459-7568ed12e06320b32ee0f9a97b71d505.npy +03513137-f0a1e3c919471b2819fa27f3bdd7d71c.npy +02808440-a92ca67b245f008b54d7082b34825ef0.npy +04530566-337531151abc41a7b390176e65ea3f39.npy +04256520-b6ac23d327248d72627bb9f102840372.npy +03691459-e11cde2df1c508f7e098c9e597ef1d0.npy +02933112-38def13ea098f098fb266533561ee98a.npy +04401088-a04e8cce46e70fc48f2c50408e4e65f6.npy +02691156-b7fd11d4af74b4ffddaa0161e9d3dfac.npy +04256520-4da36f40feb209fedb52360728b4b83.npy +03624134-8e1642ad868579a57ef00b10b1a864e.npy +03928116-dc078a781ba248f016a0adac6af4232a.npy +03636649-5c8df2c17d09028543ba2b548bab2839.npy +02958343-d56104e27f9d5f55725a7749daae1afa.npy +03001627-a27818db3f288ac8473f10e6caaeca56.npy +03001627-bd6a8b133fa4d269491d6cee03fef2a9.npy +02691156-cfaff76a1503d4f562b600da24e0965.npy +04401088-2eafc16c78c43b35d9f7ce5b19e46227.npy +03691459-4ddccf2b67d0cef538cf6df9faa9b65.npy +04379243-460bd446c3f1cd5711beb49b60c734f.npy +04468005-9518c86ac24e7c91bfb63e2c713ae7cc.npy +04379243-93277f95f365b958ffd5817f210f277d.npy +02933112-51d9a60e0654e3622ea98d69e91ba870.npy +02828884-cb81ce8d2558935881faebbdea6bd9be.npy +02933112-59e0e7f6eaa54e359cf7640f6c7f518b.npy +04379243-eb66e5ca3eeddee87fc7604ac712879d.npy +04379243-941c99dcbf881c6939070a7367ed1554.npy +03046257-6073c2fa3bc752b314038d588fd1342f.npy +03797390-5fe74baba21bba7ca4eec1b19b3a18f8.npy +04379243-faabf2f29b99589991752ed21892d778.npy +02924116-dc172096d37448faa3cfa46226644b04.npy +03001627-9fe840a156a5647c9ce67e77fac3db9.npy +02691156-62e29787d3623618575bf8a4b14be4f4.npy +04379243-5700152736510e2b45c44a42b411ced8.npy +02958343-5d756a52f6f361abf500cc506a763c18.npy +04401088-e8345991892118949a3de19de0ca67aa.npy +04401088-267a2d6fbf29c04cbc17518d87dd1f7a.npy +02958343-b1f75a8e8b9e921a8a6cf8c6b92417f2.npy +02933112-70c0c5438f0da757307c5c16466b10c6.npy +04090263-43dade9260b93b2c3d204f0b9150b384.npy +03636649-57aa536c02ea697b2195f9e636aede6a.npy +02954340-3a666502c0432522a3340564b56a7f70.npy +04401088-b91bbf0a0d09d2eb243525d45e430520.npy +04530566-1dabc979fd569a0e850e00840470903a.npy +04256520-b08fb5e8df4c11c090a9ce3e4b15521e.npy +02992529-722acb5e8ccd39391e5d846d206adf3d.npy +02871439-caf2c03bfb37bbce35836c728d324152.npy +03624134-713e17148c90c902830e3a69f9610d57.npy +03691459-1297c443d9a147ed9d783559814f4705.npy +04004475-b5d3d85c016b25b0f39d7554d3e63ae4.npy +02958343-f4b86f895a221f353b0907d01b34682a.npy +03001627-1145248e1eba424d492d9da2668ec34c.npy +04530566-44ee47ab9926aa821e062833a4a1a38.npy +02691156-40c730231c4da8f33c3bcafb5ffed4c0.npy +03325088-d3aa2eeb7641d99fb9101063463c970d.npy +02828884-3824b040bd8906e0f155d75bbf62b80.npy +02691156-1bcbb0267f5f1d53c6c0edf9d2d89150.npy +02958343-8798825a3c68e5c7e0470509f60266ee.npy +03636649-48a5b451573920d44cb3aae7b27db2ba.npy +03636649-5aaf61da59f1c0773225afab722d9fd2.npy +04330267-2d5b7183f052b34f56efcb65c52d83a1.npy +03001627-3d029e681e0b4a0c12bdfd84d1dcaa33.npy +03642806-520d98e360cf44ec8139dd63d55edc44.npy +02958343-93d49d2e5e4ab1b7ae33d942430658c.npy +03046257-a911990b617749ee738f481f8560d58.npy +02871439-b7697d284c38fcade76bc197b3a3ffc0.npy +03001627-6072ff799065609b6bc601efa799c927.npy +04256520-615ebac351d7e8356051d49e4b21b83c.npy +03636649-bf659a08301f20f2ac94db38cec7b356.npy +02924116-e9afd0d7aa653df4b129901f80d24b7b.npy +04256520-b913574ffbe7400ce8417aef1b7a422.npy +02958343-3027a9d3b70435416abce8cb03e7794.npy +02958343-3b95f46c0133167b80e98029b8cda1b.npy +03593526-cdfe4639a2da7801d50406298c1adb95.npy +02691156-1e7dbf0057e067586e88b250ea6544d0.npy +03691459-b8b1643518382596aa623a443910bb58.npy +04530566-819a7b31f925a302474a33db0a80b327.npy +03636649-e485053f3e0d18252cd2160e449d45ae.npy +03001627-1fe0a612dfc3fc548be8b77157b819c9.npy +02924116-6f59f085a589522b6481aaaba8c72ee9.npy +02958343-96762f5d7f7e93343f9daeef6b843610.npy +04379243-8ccbd2949fd8809b82cdf8854f156846.npy +02876657-ae52386c7a6e25a1a666d1503f8e34ad.npy +03636649-4631e756666a8a208ca4aeb5e3b33af7.npy +02828884-f7b5756c04e354a0c1c40d87de24d930.npy +04401088-558c9b7e854db7da21844676433a0aca.npy +04530566-e177d4186bff96ea6dae8586082d789.npy +03948459-d706263b307d12c9d4f4334cc3aff513.npy +03001627-4aa70df1db0ff6ce2d19175e7d19b7cb.npy +02924116-967d5e9bb9b79d92ab2c2809513f396e.npy +02691156-9634ed6dc8ecae0026360e1e29a956c7.npy +02691156-18806a80387734b754c7b6e11bf7148d.npy +02691156-ab95a4e7f2d3cf9ca8607f540cc62ba.npy +04379243-e435c1e3430eb7b253fa79783efbc3bf.npy +04468005-b36bcada3b5d7c7ce0ba12f63b0c5b5d.npy +03001627-88042e6d331ffba0f63e8e405d49b8ce.npy +04256520-bff79b49732569307ea323bc74055b8.npy +04256520-82a13477581d96a1fd3e75cecd4d5ab7.npy +03001627-cacb9133bc0ef01f7628281ecb18112.npy +04256520-7fde281d5d2cf5bcdd2b32fd72ab4fd1.npy +02924116-f3f22f9a45ec3592b747ae6b3860f54d.npy +02958343-5823e5205bc7eb46cebc874b6631de1.npy +03001627-74636f18a539da1cab610b0c94236463.npy +03642806-ef6d43add46d0cae4e07b09c086cc5c4.npy +03928116-ce7a03d645722d503f7e27638e63d848.npy +03928116-f858955bcd01c82aabbc032d2bc8593.npy +02691156-4d139f21350f64d2425a06bba46b20dd.npy +04090263-a4a62998899fcea2fccc89e375e776d6.npy +04256520-34e48812eaf19420499252a7ccb366fc.npy +02691156-bbaa22bfada1dc0fc6194c8172019a35.npy +04090263-9c3f797d9b352d35669d741f4ab14065.npy +03991062-70cfce0a272195a236b0f2a1430e993a.npy +04379243-758649ba384b28856dc24db120ad1ab9.npy +02958343-4fa9b14789c8af5e3781057335c8a2e8.npy +03211117-5a20c7f723b42d2b74ff95ba57b167a8.npy +03211117-45406c697e4fcbced742faccfe08d94c.npy +02992529-748f4a9aee8f610e8463cde8953cc1a5.npy +04090263-81ba8d540499dd04834bde3f2f2e7c0c.npy +03593526-971d8456fc6fde71cf644619c59e0de.npy +04401088-9e302a3f21a992c0bb579d1d8d989550.npy +04090263-7dbf5ff231497ee511f7dcbb4a32aee5.npy +02933112-c0d58499d2cecf07e1c245f9728d365.npy +04530566-dbcf36d87385eeadf64bc205d76349ec.npy +03642806-4fc3d56243d2d8801ef1ccfaf50f2048.npy +04256520-64c8591e8a837cd5dc8d41086ec55d96.npy +02992529-c7ec332bd52f939f04143dfe595ba79.npy +04530566-ff7b2ba047233a5b149489fae2289e6b.npy +04530566-5fb24b87514df43a82b0247bfa21216b.npy +03001627-2e28fe9594c48874a6eb1dae0394cf12.npy +04379243-89157839dd80262087e118e254d6659f.npy +04379243-dd2238408ee5d84d8d1c97149a00bd19.npy +02958343-347ffb0b0761c6ba8514fc08fc0d2ea6.npy +02828884-2f0cd28e2f8cdac16121178eafd002fd.npy +02691156-6a54d956a8adb2d0e691625fb79e2c2.npy +04256520-5f5150a80e5be6159141f9b58470d646.npy +03710193-e6f75c44739ee7b48f74cdb60878d9a.npy +02992529-9b74db2ebc90ae4789905122ac8b41f3.npy +04460130-3668753b904e53c4b96aa5dc23c036c.npy +04379243-33c4c7c47b8874123c8f5d3bbb1a3215.npy +04401088-e70ce62b41a598dba48aee3bc134fbf8.npy +03636649-e35c4fadbf8d0426c26e81144f3196d5.npy +04379243-5a7f0ba2b1845e7bd2a79e157dad9b1a.npy +03636649-dde3b4bb9fb1ad25e0d089cf3411494c.npy +04090263-3dc3dd08910169be2e3059b0e19cba0b.npy +04256520-8dc7bba62eabeae9b3af232f92902efa.npy +02924116-8886dc9b9405c6d914f96752ea902e3d.npy +03001627-3f95c370fb3871621f98c0761af40e04.npy +03001627-e9f36f74e22ca0897298e452825d1f0c.npy +02933112-85ddbd698b3e7dfec59350d819542ec7.npy +03790512-4f30742005b7c20e883158c0007ed9ba.npy +03001627-bf0ba9e2ebcfb431e6fe3612af521500.npy +03001627-9d05b0a242a5ee06639159c697a89e8c.npy +04530566-ac52cf0b598e930ab38d3c03866c1379.npy +03636649-d357edb3b9ae47f230f6e0ede20c4525.npy +02958343-7751f6695ce5013bbda733a39f84326d.npy +04379243-aba18a9a32753bb6390dcdc075aa60c5.npy +04379243-21a65be5dfed538fa3461a37f23a9515.npy +03001627-5f2441ed2a9ec8fab5d55ded7962c792.npy +04256520-1f860a494cd615fc7d4bf609d539b368.npy +03948459-4af05095ad02dd8c9cd99d3d15a8756e.npy +02871439-465bb5a9ed42ad40a5817f81a1efa3cc.npy +02828884-26e3a9d86dc09155cb2a965e75be701c.npy +03593526-578096b08ef3c3534637188d1bc69cfd.npy +04090263-15a209524ad3fcb67b84b9482c4b66d7.npy +04256520-21b22c30f1c6ddb9952d5d6c0ee49300.npy +04379243-6f630e2080aa9f10e45ef4135c266a12.npy +03001627-3316a00869217c2632ed7dae08823495.npy +04379243-525148edf1f9aa72bc7f58784fda27b5.npy +04256520-288837a47f55c0e9d8d964adc0b6502a.npy +02924116-b875a7af988b644d29ebc23acefb248a.npy +03211117-fc0d0287ea544c707c65e97bab3e4970.npy +04530566-1d176576e4ded157a313c221866393fc.npy +02828884-edf14e0208ac61b570eb586f56eab45.npy +04530566-dd012d1ee91543ff500cc506a763c18.npy +03325088-aef73acaaf17e0b614b35a7d7cea7130.npy +02958343-54b89bb4ed5aa492e23d60a1b706b44f.npy +03211117-3077837de566c236a42abfb83da6a2e.npy +03001627-47ae91f47ffb34c6f7628281ecb18112.npy +04090263-5370fd7b6529876574e18e0e7a19212a.npy +03636649-206ef4c97f50caa4a570c6c691c987a8.npy +04090263-b68218340f090e03519f927f2bf92da9.npy +03001627-226f38ce0d46fddef7a06a265fb36208.npy +02933112-6219b46946f62474c62bee40dcdc539.npy +04401088-ac0967f9fe8f63f46b2ba76eab0d2b1c.npy +03001627-234f40c665976a51dc1e30a57aedbe31.npy +03001627-8affea22019b77a1f1783a44a88d6274.npy +02958343-f6a93b95e10a8b2d6aea15d30373dbc0.npy +04379243-bdf30e94446293c645de94e1bc93a4f6.npy +02691156-18e86ba0172154f3bc0909d98a1ff2b4.npy +03211117-94482409d0396dfa3f8f528a267748f.npy +04468005-d2a55d5745da47892aa93fe7a6076a9.npy +03046257-9937b55d4b6bd3b3f78bdf37d618e97e.npy +04379243-d126210a20db32c23027f298c7ea0c6f.npy +02958343-15c3b923c85d22796d8b9531f93cc8de.npy +02691156-d59bb0ad79371634f3d7c71ae132007d.npy +04379243-f5d9f518e284989cf930da774352b970.npy +02954340-6e983d20e0bf80296829cd4082fbdbdf.npy +02691156-b8720c5fee3264f735fc197bbabcd5bd.npy +04530566-9380065fd20eec791a7be2887bc37d1.npy +04379243-48ff9804a1ae69f4ad5067eac75a07f7.npy +03691459-a5c19b4bfab3a826236632eedd876bae.npy +03001627-e12ac2c1c707b7b2f45a7a3d26bcb6ad.npy +03211117-e7409303fa52f74b98de02aebd38a1f0.npy +03046257-3234632251c769afe460d06cd9b374c9.npy +04379243-2e30c286710fd73d492d9da2668ec34c.npy +03593526-1f5c74f0a55cbf9798d5fc0473d00a1c.npy +02958343-705840df46a582e2ac826a3c82da491.npy +03624134-9b3bb2c269ed48741c63053ffe1a64a7.npy +03761084-e1e2879a951cac7b178e7d331e641179.npy +02924116-462d1cff923e1e94c366973b1ac73478.npy +03046257-97789558032ec294f166e7ba85df03e0.npy +02691156-31b201b7346e6cd15e9e2656aff7dd5b.npy +02958343-6942e70e574edda3c8831f15c6e487ac.npy +02828884-9d7185edf0717575a6195e775546b04a.npy +03001627-6501972156717723e8b2b8dc0c816caf.npy +02933112-85b82499e3ce7aea3a5893ad04c930a0.npy +03001627-2abb64b16e61663ce99b044850de1b87.npy +03636649-894cdb80665ba73dbfeb5b5bfc3dfc3b.npy +04379243-97894130bbbd202df4b6538438a0b930.npy +02747177-5d756e92b734f2d2b12aa6a0f050b3.npy +02958343-4c1504f3463445dbbda733a39f84326d.npy +02808440-5b088060eeffc5723af30a3946d92feb.npy +03636649-9a976020602ee60b5fc8f4c1fc00b380.npy +03001627-3b57aac4b7f4b9f52d19175e7d19b7cb.npy +04379243-15ebb1e7e6663cbfa242b893d7c243a.npy +04401088-1984fb95afb6dae5804722305621f918.npy +04379243-3a3c922623ddb42e5d81820421265171.npy +03001627-8af939d95f201d17283b00891f680579.npy +03001627-507a5974b24dce2ee1fc1bfd241d8d6a.npy +04379243-d37fd2ce56b3340eaccac37ae24b8e2.npy +02933112-9ea0005f3d702b4f6cc679ef84e06ad6.npy +04379243-b63c8ddca680a2a3492d9da2668ec34c.npy +04379243-62a4f3c24bc69f593eff95e5c4b79279.npy +04379243-752d13c1011bbe94f68132aeb243f95b.npy +02801938-f76b14ffc2fe6c7485eb407ec5a0fadd.npy +03001627-b1f4b2c32f8a2fa77ee217c21e683487.npy +02691156-8675974f9f6ec91ceb3b5fc90bde085d.npy +02691156-d54ca25127a15d2b937ae00fead8910d.npy +03325088-57c9713acf2765a13321831d2245cf06.npy +04379243-a9747a8f0c31b46188793ca7bd0e6fb0.npy +04379243-ed0be8928caab4bdab610b0c94236463.npy +04379243-d70bb0c4015f6e10df2b21995cbbbc4f.npy +02958343-e07608ddf2b0bfeec726c061bf976915.npy +03001627-b47e994452b71943bf30e5b4764cebc0.npy +04379243-73f34f95a001731b855931d119219022.npy +02828884-608af07bd357d605f155d75bbf62b80.npy +04379243-30f06495dec55016bde93a1daa41f517.npy +04256520-ddc31f9e7064be80f51f77a6d7299806.npy +04401088-5e87bca3231cbdf15b5f05be350ae67e.npy +02992529-1ac1e6fc09611ff049c647f92ae11714.npy +03636649-fca3ffd4ee694c1a9c0ca344f487323e.npy +03001627-38c67c695eb4cd819e179bac86183112.npy +04530566-563d66d82ad3f27e324be6ae66f7fdf.npy +04256520-b653a75f89a6c24237b2bb75885cfc44.npy +04379243-99e89417f985d077738e43095496b061.npy +03001627-5db74dcfc73a3ea2f2ca754af3aaf35.npy +04256520-a693b27591fe6ca2fee6b7db2f5f826.npy +03636649-b4aeed70a21518fefcb8d8c6d4df8143.npy +03001627-d2c93dac1e088b092561e050fe719ba.npy +04379243-e3820857258a0bd2800d7b7d07715065.npy +04379243-7a0a47c08464a493d1433b6d2f686197.npy +02958343-7121e0332f0c2e0551a95aaa6caba1d3.npy +04379243-327f5df925ff54121dc8654936e2968.npy +03046257-50015cb7c658ce3d93f709c6d6d99cb9.npy +02958343-38b80589a780fc3af63ee8a34069b7c5.npy +04554684-49a0abbe22fb557bee526fc96b277c69.npy +02958343-dfe114950aa726f1cfd826dd468a5497.npy +03001627-286c07abeb67b83bf7248d9dbed7a7b8.npy +03001627-9b902b5c6570acb314b96b665a8ac321.npy +02958343-29b558ed31fcbb48a2cf64b275615f0b.npy +03759954-d48385dd958c4ec2f1e87737afc5aa24.npy +02992529-e8345991892118949a3de19de0ca67aa.npy +03001627-4f51dd4fc61c41a27ad11050da24bb12.npy +03691459-ec0a8e2fa00a746dfe74514a9fcabaf8.npy +03046257-447b9c347c64d6ab2d2d2896f4b277fc.npy +02808440-deba7a0e1fe26833f0aeabfdcb4e1dd9.npy +04379243-aa0d0d753ed85d62389bb6b6a6e983d9.npy +02958343-3831ed7bc22100f7c3c8fbe62717803d.npy +03001627-9a3a80065f75e33d822e11aea23332c0.npy +03624134-3bc1492102c727e420cb8f10e0bcc790.npy +04379243-8aab7aa2fed02c6f3de1a463b8ceba0c.npy +02992529-2874447c7552c6b942f892024869e751.npy +04379243-817f1c820e82cd498962005ce0e986db.npy +02958343-ba0ac1d1e25d3fad63f2c3a55558a78f.npy +02871439-e3edade4418b0b88bcb7a87b4876a2a8.npy +03624134-bf5cae3922d3cb2bca7250d90eb506cf.npy +02871439-74311e787aca16d661720f1d4858ecd6.npy +02808440-166f3c900cac3bdeda5444b776d14740.npy +03325088-c297a977dba85f9fb362845c6edb57fc.npy +02933112-b29de5206eb16c146ec91c2f4565a1ff.npy +02933112-1e25501b8930873129a50a2b3c5e5b6.npy +02933112-40df2ce55ea8f002c59350d819542ec7.npy +03001627-fbc87a27b5691196bd3b190b59dd9fb7.npy +04379243-4dba531ab70199ec3002761e7a3ba3bd.npy +04379243-a569cf5284a45a3f353c1d159a8a8422.npy +02828884-9699995246fd521ca909cd1ba5751669.npy +03001627-1de733a48e5607b22d9c1884c92fce12.npy +04379243-be4db395f7b2f089391e4d6c585a697a.npy +03593526-5e914dd726313181b1b4b514128408b0.npy +02828884-133d46d90aa8e1742b76566a81e7d67e.npy +04090263-df6581f0ce7c00421b00524af022276f.npy +03001627-56fd0fa3863cd4c17d63360731b4227a.npy +02958343-d776d298be6bfe88e78002a96f52ef26.npy +04379243-93a6eb93e11437e1bdfa5e0753fa3240.npy +03211117-25c6bdd929f9aef77d6fbcfb6b291844.npy +03593526-8b9432e22e801493ce364511e87f52b0.npy +04256520-7882a06b4612d536ae882f622d5cda14.npy +04460130-224934a28705403238cd8eb23853c009.npy +04379243-d6ef0aa7b674c171fb4f26e87f6a6814.npy +03513137-65bd772022c2ac094fd7d35b0d9ebb77.npy +02924116-76b521e4dca09e7f673ddeabdcc8c6e.npy +02924116-dc771f013d077fe4dde60bf2d879e14d.npy +04379243-138a1ff3aa457b30497839e108373e6e.npy +03642806-9cb54ee28aec14013cb02989e2da5a2a.npy +03001627-9b6d1c0f3a20783af51f77a6d7299806.npy +04256520-d9fde31ef5c2f3ed17b431cae0dd70ed.npy +03001627-91e4eb92e010047d3fc7406e820e0781.npy +03790512-ebd02a4811dbb91b594057aa2102e240.npy +03001627-6326e2f6e17cfc21d43c0a5e70f98227.npy +03001627-5043512b70a157835a15b6547f08c8fe.npy +02828884-605b2c687b73695c8da90b986150cc3b.npy +02871439-edf600503d359b7975e8c36bab2b18e0.npy +04090263-65bdbbcd861aa385ac52f5edacff5504.npy +02828884-c3f92e6a78ad156863b2acb037dfbcde.npy +04090263-28d70dbbc48193e0a39dc4a567ce225f.npy +04090263-8b1b66ae9e416cb13b5076da3c7eba98.npy +04256520-6f84940f81a61eef2e9208ffa1a27124.npy +02958343-e607a20da6c5132dd141480e2c154d3.npy +04379243-b0890c9a4332f7a07e28af1b4b42317e.npy +03001627-6549c13a4c96b926f51fa0238791f5dc.npy +02691156-7bd43965f17c25377209009cfb89d4bd.npy +04401088-2964d10d72ea38cf4857f88b08630a42.npy +04379243-713c28954944221f618af5c2f6d28c1e.npy +03928116-a6b26dfef15ace459e0d848896b0095f.npy +03467517-9925355d4b0deff6247a5be450795511.npy +02808440-a88e254ea9ff7b4dfe52ffd0e748a1ab.npy +04530566-88baa5e1db4d1c624c24aa820d0994e.npy +03624134-dde6b5fad601b25e80b72a37a25b7e72.npy +03636649-bfc4cae9fc343792fcb8d8c6d4df8143.npy +03001627-d38129a3301d31350b1fc43ca5e85e.npy +02992529-457b4310870bcf047f4e0c14aca1a926.npy +02808440-469536fd1244fed42bb02d55712c595d.npy +04379243-fb3c684afcafce085a3075d93a0a3a93.npy +04256520-7b914fb42c8f2368393b1800bfc51a93.npy +04256520-a3faa167208786cef81b7bffcd0a03c8.npy +03001627-403b4eb7194f563f79b3e1be3524f72f.npy +02958343-f45022f442368e60c038d3a33427a80e.npy +04099429-c486afc7d7184e0457c81888891466e2.npy +04530566-48a584c9080f7495b97c9314bd4647d5.npy +03001627-94b55dcb770626d9c8687ff9b0b4e4ac.npy +04379243-346db24c1279e8d273fdbe4b39ff4036.npy +03636649-e02cc9c4cac285419cb07ecb5b4102.npy +02828884-96d87da2fecf81ddd2b12aa6a0f050b3.npy +02958343-29fc55965346a53733d7c9e122eec9b6.npy +03790512-896f688e07909b9b893e67220bf9be7.npy +02828884-a90115832bb80dc956f6fc4b4ce1db04.npy +02876657-f079d5f4f4a8cd9318431871c8e05789.npy +04401088-da24f27173874672ed7485a1aa598365.npy +04379243-18b1461f48e0fe9aaf15b62af6b513f.npy +03691459-a1d1f232168607c81dd4da6e97c175c2.npy +03001627-c67949ee2c241e8e9b9f2eb77f5e247e.npy +02691156-6c8b2544144c38d99e8d5aab043eeb56.npy +02828884-71225307ddd5a772dc11eeca04f912e.npy +02871439-8f16bba329b15e6bdc219d6984e72318.npy +03325088-5b7e61559ed415c6f893b5bc716a3fa.npy +02828884-4b079b2e510fffb8cb2a965e75be701c.npy +02691156-55d0772f003a362916c1ee83fd7a7f1a.npy +04530566-f3f66f0bce27d439c1dbab1d1ee81853.npy +04379243-2b3b491b70535af2f7f596f1d05d059.npy +04256520-107637b6bdf8129d4904d89e9169817b.npy +03691459-8c23967793e62320825138352acfcb46.npy +02691156-aa2af754642256c08699933784576e73.npy +02808440-96fd142c3abacda0ccd0340812259a39.npy +02808440-290df2ce1251492db84959963148f2a2.npy +03991062-6bb307429e516e2f129f1cb6c6fa9dd5.npy +04090263-d980e47a5890b42e296e0e62674e2efb.npy +04379243-8b3543f09b36696b488017d48a7f7eb4.npy +04090263-2eea6b3bddd73b1be768fc5ed1ac23d0.npy +02992529-113303df7880cd71226bc3b9ce9ff2a1.npy +02933112-e0f6e225c7f88db19ea59510032cbc74.npy +03642806-6b6edbe38c23db5a4599f539a26d98d1.npy +02691156-ece25d89898c7d9090b1d6deb98feec6.npy +04379243-1615fc31b6daa088c3bd24f986301745.npy +04379243-4c18b279e078ebb91a8781c24b79ae57.npy +04530566-57b1795508e5f9d19996f95a20b4c45a.npy +02828884-16ce0976d3bca243e6fe3612af521500.npy +03928116-1a8a5e4095e7ca4749f90dfc30e57686.npy +02691156-7f4b166fba71407490b1d6deb98feec6.npy +03001627-72fd9c2f47db23987f377effd1f7ba9e.npy +03001627-e76b4872f067395988dc0b76b0c63f53.npy +04379243-b723429f1ff9df7dd604f93937ce2d3f.npy +02933112-6343efcc64b331b3e3f7a74e12a274ef.npy +02958343-40f2f3962e360a3c16abce8cb03e7794.npy +02747177-555a9bff25db49ddcb2a965e75be701c.npy +04256520-31e343b657358ed0a4e97ce1d10a5ae6.npy +04256520-23d1a49a9a29c776ab9281d3b84673cf.npy +03001627-60a8c55e653a107ca192483aa282f8e5.npy +04379243-d1525a08cc96beeec786af79f5203d8e.npy +02958343-953531696c554fb275dadc997718614d.npy +04379243-496b37559f4ac973b9fd3978c6bb311c.npy +04379243-409a932e371e12d490ad276cd2af3a4.npy +02801938-781c3a0887e320575ce2e5974a5aa15a.npy +04090263-51a8def44b1e4f40e8e10eefab4b2a63.npy +04330267-ecf21890f17fbe04a3cdeb33500ff1b1.npy +03948459-96013016f3e33bf3e1f2a1daf140ac9f.npy +03467517-95f9f944e62274e8a2bdf3e6e90db79a.npy +02691156-319cf93077118d19f64801ad2940cdd5.npy +02691156-bd22bcf18a9c8163adecb6fc00604132.npy +03467517-ad605b17253e57a9c0f719b596bfb81.npy +04530566-3f6340ffdc0de35caba19ce79eba1cbe.npy +04090263-25796f85c74347726a34aa94ca8a3355.npy +03325088-541954f6d461d83d76c18e71fd49c4dc.npy +02691156-4e2769ec84c0bd0454eefcdc602d4520.npy +03211117-a71826a92bedd8e1f3c3e7bb31acc31a.npy +03337140-67571ae65a181c09d42ccf5f969c90ad.npy +03991062-db562d86ea10c9eefcf9154182ccb5a4.npy +03001627-ee4858f78dc33591100e9bd5c4b0af54.npy +03001627-8f70be87d6eeefdf213c3458a0fe5598.npy +04379243-3eedf733e9318ee06bf0788e630e3deb.npy +03691459-5551b67ffe95c01b73c7253ec9acd58b.npy +03211117-dfe294c64407f6035c6271c95adbdee.npy +02958343-54473bc01457b7291b3636ad9ef344ff.npy +03636649-fed712ffbeff29defcb8d8c6d4df8143.npy +04090263-677d8473fe8fb35280c2e60c312b0f09.npy +04379243-c958f04d72957fb855182f299fe41fdc.npy +04530566-4abbc9f36affe95dbcbc3fd6f72b94c.npy +02871439-58b97051fb1efb3b4bd9e0690b0b191.npy +02958343-3b578ddeae9eeb9ffb8de648691848ea.npy +03001627-61917c7f7953ee7fe6543556f230fe9c.npy +04256520-8f3545743c58b730a92a1b6e1dab7c04.npy +04530566-fcab40b30e1ca530713e7356d62985db.npy +04468005-110a2bd7bf9f8c74de773d95513f207e.npy +03261776-db076e314df03db9235fd81b905fa6b.npy +03593526-2ddd2ef6c8ed56afbfec1075852e48f.npy +03001627-eb7c250519101dc22f21cf17406f1f25.npy +03691459-5e320dffc984b6b5769dec5ec0157054.npy +02958343-a3672e5ee27e389ab19dbf7b5aff7ec6.npy +03001627-9e0a0ad80be6df7789d2595edb5088ee.npy +03001627-b79a15077c4a662719fb4103277a6b93.npy +03001627-f112035c6413080a664b3b9b23ddfcbc.npy +04379243-c27e9191723f352d91829b477862aff6.npy +04379243-af4bb12decb39ab082f29b648e624c33.npy +02691156-688c645ad207773f5c3e79a10705422c.npy +02958343-3bfa196d1b48f1e0c5dccef20baf829a.npy +04256520-d1f68ceddaa3b0bcfebad4f49b26ec52.npy +03761084-94c1905c213382a71a839a72929cc712.npy +03001627-f2dae367e56200a7d9b53420a5458c53.npy +04256520-3a01d750779057f8febad4f49b26ec52.npy +04379243-8ff873162e6237fe571b2dc3839da461.npy +02691156-2018b7614e77d726c1ccec171a275967.npy +04090263-691880ea91ab76abde423072102e0bc5.npy +02828884-4ed2e0a972432881ac3644c4bb0fb64d.npy +02691156-909f59399d056983a0a3307f8f7721fc.npy +04379243-c3e5380fb498f749f79675bb6cb63c97.npy +03046257-4d9733eb21fe5c76eed4b2bb88c072a8.npy +02747177-8f641a48f55555f7a2105179d0c9d51e.npy +02828884-a0ffa64279a8c6f0f155d75bbf62b80.npy +03001627-8086d53c2535511597976c675750537.npy +03797390-17952a204c0a9f526c69dceb67157a66.npy +02691156-1b0b1d2cb9f9d5c0575bd26acccafabd.npy +02691156-1ba18539803c12aae75e6a02e772bcee.npy +04090263-69d0e94a5dc3eeb3fcfb3ae2df2f7efd.npy +04004475-df48a134fe1abe30ef77ec138083ff82.npy +03642806-f1c6801e84c85a07bfb149497503af.npy +02958343-d0a906517e0ec98589fc8cf5232ee9c.npy +03001627-419698e72a0d4d75d8f2ca82d6e1c314.npy +02958343-b61b7103e8d8af91fe21694bd5f519d1.npy +04379243-bdc159bdb0147e2d54f10b531fe5914c.npy +03001627-d40e314fbb7f37199753496ba23f2183.npy +02773838-cbc1512b28e9ed382bef451de0ed6949.npy +03001627-cc70b9c8d4faf79e5a468146abbb198.npy +02691156-446f9144536c0e47f0c7ca80512a3ddf.npy +02992529-50504687883a08e3c6587b192c4cd3e.npy +04379243-876794a6a673dcfe502c728096f4ea53.npy +03636649-ca968e46ba74732551970742dd566321.npy +02958343-3b56b3bd4f874de23781057335c8a2e8.npy +03001627-9a68fc6d001c4ceadc75c30c88b2f7a9.npy +03001627-9324b077e28980f3e3dec121245a30.npy +03636649-2269f268b32b40b35fc8f4c1fc00b380.npy +04379243-206cc839c7796a82a09e5a1a20aee2ca.npy +04379243-9417a62558b74cb8fda92aec8c5adcfe.npy +04090263-4d1881a99b034305e71e857afa9df271.npy +03624134-97ed13011e2d85e16029317225a75a9f.npy +03636649-ca4607a427a5aa127715096cb6ba15f2.npy +03636649-f7a4590c54e2ac7ce62fad6b4f42c880.npy +04379243-8f1efc5edaf6d44a8e6d6e67bd4767b.npy +03636649-f40624156dcbab68620a56d13e6d773b.npy +04256520-6b8908f72b78ddddf51f77a6d7299806.npy +03636649-c28d9f943fbf806ca0f23466c3c25e2e.npy +03759954-2d680a6c4d0097f1127454bdf69cf23f.npy +04256520-fff8834b262dcf4aa89012425147541b.npy +03624134-4e5602e8a655ab0ad43bb185feff0470.npy +04379243-43842d53c1ecb4ef2e3a784001157d1e.npy +02958343-c033fb1c91079242ed3696d854eee1ec.npy +03636649-be6c5d39cbc0d6f9764567afd7c5990f.npy +04379243-57362886500b303632a11457e23fe120.npy +03001627-84767939783aade4611ea9b20dcb5c83.npy +04530566-e964c2fe232f6c3e3ece64552d44d319.npy +02691156-4374a3b4b98e247b398db3ebdf468ed7.npy +03001627-7bc3dbe5a36791cb451e78cdde0ba44f.npy +03624134-74a175fcc024644cc34b900bb2492e.npy +02691156-3bad4bd2c944d78391d77854c55fb8fc.npy +04090263-6072a9dbefe5fb3ab397b12318e6683.npy +02691156-bfd606459cace196e7ee2e25a3cfaa4d.npy +04530566-8f9e62cf323515c4ca380c8375c4cdb6.npy +02828884-5a6e7c4fb53f27925d3bb412062af8d4.npy +04090263-b8430f8c82e80d4dffc0a401ac49c50.npy +03001627-61d313bb88532dcb74039aeb9f7d295.npy +03001627-3297a632aee6ac55dbbc9440457e303e.npy +03325088-4524aa501d924471f7efbe2b298523b2.npy +03001627-1d498876c8890f7786470a1318504fef.npy +04256520-cd249bd432c4bc75b82cf928f6ed5338.npy +04401088-6f63df7ca322514f41ced50d3a574698.npy +03001627-d8e5d15cca97d3fcbda72093f9b5aa73.npy +02876657-150108e481b52e41bfeb5b5bfc3dfc3b.npy +04401088-84f07a9773374b062da40fdb29d70537.npy +03467517-6a983b2ff1b8a42e1285d7bfa3e922e4.npy +02942699-b42c73b391e14cb16f05a1f780f1cef.npy +04460130-7feb6c263e565cfb16a06efd4ad41db2.npy +02933112-c0b055d5060f7f6b4470f9a1ecf7bbc.npy +04530566-a36f6174628ee5807789fc10abcbc749.npy +02958343-26f20ab8033f6937ea859f774de0c90c.npy +02691156-4f3f39ddde5874f2db73445864b72015.npy +04379243-1875947951e8d536365c18a0ba9d127c.npy +02924116-d9c61b05cf7146fd7195e86ac1f6df00.npy +02876657-d910d855fd179dc066c1a8ee69277898.npy +03691459-19f4ee5b1f70c6a47117786c46f53d55.npy +02808440-e3129b782d99d04a44221bef0fa3c36b.npy +03001627-cd10e95d1501ed6719fb4103277a6b93.npy +02933112-74c692a9018b66592246f58eda789fa1.npy +03001627-8e2c39986badb61e6fe3612af521500.npy +02691156-e5f08a5e3dad6cdff810506e9ae2dcc2.npy +04256520-3ee93f4b1efe249bb21450114b9ae3a.npy +03001627-c4a73db5b3503ffa86abe5555a3b447d.npy +02828884-ebf5b387f119c51cad5067eac75a07f7.npy +04379243-580a053d716c2d5aa09e5a1a20aee2ca.npy +03636649-f835c863f175df72fcb8d8c6d4df8143.npy +03991062-7c506f558c25a6cffc6e457221b9271.npy +02958343-4d12d72baa7641a1d1debe6139d9c454.npy +03928116-8e3923a40b3889e532f775d262a68ce9.npy +03691459-5d0499650653cdb9a37f3fc191551700.npy +02958343-fe8850296592f2b16abce8cb03e7794.npy +02958343-4d1dc1ad555807559b0a29632c8d0005.npy +04401088-abf5c8d2cbcd97d81a0d6bd0d03a1fc9.npy +04530566-67f3fa7b1ae6df7bd36a8aec7c2382cc.npy +03691459-3b911043f7cea0639f2401cb9e9e4a2.npy +03991062-fcbf5e87e140b2e78f672c860d940b4c.npy +04379243-b31bf17ab00837ce30bbb59b54a585de.npy +02691156-50da48c8e7644508fca1f1143bb6bc17.npy +04379243-34309cdc141101e42027cee422df2aa3.npy +03001627-c18cbe2537859ab6877a4d9f8fd3e241.npy +04379243-1c7ce8d5874553ccc3bd24f986301745.npy +04090263-d72ea947f961b2bc589c07868201b17e.npy +03467517-4fc341332ed9e642604b03739297cc32.npy +02801938-5c67e859bd49074c5a9dc003587438be.npy +03046257-9d7439534373886fb8183a4a81361b94.npy +02924116-915a57c5635457bd38b9be827bf6fc77.npy +04256520-b567bd1f46bb3b347cf414b698427dbd.npy +04379243-809dd3a7fc2bbd2dec89626a4213fd07.npy +02958343-43cb6a878cf18fd92a9eb0f146e94477.npy +04530566-7103677dbfe63b1ff85fa5c7c88c6c9f.npy +02924116-3a9f2ce77802ccd2b8c11d63630fbd96.npy +03001627-f413955a0f16ae18b76e29c9c43bc7aa.npy +02691156-5678fc24603d25cb74745e8fbb11e3df.npy +03001627-dbcea1998258b0fa6f500315ae356942.npy +04090263-e33dc844a5227c3d410e09f4a064836b.npy +04256520-d27b9c12f500c3142d19175e7d19b7cb.npy +03636649-f8a6f60ee9926c01e7822b3160005e08.npy +02691156-f986604528abe35554eefcdc602d4520.npy +03797390-a6d9f9ae39728831808951ff5fb582ac.npy +04379243-d9628700a086ca293c85bd0482f3094.npy +04379243-db3f9b48562440acbeedb4c8fd29e2d1.npy +02828884-f495bd67af8d9f0cadd1cf65e8dc4de.npy +02933112-c48151eb47f0e4ffc59350d819542ec7.npy +03790512-6046f323c82b280ea75120c0e0c5316.npy +03691459-d12ec06509389e01574d21c0c95092f.npy +02828884-5d68fdf84dfdc4809f136629ee03397d.npy +02801938-d8b9cb175465fac03a360f4a31f99f4a.npy +04256520-5a0fb2d34e0dc4445369e32fb818f337.npy +04090263-27803e00894dc087da95b0caa53ebe1c.npy +03691459-38e4bd990b3031bdfce87fb06e25db17.npy +04401088-8d55c1677626cc48214d974150b798e9.npy +02958343-d22a2d20acbdca70c972ff3f74d38438.npy +04379243-2cd0f589d64ea3ec36ac40071701c687.npy +03001627-e23400a634c81fec3cc5c2b17dc81196.npy +04379243-4f2b4f1c35054480438d580e74643a65.npy +04379243-9d41c5e8ac8ca4e6827b73eb36515554.npy +04256520-fdc419e377f15e728101accd22c701b9.npy +02933112-422975f531854eeaf36ea1eb6542fe7e.npy +03467517-980e470ec52ca71863ae8c3a62777578.npy +04379243-631251b7c08bad443e890a18a7c6a6e8.npy +04401088-8270c952b147d263b9746cb9e2b9d08.npy +02958343-2b043f3cae45d4937cbc6cda01aaca49.npy +04379243-535911bcbab242877543d7dbfecfffbe.npy +02958343-35f6b9780e173878a8c38723d07b122f.npy +02958343-5f2ae8bd2d571e7c6436916a86a90ed7.npy +04530566-5ef0011ffbd75eb6dc1a42a6163b8fdd.npy +02808440-3e9b4b309c9db612b0957d845ac33749.npy +04004475-f3ff60a4243d6667b609fce60c2dc7.npy +02933112-b6c1fd850c5b042c738e43095496b061.npy +03691459-ff9c1754252b9ebf73c7253ec9acd58b.npy +02691156-7220043361fe9e50eb983188eb4e930b.npy +03593526-c6506a2457f14e9e5ca1f314f1afc186.npy +04379243-4bff004a90877ea319fb4103277a6b93.npy +02691156-ff2f975a23b78bc78caa71b1fbf7fb98.npy +04379243-5ac80d0ff2237fd8e2dba1fdf90cf48b.npy +02691156-9a84ed39f9a2a3c0b3f2b01de37c0b29.npy +03948459-8cf7c6268ed360c35ca3862a7efa6401.npy +04530566-cc03dbbf18adc483bcf964ea747b39ec.npy +03593526-d61010bad35efd8199e8bf807e902261.npy +04090263-bbe366b82cec5894c082409e8305f221.npy +03636649-cab6546da3916aa53c8d0fdfb1cc2535.npy +02933112-7728f0ae18c58d067e427098d75ece6a.npy +02871439-a69640051e489a414b9112ce9ce98204.npy +04256520-9451b957aa36883d6e6c0340d644e56e.npy +02992529-93556001d266860513ddb059403c66d.npy +04379243-f03a86b27bd0a6b3d86234e915108e6a.npy +03001627-6dff84a93b82c888486150a9b7f2cf18.npy +03001627-33abfbb0993473bd71a782a4379556c7.npy +03636649-d508d163bd2e50a41b62028fb8bbd788.npy +02958343-92ff3c7b2b8b1f65e2693f33cdca907b.npy +02933112-8a2aadf8fc4f092c5ee1a94f1da3a5e.npy +02946921-f8fd565d00a7a6f9fef1ca8c5a3d2e08.npy +03710193-e434e428f65c56ed79dea5ba5d13aa5e.npy +03710193-b06092a58fd7f1dc9981642c1048582c.npy +02808440-d066024b84c1b4fb469ceade478d6997.npy +03001627-103a60f3b09107df2da1314e036b435e.npy +04530566-438a1ce3825bc06a18803813f0c0dee8.npy +04401088-9c2e939e173fb6e88af54f33b2f21f70.npy +03691459-f7624b0826b4da3ae7e41e72dd76c27a.npy +03761084-3420e627144ab8bcba7ad9409a09b1a9.npy +03337140-bfcdaac4627b7c13a7a7a90dc2dc5bd.npy +03467517-27e36c61a12d6df8d57700c05b1862d8.npy +04554684-4b5552c17c1fee56b6c98c3c1d4f4fcb.npy +04379243-9b8e6eb835f0c8bcf37af16b2893f1d4.npy +02933112-2fff20fe8b4b4a6cc59350d819542ec7.npy +02828884-722458bd2a0eb811214a15a5a42c49c0.npy +04379243-d799cc222f34fc0879bb09dc5605a57.npy +02992529-434e23fb04effbb86bc30c6a9ae3d46e.npy +04256520-7446fc82485002938db1c6c15d875c99.npy +02958343-485df8eb9c410c132a9eb0f146e94477.npy +03001627-3f11833d3d9309bc9952c05a06935ddc.npy +04330267-558f7129b2b31c34134a4ff70ce43955.npy +03624134-8280b4bba3a38926ddafe9b591eb9ebc.npy +02933112-d3257b1df741d9a099c549327bba1953.npy +03325088-cba9093647736733275d003e423c59ba.npy +03624134-7aed22a7074f16431cf05d6e4dbb95af.npy +03790512-3a247c8b82bd675c1fbdb352261d023.npy +04379243-c27bb0cf69183cdf78ebd8af2a314e49.npy +03046257-f1bb9e3a9f4b37984ccc5a59d21f8efb.npy +04379243-20714210c5319a68b16d12ee250aa07.npy +04090263-4b4273fd49971552cb833b31b53d151.npy +03467517-e0ca9ed192df5529e5e24299d76e4a78.npy +04090263-2caebc928dca9f84b205c7feccc0f737.npy +02691156-132111c575000a3c146e44cc99f07c52.npy +04256520-152161d238fbc55d41cf86c757faf4f9.npy +03001627-2d08a64e4a257e007135fc51795b4038.npy +03642806-3237f5cd4bca555955357c338ec9641.npy +04090263-9cc96465d70061cb94deaa9fff391d41.npy +03001627-90b6d8a730e9e17cc55161a63fbd109a.npy +02958343-4773cf28df771861b112e5ac235c21b7.npy +04401088-90010049891220187eda1e12bd28fb7.npy +02876657-912a49eeda6cd8c5e3c462ac6e0f506f.npy +03691459-74a4f472155ed5a3b2bf4f773fe0e622.npy +04256520-16ca439cd60eae5f23500a5b036df62e.npy +04256520-51e5da3e9f55c77ec15dc8fdbaa55abe.npy +02828884-617fa8d6d65af35d71295682a9280b8b.npy +02958343-604d915e7bf91cbca22cf2b42142a7ea.npy +04379243-1d43a3a22ee451e62511fca00e0288b.npy +02992529-fa9b007a326be6975c8fa950032e0987.npy +03001627-8862fe77a7856db29a8ef44e1d2c5b75.npy +04379243-8d0e190bf8d8021cea7b477e7b62986d.npy +04090263-90859d41f2b4b996cc34b900bb2492e.npy +03325088-abce921108990509251c40136771148c.npy +02992529-8e00be7402a612e17d6b888b4eb1ac9f.npy +04379243-a2f9a8c649bb70d35c08aa223a05362d.npy +04379243-7f71383698c24d4f43dbb6421d614c0d.npy +04090263-c3d75ea41abecf51519f927f2bf92da9.npy +03948459-b8fc16725ae2daf076a05817943c3b79.npy +02992529-2acb9ffbc050ac2e48bb2194a2a904f7.npy +04379243-8b5061128585edb49e9583a661702ed4.npy +03691459-244f40cd50620b32dfdc04b8b8434e84.npy +02924116-21be26f34e5a017f70a039e6dffc91d4.npy +04379243-33e344d8250471396f6d5059be65ac2f.npy +04379243-59ce1f3fbd81ab18f4b6538438a0b930.npy +03001627-46323c7986200588492d9da2668ec34c.npy +03991062-2f6399df18f55c0f5076fe09061f1a7a.npy +04401088-eb6fd5cae6ee26c8a2651abaf391628e.npy +02958343-d474f5971b5e8ecae9795e5d56b7e9f.npy +04530566-c929e6d77b548b27e6f3ce318264cd13.npy +04530566-3d908c2b4f5812702fc668af6d3ad0ad.npy +02924116-a58cf9f41c11e32541cefd10ce5d6cc0.npy +03636649-31c9507ec40650d0d5506bacc83bff24.npy +04256520-2e0f5e0ed5acb122597976c675750537.npy +03001627-a345ea2820d2f4af7ff6ace05b36a5.npy +03467517-d8fe40b706db9bedcfcd7283054963fe.npy +02691156-d54a694d514b1911844ac48bcfce34.npy +02958343-28c83c5adf799340f2cc18e077b7ba53.npy +03001627-842130b6eaaef7a4932471681ea5bcf2.npy +02691156-92a83ecaa10e8d3f78e919a72d9a39e7.npy +03001627-6ea006e5c76576b89753496ba23f2183.npy +02828884-86341aada547727593ebeeedbff73b.npy +02818832-ede5fb0f443d4f6afff56d5190327d3a.npy +04379243-958c5eac527deb6e89a6f9d60821eb9.npy +03046257-68b82646290e0be6b0a29c51aa6f10ce.npy +02924116-c2799e2c3f5845f22d42c1e28ea24b6e.npy +04401088-bf1f95958ec4d3e8d485372bb746f3c7.npy +04379243-a5b1e3e2c602d464ded526a7be77b30e.npy +03691459-1c25b626dddfc36a28d267d044b54402.npy +03642806-97df7577c2690ab82290f0f0820b73a5.npy +02958343-147889b73fa491d82e877e82c90c24d.npy +02871439-bef0368b3a9c6424d810b14a81e12eca.npy +04379243-5129899201421fe84a873bbe35452b88.npy +02808440-830fbc92254de7051c17aef130ed6213.npy +02933112-329f80229edd920a82ef94da039e491f.npy +04379243-e4571a5b7457d2dacea003eff0268278.npy +02691156-10155655850468db78d106ce0a280f87.npy +02958343-28009514ec0e2b4ebda733a39f84326d.npy +03001627-602ada3b41238c77b87028a4b477349f.npy +02691156-37608404f9e224d4fd180252c91ed0f3.npy +04401088-725cf43af935ee023832db239383a26e.npy +02828884-5b45d3a1edd81a8f2056b4bd5d870b47.npy +02828884-e285e553a6879a5e2056b4bd5d870b47.npy +04401088-6907dd835a22c32f46895db2a69f45e2.npy +03691459-80aab147daf83cde332fd8bcb8108236.npy +02691156-852e1b84dfa1f7e8e075f0bda7acfbe2.npy +04090263-602c00b06f2b47af8bfdbc9c53b14228.npy +04090263-263cb889dcad2b6ffcfb3ae2df2f7efd.npy +03761084-7431c55078a49981f557d80e0a8a9303.npy +03001627-2f1bc92c53f359d759a6208793b9dfca.npy +02933112-82f7946adba23f5f1c6beaa592f1b2c5.npy +03991062-a96ae58bf14794197e03b8d39fd0ad70.npy +03691459-e2603611f6d3c661b9b2b9d5b2804865.npy +02876657-24feb92770933b1663995fb119e59971.npy +02828884-a0cadebde61910df98e8242d4a63e1e5.npy +02933112-a8bb33c995207084bed1bd9593e318c.npy +03001627-cfe139c0e8b8cfdae342bce0d924820.npy +03337140-7ac63d16fe21f2a491c352d02061b3f7.npy +03467517-675a76195e608c749f817bf67854cc42.npy +03691459-1ba6735cd32d907ad493bfe20f94b6ab.npy +04256520-c70310da520e0499c2c449c0c0579ec3.npy +02828884-d06cf2129d36dec7a4f92840428bbcfc.npy +02958343-11dba0c2ec8127356c2fe9dcfa1ee2f8.npy +04090263-b3bdd86b01306e7b410d23b0a192e911.npy +04330267-12931afc82f7925359e2566a2e6781e5.npy +04379243-486b0764bb1fb92cc3bd24f986301745.npy +03001627-52f9bde46afeecc5dc3653f8341633a.npy +03710193-df7337cf26adeb865bee258e658f9767.npy +03325088-d35b4af3d4e779d4c36fb70296e45483.npy +03691459-48c21ec6f9623c997ededbc2b9b4362a.npy +02958343-c778e4d590417da82205cec171865d70.npy +02933112-9d0a9c46bb6768fbd37a1bae74ee50a2.npy +04379243-bd75fa23435df54b8430b7446f9e1252.npy +02933112-115e4c9a9150fe8e99dd23ec22c4943b.npy +04379243-f5d87f88bd9b31ad2f0ebd444c10bd0c.npy +03001627-3193949a635d8682648909df12856289.npy +04379243-4b399cdce8337c29285e0e27752e54a8.npy +04530566-c2eb5277d66ff1af79953c8c5ce3505b.npy +04379243-e99f7a450afce3b62553cc33364504d5.npy +04379243-4cd35d6ec155d39633207e4c3ac155a4.npy +03001627-e6719610fd2c44c99295da7959c963a1.npy +02958343-135c965744d1a523a60665b13300f1fd.npy +04379243-4231174a23bac5d354d30af857cfae06.npy +02924116-a3841f9c67d82a24193d7855ecfc1bd3.npy +04256520-d2a4faf6613ea1e66db434563c7f5ea3.npy +04090263-d439acf80dc6e1a9d40e00f72aac160e.npy +03001627-22b8498e1ee46520737a00f007529fbf.npy +04530566-7e6aa3337c2e52ff196f35b142096073.npy +03636649-b2c3fb8c5b65a63ce2c3d541bbe76212.npy +04379243-45b9800c1bcdc13735836c728d324152.npy +02691156-46c311894026d9a762b600da24e0965.npy +03001627-7740fa5979753c734209d14d674fb332.npy +02691156-d5ad529ad399086e4e9a6f7cd468e49d.npy +02992529-2009fed0ea8d1fc3e2dbe704eec7e8d9.npy +03710193-42cf808462bfcc2a8d1fe8cdc415f4c5.npy +04379243-a131dabb9fddd3c97a845b3267216856.npy +02691156-b4b21950f0627213fba066e52ee0e502.npy +04090263-5833fa72da0bab839c82b3f5ddca589c.npy +02747177-41b946cebf6b76cb25d3c528e036a532.npy +03636649-6faffa042190494a3def89b32cef8e45.npy +04379243-843713faa2ee00cba5d9ad16964840ab.npy +03046257-7b10961a2fb3de4b4b3c42e318f3affc.npy +02992529-fe02978cb3b6fcc4cec837e48e8de67.npy +03636649-8422870b0a65255d5cae1a083183a237.npy +02933112-30b75567780d84638ac5263758737a81.npy +04379243-2baa1d2adfec9a58445e85eb534460b0.npy +04401088-30e53b35873e59da73ea3d752b4ac8ec.npy +03691459-ada71fe1283154ccdd70fcdaf3665b80.npy +03046257-de0a333f86fd60713b48a711df82173e.npy +03001627-97326604c5fdff1febad4f49b26ec52.npy +04379243-e6ee101d3cb13bdd16a2b5862518c93.npy +02818832-89675cd9d71a905db0541044a1a3304d.npy +04530566-4b491c434e9c230c9e450dd115401ef.npy +04256520-76bef187c092b6335ff61a3a2a0e2484.npy +02691156-26e26e21438ed02990b1d6deb98feec6.npy +03001627-d460611ebc267961d838ae16242881dc.npy +03001627-46dfeffa91719044de2bbe257d2639e3.npy +03636649-e22cc77e9bf9eb0875d36c94c257eb30.npy +04379243-212756a9f7bff5892f6b08a7db6d1426.npy +03001627-c4170208c9586eb63c2247b30d3fc073.npy +04401088-e3c02395e83fefaa42dbe6bfe3cdb29d.npy +02828884-d290989e0cd0ef7acc546d806a30d5b.npy +03001627-59bbf4d0360e4cf733e5ff708bab9b06.npy +04379243-cae89eddba3c4fa1b20aa91e9e90c311.npy +03467517-13692f8afa936159b1a94e2dc3e48368.npy +04379243-592819b967c53ef0f1755b5047ed68f.npy +02828884-1ccab18605adebb15735dec4de5bdaeb.npy +04090263-49083d2b9f3e6222bde9b246866ffe11.npy +03001627-2a1f13b41192e80bf51fa0238791f5dc.npy +04379243-cc4c36724d3c26c65ff61a3a2a0e2484.npy +04468005-5b4131c68ac6062152470de2774d6099.npy +04256520-8ea0e8e7a863b6dab2302e21338c08b.npy +04468005-12733f035bee06de52aed63c67d1c6.npy +04379243-798fa47b8508c8b162a510b8f97c658e.npy +04379243-e65cd563d3a74dd4c0a61ad1cf92b694.npy +03046257-6ed55af31d57c4f929a60d6ab40898d.npy +02828884-501e374fc9a9e5c263b2acb037dfbcde.npy +02691156-2d255ec7a05b301a203936772104a82d.npy +04379243-d4c330d27bbef3808f6610bf672cd686.npy +03691459-69212e8c41ec753fbe62db7ad46c40f3.npy +03325088-fc13ea21c2542368c36fb70296e45483.npy +04530566-a7fdfc15268ff4d68413778731d6cd28.npy +02691156-299ec43108d7109113ae47e860a2333a.npy +04099429-b6a04a1ad7e71394973c59607554704c.npy +04256520-bcc3c5da89afe93517a7e95ef7821038.npy +02828884-715445f1eb83b477b1eca275bb27199f.npy +02691156-576edc1da4e3fb47b627754c4259e985.npy +02747177-f2ee002e961747032056b4bd5d870b47.npy +04530566-af09fac5d37072a3b830672ec83e0072.npy +03691459-c98654c348ccf6baed1d3c8863995334.npy +04401088-7eb1bb8e7f83313b5bfaa3ead015ed29.npy +03001627-f51ab8433184dfd2c8687ff9b0b4e4ac.npy +04090263-46b29fe9796be46497ca877cfb285ed8.npy +02958343-303bbfd0c5862496ec8ca19d7516cb42.npy +04379243-eb62d577d4de8bcbdda7f1d27cdf247c.npy +03001627-d5939ecbcb583dea9753496ba23f2183.npy +02958343-e859ef0e793c43dc159a969baa659ca7.npy +03938244-3e4659a2dcb7bd3f959a2da56ff43b4.npy +03790512-1650afa5bf6c8335b37378f3c85478b4.npy +04256520-be5def882071141c1a8781c24b79ae57.npy +03325088-6b513f89b3b0a06b2b3e9b6eb52d35df.npy +04090263-48b607ea57a1e16d309c2ee598f7f2c8.npy +03325088-cdd72ac0d6def4e8b362845c6edb57fc.npy +03636649-904f90ab5c4d408b313c6de30934784.npy +04379243-685b5890e66bd010dcba2d9cc78a3a32.npy +03001627-8ec247d0e133ad3ce922ceea1248b9b0.npy +04401088-db4c6fcc45cdee08d8dc338f42ea38e9.npy +02992529-d299bcdfee69c57d419fdfebc874eb8f.npy +04379243-6f88879125d12e03492d9da2668ec34c.npy +03046257-86c295f96d02fda679e11b00c4c5627c.npy +03624134-60e7b05ddeeb48eb37fa2c3ecb75f337.npy +04256520-21f76612b56d67edf54efb4962ed3879.npy +04401088-ef57d8665eb5ef7cdb965514105122a4.npy +03948459-c3906de76406ea607086518c859a3e32.npy +04256520-d334047dcbb37017f5f004a628d601ce.npy +03001627-b6c9495629c00419940806ade53ef2f.npy +04401088-447cb44311eb5dda57e80f5278d5b50.npy +02924116-3a9ea0b73c70deb015c32d7ea7a11ea4.npy +03046257-ebb7e54b68ffcf2c3ee5ff7ba8322f9f.npy +03001627-673c396b8989cd1971a782a4379556c7.npy +02992529-e458abdbff34fefe255591a17641445.npy +03001627-70e3e98efc6ec0dc611a1a85a9d58686.npy +04379243-c9c29b00aa05386562daa5fd16a7828d.npy +03691459-fe13f67712bc5e4a1b02cde7e81f0fc3.npy +04379243-72c884f3b9b9119966f379f51753f72b.npy +03593526-d7c1b9b30600ae252a6759f6ef8e2848.npy +04530566-83c90f7b104816ecc748af2814b558c4.npy +04090263-85b6261930b2174d85639a40426ad4d7.npy +02808440-62b3b1e91deef860ede9471c962dd6ba.npy +02958343-777365016f4b7febb623d8d239f6c6ae.npy +04379243-9a52ba3ccb97a11426392a5b643ed5e3.npy +04379243-5af813d1c68d4e557307e0a6ee770fe0.npy +03001627-33f5c19e34d74fa97f07eeccaaddf1d0.npy +03938244-71dd20123ef5505d5931970d29212910.npy +04530566-a88fa5daf540c14a4f6190a680acb783.npy +02691156-c0bb4f92d12f4504d65766fd3c4f994c.npy +04379243-f183fd6b062f642b5fceaa39a8353bde.npy +04379243-689ce3419913a1c5ad5067eac75a07f7.npy +03691459-82ccc798c04e4592eb34db531a289b8e.npy +02871439-bf8c485ab29e0c3549a1e995ce589127.npy +04256520-1543a5ea73b6ab10df2fa7eaa812363c.npy +04379243-2bc58f346be3570ed739a99f2688300e.npy +03001627-c535629f9661293dc16ef5c633c71b56.npy +03001627-8f6395e2451cafa6473f10e6caaeca56.npy +03001627-3dd8c11bc608441f1b17743c18fb63dc.npy +03467517-2b394d7e325c0ff5f48dc85fa744ff46.npy +03001627-e026adae39724b4ff5f913108da5d147.npy +02958343-498e4295b3aeca9fefddc097534e4553.npy +04379243-b09894688b176d426f3d2b1b15fba494.npy +02924116-ae370b6f9e51b0b26ad203a886d7045e.npy +03001627-935f5e58e9e15231febad4f49b26ec52.npy +04530566-8666e4e88dc55c5795ea46728bcdc15d.npy +03001627-f29cbdb2c7bb10f9953d950bcd7de7a.npy +03636649-92f9d60912030cfb3a8888e78d004b3.npy +03001627-1e4fb9149de6be81f51f77a6d7299806.npy +04090263-65e3a44a0a13a1bb547046f04c724fd3.npy +03928116-13394ca47c89f91525a3aaf903a41c90.npy +02958343-626a407fd0fa17d3aa1fca93ac59c77e.npy +04530566-a8db7dcc16750af73c83f6e156ad107a.npy +04256520-3e3ad2629c9ab938c2eaaa1f79e71ec.npy +03991062-a487dbb48fbbe5393f437989dda71b40.npy +04379243-c64b12e620977f0a87039a8d98cfc027.npy +02958343-879121a1bb623324eb79f1a2fb4e869b.npy +03624134-7fa2fc6addfa9191b70d6d22050634f8.npy +04379243-73dfee7c17dd0b2e469ceade478d6997.npy +03001627-4e1948cb03956c9079b3e1be3524f72f.npy +04256520-d21b63623023b40a593ebeeedbff73b.npy +03211117-c7185c6e5dd741e139b7c00cb61e68ec.npy +03691459-6833234a218df871aa35b1de51ec4cad.npy +02808440-1ccb1ab19056b80891a2440e0fc33776.npy +04530566-4af6289f159094d21197663c308adec2.npy +03001627-51aa5f1157cd456f9f9dd9e7d6540d50.npy +03467517-605ddf879e8601d4a072700b3aa0dc00.npy +04379243-625d465a8d9342867ff6ace05b36a5.npy +03467517-bf038654db326b819f585e02b4e871f9.npy +03991062-911256bae9b19fdaa2c59a4d90e63212.npy +03691459-f0e562c21dfcaaa1d1936ff8c5fb2337.npy +03001627-100b18376b885f206ae9ad7e32c4139d.npy +03636649-f85f26c5a807b22312bea13341a54c3f.npy +03691459-8e55b303ce059ac5aca1a38908852eab.npy +04530566-18761559208a970188d5590328ce0ddf.npy +03001627-bb88bf9eb071f85bb232f4221eaa5610.npy +04530566-7e96722d076d9e9020dfe072b77502f8.npy +03642806-4504a4d244d05ddbf5f79806bd65844f.npy +04379243-af8636a4e4d6bfecfebad4f49b26ec52.npy +03211117-6f9ee2b839d3a03683fb187ab7c1f026.npy +03691459-6922e97ab45e4e47b59e9758ae7f41a7.npy +04530566-303736b1be32f43c1c426bf7baf37c25.npy +03636649-441d06d5a657a5dfe7ae87d20a4fdaa5.npy +03642806-c3382162e3502ee41bd042808f3b79ee.npy +03624134-a105080ce4564145aeb54153795ede63.npy +02958343-73e977c312f8628b1d65faadf0df8f28.npy +04090263-552243084ecb0eddf500cc506a763c18.npy +03513137-500502549d46f6d34e61e54863a9d5af.npy +04090263-6f652f3940aa986e3e243aaa4500940e.npy +04090263-b7b3f609d8af14965d0dded52efeb4fd.npy +02946921-efa4c58192cc5cf89e7b86262150f.npy +03001627-4c5ae0ca12a5e8b3490ad276cd2af3a4.npy +04379243-71d35a394d35f70619fb4103277a6b93.npy +02958343-139df45393b6847838805e546aa28d99.npy +04401088-b442b550e827cbcc8ea897fbf75dc392.npy +04256520-79b544db8d95c3dbc1a25f36f85c3fd6.npy +04401088-2216e78a43c5d587b8e1b99345a5afd4.npy +02958343-eee2c0e2912f27b15a49026b22f63b06.npy +02992529-fbe18b762a1328916b7f36a4c89ad37.npy +04379243-469fba8f6fa06e6d2668a5ff3e8889a1.npy +02958343-b41bb2a3159a9506977b27045b1d8055.npy +03046257-e2f7bb607fce0e39cb0b7c9444ff3e4f.npy +03325088-a85bdfab2e46ae2ab7728045d0c829bc.npy +04530566-a53eb39c51a7e0a2dcb7d7c06abe0da3.npy +03636649-ad5c4651205a59f7fa0f332f678cca2.npy +04379243-45f04dd3dfbc4926d42ec7e303174a87.npy +03207941-fdcd7f8a036dae3a96a401b0ce8b43ce.npy +04530566-8c4fb998d99465b48cfe472915a175bb.npy +02958343-d85d6bcdc81df377f52657bb1f80be90.npy +02958343-67ec617aa2352596ce6bb1d0811960f.npy +02691156-e08402fb1e5953a2a93f0f952e72609.npy +03001627-366118e316f03a35327289c00b6dc9ca.npy +03325088-222c02d696583d5b362845c6edb57fc.npy +04256520-7cf9738a01e47dd6a123ce0dff5bf4e6.npy +04090263-ff3425cf1860b6116314c3b6a3a65519.npy +02691156-3bc8cebf08ac975dbd46d022fd7d80aa.npy +02691156-9e4c0840aeacbf10f119374ee5d5f944.npy +02933112-d894ca00249da3fbecbb1f16dced7a99.npy +03001627-f3fa7bd00b76f6a87a8a6b9421844d96.npy +03636649-bcd32489ef6fc12d8f32b552c0a1567c.npy +04379243-3834bf577a25eb2d1ce5b91ffe4491de.npy +03211117-ab69e803c34c6b8536871b478a4420ba.npy +04090263-40f9c088e4a4eb77df3029a778e2c881.npy +04530566-b78f1dd3083c35a1a716de2121565fe.npy +04090263-ddc90b69e90b208580c2e60c312b0f09.npy +03624134-de62211649b4cced49384f9741ad64d8.npy +02958343-c1aef2e67a9608511c4ba4758a592406.npy +02691156-4244f171a6065c2f71e3a79f2415f19.npy +04379243-25dedf655982acf6490ad276cd2af3a4.npy +03001627-4848b62ac4a996b3f51f77a6d7299806.npy +03001627-ba5911cd07d1eebb31475fd256bf1b7a.npy +03001627-ca4900c42b8016ef8397cd720acaa508.npy +03001627-7b17a70aef82c51cb8fa4cb65e077db1.npy +03790512-6b93d5f2e88326f91f80189578e6ea85.npy +02691156-6dfde67c8b905939bc0909d98a1ff2b4.npy +03337140-58e1ece086677b135d354898d3243eb3.npy +03513137-854adc84a21c0a1de8fe5a1391785bf6.npy +04256520-8e74405f71017cd5d509fba1e6dd3b0c.npy +03211117-35003dc3d74527729a1d432cc80562d9.npy +03211117-c8223ca4a4fc81b3ad1f278e1513f3b7.npy +04530566-7d3eb0d2de5c5b8672a78a0929ee12bc.npy +04530566-e708ec80c30086c36dd8881532b5a3d9.npy +04090263-e37b87e001f24db1e55d13d7a8d27c90.npy +02828884-9790980a8ff823287ed9296ee19fa384.npy +04379243-d69a4fe99afe6e0097a5b791ac4ae3c8.npy +02933112-38c9f4bc9c5583d7824662341ce2b233.npy +04379243-f252711946bff75aa5234533e6540c01.npy +04530566-4a7375e11a8ac1ae565f244baeeca983.npy +03001627-d29971cef754cc91cd8c5d1ba690a2c3.npy +03337140-946ae7b4553f69d7784168ad9d1dbd5b.npy +02958343-8e85cc8c9b9ead7562b21e1bf23b9ba8.npy +03691459-1152c16d1081c32a561e8b31a1141890.npy +02933112-c95634c0a44d6596e71fb4d3a412f2d0.npy +03636649-846ae34d173c06d828e0b580c4eee0e6.npy +03046257-9f997f890bf6143d5bcd4b910d7ff028.npy +04530566-5ab18f317c0a5d21576932faf8645222.npy +02958343-4c53afe560e36d8380ba2a9340bf2d77.npy +02808440-6fe04845ce20dd244221bef0fa3c36b.npy +04460130-614ea50301bf9179514f720d40bfbeb2.npy +04530566-9d8d5086930871efe2e5f41247736024.npy +04256520-9ecb691016c6295a50f06b72cb7e77fd.npy +03046257-2be4aa0e5ee54d80ae77574c7d9d2318.npy +04379243-e09377eefe363b4f8101accd22c701b9.npy +03001627-b85de1f567a654737f8769b595aa12b0.npy +04379243-d4491f4fc4d37391f8333d818f5f80e1.npy +03001627-91d84fd5e5ad5c09e63beedfeef0900b.npy +04379243-9c5571c45d44edebb6aa381e6d41cd4.npy +02808440-10d8ddc79b74d150d9b53420a5458c53.npy +02933112-3bf437403138e6c9aa669fbe8e7a7c4d.npy +02958343-fc5d8e25052fb713f559279c88cd9a37.npy +03467517-f411d80eb0dbc9158757b091804bc082.npy +02828884-f7fe4b70b7268f6cc118bd35b5372812.npy +04530566-9004946f75082a8632c0857fb4bcf47a.npy +04256520-bdfcf2086fafb0fec8a04932b17782af.npy +04379243-9affa2569ec8968c60edf8bc2f5c8881.npy +02808440-e90b251f9f026ab36b354c7301136f53.npy +03001627-729650e08d4ddb97ed98cca8f0ccd5f7.npy +03001627-1c6eb96eab5e75b67b79156a61ad4c01.npy +04379243-a8e015f1de2c48c5f51f77a6d7299806.npy +02876657-4c95086448461907d2e07f4a91040392.npy +02691156-9a5f4508a4337d195e48cdafd0101d9.npy +04090263-3387f6bf3cc73546434837e2aadd6d77.npy +03642806-8fefaa8179404c4ae165aa9cd54a0a29.npy +03001627-ce474d7c415941acfebad4f49b26ec52.npy +03001627-48fd6cc3f407f1d650c04806fcb7ceb6.npy +04090263-24386a93c942c7ebad7daa06d33b72e7.npy +02924116-bca84022a19d22f041cefd10ce5d6cc0.npy +02876657-275b8572dbfabb9d88873c05c27001.npy +03001627-f9bb302961c91d7220160736f02bc9e4.npy +02691156-de72864008c4db8bdeadc9ca0263db5a.npy +04379243-d1087cbbd15f509c20768660cf080d12.npy +04530566-3ffae5def89153e911141f4b3ef0acd0.npy +02958343-22d57b895b9cd22137ca7da637f7c918.npy +04530566-d8acb2681ea3e2466c64e0542c2b0af.npy +03325088-54eda983813a7168bad9bd0c4ab8e3c.npy +04530566-7eedbeaa5216ff06ccd600f441988364.npy +04379243-6f1d3ad68c0440a38b424343280aeccb.npy +03001627-5f45bb76bdcf883d5adb3ef1dbe9e3b3.npy +03001627-b23cd3a93c8adbf56d33c8b6c0fec1f2.npy +03001627-96e8a51b1680b756e99481ddc3bbddfb.npy +02691156-d6749fad86648a9719ba010ddb4974fe.npy +03691459-3609604595f025801f9f3ce366e030fb.npy +02958343-dd35ef6632cf507804272696dc83193.npy +04530566-769a3afbadaa92648bfbe54b5d01550.npy +02691156-47c7b3cb099b3212d1c83bc8b134e4d8.npy +03001627-7aea8e52f24cd40c496c9cdc8d0a8c08.npy +02828884-717019a5d139874f44dfa7c5506ef235.npy +04090263-dc222cfc347506ee73482852b5932f76.npy +02691156-2ebfd5fec5c0bc85a52a419d042ca7b5.npy +02828884-76e5103be2d6199071998932c708d327.npy +04256520-23833969c0011b8e98494085d68ad6a0.npy +03325088-7b1678602d33579254d7082b34825ef0.npy +03636649-42bc0dce81734d892610e2a20d7c4b61.npy +02933112-abcac243e3ed325b34943af333340cd2.npy +04379243-9e55b1135ddf93211c8d18742f91c015.npy +03797390-39361b14ba19303ee42cfae782879837.npy +03001627-da02c479d1284ad38727553325e63baf.npy +03467517-133ebdf2ca7bf4b81d4e8021f58beea0.npy +02828884-64010fd77c10672dac3644c4bb0fb64d.npy +03467517-54aab60ad947a9da37d3e9143e987d83.npy +04256520-3fcb0aaa346bd46f11e76965808086c8.npy +04090263-a7da2c6df867c3e91c1943a82a09125f.npy +04256520-aa2d1614a9bbaff7e6fe3612af521500.npy +03691459-b03b88ff24870f2720363e2561dd589a.npy +04379243-681581df89b7d39975eb2bddebec5e6b.npy +03593526-d3b53f56b4a7b3b3c9f016d57db96408.npy +02958343-c61ec8875746ab78227375499b768057.npy +04379243-5bbfa33dfdab27e5821ac289e2458975.npy +04530566-693566461a33af90d7f8e93419dcfd5f.npy +04090263-adef049969b447f87ddef91dabb146f3.npy +04090263-de637cf64b212f4061b28e02a259d647.npy +02958343-88fda6df0a162605e52943dcb52313c.npy +04379243-4b2a7beb13fbe74296610c8d5ae64f96.npy +03467517-4709e55a82a63f64d57700c05b1862d8.npy +02958343-89c7e63c3d3d14aa17b597d473206848.npy +03325088-10fe88cb5484797d664b3b9b23ddfcbc.npy +02691156-41afa42c77cd167c2b5147716975ed8a.npy +02691156-c01746b173e0870b3a4cd082c6787017.npy +03001627-bbef67b2c3d3864e8adc2f75cf0a8389.npy +04379243-63e109fc1e40fda246b9f3b6ee20ff4b.npy +03636649-75cdbf96a597b57a29a42a0444436860.npy +03636649-bd0bbdadcd0b9fca7d57a0513a353be5.npy +02828884-7631a05d80484ad6d2b12aa6a0f050b3.npy +03513137-21d201f43ddd36c52fafb0cab311e6a.npy +03001627-5eb38d4e556a893a3b832d9b48bc2dd3.npy +04379243-b6a24109a5076d4ba5a296b0eec81c96.npy +03636649-84ab363e60b9bd9185d624cfcd9a37a7.npy +03928116-bfa3b2dbacd27547c124f92750a205ca.npy +03948459-898424eaa40e821c2bf47341dbd96eb.npy +03001627-8a5d60067de905336c183a120a388982.npy +03636649-d3380ee3db68aefb3f214ef9c53ac06.npy +02808440-ea8891fa9a19f8cb9e2e2edd05265482.npy +03636649-3bc8edd5ab3a2ddafcb8d8c6d4df8143.npy +04379243-6f87c833355679ef36b0f2a1430e993a.npy +04090263-f70396fbee1bf3f2f2866d10640f3af5.npy +03001627-4a48b39219bb7d64457ba044c28858b1.npy +03001627-acbcfebf917e708b2b5bf1f191733d75.npy +04530566-209f569f50d42f7e45e2a4e5729b970d.npy +04401088-e85bac837e951f3780ed245d94a6a268.npy +02933112-403661cbfc8deb029a50a2b3c5e5b6.npy +03001627-1fc918b0e5c7cf2da5c25aecef10278f.npy +03001627-d9bbd1a1eaf6d2259d3ea1c6b57a0095.npy +02801938-95385afe0390705a36b0f2a1430e993a.npy +03211117-d34a267fb332b052901fed29c825c894.npy +02958343-a77879318434261612725caceb9cca76.npy +04256520-a4de0830d9a1020e3b85980206d96693.npy +03797390-642eb7c42ebedabd223d193f5a188983.npy +02924116-fa47d3c4547b4d4fcf8b2866c5b881bb.npy +03636649-54a7ea6d6e297a849eb34048e600e1ea.npy +04256520-9c1b448ec62cb9fb36dd029536673b0b.npy +03624134-b0c7d11b2c7a3515eec6d8d24f1fde1.npy +04530566-e9cb5c7799f291ce51b48b48046ec39f.npy +03593526-c7fa54dc356f039d2f2318fdd66be40a.npy +03991062-eaaa14d9fab71afa5b903ba10d2ec446.npy +03642806-d30e41084edd4d73487f00a15f77c99.npy +03001627-abddac917b144928f91663a74ccd2338.npy +02924116-d236a2d3d923650aa3cfa46226644b04.npy +04401088-e2d49d74845ff0207e1c85c5c15da7fb.npy +03211117-3e1d0fb46bc7f84f9c4081063e213a15.npy +03636649-1ef03aab18277ff1ef3a2c64cef919d0.npy +03001627-fc369b19cfb50322492d9da2668ec34c.npy +04090263-5428fea9cd816d764fe44fa90b97c5ab.npy +02933112-6c7a1a40e645c48e9c22f14c4b6aad23.npy +03636649-d00157a022079bdef3655a2ce983ab1f.npy +04379243-44c35996414c4d89f1f3662486c882e5.npy +02933112-443a726ba9fa8d04d99265061a435799.npy +03710193-10e1051cbe10626e30a706157956b491.npy +02933112-6bf0f5e06cb748bb9671c58246946ed6.npy +02958343-7b57af1bd2d83363ea1216357e7f0768.npy +03642806-dafca3237829fef9f6fef4a0ba2e7186.npy +02808440-20c8ca22f5010bc81291d1279f7bf122.npy +03636649-3e1a71694488a4cd77b98fdac17a3204.npy +02958343-99fce87e4e80e053374462542bf2aa29.npy +04379243-9e560ee4c7438578f51f77a6d7299806.npy +03467517-576ee680a8aa61fbd4c2efa838ad32da.npy +03001627-f1f670ac53799c18492d9da2668ec34c.npy +03467517-fb1a79f06ffbcaf540c20797381ee39f.npy +03001627-23218bd682d522d19fb4103277a6b93.npy +03467517-f2b4f9d8f31d0dfcfffda81e9d316a1d.npy +03636649-33db0d4bf66731a7e7c7920f6a65a54d.npy +04256520-bb4c963786dc746855f9a00acc25f137.npy +04379243-3e760133301353a147cddb7c026e92eb.npy +02843684-91c3a3be8f8c5ed1a309fc846e6b0c18.npy +03691459-efb2eac3d84429d6363cbfdd3d5388a.npy +03211117-4b2a5a666ebcc1ae57c0e3dc4a759a6e.npy +02747177-c50c72eefe225b51cb2a965e75be701c.npy +02958343-e9738c96c8ffbdfdeae19b6e682da29.npy +04379243-b6afecd780203c81b9a51c308250e422.npy +04379243-cacf61ed869db8e7f84b0be7f50940eb.npy +03046257-3d18df96d6de08b1cbf3dda885c64a76.npy +03636649-ca6c2a23c86be64e2b93fb2743876c57.npy +02828884-1695ec4ee4d2e60b50039fe1590fc615.npy +03001627-e07c7d5be62d7cd73ff4affcd321d45.npy +04256520-901eff0fb9cf6e0646a3128b588876cf.npy +04379243-bed0b40333f195c52ea6ece84d077ef0.npy +04225987-30c835f06a930d356e6c9ebd9b889ec2.npy +04004475-2135295ad1c580e7ffbff4948728b4f5.npy +04090263-cf21d9de1440d3d203f35d9b3b48203.npy +02958343-4fcf76fa7f07a0008bb11dbc05ffaa74.npy +04379243-9665f677dff2405ef51f77a6d7299806.npy +03593526-ddad820c8cd5c1ee564eaedaeaa04f28.npy +02933112-1d7b04fd768eccb5f838a2212356e267.npy +03001627-434512cad2c10e09e8b2b8dc0c816caf.npy +02942699-db663e3f7ee9869f5c351e299b24e355.npy +03001627-987770212e08392d2c528d33bca1ac2.npy +03636649-3a29634236aa0596f9e8cd846ef13776.npy +03642806-6a360b7d69a4d522ce45dbec0d835ca5.npy +04330267-ae6e6b33ef0f78d8c9a835319c0150eb.npy +03636649-8adca6727b3275cc305056296c226e1f.npy +02924116-e887b5b410aa97d347eb2ab702fd92a8.npy +04379243-d903be5d4ceb3fd56eceb9b47ba95c.npy +02958343-1d5872004edf12038644d87f4c93cda7.npy +04379243-73a870e530c3a9993c77a85180cab6b6.npy +04379243-f979c7a650d29ea819fb4103277a6b93.npy +04256520-1b4cfb30e4f49edb4b3c42e318f3affc.npy +04090263-3aa24b3c616c2d649d5aeb7097eddbda.npy +02828884-6daa439badf26355593ebeeedbff73b.npy +04256520-3c08ae3ae78253bb73800789ccff9705.npy +04468005-2c7bff9607252a9829054625f34e281d.npy +03001627-800f60058f12a5243c2e0b170f2ad8bc.npy +04379243-898936a8b8e448ad1d70b774ac91773.npy +02933112-2bdedc5d70cda02cc59350d819542ec7.npy +03001627-66c791cf5f1e61a09753496ba23f2183.npy +02871439-60a120d9fd6d2e6afa910dff05693976.npy +04460130-f584f1a14904b958ba9419f3b43eb3bd.npy +04256520-82f8c687a9cf7dcd5dc3653f8341633a.npy +04256520-9cddb828b936db93c341afa383659322.npy +04379243-f2e6820ca69d9b7719fb4103277a6b93.npy +04004475-a3cbd7f73ef9107ac79ad43fc7954c58.npy +02924116-cda78b99ad19e0bf7cd3cf23748abfc7.npy +02924116-da206a22fab289812dcbe72a6f5292ad.npy +04256520-d13cd4fdf27074854b3c42e318f3affc.npy +03337140-10f998ca3f52fd7991c352d02061b3f7.npy +04379243-f294a34bf1c9ebb7f12d7184a2ad3430.npy +04379243-6af9a593129b028eb67e68783d58425a.npy +02958343-c5f77a00c9cae334cfd826dd468a5497.npy +03467517-2a5254c39a3ada8ab7f9d2da6fc61cf.npy +03636649-b57bcdb88c669663ec2a7a1f5fe7365d.npy +02808440-945852e568b5674a1c17aef130ed6213.npy +03211117-1ec7d9fe07b94f6e274d4393e80e99fa.npy +04256520-933a9330407d51b6a8cfd114c4b34e97.npy +02933112-a58e77d8a9b37e0280b9485fe431cb14.npy +03046257-a70d4a4cd569e7ae4e09ebaf49b0cb2f.npy +03624134-e4f610f36ba3c6f69246ea0301684d80.npy +03001627-2acb11399d4d6cc335836c728d324152.npy +04379243-70f9acbbc2881b7657629428a2666327.npy +03991062-79e00a2e90a0f4e37680453d225551f.npy +02808440-a00e66c628e452413beb0acbcd481c2d.npy +02808440-751e8ebf30e1045e54d7082b34825ef0.npy +03211117-5a440522b7df4cdf318d408ca5b702a3.npy +03593526-1a1905d6da94d9c7561ca0447e446f39.npy +04379243-b10d84b3a04085b17618b16b281bdf56.npy +02691156-92fb0d6a866fe7aca8607f540cc62ba.npy +04379243-8934c3cc317957db4637188d1bc69cfd.npy +02933112-b64d237b3718134b6e5b9257c4084ca2.npy +02958343-e23ae6404dae972093c80fb5c792f223.npy +03001627-3ae4d69fc1f9b15d2f008cb82e08f24e.npy +02876657-f2279b29f7d45bbd744c199e33849f2a.npy +04256520-f49df2996692bda02c528d33bca1ac2.npy +04090263-d7192df213be19cb365a9fccb786f8e4.npy +03636649-fa0a32c4326a42fef51f77a6d7299806.npy +03636649-bc4db3c90716f7ede76bc197b3a3ffc0.npy +03624134-40ccb8ac250e0ea5880595487ba7a30b.npy +04379243-99ff33b261920e8a55f9913e822d5318.npy +03513137-dfc0f60a1b11ab7c388f6c7a9d3e1552.npy +03001627-a598b87a9e37a438617c72672c86a49.npy +04379243-682263e19fe7c52d492d9da2668ec34c.npy +04379243-6ace903899706a5819fb4103277a6b93.npy +04090263-9b570b06ee8a7b6f56642b7cedd4edb3.npy +04379243-743992f3e73c7e258ba8ff316aec8d3d.npy +04090263-369127e85227fe5e218e4ad7111aa13f.npy +04379243-a88b21425768bce39f6ec855d7c1f09c.npy +03001627-11c9c57efad0b5ec297936c81e7f6629.npy +04401088-fca7558e383a8200a1a64f95774cf79d.npy +04379243-124c4b3afa6a3e56eaf288f952624966.npy +03001627-fbe08af112773184e6fe3612af521500.npy +04090263-3d4d7ae437d1153317c2892ca017a9e0.npy +04379243-a3ecb4d209807312492d9da2668ec34c.npy +03691459-56e41e5e3bdb2c8dec29f84f96a7e29f.npy +02691156-4542b5cf23a95691ca8607f540cc62ba.npy +04468005-3158fe582164b940cb2ecbd32dc2119e.npy +03691459-e637b80011db78c3dd6a08110bca7bd5.npy +02933112-76172d3f487ccc6cf4ab13f4b49ac318.npy +04530566-9b02ecc129d89000f4841afd366e16cb.npy +03624134-67b845419e36948dbfd8c61edd01bb6c.npy +03337140-2a9fe1253f9433d1a2651abaf391628e.npy +02924116-56c9074a335703c8c9684e1b606d6226.npy +02933112-763c7a6a8821cc75ed40cf95f720995f.npy +04379243-94ef4f9589a1577e123691872d565e10.npy +04004475-d4786d9d56c74302b216fb38ac0eb009.npy +04090263-311f3a46111ef5346314c3b6a3a65519.npy +04379243-41c027788c1388bbc48d90eef8384210.npy +03636649-b8e26fbbb44def8d1deb48513aeadf93.npy +03790512-103e3c517cd759657395d58407f193ba.npy +02828884-9a7847726c939d86c267d7dba6c1d40c.npy +02958343-7076464b3733aa38d2c2bfa672ed621f.npy +04330267-b41c827cde59b18c41965be83b7745a.npy +04090263-cb9255733bf39c58f2dfd8037041a218.npy +02691156-aa4df918db6c5973db6e67bf56014264.npy +04379243-ac864eb8b8a084756ddf5c10cced4ccf.npy +02924116-cb92e325a921477cb2396a459c8a8602.npy +03928116-f687d16e2b69a6d48a8cf1e3e05903e3.npy +04379243-4e08d2efcf14b7adee170fb6995748d0.npy +02747177-21a94be58900df5bcb2a965e75be701c.npy +03636649-da5f13f4048dbd72fcb8d8c6d4df8143.npy +02808440-10912c73b7290f963321831d2245cf06.npy +02992529-49ce3fc723ee4b362d43b5caea00b490.npy +02958343-d5f1637a5c9479e0185ce5d54f27f6b9.npy +04379243-59d4c154eea079c5492d9da2668ec34c.npy +03636649-d543465b35604aae1735ea0e092a805a.npy +03593526-82b47431bb7a115a797bc94512844136.npy +03636649-9cf1c74f842be30624a15e3e5e0014a0.npy +02691156-bc48b77452fd108adf8f666ba0e601ac.npy +04379243-12936ff9bc1103944b3c42e318f3affc.npy +03211117-cab3f094677c1070202380f1becb8a55.npy +04379243-73d02435d9e077a75e062e3835b2d911.npy +04379243-1955e341a77661a749684afbca35f3c6.npy +04530566-44a50dc1a9d8a8a65144962e2c20b832.npy +04401088-597b3a321198f0a029b6ce1cfa22349d.npy +02958343-27645458fec3d7ed514e3d96995c555d.npy +04530566-969163f17ce6467d9378da473ee38a8d.npy +03211117-3fa2125a637970e2dc43f1f9f0a849c6.npy +02691156-6615bb23e68159c193d4024985440d4c.npy +04379243-15f0878e6bd57e6c417da6e71c86659f.npy +02691156-fdcb11fa39661f0fb08f81d66e854bfa.npy +02828884-82b8609a6b1dd9c1c1c1ff0fb1d59ad.npy +02808440-35cda808679bc2544221bef0fa3c36b.npy +04379243-14e1d60337a533acea003eff0268278.npy +04256520-34d7a91d639613f6f51f77a6d7299806.npy +03467517-93ee32a4660864eb1c91d5bf986c0423.npy +03325088-1cc79cefa63fa41d2d3adeba9d9c3aae.npy +02992529-25152b4f593e5c0555940ab8fd747fc0.npy +03001627-85c2609fc7a511ece32cefe0e484fed3.npy +03211117-9be4d56513c06315a045e7ca381c39f6.npy +02808440-b27bff29f03406c63321831d2245cf06.npy +02933112-26dcf7a76c89d5aa4da5feafe6f1c8fc.npy +03797390-83b41d719ea5af3f4dcd1df0d0a62a93.npy +04256520-9f575d367e59591128fff7ee99dcfdf8.npy +03211117-3351a012745f53a7d423fd71113e0f1d.npy +02691156-da7354a90e6596e6139336f03eb955d2.npy +03001627-51adac207965e93559f8e31ca87c470e.npy +02924116-93bc3e5c081291c2fd8a70fadf367c22.npy +02876657-b8fd592b4b5dcaa41aa761bcc4793321.npy +04090263-62217abb02b74e9deda1c1890030d195.npy +04379243-993ce4314e32140f38454b411e0edc29.npy +04379243-41cdb5b619790d5a74eb542502c2205f.npy +04379243-d05ff7b47febe58a656db3f863b4b796.npy +04530566-e738f72e4c461e79cd202a4790115f0c.npy +02828884-94ac417b7ec10bcc6420261eb2dfc717.npy +03467517-48d8c9000728c71d9cfb8e6f6728789d.npy +02747177-632c8c69e7e7bda54559a6e3650dcd3.npy +03991062-5b79c55d2266d4f272652f4081ec5a77.npy +03001627-df7fc0b3b796714fd00dd29272c1070b.npy +03928116-5a91c90b73671e35b249ce9318fa571.npy +03001627-df8311076b838c7ea5f9d52c12457194.npy +02691156-38884564ee0da15798494085d68ad6a0.npy +04379243-c094e213b2199035ed90a8a4ccf0ca93.npy +04379243-6f957742745697cbceddef1607dd507.npy +04256520-29fb859b965bc4af691e0e3fa7867bda.npy +03636649-50cade4e6f714f2fc72e6d708486db91.npy +04379243-64aa142f104b99379a535d0a5590e4c0.npy +02808440-9e0e6ad9f5fb863bb362845c6edb57fc.npy +03325088-e1e7f5f1d431e77f6d0157e3e7a8917c.npy +02958343-ab2759c8e0cf3b8da9d243597c4c2c2e.npy +04379243-611354b629b71f72d5b708f09789d978.npy +04379243-41e1dd0f69afd7b093e18ebd46d61795.npy +04256520-baa8760ca5fbbc4840b559ef47048b86.npy +04379243-fd861b13a3fb637e463650bb8b4560e7.npy +04256520-136d5a16b110c84566b7da89cd9376ad.npy +04460130-aa20fa2c82a588d381b0d56f7467d8ca.npy +04256520-a4ecec332f0ac0d22906e6acfda251cd.npy +04379243-399b6e11c037f7fb5a11acddfe168a04.npy +04379243-db64db160fd13a514e1a714ee619465a.npy +03001627-65840c85162994d990de7d30a74bbb6b.npy +02691156-85d3691b7bde76548b96ae1a0a8b84ec.npy +03642806-d380e53dafa66c1a86a7e0484f5238e4.npy +03001627-c2ad96f56ec726d270a43c2d978e502e.npy +02924116-638f96b7300e754178d5e65673875191.npy +03467517-2105dd5dd6a40240142846fc3207334e.npy +03046257-299832be465f4037485059ffe7a2f9c7.npy +03636649-c125ab8675fdc2b03225afab722d9fd2.npy +04090263-156fbb9dc2645686a3daeaea95a3adc4.npy +02958343-71304f56bb1165e7f42b5c72b4901f94.npy +02828884-d41ba8cd6a5b1071c1237601d86c1b5b.npy +03001627-b38d05caee69c7ac8fc6229eb64e56a.npy +03001627-38279fe5f442d95f458feb88086a534.npy +02828884-4ba9cbd97e4fb17a75e6bc7c944c5642.npy +03001627-17b7a0e3c70dbc3d90a6b1b2b5522960.npy +02691156-b23e79036b214fd4ca27bba175814d1.npy +03001627-74cc57ea0e2e06dbe4106b1d06dc89b3.npy +04530566-d9e8f45b4cd81f0fd1c387e16c0a41b0.npy +04379243-32f116e50ba1dcde7ff6ace05b36a5.npy +04379243-2167f82caf4ed2309eea323f522c6486.npy +02942699-ce40b134b11e8c822bbc2c380e91dfe2.npy +04379243-5315fe89ddcd618a6b9a552adee29b1f.npy +02801938-3ebac03588e8a43450da8b99982a3057.npy +03325088-194ad4c66c27718b603f99a15dbe4cf7.npy +03710193-7970cdbf8b2f60922ccc07812ccf5b3.npy +04256520-58447a958c4af154942bb07caacf4df3.npy +04256520-beb06b61dad3795c95c7d6b48c371712.npy +03991062-7ae8b260ffda13745d90c2f8862ed5c1.npy +04256520-a6239b94b8def78a2f7a42055c3e9340.npy +04090263-86baf335855c96d212b38b1d99376c0b.npy +03593526-6628119d7cf6ca8b82db9fca4b68095.npy +03513137-bab3a20dee03a0f0e4773d7a183337d9.npy +04379243-48ccce122177c96c3dc1643807625350.npy +04256520-10f2a1cbaee4101896e12b33feac8da2.npy +04379243-8478187660d5443186915ea7a2083dcd.npy +02924116-2466d6065594dbd373873da0bf53928f.npy +03325088-bb727c220cb940bad3ac876afae3fa86.npy +03691459-27266a732bc955e4db965514105122a4.npy +02828884-3a8f4586fbd17e6d56f6fc4b4ce1db04.npy +04256520-458bfa76a934921f4494e96d71433541.npy +04256520-fbd0055862daa31a2d8ad3188383fcc8.npy +02992529-2266b891f080ad7eeb2a3da43bd37462.npy +03001627-a18b3364ce7ca94d5921d1ce0656232d.npy +03001627-8841a35812d5a95f98a4820926b2a786.npy +02933112-1b32d878eeb305e45588a2543ef0b0b4.npy +03046257-c00fa590249faaac140ebdd4d6d66fc.npy +02958343-d6b7bb6c6203fd9590f0aa5ae25c9b7e.npy +04379243-72194d338303b1b155d7f0828042fbd.npy +04530566-45642e87b3904a1395f5b96bf7fdcaf5.npy +04379243-6c844e3f4a99bc3ae8375def5e736d8.npy +04256520-8481271bdd974c424b3c42e318f3affc.npy +03001627-1886b3e3f3d4af3ace522e6dda26fb51.npy +04379243-6fa6f986755409b77f4b44e9ef57971b.npy +04330267-a036b70289e45fc177fc9677e91cfd1b.npy +04330267-830b31818f5b91474efc7e7114f1b9c5.npy +03593526-4689cff7bb28dad35425a71c247ca5d1.npy +02876657-a4a6a464cb1db9286bdbc69440dbff90.npy +04379243-26797a03b7940d43d9a7daf2d70e57bd.npy +02933112-4946c14a466fb5094da5feafe6f1c8fc.npy +03642806-cc596eaa22c3e6cf37e1b9ea967d5071.npy +04379243-266ba504ee57b85c5298386582afecd3.npy +04256520-ae4b600e137214dfb675aa3c10a97f3a.npy +03001627-b526dccbbe8417bd6cf45f1c1a3d29af.npy +02691156-ff77ea82fb4a5f92da9afa637af35064.npy +02933112-5b6195448cbcfc04b8cac7fbb9e49985.npy +02958343-a34dc1b89a52e2c92b12ea83455b0f44.npy +02808440-d319ba92fbe38bf4429d80a62aad88ab.npy +02801938-f870bedc47fdbd287ae6f33544c233fe.npy +04379243-bcfda4ca76d65ca8d4eb6d6477feba27.npy +04090263-5cb8be7d0224277b74e18e0e7a19212a.npy +03001627-458637d073cb6e9dc8687ff9b0b4e4ac.npy +02958343-1e6ba139bec5e49dd9f9c2955f462abf.npy +04379243-84f5e52756fc84f86df14337f24e49f4.npy +02942699-d6721b4ee3d004b8c7e03242f1bf8d19.npy +03691459-3a346d78102ca842b996cd669da05484.npy +03211117-7a5a80c7a2d89bc6728fa2df514c65d4.npy +04379243-31f09d77217fc9e0e76bc197b3a3ffc0.npy +03001627-c98e1a3e61caec6a67d783b4714d4324.npy +02992529-33cd4232a87e1f416a1f7081746396ba.npy +03001627-e7304e89fb763e45507243968c1db8f3.npy +04379243-76814dd29a8fdd76e400ee8c5c49a7eb.npy +04379243-4e855038d6060cbb47e81ce1f9a6ff7.npy +02691156-e0ad511aab31dfdb3e237dc81fd8be72.npy +02691156-655dc5a5376e9c8152c3271e911ffe19.npy +03624134-2bf31f2abe9aad6d1a768998fd92e128.npy +02691156-487c60f57489506d5d515fd83cfe3891.npy +02958343-718bfae0c87ad9fdb04112587bd2b79.npy +02924116-7c39944cf7564a05c05ee00ba679322.npy +04379243-a3d05dc39ca639bc662cdc2f77e49a85.npy +02924116-3fe3cc5389773fc21f3f27ff04a4459b.npy +03636649-e474916f1ee1635e0bc0e32d71e297.npy +03001627-35c3575340cc8234456cbf78e1e89022.npy +03790512-a94060c97cfa0c6350bbf5cd198b144c.npy +02946921-91a524cc9c9be4872999f92861cdea7a.npy +03211117-bc690122f4a3646047dd811b692e315a.npy +03001627-66683c677e7b40593c2e50348f23d3d.npy +03624134-423adc73596672f08bad9bd0c4ab8e3c.npy +03001627-b856a62e23ef65324b87db09ac4cfa73.npy +04530566-a31a0ca1247e23ceb1bb46d2556ba67d.npy +04256520-7f0bd726971e34eef9aec59741c69cf7.npy +04256520-a6acd78fda77bddc52862c62c571b1e.npy +02958343-e1c16a07b6e974b951a95aaa6caba1d3.npy +02876657-4fcb653e7978812d9c3900c9619d4db4.npy +04379243-e44531f7204b6fb9fe43ff1e45af424d.npy +04530566-c6bc9330b0a75d83cc73edf5d735208.npy +02876657-1cf98e5b6fff5471c8724d5673a063a6.npy +04401088-5a7e19fca06d2bb7f2848e928a160066.npy +03636649-af3d58dc258e0fe06ef604d255267aae.npy +04379243-ef92a53a5aa6ce008f88435cd882fb0c.npy +03624134-df6ce028a9a0d8178bcec9d54ae64e9.npy +03691459-84adc06696eea1774a2b8524bd5c98.npy +02828884-de80be770d51dbf53567b82c74e275b4.npy +03790512-aea3c4f2687e97c92942fa3063963cb6.npy +04256520-11007f74b06bd90c518b6fc7ed4f3487.npy +03642806-f811252fcd1f7d686845a0762dd07baf.npy +04468005-4ee9bd908e79cceba09163d0bb607639.npy +03085013-a5349bc8e3a7ff77c600925618bc4f77.npy +03337140-e58274d0771d56f77984fb9ec7e40829.npy +03636649-ef9e0709f535c549b3914c1351b16c4d.npy +04379243-eeb23be65d6c76123199fadac163f8c6.npy +04379243-ba8378a73db72f51febad4f49b26ec52.npy +02691156-68899f486f3a6015ca8607f540cc62ba.npy +04330267-51c2dac89ab9db802f79567a8778b1cc.npy +02808440-6bccbd29c44ea50d54d7082b34825ef0.npy +03636649-9282928d320e83091735ea0e092a805a.npy +03642806-55a05b33f34e7211f71cb38553f14917.npy +03001627-7fa5ce045ee0a286606aad310bc344b7.npy +03797390-9961ccbafd59cb03fe36eb2ab5fa00e0.npy +04090263-69252c7838ace59f8aa7cb0651220ba4.npy +04379243-c5a02d586ea431a1e76bc197b3a3ffc0.npy +02808440-29ad8134c0e600c458661a3fa3dffb70.npy +02747177-fc62acf82529b74867964ba700cd97f5.npy +03624134-67802020163f6b8c1395331ebe4786cd.npy +04379243-b00d6677641be37dbeedb4c8fd29e2d1.npy +03636649-348fa2fd3af7dc0a4016a312c4d162ae.npy +04379243-4e87db85d5dab96822339a4b4aacca6b.npy +04090263-6f447ae319cb3f8c95822127460cc765.npy +02958343-457ef8db81db726909e2381adbddb4b.npy +03046257-b7b988707b63c048c5c6c5671b8e3bb3.npy +04256520-a015c48d41079f9219e48122ff512ea5.npy +02958343-6979a814a64f6da8becf71e2e014ff6f.npy +03593526-9e8595c3bbb0a5d0ba5342d638d0c267.npy +03001627-3919e93cc1f3bf5bd7f7a4c4609b0913.npy +04379243-9d63f4971a332c55f7628281ecb18112.npy +04379243-b69df94b39931f196c8336429b11e233.npy +02871439-3c6b1e5888e5fabd9463d0e381798ed8.npy +04379243-12b1fb7c765dfe8eb76e29c9c43bc7aa.npy +02691156-326e859d86a8078427eb9e7911a17418.npy +03467517-cd26da8e82da2ff36212ceeee46a9894.npy +03001627-9ab4d3826bd2f07b51bb569b4bf0aada.npy +04379243-ed320d80089655bedf6cfab91d65bb91.npy +02958343-d967be366b99ac00bac978d4dc005d3.npy +04256520-17c61068a15115a87c2f226180343d2e.npy +03948459-708e38e7b733fd22bfae4699de9cb91a.npy +02958343-36b211593bfa7c2f7f33a9b0659de0d7.npy +02933112-600d06bd779fbedfce5d6e9371bb5c33.npy +03636649-a54ea55a07b96a237b2bb75885cfc44.npy +04379243-7ee81223e7a4785ea7866257ee5db61e.npy +03001627-76ee694df725b5b4664b3b9b23ddfcbc.npy +03624134-854e7bb73afaff7591ea3afb2749822f.npy +04379243-b21a6839869018c6ab10c969b34d14c2.npy +03001627-7f4f73ad1b3f882ba14472becb07b261.npy +03991062-4996f1c0120f4c62ab361b6be63163da.npy +02958343-f45268c928a4b3fc8bc584bb94b0b13b.npy +03001627-726996e3177354cf2095dce957a7a5d.npy +02828884-516e288a1f609250d2b12aa6a0f050b3.npy +02691156-7201f2a0f410dd0ea79efb489d71d723.npy +02691156-e51bd7d434d1ee6622096c1bee7ddc7a.npy +03624134-581bc5e4154baccbadbb944d3d9cad9.npy +03636649-817c0b1b85437923e7321f25048c6142.npy +04379243-fb50672ad3f7b196cae684aee7caa8d9.npy +03691459-f0f9a2082454542751dfe6844b6e8393.npy +03211117-f47044b611046a7bf901627f525bf7a.npy +03325088-f92135b11ed446bed42b9650f19dd425.npy +02871439-c947f9834b2e3dd66a2c9acfda86bcf1.npy +02924116-514623ec3be9f8ac9f46749e28e16975.npy +02828884-582ecc11367a2aca2056b4bd5d870b47.npy +03001627-fb794b0b3260794bfebad4f49b26ec52.npy +03928116-a51c7a09c0bd3e8535a276fbe43f61e5.npy +04401088-f0b3e6f5bd34ca3cf0c6f578f0594c3.npy +03636649-a0812cee3fff72103ca265f557f5dc3e.npy +04379243-e0caa2e794d98c814c9587cb3f654544.npy +02958343-37ad66d0433beb633df8f4ac45647158.npy +04379243-994fac397c6246beba878f7904755875.npy +02958343-37e781aa8ae8933a61c6c61410fc904b.npy +03761084-46dbba829a57ace8cffd61677456447e.npy +04530566-2d07f2ed9c3d78b33f222a37719e9945.npy +03948459-d0116dcd5bf9b88fea96bfd37cd8bdfb.npy +03046257-ca9d22c90fb687e045a3ee2cfbb67212.npy +03001627-bf01483d8b58f0819767624530e7fce3.npy +02691156-babf58c69501ae6b9b46c030f642fc41.npy +02958343-1b85c850cb4b93a6e9415adaaf77fdbf.npy +04225987-710467261256490ce1bed90743417b0c.npy +03636649-da09a8c73054e9220ca3aeb14e36a45.npy +03797390-d75af64aa166c24eacbe2257d0988c9c.npy +03691459-14e608a76c6b77bdf6045e4ebc9df52f.npy +04379243-8421fd68fddd2a033f40a91f25bb93a.npy +03046257-5924dd5aeb057e576ef2faffa907bc32.npy +03636649-11913615a1b732d435836c728d324152.npy +02828884-895563d304772f50ad5067eac75a07f7.npy +02933112-bd89eb4a7407f07e54d8afaf6caac97c.npy +03211117-f800fbcdef1ac9038b5dbcd4be5ceef8.npy +04379243-b35bba0caa2faa642eaa34003788a9a2.npy +04379243-73ca85d8666e7e26e836e479c0864af1.npy +03001627-218233bd68f5261dff318cdb0cb45ca.npy +02958343-4b67e004d83d62bca1aea50fbc4b17d.npy +04530566-72a9394882b8151bef94bcb012573cf2.npy +03593526-ee81529fb1ab07754b3c42e318f3affc.npy +03337140-25ec4822418e70cc91c352d02061b3f7.npy +04090263-3925a46f22a5587551f49d4582a8d17.npy +02747177-676aa5ae01563ba9ad5067eac75a07f7.npy +04379243-87c752e8280cfa2316a2500eff5eef3a.npy +03624134-bcd5c95026dff530542a1605686ede02.npy +04004475-2263c8fa2d951833ecc46197d5349c6e.npy +04090263-c8cf9fce86c7bcb3b38e8b1e877a5704.npy +03001627-1fb9ffbcd38f8ba63eec26c23f5bc80b.npy +02933112-88e89b29e8100f1c1bec2e8246842c2a.npy +02992529-3f4a507d616678da650fb6b8f6bf3419.npy +02691156-4c008f39378be18bc0909d98a1ff2b4.npy +04379243-3804253f3eacff56a55e6ad8c321a190.npy +04379243-97f5d86912ce0f872caaf8842dbb8ac2.npy +02958343-beef4a450e0d42db6436916a86a90ed7.npy +04379243-fe84ae93e0eac1e45b903ba10d2ec446.npy +02828884-50a3b398b3a2e5979ec4bb690ca24962.npy +03325088-228a2b60a63135eec36fb70296e45483.npy +04401088-4116965029bd24393423610e52061098.npy +02828884-c79fc66b27a900ac842d08202a7fd76.npy +03211117-9e1b897c08a6a91f94cedf1e55d56e03.npy +03991062-f4fc8dba27f70ba8d4d8765e3910f617.npy +04379243-307474fd0cab5c982fa77440dcb93214.npy +03642806-2d47af483371ff60672faaae04fc887.npy +02691156-fc2c9fd0bbd77dac4d210d9468aedaf2.npy +03337140-6479718ba7e517e6492d9da2668ec34c.npy +02958343-8d560e44c4eb588d4fdf31cc2d78fd0.npy +04379243-95483e7754185e03986b14b31452df23.npy +04090263-bf76395bab45ffac2249915e95f55f08.npy +04379243-25bcea593e4314c3436e6787c76ef3f0.npy +04090263-3be0bc4b1169ca4959db9878902bfe69.npy +02958343-25480875a6be8e11afe1d4530f4c6e24.npy +02933112-b13778ff6594e980605de7eae9f0b0f4.npy +03593526-507b672473eda11032a1eca0e8e4f468.npy +02958343-65f0321c5aa8c303a1936d27bf774e9.npy +03325088-576e6b3d7b188fe9b362845c6edb57fc.npy +04379243-e77fbb3e21ccacf1a03bb2c2325d6f92.npy +03642806-f9f484e4364663d61bb5a64b9a0f552b.npy +04379243-a31e317e57540f3ffebad4f49b26ec52.npy +04554684-452f7e16dcf5b2cf46cde67a6a1ea328.npy +03991062-7eaf07e7139f5832a2c59a4d90e63212.npy +03636649-3889631e42a84b0f51f77a6d7299806.npy +04090263-5a2232cb9dd25917768d4c3a89626da8.npy +04379243-22cb00fd7f4d016429b55029703aed8d.npy +02828884-976636850849c3d6ffd996335233167.npy +04379243-f7646a27fa757afe1829bffea9d18abb.npy +03001627-32a4ddf426cef33c323ad87fe7d4deee.npy +04379243-faa36ee5b5a296ff7e66b3e5c11f24d4.npy +03467517-3839f1edddecf07c502e2eeb62a0f66d.npy +03001627-a5d41f647e7ae9deeaf288f952624966.npy +03001627-1c758127bc4fdb18be27e423fd45ffe7.npy +03636649-4b48b7f72cb4f56ef00f0216ab99ff30.npy +03001627-db549976c0b7b960d42ec7e303174a87.npy +02691156-167740d2a5f5cb6c7f4561609781d8c9.npy +03001627-929ab79b4f45f747e6fe3612af521500.npy +03001627-a6009749fd05fed82d19175e7d19b7cb.npy +03325088-d9e81180a1dbd0a550da8b99982a3057.npy +02747177-dddfd6b37ca28647167a483e22d2eb7a.npy +04379243-70f408c759664b953f99a25d2bc1902.npy +02992529-4b72058b03234d188a81847056b4708.npy +03991062-cc7c12306cc3785fe15a365ae69dc5c5.npy +02828884-f8ff2310c6b130d38aaa31e538081318.npy +03467517-3a234019cd1da956fd3e16c646c7a0a1.npy +02691156-c489f0cb96399da63c326782eb2d380e.npy +03001627-a98b128938b56846ee316b26c8d85c48.npy +02992529-4b91c9711ca991768a57ed2dc0905847.npy +04379243-8963760f8bec0fee7f807d3c406ee.npy +04256520-f114b76d551b5e5affcd08faf4fccd0f.npy +03001627-21da49c5fccfc3e68d861be5b561accd.npy +04530566-6b72a64f1a6a745ec99bbfcf5650bf52.npy +03001627-a36aa9aef138fdc1377b9297f3055210.npy +03325088-1818f3ba4874e5ab362845c6edb57fc.npy +03691459-7998efe14649e07c397a4ece637a5.npy +04074963-a6a121234c2077d6dcd16fe97fafc2c6.npy +02828884-8d1f361eb7a927d8907921e9162f6a43.npy +04256520-70cf74bb4e1e14dac15fcbb4bdbaf13.npy +02933112-47e09607098c43b5768049e7324c832a.npy +02958343-edc9a70958a17433b1bb46d2556ba67d.npy +03001627-896303208667c3e9713decb1a0563b12.npy +02691156-273e90f5c26654ea8b96ae1a0a8b84ec.npy +04379243-ffd45a17e325bfa91933ffef19678834.npy +03691459-bd2d91052e6c10804c6c80caaf15808d.npy +03593526-44e3fd4a1e8ba7dd433f5a7a254e9685.npy +03636649-d5a67642ff0a2908dbfbef883e8d10aa.npy +02933112-e2de47fd0e63a280490ad276cd2af3a4.npy +02958343-481999bad4bfe8bd3dc7f272b20d8426.npy +03001627-916a6ff06a128851ed98cca8f0ccd5f7.npy +03001627-4978fcb47c15f96dce88197ffe0c21da.npy +03790512-edc4c7a08293697db37378f3c85478b4.npy +03636649-a22c4d43974086de31ae8c8ff1eb3d45.npy +02691156-9705e3c2d21106ced7f23cd024f22c12.npy +02828884-bb020b7d9c7fca9cad5067eac75a07f7.npy +03636649-a51f72154f09a2f926d49ab26d3c4ce6.npy +02808440-125720e2aad7cbae412ac8cccf0c180f.npy +03001627-b8772904c25b61ac6b2befe83a0efe39.npy +02691156-59b851010f0aef7422b13c48c34706de.npy +02880940-95ac294f47fd7d87e0b49f27ced29e3.npy +02933112-dc4e9bf3eaadf2544c62bee40dcdc539.npy +02808440-a5554278ba72e07213d2510999d0f1d2.npy +04379243-e48675e37096a6898527e24d5de49fe6.npy +03001627-6e5c0ca5ee70c88b77dbab4c80b965e5.npy +03001627-4f243d655c40702ec772d43f7a27a1e.npy +02958343-4270f4f3372a1b24546b7395fb17f97e.npy +02691156-b8e4e4994d4674cf2023ec956848b741.npy +02691156-22393fa9307224ec853c6f214c15e60f.npy +04379243-21227197948fd2857c2f94a943a8669b.npy +03046257-289850e742ec351bdc7cb2def50cc404.npy +02933112-964258d29263afdae76f0f0566cf10f2.npy +02818832-e154ac0ffdc047b8729c04438af8eabf.npy +03001627-3ba15bab072af6ced014b923da2a041e.npy +04379243-3a52892dc6c06efeb2403dba7fd079eb.npy +02691156-78789e98f905fcdd9107f68a9cb8e3c.npy +02691156-5d81abbccc11935b4d4cb1c2a5e48b7a.npy +04256520-83d39faa5782395b651fb4677c188d35.npy +03001627-72fe5266a93c1998dbbc9440457e303e.npy +03001627-a4bf3b34bf49c5aa799b0b9a0d4a12cf.npy +04379243-3ffe22ce4ede7a187886a3eca4dfc4ab.npy +03001627-669a23c329080506d295b24579cf55b8.npy +03642806-29f5cfcef7272f1f640578ae55230ebc.npy +04330267-bee6f7918373cf8026587cb13c78fb9b.npy +03636649-2ce7732982343c1d9792f6094a78f8d5.npy +04090263-337d3642a2d949a4f58d2dcaa6073061.npy +02958343-da82ba81a8fb0737d06f1bbd2acc051.npy +03001627-43c71ca7f9d3dceb8b0742c681b435de.npy +02958343-6208c5fcc94fb6ddafec9b6a5ecfd79d.npy +03001627-43f15ce32c7c97ef19cb07ecb5b4102.npy +02958343-1159faf9bf78998493680c5a9a367b4a.npy +02691156-5f73e503595094b783b772877a547745.npy +02933112-25c3964cf7a607b1f51fa0238791f5dc.npy +04090263-f3298345f6d6ed3dac4f72bf08dc79a6.npy +02871439-b8e455419b42c77e262b272ccb3b11c2.npy +04256520-1a201d0a99d841ca684b7bc3f8a9aa55.npy +02691156-cc113b6e9d4fbeb23df325aac2f73830.npy +03797390-c6b24bf0a011b100d536be1f5e11c560.npy +02691156-22ce6f6d1adb08d7bbf3143b1cb6076a.npy +03001627-d7e4851fb3001a10f652f706160dc96d.npy +03211117-6a743f7ae8deade97e0bbc356ce23758.npy +04379243-45bd3bed8ef1315ed42ec7e303174a87.npy +02958343-40953c3fd24e9d65ecf689885b7c1e59.npy +04379243-3fa5372c0ff38e447135e387a71e9d31.npy +04090263-1639ae190f0e05196df38a7dd1b448e6.npy +03001627-769b26b459617608b04cb542e2c50eb4.npy +04401088-f66d8ca1f6b259de2a9eb0f146e94477.npy +03797390-6aec84952a5ffcf33f60d03e1cb068dc.npy +04379243-c35a4a82cac49ecc55f46d55537192b6.npy +04379243-91ed62f2b3fd5919f12d7184a2ad3430.npy +04554684-8f9232a493ccf77e46cde67a6a1ea328.npy +04379243-1b5e501a28921c43d46cc1240811b39d.npy +02958343-2a82a66ce6273dce601c8ebc794de3f4.npy +02691156-b75575684fa8ffaeac7e7b41e1ebe3e4.npy +03001627-85654bf43265664eca5d1f82257fb9d9.npy +02933112-8e897603bc5217174b8710a3469971b1.npy +04379243-5d82e3924ace17d814038d588fd1342f.npy +04379243-138c29cb642dcd6352620f29156438e2.npy +03001627-a838d73a1ae66934b161f36d4e309050.npy +03467517-4bcac7ffff02037f624b30f45b82fb10.npy +02933112-55bfa46d7b39f4dcc59350d819542ec7.npy +03624134-3ad3c5fd3ba04fdb12cad8be168fe72d.npy +02691156-f7739764eb1c78a053f370d353cea84.npy +02691156-a3bafea9edc457463da2ae40e7681e7e.npy +04379243-15ceba504a820cdfb4c161851ed2b4e4.npy +04090263-4c727a571a5226549a6e43b878d5b335.npy +03691459-569fc1b111617f4038b28f94c165f833.npy +03467517-a0f18369bec03d61e32ec871de9544ab.npy +04401088-2c6d9512b4013504ff0682cfb57a62dd.npy +04256520-104256e5bb73b0b719fb4103277a6b93.npy +04379243-5243b5491a4f8a16a2b5862518c93.npy +03211117-dada218e78c9c81e2250bf58700b4d8f.npy +03001627-747d2db60ca6b98f3eec26c23f5bc80b.npy +03636649-6999ab054bc900d1868fb986bc092533.npy +04379243-cda35fec5923a8602250bf58700b4d8f.npy +02773838-e6daa1435018a044da5feafe6f1c8fc.npy +03001627-b81be96660f38a8c7543d7dbfecfffbe.npy +03001627-5b185142b33f3e45c3bd24f986301745.npy +04379243-6f2fa876147a970c5acde0d39b1b9dba.npy +02933112-962b62d2b3823aff51f77a6d7299806.npy +03001627-33d8a82696afadcbc3e3d5df2a6ddacc.npy +02808440-1f0ae93f9aafbe27322d134e1c4a80fc.npy +04401088-d37afdca0c48251044b992023e0d3ef0.npy +04099429-d781243cc1d1d2e91a0ec553feb1c2c3.npy +04225987-776eaffd7cbe7bc6b9e8bdc9c4a49aa2.npy +02958343-49a93fdbcaa0302ae434963ea517a487.npy +03211117-191bc5c03d27789379857d0b1bb98706.npy +03691459-61ec03d50268a852d4c639228615260.npy +03636649-6a11bbf62bfb5a5a59f8e31ca87c470e.npy +04379243-7607b1762ab9c79719fb4103277a6b93.npy +04530566-a346005de2c522e9c9078664355a9ff2.npy +04090263-49429e1d1e90c1ca202be79d8b285c1e.npy +04090263-3332ad937d4cf220d34156e5a2f990b.npy +04401088-60193289e8d9689b62f6b877265e2679.npy +04379243-a4b1d784abd7eba15b17dbcbc75d58df.npy +03001627-eabdb3aa920b216820b64028d2efc877.npy +04379243-1c90216659d7b97fec5d8105ca6b7dcc.npy +02691156-f25da5eca572f01bd8d90babf3c5509a.npy +02871439-d7f1a22419268800e76bc197b3a3ffc0.npy +04379243-f0c1fe7cfedf97e9b91b871e750ca615.npy +04379243-a392cd632ea01b6f53a71d150e481685.npy +03991062-81ad2114304874ccb7a1efa8b86b495b.npy +03001627-21ba49d0622c590c8a93d439b5823fb6.npy +02958343-65c225fae513a6dbe7b23463fd9b0ba1.npy +04401088-9adae247285e9538836a2d8722d73dfd.npy +02828884-12ae14d584758b4ee42c56c78fb88524.npy +02691156-7462d130f9c7abcd5e9e2656aff7dd5b.npy +04256520-465e28e9cee51df8d5cb6d178687b980.npy +03001627-1ab8a3b55c14a7b27eaeab1f0c9120b7.npy +02828884-af06152e440a5224e23bd316353fa056.npy +04379243-2ef075a7b9433b06b2b7d07d6c0cd464.npy +03325088-7ae63b6abb0eb0f4b362845c6edb57fc.npy +04256520-d52584133659bcb24b3c42e318f3affc.npy +04379243-a6681ac778c7c314843f1df79528e538.npy +03001627-27700c06980561845c7f80200eb528f.npy +02958343-d63110386a6bbd52d647b1c17442c93.npy +03211117-415b39d4f60a36d742274cb89cb6c841.npy +03636649-e293003f297e155624d1b7c6bfe44fcc.npy +03001627-ea1566ac9fe1670d3b622c8598928cdb.npy +03636649-e180510d07b65fff571108a6d1e94edd.npy +02691156-e9704a563a5a0a3f5a4b8d382b9decda.npy +03691459-2eacd8302d46093ee138e561e8f9c254.npy +04379243-d3fd6d332e6e8bccd5382f3f8f33a9f4.npy +04379243-176e6b9b4340f25a7ff6ace05b36a5.npy +03636649-22315c51156a826525b5da4000a94497.npy +04379243-9199b088ede8a2c920768660cf080d12.npy +02828884-85db4f1bf9e2b62c492d9da2668ec34c.npy +02924116-4fcb65468c2a5a56592ecd319dfd8c5d.npy +03046257-eda7c21b3ab9fc61592f292ab531da8.npy +03001627-99e2f8ae1bef62dcb74c46f4848028ad.npy +03636649-bf6674af4ba8b95fa4080573400e0dc9.npy +04468005-87886a91100844985f72adf4b0bfab9.npy +03467517-58543cda179fda8e6761cb5f9159210f.npy +03001627-90fb9a742f5a0cedc9736640ccf985f5.npy +04256520-93e20cc90bc4ead618a6353ea60f11b6.npy +04379243-3e0f8c39a72f3c91200ad3f421b6c3d0.npy +03001627-43db37a72cbe0f5d4ef0f56ac2c64e7f.npy +03001627-aa4b1153a1c4248930e06a011e63236a.npy +02691156-91e3ab3e12059b4a9d92b4de623f5639.npy +03001627-c42bedf7a36202309056fd4a77b3a4bd.npy +02958343-ef7f623beb7260287b5adf84ce6f7865.npy +04379243-1fb025077ea5546bf7af398806a30cc7.npy +04379243-5b3b19203b5da49c310af74324aae27f.npy +03001627-3fc1e991fee82e42713decb1a0563b12.npy +02691156-538f0b5ee7c786e6d3b936925082270f.npy +03636649-c7c15b7d23fdfd98808760409d52a60d.npy +03325088-26abb7085ac6d50250da8b99982a3057.npy +04530566-fef52f113f59137dc541ae04c251c7da.npy +04256520-f398deceae25a0e752ac884aea4686b.npy +02691156-4f9a01d66d1de632f810506e9ae2dcc2.npy +04099429-9d6c3971491bd0de616ce6fe9495197c.npy +02828884-32b74d6b08ea4603d2b12aa6a0f050b3.npy +02691156-d940f33afc01ff036da97d9f744f7e97.npy +04401088-b7dd49e4f54f736afd5d38d2ca555422.npy +03001627-3f7c81bc7eab161e19fb4103277a6b93.npy +03636649-2a05423b37f2620e1b17743c18fb63dc.npy +02828884-73cc1e9a8f666ad2d2b12aa6a0f050b3.npy +04090263-5f03499ea2b4adb5857835988c6a287b.npy +03001627-2b6c09e26719b256c5facc3cc8dc041e.npy +03001627-ece627bd883d9bbfb0eb7e753c06942.npy +03691459-126ce29983c5421fce567a7bafc3f52a.npy +04379243-67fe5ba50738e325beedb4c8fd29e2d1.npy +03710193-d0b43f44ee976eedbcdd9afbbe6eef74.npy +03085013-21f6bbe54dab206a571ee28145703271.npy +02958343-4ff291758d03aab8d935b10ea652d50e.npy +04090263-83d1b16c362e03ee99362c38b018f042.npy +03001627-56eca3d859b5e8b4594cea63c14fa879.npy +02958343-2e37a9a6abbdf6cf25d175f53644eac1.npy +03325088-7c33d6466f9e1df350da8b99982a3057.npy +02691156-33c9e81a88866451f4fb6842b3610149.npy +03001627-e7a0200c28cdfea7c3bd24f986301745.npy +02818832-9fb6014c9944a98bd2096b2fa6f98cc7.npy +03761084-2b7006326f739b3fe793cc5433bece89.npy +02924116-b943af5eda244f66784879e4d6b78ba0.npy +02958343-425ba801e904cb50f3aaed7e86215c7b.npy +02691156-ebedcd06f1770cd4bbf3143b1cb6076a.npy +02876657-74e5ea1a783a5f5f533775ea6714a372.npy +04379243-3073165c54b44f276e1bbb3913878400.npy +03636649-18010f1e7133415290c2e24416edfe5b.npy +04330267-99f1b9951d4ad128453c30eadc73690.npy +02691156-a42bfdd67b3fc9926b2f6b824c9990c0.npy +03001627-2952ec189e993eeb17e114a7b3c6fb1.npy +04090263-ef672b394e09257d719b648239c8e160.npy +02992529-bf7daa3ade10ee75bad093be69512dcd.npy +03642806-8ac9eb2b975c0d12b5328fde615e4a0c.npy +04379243-cb65b7ed48165ab09e9f71d2c7dacf45.npy +03001627-dfd92aab082e4915e3d9492680c47206.npy +04099429-d1b5300610189ff4e972ca7ee40523d1.npy +02880940-e30e5cbc54a62b023c143af07c12991a.npy +04256520-cf027d5b0debe18321bdbc0445d9f748.npy +03001627-10c08a28cae054e53a762233fffc49ea.npy +04554684-a40e52582bad42308961a7696b4b91de.npy +02691156-e8289fd7e6ab0df4d37636af9c7bcc34.npy +04379243-854b885039dd51e7ba57e2d7b7436136.npy +02691156-dc7c5d12854b9467b96212c8f6cd06e.npy +02946921-29bc4b2e86b91d392e06d87a0fadf00.npy +04256520-1226d123e89626a2406329dad4c94770.npy +04401088-ae819b81ba34165dd6ec95d8e6b9f557.npy +03001627-abbe727944da8cc55f0f8f79871ee942.npy +02992529-bf2a5f434972f11a690a03770c5de186.npy +03691459-96d6d519784e40c0c066b9622c005c53.npy +03001627-31ab0936f07c21ba7b11ae648ea92233.npy +04379243-9a0d79f4e766f18c7d10f85858b5d957.npy +04379243-f74b9b8412dd152f6558f5c8c0d2d888.npy +03513137-be9b9c3bd70c6f5c785b8fa1ee371fb3.npy +04379243-3b9e28ad033825b6d0ae74ce506ca590.npy +03691459-3983ad3c93f4ff0ce029fab54b6cfbd.npy +02871439-6081348fd96b21c3eca22c501ad0a77a.npy +04379243-415c174ecdc612fb6f5c30e29039b12d.npy +04379243-8b7f24a53beb18e8a69f5de385a4c191.npy +03710193-b9f695f1f05c06c573b8c60b60e50ba9.npy +03001627-73abab8429d1694c82e3bf439621ac4d.npy +04379243-dfef8f26e9a8437782db9fca4b68095.npy +03001627-e3a7c517fbe992ddd493bfe20f94b6ab.npy +03790512-9ff5b01d1aec18b2aae529ab4a75c4af.npy +02958343-87ee241d3d0d1dda4ff3c6764341833.npy +03691459-1c29d002435ce5f484f78eafcf19b8c2.npy +02958343-3428307ad66c58c53a0daf3e5400b95c.npy +03001627-aa05a0db9ab12c5e3e7d886a315f2350.npy +03636649-3c1c411ce82c4c43f193a5d512f2c2fa.npy +03797390-ff1a44e1c1785d618bca309f2c51966a.npy +02880940-afb6bf20c56e86f3d8fdbcba78c84028.npy +03211117-941c16598b8fb4f92ddfcbe9b600cb8e.npy +02933112-c8f5521a1f0ddac6c59350d819542ec7.npy +04379243-fa83ef67ce97491ac955e5ed03ef3a2f.npy +02691156-83b55a6e1677563d6ae6891f58c50f.npy +02924116-60e9f9301610e0d8f446f92b52bbd82a.npy +03001627-7a427785ad85f0c771c3cf047830ec1f.npy +03325088-938780d2b2148596bca5df27f3ec6373.npy +04554684-2ecde1b0c35fe63b4e4ed13543f85ef0.npy +03513137-58fe8b9f7026cd2bf1c20b7f59bbc099.npy +04468005-a2c5af9fa5633c3ecb607ef51aa2061c.npy +04256520-7051b028c8c1facfced9bf2a92246703.npy +02958343-d0e68e14e8012b497d6d702dc488f23a.npy +02992529-645c1b7e5297cdf567b9bb226efd81df.npy +04379243-e67447e5ab4b63246d871377f0c1e8cb.npy +03928116-ba07707823473bff5dea31ce253437e6.npy +03938244-397d66329fcf4b862bf863b361489dad.npy +03325088-7d6baf6cdeab0db93321831d2245cf06.npy +04530566-4c1c5200b239b15db700877f4d4ef8cc.npy +02958343-aeac711326961038939aeffada2c0c5.npy +04225987-bdfa2c97ef7089d6b267718342f3f316.npy +04379243-dd63ad97240a5744a022be8e8ae85897.npy +02691156-dadf41579d385b0aacf77e718d93f3e1.npy +02958343-f78bf954495be532afe1d4530f4c6e24.npy +03624134-245d7d1911237928c36546d954c4fa3.npy +03001627-52240b141c70e6d8a5901d93c937a07e.npy +03948459-4a5ed50fe28a7380fef144202cb2b935.npy +02691156-595556bad291028733de69c9cd670995.npy +02691156-ce339f515469303979e13964f05c24f9.npy +02691156-315f523d0a924fb7ef70df8610b582b2.npy +02828884-6e84c668dcc028e6864f7d01926c6c64.npy +04530566-ebb7451625233d772afc5c10dbf83b25.npy +04530566-c715bbc7a1586afe64ab9e610db7c692.npy +03001627-720bc3f0677a75fb2f134420f7b0d7e6.npy +03593526-e142e0414bbe9b39cb6782d0f0acad78.npy +02958343-29c0b746704727593030e8e3910d2b3b.npy +02933112-a08aa6e386cd983c59350d819542ec7.npy +03642806-1dc28ae9dcfc3d773487ed70d4534caf.npy +03001627-1e44e3c128b667b4fdef1c01cbd4ae0c.npy +03001627-c2956c43f763e135c9bfaa062f2e9d4c.npy +02691156-f0137228f926dd464f8327dbe71ce85c.npy +02958343-29487596941c12dd99f6b4f86609dd6a.npy +04530566-b77075c46e424ce9eb2c303a0e0d287b.npy +03001627-6730fb4ca7c90ddccd8b2a7439d99cc3.npy +03001627-66342d92d51f402d3f7e27638e63d848.npy +04401088-c8550b3e45672f5d891ef59b77a7541b.npy +04090263-43ea7cdb23aa0e3de1f2a1daf140ac9f.npy +02691156-b1f08c51a098c43696d224195a988f09.npy +03513137-5174613439e9cf79d2808af04871028b.npy +04090263-bc1d02e51b46cd8f12b38b1d99376c0b.npy +02691156-6ea21a2265075beb9a2f7b9a6f4f875f.npy +03001627-3fdc09d3065fa3c524e7e8a625efb2a7.npy +04468005-2d0265b94d87d381dc14ba0818ee5cec.npy +04256520-1b17f84df81e0165e336453ccee6eebc.npy +02691156-d844094b073a0452b04b2d1c5ce9783b.npy +04379243-659e7b7166d8b9972f84a7804aae667f.npy +02871439-6d5e521ebaba489bd9a347e62c5432e.npy +04379243-ad75eb223ce16ec5b6dbeff8ebe9459.npy +02933112-c4802a2901dcd6e84da5feafe6f1c8fc.npy +03001627-981bbe2950bc9b188f1d1d7c3673dc3d.npy +03001627-fd3759f684abe981d85b29704f5fc7f2.npy +04379243-36fa3daee9a560f049ad73d13f0c98e0.npy +04468005-3b1d2be218ead5992217baa3b8e01690.npy +03001627-5963e316d9015ff1785d41fe7f67162e.npy +03001627-cf88ae03d8cc2fabfcce6278f5ffb13a.npy +04379243-46cef01263d9b449405738a4d4d0fc7f.npy +02691156-1d4ff34cdf90d6f9aa2d78d1b8d0b45c.npy +02958343-5494ca610eb9fad59bd53ddfa65bb6b1.npy +02828884-26240de6617ea89cc6c4a9ba1f33346c.npy +04379243-a2781622b5941ff2a886fe6408aa7382.npy +03624134-dfabed4f151870eb4bd26ac3bc3791a7.npy +02691156-1caa02b831cccff090baeef8ba5b93e5.npy +04379243-3cf25cdc0cc8b384c652d01955093125.npy +03928116-af4904dfed13c508f6646a841979f507.npy +04090263-74a11a9b7ebd4baa424c267cd8f453c4.npy +03211117-ed9d09a17e472e0acc9692a1d1e7dea.npy +03001627-681f4302a8bd9698f4b6538438a0b930.npy +02958343-4b6e6fa36c1e6f865cb51d79fcf5dad4.npy +04256520-3ffeb5868d6f5dbd8c46a3a266762d7.npy +03001627-77a4269a0d64d48336b0f2a1430e993a.npy +03211117-aef2bbdc3b1e9e026a5e01bb88954fd1.npy +04090263-ec688ef9a40c78451188f2b8eec55c9f.npy +03325088-5f76becd78c7eb2bb362845c6edb57fc.npy +02933112-47b069b828d9fae54692707833167ca3.npy +04225987-35c281c44b5ee115f62521393bb9c2f6.npy +04379243-132ffa7d607ffc53d810b14a81e12eca.npy +04379243-fa1317f3a80bd8b1278d386bfa54545.npy +03001627-4ac17ecd78880859e302b6082b0ffc09.npy +03001627-3789c5b85f49b21ef7628281ecb18112.npy +02691156-e75ce21b914ba565b4c6d1a32dc4f554.npy +03467517-40ec077329c26d773127c5e409872bcc.npy +03261776-d768ee2d3f60aedad4ea3f4c41b1b9bb.npy +02876657-21239b0cafa13526cafb7c62b057a234.npy +03636649-8c0380a0d385c98145d451096984140d.npy +02871439-6422a1f1dae8fd231e23f97c3de97d74.npy +03593526-117843347cde5b502b18a5129db1b7d0.npy +02933112-8ee0fd1d620ac1ea974523dbdd88cc4e.npy +03001627-f3f331e64d12b76d727e9f790cd597.npy +03001627-325f9ca506317aeff2c0658ad22a9a9b.npy +03001627-4dd46b9657c0e998b4d5420f7c27d2df.npy +02691156-a5021faf372fa2c48f329df3701cbb3d.npy +03001627-f7dec3c72af895884cafc8d32c041834.npy +03001627-5b2b23120a4607dff7628281ecb18112.npy +02958343-df91db4ada9bad0f9c0cac0d72a31ff9.npy +04256520-3f1e897f2da10d808e52cc55aebae3ed.npy +04256520-2351fc9da59d571d9a404da609e2789f.npy +02828884-74a91aa0a8d9f2b5bef71ebb79d44440.npy +02924116-27b53c8572a52cfa0ea4af438fd24ad.npy +03207941-a7b9af190b190bebc8a1bb0c38d7dee6.npy +04379243-e15a28c0743ded35673b9aac59c306c4.npy +04379243-4ff87c5a639b181b6c6add082247679.npy +02924116-454ff74dd295dbc52470de2774d6099.npy +02958343-1d4b2404a00ef4bb627014ff98c41eb1.npy +03001627-ceec3aaa6ee72dee613f0dbd986ed6f8.npy +04530566-995547c0276be2626bd4106c65ec103c.npy +04379243-b48d04600e7cf2bebeedb4c8fd29e2d1.npy +03642806-d37f5f4d76bb5aee6d0e9ec8b698ce7a.npy +04468005-6f4ac6a0940302a31307b8e7d9f7be90.npy +02958343-d32cd105c2dd79259d959a8bee08198a.npy +03001627-b6a0afcc2ad2db2b490ad276cd2af3a4.npy +03001627-1b8e84935fdc3ec82be289de70e8db31.npy +03001627-b8049c767cb298745dca6305fb9f97ca.npy +03513137-1ae94e883149a07a242154514ef1967f.npy +04379243-15616cf6115c302264e63375fc652d6.npy +03642806-42f71a2df30eabb1b8183a4a81361b94.npy +03797390-71995893d717598c9de7b195ccfa970.npy +04379243-7fd9f6bc9a89d240800a0120f3e757a2.npy +02924116-304d18039eb8f78cb362fb9a75ddde8e.npy +03001627-fc97c771d058556f593de14e4664635a.npy +03593526-d6b6a7a860cfeeda2f2318fdd66be40a.npy +03691459-d4fa4988db7f2eb477818a0572bf1777.npy +03691459-908202c73ba60671c0d274eb53f065ff.npy +03761084-4809d18c7a655877178e7d331e641179.npy +02924116-e21827cb731e3e8d52d3524c5bacd7cf.npy +03636649-16327d928854b34ef11c3739edd52fa3.npy +04379243-d2a331898525d0d1c955e5ed03ef3a2f.npy +03001627-d02f9ae175fa83d3e6fe3612af521500.npy +03467517-22b21e858c58a3d59a6208793b9dfca.npy +04379243-6b13e49c5c13050f5589b48ab7a00cdd.npy +04468005-5e09f52f141e1c04e8784f880dac0f61.npy +03467517-e5fc7cde70b4d5dd63e148e250c0340d.npy +03691459-10421ef12dd27f3650f5fdf97aa1ef24.npy +04256520-8bb72bf16f65fced40ef1c8b63a628f9.npy +02818832-c758919a1fbe3d0c9cef17528faf7bc5.npy +02747177-89aff0d006fc22ff9405d3391cbdb79b.npy +03001627-2eaab78d6e4c4f2d7b0c85d2effc7e09.npy +04090263-7d310ff81ee66564b38e8b1e877a5704.npy +04379243-d51dfe604d380ba9bf01c8d1f07a5c67.npy +03001627-5d0a9fa5c8d9bef386f6991406b6a562.npy +04379243-252d046ecff65ed1f9f3162e7c61521c.npy +03085013-3df729da3b80c91033297782c16a4e28.npy +04090263-56141e8844aea9e4d6c7a58fae95cf0.npy +04379243-4a6d33949265bb6569eabdc5c4c6d724.npy +04379243-46bfac85035dc6f0382c5a0f87d73d23.npy +04379243-15090e10ae2d06306e25f3efedf6785f.npy +03001627-9958038b6d06278a68d1b9a1d97e2846.npy +03001627-bffe3e68857faf7f4d1242a685303c47.npy +03001627-3fa1eeed2e8e2534febad4f49b26ec52.npy +04379243-caa172578943812ec50fe5c30bda6ca4.npy +03691459-4583734434ae5842a820191310c9bacc.npy +03642806-91b857a748f0ccf2ab0b172d4dea80cd.npy +04379243-d87841ba0db5931576a45e9a12af8158.npy +04468005-59b81fe0e2223ac752470de2774d6099.npy +02828884-41d8b7b9480fe27dad5067eac75a07f7.npy +04090263-6e2dc15452034791a791c4f82c7b99c6.npy +04090263-6d751616e0ca4ca0aab32791f5a03201.npy +02958343-c9e555bb1a17cfbc5d918097f81825e3.npy +02876657-523cddb320608c09a37f3fc191551700.npy +03001627-324b0bc4363cf4e382db9fca4b68095.npy +04530566-cc7369fee843cbfc8d1322963ff40d1e.npy +03001627-91bd85c70bf89da2a8737fcf23389014.npy +02828884-9cd6dc2b9d11016c49b3ccbe36f67015.npy +02691156-605c79a4937e72aed0f4914f6d630bad.npy +03001627-f8b90f63fa9ed154e759ea6e37e5585.npy +02958343-7cfd1dad90b79cadfe2e8ee5c450bb81.npy +04090263-206d5e32ece7b8878cb55268d473f123.npy +02691156-e8ed294534ba18df4a29fef5d2b2f3d7.npy +02933112-37fbc4e7c9e46b602b5631520b7d94fe.npy +03001627-1055f78d441d170c4f3443b22038d340.npy +04256520-4307657b2731fd392c37553db37ec752.npy +02808440-240302fe2eb2dafc322ed2ef5fc90e25.npy +03001627-70be8ecf5200fddd818fffcf4a59bbc9.npy +03001627-f68c32ea1e6cecd3c48d90eef8384210.npy +04401088-5891622298f30916f31b75c4a94a8879.npy +04379243-b08310a1d75702eda09ce9c1262c7237.npy +03001627-106e9487a1d47ff1a09cb462b3e723e2.npy +03948459-6f8956455813727c3e93a3c4fff5237.npy +04256520-3a3f425190044bdb2efb565c08a63897.npy +04379243-2e007165e4f48ee3cd4a89b0fee32930.npy +03642806-cb1e3a990782678b4b6682da890df381.npy +03001627-791c14d53bd565f56ba14bfd91a75020.npy +03636649-39acb6226133f9e0e4c9b82a33ca42e6.npy +03211117-4dfbb9a4ee89b5b29382b62c9161999f.npy +03325088-484b0d59f6954a8854d7082b34825ef0.npy +03636649-5116452b7826dfd92548598e855f0844.npy +04256520-24cbeedf72674d1eb615f5e15a637115.npy +04379243-1e3dc37e2cc335441326da246d3ca9c5.npy +02933112-6ee01e861f10b1f044175b4dddf5be08.npy +03636649-ede739cf0fdf5af9d49b2e04785f8492.npy +04379243-2ee72f0fa8848523f1d2a696b973c343.npy +03211117-42a81c2a4a261f1e1bb088904f7cb154.npy +02958343-8053e014516531ddc3f500d7b182f6.npy +04256520-9b1a7c1df1ecc3c0cabc196a7f35f1aa.npy +03001627-ed7ed25d40b3c16b37bf42a4ca375618.npy +03636649-f91b13fe06141138fcb8d8c6d4df8143.npy +02924116-188ec01e6dd6b60ddfe356ac4b10fe3d.npy +02691156-b788ca6fc544c0aff3f3e17ace8695b.npy +03790512-7fcee59a33976221a88e8cb97b773125.npy +02691156-fd6210721415e4bb51a9048f9848535d.npy +03001627-33fa27b08aee4432e8f8c11a24c52ebb.npy +04379243-fe4c20766801dc98bc2e5d5fd57660fe.npy +03636649-5f24434ac22353708749901456352d5.npy +02691156-ccdec989c4ca289d9a6e43b878d5b335.npy +02924116-2f3d0b1432f014caacf9e4b0d73d2434.npy +04256520-9c3b2d053adaca577b50cd55c08e6bb6.npy +03636649-daaca6107846a666a8737fcf23389014.npy +02958343-b0801e9d8e004e7758dbdf2b5c6acfca.npy +04379243-ad61a5bc7cba29b88cc413950b617e8f.npy +04379243-42f22cf6e29876a9c19a59cdcb309b91.npy +03325088-416dd83d7a18d2543321831d2245cf06.npy +04379243-7c3507fc4eeb9854febad4f49b26ec52.npy +03790512-1d8fb258aac4175a5834749a5ef37100.npy +03691459-a9957cf39fdd61fc612f7163ca95602.npy +04090263-d7806192d775465cf26216cc0b9f4269.npy +04379243-180dd8913e894dbf5c6a44a505804654.npy +02691156-c6009ba1bf947303ca8607f540cc62ba.npy +03636649-b2e4c14ea09658e3d0e9f1d4665fda29.npy +03046257-ba3121c7429ff19b83cd0ac541913e0f.npy +04379243-e36dc839d70d3bb927445c0c7cf3becc.npy +03325088-1396874a375c365e3eef3cf37d74e423.npy +03636649-34e4bfd2000916c6a5f9d52c12457194.npy +04379243-2145b7d411f1cf91bc4e0550f830290.npy +04379243-a18a9e2ea68eeacd36b0f2a1430e993a.npy +02871439-701d5ef8d155c3c7eb6d6d4fb283476.npy +02691156-52a1b6e8177805cf53a728ba6e36dfae.npy +04256520-9508699d8e6112cbc6b21d0fcb810056.npy +03001627-d810a38ebae55007eaeab1f0c9120b7.npy +02992529-d565df5aa65604c86b69fa5331093439.npy +02691156-c2f43dd2c483e0d86b7bd17e458d0dcb.npy +04401088-9644fb6a1520af7fa90f3ad3635b46d5.npy +04379243-799a262e7eeacf2a593ebeeedbff73b.npy +02958343-e46d79a5d356436f23a5d95daeb50835.npy +03636649-38eedb7c36b785fda81f841e85c630d5.npy +04090263-804342eecbe40a4c79f92df566f8c6b.npy +04530566-3899f8b55ec9f1db8a1ec28cb7d97871.npy +02691156-c8b848f32a850b15e816c75152573ee0.npy +03691459-ba85d89312054ee95793a80f4f864500.npy +02958343-b7707e9f69d6c0ec6c23793d085f1519.npy +02958343-e90a136270c03eebaaafd94b9f216ef6.npy +04330267-dfcc7689382e0f91adf06fa21339d492.npy +03691459-95b29837dd0209a413e18f148987464c.npy +04379243-9e6d6817c0a0a022fdb7f86985d6e5ad.npy +03001627-2a445cdc8cac449271c43550cfb383a8.npy +03636649-6b29d8827f1705b0eef5d83b671bb264.npy +03593526-eaaa14d9fab71afa5b903ba10d2ec446.npy +03991062-48c94c6283fa5566a4136492f17b9a59.npy +04090263-dcf13ca83d9580bd44c069e8827241aa.npy +02691156-14762404f34eb050bf7a28999a707afd.npy +02958343-fd5a6dd153a455bdb112e5ac235c21b7.npy +03636649-c5da06189b219effcb8d8c6d4df8143.npy +03691459-b987e53822ad2809c7e1c32ca6dfa00d.npy +03948459-ac8ecc77946b9578f342a9bc61de5ab2.npy +04379243-b1333bac9640db456e5061f0592f234c.npy +03001627-59155eb9123a9aa330bbd4cddd04c77b.npy +04004475-4dd4acc48cf804d39b5ce3f3ee534f14.npy +02691156-347d86d7001cef01232236eecec447b.npy +04379243-392093300321b9e1eca22c501ad0a77a.npy +03928116-7a7f23b15bad26326753813b2a3a4093.npy +04090263-c57d7e81270598096314c3b6a3a65519.npy +04379243-1aebb6c07b8d53737062f2d72cde5c95.npy +02933112-21eb0039185dd955c59350d819542ec7.npy +02691156-cc7a48498e745baef828c8b5be2ff54.npy +04379243-ab7b0db92f96381f8cbb8bac2032149c.npy +02958343-6cd11fccae408795a99406d7384c870d.npy +03001627-6344b2a2fce93cc3d2f33aaf794b5932.npy +03636649-5eda619e5f36499fc1537287b5c50d9d.npy +04379243-ea37d7670bf3294e60a3b49d78923dc3.npy +04401088-aae6554b1abe736c70ed77f7659cc6f.npy +03636649-369555d5aca3e7e65a31d91ec836a511.npy +02828884-38c4c2ddbdb502e162701a18243b45d3.npy +04379243-a3f369c885720efc459b850e737e0048.npy +04379243-4381d6508786fbdbc694ced1c311421b.npy +03467517-ae0b98bc6313c33940535e68d82b97bc.npy +02691156-3fe365251b54087af0478431b5ad57db.npy +03991062-5b56ec15c6b412115aa9d06b3815555a.npy +04530566-a554a62acf40e578cba07fb2573fff75.npy +04256520-ff2a456b438b0f2ba494798fa117187b.npy +04379243-8b077b3be444a1338aa76d17cc411fb3.npy +04090263-bc3dcabc80b38ab6ba3efb88a329778b.npy +02958343-9702eb7f07f013532764cfba57a5de73.npy +02958343-8bbbfdbec9251733ace5721ccacba16.npy +03001627-b54d0fbc33d125bb7a6d149f6c9151a9.npy +03636649-abf04f17d2c84a160e37b3f76995f8b.npy +03046257-cd074c458e0aec2a4b3c42e318f3affc.npy +03001627-5107542cfbf142f36209799e55a657c.npy +03261776-49b17a26edadad7f46619c79b20f2c6e.npy +03001627-903a14845425ca3176e30bf48cd56fcd.npy +03636649-20d36ce3148091c5764b5e62529f6d7e.npy +02958343-d04fd72c36fbc71731d383b4a9dce77c.npy +02958343-64ea044763ab4d742a9eb0f146e94477.npy +02933112-6c7a2ca9ef6cf7a3ef4e42d70375aed8.npy +02691156-e18b6350437cfe0d727249e8d9a90100.npy +04004475-a6d9da1c37aab01129f8bad8fa208851.npy +04530566-6ea8d00d7359f08f9e4614310319ea50.npy +02828884-beb4feca82b0082efd60059ad8523f1a.npy +03991062-8f45584aabfb17e9ffb8dd272bf2a810.npy +04379243-dfafa039da1cf318a42557fe008dfc94.npy +04379243-8e3303cae6cc104bad4f8ccb153c24e.npy +02876657-a02a1255256fbe01c9292f26f73f6538.npy +03325088-a0642a6b2849d4f5b362845c6edb57fc.npy +04090263-2f4209998288a4634d0af51460733e47.npy +04090263-604d927e4954713fd735fa1ab17311ec.npy +02691156-1a963a929d9b1332290d63dca780cfb6.npy +04379243-a379cb01e0a98298607974568e26586f.npy +02924116-aaf17fbae6721ff4839e2313a3cf4083.npy +04256520-4e664dae1bafe49f19fb4103277a6b93.npy +04379243-a713c7f070c4fda022abf78951dd8624.npy +02958343-d0aa115eb63f6f0c97df6383472cc5b6.npy +04256520-f5960ae57bf84fe77b79156a61ad4c01.npy +02958343-6b642c1c62ae5b49247a5be450795511.npy +04090263-36d72181bce0939c49f0e3dd7767881.npy +02691156-89a6af782a025acc62b600da24e0965.npy +03001627-cbc47018135fc1b1462977c6d3c24550.npy +02992529-49081a0c0cd4ad32166f3c6af52a7c59.npy +02958343-8141677722f680076a2345809e2bb169.npy +03001627-730a4d879380fc78990561fc34164364.npy +04468005-8ce6b54c47bb1b1671547adc319f74f8.npy +02691156-6bfb3e84a0fe44c1bc6e7c82ab33ecb.npy +03467517-97e8ee1b6df404bd57700c05b1862d8.npy +04379243-8bfdaf14a1b271954be714694b176f45.npy +03636649-aa734f5c5dab1e672d26f74bb535ca48.npy +02691156-12c66a0490b223be595dc3191c718398.npy +03636649-15e38eb29fb84898e7e684d25d4dcaf0.npy +02958343-b2b22a1454f2c88bf63ee8a34069b7c5.npy +04530566-a56c3a66dbe0ddf4a70cfb3232f40c6.npy +03991062-eff3b8277a2f1fb9d4d8765e3910f617.npy +04530566-7cc3c41e998caed8a70cfb3232f40c6.npy +04004475-586a0979ea3792f1c17df6b0271bf00d.npy +02933112-6c2762c2c95d7a2063b3c67777442463.npy +02691156-89b6f678789287a3d3128304aa2279ec.npy +02691156-c1d8614b0e5e3f3bf5a498db2fc1d347.npy +02828884-45dc4d46a456d36c2056b4bd5d870b47.npy +04090263-97532871e6ae97d8f0e1c0df18936d05.npy +02992529-ae942af3b88d07af2c557fc696108818.npy +03001627-d9902456104543c898d5fc0473d00a1c.npy +03207941-dfdf181c7c4b9a0a525c8adfc0dedbf6.npy +02958343-2307ced410b955a8cf1e58caa15acb49.npy +03642806-8e38d4d1f849f024296462783ef76d22.npy +04256520-fce58f4938a670db91c74eb018d3bfd5.npy +04379243-2ba4638aa672a0c419fb4103277a6b93.npy +04256520-899389d5ac054e7f33a851a05440ba33.npy +02691156-121b5c1c81aa77906b153e6e0582b3ac.npy +02773838-756066117169dbc96c1d5082d1bdea19.npy +03636649-ef40f27470d99d6fcb8d8c6d4df8143.npy +02818832-57764cebd92102552ea98d69e91ba870.npy +04379243-460bc82ba3a41a4f492489969eb2d929.npy +04090263-5835fd744208d5c9e6f7dedb7e5f584.npy +02828884-4f4416c9c53cee10b3a46b931571f116.npy +04379243-3a3f32deb30dc4e32ea98d69e91ba870.npy +02691156-9e06044df59e7f9f953041d9e16fa262.npy +02691156-56616237ed5168f3a18e0889038e4fb6.npy +04468005-e9dd4e42bc49b8c230a8c472227cd05e.npy +03642806-bb6af0aea6bd2381b0d7b0d4230df8ca.npy +03513137-a1bf8b293de641b5a5cc2b36a8952e0d.npy +02924116-a78fa491148db09526479a182158bae5.npy +04256520-33384d4600a8bd0ad88a7002dfb37846.npy +04379243-9b32bae53b91a01f278d386bfa54545.npy +02933112-a8cf3a04f848ff0e4c62bee40dcdc539.npy +02818832-d59ed3ebe65d978a922962743a259201.npy +04379243-eb34935c60281450d42b9650f19dd425.npy +03046257-56a3239391f73773a5e3e028709e0474.npy +03325088-81ca48ee431c29d472101dcac4ed75d3.npy +03636649-9b786274df42d55b774476b2e205b9b7.npy +03513137-96e81d71a15ecb1dd3f1ead878957615.npy +04004475-1f2a2824554a679abe4baaeae0897839.npy +02992529-7731182b7b8702bb357be8fc4a9ec12a.npy +02691156-b2b3fc16b9a676f5950bd071d87a18b3.npy +02808440-44bccd348dbbc2d6b448b8aaebb705c.npy +04090263-c12e1342d88e78bfdb132fbd93e54108.npy +02933112-278d1992a0aa9116ce8f46fabe978829.npy +03467517-33f932665104970740a420d466980e34.npy +02747177-cf09264eb6d80455526c1122178737e6.npy +04554684-270df61e08a104c4c2180858eb6a5f28.npy +03211117-dc73dee56c43fe018047f0f85f295702.npy +03001627-1e6f06d182094d4ffebad4f49b26ec52.npy +03001627-eab716562b582538f2599a47b2a7e92a.npy +04379243-798c315f86d8f02f931e98da3a93e73e.npy +02958343-c59e3f28f42e6ca3186fee06ae26176f.npy +02958343-f120085da70b2913627279ad10ae805a.npy +04256520-f094521e8579917eea65c47b660136e7.npy +02992529-5bc22a940bd88a21886d9e4484b773bf.npy +03636649-6e46cdd2f97cd28ad98bf80379cd1d6.npy +03085013-4c0d7cf86419a997d528a236ffa583af.npy +02691156-e9f39176973edd33a8cba409c4409ba9.npy +03001627-4e222d6b128a7af7b8fa4cb65e077db1.npy +02958343-171c20ce4de5ee8730f65ce13e7c1910.npy +02958343-355e7a7bde7d43c1ace5721ccacba16.npy +04379243-b3ca1f79cfb6b29cfc25405fbf8f85f4.npy +04379243-c47d1d0aae5de919f2bf00ef0d8c7aac.npy +03467517-66a6838a0887a85fd2f0cc036969ee4f.npy +04379243-585f8cdd992f541d23500a5b036df62e.npy +04379243-bbb7ad20cbe09b9b2ae0028d477b835f.npy +04090263-6e10893742a5add1139336f03eb955d2.npy +03001627-9a54daea9071a536bf80985a99195eb8.npy +04379243-bc8e050a6c0e49afea5682a3b818969a.npy +02808440-225742b31d7e28a97c35d3c5d3b1fcf7.npy +04256520-a05d53587e59b2ead6784d11c8f5b5.npy +03001627-eb3029393f6e60713ae92e362c52d19d.npy +04530566-ee3d521376d89f408c954439655c356e.npy +03001627-60512d74c623484bf27383fc5a5a711c.npy +03636649-e2209dc7b188f4a061f2222dd11ba79b.npy +04379243-649eda5783cc47e7948cb8e1d9ee487.npy +04090263-6a5c090b753cde05b5c25a656ff55929.npy +03001627-32408a694ac56775ce62834dbceac22f.npy +04379243-b9009a7b33df161ba022b82859ebabcb.npy +03948459-7ba9f65e926d5e3e6fe695987d47043.npy +03593526-d4b9e1085ebd4f226bc258c0f0234be0.npy +02828884-5aa9a03af76807fa94f937d854219137.npy +03928116-4a28d4c85e55a252a876e1c6fd98a946.npy +03467517-5621a833a3b1609145692e007d878b1d.npy +04379243-31e3a6b2e0b40045cb2a965e75be701c.npy +04379243-79b1e6c1e72490c98ca0fe30c6caf3f4.npy +04379243-e14f505926399396b5997278ed74fcb5.npy +02958343-80642f8965edbc51ba01f2d8d5d9ff0.npy +02958343-614d683fa574cd817fea5423f91210c9.npy +02958343-bcf4d748b5f3f13dafe1d4530f4c6e24.npy +04530566-52176ee07927984ab13f6ba928a796f.npy +04379243-505a99351f70664238b87428c6845ef9.npy +04530566-29f385987ef4594ff6b98f041a0ed52.npy +02691156-45574293b59c62ff301fa0a0663ee996.npy +02958343-fab45f900797908bbda733a39f84326d.npy +02808440-7072816b1da8ca1b1c17aef130ed6213.npy +04256520-b5c61f497f9354d535c2f4da17c09efa.npy +04256520-4e05ca172c988b72dc1f6c4cdb4bb9b3.npy +03001627-9a711bb7070ae88de948e3d64826c640.npy +04090263-1c96532b385e22edd0a6af9bfb470a20.npy +02958343-9e44269655ec3df9afe1d4530f4c6e24.npy +03513137-b3049575684f6ebfc0e57505cc92501b.npy +02691156-63a2144cfae402149b30aa09067b7eef.npy +04379243-2a88b6cbfe4b9a3ce2dee6f9fbe318ea.npy +04530566-ff2b8253ca3190d5d65fb76f5f0a1db7.npy +03691459-2a77ba363947f4f38a9641b35ef045a.npy +02933112-12f1e4964078850cc7113d9e058b9db7.npy +03001627-ccea874d869ff9a579368d1198f406e7.npy +03928116-3a8539e63cffccf65420ad944870069c.npy +03593526-e1835d106d89c69ef1f3019850abf317.npy +04099429-95fd683ddc8298d0b5a019b4fce31328.npy +03593526-661f1f07ee3cf13a77d7528e1646c585.npy +04379243-6a94aa414d11c624552edbe2a62e882b.npy +02871439-32131c4f13c51192bbb25886240eea46.npy +04090263-49ff48905ac9d95e585eba7ae331fc47.npy +04256520-43131890e972bb1febad4f49b26ec52.npy +04379243-fdf1cbe0d8aeba868c1cf3f7d7f0373.npy +04379243-e50bed5236712874ed258f1e4fbd53d.npy +02691156-3390c5050cda83c09a6e43b878d5b335.npy +03001627-2882587cd2fc021c168776226d349d71.npy +03691459-4c18da768d4c81c787695b38431695f3.npy +02828884-ab891fba7aa43f9df155d75bbf62b80.npy +03001627-2853ec74532f23f3670cf6c75c1c5868.npy +03325088-449ca62078205918d79b16e52324b152.npy +03211117-7422a1f42ebb1a1bea9ea4147227b8a3.npy +02876657-ee007f1aac12fbe549a44197486ae284.npy +02992529-84f07a9773374b062da40fdb29d70537.npy +02958343-db8eb94d24f5d8a2350dd0b332d84c76.npy +04379243-8915112d9819c83633b2a5760b4dd1f.npy +02958343-65ccd33df41999496d6573f48a06281.npy +04379243-599dfdedd707f7c8ef38727c2b4dc2e6.npy +03211117-a47aaca6619252acc4f499be00229a55.npy +04379243-d9ce0b512e0420f8be95ff480950e9ef.npy +02933112-8f30bc2f3ae12300a4669f677ccd56a9.npy +03948459-224947e496219e1da39dc4a567ce225f.npy +03001627-eea9a17689ef174ec14f867747674e73.npy +04379243-661b8e9d5a93e2a4b4c161851ed2b4e4.npy +03797390-3093367916fb5216823323ed0e090a6f.npy +04379243-9a5cb4122d518111b339f790b1757e92.npy +04256520-8e6312c23b6ac12f956c23e7ddc28c00.npy +04256520-8b066cf28fc1319da11411fb873de302.npy +04379243-438b2dcdbd25a93dea65c47b660136e7.npy +03691459-add914368a6ca448732bda87f2718525.npy +02747177-f095cf11c6049709d395fa91e75a7dc7.npy +02958343-9cabc9b21a7c5fcab02964031d37f87.npy +03636649-58b269eba3c6d09b57f40ff86fe708ff.npy +02828884-d5fd97ad2620480c62cdb4b7b7821421.npy +03337140-bbc516fd63703eee9dfa717f86ba8028.npy +04090263-aa235b7d9006c30de98e3214935cca1.npy +02808440-9de93ed7919c499854d7082b34825ef0.npy +04090263-144f38700549b35b31f639996cb3d35d.npy +03001627-27680e1b7951526518694a7306254063.npy +04090263-5e3e2c6779b3bbcf5e22590d7220b895.npy +03001627-ff49ca82d7f8e2bef27383fc5a5a711c.npy +02933112-40209ed0c2a718bd82ef94da039e491f.npy +03001627-37607ea19e352af4fffc97a61124b1a9.npy +03046257-f035ac6992723f9ff546596ce7364503.npy +02924116-b0604333bb40f58136c3fba5bd012bf2.npy +04379243-75e59e4626875167b2f7093e7efce142.npy +04090263-21acb1cc84ab5e5040aa5b072f9ee3d1.npy +02876657-77ad88568cb55237e01d7dc978602402.npy +03636649-e959384247c0dfbe1e18a354bfd56290.npy +04256520-de4d86efa8bdc67684ad2abb799c0f8d.npy +04379243-2fde3d8a04798c325b937c87a8810c08.npy +04460130-90e931890719c1b43d36e0a1be1c720.npy +04256520-53319f95d4bb6a0beaf288f952624966.npy +02691156-e712867dc4c1a4a6d016d0153a25a372.npy +04530566-d25d9a2bf4820003f3e39f2e17005efc.npy +04379243-73fc0f27cd57942ea2edf7a1fa4be45a.npy +03001627-e71ad853f50ea7872acd2bb6205825cb.npy +03593526-eb344ece6d6669fe68dd306b8ea5e1c2.npy +04090263-c61fd3dd6eee6465ccaf38f4d3340ec.npy +02691156-45570756a871989cfb5c1b0f759e2bc1.npy +02924116-b8f32af73acc268939f4ce9a2c9fb9f4.npy +02958343-cfd7228f455912dd9618aa9e2febbf80.npy +04256520-614ee0988dd6661d9559145fbf4877c0.npy +02843684-fa74d414933cb06d8c1dd15b51930812.npy +04379243-c4e7fef0548b8d87247b7570b0fbe63d.npy +02958343-425431f166ea35bdbfed25440ee4185e.npy +02828884-c9ca9b7317ac41b82168e5dee0d7f21.npy +04379243-48c2e34854c9aab889b74a90878aa3cb.npy +03467517-a2610d25db838d92538d7c152e19632d.npy +02958343-93c647af0338e9f35a06092d926a13ca.npy +02992529-16d7d7be19cde848dbe1e810cdc7471d.npy +04379243-3f1b826134c88f5fa0a2f1a46df5a003.npy +04468005-1461a40ebd86a9173c38a6d7dd5303d7.npy +03797390-b9be7cfe653740eb7633a2dd89cec754.npy +03001627-b3ced617a2923f674c9740802f05a1f4.npy +02691156-e33fbcf5b616d6f9f44f89e40af48618.npy +04379243-e4f9062ec3d2c6247d7b76078f434820.npy +03325088-bf1a08ed8d7a09833321831d2245cf06.npy +03593526-912c3e1cf2ef3b9ea7d0cc9b15400f65.npy +04379243-eb31e5efeb810c5280d6227ff9b21190.npy +03325088-bb2c9b746e450ae514b35a7d7cea7130.npy +02958343-fa997987367ed84ef15cbb7bb6511cb8.npy +03636649-d1ec5f73a0d3d6e4f3ff0017952fe4bc.npy +04401088-56a32f9e4785d3928a4adbc089030705.npy +03636649-b45b8df0557da6acc14d5c159bab8297.npy +02747177-f116f3c432856fccddd8899c86e55073.npy +03001627-bcadc00cd1bdc19494db33559ec0df30.npy +04379243-a3d155f1ab4731a515dd7d7985e749c1.npy +03001627-bf236db6dfa517aa456cbf78e1e89022.npy +04090263-3564b539a24a1b721a638d3d0d97d12c.npy +02828884-cf4075a6207a77fad5067eac75a07f7.npy +02691156-ff569b4018fc2640cea77fac5d58428e.npy +03636649-a049ad0f20953a144cc30865d6337b9c.npy +02924116-cfff3b5dd35f0b7d174bff1ac228f365.npy +04401088-b854fc846c1fc2ba619a006c72381476.npy +04090263-1d285f3bc7767bc8b4cdad9a5bf52dd5.npy +03001627-7bb5321d1e63d8bb36b0f2a1430e993a.npy +02828884-8596664f3d7925cdfdeb515ad63cf4b0.npy +04379243-670c2d3d20dded2bc5a208307819a3a1.npy +03593526-bacb6b671e5904d8274d4393e80e99fa.npy +03001627-446430548f6ac25ef25f6a97c97019cf.npy +03046257-921afad0f119509c4e09ebaf49b0cb2f.npy +04379243-a80c06903eca9eef7b05ef4148fe3aff.npy +02691156-939f3dcf67a1e1adbe13ce34aa7c0c1c.npy +03211117-b9cc669597085c028766390809048ebc.npy +04401088-ed53e90551ef9cb7118f00b061390b2.npy +03691459-b51a5f044c349741ebc9199df8e5ab6.npy +03636649-99f8c4a6b9ff1a2ab7f1f0dea571cede.npy +03691459-f9e6e10cdb3066929a3fe7e437a02206.npy +03001627-49aa713bec70ee1f1104b8f54582c707.npy +02808440-93e9520a999562f93af30a3946d92feb.npy +02958343-707d1e19b465d075adbfb30d8d1b297e.npy +04090263-1abeb8d7f5dcdaa4e06ed7bb63be5503.npy +04401088-9fac50c7b7c72dc694f8f49303e93f14.npy +04090263-5738a6de833d8da68d4ca42bc1bef451.npy +04379243-855f3c5541cfeffeef5609fd2064c33d.npy +03636649-a4c50a7adeb7d20b51014c684c004c28.npy +03001627-1e67e443849379fd6666a748bda83f67.npy +04401088-ce0ad218c6b19e76e7eb1b9b386befd.npy +02808440-ccafecd2880b61f754d7082b34825ef0.npy +03325088-fe9a455eb6d7867c3ca0c4be71e7b721.npy +04379243-f6f9626b892a529c2b642dfce4c7d8fc.npy +04256520-57183931e41c7aaa5ff61a3a2a0e2484.npy +04379243-4903be367953db8c579961b8f4afc151.npy +03211117-a9a2ec15d1223290916cd984b3abbf4d.npy +04004475-6f754dd4251d2bfdd4713685ae50fa13.npy +02801938-e3ef8c272a15fe83a0a1ab077d2d8b1e.npy +03001627-17f9eb6c0d818d45d7b20fded0142d7a.npy +04530566-47130fa6563a4712af6320700e3cf173.npy +03636649-c561496324b6d8154c5b22ae639d5204.npy +04379243-9bf704d5e2474cba3a6b5b5b9b35aa8d.npy +04379243-509d9d137fd7465a85c5f690e9252fc5.npy +04256520-ccbccd9a5bfd52cbd29d1a0303294bae.npy +03636649-8b85d01ba70a09e9a5f600ed2cf472ac.npy +04379243-46eb174e4df0f2e53719086e0b4ab8be.npy +04379243-a4990b3c86c680c3a71c812e027f94d9.npy +04090263-19fb748dbb9a97d3bc6e84bc30e573cd.npy +02691156-721eab5632f60887e72b7fd373921885.npy +04530566-12159b68a31a4a7eacb3e49e16caebeb.npy +04379243-1dbb8fd083f96ad279b3e1be3524f72f.npy +02828884-a12abb06ee3aa30ae074517a246f1e65.npy +04256520-73bb6025df29d208ae17f74ec30c4d4.npy +03211117-75336682aa3e245f80ecbe6250826360.npy +04379243-7249c3e41c4807c0f7e0e05bae6131.npy +04256520-a86bf379ca2ba8d8f2d5a0d235580548.npy +03691459-5b83ccf84149f28882613fcb45c2087e.npy +04256520-44d55ed577b77106599dcc439b161a52.npy +04379243-eabe7e2ee9547616214a15a5a42c49c0.npy +03211117-ace79948f769c652fdccfdbeccce2c03.npy +02992529-96b1d230e88cba16f71555c6480aef72.npy +02958343-98aa3b11abac3d73b7e1a37f8df80928.npy +04256520-3d5084d5e7654bd11cd6319703a6cb25.npy +03624134-d243969f5010c6c29b5844aa8fc56c71.npy +04256520-15fad17654ddfd3c33defcb28e53dee4.npy +04401088-49db0f97d215a109a2db3e68315c7819.npy +02933112-9ffc432bb61dff9f339797c21e8801b1.npy +04256520-625ffe6a78f1697d87ea4c09ea2202b1.npy +04468005-d433ceb5bb3eece98c8b260b832217ab.npy +03642806-69850d70fcaf5a464161e123a102b12b.npy +03691459-c725f6e275e9942f989542bab68e6843.npy +03001627-67d9afec46e20fd279c4b4a860b67e81.npy +04256520-192afbc1f0977f74861e0db9bb7afc48.npy +04379243-bc38dd123d9d50ad8b17d6d1965c2fb6.npy +04379243-92cae8ac60b09e3c6cfd6748e1399a49.npy +03001627-33ec1e64a02ff718faaadcdc0221eb72.npy +02924116-ef798c5d0e531dc53a56022c831f34f6.npy +02691156-918b46dfb239ee044a8d8b0dca1fd34.npy +02691156-a374b0448461438ef3d4cc10d9776c62.npy +02747177-aa547280eb99fd3fc8a06b09a9a18b3d.npy +02958343-bb9109ffb1789e98e55e3289e5df0916.npy +04379243-b7f733e648c850abdd91f8f6f381b291.npy +03691459-209086558286d4621ad88f716ea80910.npy +02691156-ff6f81eba664481126360e1e29a956c7.npy +03337140-4d591f85405c6a458eaad608e74402f5.npy +04090263-b8ccd8d1b693e4fb11f7dcbb4a32aee5.npy +04256520-7b1d07d932ca5890f51f77a6d7299806.npy +04256520-e471ff9cacad70d391fa1c643766450d.npy +04379243-7368b47a95e0db8886cc6209ffc37d3a.npy +02958343-405cb7dcad3d6f2f65af93d4326737fe.npy +04256520-51ccdee7080b11dde21111e385a0661f.npy +02958343-ef05b5fa8e2377f8fa7a46166f316347.npy +03948459-6663978acbe7f2b5336eda14178e5ec4.npy +04090263-16c510cfb4186a46d44d717fb37058d9.npy +02958343-a242c0446b186585852e57cec5098e60.npy +02958343-928a5f0e95e7aae5780bcccc86c008c3.npy +04379243-14ed71cd9f154616bdfa5e0753fa3240.npy +03211117-6fa8694a2b5dd0b9db768007c05f817.npy +03001627-5e5d9a681b53ee0d3b8d5c0ebdd194c8.npy +04379243-cfa43d56d70e530160dc76a524f85955.npy +04379243-10ca7bfe736d81b64b3c42e318f3affc.npy +04379243-ad060b3914729efe2175f7e45480df72.npy +04379243-16532364b5876d3881a172d69c52a28a.npy +03001627-4519d91ba59f0267cc0484ea4f50062.npy +02691156-1e4bb798f236f0b17f1f82f6fc8747b8.npy +04090263-607a6770f3bd10a16b2c8bb96250e4a0.npy +02828884-3ef2e306aadb9f98dd1f70bbc27696f8.npy +04401088-975de17c0b5d96cda38e5bd2fdb10d11.npy +02958343-f7b61de5d6d919a8953536e7c905b301.npy +02958343-4244e025c4a5de67ad411f846a866947.npy +02691156-219fa6821c9240e42476c2e017302af2.npy +04090263-21f013795d1b241d525cc89e716770ad.npy +03691459-21612bf3e866a8831d6b14cb827cdf85.npy +03636649-f39cc29063a308168466f606a3db18ba.npy +04379243-fa345f8f107d93b9ba70f71694a4b74c.npy +03691459-5b7cebe280c5aee935cd53a06b1d2317.npy +03624134-7725d5d2067f8fc0dd9394cb5004b836.npy +02958343-26c2c91d8eb660ecbeaa545f7f633287.npy +02876657-74690ddde9c0182696c2e7960a15c619.npy +04256520-7525a8d905a7aef4b3c42e318f3affc.npy +04379243-5919dea71f3bcb071d54ab02e78bef2.npy +04401088-ab621af8d265667a396287d16057dbdd.npy +02828884-410c1c5ae4e9d49f5ebcc146be902492.npy +04090263-62f99c3f2e7d133131e1c03c914d6f10.npy +04256520-14aa542942c9ef1264dd558a50c0650d.npy +02958343-72d4244540e81c671d9826a79afd9186.npy +04379243-81d84727a6da7ea7bb8dc0cd2a40a9a4.npy +02747177-3562096fbba555eaad5067eac75a07f7.npy +04256520-e5dee68606d47d3aca9b40e76e725878.npy +02828884-a2c53b2490e4151517a6e523c9595e10.npy +04330267-ef97ff5c1d6a00f2a760e402290727de.npy +04379243-8a45e9dd681d40d4789ee5c8d247b09.npy +02691156-ae8a5344a37b2649eda3a29d4e1368cb.npy +04379243-68b2ed56ad8d4e1896b84415a3f1393b.npy +02691156-f5403d3ffcc6bb17adce4f2283adbdbd.npy +03001627-6131ecb5a6fc9329f51f77a6d7299806.npy +02828884-5ab786ce3a18e3a170387839208c8db.npy +03001627-b69401b412d9300454d7082b34825ef0.npy +03001627-c6786aeee29edd1b2bca88fbd368f59a.npy +02808440-176b7a226dbede9ba9fe1734a6086750.npy +02691156-4fb69651d04e010554eefcdc602d4520.npy +02958343-755717e2f9edd1e36782fc9cb2c37844.npy +04256520-2dd491294a34ed7eff98db9ea1554f19.npy +02958343-7478183ebde9c6c2afe717997470b28d.npy +03636649-dccb4da9805924c23466f97f37dccbde.npy +02876657-5561fe6ad83a5000fc0eb7bdb358f874.npy +03948459-5f487e398bc0551c276c3d558130f8b4.npy +04379243-64f73518c32b8b7af49a23658fe5597c.npy +02958343-373cf6c8f79376482d7d789814cae761.npy +02924116-7c3411d4bcd34e6de841ebdde48e3937.npy +02691156-fddcb2b3d45ce98e641c309f1fd7e183.npy +04090263-a12b0328e2b9eb17f084db89eb9085ce.npy +02958343-9d5c0108ce2c848e977b27045b1d8055.npy +03001627-39d357d7ba9645d4647d4fd8d921152a.npy +02691156-37fbd275a734ec1b66cf1b4a8fc3914e.npy +04090263-84ab70232093057c12b38b1d99376c0b.npy +02691156-e7c6e2f7c5fd372e8e9091d822257500.npy +04379243-639d99161524c7dd54e6ead821103617.npy +02946921-100c5aee62f1c9b9f54f8416555967.npy +03467517-ef8874b3d10303c793f0194265a9746c.npy +02691156-3cbc83ba49edeccebc0909d98a1ff2b4.npy +03636649-d748241313e5664696a3517f50eeb9f4.npy +03001627-5d72fa9aea5383384a73e364671ba824.npy +03001627-898dc475a4f36d0d35836c728d324152.npy +02958343-323c9dc2a8911e146f2f07de403e98d8.npy +02958343-ee5e6649db524dc2eb22840c40c3154b.npy +03325088-7d1c4b0c119adf6914b35a7d7cea7130.npy +03211117-ff9a428991106434b9e65df431a37c1.npy +03790512-68e8c73ec51aeaaeab548456bc75847f.npy +04530566-77331918e10b8eacd07153997ca82b26.npy +02933112-54d9053622deb8866ffe0f6a1d92eb85.npy +03467517-2a0a47930aa7ac1163e148e250c0340d.npy +03046257-fb0fd780eb40e7151b02cde7e81f0fc3.npy +04225987-1c8d5e05c3faa05861be5ced44bc18ac.npy +03337140-bc07b1d9c50dac514c3aee8e9d3a6ffa.npy +04330267-a7414667b8274cecebe9a187b97c9295.npy +02958343-ba7a583467ff8aee8cfac9da0ff28f62.npy +03001627-38dd3fee84698e5242ecda58458cd17.npy +02691156-262795bc8a994b11ba0d990ae229b477.npy +03325088-2c80e8261b08d3e76c18e71fd49c4dc.npy +03211117-44d14268d1e961e02f653d2c3f9c5e62.npy +02691156-62fa636e217a3db25a70c4e5328e0b9f.npy +03636649-1a9c1cbf1ca9ca24274623f5a5d0bcdc.npy +03001627-bebd1aac01d747e82500a3366a96c301.npy +03691459-739f89b772ccf495b9451ae41e1d9ea4.npy +02958343-42eb287e220fd02c2e466666025c187.npy +04256520-a0a53f2f112055d496626c84a010ee5c.npy +03337140-53e41619c15465c14c3aee8e9d3a6ffa.npy +03691459-4678a534b01fd4d6a29efdf1e3212661.npy +03636649-437b5e12cf1b8771146f6ae9394828b0.npy +03001627-540aaf05d1ff41c0c90a83871023986a.npy +04468005-cfe064a6bbc9a33a64efb12b82a690dc.npy +04379243-1315d61d095210c05510d59f3ab1ed64.npy +02958343-79d684368c596b4613f9826aa0cb4736.npy +02691156-44dece8f8529374ee2199ec015f35ba2.npy +02871439-8db6a080f00b52e46b8fdc9bc8edc250.npy +04379243-726164afa497b154b075b4c36d25279a.npy +04090263-57bc575daa1a56109609aa6ba54014c1.npy +02828884-6b2caf6470d3dcb58ccde000e771fc1a.npy +04530566-c8f5e3891a7b0d1188d5590328ce0ddf.npy +03624134-150ad6a5c35beb17ee79d445a3ad4fd4.npy +03790512-1a2d2208f73d0531cec33e62192b66e5.npy +04379243-bd594555e192d5797d3a650ebc940efd.npy +03001627-798a46965d9e0edfcea003eff0268278.npy +02691156-db8ee29417ddae1bae6908c1ddfd8734.npy +02808440-eb00cc6ea32fdf6d3321831d2245cf06.npy +03642806-5678a2173ff575d09cebe817bc1591b3.npy +02828884-e329a9a5e7422b0a43638dabe1eb5336.npy +02958343-9af8945bd83ba89dfb115c90506f20e3.npy +04468005-55c595c848a8478da09163d0bb607639.npy +04256520-698a0a47dd9bba797ddb7abd4c043364.npy +04554684-d2711c36636e9b1eeacaf08e3ee3b2b3.npy +03636649-538dfee2a9b520962301d516d0cd4456.npy +04004475-c34ab9023b4d12b8b49ae6eb1612b7b9.npy +02958343-3d81e36e5252c8f0becf71e2e014ff6f.npy +02843684-4fdd9afdb1b0785c74b7a6c82ccb98ba.npy +03790512-30157c4a6c09f884c97a3fcdcfe70d5.npy +02691156-df68b8fb9f4531b42e690fa6dfd5d610.npy +02808440-61475bc1cf693943d6a6890cb66ada39.npy +03001627-7228564fe629f578e8f8c11a24c52ebb.npy +02880940-381db800b87b5ff88616812464c86290.npy +03991062-6f3e2c8b4647f488ce6b277e4d642b55.npy +04379243-9f3d0cb709260aa09ccce4c6d5bb195f.npy +04401088-434e23fb04effbb86bc30c6a9ae3d46e.npy +02946921-28c17225887339bd6193d9e76bb15876.npy +03467517-5294e1ae86ec43bf8b6c1eb99bbc3bf2.npy +03211117-f39b7f08d4ea066be57ac88f5432bb4e.npy +03991062-d74b9f970a2f4ff098910e50f05b8001.npy +03046257-3eb3ca1c532733841e085a650cc639f.npy +02992529-c410d13694b8ca1d15e144fc878b7afa.npy +04090263-f26068a05c107a8823c69c7ff0f71040.npy +04379243-884f15cfc6a3eea3dcfcef693e7ec696.npy +02801938-e57f5dcfc6c4185dc2a6a08aa01a9e9.npy +03001627-575eb48e4bf8f7b4cccc2bf504407f19.npy +02828884-b19e1c6ab766b09bcb2a965e75be701c.npy +04090263-575ccbbf4be84e3ff85b811e02bb4272.npy +02828884-3b8d16dc796f667af155d75bbf62b80.npy +03001627-8c2a3ae39c683fde3ae7d83fae2b798.npy +03790512-6d4ee0be5746095d7c088bd2a4124c69.npy +02958343-3db560d20e40c3b835ac1a825225d411.npy +02808440-b19ff5aaa6a6940b412deb0d2b0f3dcd.npy +03001627-f39d0db80cf41db9820bd717b66cebfc.npy +04256520-9c0ed8415a0a9e5c49b1e464b71de577.npy +03001627-82b42b0f3ba76484e4fa0af6f7c25e58.npy +04379243-21486e6d0bd896ad5cca18918d24f6cd.npy +03001627-bb0c057df2dff54fba4b91e89f6f35cb.npy +04379243-27d846b100a1be0535836c728d324152.npy +02747177-46fca3bdcd454402f155d75bbf62b80.npy +02924116-e3c1213d68656ffb065f1478754df44.npy +03211117-ea7dc70f0ef4b04bcbe0b8af4aec5d6c.npy +03001627-bc78f5fc9b614e357cee0fb3ce7bfbe.npy +04379243-768cb2332a16fd63855931d119219022.npy +04379243-3d8feac23ebc7b5dc6a19173dfae14a8.npy +02933112-353dd8c418146de16c7d1f675f2a04a5.npy +04256520-f43414acdca3878674c5bf7a74b1b6df.npy +04379243-ad5c26058efb026446b5ed2bbbe6c.npy +02691156-186ca7892ed6de2adb22b838c125a50b.npy +03001627-ed56af61297594bf1c4300651205adf3.npy +03046257-3c100b0dea7a60b768aab09a0ea50724.npy +03001627-9bda786a525b1ef93a11565e5be9cf53.npy +02691156-4710274bd87b099f19cd118ab9f114a4.npy +03001627-9214670b7c1e36bc1b1e2ecfb322ccbd.npy +02691156-5fc53108f6bf2f45893f875739da1b24.npy +04401088-e7ef78ddc23ab4edbad0eedd46c6260f.npy +03001627-c649c3e28d05e0877c65caaca24f3fa0.npy +04379243-8b835170d8123a1dcf004563556ddb36.npy +02691156-c00d38c09ac5e6b8405970680284869.npy +03001627-9ad2ee3a38a3d0ce3b32c8e0ac22ac44.npy +03991062-133dc38c1316d9515dc3653f8341633a.npy +02691156-fe23572aac36c84761cfaa00f7177470.npy +02880940-a042621b3378bc18a2c59a4d90e63212.npy +03001627-e26ac9cc4c44f8709531b4e1074af521.npy +04530566-99c19a1c05dea30454e3de9fd2bf8dea.npy +03046257-c526b6315e1600092a8827a91069be93.npy +03636649-ad7fedee24a70d82a5f600ed2cf472ac.npy +03948459-467ac647f0aee4453a4133add633b5c3.npy +03710193-51ad8559caed86a55b2b887334b359e7.npy +02933112-97902b0e2ce271ae60f16a92a4f24bcd.npy +02818832-7c8eb4ab1f2c8bfa2fb46fb8b9b1ac9f.npy +04256520-bf264dae9a5fd53dd39e33fed94f56ef.npy +02808440-fd34f47eb1b816139a625c8b524db46e.npy +04379243-5bce0f5c92198217aace21c72a80029c.npy +02691156-172ac13acd9aa91f3df325aac2f73830.npy +04379243-4502c9c63e7b0bda412dfc90452742c7.npy +04379243-933937b12b4313dbe7c58a5ade21d962.npy +04379243-18c25f8049fac943bb7ac4d22a68ec08.npy +03001627-953a6c4d742f1e44d1dcc55e36186e4e.npy +03001627-ccc772dd462e8d2da6fee8e2140acec9.npy +04379243-995b7cc4da9f0371eadc9f074ecd1df1.npy +04379243-afab57dbd3c7ef0e98d5fc0473d00a1c.npy +03691459-94944fbeaf37861c61ffb06b88ae391a.npy +04256520-371b7d7d2f2d334c574754e046bb9a7d.npy +03691459-93e9c3de55b1a662989c6c7df583f91e.npy +04256520-8880686b417a054fa1e36ad603c7b9c2.npy +03691459-736820a85063a4371e5b68ee10358ea3.npy +02924116-beaa2d7bb79d11758b89799e9a2e578c.npy +02933112-65dcdb468234c4f64e2e1b2af0cc59a7.npy +02801938-7a0a4269578ee741adba2821eac2f4fa.npy +03001627-bbf45d2d189dcd758e5f5b49c9f5b3f2.npy +03691459-ec1b85abce89d680a7bc6032416bc8ae.npy +04379243-69604fc24b7976d69ccce4c6d5bb195f.npy +02958343-df72f352c7fedcfad9951d9ecda74409.npy +02747177-9887c4dfab0816a0febaf541a3d4b03e.npy +04256520-c57bac39e7c4e151c8a0fe52b1df3602.npy +04379243-3b9f12fa1f257b9d85fcc38efca7d59c.npy +04401088-ab3ebae8a44e1ae8ca47cd18decbac61.npy +03001627-312df229ef2675c4492d9da2668ec34c.npy +04379243-ba03fd0b4b54655df51f77a6d7299806.npy +02691156-7ba9eb4e8405371ca8607f540cc62ba.npy +04379243-d21ad1e0d76175e3486040c0d9e85846.npy +02924116-f6f71cf39d30d421269ee466c7a9d8b0.npy +03928116-dfc9e0e55de5b717c4fc722cf32cf40.npy +03593526-5e421da99a879732d8564c06b061019.npy +04379243-1d8278324bf01d50c45662a6a951b979.npy +03001627-44c5b57d406c663403f064eb1ac2f31.npy +03001627-1e68489b0dc2bfc3327289c00b6dc9ca.npy +04256520-6d0cd48b18471a8bf1444eeb21e761c6.npy +03001627-6986aa6ac96abebc71a782a4379556c7.npy +02691156-22acc443fd007fce6e80138ae17d7d07.npy +04090263-785ec43cb6f1a534e1f2a1daf140ac9f.npy +04256520-626104245de40df863860d683ccd0da.npy +03211117-9b7cab4099b2d1dcab29d5c9003deef.npy +03046257-1ce45a951007b5948ead471f0d2cadc0.npy +02871439-67f5342ca73bcb5a664b3b9b23ddfcbc.npy +04379243-2312d2762c1bad27f84b0be7f50940eb.npy +04379243-d291243cfb51ea7dcb25d116843b43a4.npy +03928116-a5c7e8103ba4ad8e950035704d666ca8.npy +04530566-afe3c44c5c05c22649d2623ea24fca00.npy +03790512-b1bb49d472fa7a39e0dbf31b32c641d1.npy +03337140-7074f91370bd1acc91c352d02061b3f7.npy +02876657-618d55a791b8280cf256a8c3e3396495.npy +04256520-70a16608ffc4988a81ff2b419139512d.npy +04090263-2bc57c73ab84f2c7d14664a287de0fb9.npy +02828884-ac477aa3d54d0e06f9e4cc51c75c384e.npy +03991062-91e4df396135fc1e368b14e48c164a6e.npy +04256520-cc20bb3596fd3c2e677ea8589de8c796.npy +04090263-e98b64d14d3fbf40b4b0a5ba224bba06.npy +02691156-75db11c354c6342aad01ec966c80ac91.npy +04379243-9f1d1d13f42bd2728490246570868c8d.npy +04530566-27f0d2bf42b0e3374ed242fafe836df1.npy +02691156-812111e3a4a545cbc863ab010b80d9ed.npy +02828884-514ba7cb3392ca5ad5067eac75a07f7.npy +04379243-80f986ae572fce791429f9a19502375a.npy +02828884-8c942a8e196a9371a782a4379556c7.npy +03211117-6ffb9e26f6d0ac61e4a4a1a686b4ec8d.npy +02828884-4145da9aceda5bcc8b6ad894ae3d111.npy +03001627-3adba11cee055363f51f77a6d7299806.npy +04379243-2fe32a0c23de48b7a4462b13868efd3c.npy +04330267-cb5668415bbfd5dd4af957103f4767ac.npy +03001627-83649708d0f14dfb8367ecca203c14ae.npy +02924116-8bd2c0ed3ad104266a35b75910eea5d3.npy +04379243-2692e57df4705d4d10faac7a8c2754de.npy +02992529-ff9e8c139527c8b85f16c469ffeb982e.npy +03046257-d697509cab438f240ba17ccf542984c.npy +04090263-e6fb0c7f8a5f944363e66191800dfc8a.npy +04090263-c836ef9c895460ae9e4b997bcf5c860.npy +02828884-d1caf5fd22c6c5083892cfdb72a66fb4.npy +02691156-472e6c2a77198432e1211756a8e887aa.npy +04256520-13a8c6129a8e80379904131b50e062f6.npy +04256520-436a96f58ef9a6fdb039d8689a74349.npy +03001627-bdeb8ea8a146bf69e54cb890e8682c84.npy +02691156-aa05bf3c5a7bb61bcacf204c07dae519.npy +03642806-928c86eabc0be624c2bf2dcc31ba1713.npy +04379243-e0b849b1545d35dab04cb542e2c50eb4.npy +04090263-b632d00231acfc0211b5cadd4563c164.npy +02946921-926d45845c2be919f8cd8f969312dc1.npy +03636649-6f984fe4627c8333752653a04e5ed7ed.npy +03046257-42529911fe6265862b5fee72119e2778.npy +04090263-48e24736473ae37f4b349e4b3dd5565e.npy +02691156-b22014408721ec314567cadca15fe337.npy +03513137-6e082b8d5dfe38c0c4278fc12d4f4d35.npy +04530566-da57d296d06af50d6fbde5631e3e226.npy +02933112-329f11a156aee39ac59350d819542ec7.npy +04256520-76fb7ca32181075e9a547820eb170949.npy +03001627-6419887905d9d67b7d3115a956c20163.npy +03636649-e69b661bb90d7e9c9dcf2183c858e6e5.npy +02942699-936a458fdb8eb12171dc2053392a6e6f.npy +02828884-2f340f2bd55d51e5c8cbe1805e7b8eb.npy +02747177-7bde818d2cbd21f3bac465483662a51d.npy +02933112-d707228baece2270c473585373fc1fd0.npy +03624134-5cdafa063633c35ea326c894c9217cb.npy +02691156-e9dcdcd8963ba18f42bc0eea174f82b.npy +03636649-d98c3d6304228f36d3cb982c5a53c2d2.npy +02880940-24907349b2323824664b3b9b23ddfcbc.npy +02958343-63f6a2c7ee7c667ba0b677182d16c198.npy +02691156-37ed9b767fb055959d61264e98b74348.npy +04379243-95b7d8f0fe70e768827291701dfaa1ff.npy +02958343-7448f1cba230298fcd61ab83ca5e9957.npy +02933112-c35d287217403cf3236641942dd4b3c.npy +02933112-c73ebca7db882f3ef26c21d3bbafae87.npy +04379243-7ab4a9f2c8aa3636cce18f92a75d5ffa.npy +04379243-e8d55124a196c71f64a8099f44773f21.npy +04330267-50c1f300272df84cd696cc46feeb6125.npy +04530566-d3f6fc016f72c08f1346991b5a9f4d21.npy +02933112-8994e11588b62bdfed208c42f7ada5c4.npy +03948459-50ad0fec4ad3b273839b0ffdb91ef00f.npy +03467517-f6146aa6171dd4f4828b9741c7dfc3ed.npy +04256520-55d89b64ec895fbbf2ca754af3aaf35.npy +04090263-6f0de5ca4ec2493ba7dd22c0aa3913f0.npy +02691156-21c7cc3e5f27540be6553f96496649c9.npy +03001627-341bcae1e7f366a233d93f57729688db.npy +04468005-84f7242486ac543b40f45eea058ceeda.npy +04256520-d60975380ebd13746a12da8b0e0f66fa.npy +02876657-fec05c85454edafc4310636931b68fdb.npy +04379243-9eba16c76875225a2d69ef58c7c1b72c.npy +02691156-2a7c34d4f5aaea962b600da24e0965.npy +04256520-31256698e33ac007dc149927e19d9b07.npy +02828884-450fd49e69534ee6d5032aaea433efa4.npy +02946921-97ca02ee1e7b8efb6193d9e76bb15876.npy +04530566-cc3ebcb96229bd325f8dd1b77a5d87c4.npy +03691459-90882268b1169ce79428390c02f266d3.npy +04256520-f986646cfa075237c02170c33e00ea64.npy +02876657-e101cc44ead036294bc79c881a0e818b.npy +02958343-187b002f0af1ab5a473f10e6caaeca56.npy +04379243-c1371e87799885a7a329355bc8cbc0b5.npy +02933112-bfb9eda1e7f92339800f2aaba8549124.npy +03636649-dafdd320477802a19a4cbf5d3b79df06.npy +04379243-927903e9992ce4877b619f30d1fed49.npy +04090263-e639996b832a157e6e0c9892807c7fa1.npy +03790512-12f06f32ede64d613ff4d2f5a7608a24.npy +02924116-eb073520d0c4db4d346f9a49ab523ba7.npy +03636649-3469cdf83a3cba1f35836c728d324152.npy +03001627-990ae87d8fb108ee80bd85224f0b94aa.npy +02828884-d87bd42b60591573c83f7280476c6eef.npy +04468005-4bde97a6453c809adc14ba0818ee5cec.npy +03001627-3869d2fda85428c4f91663a74ccd2338.npy +03948459-9accc818df62042146be58202cd6477e.npy +04090263-f7f945288a571090202be79d8b285c1e.npy +04090263-1068169d0f5df80e91cd21d02e676faf.npy +03001627-d85b661f2c9345f819fb4103277a6b93.npy +04379243-154fd969a077a39772dc9d42e683347.npy +02828884-5b50871735c5cce2d2b12aa6a0f050b3.npy +03001627-a094ba480568333819fb4103277a6b93.npy +03001627-1ee92a9d78cccbda98d2e7dbe701ca48.npy +04379243-33eff70928eefb54738e43095496b061.npy +03001627-df91f68fcd968fd0e4f1a5bf17db27b1.npy +03636649-1a5778ab63b3c558710629adc6653816.npy +03001627-4c1c81cc186dc50fd84b8ba651dfb8ac.npy +03001627-cb711f2991feea1de6c5cd45aa112726.npy +04379243-ed59a9478c7cdaa27d892bb924f972b4.npy +03636649-2388c99892c2185268d1b9a1d97e2846.npy +04379243-d35890b708c633546f31a2b0e5969628.npy +03001627-1d6faeb6d77d1f2cf95cd8df6bebbc3a.npy +04090263-2ab086ef262c8688d6a71f46c1c1c5da.npy +02933112-babe716e40b3aa81a54c1b71c072d546.npy +03001627-e7316ceb5b944b6fd0a96520c31993ad.npy +02958343-67e1b04f88c88a5c6d07c55cf995503e.npy +03001627-895be5f65513a7d09a8ef44e1d2c5b75.npy +02808440-6c1b18b0fa544552d93d979414505038.npy +03001627-52a96a3c89305673504721639e19f609.npy +04256520-40337cef87a495ff6e8f2cf4a97051f.npy +02876657-ed8aff7768d2cc3e45bcca2603f7a948.npy +04379243-a14d6cda9c2ca5c0c955e5ed03ef3a2f.npy +03691459-2bdeb030dc3caba21ad88f716ea80910.npy +02933112-58b97051fb1efb3b4bd9e0690b0b191.npy +03642806-f53a54a64dc475195f2e56f31ec62a24.npy +03046257-fb0c59c0bedf2276f51f77a6d7299806.npy +03211117-4bfa2e1e43d64c51cbdbc7635e6b79a5.npy +04530566-8410626d841dca3218b14db3b83de9ff.npy +04379243-497bd3f966eba2d76402b8f491cd92c7.npy +02691156-5c6590461085c93ea91e80f26309099e.npy +04379243-856e86709df98497dcfcef693e7ec696.npy +02808440-654362e53ebb6e303321831d2245cf06.npy +03467517-222b705a80d75a4343b0b12983b9982.npy +04379243-1c996c187f4354db7252c133a7e17d94.npy +03325088-86e97fe0431d070fdf279ac1867e743a.npy +04379243-d47189d9686125553caaa84ea4cea094.npy +02691156-f6e6fd724a9eab24ba8e93696257b3fc.npy +04379243-c06a4b0f57cac2b020afdc30846c0661.npy +04090263-320c462553b4eb18d18f925e78a25ab7.npy +04379243-322e8aaa889e25720768660cf080d12.npy +03636649-df22225de54de36d71d7520e3757f3e9.npy +03636649-b4be7d84e2151a3e8bb3deb7fab7c9b7.npy +02691156-e2f91794c302f5c03221f63172285740.npy +03001627-61a6a9dbd3d0efc2c3bd24f986301745.npy +02843684-9c038a6c2564f3b0560e99aa033eed2e.npy +02691156-55036f6b22ddeeedca8607f540cc62ba.npy +04090263-744064e205da68779180711d39b16e1.npy +03001627-f030f5181057ddf75622d7484764b58f.npy +04379243-e686855b4c95330db3a8888e78d004b3.npy +02691156-b4d64b689e870d1b828204947d78b9af.npy +04530566-f83474c31e7bb6bc1022decd5ff96217.npy +02958343-caa26e8b5033be6ac02f176e44f0fcec.npy +02924116-2e86a7793af11e422d32966c67e5becf.npy +04379243-905628a74c7cec233a574a2e3bc99a1.npy +03928116-4b108a9725e4d514f787be2ffd2fc6c5.npy +02992529-b854fc846c1fc2ba619a006c72381476.npy +03636649-1d89da4ac1538ada9c949ae6274aa016.npy +03636649-4775f35d9b6942081b42cc426459cc26.npy +03928116-b4c3484639d15d24d6cfdd2c4c6de262.npy +02958343-274bb81c9dd9420b748999a5d81a158c.npy +04530566-bf8995f756b59102698137c717c4ad11.npy +03991062-80608e58db79d4d83b722c86abee0751.npy +04090263-d032874b5c3129a313b55e8563d02319.npy +03467517-5062f174c623b70d4bfcfdb26b8cb2c3.npy +03001627-56bd6bcf5034c7e2f9b9977a2406713a.npy +04379243-30d6d671a33b6c22e76bc197b3a3ffc0.npy +04379243-57d6c26b519918d770cd267ba4f2b2ee.npy +03046257-7e779affe56aaa3645a3ee2cfbb67212.npy +02933112-37ba0371250bcd6de117ecc943aca233.npy +02958343-7ff4c1fdfd0e9bc7b99adc532ba20916.npy +02691156-b3ac8c2c48af1c07ca8607f540cc62ba.npy +04256520-1c9d333bda4b2977f92f3e7bff4c4ab0.npy +03325088-a954783de7f881e9c36fb70296e45483.npy +03513137-43f6f91a2a64a62b5fd0ea7ae0dec99c.npy +02691156-8bb8876d55433eed216b327569dd806e.npy +03636649-1f15e31094a7460aad5067eac75a07f7.npy +04090263-28f82ff412a37a304c8f375eb1452283.npy +04554684-24d50c4d744c20494a084dbeb79b6bb2.npy +03691459-7bb0cc242729aa90eafe995fd10c1326.npy +04379243-f3b8c91c5dd1cb6b8722573b29f0d6d8.npy +04379243-d97819998f885d54fb977fd7ef10cdde.npy +04379243-3fde8835e0f31a64d8cad143689f8b51.npy +03325088-3be00bc0418fa112b362845c6edb57fc.npy +02958343-9f5d5b655ebbbb9c4d31b03e74c723a3.npy +03325088-a088bb2b65e1275f76c18e71fd49c4dc.npy +04379243-224820b020c1b6136b0f2a1430e993a.npy +02992529-ecbb1c53e881c2b25f4e4793ed432bc1.npy +02876657-10dff3c43200a7a7119862dbccbaa609.npy +02691156-700bc5991a46c1d53ddab476a0f5c5ee.npy +03001627-34108b791e6bc4ec1bb7158ebaf7e1c8.npy +02808440-f3cb920a47e224cb39773ee5b5578e3.npy +02691156-e86fd13a49f0ee0a62b600da24e0965.npy +04379243-bfa77d6ff4e853a275b278bf2780ee51.npy +04379243-440d371725f4f6bca570c6c691c987a8.npy +02992529-359be05b5042209a502122ac3599bb74.npy +04379243-8647063ec039c4eff51f77a6d7299806.npy +03001627-32d67f875ead7f1eaf46128407fbd2a0.npy +02871439-7d8a58d4c6dae408b4e3935c6cee4b35.npy +04090263-3babca331dad56aa1b3a159059d827bf.npy +03991062-d31fd6abafb3daf3153f43b48d21615e.npy +04401088-43f7d0cb3f0ace029bc144914804a8be.npy +04379243-b278b58e294a7d2bac242c3aebc81b2f.npy +04379243-b6ad7be371729438dcfcef693e7ec696.npy +02828884-e807cba7fec6d514bb5d4e2d93fefdc5.npy +02924116-ac69801f426df5c76ca2b6e5474aad11.npy +02691156-6047f2c5854dd38526cb540828830330.npy +04379243-821f2cc776043008efe8aae804e55d6f.npy +02691156-2c9797204c91e3a440975e4feec771f6.npy +04090263-77241daf76a045c099d9d900afe054b8.npy +03211117-e5e5018fe96e414528d0f4c81cc1f1d8.npy +04379243-df767f2df999315b74ffc2f06690002e.npy +03001627-eb63908dde4b579e25d45769a218937.npy +02808440-1c68386f4be530973321831d2245cf06.npy +04379243-224ec626233b7a0c14038d588fd1342f.npy +03991062-db36c80ae2c96e3dfd8e2841125af0fe.npy +03691459-f25cae5549e30302803f272bf12359d9.npy +03001627-c8265e04c94bcb5a1346e336f65f96f6.npy +04379243-ee6a58b9f4a5a129ba5342d638d0c267.npy +03001627-27317a0db349369c8b74e4684f0d409d.npy +03636649-a2c9d00ed67862af2c528d33bca1ac2.npy +03593526-ef5269ba557da598561dce3fe08634b7.npy +04256520-ea0ee7b60919e35bb1dd813f3c0d0dd.npy +02958343-a6acea161250379aba3e2415e22cd45c.npy +03001627-2dca240a3726c004a83826e22c7812a6.npy +03001627-8f23005418fee71819fb4103277a6b93.npy +04256520-baef1491d5bfb6cb58e51facd8ce1a25.npy +04256520-87936de578cb81c4c61648d3e90c5695.npy +02924116-bfa9f15a8aad2e4d37bff66a594d9608.npy +03636649-381c2fb265c32cb093be5e169656ef71.npy +04379243-ba4ffdf3eed29dea9f8c3d2002c77ddb.npy +02958343-d953bbe38edbc6f4ea999fe4ffdc2504.npy +04379243-5485834dbd8cd031c963bc72ef3a8742.npy +03636649-b0c346ea1fa3ad0b2d7dd0a148440b17.npy +02801938-eb58305e6c1b4455a9e3e4940ed610e4.npy +02747177-2a25715df1064c8ad5067eac75a07f7.npy +02933112-c7c782fd5976ed7214038d588fd1342f.npy +04530566-9e4cf06ced9331d3bed4193378c6c5c8.npy +02933112-6a121783609b4a18824662341ce2b233.npy +03790512-bb1c9e1346c5262bedb66d5d04c0da43.npy +04379243-17f4b14ebbe37179ab2b7e9ed9191486.npy +02992529-e30f2d19e9f44f6ab0cb879d4613195c.npy +02958343-2fb5fe84c28b8b35cc02882a83047172.npy +02691156-446327ea5e2e50aebbf3143b1cb6076a.npy +03948459-af10941be2d5778d25c70fb1df3f879b.npy +02818832-be8ce1bffe716f7ed2ebda13f0b603e6.npy +02924116-cb3bb1c939c73f5752470de2774d6099.npy +04090263-49fb34153b09db8dff790997f2048517.npy +02992529-53ce93c96d480cc4da0f54fde38627c3.npy +04379243-ac1f8fe1e544b87fc798432661977bc1.npy +03636649-57e53cf314a173f835836c728d324152.npy +03991062-6e8297cba6273bd172a90fe1ba02202a.npy +02691156-7f09b3b11ae3f22dbe13ce34aa7c0c1c.npy +03593526-451d7b1633aa8ee741da9a75408092f6.npy +02958343-37fb762e57f343a7aaafd94b9f216ef6.npy +03691459-a0f57b3d2c2ff2ee2666ee81c3e6ae4f.npy +02773838-6187bd900c3bc002ed13f430b2941481.npy +03636649-b444be0623b2e237d73e51f8db3a696e.npy +03642806-f3d162798a285521da0ccb8671dd235b.npy +03001627-e9f83e38241515a7438d8caa9ae106fa.npy +02808440-a7e6c5f63e2ed8c2f6b70f40d73aaf47.npy +02801938-f15e1a252c89c4d3494d18cf12f347f3.npy +02958343-3d693af6fbae47f9cfb661f69a0dfbbd.npy +03001627-2a6b8437623a374e504721639e19f609.npy +03001627-19861e56a952fe97b8230112437913fd.npy +02691156-d1cdd239dcbfd018bbf3143b1cb6076a.npy +02691156-2b5c0a38c754927d21abaaa81d1a4195.npy +04256520-9357812939117927c0450f087c15de65.npy +04379243-dc611d5add49200d868cace2a58d7210.npy +03991062-5b476163b025a5931143841839c8c312.npy +03046257-83215aac91958278ee2b478fec745c0a.npy +02691156-9dbab9e46b372e837645a27090729af6.npy +02828884-1d9fc51fa296bac9a1770107888e7eb8.npy +02773838-581af450a3a8009abc49cae1a831a9e.npy +02828884-1ee7b919637a2acecb2a965e75be701c.npy +02808440-e88fb160e35aae493a762233fffc49ea.npy +03691459-9a91398e66a8c980ebc29484102f14e3.npy +02924116-d6b48aa8ab3b5c8ea22d178fb4ac75ef.npy +03991062-297b925ff864c56c8ec58bafa7a6bebf.npy +03790512-70d9cc5115bfedeeab548456bc75847f.npy +03593526-9a5cb53a2858225e72a5c49c981e6593.npy +02871439-f807ffc89f4855f7d927b44c79143ca4.npy +04379243-ad63116007d98a6d19758238d4c7aff2.npy +03636649-67780176ebcb050dfe3e90bc90e90c63.npy +02958343-528fffd59eee9bc5851f021b9ed69c58.npy +03636649-3c756a2c1c62e73b7252c133a7e17d94.npy +03642806-151fccb37c2d51b0b82fa571a1cdbf24.npy +03001627-28844eb55fc82dc8f4b6538438a0b930.npy +02691156-6eb12144093da25e816e98a113f4d393.npy +03325088-7e8cc52fa74c26b4eb1f243bab39fb29.npy +02691156-8f33d2c0c08befe48caa71b1fbf7fb98.npy +03467517-264811b5e65101acc34b900bb2492e.npy +02691156-a430ba73d3ee2c0fca9f0727e23831d9.npy +02958343-b619910e7e51d8e176ad064d1c5fdd7c.npy +02958343-9609eee1c5f60dcd610425baad975046.npy +03761084-b2ed63bc028b50096c3c8e8c91d35a17.npy +02691156-9378f4e9b3bc187e621c837076d6923a.npy +02958343-d014af11d76dbf667aaf79c2db0c7371.npy +04530566-3c52a65c90a604f36d41dce38b96c472.npy +02691156-584e076b6cee78addc3757fd1f4189a9.npy +03691459-28be6cc8685c68464aebea9384ce74e0.npy +04379243-90631514bc5dd234c798432661977bc1.npy +04225987-efdc98987203bafb183fac288c6ded1a.npy +03001627-1d1641362ad5a34ac3bd24f986301745.npy +03337140-b4194440c21b4db77a50afc9c93f8a50.npy +04090263-329f6414584d87a999b3da21343e5637.npy +04004475-d80d585502fcb9d3199f2eca998ded6d.npy +02828884-729650e08d4ddb97ed98cca8f0ccd5f7.npy +04401088-bcb8525b5aa7e4a5a62dc47412730fc9.npy +02808440-dea2eef8fa6690061031459726e7e8b9.npy +04090263-a8e3b605c0eb659e5f6c4107d78f2cc.npy +03636649-bb3f359cbcb046a8d24a4ba64e02f65e.npy +02958343-e7f40f595169f1b44a383db4764d5432.npy +04379243-fc3d08b88b00d95212610a4585592f3.npy +04530566-697c8a9055e5ff2ea7a62969e8bea32d.npy +03790512-6bf1f988493dc23752ee90e577613070.npy +02958343-1a64bf1e658652ddb11647ffa4306609.npy +02808440-1f3abd1016b4b39e4c62bee40dcdc539.npy +04225987-141616a00df67c351082f2ea630bf69e.npy +02942699-9d79c246317bbbe87f72d6c7f2024896.npy +04401088-46261b630244bdda533775ea6714a372.npy +04379243-7b9a5531e98308c8c3bd24f986301745.npy +04256520-75d58cb9ca1475f86f37a8be59c15bbb.npy +04256520-83f9051ae9fb1598cbf5d61bee02065.npy +02691156-77c86e12f27b2adff602d628e1c92113.npy +02924116-48a23d75d3bbdc1c8c6047ec67401af8.npy +04379243-6c322cbf532f87337c577fdb71c158.npy +04004475-68a0a6e41a0409ac77efed640f9b11b5.npy +04379243-904a4c3f1ecef5f852046ee916d15a12.npy +02992529-df2299185baf20a17b1546f309a98bd9.npy +04379243-649da94b45bafa807f8769b595aa12b0.npy +04379243-7937479e527b07dd19fb4103277a6b93.npy +04530566-e765446c37351a26850e00840470903a.npy +04090263-b0bfc504cf144baf2685de1ac73dc74a.npy +02691156-e1e7f3843b1fb876f5156bb441883fa.npy +04256520-4afee57f3134a483d9b53420a5458c53.npy +04401088-96b1d230e88cba16f71555c6480aef72.npy +02691156-52a84fea7c314f4c3dfc741b4df74043.npy +04460130-10312d9d07db5d9a4159aeb47682f2cb.npy +04256520-63e91cd73f169af037f251300f603b8c.npy +04379243-8c67fd5a15e8d9defebad4f49b26ec52.npy +03593526-bbaf380835e362d0de03ab2a27ba7531.npy +03001627-4446234d12158c42b161f36d4e309050.npy +04256520-c2f02274b4dd4431b4e7c0374e7ddf69.npy +03691459-40007a605a25c71d747b49524a1246e.npy +04401088-d944c42ad08401651e5d846d206adf3d.npy +04401088-36290375c3ff67b9fa391a6b067626b4.npy +04379243-387b1c9a2f50ec314b3c42e318f3affc.npy +04379243-a50fe14a700587304b7b1010fff3cd07.npy +03001627-21fb308ca737174e22f2f93459bd863e.npy +04256520-990adbf32c6452878eb3bc6c6d15f9bf.npy +04256520-dd78c16d85780d6b413102507b68bcb5.npy +03593526-44a5d28686a9b8c9182816640e3b1915.npy +03938244-2805a2c180bdebfa38071eaa0d0d49bf.npy +04379243-d8b547a164d2f356ff24b36f1450b61c.npy +03593526-e42b51de027eba748b9db7e7b88ffbb9.npy +04379243-7e85deaa7bd114eedcad73f240f03a20.npy +02808440-eaa7c4771b639fc554d7082b34825ef0.npy +04379243-5530f95795fce09ca71c812e027f94d9.npy +02876657-a429f8eb0c3e6a1e6ea2d79f658bbae7.npy +02828884-595e48c492a59d3029404a50338e24e7.npy +03636649-f97011a0bae2b4062d1c72b9dec4baa1.npy +02828884-db663d2bc7e398ad67a2f40ab335eb08.npy +02958343-312da43baca104262c98dffdf7adc4e3.npy +04401088-504c453471faee3ee304974abc9afad9.npy +03001627-94ae179dd1a1492d1191025061735ea3.npy +02691156-9a3cb94af2f2a5b826360e1e29a956c7.npy +03001627-539ddc43afec160e57b8f616df7adf9a.npy +03636649-28210d460a79e323322123314d92e1d.npy +02958343-a015b428cf628af3522dcdfaad316d22.npy +04256520-13534db5278d476d98e0d1738edd4f19.npy +02691156-9259906152f9d885a8cba409c4409ba9.npy +03636649-c6424950ca9447627d8864caa856253b.npy +02933112-d56ac97208393d54bc8967b0321bd9d2.npy +04090263-a32acd243e91fb32a59327b8ab7c01fd.npy +04460130-fd6ca820662bbbf3ba10616cfe5316d6.npy +02828884-33458d73568cfb62d201085e80edb26a.npy +04090263-c044bff4423c7889a2ee232a197081e.npy +02691156-8b72934186e1d8b0f510cd52a5f27547.npy +04379243-69e670c5a40a40ec9095fe1213108032.npy +02691156-3112ef52e6da5d6142320ab3b0c39c62.npy +03636649-c52af321a31d28a2e95e8a5faf311c2.npy +04379243-25c9cd32e5ec1e7cdf54d2cac06dae5f.npy +04468005-e02ea2b2d926095aeee40229e2e3ae1e.npy +02992529-3993102ecafa0826ffd1164158ab2e9f.npy +03691459-ac27fec4b0460b00318a4feb4ab5fd2b.npy +04379243-237e15796ba16d86e1b32bbe69d5bc15.npy +04256520-71e0e0315d718004e7c7920f6a65a54d.npy +03325088-16ea35ec6ba0c4a7b7a867e9b35a1295.npy +02747177-2f1aed8925147120c62ac18334863d36.npy +04090263-e892f50659fc9f8ad33dc284f29d8394.npy +02946921-a70947df1f1490c2a81ec39fd9664e9b.npy +03691459-421eb9597a33cffdfdd1073b17e9e51e.npy +03001627-8db4d399adc4d6148738e7290b6f3237.npy +04379243-75bb849ce0a252e72c1a544eca74c954.npy +04090263-b3e73818cd2e03c080149f7d680e9c1a.npy +03001627-20d01aedf15d4d1d23561140a396280f.npy +04379243-1a3cf7fca32910c4107b7172b5e0318e.npy +02691156-ca88882d06ee5468c34c40f49da8010e.npy +03642806-ed35ed3a7c8824e5996bace9c8deb982.npy +04256520-c35d42881295d9cb86debb0a33c851f8.npy +04379243-d4937d73a4602e66d9a65329a03d80e5.npy +04379243-379ad91ceb20859b0a3f25f5d8cb0f8.npy +03624134-d7cd204b24ccfc99baa86a06fa108e26.npy +02691156-6e25548ed9d2c7b597dec65c2238cb8a.npy +02992529-f400eb5421283e8a102f4912aece242b.npy +02958343-53c118280e60df0bd2350421a9405ba.npy +04090263-8e461cdfdb0536e1b5666ac9dae008e8.npy +02958343-2d1718bda87f59dc673ddeabdcc8c6e.npy +04090263-c5cfbac689f8f49310e71dd8027aa9c3.npy +04090263-5004ff6a719d0c16c52533855abed4c.npy +03001627-2f0bda4f2c225e0254141309938df7ee.npy +04379243-c0df578cee43eb8526f51cb1aef0ea9c.npy +03001627-330dfd669062043f5e60ee22a227533.npy +04379243-c8575754df874644dbbc9440457e303e.npy +02958343-9ee32f514a4ee4a043c34c097f2ab3af.npy +02958343-cdba926f41c3b1ce92dd8154d7e0933a.npy +03085013-6c3bcb83c57e430f584c9f4a9f37e15.npy +02691156-1f7a516fdf80dcdc1006ed55bc1a3fc.npy +04256520-97334ba30676598958f7bbfa65d864aa.npy +04379243-6efcaa530059319a720daf9b94e7a5a.npy +04256520-64800f14a795d8759055f83d11955109.npy +03001627-523269ef7703a120cf004563556ddb36.npy +04530566-82180d1a6a7edf815e585de41f56d4fd.npy +02808440-e3a0391e9fdb7671fdb7801f07fef3bd.npy +02992529-ab4ddf9e4130d6b560cc5a290ea3b31.npy +04379243-2943ee99465c7adf30bbd4cddd04c77b.npy +02691156-f21a375ca5fd26994fb6540b6bb872e9.npy +03211117-2d8a4b48acaf84d791bf924be509bc17.npy +03691459-b488f301cc8c7d0d4079257326eb1699.npy +03001627-3c81fab5678a3872327289c00b6dc9ca.npy +02691156-65468fa9ca2f3e9e642566c028df23cd.npy +02958343-4271d0c8cdad6a84e572d3df5e4fc85f.npy +04379243-683ca17c9b0d6c83f15d71fccc06917a.npy +04379243-2dedcb98bb6e9375aa2e219918fb41bc.npy +04379243-db3d26a5f2a99aec433eec73a2fff97a.npy +04090263-85eba152f5c367bdb3bf5cd8f4c141b8.npy +02828884-ce9c518ef76b4974d56cc378741d37e8.npy +02933112-de23f702d6e8232f12de5317fe5b354f.npy +03046257-7c62a7d42797a720a480742f4529182b.npy +04530566-12b5302a8aa697a138b0c448fc291f4a.npy +04379243-c7fb18d9ee7dc33318a6353ea60f11b6.npy +03325088-1216d075b84b3557979c556124bee033.npy +02691156-dfe65f8a20df11c5d1df55cbe0874aa.npy +04530566-6f8bb01950141f63b3e3c8d3ee0e8f52.npy +02871439-128a322c75bb43195050d6a2f5d42f74.npy +04379243-12cecbf8685f52aaad762904f2c09cd0.npy +02933112-d7762b2997bb9e2aa70a592d6c8c9234.npy +02933112-1b269019c7698355a8737fcf23389014.npy +04379243-210ad02f34db100c236f7a807f5aed3c.npy +04256520-b929ff628fee53d452f2ff843abfed75.npy +02808440-8bb8368541ec46f654d7082b34825ef0.npy +02933112-6aebdfb1622324617eee615e75bc3b77.npy +02933112-54c4eb19c59440128f7c4148465d43b6.npy +04379243-e13ea4661bd5e168e7fcbdad594ae05b.npy +04256520-1731d53ab8b8973973800789ccff9705.npy +04530566-5cf29e4dff6535c394eb4a27c704b88.npy +03001627-7139284dff5142d4593ebeeedbff73b.npy +03001627-2b69e899da0c15cfb40f0ac0fb9a650d.npy +02808440-3124505d1bab02cbb362845c6edb57fc.npy +04256520-cc906e84c1a985fe80db6871fa4b6f35.npy +04379243-fdc04ac9fe8dd6db04cb542e2c50eb4.npy +04379243-a7f98e26ccb27f0b52225a4689f7f600.npy +04379243-485516a2c88eb0b8b516c05d046e8e45.npy +03001627-ceb04c53d8aae1319fb4103277a6b93.npy +02992529-6710c7894efe94cb918f30c146a92bd0.npy +02924116-36c043dde81d976b9c331a603e039290.npy +04379243-42384087aab891baee18bc48b60b36b7.npy +02691156-c235f2c6d1e8c80e7f436bc8bb8973a3.npy +04090263-5aac06335039030132f8337ee2b84248.npy +02828884-9ceab93b37b71c47c62ba64662b2626d.npy +03085013-aaa82b33a0414ab6a374d341749045f5.npy +03790512-f5510d06aba5b0f683a3e53900c6cbba.npy +02828884-80b20fdbf1183f37b7491f8d3451cded.npy +04090263-94a724430f78e09bf0e835155cdd677d.npy +03642806-2ce3a50ca6087f30d8e007cc6755cce9.npy +03211117-58837198e067db4cde008fce66fdc56a.npy +04090263-27b6d2084f80ef3a7b7f00333604764a.npy +04256520-ac16057c9ab79f7f2c7685af80c3d87f.npy +02808440-9c66a619b577ae713321831d2245cf06.npy +04256520-e877f5881c54551a2665f68ebc337f05.npy +02691156-a36d00e2f7414043f2b0736dd4d8afe0.npy +02933112-2cfa88eb16cfd27b921dd903dd0b8b17.npy +04379243-7494fb1b493b36db2b3f122bf827792d.npy +04090263-b017d865b68cd1adb4cdad9a5bf52dd5.npy +04379243-41adf7a8d492a41ff12d7184a2ad3430.npy +03467517-1070208ea6a020b8782a47e264016477.npy +03001627-ecb57b01c7ff75cd416e7824059e108.npy +04530566-1b00e4c41b4195807e1c97634acf0214.npy +02691156-c0edd36fbf8d63fa35fc197bbabcd5bd.npy +04074963-7af8b6f6f78d0eddea30b1080420ecf9.npy +03046257-95603651d927cd6c36a36f8fd7d27134.npy +03636649-9fc3ddc511f4ef62dced62abd38a02b0.npy +02958343-b0945cdea946d1a363c65629bee30ef9.npy +02691156-a87adc4fb1229b7f6d0f2528dd6f85b9.npy +04379243-4c0e985f49767f90388021e2e5bfc1bf.npy +02958343-b1736379a44bc475352a2541f8b4515a.npy +02992529-8d55c1677626cc48214d974150b798e9.npy +04379243-d6acd7d7c9e0deaacc963bba1556032a.npy +04256520-aa41f9c1ea3647ef5dc3653f8341633a.npy +04379243-8ac4ba5328ac4f423a14972b15e80b93.npy +03211117-68944f7b386310c2515fc0d40df6c5c1.npy +03710193-34b80115a8b77c8c1647dbe61e0fcd1e.npy +03642806-4c7814676c42d67b902e12fe4da5924d.npy +02808440-51ec60c0a42d6b23911cae4661bfbfe1.npy +03691459-5ebf73b0ef33aac5451319990092e2bd.npy +04330267-50557c5a0d38b38920192a5319e3e2e4.npy +03325088-12e62ae56879bda8979c556124bee033.npy +03636649-4bb0f244d4abe00b44949d7685cb63ea.npy +03991062-6c2bb8a74adf58305a340b65638f743c.npy +03046257-52255064fb4396f1b129901f80d24b7b.npy +04256520-5319006bf5783b6919fb4103277a6b93.npy +04379243-c21637acf98dd08649bab4be538c970f.npy +02958343-c1b4d407168867c45dca6305fb9f97ca.npy +03085013-3ebc2b3e6235869fc7be8dc1ce3991c2.npy +04379243-2b4d9c4722bfc075ebeb8f91be624923.npy +03001627-388ffdd2dd3c0dc0780672cae8ec94c.npy +04530566-ab40191e935c415cef0a5cdc2cab422d.npy +04379243-6ce30b0327db26f340b4c5428883e585.npy +04379243-bc5d39edb7a6efd77b9bc6a8e1b90da7.npy +02958343-b67d3833e6991de8dd141480e2c154d3.npy +02871439-6003c51eee40d5942f84cb7932f866fd.npy +04090263-f90191dfe0bce3ad49f0e3dd7767881.npy +04530566-1b2a8980c17fdd97c897e89b561760b1.npy +04379243-46c3080551df8a62e8258fa1af480210.npy +03691459-28b91f5ca7e3d174fb0a4dd466ef3d66.npy +02933112-938d8ae0cdc787107bcb070cc655f13a.npy +02747177-a9cd539f8a5e19e06af350e51093426c.npy +03636649-12dd2b962777328551014c684c004c28.npy +02933112-22cc22fa33c8203ef1bd05634b542a1a.npy +04256520-6ec8a2dc3bae5a9b8b709c58c1c5ee96.npy +02958343-d1a54cb41a88702b1e8e2692714b2614.npy +03001627-13d4fceabfda96c0bff8d8db0f9298ac.npy +02871439-fcb0bf443c62225b4bd9e0690b0b191.npy +03948459-b86cc2e83384030d91e284193311f752.npy +04256520-d3c5ce89b20dafcc57ae08c3105b4e6a.npy +04554684-d4305fddf4c03812625f0e5788fbff74.npy +02958343-fffb1660a38af30ba4cf3601fb6b2442.npy +03636649-dd284c442afd361e37f2340db925336.npy +04090263-37cbf8e368b06b655e43a6efcaa57d09.npy +02691156-75916f78e72f90984b70ddbaea6e513.npy +04379243-a2405bb8642d5bcecce90f0d61ed7a70.npy +02808440-1dc8e88da760f186ccd0340812259a39.npy +04379243-4abe61d5f1f800b6c8d74856214be3b8.npy +02958343-c8c51e709d1cdbe0673ddeabdcc8c6e.npy +02691156-44836457aff60736e10e757961deca98.npy +04225987-8f78a26403f09b708b3b3a08d28a7d7c.npy +03636649-d4498a4ba89b9a0d4a73e364671ba824.npy +02691156-48c4b6bde824e987a8cba409c4409ba9.npy +04530566-ac8afdd8c70178abf0a977ae17a6b223.npy +03593526-82298657eaa980d323a295070ca176a0.npy +03797390-b6f30c63c946c286cf6897d8875cfd5e.npy +04379243-96edd3d807d2b1c7d1869c3a235ed163.npy +03928116-8c021db546a9248b582c9847073623b0.npy +02691156-251313501093a024599faef54fd54e83.npy +04379243-1f748bcf0ee8eea7da9c49a653a829eb.npy +03991062-1b39d7b69bee8a09a2c59a4d90e63212.npy +03211117-f7d209529e47778d7a39f8821ef8c382.npy +03624134-dce941899bcb752dfe474f09e3f3ac9a.npy +03636649-522bc10920249e67141c66e2b49d221.npy +03001627-4438e29f9d3cf45bfe52ffd0e748a1ab.npy +04379243-8c7a08d437dc8431369b4bd8c721a288.npy +04379243-dc13119307bb03338aaae3d020f5ddf8.npy +04554684-2010a39c4b0c58b714b35a7d7cea7130.npy +02958343-f7362613dfd3772faa69dfdc5532bb13.npy +03691459-9432e02e277a206e3fccb208b0350a.npy +03001627-2d6ec4afb0ef827e2c5b2f528cea9dd6.npy +03001627-5cb06ff2b420c24721711c78ff413696.npy +03636649-a17a7f72494b303abc5744a94c74a7b9.npy +04256520-75071b6962f431175becd8a4c3f1866.npy +02958343-b88a4c0cb2092fa52fa4ad29a1236d7.npy +02691156-324304121b61339bc36cfeafa51d54fc.npy +03636649-8425ceaafc6cdb0b159fbcda62e85465.npy +04090263-b449f16a0cbad90088be2a30dd556a09.npy +02808440-2e752b6c5b6c1cf865793e85eb09b261.npy +04090263-baa007b1a903fc432ce452abffb6910.npy +04379243-7084db2193bc9ee43d113b8340bd5029.npy +04379243-913c0ff011ad0658dcfcef693e7ec696.npy +02691156-40dc09d726aa6325ce2cec85ea6ae00d.npy +03761084-1674b409f2dda7774c86b1fdc94892eb.npy +04379243-c06f1cb96170e548b2c2cd006d206129.npy +03948459-2f50338488d6254c6460d209041b501.npy +03211117-f17247f450ab313489d3a03b2edae972.npy +02933112-6e765437962f4c578e51433393e177c0.npy +02958343-4b7f9ec47ede386222f104fd8dca95f6.npy +02958343-63959ab016687a50618e9d35559b7aa.npy +02818832-efdc740a363e1521a58e28eb06d46abc.npy +02691156-4a199b1c3c80c8823bfdf036d38c839b.npy +03642806-517de75577ac6e8a42b9615216f9a30d.npy +04401088-bf15900bf5afb946b35f223cefd97829.npy +04256520-be5f2498434ecf9a4b3c42e318f3affc.npy +04379243-5df14a5997ca80fee45ef4135c266a12.npy +02828884-6b05c22024088fa92056b4bd5d870b47.npy +02691156-5c379a118ec80927febd4e8b843c95aa.npy +02691156-7662fbb435dc1d0760bb9786c97a649e.npy +04379243-27a90972dfe64be5c3bd24f986301745.npy +03001627-fdc7f288b8c65494a7101992f797b6a.npy +03636649-4ffb03a364a13c376b41b8bcd0404ec.npy +04379243-724fa46215e03f4c52d9fc61873164a1.npy +03467517-eece2b501ee7563683ce694a1c6f6c51.npy +03928116-5e3aa6ba5934dfc6a9a82795b0444b1e.npy +03001627-49cbfde1ae92ee555706d1c54190f27a.npy +03001627-f3718bcd0e497868af7c7ad2549a1b15.npy +03642806-b962658596d9a6ccc05c2f3d0d461abf.npy +03991062-51a88bd35c6d7824eaea040a8e2015d2.npy +04090263-68432645acc0d554def607f4d4140edc.npy +04379243-d48ceb6fe098d078f0cfa7d27eaf1bef.npy +03001627-cacaca67988f6686f91663a74ccd2338.npy +03001627-d49ce68499ee980de6c5cd45aa112726.npy +04379243-dff9b5c37bedc55e9f011a37a96f51f.npy +04379243-cf52e17b21021ad9490ad276cd2af3a4.npy +02691156-f2fda88e9688fd81d972c9dd75ed77d4.npy +02958343-de0cbca344b9de834f36122a581b2941.npy +04090263-7bde81ebddddd161cba7035647fbacdf.npy +03624134-693c599683ba86a410240762b65ed973.npy +02828884-a064a3e9b537fd64818b16b10229b98.npy +04256520-ceb04c53d8aae1319fb4103277a6b93.npy +04256520-17555a8b1def80abce101336817a135f.npy +02691156-efc2f4eb92871bb2b7a641946dd77b16.npy +03001627-3a4d572dc16ac52e201e82f29479384c.npy +02946921-e928ebedb376404f8e5478c8425d418a.npy +04379243-79650ee83a0aabc8e1dbce34224f2394.npy +02691156-53958f924a50069090baeef8ba5b93e5.npy +02924116-f55c41a1f4dfe4e5a1c12b50998c10.npy +03624134-ebfb56c4968055e794581d435607029.npy +03467517-d4ec02d3ebae75249f4d0101328eae2.npy +04379243-89875a037902c0664bd9e0690b0b191.npy +02691156-a2b758aa5d51642bd32761b337f8b72a.npy +03636649-376c16f40c95e81429eb9d04ea723179.npy +03642806-be6a1fba2165bdfe2f81cb887dc35578.npy +03001627-200597e4eaf96015a4fb72f4f3b0e317.npy +03046257-729270762f381e7b1bd71c75e3a794e0.npy +04379243-a8126dbed61e760433ea3991d83e660a.npy +03467517-aebe041eaae1962921d62dae9ac1d30f.npy +03001627-ba074c9ff5e36f60e8b2b8dc0c816caf.npy +02958343-555a48617127033c25ad20bb66839d61.npy +02933112-85868e1440bec257a4bc7fdb4c84963.npy +03001627-45fa737cbfa8a8b69b75b6346baf0c12.npy +04401088-5cf5bbb8f745033195c9a4bc0e92777e.npy +04379243-1dffc3840500e89ab8e1b99345a5afd4.npy +04379243-394c63a5658ef759b515d1675be6b5d3.npy +02828884-433253d0d97f814025444614eab3fc33.npy +04379243-e92a4ff2b36cbf83490ad276cd2af3a4.npy +03001627-28a60e0e9adf7eb0a3340564b56a7f70.npy +03938244-cf2ab5d9bff184ca6325569942918d9f.npy +04256520-3aa613c06675d2a4dd94d3cfe79da065.npy +04074963-86982fe32e06c96b11eba86b475bafe7.npy +04530566-c96d837820b8fad281b4fce04c14eb91.npy +04379243-b4a66058027312c7ac51268fdb437a9e.npy +03001627-697cb70c54a483f1f80ff10f4838c137.npy +04379243-9e3514da2268557855931d119219022.npy +04090263-c4efdc79b1132dc6533df38649ea120.npy +03991062-f7e29e0b93652ea4b522742df2e8c383.npy +03691459-1e9032f25c5d068fa7a69b946cbafa2f.npy +03211117-241b26438e8523ee2846fa729d90e125.npy +02808440-ae8938fbd91ce8e0c790d7efcdfb5239.npy +04090263-f16eab54ab97a97c8cb82d02bad057b9.npy +02691156-1deb997079e0b3cd6c1cd53dbc9f7b8e.npy +04530566-fcf21e1176459664806b90e3f08c9a28.npy +04379243-8aa73d4e62b33e8787e41ecbc4197db.npy +02691156-12c82319147385e7ef0e1705c5c9e361.npy +02958343-bf1893badd1c6bef59a47b1880958de9.npy +02924116-30c34a579410bbf2102055801a18154b.npy +04530566-e2446b9f4b9fb179f525bb02d30fbbfe.npy +02828884-7cbde340db4f4ee2cb2a965e75be701c.npy +04379243-392315d4bc7f11f0ca67acef5667509c.npy +02958343-cfac6b6374bc4fedeb7780cdb3ece367.npy +02933112-942e67160b47dee1b27fe5b4f7a28eec.npy +02691156-8448475504ba9fdeca8607f540cc62ba.npy +02992529-ed9149921b734b2941edb96d309c9a23.npy +02958343-5ce9ef613933a245538f2c6e5c51cc7e.npy +03991062-f294c6f54167f608f5c37fe197319e1.npy +04379243-3083f8a34c6a2087a538396439009b89.npy +02958343-a8f7a7271a02fd56afe1d4530f4c6e24.npy +02958343-fa37419c844e77076489e70b7c61a054.npy +02958343-8d14c94dd325400d93b973d059f27e65.npy +04379243-bfd91773d0b2a32fd39e33fed94f56ef.npy +02958343-e673f203b40ef869567880160b3acb12.npy +04379243-ecd56b7b86c4d94ad1f278e1513f3b7.npy +04379243-a871ec9aeea7cc5ccb5cb7e88a8b34ae.npy +02958343-d224a01422266fc51b3c1c9f0ad4025.npy +02691156-1d396e76ecfd973575ffe5b08493cffc.npy +02958343-cd2ac3225eb36c0e1a04a94f2d5fba0a.npy +04379243-441bfde4486fb4cfc3bd24f986301745.npy +04530566-d65fc1dbe7fe802a5761a0b53ed37cec.npy +02871439-aa0c28ead04591cf85e5aa3b80e9875d.npy +04468005-ab084adb3157a8d44b0b2e6e63122009.npy +02924116-134537791c7e420180288501d9901d7b.npy +03991062-289ae5a92b072ffcfa34c1a2d1bce0e.npy +03642806-b6b27929b34cec44125129881929616c.npy +03001627-8c629a89e570c8776a9cd58b3a6e8ee5.npy +02691156-ec879d7360572a5db65bd29086fc2a67.npy +03691459-55e68ac8c812b332ce1db673cf70420f.npy +04379243-2d466533183daaf027cdc3d721fe0086.npy +04225987-47bb28c62a245621ad3e04762b7c31c.npy +02691156-1d6afc44b053ab07941d71475449eb25.npy +02691156-3998242c3442e04265e04abc9923b374.npy +02933112-247dfd279585b1b0c59350d819542ec7.npy +02828884-63a218005fa1bee7fd313061a14ce51c.npy +04090263-2d0eeaae7231064af4de29b99f103946.npy +03691459-bb1b387c674fdc4750577cf04f3bf74a.npy +04090263-2036799fd4fa273918ffe448c7d16fdf.npy +03636649-ab3e153cd23e992b576a354bb9319732.npy +02992529-758b9da6bf573838d214322c26aa0cfd.npy +02828884-c064a0ebde53de5ad5067eac75a07f7.npy +02773838-4e4fcfffec161ecaed13f430b2941481.npy +02958343-2b800f158324986ab6f657757c95f74e.npy +03691459-47d3fbf37d73e0bfb9b1918ad0534ba6.npy +02958343-846e6c678f53bf422e877e82c90c24d.npy +03928116-c7ab660e1fde9bb48ce2930380f4c6e7.npy +02933112-736e810b71d009bbd40c07d3c15cc681.npy +04090263-fb62b780ab54dbaab20f6e48f6a30cbf.npy +04256520-d6f95d8ef06e6db3ba0604df5d71bead.npy +04379243-5261950cc1cc0d2a9ccce4c6d5bb195f.npy +04330267-2de24aec04fa960a5eb64c1003065596.npy +02933112-56e1f35c70ad2859c59350d819542ec7.npy +03636649-169ee245f8ae927f5dc3653f8341633a.npy +04379243-ab10c2ec41e0e7f1391e4d6c585a697a.npy +03797390-e94e46bc5833f2f5e57b873e4f3ef3a4.npy +04090263-5a64d7b0677ea932d08e423afb7a8cd2.npy +03636649-4cf4ca85d2685b9b98d5fc0473d00a1c.npy +03211117-2a2369e8b0a139f67230cc2111ecdc77.npy +04379243-5353ec05576ed7c0aa7cb30470f3273c.npy +04379243-f98b9036a56fae4626da964cc0cf44a4.npy +02924116-7290270e8dc33f5bef54591980b8a426.npy +02691156-5a4c3f3af30e42e057891d676f728bc0.npy +04379243-e2ccba151d9fee85a71c812e027f94d9.npy +03046257-eb1bfa668da64d48beb12355e9e20a98.npy +04468005-b46cc19663effd52c6a67affe9c25b21.npy +02924116-6f4317ada701853d76c2a9de5c96f76.npy +04401088-72d3c4148500a7fe1bf02ad5664135fe.npy +03624134-820138b6742e713ddaf44b37a13dc4d9.npy +02691156-ac463974cee5a8867bd1a5c452e6bb5f.npy +04330267-3ea1ace396f6ccae48407a54b1fbfda8.npy +03001627-fe8b246b47321320c3bd24f986301745.npy +03636649-20cd92a6797a9ee12ebeb1e6a8111f53.npy +03948459-6dbc7eb805ad5830bb1cd7e49c28b731.npy +02828884-210ca657d9a1b85cb2a965e75be701c.npy +02801938-acfe521c412fcd04564c0afd61663476.npy +02691156-391b9c5bb875607c19ba010ddb4974fe.npy +03948459-990a4cb8e20177dad957eaf7f4edb205.npy +03001627-672a6459e7606b23532a8e162f399205.npy +02828884-c7fb65bd3bd09a852056b4bd5d870b47.npy +03691459-ebbb434aba6d7c271ad88f716ea80910.npy +03211117-c201c9ddb8493c15c3b69089417dba57.npy +03928116-ab86f892d8efc2f263920080bd2c2ed3.npy +04090263-ea4247ef739736199f433921788191f3.npy +04530566-9262aa413df7b369d735fa1ab17311ec.npy +02933112-148180c71c8ad4e3a1bfe809f99d2951.npy +02691156-297316f1c8a6f59bd007e7980e2b01ba.npy +04379243-fc8e92ecfc4a39a47149dc6ae5708157.npy +04379243-9ee885f08e0dd5273d154a49485f64f1.npy +02691156-14bf5197d60d733f2a3ecc4a9713cabb.npy +02691156-c85079e83e463fac65f50257ecdfa5c7.npy +02691156-41abfb4a9e8071754a40844f179aeca9.npy +03691459-573a662d56db6a9d1ad88f716ea80910.npy +04379243-7b8c92d0202211d53d098fcb46b95c.npy +02946921-9effd38015b7e5ecc34b900bb2492e.npy +02958343-9cd875a215c8806731b76be6623555e0.npy +04256520-8a4e1f7cc3bb76da9c9245e96a55cc5.npy +04379243-f96c029d342f72d6ae59128002f89f91.npy +03691459-afb32fcdbc6716b2fb14bc0c4e180ab9.npy +03467517-8a212984c1175c8fe2b49d4be00c74da.npy +02691156-41dca8046b0edc8f26360e1e29a956c7.npy +02691156-be11ce096084bd784f95630cc18536e0.npy +02958343-189c2b53ef76d02978a20fe14185667.npy +02933112-bbc516fd63703eee9dfa717f86ba8028.npy +04256520-a8418bfeae7c4cffaf802a9d0ab09410.npy +04530566-2ca06dc9165d4cdf5fbe3e7e4d41e98c.npy +03001627-3dac0fd995c747ab336e8bf2357c029a.npy +02933112-94b497f0a8606eb96dc1f81f95db52d6.npy +04379243-8627071fef9f1ccfc79fd92a0bf07e20.npy +03691459-35fa721c71ae04c1472cc88b92e0d72c.npy +04401088-baafe1add38af23a5f0b5b54dbc4f35c.npy +03001627-865551d21a4b2c09ad484915511ccff6.npy +02691156-1887d7e3ec69fe06a5cac89017eae8d1.npy +02933112-aba010c771d153069c7285ae7854d4b4.npy +04379243-2a34205ffef345d13002761e7a3ba3bd.npy +04256520-b6e744f896a202c119fb4103277a6b93.npy +04379243-fc731e1489031acbe02c30c9027468fb.npy +03001627-7dfdfe28e3d25a0d19fb4103277a6b93.npy +03001627-76de2f91710e9bd85f31725202dd5bbc.npy +04468005-861e13b787eacc236568be7ac7858e63.npy +03691459-c3d845c1fe644b39b6ab6d583025c7a1.npy +03001627-61b76525022f44fa9f2fd5a6f642de3d.npy +03001627-40e603e93818760fa7e431436fa7573e.npy +04379243-66bda56e82bf90a677ceee024ab73ab7.npy +03642806-d7e7e6651a23afc68ba4e518219eb66a.npy +04379243-8c68ea99b5de38d3a6d7a9f3c5f7bb41.npy +04379243-92aab082da6375cf5b9744d121bf802.npy +04379243-ab04df0d02dd6126c183308b9aafe2ca.npy +04256520-8f784e9c1bcf3f04225230e9f2d3c8a7.npy +02747177-b6833a66eedf457af155d75bbf62b80.npy +03467517-7027bc171baae1d663e148e250c0340d.npy +04379243-2eb4a0d015b80a8d9ccce4c6d5bb195f.npy +04468005-e14470a10179d300e810c01b1498aa2b.npy +02843684-11dc4e10ef6e592f1aab8791875b3551.npy +04090263-d27b357966e47647f8fb6cb99631d97.npy +03001627-d761518bcbcefa4080067e3fdc6db24c.npy +02933112-13d5f9d6a7464e39f0f01f1432a517c3.npy +02933112-de30133b2550826647d37c7945792fff.npy +04401088-c1ae3b758aa9ea5e6dba92a4e2177102.npy +03467517-5d629c65f490d33063e148e250c0340d.npy +03636649-e365a641480635d330c09d86acf3d5c1.npy +03467517-5715a289185f284dfe12fc760976ec8.npy +03001627-44875441fe578186d35ac2e5000061ec.npy +04379243-5db63af675507081118ddfdb81cc6068.npy +03624134-ce57682fdc1209731395331ebe4786cd.npy +03001627-8d983a0adc059082b300c4ca2f51c01b.npy +03211117-586b4ef8eb5a59b39bd9aec93599c5cd.npy +02924116-9ec180fe80e8d0d46bf1727fa78b974d.npy +02958343-e4bc9cf3aaff441f19d740e0f6a9a113.npy +02691156-67636e7d15d082089412a62cd6b1bf5.npy +02747177-200b3f3d859c8677ad5067eac75a07f7.npy +04401088-c06c6362fc6d1c9c5677057f93c3c270.npy +03636649-2ed7e410931f984cd59517820ada1bea.npy +03001627-f3f0238ae8d9ba8dc8687ff9b0b4e4ac.npy +03001627-c07c96f19ea1d431d4f67da0de6a1054.npy +03642806-9c6176af3ee3918d6140d56bf601ecf2.npy +04379243-fa6952fbf7f52682aece045e8bdac80f.npy +04256520-89ce842fbc7c786d2d19175e7d19b7cb.npy +04530566-254f1c0cf13108c46c63b8b48495261a.npy +03636649-a0e4661a3c458405899bad344dc01f2f.npy +03001627-de3e082195346ca419fb4103277a6b93.npy +03001627-f1c390f2a04d13f6742728b30848ed03.npy +04379243-da9ae22db57775cf67cda8f7f78d0d19.npy +02828884-cbe802da10dcae19f155d75bbf62b80.npy +04256520-9484665b03423168fd1e5a951c425f11.npy +04090263-5341d156f8af28966a52e97955091b6d.npy +02691156-675a2332a973401f6376dff6c42ab2c2.npy +04379243-3de49fd2e80f8c95c97cfc3e8a6b1d16.npy +03948459-56a293cf1103aae4c6e34b38e9a5066c.npy +04256520-6971254cdae82dccfebad4f49b26ec52.npy +04530566-fada91842e68dac015ebc00dd3588bef.npy +03691459-7e63f06b3c48fadfd6d49cce41472b6e.npy +02958343-d3d121f2e2d57b5cc5903e2355330295.npy +03001627-6f8ce08e77bc27cedb4331c656714a1b.npy +03691459-be2df150c86b57d2c9db3276cf490d3d.npy +04530566-6c1c628f4ff60addc5b0cf694baa734f.npy +02876657-abe3a232d973941d49a3c1009fa79820.npy +02958343-819b98c138192c88e5e79d9024e2fcae.npy +04379243-d26f2c85a4aafa72db6f3ca49e992ad8.npy +03991062-e53e623e49b97bbd72652f4081ec5a77.npy +02808440-cb4d05a8749093ae3321831d2245cf06.npy +02933112-68220c134171d105f0fb3e3d2a0d34c9.npy +03001627-90c8ae65e3ec4ef119fb4103277a6b93.npy +04379243-4f8ea79100a324b77445d25f394949d0.npy +04379243-f4fb644d5c81e60e1a1485fc0329e88d.npy +03211117-48f2b6c3c82635c119609759f8339ed9.npy +03467517-a19fe6a94d0c6d2c56d301ea6c7f3155.npy +03325088-2f46e4d513207150b362845c6edb57fc.npy +03691459-50b1f4e5a130dafbb5b1048c702c9b77.npy +02828884-6df5b51b250a823b147d36b9f2f13116.npy +02691156-8c0c8307c5de1b65ac96c03d6280efb7.npy +04530566-a4d9445d191c80a235a6b421c152ac60.npy +04468005-858da2187b0dec8152470de2774d6099.npy +02933112-a8725dd0e0eb8d7d492d9da2668ec34c.npy +04530566-27e9a27b6e3b49c227ac692756be9e24.npy +02946921-ebcbb82d158d68441f4c1c50f6e9b74e.npy +04379243-9c09df47d2aca46ed6f21f7a864a309e.npy +03325088-ba9606bd6aaf2f0a50da8b99982a3057.npy +02691156-1b171503b1d0a074bc0909d98a1ff2b4.npy +03211117-181bc7c78185f30516a6c448fcdff967.npy +03938244-e973f4a81707004ef2197da8dec8488d.npy +03001627-2773ae187d1e9d3d504721639e19f609.npy +03001627-342d41101756553eb3ad032acba61b79.npy +04256520-4b24bbd3cb03206b58db0ef36af1d3c5.npy +03636649-2e583ea74f46aee239b3360f500ac52a.npy +02933112-8928e0f1fdd7f107f975e70a1bde427d.npy +04379243-34ba7b78ffcf0b46d30ffa15d9c1eeb4.npy +02933112-8ddd7f1e19ff809abe81a9109a782712.npy +03691459-c91f926711d5e8261d485f425cc21556.npy +02691156-440ac1b4ac3cbe114c3a35cee92bb95b.npy +02691156-d615a8217b70af06bc0909d98a1ff2b4.npy +02691156-70295db03521e219a5be3c7b80fdc3d.npy +04256520-a73a49fd2887a030f51f77a6d7299806.npy +02691156-b72804a8bd3dbbaca8607f540cc62ba.npy +04379243-5f3fd62e285aeaae4e2090b842effe89.npy +03001627-b8af96d9c542e1bab34e8f502d7c7e1a.npy +04379243-ad139879f97c141e1ac9af6c714d1419.npy +04468005-fb26c97b4f84fe5aafe1d4530f4c6e24.npy +03691459-dd57cef71e09d11121572f6a2d968d88.npy +04379243-6fa34794adb6acde24dca86ff4e91ac2.npy +02992529-73b87e2025cfdb6daf19fa8e8218bf64.npy +04256520-3d297a9092136d914038d588fd1342f.npy +02958343-2668f2d9b8a2daad95551e0d9e50cb0d.npy +04256520-4538a9c622fc554dc048a125b47d14c9.npy +03001627-b8eaa2fca64d7e4da52ed1964df255d7.npy +02818832-cecc7a6677eab8accf9f37ec17841254.npy +04090263-ee4ccd4b40db28e2eb068a83f75a6c3d.npy +03211117-dbc61cbed5f7f2b33c1abb78f1519c49.npy +04530566-731b8fb370639bec2c8b4a1ac32beb2d.npy +03325088-3a86bbcb33d39bc72636ff7d41908032.npy +04401088-9e98174951026624164c8c77555f8e1f.npy +03001627-7facccfa81369078a8930422448288ea.npy +02691156-7526757d0fdf8acc14f1e6f4f4f49b.npy +02828884-95eed587c3728d22601104cd2d998272.npy +04379243-6ae77e7aa510e044c955e5ed03ef3a2f.npy +04090263-f30464cf9aef3abea7f9996575f1f5f7.npy +04379243-2b40fbee96b93a5eae25f6fe802a8997.npy +03991062-f4e2f7d4ba0f8af8c7c88564709ab8d9.npy +04379243-c927a92a2ce0be7030bbd4cddd04c77b.npy +03593526-a263bb1f29feb8354dc11e421397c795.npy +03261776-b14f3ad3044ae1545f16c469ffeb982e.npy +03593526-c067e10ee057104abd16d4490a10a752.npy +04090263-9b0867286d296d3934057837e526fb02.npy +04256520-37b94e004ee1f7847c63c1e5173c47a8.npy +03001627-287413404880403751e5a8425285015a.npy +03211117-898073ee0a493fed4c58a7782e1dd690.npy +03325088-3cace6ee49f5bfb0b362845c6edb57fc.npy +04256520-fc7b96235eef479075becd8a4c3f1866.npy +02933112-931fcaa08876700e788f926f4d51e733.npy +03001627-cdc2a53559d3db78febad4f49b26ec52.npy +03001627-66aea803dc4a6c5390907a4c1a185a7.npy +04530566-7be86a514fd217dbc91817453f80389d.npy +03991062-af689238ec306deecb2a965e75be701c.npy +03001627-3e34987bd5e7cf0e6c5cd45aa112726.npy +04256520-a00bdbddfe3511208dd711af5650bdcf.npy +03467517-6f480a2f23eebe9b552ddced979ec9be.npy +04090263-1fa2cbd03c1d57829f7e0a8a6309376.npy +03046257-8944ac6e4a7ee7d1e47b5004844debd8.npy +02958343-20e01ed9c14d4659e61b9ff60b1be412.npy +03207941-2666ea267824515b6a047293eefdd617.npy +02958343-df1d1694cb98584cc23e2024862e7f3.npy +04090263-8c43f0fb829887f972cad024c77ecfb1.npy +03211117-14a02f4475a5df5e337758c9d9c83ebe.npy +02933112-68bc79caeaf162a7ce5d6e9371bb5c33.npy +02828884-bd40921448838cbcb2a965e75be701c.npy +04379243-78a144a7c0f60dde744107c67e903f9a.npy +04379243-91763ac2faf129e9b35bd41c666704ac.npy +03001627-3026908df3400c1a11d9b84664f8595c.npy +04256520-ee7ffc0b1cead515b2cf0fffc23ad5.npy +03636649-4bd69765d13c26ee29a42a0444436860.npy +03001627-6e1e73e14637a28da1c367d7a459a9b7.npy +03001627-22ff2267856b5d369158e0f216b27548.npy +02880940-80608e58db79d4d83b722c86abee0751.npy +04256520-77a5f44875119a6b5369e32fb818f337.npy +03691459-a288498f21acdedb2a65278501cfbe7.npy +04090263-10cc9af8877d795c93c9577cd4b35faa.npy +04401088-4cbd57cc8e6aef9f2ed91d160fd4ae97.npy +04379243-4d5362a8446fbc8f8cbb8bac2032149c.npy +02843684-f04ba261ea073ef9390cc49064ed7b4d.npy +04379243-f6c5bf92d03a93e247839bae1bc65257.npy +02691156-8ddc3bfd5a86d4be2e7c68eb5d1b9123.npy +03001627-2ca6d10b1ba99fbd9784ddd96453bcc2.npy +04090263-61796c118778fbddd0bc9224a67ebcda.npy +04379243-11cf833ad0f8ddc1a6f925961cc8367b.npy +03636649-13daa0657f5c3e32cb0c0d433974e32b.npy +04379243-7b5b7bfa8580e913e2580b23e60e4674.npy +04379243-51fd921d3703b86381289b3cbd650b9d.npy +04379243-be025ee89a077c31a9bdc22a1e02e82.npy +03001627-d7ea1356ef7664e2ad5067eac75a07f7.npy +03207941-cb469755f7d9e486abb564bb0657e0d6.npy +02691156-be92048655bc5b001d4c061b53288f62.npy +03001627-786c20111b691c152b4875f731f71cd.npy +03691459-c94dfdebffb371022b75817a0faaa5a0.npy +04379243-b60145d7ace5fb53aa7cb30470f3273c.npy +02691156-2229bc4e646f506679f56e78e8640bfb.npy +02958343-39279457a4bc87285e717a211c863fc6.npy +03636649-c080aefc6cbff8c81185ac82ed4da80d.npy +04379243-285857e7d12f1b74a4d2a71d4ca57f99.npy +03636649-d6ae7a5542800519fcb8d8c6d4df8143.npy +04379243-6f1594512b88901798fc1d0403f6ad0.npy +03001627-9f212a5127b4544bbe3ca6e34dba44de.npy +03642806-3b9a99663babc301e2ce1e6d2467cb03.npy +04256520-de2bb45b7e200d6916d102513d0383c0.npy +03001627-6e1dd008531f95fc707cdefe012d0353.npy +02924116-b7dd213f86614a464a166e19dc7bdc6b.npy +04256520-7ae657b39aa2be68ccd1bcd57588acf8.npy +02958343-ff267b1a6d986426c6df82b90873315e.npy +02876657-898101350771ff942ae40d06128938a1.npy +04379243-7c7434a9db4a407a2b151d8b52c53b90.npy +03325088-a159b9589f58872c4170d40a78a51640.npy +03001627-3b4292989394ba62f51f77a6d7299806.npy +03642806-342150823878f1ec9aeacfc2a1a52243.npy +04256520-9df9d1c02e9013e7ef10d8e00e9d279c.npy +04379243-7f837553c70b2a63684b7bc3f8a9aa55.npy +02828884-8a03039b614b41b319fb4103277a6b93.npy +03593526-ffd399fabbe3c6268798e1381538cb0b.npy +03325088-1fa06b97a0498b3ebb201909fefe7321.npy +04004475-598ef206ffbed1476307a98defed0dd2.npy +02958343-2521a90182ccc29c253c03b7df20edd5.npy +02871439-f081b7f255aed00053d040168a517ac7.npy +02958343-f34c03711c3fc44ac10e9d4ee4bae4f4.npy +04379243-5430799502754b5691fcddfa9c1209c7.npy +04554684-33d3f4a7b2df861248bfbf0a3bc453a5.npy +02691156-542a1e7f0009339aa813ec663952445c.npy +04090263-460ad09b269895f73f82da5dbc1a5004.npy +04256520-75b57fc1eb40d27114e19520b26970dc.npy +02871439-e7e3aacb7ef4ef00f11caac3db6956bf.npy +02691156-362af793b1d0084423fc69eefd95e6d3.npy +02808440-bdfb4d590b4810f38d90c09521490a5e.npy +03691459-2dd5a69034a03d267aec59a4d1722658.npy +02691156-fca40e8cba1e5fd75bba9363f40680af.npy +04090263-1e57dbf3e917e55c25ef5089f95ac09e.npy +02773838-3077a9b76724b6d35de21284bb515a83.npy +03636649-fd8f9cb134743e0c80bcdfbddc82df7a.npy +02933112-ce85ce0eb106d409b8a453d61eaf046c.npy +03636649-990aa9dec2223f108bad9bd0c4ab8e3c.npy +04379243-9d90a58677e619f94b8710a3469971b1.npy +02958343-4f17af1ca7ae689d409b2c4484d833cc.npy +04530566-79803d0a02bbdc93ff790997f2048517.npy +02691156-ed95d9219432bbdbbf3143b1cb6076a.npy +03948459-6aae44dd39fb9476f059c10da31213ea.npy +03001627-d6579d7c278cb9a47f093285855bdfd7.npy +04379243-972ff7998554988ae6c5cd45aa112726.npy +02691156-af71e72822241808a8ab13c300600dba.npy +03636649-466af3262bb31094c35131da26f8061a.npy +04256520-a47c0cddeb15490cca68d7e2f215cb19.npy +03001627-a7b82d009e29bafe705fef512417e4c9.npy +04090263-152f03b7d3eb03c8276c3d558130f8b4.npy +02828884-4ec290c73990a82aad5067eac75a07f7.npy +02958343-6a23da6a9ab0771caa69dfdc5532bb13.npy +02933112-33445d9d7f166d6c5588a2543ef0b0b4.npy +03001627-619a795a84e2566ac22e965981351403.npy +03337140-9864a3d01b9627e94c3aee8e9d3a6ffa.npy +04004475-4641b207d1190937fbe68c7a7c2ae4b.npy +02876657-a34966853ab2272ab2047d3072d5e051.npy +03211117-52a7f3e36d09848ca63c1bd05197cc.npy +03691459-3972d44065257859c0b45c582c6ed736.npy +02691156-bbd1b96d77b8dc08b96212c8f6cd06e.npy +04379243-3f843409e853828803734eb00d01e20.npy +03046257-57df2e218911273d68661782af60b711.npy +04530566-ad8623ad47d72317eda0f8d4b3ce03d.npy +02828884-135765739f0cb969f155d75bbf62b80.npy +02773838-dc52131684ed9cbbfe4a8257a424ee86.npy +04379243-e9a1325245afff7c405d9b5bb7b18be5.npy +02876657-63f60daa8d254f445200bdb78a83bb9b.npy +02924116-b70e1062c67b159367f73e2a1cdb19c9.npy +02691156-67217ee1bb8443c8316b8b2265213f7a.npy +04379243-d2b7b34e176262513521fe8ac6222005.npy +03636649-27436a813a1abe835836c728d324152.npy +04379243-ba68b45f1cc9038abeedb4c8fd29e2d1.npy +04256520-cf651d12e2048e1a4b3c42e318f3affc.npy +03636649-a1a8616e38e5f684fcb8d8c6d4df8143.npy +03636649-e9b1b74a44465b8b192ae1372f64f330.npy +04256520-bf28dd5d38900b1314038d588fd1342f.npy +02691156-7a3392340af9ec7b62b600da24e0965.npy +02924116-4df2284d70a36be2dc033f2a4b1df7ba.npy +04379243-6fd5741bbf559e0ff51f77a6d7299806.npy +02933112-92ef2c5091a97df18a6e1efe1f5fc0a3.npy +03046257-abbde103685802186e71174964d90e49.npy +04401088-1c3795fd5c4c0a3c2efb70bd2c052734.npy +04468005-d2eb4582107f4d8b929629f626be0dd8.npy +02691156-87fb26b8e56d25f2b87697d3904b168b.npy +04256520-4cd14d58eff772da946789884353d9f6.npy +03928116-b170bbec8f10e7ba5a64dd604e7f66d9.npy +04530566-a3109a4b09953b5e2b141dc6bd7c4bce.npy +03001627-63ac45ba2c2231d155f9a00acc25f137.npy +04379243-bfcd5d38663fd5338738e7290b6f3237.npy +03761084-6888d8702b758476fc350be62d126bad.npy +04256520-81c3f54ae8f5c434970d4dd67731c543.npy +04530566-d7fe3d95cde66115874f0e42f84eb4f5.npy +03642806-b272eb1541844f55ad7b15cd0061e5ee.npy +03001627-1d99f74a7903b34bd56bda2fb2008f9d.npy +04256520-5015912352daa0113e2f5d8f8875fba6.npy +03001627-c5abc457162ec704bfffd5d6a62e360c.npy +04401088-68b80d0086322ea33615136d92a66ba2.npy +02933112-953f545f33716fd01d860ee2ad2a42e1.npy +03636649-b82e5c6e1133aafedf6cfab91d65bb91.npy +04401088-ae7b93f3ea4238712f20ec3aefa0fb91.npy +03636649-2f972bfe152e4c23f36ea1eb6542fe7e.npy +03636649-15238270f4f59a011b17743c18fb63dc.npy +03691459-a1f0c93f000051c7f1aca3fcb64b7fb2.npy +04379243-2a5618e34de3e26a20768660cf080d12.npy +04379243-5b2fcf551345b64bf3412e3273fc1682.npy +04379243-4d2f7c689e77df6b6dc1766995c17a41.npy +04090263-851afe676885dd1dd5c93d34ff51959.npy +02992529-cea8f15682797fe6eb386a4e845c05f5.npy +04401088-1727e7aeb3d159a57f521a3dcd28e9d2.npy +04379243-610709315a0f542552b3505ff8f3d685.npy +02992529-996fd7ccc0567c3c6b2ba76eab0d2b1c.npy +02828884-32fe3c383ab3687c94c13f8f78a6d62.npy +04090263-8d65e71e5f925fac58dc97820d1d9537.npy +02818832-5f9dd5306ad6b3539867b7eda2e4d345.npy +04379243-2391f652acdb73dbe958df2e8332e31c.npy +02958343-5316fab78a6732f0428df271ebc70bc0.npy +04379243-b82e068c2c18cd67b09f0ca9c143fdfd.npy +04460130-7f38c8033cc2f0854d423544e7c5cb27.npy +03691459-a543d9e58d4501422a9eb0f146e94477.npy +03001627-f2934658407472a92ce025aebfea84a4.npy +04256520-4991f4fe771cae7f18b14db3b83de9ff.npy +02924116-38213f1b26479fe87586f47a860969f6.npy +02691156-1954754c791e4571873ec74c119307b9.npy +02924116-3e9d38a3fce2070312aee40928395cf.npy +03001627-cbc9014bb6ce3d902ff834514c92e8fd.npy +02691156-4653be69e215a1a4b378822897b79a81.npy +04379243-678f7fe1c4f977927e9fb8aa5670f37.npy +03001627-7dc902a12843fa60e84c9243a4e577f.npy +02747177-6d1aacdd49c4bac781faebbdea6bd9be.npy +03211117-9cdad8b178d7743326782c9200ca97fc.npy +02691156-6c36b0f84118a75cf9c41a0805a0d953.npy +03001627-6e12481d3158dd4e8f8c11a24c52ebb.npy +04530566-bb79e21e85306ba19e51f6d13f6d609a.npy +04379243-db49ebac740bdb91d016fde69633b7dc.npy +04379243-c26dfd3453d81bf7788eb1f5e7ba6e7b.npy +02843684-65b9d72427e109fa1d531071e42cd4e.npy +04090263-82c241396ddd0232b3f2a90d50e9caaf.npy +02992529-2d26f853e710b3e894088ff49a6baac4.npy +04090263-da421715af11fdb4beac07ad11d3663a.npy +03691459-bc6dd957c20a08f67b440c5df8efc309.npy +02933112-9fbb34244e00b2a9eacb155f400b9076.npy +03001627-bf52432c9b1b5e11f98c0761af40e04.npy +02958343-ff564f7ec327ed83391a2a133df993ee.npy +03001627-7a712ca74183d8c235836c728d324152.npy +03001627-3aa228edd648d1e1f51f77a6d7299806.npy +02958343-2ec9a7479a8ece30ebe23ea7d95f2a30.npy +03691459-4e6e05676ac77f30ce029fab54b6cfbd.npy +02691156-6ea4e68428cba49f68557927e45c29cd.npy +04379243-5407f938370ffd34390dcdc075aa60c5.npy +03001627-19e2321df1141bf3b76e29c9c43bc7aa.npy +04401088-420138dffb14f929f0b45b4b4c7e33b7.npy +03001627-cf04f5b16aba20e3e3849910c5019154.npy +03991062-23dd0031ba0db00d1a08ef511bce5615.npy +03001627-31dad882e67008adab1b53c63e6e87b3.npy +03001627-77105ec0251d92a8ba13aa51cc141639.npy +03001627-75a2cfe5b82e03d2fb0eb7e753c06942.npy +03636649-eee7062babab62aa8930422448288ea.npy +04379243-3adaf5ec2c9fa6fef7248d9dbed7a7b8.npy +03211117-31f6f2b4bb6c524cab1a5567c60e2688.npy +03513137-a50fdcc3128ca95c663e90eaf6b4ca52.npy +04256520-8fd43f2955e4d397b822d48a43773c62.npy +04530566-567e385bc5c40247e414f982f9c422f7.npy +02691156-2af04ef09d49221b85e5214b0d6a7.npy +04379243-b1cb375e7f3fe171c242632b2a8c3129.npy +03001627-5ea01d852c88e30a6f2222642bd41c09.npy +03467517-cda7995e00026129e33462de7b4c569b.npy +03211117-54f5393846bbdc64e34e21eb7fabb319.npy +03691459-6abdfb1ca4d076a09c4dd878242c44b7.npy +04379243-abb8d6d056f48eccb8015e57f308c60.npy +04530566-e6fa4d02d2df5a9b1bb46d2556ba67d.npy +02808440-752f091bd4264d2fce772b67783de9cb.npy +02691156-ca6e0a1d5cfee53a8cbc4ababb61ad1.npy +04401088-9e5b9dd860689c5c217f93816a639386.npy +04379243-892e2630024144f94f29aafe46fcf418.npy +02828884-bd39e9a5489f89c8d6d3866b78fd4902.npy +04530566-6419254bff42d878e820a92cdd43b76d.npy +03325088-53270b19da085eb1b362845c6edb57fc.npy +04379243-1264d88ae599df3fbeedb4c8fd29e2d1.npy +04256520-429d58759c85f4750276e25240d21a2.npy +04330267-b37d8ea38b1438f6fddd891c70a6adba.npy +04090263-1c1008be00fa5edb30dd2b88f7efae34.npy +03636649-44eb1db902d44daa30f6e0ede20c4525.npy +03001627-6d83067056915f4dd2f15044a9418e0d.npy +03636649-5b744ac897fe8bc557f40ff86fe708ff.npy +02691156-6720352c366eba1a60370f16a3e15e76.npy +04379243-e055a8a5d8ca0b9869df3aa2bce421f5.npy +02958343-498b7c799350d1f7c4acded0fc8a9118.npy +04256520-f15d3637d11e93f5dd17d7a192a3a64c.npy +02933112-62f5c85919a21aee7868105076bde789.npy +03001627-3230b6c7f396afff19fb4103277a6b93.npy +02958343-383f8d508b6f25f565d21723f535417.npy +04256520-192b06cd91bf659ce3db80a3cacc6e3.npy +02828884-6a7ea728941d3f4f4fb4dee5181bee.npy +03211117-c57f3b53b19aec84713decb1a0563b12.npy +03001627-4e4570768f981ca7b95617254e8005c0.npy +03761084-b92829a039380e31cf7f052999a00e5c.npy +02946921-129880fda38f3f2ba1ab68e159bfb347.npy +03211117-c4c15ab5dace66f81ba1d2ff478f3057.npy +02691156-a2491ac51414429e422ceeb181af6a7f.npy +03636649-399573561336a341b754c9a53619150c.npy +02808440-35a0ea7e7f9eac13321831d2245cf06.npy +04379243-ddc16ae1263d506c955e5ed03ef3a2f.npy +04090263-a7b3c912a793ddbdd107072754c68ce7.npy +02958343-5d2e0f8fa5d5bc1496bb71fec38e082d.npy +03325088-808b5b4a67f645db362845c6edb57fc.npy +03593526-4b16d8e3aa65a107e9814058bbcd7b44.npy +04530566-9a7b0effb53375625f647c1b0a6369bc.npy +02828884-d9b39a2a427c17ed43d55fea640906fa.npy +03642806-8d70fb6adc63e21eb7e0383b9609fa5.npy +04090263-172a4e03c151d14a9f433921788191f3.npy +03636649-98d0f886ae05db5af54f0f3959ecff67.npy +03325088-c6815bc73e12dd1f8f64d37593728c5a.npy +04530566-7551b29b91fa4d47ca732a92ee1dda3b.npy +03001627-3f55eca70a6ad5dfb4f2d409b6697059.npy +04530566-ab6724e38aa593602a99899765aa8dc1.npy +03001627-60790035c8126a677645b4fdaedbc34.npy +04379243-bf9d12b9a6a79eed342501391dc44531.npy +04401088-350dad20c76cb54b7ad5140f7d56e11a.npy +03797390-d0a3fdd33c7e1eb040bc4e38b9ba163e.npy +03001627-56184b3a4ea198af7e14b034d75254c9.npy +04225987-aa2c5469590761793c497dcbf6659611.npy +03046257-464a76c004ba77e8cc14b65ef8ab235.npy +03001627-22cc9b68e67339738d2d730aebe7865d.npy +02992529-90010049891220187eda1e12bd28fb7.npy +02828884-93e43734f99c7ca6c42fa56863e48020.npy +03001627-fed8ee6ce00ab015d8f27b2e727c3511.npy +03001627-d90b1021dc6e09b455369e3e5b79b017.npy +03593526-3074ccca5d98c71c197894d64e83a327.npy +02876657-7a82a497bc4d10511d385f351a1d14c5.npy +02691156-7e8be9c88e596b84198609c994ea801.npy +04256520-6f0b36b76bb0946ce642ef37786b5c80.npy +04401088-10b3b46298af96d40e7407386eaee0f.npy +04379243-941e751844d8b0aa8b424343280aeccb.npy +04530566-97402ccd78c061251141cd3611961b0.npy +04379243-4d4eedf718daacf945714140d50db61.npy +04530566-4690184ef7ea805dfdd29529d1a15514.npy +02747177-a513393efc093c7cb00bfc975577e7b5.npy +04379243-b814241f84521f797ea323bc74055b8.npy +02933112-7aa00b5d006a7e8de6860aa648421493.npy +03046257-b5c200a23c66bfb4617724635ed7cc4b.npy +02924116-931f70003561699ea8d89e4d21910b0e.npy +02992529-68189c0fdca1a8744db121a0d72356af.npy +02992529-e06b902efc1576c62fd4061aba358325.npy +02958343-b8d3a079edbc04fe51a95aaa6caba1d3.npy +04256520-8428d483ba327a2da11f6bacf5c7662d.npy +03211117-dbcd5a88a9d4f1d7579cfe4420588034.npy +03691459-3d7e4939b677bd9f3670cf6e57497e9a.npy +03001627-7f9733a6370440dcc8687ff9b0b4e4ac.npy +04468005-3a20481892ebe6a0e810c01b1498aa2b.npy +04379243-df7761a3b4ac638c9eaceb124b71b7be.npy +02876657-b198ccb35182e73ffd2866d52d2e8042.npy +03636649-308bd35d5f52de4e57b8f616df7adf9a.npy +03046257-29d4598fa30e51958e2b55561bfbee30.npy +02924116-9baaa5688e83f884f4d6cfb91981e4c9.npy +04090263-62fc2e971d8023e61a6fae073bf19933.npy +02933112-14864858c05f52ec4da5feafe6f1c8fc.npy +02958343-40c05e511efd3fa96945ae93118ea9d6.npy +02958343-63cc90709837d314a0b2db16370345f0.npy +04401088-52a81d42c352a903a0eb5a85db887292.npy +02828884-abd7c6ee28e19480a00f752d8c024637.npy +02871439-65f8af76d8e4f477c6baf9d9782f25e1.npy +03001627-c2e50f21663db36af8f5708c6c7585cb.npy +02992529-4ce4f7fcf5f0c57a3caebb882f007959.npy +02747177-db9d164a58b37117ad5067eac75a07f7.npy +04379243-be461a1a083481c8488017d48a7f7eb4.npy +02992529-136ef91c95ca5c2d4b9a4e1a888c5f59.npy +04256520-9de6e26211d151931ae8c8ff1eb3d45.npy +03948459-c6f8a4781d8a5b228c8cac88a8c48208.npy +02992529-9090bc906ec8d80aca54a3214c333cc.npy +02691156-cbbf6ca6a621c5f9acf77e718d93f3e1.npy +04379243-3c1c6695e665ab474b8710a3469971b1.npy +04379243-6c081d6351e07db937251258858a7a58.npy +03513137-ecabb65ac86924cfea1118e44682a5ab.npy +04004475-322a2ab28ff01dc496f0bcf2d61abe7.npy +02992529-388798a892636235d2a526c0a7ff71e.npy +03928116-ac47e870aee0ecf5c4dbe872a948b23.npy +04330267-41da6df6f2a4e48b5e4e23ed78187234.npy +04379243-faa05897ccdaa0e4f51f77a6d7299806.npy +04401088-6909da0ff58823615a82137b384b94e.npy +04379243-e440f87f88335680b20aa91e9e90c311.npy +02933112-2b6bd6e0b3c2565839d3717288022c20.npy +03001627-96af52c34e42b546cd2c9316e943c316.npy +02933112-10798ccb7072393e86d53ab0fe94e911.npy +03948459-2e3a11f4328843dc61da9de756ddfd97.npy +03938244-1399af537cd5f80723a295070ca176a0.npy +04379243-b3e92f795bfea504492d9da2668ec34c.npy +02958343-25a44213579e75782e877e82c90c24d.npy +04530566-e27fc8b68996d205f650f4803ec7962d.npy +03001627-3186f9dd5179358b79368d1198f406e7.npy +03948459-732dedcf453bcf0615ea1d7806d654ad.npy +03928116-a8b047e1ccb66c889e4f174839257564.npy +02933112-2f12c90e2001a0bfd7bd133fd14c164d.npy +02992529-8b11b38e035143ddb007a3ad40c5add6.npy +02808440-f2ef257f008b08277f540470fee080f3.npy +02691156-ff725af6df1b76207b164268a44f7712.npy +04379243-14b96e25f93105674ee71d2f70ae4021.npy +04468005-30fb22cfe7db9dc7ad4ca49782f6b451.npy +02958343-88c884dd867d221984ae8a5736280c.npy +04256520-8603da907b2d1bf0a9c6c82c1fd82c5f.npy +04090263-60a861a5b416030a93153dd7e0ee121c.npy +02691156-fa7cf8d11d1340ff9a6e43b878d5b335.npy +02691156-1dbcb49dfbfd0844a480511cbe2c4655.npy +03636649-2ac7f0509507c6cfbaaf4e0b7520fb81.npy +03001627-29d5a6ae911ef708f51f77a6d7299806.npy +02691156-22d0100fa46f20eb8699933784576e73.npy +03001627-cecbaaf284d32574e669ded0ef71cc0d.npy +04090263-a467801481b450b8cc34b900bb2492e.npy +03467517-9aaad035af7e6ab1ed724609df3eb104.npy +02691156-617259db5ef0b9f8bc0909d98a1ff2b4.npy +02958343-c09c9e2d85df1abf6a3f171e9d98eb02.npy +02958343-c769d45be62178f516abce8cb03e7794.npy +03046257-e67f610cafeb2c0dbf93f50e43a43f7e.npy +04379243-ac35b0d3d4b33477e76bc197b3a3ffc0.npy +04379243-796fed2b90efc756dad3b08da15912d.npy +03467517-aface94c7aeb373865ffdcf45b6f330c.npy +02828884-be9c2b70082503eb352fc7e973ba7787.npy +04225987-a6d79366eefbfa6df9034ea5f524d56a.npy +04379243-82e47329faf11e5c7235016c2c2c8150.npy +02808440-9c72e9c273fa91701b5647ac5820a290.npy +04379243-f714747e5abc01cc14038d588fd1342f.npy +03691459-b8da73245beb77848d257d2dc106cc1e.npy +02958343-1c1bd2dcbb13aa5a6b652ed61c4ad126.npy +04379243-3565f5bce51b333e9b19181a19104021.npy +04379243-8c3c81a802ecdc45609fb05dbd8681bd.npy +03001627-1767c5e3771b0510f5225bf5a419e95.npy +02933112-1252e89db37d786386d53ab0fe94e911.npy +02992529-ef16dd3bd944608821844676433a0aca.npy +04379243-b079b8fbb6199f0eef53a66b4f397367.npy +02691156-e30e25fe047ce1ea10b08ceced9a0113.npy +03636649-c414d046062b529ffcb8d8c6d4df8143.npy +02876657-712b597f47b04755f715d98aead3ae6f.npy +04554684-4bca315fd61741797fb96900a295055a.npy +02958343-f0d16187cae178e7e9d8921ebe6d5b8e.npy +02876657-8a980192662f95b84f42eadbd9a0b820.npy +04530566-8b57b62c984575334f89761f054e2019.npy +03691459-bf27f6d33ea63c041df7ea94ca903361.npy +04256520-bc007cba6288e3503790005cfb7639de.npy +03001627-ea762c2f1c6e966be464faca7dae7fdd.npy +04401088-e1a4ea72b1f98e92d265c94f4d41d924.npy +03593526-a96b8f654eee2e8168825f3d0ad04fa.npy +03642806-5ea74fdff0f69a60546d7b6431984ed4.npy +02958343-73723a79817b594098c11e8f05368fe.npy +03691459-4e8eb4a0a6dc83e0c779d976f4b3d7df.npy +02958343-278f301a4ec1382865306f052698c1e5.npy +03948459-89bf5ef4ec5f275a70eabd84d42e060f.npy +04554684-e3c637980c8c22eaf4a3d771dd0a0ffa.npy +02691156-cfd42bf49322e79d8deb28944f3f72ef.npy +03001627-86fda548f0fde39328f80188b7c24dcb.npy +02828884-84d0db8ad40017a195c500dedd6e2c23.npy +04379243-66f1182a5e4dcdf9ccce4c6d5bb195f.npy +02924116-a32145f859e16c791bf41075ed1aebfc.npy +02691156-64e36b948869a79683653a771e25099b.npy +02691156-15442b53631b7e88232438a710acf1da.npy +04530566-28c2e4576e53da5ee25f26a257fd7871.npy +03991062-125ef534450afd4de770d8514271b45e.npy +02691156-c94efebebb2eaefcedc8262267425d73.npy +03759954-b4df512cd2ecdef445eaf8d7198d3016.npy +04379243-425e21671035806ff51fa0238791f5dc.npy +04256520-ae69ea12f45b428a327289c00b6dc9ca.npy +03001627-fe5951beafda9dc5b76982957f05710f.npy +04004475-a47045e07932413812bc5d0d72352297.npy +03691459-7fc23785c19991e4e180a1a604561d3b.npy +04090263-65b1329eee48bd00d87c63d8b3018b58.npy +03636649-20af3e3a79e7023a6c342cf382162bc7.npy +02691156-c8ea73dddcd80d901b1cc145b0144991.npy +03001627-40d202afdcc49c6d35836c728d324152.npy +02876657-2ed752a96e55398928beb1ac60ef8914.npy +02958343-c0aeb1f7a3fa4e2aea914417bf582f8a.npy +02691156-f9f4daf3015b5ece5e9e2656aff7dd5b.npy +02691156-7c7fe1664a1f36b8ad6a38fcc21e6e9e.npy +02924116-96ad7a734ab428c4193d7855ecfc1bd3.npy +02828884-651141a1e0138b82ba6cf6cbb9f4c2bb.npy +03691459-e796a74db4708efcf115c1f523ea8464.npy +04530566-448148366050fa2b17dccc00bc197b9b.npy +02933112-cac3d104981b47cd3d113b8340bd5029.npy +02933112-6f2ce914b5d4db81e28993aa4d91dd77.npy +02691156-b0f3f0f754c0129486faacd7b0ac262e.npy +02808440-d9bb699461f28db61c17aef130ed6213.npy +04090263-91156c525c67581f0cadf545f40c8f9.npy +03001627-b46361e53253c07b6fa2cfca412075ea.npy +04530566-498bc74044946e85484d83b7c37bccdd.npy +03001627-8da327a8eea887fd492d9da2668ec34c.npy +02958343-6a02e129dabcea8ba7dc87c65b6a70a.npy +02828884-bf504bde782c3f2ce8ced3508709e1db.npy +04379243-b9695f4e1589c6bde12186cc8c5022c7.npy +02933112-7e881ebf38366c6b5c91aedc71c80652.npy +03001627-abf03d43cdf0825ff51f77a6d7299806.npy +03001627-6446846bd5cc3cef5b4aea6c98f52b6e.npy +04530566-7677121309eded5fbbd09450267d17cc.npy +03211117-12c1b3fa24cce3e75745b9fe8da12812.npy +03001627-cc665438c4f7baab137d9700e13a503f.npy +03467517-73a1ac3658e2505f76d05024fabfa1e5.npy +03642806-3909e96930cb1e32a4f2e5eab55eddea.npy +02992529-30efef3eef4b37eb9ed75a6428ac0ca5.npy +04379243-812f86b9e1de03419c0ca344f487323e.npy +02958343-1f6ce6dd6720436642534f02c8e8b5ac.npy +04379243-76665ee7994012f2bc74913d2fc4a0c.npy +03001627-27efa956ccd86120464bf8a1dbad4432.npy +02808440-868d4ab648e8cf62b2f1a4f3f8449762.npy +04379243-dcdea1e749d4e20c63eb57c871ab1d8e.npy +04460130-1fc436fd53db26d667ff3be08608de4d.npy +04468005-5df84478c357fc7c5b056960183c4aff.npy +02992529-99fcfdd6edb3898a1117cb504804bf09.npy +04090263-9319229e8b90b7d794a57adad86ebb52.npy +04256520-a9da19aecc65656019fb4103277a6b93.npy +04379243-e4947c9bc17eed10e54cb890e8682c84.npy +02876657-5fb5ef6280e09d96d11ab9fa7ac20266.npy +02828884-ea6da848da3f603f81faebbdea6bd9be.npy +04401088-c3e0378cf861099ae3f7a74e12a274ef.npy +03001627-39311ad85e77d3b7492d9da2668ec34c.npy +03001627-c19ff7d2a5a3d29aab966e32f5a3808.npy +02958343-7046566750f129126aa0f1550c0a545d.npy +04256520-fd56410fc541a09a749add7c3dfb27c1.npy +02691156-d34eba7c2ce4db53adecb6fc00604132.npy +02933112-d69d9de0c79ac6a9c59350d819542ec7.npy +04379243-ebfc108a60197d8d55f46d55537192b6.npy +04379243-74b86828a5adb4c15b4baf82e4d24faf.npy +02958343-95a6e03656bdff26f69bc9777f9c3c39.npy +04379243-16dd49ad350321e678996b707ffa04f5.npy +03001627-71372c1f20b6a04c43c40c5aa3d5c5b7.npy +03691459-a11a2f20b1680f91b626640605322b5a.npy +04530566-2d847f7ada349864a4f87aa9a31cd70.npy +03001627-2e17502c7a131b4061962815e1518ae1.npy +04379243-4f0fd96b50c261ed48fda83c10428379.npy +02828884-e941e1929bdc87d5ad876645af0395fd.npy +03467517-7e4c32c76690d64a59ca4b9cdfa4cd73.npy +02691156-688f4e273beef132f0daafcf2996daaa.npy +04379243-eb98dcef687ca46970553da2430bcd98.npy +03211117-cdede148ed40e40187cd01e4a414d87f.npy +04090263-c825f86ca0c8550d45e0c3a4b827d51a.npy +04256520-d3a550ef8b98f55b21cfc6e95839d798.npy +03001627-2783a969fa42cdecbe31379a5751d820.npy +03001627-a39f54db298e53b035d20a1a3ca345.npy +03691459-1f59ba1fc5d296a817a0d4867f131bc.npy +04460130-63150ddf5088cb6a1b4b48d3a6cc767.npy +03211117-a8e109c66a0fcce7a87d866b539e4b68.npy +02992529-bcb8525b5aa7e4a5a62dc47412730fc9.npy +03211117-64abc0ca2670818e441f5bb6f88ca61.npy +02876657-3dbd66422997d234b811ffed11682339.npy +02958343-c6e3d9cf26016b5752aa494042b7c9db.npy +04379243-2c08886cba42af25f1acf3f2c6f9e1eb.npy +04530566-1b3a8fa303445f3e4ff4a2772e8deea.npy +03691459-440745e23b80c41f398d0c5832df00e.npy +04379243-352be15a6b1439c135836c728d324152.npy +02958343-6710c87e34056a29aa69dfdc5532bb13.npy +03636649-c8305b6f8521e9b3565822a81bbbb03d.npy +02958343-93486febc6ffc1aa7f04cab89c8d2959.npy +03337140-9d4189605087b029ce5d6e9371bb5c33.npy +04468005-dbae1cce1fb122d7dc14ba0818ee5cec.npy +03790512-e86e4d0b530743e129c87d1be93099f7.npy +04530566-35e014dccdd4fed12c791a7edd1fdff6.npy +03636649-e30a70e900f0a9565d28221e3b996124.npy +04379243-827bfeaf1de70f08f7d9678498f2295.npy +04256520-e2b1b05de388e7db3b52c6376e0759d3.npy +02958343-4849c61634fe3023fbeef84a1ff2df7f.npy +04530566-607b88a99de743eda0fefbd3658c7966.npy +02958343-5e236dc6f4381ed37af61b3a12bec0aa.npy +02871439-da85e3cd457b2306a64bdf68b802832.npy +04530566-99450835aba6e4c4da2951c4977eb283.npy +03691459-e750bda061e86402cf39ad4726172e1d.npy +03001627-6ed05dd2e39e06223b12a1486cdc4b7.npy +04379243-9be565678aab11cba0ab1d82ef09f78f.npy +04256520-834fe65aac9ea9bce589b08489d157d.npy +03001627-d69aad24d253474dc984897483a49e2b.npy +02958343-663bec87ecf2e0adad0e351bfd714e3b.npy +03642806-16c49793f432cd4b33e4e0fe8cce118e.npy +03790512-90c209ff795be387afe1d4530f4c6e24.npy +03691459-1c5c9d780dffb5c2599d9c8430d600ff.npy +04379243-6acf2b080e171859412dfc90452742c7.npy +02691156-99ee9ae50909ac0cd3cd0742a4ec7e9b.npy +04330267-91171b5e88099d8a642cdeb209ce68c.npy +02828884-2212ad7db1587578d2b12aa6a0f050b3.npy +02933112-8bd6e4ce15468e1ad6eefa796d2f261c.npy +02691156-876127a17b7285b3c1fbdb352261d023.npy +02828884-bcb4f576747e10bdd7f6e86d7d335698.npy +03001627-a801ccbf4985a57f17adebabcec6b7e.npy +03636649-f12822778713f5e35b36bbc16e99b441.npy +04530566-62cebab704dbc0d02b76c9fef45435c7.npy +02958343-7eeebaaf4df31022aaafd94b9f216ef6.npy +02691156-94bb7abec5f1b984dd1c97b5ee3d49a6.npy +03001627-bd3e65b625c9d994b022c94235bc8601.npy +03001627-662928421872897f489452a0032ea575.npy +04090263-3fec7abae87ae773560ce90a898cf5fa.npy +02933112-54ea003ba0d36f34da5feafe6f1c8fc.npy +03636649-97b7d9aabe38f91df11c97be803c47d.npy +03211117-a5269c81a3d7e8a01242824b4827fe77.npy +02992529-595901b2d5b23f58ed756341424d6b8e.npy +03001627-9b4e072fbf32d793e6c5cd45aa112726.npy +03001627-8707cf0c311ba8f34b3c42e318f3affc.npy +03636649-c97cc6e7fd4b4a07d650f729d0ffe69.npy +03211117-5880abd2815da0492fc6a8cbc82a5bb1.npy +03001627-4647b2b982deda84217ad902ee02afb5.npy +02808440-1c6117c2eef53221b362845c6edb57fc.npy +02828884-cae6c2b329bbc12de5d5fc930770c792.npy +03001627-a8c0ceb67971d0961b17743c18fb63dc.npy +04256520-a680830f8b76c1bbe929777b2f481029.npy +03001627-bb5791b1d4cb5fe81c1b3b2ed8d13bf8.npy +03001627-52a8dd8b79ac85299d4d5dcd2cc33826.npy +04379243-da9ff1881e8d59847d76632660780a8c.npy +04090263-f4239f72396f4170e80f8461d134c14f.npy +02843684-1b73f96cf598ef492cba66dc6aeabcd4.npy +03001627-f31f8722de9008c8c5aaa7f1cfa788b7.npy +04090263-f53d6eb7baf5a29ec24d00518a3dd6ec.npy +03636649-a1194aa9dd64c3c849d61704e3b15013.npy +03001627-c5c90d3e84be70a11b17743c18fb63dc.npy +03001627-be9d5105e48ae27e713decb1a0563b12.npy +04090263-bdfb8df0d6d316012b38b1d99376c0b.npy +02691156-d37781e47470fa3d664a56105f5816ce.npy +02828884-6e045aac2c52c7c556f6ef8b6ca8f4cc.npy +03467517-f7938e387f8ee3f8f94083089dddc4d3.npy +03001627-797df32cd5248558f779fe11f536ba12.npy +03691459-fbdfa353d97d91fc719d3f85e0c9919f.npy +03261776-5b2847f952068fd8992fd3dac901d508.npy +04468005-b5be8fd2d66546f452470de2774d6099.npy +03325088-b3553c13686cc769ebde9a63a3b4b302.npy +04379243-343bf23c280a14cc4ee8db28f96ad26b.npy +03001627-488041c2e021e8e87b11ae648ea92233.npy +04379243-5a9e3e5bcfe506cb323ead02771c3ad6.npy +04530566-2e19e953c01ddd69d5bb7fc09b61862a.npy +02958343-1710ff46ca275e171df27141dea8c9a.npy +03001627-d04a1ec4ac9de6d6eab55e294b4eea02.npy +02958343-1552f1a6521bb54a4bb135bcd06914d.npy +04256520-27be61a3c437d7a0eaf288f952624966.npy +03325088-88bed42acf279854c36fb70296e45483.npy +04379243-7f5c20bafb143b92492d9da2668ec34c.npy +02958343-3ef041182cc1d037a9d3767c58267708.npy +04090263-8cac8a38e96e3754a59c12bac2e48f46.npy +03691459-5000f99de4ae981bc52c9abdcf87548e.npy +04256520-e48455c2ad642df1febad4f49b26ec52.npy +02958343-679a25d96d21cae4a7feb903e89a6153.npy +02691156-34c656eeca31045724a182d01c698394.npy +03001627-477fdfa65563f180f51f77a6d7299806.npy +02691156-2993c233805d2718ad8912880b776dcf.npy +03593526-f8e8740b44ca276abb6f5a9e4b6b8b34.npy +04379243-45dee2774ca0527c9f8c3d2002c77ddb.npy +03001627-54f33a7cb3621d5ced98cca8f0ccd5f7.npy +02958343-c004e655af0b35e3bda72093f9b5aa73.npy +02828884-9d7a51641609efeb54db38a439aab3c3.npy +03001627-cec74855ee27972040a35da25154231f.npy +02828884-9159af619d9125ecf4fb4dee5181bee.npy +02924116-52f8b3ab45b05c27379393d232db737.npy +04379243-a24cc636d32bea058c833bc3a0fba1ca.npy +02958343-c0b2a4cec94f10436f0bd9fb2f72f93d.npy +03001627-13c18609602e4ced37b2bb75885cfc44.npy +04256520-1429db0e06466860dfd64b437f0ace42.npy +04090263-f54a04aa65598c3cbd32f07d6724eb4.npy +03691459-c56e62ebcae613624c40f34de8f3bdb8.npy +04530566-e2595bc7ef0809097c0ab7347b9e831a.npy +03624134-960333056428b9302393df8f7c1d9394.npy +03001627-fd9e909b082d8175d319c38340319ae4.npy +02691156-330f797ebbc565e71560e45167753555.npy +04530566-90a71287364b3d1bccb9d5278825aef9.npy +04090263-243a8273104d83b6e1f2a1daf140ac9f.npy +03001627-cdea84a63ad8c44febad4f49b26ec52.npy +03001627-87e11555e7233fb4a9bdc22a1e02e82.npy +03636649-6d5d4e506d6630b193528e10aeca0aae.npy +04256520-ea35493dd0e9039e8d2d730aebe7865d.npy +03261776-6bf1559769018cbb354b166143712fb3.npy +02933112-1dcd59ab33d275705ac7b7ceda74ec30.npy +02958343-ef686b06e51b00601c9427735f8d544f.npy +04379243-852826a94cce36ea9f1deb04fb8ae481.npy +04090263-e1e43d3916a7e19acb7b0ec95e9a1b02.npy +03001627-37a273cab5c24d457e871e09a3769b30.npy +03001627-3311f1cf612be98290a9ce3e4b15521e.npy +03001627-9b12d223347d4bdd4a11872aa986426d.npy +03001627-c0720c8d54745ea8c8687ff9b0b4e4ac.npy +03001627-1f857fce279b761435fbe95f496199e.npy +02691156-bddc2c1a4fae008947a1dbf5fd48a4dd.npy +02808440-f0fc7248fd16e45dfac6ca167c92d21.npy +02691156-1f5537f4747ec847622c69c3abc6f80.npy +04090263-621502aa0a01864d20ded1536778b0f.npy +04004475-b13d7229f113cc6fa3ac1bbe37d03a29.npy +03467517-c33328c564f0f6be799d06ad2011f8d4.npy +02958343-73dd68fb65a4f4d25d9d397842621b7.npy +03928116-c8cf8b011d5a3dab2203dc8a6e206818.npy +04530566-58d8ded0bcfae37985974f8a4d3be0b0.npy +04256520-360c1058f401dd27fbc060fd555478.npy +04256520-46eaf99e641a0fd264558a1c6a2a9f11.npy +04256520-54eb2ff4ee8889f65ff59927d484940e.npy +03710193-f1f92f0942b4d85b5b9eccd25a4faf01.npy +04379243-ebcd23b7d8d9247292cf95a109e87d7d.npy +02933112-28bd3151d50a4d78c59350d819542ec7.npy +02958343-f8b92a0ea7f4705c9fec71e8f4aac226.npy +04256520-e771166e02fe1016bd16d4490a10a752.npy +02958343-77065a7bc997bae82d5feb260eec50c.npy +03001627-475e2c8f7a2c1bbd9acf9a86c283d1a2.npy +04379243-10a4e263f8087c4b8cf2bc41970d572a.npy +04530566-953adc8c58842c1281d9d9b1473043a2.npy +04330267-e30e4f8c9383b4b3a805114916841d69.npy +03001627-fffda9f09223a21118ff2740a556cc3.npy +04379243-a7949f6ffcb23c178339e983761bc4a3.npy +02828884-d26818a4e62d931d2056b4bd5d870b47.npy +03001627-d619fd50c4d0fb46dea83bbf303af433.npy +02747177-4648772290e4dcf6ad5067eac75a07f7.npy +03691459-f8d4287a583bcc499393793f9cf3dbea.npy +04256520-ead4e128aa3ef03b9283104e53cccd61.npy +04090263-b7d6f5e0a80f9502d4eec64750f57123.npy +03211117-600bb2a17b238a927f7954f9ba534b6d.npy +04379243-5924fe80dc26ae812b0c00d36a59e875.npy +04256520-f6d695e08f246d4ef5b0cb6df351ab49.npy +04379243-3d54679cfdfe8d72e1aff9039d025.npy +03636649-b10efcf01493c922e7e684d25d4dcaf0.npy +02691156-f3f3805b0f1c81e6f1218670339368db.npy +03001627-d490f77bed3bded5af7c7ad2549a1b15.npy +04468005-2c66af94406704f3bcce76f79beff867.npy +04379243-8b62f4352dca92f657c81a572b80bc7.npy +03001627-77e703a4baba613937f1b3cce66816ca.npy +03938244-a97e7bc8291f73d521788cb501e76904.npy +04379243-1fa966f9c1d9b994d2ae2f26e86f819c.npy +02958343-2a1523ee15233761d9f8911ce020a037.npy +04256520-c4dbc5a64db6c2d72a9a1691b6f98331.npy +04401088-cbe652c317a4366b4298c9fe028be1cd.npy +04256520-15ca4d51db95edd783f3ef99fe735c7e.npy +03636649-d7a10c837316de2f3ca265f557f5dc3e.npy +04256520-5f5ccb837124abe11298312f680c9cb8.npy +04401088-a6fa27ebfdcfb0e165f198d5d73e9283.npy +04379243-d7c40ca08579ba4e664b3b9b23ddfcbc.npy +04256520-73f7237dd7ed9c1d593ebeeedbff73b.npy +03991062-8d7083a120eb546c1c3b3ce292007d5b.npy +04090263-12038871e583f645af56497f051566ab.npy +04379243-391fa4da294c70d0a4e97ce1d10a5ae6.npy +02691156-3c1e298b4222f4d15d3bbd70fc7759b7.npy +03001627-ecb43e4b0fc96935664b3b9b23ddfcbc.npy +02828884-e30527e054c1bf2ed201085e80edb26a.npy +04256520-c71a8fe3f0f14c074016166a4bbee8e7.npy +03001627-c86cfe147872280463626070a93463cf.npy +04090263-154d2a83fc91d473d735fa1ab17311ec.npy +02828884-7807c68ed9963df7f4fb4dee5181bee.npy +03001627-5cc61516525325f55e0d6e917505f52f.npy +03636649-d97a86cea650ae0baf5b49ad7809302.npy +02958343-4dc19314aab40eb83a93df79ef2b80ef.npy +02828884-7047ed12851201138cc469a51e5a5cff.npy +03001627-49345c62f63818a036be1486373f076.npy +03761084-7672e8f619765cc51af9a5a7008cc3ec.npy +02808440-7e5e0372dbccecb244221bef0fa3c36b.npy +03691459-c216e0b5470ec21f6ca2b6e5474aad11.npy +02924116-a4b740849e66f14241cefd10ce5d6cc0.npy +03001627-a48e359faed3da88d3519c62a8100783.npy +04468005-5e4a6599e030061d9f47439175208c26.npy +02933112-28ad7242b0bd168ec59350d819542ec7.npy +03211117-72353901edbe553ef5f9c04ae80a1c59.npy +02691156-1272dd98c66f13579a6e43b878d5b335.npy +02871439-a65e62186ca1b1eea58c3abb1c7c441b.npy +02958343-437f3ed08c32f2b9092ea6b09901598.npy +03211117-2bd7f9ea0c695a309c739d3276070b8b.npy +04468005-59b9e0fc43c367df52470de2774d6099.npy +04379243-3491a4102095b1e87ff6ace05b36a5.npy +03991062-240a7e8eb09d64e2b1a98fe8994d06b6.npy +02933112-76271327a3224e56c59350d819542ec7.npy +02691156-34ddff243ac3783521b85e5214b0d6a7.npy +04379243-9a60b3b87a457c73f522eecffc49e6a3.npy +03467517-ca9d66e82f8495a790e6e6b4a6e53622.npy +02933112-243284bf14a193771f6fe06b2fa3ab21.npy +04401088-520bdc1f312a9c92e44148b82b01a424.npy +03046257-3c78e14b999a04bbcfa93d76721b3c29.npy +03636649-d60a54564aa1856fb18d6f615cb18bdd.npy +03211117-8dda338160076595234c2f2e8f2fe6da.npy +04379243-d4a3c7e26b4a6eef30bbd4cddd04c77b.npy +02992529-2488bca663eab268d53bf953feb52e3f.npy +04379243-c25167c0af7517778cbb8bac2032149c.npy +04401088-20bcd48918a843946e74af071fa12682.npy +04530566-acc820666df876cb33af5a5d96363fe1.npy +03001627-da1ef4e9ccbfab13b3234e0da44b11e4.npy +03046257-e6d392fdd687188981d125a53e3295bb.npy +04530566-b26565bf67d9f61abdda868bb83c524f.npy +02876657-40e5d2c6e9e9cbbf5cafd3b1501bc74.npy +02808440-1b021f1332e7d185ccd0340812259a39.npy +03001627-a33c519a3d90184f504721639e19f609.npy +02924116-992436dd99cf145a19fd3efae56693ab.npy +04379243-74a626c1b31c14cbf8b8d4a282992be4.npy +02992529-57657c2b0d983a1658975870bb96a55c.npy +03001627-331e7c7897b8243694887ea54f3cfb87.npy +04256520-c2294d5c7d629f11b17743c18fb63dc.npy +02933112-54f801646e066ce92afc25cef0918375.npy +03636649-b8f5122793e92cccfde2773767fa47e8.npy +04330267-39a419de848fdf542a2fbf58d878928.npy +03691459-4a158b46d8e943f2d612e9885a7318aa.npy +03046257-31e745ce313c7a786463df620b7b4cbc.npy +03001627-18d391ede29e2edb990561fc34164364.npy +03001627-e545ff0d2058b382c3bd24f986301745.npy +04379243-b5feedcaea797add4830ebf7106a333e.npy +04379243-6d67f92d6e11f29e5792b99b8245d225.npy +03001627-81519481b3e24fd7b0957d845ac33749.npy +03001627-39ac9a459a28e252763d2f5638da324e.npy +02933112-5ff47fe4724d0c9320768660cf080d12.npy +04379243-f8e8b0059395805d9bd3e6056359bce9.npy +04256520-25220d902288e352632c9ddc45ef4651.npy +03001627-fdfedb5bb8cd35374233148ffd345970.npy +03211117-6f1c8a6b5d684a98e3d888a4f2b9ef73.npy +04530566-8411cba605709e46c26de8baaf779d69.npy +02880940-b5d81a5bbbb8efe7c785f06f424b9d06.npy +03001627-7228d43e00af4c1e2746490e2236e9a8.npy +02933112-b4cb08749e099f0a899736e5d685d0c2.npy +04379243-52329d991c54c5104febf42664c91820.npy +02691156-733db701650ed0d4651e8da9cf70afea.npy +03001627-e4114b81f793628fe8f8c11a24c52ebb.npy +02924116-f86dbb66cffcfd9b38b9be827bf6fc77.npy +02992529-7afdaca858bb0a964a28575f3344964.npy +04379243-d4bf9872856d6fc2b300c4ca2f51c01b.npy +03636649-d1ba336c09928deefc91db1746a83b15.npy +03001627-ed6bc67f247a5aa3e43df8c9a38bf11b.npy +04379243-697779230551768eedf21eadb26f2ac0.npy +02958343-60c6194b6f164cdc30276fff5ca3093a.npy +02691156-b7eefc4c25dd9e49238581dd5a8af82c.npy +04090263-9fc9bed98828febed4713685ae50fa13.npy +04530566-36c8dc4d5bbc44c87ce8c809505eca2f.npy +03691459-93aeccb6a5e0a62035cd53a06b1d2317.npy +04256520-730dfb84b370682d9cd8353ccb52cf6.npy +02992529-ed5ac4e8c681102e848d333362aaa342.npy +03001627-1769c3cf3391d5c1a1d7c136d0e341.npy +04256520-254fe5715b9de05db499b6b5bf6f9f82.npy +03325088-5cc1d274e57dcef73321831d2245cf06.npy +04379243-156d606fa86ba19c4eb174a255d0ec5e.npy +02942699-3b56239e45828d2bb4521a835b1946c8.npy +02828884-3b18e32e6e0c5942d4d8765e3910f617.npy +03948459-89e248c25d3fbbeded6071560148e6eb.npy +04530566-49fb20c0d5c84e2757920cec1ab34b29.npy +03001627-9a522f446662bd23a07a1bace8cff15c.npy +02691156-7cdbe41e6701c661bc0909d98a1ff2b4.npy +04379243-f52e33287b89f0109bbfb8262cd69a18.npy +04379243-faedeae65bb5644040ef1c8b63a628f9.npy +02992529-2df0bc8b46ad3cb858932236a22029d3.npy +02691156-4d2d87e61a18760ff64801ad2940cdd5.npy +04379243-3c1f16ccf38710e64b3c42e318f3affc.npy +03691459-8dded99a589a526d609daf4d63b3df5d.npy +04225987-d31aaca67fd8ef1827d17dabad15093.npy +02876657-e24fb21f7cb7998d94b2f4c4a75fd722.npy +02871439-fb577abb5e7b7835b5268e212359ccea.npy +04401088-e0d9622225e1361883b4bc86420ed21d.npy +03001627-9a6061dc962c0480ec2a7a1f5fe7365d.npy +03790512-4df789715eea8fa552ee90e577613070.npy +04379243-43321568c4bc0a7cbaf2e78ed413860a.npy +03636649-b074f648cc99aca6fcb8d8c6d4df8143.npy +03691459-cfdd69078d7752298b54295fac36ff1b.npy +02871439-dcd43c744d65d713c351d52e48bdbbe.npy +02828884-5775bf637d14acf1eaa4526a35f01085.npy +03001627-ff969b22a8de5eac30e06a011e63236a.npy +04256520-f39246dedaea087c397356311cbeea4.npy +04090263-17733d33502704ce9555419173518aa4.npy +04090263-8b8baee427b1adbe30ae8c7dca0728.npy +03691459-5ea3d1068a624c1da91bbba4742a1643.npy +03001627-ebaffb5ce608e7158d09bc92d0fc6d3a.npy +02958343-e54eb2674d6b3e241e351ee0a9db4268.npy +04468005-c4634b70047f855292f8ff9dd121a20.npy +03928116-b549a0c108ff0272e4b68d3b17c43658.npy +04256520-b67232c18d00fca7593ebeeedbff73b.npy +03636649-266ca6ba2582dd9dbc24b3e693083ca4.npy +02773838-d5881d42567baaf5dc19a9901b7e9a4f.npy +02946921-3fd8dae962fa3cc726df885e47f82f16.npy +04379243-4e5172cf359d577154ffd0de2b0db5e3.npy +02876657-5566c65116a9567078fe949fc1419876.npy +03001627-e175bc785390e8f6c05575120a46cd3b.npy +03636649-e083ee4f045402b2806fa01b99bcd24.npy +03691459-b10f7a407b4a3722296ecd3bbf65f1a3.npy +03001627-5ecaad1f7575b3918ce66f12ba927a2b.npy +04379243-b69b2ff85d0ec661d8f9dd7647048a0c.npy +03991062-1b121101806758e4f9aec59741c69cf7.npy +02933112-98e47ed9746cbc88ef9b1f19ef4b8cc0.npy +04379243-8aaca7e2c1b0ec549eea323f522c6486.npy +04256520-ef479941cb60405f8cbd400aa99bee96.npy +03928116-e966f5e34789b32210240762b65ed973.npy +04379243-ca6071926d0d910372ee08e78374a212.npy +02933112-4a007c5263b36c35f51f77a6d7299806.npy +03001627-42f77dcefe75f7eb19fb4103277a6b93.npy +02958343-b4f385b36ef0918d9393793f9cf3dbea.npy +03991062-4fcc70a519fac2a3f11c3739edd52fa3.npy +02924116-f1620392bd8d9249193d7855ecfc1bd3.npy +02691156-65bdf7b997087055ba30a078a973ced0.npy +02808440-9b2952001ce703ab6b448b8aaebb705c.npy +03001627-267dcb267138fc92c242632b2a8c3129.npy +03636649-c0f67a9a45cac532fcb8d8c6d4df8143.npy +03001627-a73a49fd2887a030f51f77a6d7299806.npy +02876657-908e85e13c6fbde0a1ca08763d503f0e.npy +02876657-22249179e88b0502846564a8a219239b.npy +02958343-9e3a69fc219ef73d37c910d2f91b3d73.npy +04379243-1ceaa8bd231d922cc3bd24f986301745.npy +03624134-a0e6f9f1061e2f2c1e5999ea0243607d.npy +03636649-bc40c19e71fd258046f1a7cdff74f3f7.npy +03325088-f1d5eb645eada0c03321831d2245cf06.npy +03001627-2025aa3a71f3c468d16ba2cb1292d98a.npy +04379243-a5e951c9d7a9a93f8cbb8bac2032149c.npy +03001627-cc8fe2000b1471b2a85f7c85e000fc79.npy +03593526-afeb60dda62138a04013b7b0fb1ceaff.npy +03325088-d79fbf2a080e30a2b362845c6edb57fc.npy +03513137-2750a9be8f6cbce54e5e6ac3ef6bff73.npy +02992529-ae86fa976ddb0f923bb35aa9d5fb636b.npy +04379243-ecf3cc67ede747adba5342d638d0c267.npy +04090263-e93954daf5406e15e564d15be4778337.npy +02933112-1ad4c572e0fd6a576e1e9a13188ab4bb.npy +03001627-5cc0b0e0035170434733824eae5cd9ae.npy +02691156-2be6cc069c95951a4304ffdb51711149.npy +03001627-8ad57afa55cebfe0dad433a29cb627ea.npy +04256520-f5d7f60d4b33ea4f63d977b06bbd429d.npy +04530566-baeb1f25ccc59698cca5d826f4b024b3.npy +04379243-f71296c0a7e93ec282db9fca4b68095.npy +04401088-295d6f0caa702a1a2f58405e4baaa2ed.npy +02958343-414ae320397821af8bf92e87e504146a.npy +02691156-86099a00dd63ac05aac413eef609e99b.npy +03001627-674f8f89f68491ff38a7c518e9c1b4ce.npy +03636649-6750d3745d49f7ad3c1ac1040256359a.npy +04090263-178539e39c6a83efb1c46f058c033ec1.npy +03691459-b1112f7597347113892a11caedd0d90c.npy +02958343-c3cfbe068adab0579583ff717105f70d.npy +03636649-3abe4c174e5e5ffe490ad276cd2af3a4.npy +02992529-983b362e25c008b1b36be681f90b79af.npy +03001627-10dc303144fe5d668d1b9a1d97e2846.npy +04460130-8b5f398ede93e1fd8da631348bdc760a.npy +04256520-383e435cdbe406e76ab870ad2db8ed02.npy +03001627-c30813d1130b492e81b31fbac7146568.npy +04379243-81922145630fced4b49e18913f04bee3.npy +03642806-bad11c851d356f6363920080bd2c2ed3.npy +04090263-e6b01d0349c34a4b9d40dc50674e6347.npy +04379243-fa871f2f88b933cd7a63d8989415726b.npy +03001627-a69a2807ca667fd9492d9da2668ec34c.npy +02808440-a26f1817df243dbf601f1922eb3d98df.npy +04379243-bfe05e0cf137791d1029f6318b92e21b.npy +02691156-dacb447d7820e7f7ca8607f540cc62ba.npy +02691156-48bcce07b0baf689d9e6f00e848ea18.npy +04090263-1fa5a9170bb276e7fcace4d823343363.npy +03001627-e02949c5e582d20682574dfd1b102fb6.npy +03207941-91cec7275a9b3266a6eaed098287ffd3.npy +03642806-97e94d800fd6dc07dbaa6d42a4980930.npy +03001627-7520005e70a54526c266013a269e5f81.npy +02691156-af04f04964fc2f1b64a62403221fd59f.npy +03636649-d284b73d5983b60f51f77a6d7299806.npy +04460130-dcc345e983796eeecb9157ba706d9589.npy +04379243-5be5ddf3780d2cbf71a782a4379556c7.npy +03001627-5b69cc96d156f286e7c7920f6a65a54d.npy +04090263-2a58d9c3a766742cc6f30d9ee0d5574e.npy +03001627-bafb9c9602d00b3e50b42dfb503f5a87.npy +04460130-5da1ddcc8d5f62577f5d4139a48ddb6f.npy +03001627-64d535abf6fe5ec46874ce99dea28d5.npy +04090263-7b0137debf39237d618f190677511085.npy +03001627-eee7f5138b978078fdef1c01cbd4ae0c.npy +04090263-22c33fb33a18b5bfbe250bd311b0c6b8.npy +03001627-63a1c3810119e2b660389b3f7b5c9026.npy +03001627-54c9f96ffc35d0c2eec2ef73f04d4ff7.npy +03636649-1c7f8ad295bcc3795a233e989a47d3aa.npy +02828884-84efcf2796fad0d2917fe9209d09e56e.npy +02958343-d01a821c8b2c43cea0061ac8d975ad8.npy +02747177-480e98c025179a68b47ef2a0cb1f9cbf.npy +04379243-4894b2193e36814dd42b9650f19dd425.npy +03691459-df8afdea84c72cd5c3dcb7e0e318dce1.npy +04256520-1059a78893d810bb14038d588fd1342f.npy +02691156-f6ec20afe98e37ef6e2a24768a2fccc.npy +04256520-277e5fc4d325fb1381f667e2a25e0619.npy +04379243-8cecee14e55bf1f4c255a5f53b753fe4.npy +03001627-86eeafeae817263414038d588fd1342f.npy +04379243-f0275c22904d275222dab9b5e1c1282d.npy +03001627-d239d38424429a9a4626612b5d655dc.npy +03636649-5e6abfc7d93fa5f1dc0efee4b442070.npy +03046257-171a6752b9a2dd95651adbce8f1811d5.npy +02828884-5d9880d63d54b9c442bdc91bf8c0f902.npy +03001627-2c76aaa00e55c26836c07750784b6bc6.npy +04554684-8a0a7c14b9cd6489d202e705a59e5585.npy +03207941-5d17e90f512a3dc7df3a1b0d597ce76e.npy +04256520-4e1a956e406bb70714038d588fd1342f.npy +03001627-89dd53d0377c28207f7114254c4286d2.npy +04530566-66a90b7b92ff2549f2635cfccf45023.npy +02933112-ca6d108120fa949163d977b06bbd429d.npy +04256520-2aa0288017b4e249f6a7b03b801e1d47.npy +04379243-89b23586ad3af3d6252e0775cff1c394.npy +02828884-146934a1cb852afc1a1a2dbbd3d54d53.npy +02871439-6be63942b2fe82eefcd4910413c446d9.npy +02958343-2cccdc287a5329c2ca92a4cdad802b45.npy +02691156-31af9b965002990e27e7e81f554f78b.npy +04401088-fb1e1826c233104a4e09ebaf49b0cb2f.npy +04256520-26205c6a0a25d5f884099151cc96de84.npy +04379243-a41865cc8dfffcc137ad4a99518dba6d.npy +03211117-5b2585db758fac87bed75a82d9bfc7c.npy +03001627-4b3c381658cfe96d4db79ead79f57b22.npy +02933112-958fa3ccebcaa8246c4866b1c92b8a35.npy +02958343-d2064d59beb9f24e8810bd18ea9969c.npy +04379243-5a550763e7705e532ea98d69e91ba870.npy +02808440-68970c4f57bb44167d54ec3c8e01d52e.npy +02958343-312cfe616ce515be5826faa473422ba6.npy +03761084-7d83379d6c2239393bf7bae2651d2cf.npy +03636649-c464b5be51b387fead5067eac75a07f7.npy +04090263-96fef95e1fbb3763276c3d558130f8b4.npy +03797390-9737c77d3263062b8ca7a0a01bcd55b6.npy +03001627-8a2349fc21f48ca78ce66f12ba927a2b.npy +04379243-fed1a75cf5c1ce38dee1e85d063fe6b.npy +03211117-8a89e2085e5f8404da89bed86b8f9261.npy +03337140-3421141b1e11a501824080f516909671.npy +04256520-47fbf101a830769fd1dcc55e36186e4e.npy +02880940-ce905d4381d4daf65287b12a83c64b85.npy +02876657-216adefa94f25d7968a3710932407607.npy +03467517-a74168d620cc4fb1b5fc96dea70b7e52.npy +04090263-4a90c8a6980c9b53aa6420fd028bc571.npy +04379243-56b7150b4fccf41355f46d55537192b6.npy +03001627-28b605f55e21acffaf88fb4321b22872.npy +04379243-456601c88eae2449f51fa0238791f5dc.npy +04256520-785b692194203f119fb4103277a6b93.npy +04256520-ff213b889d304febb6f5fb02f36f9480.npy +03001627-b04f736cd05361d1cf63f06c65fa88b2.npy +03001627-a749c31cee6965f33dc9e0e58bb697d3.npy +03636649-7e4905eb4670c6df2f939979b0dbf5d5.npy +03001627-a10ee4a0964f4ef9e3b9dbfb07aa21fc.npy +02691156-db5146b7695fafba78d7c0e1adfe122c.npy +04554684-d1aa6a6c230b5150f0ddc6174ecef5c.npy +02691156-58e7f5046a0eb6474298cee0ed15ce9.npy +03624134-464dfc36b0b340724b7644126b1d71e0.npy +04379243-8f3642beb6eb088d37251258858a7a58.npy +03001627-4a9ed043cb91fd91b04cb542e2c50eb4.npy +02958343-a5dcd1196a1ffa9739f20966eb25504f.npy +02801938-557c0c8dcc9d84b2250c527721570ba0.npy +03467517-21a517abc4729e6e352e5d4d2615db5b.npy +03636649-e1fedf82bf8fce9eb8b431083b6191e2.npy +03001627-4af5131ebc2ffc25ec7cbf3284585a40.npy +04379243-ae9e04d050f5cba1492d9da2668ec34c.npy +02924116-8cd0cc99910e471d3fc5ff9790be0ab1.npy +02933112-955a80162f342ab45d64ebd26708751e.npy +03636649-60d7d0e9c45368c282db9fca4b68095.npy +04256520-7afd499e9b3a2e0c1a90a4432f1af114.npy +02958343-bbaef5a610b0b4d5368f3995546e59c8.npy +02818832-22b8e1805041fe56010a6840f668b41.npy +03467517-c55430c190de1580922b76fa1a7a2ce0.npy +04530566-370ab590d5f9f6e12998de2923cbf8ed.npy +03001627-5ad3a3c3b67433174733824eae5cd9ae.npy +03001627-67fd2b1f102f4f76ec89626a4213fd07.npy +03001627-8df0910897498e764d183b64817fa09d.npy +02691156-5a0fe6557b4e2b9ea8e091cb544689d5.npy +02958343-fd7741b7927726bda37f3fc191551700.npy +04256520-a6d807661eec51a8c0b437e347e8066.npy +04379243-1241ec2dc5e59b0ec3bd24f986301745.npy +03467517-5c4ac761701cbcb21021cd55d164c0ed.npy +02876657-fdc47f5f8dff184830eaaf40a8a562c1.npy +03001627-5b0dd54eced22552b283c8c7333d797.npy +04379243-93aafe1aee82e2fadafcfea63f0b694f.npy +04401088-dafeda191170938ad33f96248c28a3a9.npy +02942699-fc83047701a0e21b901ee6249a8d9beb.npy +04379243-6a3c9ea7e4cc8fabb20aa91e9e90c311.npy +02828884-687efa006864f71d46c340938e2ff1c.npy +03636649-25427fc8b45e4c6370ad12dcb213189e.npy +03001627-6dd5e21ca65a9ff73c837ed50dd492e.npy +02828884-a31ab48a2b96574b9c3a7877712317b8.npy +04379243-1ca75076bcebfac76c3484ac7eef025f.npy +02871439-d8d3d2c777b12d4996b705a68a9174b8.npy +02691156-f1ef7546cc85a1815823df672991ed66.npy +03636649-61b57e8b5da8fb13d527a9a6f5a872b9.npy +03211117-3592a95cd54f38599bb952e15a37e248.npy +04330267-33cc4ac44ff34a789f71457a3f84fcdb.npy +02876657-7778c06ab2af1121b4bfcf9b3e6ed915.npy +03593526-a32fd1283c58bebda7f0dc86456c3021.npy +02828884-5e0c9babeb535aa4718e797a380b813f.npy +03467517-8e15e57014a36199e52028751701a83.npy +04090263-a4d66892876b5e0cb5acf79024643c18.npy +04468005-2158a6182c1be38a4b0b2e6e63122009.npy +04379243-fcc387cf43f5c63855931d119219022.npy +03948459-2a0ac4cb28aeea64eb127ea937b74f9c.npy +02958343-5785192c95cdd67b704715417c0f83c1.npy +03636649-cbe6d8fab4be74a11735ea0e092a805a.npy +02691156-b3dd0a06e7f727449a55c6af6f4b2bb3.npy +02958343-51c957fc4a2690ea7af49dac67ce8f.npy +02691156-eeeb30213be73bd14c3a35cee92bb95b.npy +04090263-59997a310b8fb3c9c1cc3f503d10007e.npy +04460130-4d1af8461018b714579e0a60e99d2683.npy +03207941-44d766f0954159773321831d2245cf06.npy +02691156-bdb7294dc4742b33bc0909d98a1ff2b4.npy +03001627-5c0d4cf28a71ad7296db593b49da23e5.npy +03001627-b4e30a512991aeba67903707764646db.npy +04530566-9f468767b1fd9285eb2c303a0e0d287b.npy +03325088-135cc2e885a4a46bc36fb70296e45483.npy +04256520-741dd57baaea906cb0449d422c1e5657.npy +03046257-93558e7f6f5ee9dea6a9ef34cf76a74f.npy +03797390-6c5ec193434326fd6fa82390eb12174f.npy +02958343-95ddaba8142bb8572b12ea83455b0f44.npy +03790512-8ed4bdaf0c8b88ea8b31e74d456742c7.npy +03991062-dee4dc24ecc3067f44c183864792bc2b.npy +02958343-1164dc97642a22ff5acf55f30acc008d.npy +02691156-12e127c0416f94ca4c3a35cee92bb95b.npy +04379243-b0e3b90a33ced56e2029d06c0cadaf74.npy +04256520-62a0f0734b9111084e78d6c405d01fac.npy +04530566-fda1e57da58ec9bee88464b900e0eced.npy +04379243-2add476bbc4144e57c9cc507bfc0f85b.npy +03797390-3d3e993f7baa4d7ef1ff24a8b1564a36.npy +02691156-6dd16a06f0e9a286bfc945be58e73eac.npy +03636649-fb8be091d77118ab90fd203f931c9af5.npy +04379243-23ece3bf871619366ff454af1e8947f3.npy +03001627-5346017af72c1843169d299c5f567c18.npy +02691156-3427fa8e6ea160f1fd138baf628cf158.npy +03001627-9ff6c78f309d55471449a39c0fb09f2f.npy +03636649-a90233920f619e03fcb8d8c6d4df8143.npy +04530566-24beb61e46bf6b1970d557f49392fb1.npy +03624134-8d8f91609580d8527bbfbed6e6c4dd29.npy +04530566-6d0c48b62f610ec0b90142192ec795d.npy +02691156-a1708ad923f3b51abbf3143b1cb6076a.npy +03624134-819e16fd120732f4609e2d916fa0da27.npy +04256520-bbd385cb3ee28279e3cb1f46427ab37a.npy +02828884-419f4ab8254c97a2056b4bd5d870b47.npy +03046257-7b4bb93293c880d3e61f61099b064399.npy +03642806-2c697db8a982242d54a8d8e3b6972768.npy +03691459-6c403ea54430684990146e2a0489a257.npy +03211117-3934f942bb0b462a90b6c749bc63f3e6.npy +03001627-bea846f692c8bdc8ce6fb1d4c6089968.npy +03790512-9cb038f61be71ed0cca5d7fbf4f17f56.npy +02828884-5b5be5419120ddbcb2a965e75be701c.npy +03624134-e8a6915bd0bcf1bebaa284808a1567a8.npy +04379243-797ecd23342e744bbff15b656f256f05.npy +03001627-6c0fb1806d66a9cc3002761e7a3ba3bd.npy +04256520-f8e0bc0d84a8f76cece93aa52d895bf1.npy +03211117-3017481ad6a978393eb1d3da560687e9.npy +02828884-4cb196a794bb7876f4d63bd79294e117.npy +04379243-c490945c032f5ca0fc0035da39bd5e1.npy +02958343-c3a1e04f49e80d22a10cf495b6dc4ef.npy +03001627-fa277e2693cba669731d11154716a6b8.npy +04401088-a523f6e5662f8f178ddf0e44d13d17e3.npy +02691156-e3473fc8fffca7d4d972c9dd75ed77d4.npy +04379243-c8f29afd512b8595b000f20a5153622c.npy +04379243-f8f36e7871d0e8382c026fed19c0d206.npy +02828884-b6b10e519fed3c9ea9d99888ae8a3eb5.npy +03797390-1d18255a04d22794e521eeb8bb14c5b3.npy +02933112-7f726fa36a428c0e11fc2b865c2a185b.npy +04090263-93743b9b3e33a272531756272f07b3a3.npy +02691156-983cb909846f4e1bbd46d022fd7d80aa.npy +02808440-e5c97c7b5cca57cb30f98136f75a1800.npy +04090263-b87fa4a82de9567af877f04737ced5b5.npy +03636649-1917888a2b6901091735ea0e092a805a.npy +04379243-54b3cb531febad83bc9f3fbfc126b5e4.npy +03001627-5a10fc10de7bd8cb8bd24d13dcc47e64.npy +04468005-51a8f19d22c1bcfcdc14ba0818ee5cec.npy +03467517-d9cd03133da5c44940c9c81d87cadc01.npy +03001627-d712f92ffb883fe6fbe6ed8d24e16d28.npy +02958343-77a170eab59d866d8a1aed4fb5fe5280.npy +02808440-fe59e0e02ca91956b362845c6edb57fc.npy +03001627-38a2b3491e8e8a0d490ad276cd2af3a4.npy +04090263-f6f254a6b02ad5268fc148cf8ab667ca.npy +04256520-9fd96a966aec6594f51f77a6d7299806.npy +03636649-6b42816b1e70429f61bcdcc7d95ea51c.npy +04379243-cca5144ed02e693f83ab30e82b39a93d.npy +02933112-19c79a42f68d7d444da5feafe6f1c8fc.npy +03636649-40c3135c95004291240cfa0649692c0f.npy +04530566-9feb86becf3f22f93df8f4ac45647158.npy +03467517-6ce23c82af30b629e8f705eb96ba3376.npy +03001627-7a962a612d7cd0feb7611322d07bb05e.npy +03001627-7eb566a254731d8871a782a4379556c7.npy +04090263-45c5c36e3736d3d64e868b194cfd912.npy +04468005-87952a04a88c9316a79fe2742d7899dc.npy +02933112-acee69c7c5517899af4d0096b3f9aa03.npy +03046257-f41e23b98991d0f535836c728d324152.npy +04401088-748f4a9aee8f610e8463cde8953cc1a5.npy +02958343-575ac5c53ab9fe21a26fdd1a1e470de9.npy +03337140-eb31fcf943d70e44f9d623e237698c54.npy +04256520-a0608ab77f25ae922b8f1e4489d2e1b1.npy +02933112-1971024c0cac65a824662341ce2b233.npy +04554684-9cd0227494eeaafabd2a8bf2cac51544.npy +02691156-d1e3bba19cb9447dcf6c095014f481a4.npy +02828884-7a0d913c66278596ad5067eac75a07f7.npy +02691156-1f7dbc112b7375dae0cfe7507a46f0c.npy +02946921-91483776d1930de7515bc9246d80fdcc.npy +03001627-6f37fb57f3da696265ba78ad9601cf1b.npy +02691156-88fe762bfda775f84c3a35cee92bb95b.npy +03790512-f959ea5503659fd33bd003e0bb7a3ed9.npy +03790512-d2f6dec6d70b111fda8b038dea29f4da.npy +04530566-79c98bef5c1870b64c55cd455710ca53.npy +04379243-4cd7d883aec1db86890992ddacc04113.npy +03636649-baf7b66d35abf0ab1735ea0e092a805a.npy +02691156-48d03ffabd0399f4303510f9a56d94fe.npy +04256520-e4066cefe0230cc7b2ccd937df5da28f.npy +03624134-e47774ba19c5aa99988abef1fd117e7.npy +03759954-c9fe3b38eb59689175a3010d3ada28ba.npy +03211117-3b01bed34001c78211eba86b475bafe7.npy +04379243-22ee7f1fdddddaccd78a975872fcaff.npy +02958343-1cf14b4004e1d2e22c6ce678c9114ba5.npy +03624134-d4be83e3062bfe9086bbb74f0f607cdd.npy +02958343-a0fe4aac120d5f8a5145cad7315443b3.npy +04379243-d4054b29b329a700490ad276cd2af3a4.npy +04256520-67d7f94aa2ab272bab610b0c94236463.npy +03001627-8d458ab12073c371caa2c06fded3ca21.npy +03001627-cca975f4a6a4d9e9614871b18a2b1957.npy +04379243-c7623649c8f34cab23afb61f25e1136e.npy +04379243-6f4c33b5becd1f3920768660cf080d12.npy +03001627-a592c3bf73afeb9294741031f62be2f6.npy +02958343-b2b2f4952e4068d955fe55d6e406ecd4.npy +02933112-2bb2456b272a23dc59350d819542ec7.npy +04379243-12ecd8ff5fee05c68cbb8bac2032149c.npy +03001627-2f2da13322d30ccaf4b6538438a0b930.npy +04090263-2a18722913244bc3c24d00518a3dd6ec.npy +04256520-17278f64413654cffebad4f49b26ec52.npy +04090263-ca012a47cf5efca23f9d84f9a87a44e4.npy +03624134-5663637633c938d1395331ebe4786cd.npy +04256520-42e06113efdedd0fbc19762eaa7ba40f.npy +03001627-b97dc64d0406c07259d43b06ede1b24.npy +02871439-de4168fe61b0968a7351a916a214ce9f.npy +04256520-755f23d93b06bc168cbb8bac2032149c.npy +02958343-ced46f74119cdb36a7fc8832cd5fa42b.npy +02808440-a23e7892bd3dc65b6f893b5bc716a3fa.npy +03642806-4ad5cbcfd2e2256414f029a400534157.npy +02691156-8d2903595298549959bf29282ea7962d.npy +04090263-f0b6875689fb72f6feafd6f06fc45258.npy +03325088-3c8af998b8d3336c7793996e6e93af11.npy +03691459-19b900dfc658cdcbd4b4ae2ff4c58b57.npy +04401088-2b48b14e226b131af3b2c084b195b056.npy +02691156-237b5aa80b3d3461d1d47c38683a697d.npy +02691156-3a3d4a90a2db90b4203936772104a82d.npy +03636649-47ff70265cba94df900cbe2c18fd90e9.npy +03001627-41660fd9cba4d5b72f4413c96d686e51.npy +04090263-9dd3d881c473a5323666119626b2af32.npy +04554684-1a23fdbb1b6d4c53902c0a1a69e25bd9.npy +03001627-d5bd6ea417eba6ce456cbf78e1e89022.npy +02933112-1c4e2879669e949e3fe047712e43e185.npy +02691156-7e10d8f0457cb48219ba010ddb4974fe.npy +03636649-cef6757831b4d9738c8f019f17f4687c.npy +03790512-db5b6c2f64fefe5b448c90b3a2fec4b8.npy +03001627-8c281caf626df58671a782a4379556c7.npy +04401088-6d053ef40bedd8fcbfa0195eb6461a44.npy +03001627-64ead031d2b04ef0504721639e19f609.npy +02871439-9a078a05f9ffff1b28f28448e3bb829e.npy +04379243-e13f70868bd5e3a08d9d8badd9c0cbf8.npy +02933112-39f7a4eb09dd695d46dbdd6b5b884b3a.npy +03691459-c27f121649123d0a51d91df189dc282b.npy +03211117-2ea0fcf4f443b36c5516f88085cb9af9.npy +04256520-124bead2c137a6d1f652f706160dc96d.npy +03624134-2cc5c29fe6e2d1e92e933547dc663323.npy +02808440-95ef936127865ae2a9a1691b6f98331.npy +03991062-e2276eb0322d1885cb2a965e75be701c.npy +02924116-6083ff0f7219d82d6d45d698c7dd7b29.npy +02747177-44a64fa7c3378f16de27b9aa1df630c0.npy +04379243-9c8c8bfbf77716f36b4fe272da0db543.npy +04530566-ab01205090242c7277945fcb3f0ff3f2.npy +02828884-c02649dad5a5946dfcb04979ea30d7e8.npy +03001627-5516e76a34984182b6f6d1d58b7b1311.npy +03991062-9d0b790fa24015c0f9aec59741c69cf7.npy +04401088-a7056690a5bf34d24ffbcf8cf904ca12.npy +02992529-6d053ef40bedd8fcbfa0195eb6461a44.npy +04379243-6af7f1e6035abb9570c2e04669f9304e.npy +03790512-aa619a9f4b2e200495ff232cd38210b4.npy +02933112-c55498c03c913177d200faae04ce3f8.npy +03001627-50415355dff6f4e0c2c1a442b53fa053.npy +03691459-e66486c1f5644e298a0181490cb73cbc.npy +02958343-c3858a8b73dcb137e3bdba9430565083.npy +04090263-b451d4091032fe57aca1893e093d31f3.npy +03001627-d9558dccfe8e3381e45ef4135c266a12.npy +04256520-ecad0dfdf6338cbd457ba044c28858b1.npy +02958343-bc9c588a00ae179fa2645d665a7d8fa.npy +02871439-3d422581d2f439c74cc1952ae0d6e81a.npy +03001627-bd9137fb2f1151b23def89b32cef8e45.npy +02747177-9c0847d6c42eca062846fa729d90e125.npy +03691459-b819ee65569e9da21acadc443e8b347d.npy +03001627-57b043906feef78fbeae145d587f201e.npy +03001627-2d75f86921cb919b88dcbe86402c7c15.npy +04379243-ba52d8aed2dd75bba75f2876a99ed045.npy +03001627-95d8553504c65fb4b770bfdf3ce10896.npy +03001627-d4b4d348cfdc2aa5f99372bbf9c0b8a8.npy +03001627-b24b70c9aaec3932cf577b918c6f725b.npy +02828884-7bcb67e77adbb19bed98cca8f0ccd5f7.npy +04379243-43ba3898894751d4a2be11b607ccaafd.npy +02958343-6d296f7fae3f7f34981c1fca8c617850.npy +03467517-16e71fc6e50d0e6226587cb13c78fb9b.npy +03691459-119d64f6de33ed4093eb0b4dff044a09.npy +04379243-96e9571393290511be52c3c71dbf7749.npy +02992529-ad66da8440023d8a1e929774f9727b5e.npy +03790512-c4e0be3db8960e7799c206f2618a97af.npy +03001627-4019d848076af6157fee47aa19e2e28c.npy +03691459-9dcf9b3c53f1cb135afcf0aaed5d73d0.npy +02924116-a47488463d1fea38550f48125b5f584e.npy +04256520-3b8f2b955ee9a904b3c42e318f3affc.npy +02871439-3cdcdefc72c3760596dd43aa0ec847c9.npy +04256520-65711cb0e57123e037b2bb75885cfc44.npy +02691156-1397f5bfd89673b21fc43d5b32fa230f.npy +04379243-c4d4d0cde7e39bbeaeeec543ce96f24e.npy +02747177-e5050955cb29144b907bde230eb962dd.npy +04379243-4788fa0af36e94ea38c2e72e63f5bbba.npy +04090263-1f4f948abd74399572e9add3b9371377.npy +04330267-69d2d6bab648bcb487dd60af81c93a3c.npy +02924116-aec4d33a26e8b959193d7855ecfc1bd3.npy +03211117-68e75f7265569b8ca2d7e4322f7f9e03.npy +03636649-54654f299bbf5ce4e7a1d4df7812ed0.npy +04401088-fcdbba7127ad58a84155fcb773414092.npy +03991062-eadfc9d3098273dd6ba14bfd91a75020.npy +03001627-fa4155f8091689a273801486f0f205ad.npy +04379243-cf37563a68edc94bd71ce74ab5e9c1b5.npy +03211117-d9960f7455676e94a0a7b8ecc42036d5.npy +03337140-aeb08906aded103ad61a2ba1b75d9b90.npy +04379243-ba311a09f08ea7899c39abaf208a73e5.npy +04090263-95cb92425673feac6b2c8bb96250e4a0.npy +04379243-e811612c42cf5c5ae0cc7e7449604bbc.npy +04256520-13568cb7d4bb7d90c274f5fac65789d8.npy +03636649-bece8f6d89e653e6fcb8d8c6d4df8143.npy +04468005-b8161eb1622da15d9762e982d16958a5.npy +04530566-a70c472cef0c354dba2abf2ecc57eeda.npy +04379243-84d5c290aa1c5c3e28d0a21d73b2739d.npy +02992529-280a42d54e91c6968a02f6ad0818c761.npy +04379243-90889a0cf4285ff4f46e6e4e575a5bf.npy +04379243-b7bab2a7986f34005268928fe2c1fae8.npy +02992529-d9d06d2772ecc526c0dc3ed657ab97f0.npy +04379243-14d6b4b09dfc54e9d679a95896f75103.npy +02958343-61bcc13c67a92542b6aab5f7ece0e6cd.npy +04379243-8d0390d8d66bf1cc30b07c64830a47f3.npy +03001627-64e440b5350da101512d71be7dbf2d60.npy +04379243-97bfeed6025f68de5fe8cd129a2c0fe0.npy +04256520-7511cf30cf10869b4f7ad0010e5a372b.npy +02958343-33ca3037b6dc96c1df7375fd56cdeb81.npy +04379243-de5de9cd2d952cc5278f90ef85162deb.npy +02871439-e5d5ee2194c108bbd295ae4632dfd941.npy +04090263-e8ceb645b5a82aad8e27654291ea5e0a.npy +03593526-de673ddf9df03b8278cf1a714198918.npy +04379243-3f682ce98ca01c85b3cf15c77de45986.npy +04256520-bc1b55a6807caa9b490ad276cd2af3a4.npy +02691156-2c9d5fed0ebb4a544c3a35cee92bb95b.npy +03467517-dc7708c870000008a24eeca91f583600.npy +04401088-57657c2b0d983a1658975870bb96a55c.npy +03691459-5775db2064a6b0e87d72888c0a9277c.npy +04379243-abd1518f823abd0ff51fa0238791f5dc.npy +02808440-247a755e3e86bdd254d7082b34825ef0.npy +02747177-f7c95d62feb4fb03c0d62fb4fabc5d06.npy +04256520-b543411f1fce1f30e6fe3612af521500.npy +03001627-877391ca125a5ad07a56985e287037f3.npy +03046257-84d1404385710894fe3e90bc90e90c63.npy +04379243-73eba3054b62c14b76c7054c38bb1311.npy +02747177-7065044631c0eedaad5067eac75a07f7.npy +04379243-1a23f3f25a8584cc49fc9876b157a42.npy +02808440-b4e2c11f4c01123933d9cf37f30825d7.npy +02933112-87e7c6e590eaab04f42a90fe4baf4591.npy +04090263-7da1ea50ed1445ce2511f68da65f4c4.npy +04379243-ff42855b8cd62a1060fdcc1483180fd1.npy +02876657-caa8379f21c74f611f058bf0578300.npy +03636649-1fcefc2c2ff00dd6c7c291dc7d41000c.npy +02933112-d06a1c6dc8a4dcdecb3bcacd97bbd8b8.npy +03001627-bff224175aed2816597976c675750537.npy +04379243-8b0e0e3fdf70192e484776fb236aef2e.npy +02828884-537a02eff282b33df58bc14da5676759.npy +02958343-3ea856c52fbb213fe151fba1241f1efa.npy +04379243-217a31e6044506f41b17743c18fb63dc.npy +04379243-f0e18881d2d01e91286a9d56d8187adc.npy +03211117-23f0e9274d835f2d75796bb36346e6ad.npy +03001627-813f2777195efc4e19fb4103277a6b93.npy +04530566-bec39afc5bad2dc45ef003dbb9fb9184.npy +03001627-c976cb3eac6a89d9a0aa42b42238537d.npy +04256520-377fceb1500e6452d9651cd1d591d64d.npy +04379243-3629fe311f6a83eaac8336231c53cd1.npy +02958343-6a81b52d03080172ea7256175786076.npy +02958343-ca93e4d0ca75ab1bafe1d4530f4c6e24.npy +04090263-e03a316409096ecb625f0699ec733ab7.npy +04379243-4b39fda4ce751bdaf51f77a6d7299806.npy +02958343-bfa5b41549e86f3c618e9d35559b7aa.npy +04530566-7cf500d15ff839e92f35bf9c34b31609.npy +02958343-73df85f3bb763fcf148474f05635eadd.npy +04401088-78b4f3aa956b52139531a714ad5bf7d5.npy +02828884-5f12f2a5d67a1e9fcb2a965e75be701c.npy +03001627-aa1e9626e1e23038cc0b9bf177196e52.npy +03691459-c3661475a6b1f7bcfbe246021081638e.npy +03325088-869d5441e74a94b3251c40136771148c.npy +03001627-3457146f11dab7eff3c9c1464e55d580.npy +03211117-2112d3266c05ad92d99bf9137e86c0b.npy +04379243-4d9a737a9ffa6277589aae130c1f06fb.npy +03624134-db33d647c8e9c8f9aa19ff1f7032d4a0.npy +04379243-f94e4eb78fa79d9d41578d1a851771d6.npy +04379243-a5f1b90f85d875f13afadfff198a630.npy +02691156-ad10ae20ac2e87a2adcbeb54f3d014e9.npy +02691156-6ad44d7abe7492b7d89ea85a4a66c0f9.npy +03636649-b474613907b293682f8b82e61bb347fa.npy +02828884-367cc7ed7b83b7c8fff16555386d173d.npy +02691156-effbe2683574dca2b37a6cf3f07b9ff4.npy +02871439-ad808d321f7cd914c6d17bc3a482f77.npy +03325088-a1b38345041badc5b362845c6edb57fc.npy +02691156-4635326bc4fdc3e9297cd7e2ef7dfa80.npy +02933112-d30e98009559150df27756ab62184cd0.npy +04379243-d03cfa4dfa08467f19620b61f6587b3e.npy +03001627-b9d60d124e24849d37b2bb75885cfc44.npy +03691459-7174c62e843e444286a8288f8ff176fe.npy +02691156-a2c5e769f19c7e97b7d7aa9b9ebcccb0.npy +04090263-c7774cf7e0e74fd2194ef2821d9a630e.npy +02828884-1b77f2fbf17f28e726cd2499b0c05f5a.npy +04379243-1645b28322131b6258c407efcf93be6b.npy +04468005-7003287f015d22fd52470de2774d6099.npy +02958343-9e2e375fd5fd55b02a9eb0f146e94477.npy +02828884-7aca4c47c6861f2122445e799be0f18.npy +04256520-629e4382f2d569f366b86624c235daca.npy +03211117-e09670b2d890f63d84e349450a5c51b2.npy +02958343-22bc49837550bed21e570d3da54bf9d.npy +03337140-96ba97564f5ab63191c352d02061b3f7.npy +02828884-86ef2d2a38bde1ebad5067eac75a07f7.npy +02992529-4a48ce1a067f686dfb63369d5dd85d25.npy +04256520-337b0e3fb3c00f6e6ff454af1e8947f3.npy +03691459-dd05c61250149ba5d49b96b9f2811c7d.npy +04225987-10b81426bea7f98b5e38a8a610bb08f5.npy +03261776-f90f01ec45ea95d65481d2ca627e43e7.npy +02808440-170cf39eca88a50e125fa9990176f0d5.npy +04379243-caee24359d445f4fac509329c62279e6.npy +03001627-3a123ae34379ea6871a70be9f12ce8b0.npy +03001627-ef463d298bb401b3ce1493daf6a835b0.npy +02924116-4f934ef7f9b725057d5938f6fe09fcd7.npy +02992529-6a073661711d8b9f1a5b805dbbf26206.npy +04468005-574ae16c1b6cabbc8a3f1a8dd89692c6.npy +02828884-fb9775e4ada511d7844283a0969502b7.npy +03691459-4d165a6accfad3d36f18f54fab5ec8d.npy +02958343-89edb3d434f4c983afe1d4530f4c6e24.npy +04379243-94c0ab5650ea392ddcfcef693e7ec696.npy +04379243-74ade89963828a37d94ed55f750426f.npy +02691156-85a15c26a6e9921ae008cc4902bfe3cd.npy +03991062-bc37a3aaa9651aa410897bb36a0ea9b4.npy +04379243-2a2d4bc0c2ad2e7e332e588d1e0957a7.npy +03001627-c06a8f95fc273106b0f4a0d43d1e4c23.npy +03211117-12c64d690700ecd2d25ca1a27cf9bdec.npy +04379243-db96923291ea465d593ebeeedbff73b.npy +03211117-ba0f98e212668fdd22532be027c41b0c.npy +04090263-f1938c5ed63aaa7c91c108af8af49f8f.npy +02773838-e90e27c3020d25dd76bb31db0358e9c6.npy +03001627-f4268a28d2a837a1167c009da6daa010.npy +02691156-ce337df2f75801eeb07412c80bd835.npy +02871439-64eb95e3fd7cfdf759bc1c69ff20e0.npy +04379243-80a86204247b30fd21ef666e979e4e80.npy +02958343-b4715a33fe6d1bb7f63ee8a34069b7c5.npy +03001627-9e9697da825cbe4b3002761e7a3ba3bd.npy +03467517-5288448a001ace0b47a275fea6658912.npy +04090263-d9c6c64bc9b2c1e0a5dd675711905b91.npy +02828884-7acc1a370dfcd3a85ff6fe84f53e00a5.npy +03001627-a3e3eee0669bec82c9f016d57db96408.npy +04379243-47f25d5b367326ceaaf15b62af6b513f.npy +04379243-6ff63214c89d65d7b87028a4b477349f.npy +03624134-954fb0819736737a1b9c8e2fdbfc1118.npy +03938244-7c94c3ede6a3d3b6d0a29518c983e8c6.npy +03211117-2eb15877e9ae80d1d50505ee01b106d8.npy +03001627-226927edcf014278cb94e5b490ba717a.npy +04379243-be5349431760322c7b7b1bcdebeec13d.npy +03624134-2e9a0e216c08293d1395331ebe4786cd.npy +03761084-fadfea8610d0a2f839d3717288022c20.npy +03642806-fae8d4929159d0df7d14ad32b7473fd2.npy +02958343-713b7eaeea5580af1f71b98bc1f8bb06.npy +04256520-fd1ca30eda9a2163e2ca61e91f2755b7.npy +04379243-332c75b56c4a80f77ff6ace05b36a5.npy +04256520-8188a091928db3cb489883f17c1c79b8.npy +02946921-f4ad0b7f82c36051f51f77a6d7299806.npy +04379243-1c679d8a4fc274f47523f50a56d94935.npy +03046257-1b85f3cd227da31de4511d9a59e40339.npy +02828884-4e4b38efc9345bc3cc543a6b1ba2fd1d.npy +04530566-56e2b7332f9011b28fecb9f40039f353.npy +02828884-481885f3ffe14c40665f42dc26fed092.npy +04379243-2b68cd4ffe443506abb564bb0657e0d6.npy +04379243-a78bd5277a6c03cdd3726fd70b88cb7c.npy +02958343-c5079a5b8d59220bc3fb0d224baae2a.npy +04090263-fe9777c5bc60bc393554ccf8c30febe7.npy +03991062-756cc1276b4894682271466eed05a4d3.npy +03337140-7cf0301223e59976e7ecdbe73ef4323c.npy +03790512-fdb6223c286cb653cc9e7530f9d8e186.npy +02933112-634fe05a380adac585430ccbd2632877.npy +02946921-11c785813efc4b8630eaaf40a8a562c1.npy +03046257-18de33d37e409ea296791035e86a30f4.npy +02992529-fabcaa4858df16e35817e30de1dabac4.npy +02958343-aeeb2fb31215f3249acee38782dd9680.npy +03691459-e7560ac665c6fedc7d54ddaedba43004.npy +04090263-6834350f16324d0527d7c45115828e34.npy +04401088-a0efaa2ba04bf091adbfb30d8d1b297e.npy +04379243-55accdd4bb5337db5cb8c3b627244050.npy +02924116-b743b94f562fa33a7c3c6f82a395b347.npy +04401088-359be05b5042209a502122ac3599bb74.npy +04530566-9e49192ba54ab0fc92c108c58096cae.npy +04090263-846075a4b76fe0c3052214d75e02efc.npy +03467517-567df77255c293b3352e5d4d2615db5b.npy +04256520-dda3a0ecc85a337a593ebeeedbff73b.npy +04401088-a434289b281e629b81139543c959a70a.npy +02828884-23c874e54f1f9f152d07d128adae16ff.npy +03211117-8359589eb5c647a61f571c9e890db987.npy +03467517-79e1607ac6676f3a1ae1027f8632e61.npy +04330267-27cebdcd07cf90aa500158c23c4c5a8e.npy +02992529-e55c20e95bf299b5fc4d1dd4278b31a5.npy +03948459-41bca1dbde9fe5159220647403cfb896.npy +04256520-b918cd058e822e00cce02970cdd7e7da.npy +04379243-e2312615b21d7690c4f22423196a0dd2.npy +02828884-22031fe0420834a9ad5067eac75a07f7.npy +03467517-3e4bc88d2f2456f4ac705d0d37f5ef0d.npy +02958343-e7f94161bd90444f8cf4cf458d5ff7b.npy +02880940-4017528ab5816338664b3b9b23ddfcbc.npy +04330267-89550f9f628589bd3e65b46d4ef6236d.npy +04379243-54bc0f4268150dfc616626762e4bb71d.npy +03593526-c0d3656a60fc5e3b16acbecd8bf6925d.npy +03211117-e65ace5f42977a75cae346657a37ed71.npy +04256520-70e157cf567eb3aa79b26024bd30ee26.npy +04379243-fe38d140fa386ed4c434c6fce2e7773.npy +03001627-4217f023367a28b06747dd1c5ab1ba16.npy +03593526-ccfa627a398599ebde03ab2a27ba7531.npy +03624134-e199629e24c10052ed9c5b25fef60d04.npy +03593526-189996124312ea7430612f5c0ef21eb8.npy +04379243-ff32ec299e6c37e767d783b4714d4324.npy +04401088-9028fceed53a144e10bc2436075f6a52.npy +04256520-cd2a6bf7effd529de96ac0c4e1fb9b1a.npy +02828884-675f7c94f5422ebe9e4965f0106e00d9.npy +03636649-3eb6c3bf89e5c9312569f5d050e29bc5.npy +04379243-3d38d16334e796526f3d2b1b15fba494.npy +02958343-5e5d7901f587c39726d36807b4d406ea.npy +04379243-6ec67ee0e57282c01e6058fbce2703bb.npy +04379243-9da75bbb92f594f19cd431573238602d.npy +02691156-23fb92d8cc0f8ac4def547874c3364e3.npy +03624134-2514540f36b2ced12f8c68dc62edc38.npy +02691156-1385305478499e6c1e06124bec25a766.npy +02933112-1fc8231114fa42a7c59350d819542ec7.npy +02808440-2272656841c3c84a61c4f2a9857347d.npy +03001627-47d13a704da37b588fda227abcbd8611.npy +04256520-aeff3da4a02a22b07b0278d6b5ba1920.npy +04530566-ac4286c2e92e3367d5ba5130450bf929.npy +03046257-faf4bfc17b75a160af04fb2a17e783e6.npy +02691156-2af93e42ceca0ff7efe7c6556ea140b4.npy +03001627-577d1c446658fdc7ebc935c637c3e3a0.npy +04379243-93f7c646dc5dcbebbf7421909bb3502.npy +04090263-f5a1080ff36f7b8c38cddde805fe966f.npy +04379243-98b0b99d86a2342b2b23d7805f9b288c.npy +02747177-4117be347627a845ba6cf6cbb9f4c2bb.npy +04090263-3ddd478e24daf437f99860cd321d6c67.npy +02958343-6fd6bb6ccf11968c5242705df8faa8e5.npy +03325088-75400f002f5ca46f275e59035e1ccbda.npy +02808440-a1531938a8f8c32b6e1f781c3bfa1222.npy +04379243-98ec86d721b235374d18c1ce5fca6777.npy +04379243-3297d1740b06d444855931d119219022.npy +04530566-605b56aa6a4c9ef49f1deb04fb8ae481.npy +04379243-380f9d534e139af5dde0caad53ba7e0c.npy +02958343-f61888bca4392106bc790478b4a84bf2.npy +03001627-77b457b102a9b82f5dca6305fb9f97ca.npy +03467517-ffa8015ea7ab2e0b900fb9e135826c5e.npy +02691156-a73231f3d0342db94e8b48a4c01e36f8.npy +02691156-e452189bb7bd6617ef7cbef6334698fc.npy +04530566-f99537c4b6d50126d87c63d8b3018b58.npy +03001627-430f87764dc3f455ad484915511ccff6.npy +02876657-3108a736282eec1bc58e834f0b160845.npy +03001627-7929676e756dcd41577b5d737869717e.npy +02691156-d80afa36aeb72c552b5147716975ed8a.npy +04379243-15180f731834feeb2f0a9a342c0178db.npy +04530566-5d0d84924e96eee6b6162efbd23a9d5f.npy +02992529-9e5b9dd860689c5c217f93816a639386.npy +02828884-edec9a4512b98f6f2056b4bd5d870b47.npy +04401088-cea8f15682797fe6eb386a4e845c05f5.npy +02933112-2dddaf7774fd11efe4d4a3bf05a8b705.npy +02691156-1d09583e9236b8d149d860a48be37092.npy +04256520-3dc8e7cd623f5aeb65498947b67a3f6.npy +03001627-4275718494dd309bc7d25fde6b97816.npy +03001627-92db07d09bb110386bd0aad3d992cb54.npy +02876657-ac7e1eed3c4ded7db3010b85c6cbc688.npy +02958343-61bbfe43afb10fc8360bb9d5bffb2354.npy +02958343-e2e9b87d7aba1dfb28044fe9244db50a.npy +02843684-ba88e788ae3bca5e84ee0c32fc6ec7d3.npy +04530566-d317c39473534f97b1bb46d2556ba67d.npy +04530566-2340319ec4d93ae8c1df6b0203ecb359.npy +03636649-d1aed86c38d9ea6761462fc0fa9b0bb4.npy +02933112-1f1484649f0b2d9f6820cc0e7030e15e.npy +02958343-ef0703db8a04f8c0c0e3666c7d0ec7d0.npy +03001627-4a671498c6e96238bf8db636a3460ee5.npy +03636649-3ba4b7bb7b6d89415461e7d030e03e48.npy +04379243-4fb3b350f197a7e64e045e9030a39002.npy +04379243-a6311f0c2108867aee18bc48b60b36b7.npy +03691459-85399d0503bc8a5b59a6208793b9dfca.npy +03001627-bc76dfa9e0a91e131e06124bec25a766.npy +02691156-3fa511e1882e41eeca8607f540cc62ba.npy +03691459-af97965ad9dc0ef01ad88f716ea80910.npy +03046257-c805c00b467a90227cb512ba2d8dc1ab.npy +04468005-7adc8184ad679791e810c01b1498aa2b.npy +02924116-869d7fde444e238d87cfb85cd974d515.npy +02958343-2fc27dad23406a2a7ae33d942430658c.npy +02933112-c07a52687cad81a4824662341ce2b233.npy +02992529-8b4d28e4df5ac6e8656557acf97c5e2a.npy +03001627-49e920c98895f90281a172d69c52a28a.npy +03046257-83255e2f9b4f039372f8ff3c650e385a.npy +03001627-9663b0a707ba9753983e0ae0e9b98f24.npy +04379243-1ad0e2f815c6f242d197f67767b32741.npy +02828884-c9d456bacf459248930524909158355d.npy +03467517-c651a91562b86ed8edb9371445f615ae.npy +03636649-330b05e262c93e216078c74a96498820.npy +04379243-7191fe8893bb6a89b5b7c35a8e7396f2.npy +04379243-b2867d5067f44e0d6b1cb83d86c19bfc.npy +03761084-86bda959021c63b48242cb5dc48c7177.npy +04401088-5681c4fec43043c1a9f85d9079e13c55.npy +04379243-175c0be26d0f2e916cb0bd372b0960ba.npy +04379243-262f3ee836b6b023c5beea20858a99d5.npy +03636649-2156df35753fc26c6e285dd101afcb51.npy +04256520-3aab3cf29ab92ce7c29432ec481a60b1.npy +02992529-cfeec23a9ea66a5021844676433a0aca.npy +04256520-103b76b2594a1582eaf14273fa406ffc.npy +02958343-74b37c2f88e0ef7a469bb3d27ee3bc4e.npy +03691459-d2553e5fc4f1527cfeae521e94848af6.npy +04379243-be8a750947549c7555f9913e822d5318.npy +04379243-adf9117f3cba509cb4e3935c6cee4b35.npy +03001627-7772a25ce35049881dff5c2e57ad46e.npy +04401088-2acc3bd87282a7e31da45817bd55c1e.npy +03001627-8f4750616cc16a3f84633b41c8a09fa0.npy +04379243-202e7b5c3ec079e299e8bf807e902261.npy +04379243-61ae29ce7a0d71bc57f15fc9385a8a01.npy +03636649-afb7cc3bbc3595a4e9b3dff83c7ff715.npy +03001627-e015df603fbf0852f58087d377226538.npy +03211117-8893ff22c6dae8e3a276bea9ebd065c5.npy +02933112-4dabd28be1615419546a56a24fdd418a.npy +02876657-5d6001f9e6a15de3e3edb5ba52088f8c.npy +03691459-bfce87b0ea79c8aa776400d171cf9dfa.npy +03691459-8ae34239b6c46afd55a4dbb6a97481d9.npy +03046257-813fc7bf6c5cc031fcda1fad26dee92d.npy +04090263-af727bd232a8f1f4c3d83d64958925ad.npy +02958343-a03c7c73c067afa9e5bf84cdd88910df.npy +03001627-61eb0af11765544ef91663a74ccd2338.npy +03001627-3c27660aacbcf99886327adaa986dff.npy +03593526-5e61ce9dd25efc97eb7b988bf4f0d1ef.npy +04379243-36a14a47b91d7c42f51f77a6d7299806.npy +02933112-5413dbc1844cbed099dd23ec22c4943b.npy +02801938-b884587324a0cb7a643af06537e992c3.npy +03593526-57c542a72c735adb7e2297b5fd58c53e.npy +02828884-a968b5d4ba65b1af155d75bbf62b80.npy +03211117-b2257460f3465f76370c049e2352d133.npy +03467517-d05fcd42a07cd11dd57700c05b1862d8.npy +03001627-56d06d2b12a40bebdbbc9440457e303e.npy +03337140-4563c70da4aa13814c3aee8e9d3a6ffa.npy +02691156-e8e1b765fdf5edfa14c19f41d007670e.npy +04468005-ebe70e10c1b17c91616c9d4a76208d49.npy +04530566-965153f3599a6ed6be7ca2216dc1576a.npy +03593526-5c1128439ea33c8398910e50f05b8001.npy +04379243-cf1a7653c10aaa0eab610b0c94236463.npy +03642806-21e03f21a8724ab5bfa1d058f8ea2f0a.npy +04379243-8069dde16a0f987664b3b9b23ddfcbc.npy +04379243-39a0cbf3e4b34ca44499f83a01888ef1.npy +03513137-8322568841b84054b581f592cbd3b472.npy +03948459-d4705e348edc0e405f4103077989355c.npy +03513137-c354dab2bcbe9c68d6d40d1978baee1c.npy +04379243-18cc2e8b4034da8fb20aa91e9e90c311.npy +04379243-a10406dec2b6e9a2df81d783214232f2.npy +03261776-724c6fc81a27625bb158ade66cebf744.npy +04401088-e458abdbff34fefe255591a17641445.npy +03001627-c4a4710012ee39bd19f4b416b31c46e0.npy +04379243-2acce0e402725f80ece694d60a812f12.npy +02828884-188a2c6c2add34399dcab1d3e38b3b70.npy +03211117-3de6f62a6faeb80933e9820fd7ca74b3.npy +03001627-465ea1eb1c76c1478d1fe8cdc415f4c5.npy +04379243-1901183525f0063d2822b5101b06e070.npy +04379243-32ddda038bd1bc15c3bd24f986301745.npy +02808440-841e9b3d40aacec23d89f1ada385db86.npy +04468005-bcc41de06b8059f5ba32f71f79130dff.npy +02691156-ffbc31352a34c3e1ffb94dfdd6ddfaf0.npy +04401088-f75e6866c8965374f1c81a6df84170c9.npy +04554684-41f9be4d80af2c709c12d6260da9ac2b.npy +02958343-ed91b2509171fdc1c48492b454f1615a.npy +02808440-da7c0e8e5a2d87f190a2f7468a138e7a.npy +02958343-1713a1ac8aedcc522b12ea83455b0f44.npy +03991062-2d97e5970822beddde03ab2a27ba7531.npy +03001627-ce8f3a0c0c0bb0b9b20716e5484f7807.npy +03636649-5c9f3efb7603bd107c57db67d218d3b9.npy +03636649-9b876bb9de59e5e9aceb781f079a299.npy +04530566-d3c26b292a4a6a82621153a3cbe4a77f.npy +03593526-94f4ad8b9ef500221952fef39dab6347.npy +02933112-2856634c4c0551a814038d588fd1342f.npy +02691156-157bb84c08754307dff9b4d1071b12d7.npy +04256520-f080807207cc4859b2403dba7fd079eb.npy +04379243-7653898ee4d8173827edb0fd78caee34.npy +04256520-19f52379f01878ad9517a37c9996fdf8.npy +04256520-92ee5842113109b05550af5454dbad36.npy +03642806-5363c4a882e17c9088557758112e80be.npy +04379243-5e0b6969f252cee2b355cfc2bfa121d.npy +04379243-1af5dee23444c104fff16555386d173d.npy +02958343-3026dc837dc5dd7a157e36ecb370d387.npy +04256520-69e983e816774aa01b17743c18fb63dc.npy +03691459-1742419bf5a54be3e1a894502fdbf97b.npy +04090263-2632b2d716be1677914c738e92faad58.npy +03691459-56e2847e61b36a134c7bf604b18af84d.npy +04256520-e596ed19966b698c10edd100dffd8d85.npy +04379243-c363667046c562c7d9c568a52c35ec71.npy +03636649-3f7eb5ef5d304040d847cb32379eb854.npy +04379243-6f7260eb15f4531348ca89b7a9405654.npy +04468005-ec0dc5270b3e1fd4a5e12deb37e3ef08.npy +04330267-a46e0c10f17f928ba2bc8d1e386113dc.npy +03691459-f5024636f3514eb51d0662c550f8f994.npy +03211117-5f0119e9c7f437ff83361808b78d50c3.npy +02691156-1d63eb2b1f78aa88acf77e718d93f3e1.npy +02828884-d8b87f36fde3f2f3bc5996932c1238cd.npy +04256520-9294163aacac61f1ad5c4e4076e069c.npy +03636649-4078ba4cad280d72b8b431083b6191e2.npy +04379243-8bd48b85e15e23e162c098c9081f25f4.npy +02933112-63cb49d18eef102a5c910a98e42d23d.npy +03691459-5da2a1ae6ec64155dc7dfac1f2c9f0d4.npy +04401088-ff8ba237ee9164c8ff86292618094648.npy +03636649-ed2f272286506a5786e8e92cc08146.npy +04090263-5ff5a86fd864ddcaf0e1c0df18936d05.npy +03001627-b0fdc43b0b4e990719abd93be2967664.npy +04379243-d62f718a14db87cdb40f0ac0fb9a650d.npy +03001627-412b79b2d0572c6afb76895427c01995.npy +02958343-e1197a4adc50d16abecf71e2e014ff6f.npy +03636649-9150920591733fae0fa444666ebe22d.npy +02691156-619f0ed9bd92778e1c6bce26aea93f68.npy +04379243-f0b044c592e19f3d8dab161b48d8b921.npy +03001627-780441a4b2e033f2796c584ff1fcf56d.npy +04379243-10d9b52541550c909cd431573238602d.npy +03636649-ed81fd0ffffd360638e74158ae3d41a0.npy +02691156-350110d2828b3b927370804727e72eb2.npy +04554684-1a53e51455e0812e44a7fc53aa1d411c.npy +03636649-266d6b136cba49504b3c42e318f3affc.npy +02958343-a3e1cb03e1af7c6161c6c61410fc904b.npy +03046257-3edef12fcf087125868fb986bc092533.npy +02876657-e593aa021f3fa324530647fc03dd20dc.npy +02992529-1c3795fd5c4c0a3c2efb70bd2c052734.npy +04090263-6c82de0208ed0f551ff1879fbc41d0b.npy +03636649-2ac3425dd13590ef1f9097f35cf9fde9.npy +02691156-b55748e796006e18b3f627c3cfda6efb.npy +02958343-bfae73d79c066a1fcc0c0cae12126488.npy +02924116-22f056f45adc9b81cd9505c17c2fdd7a.npy +04379243-62f7c1abde6bd25e601bea3dca268229.npy +02933112-c54828598efd80d78542f96306060db4.npy +02808440-93818961a43764e23321831d2245cf06.npy +03593526-e3fcf5ec83e5fdc54b3c42e318f3affc.npy +03046257-23f83dd607100e84b5c397b37fbf4059.npy +03325088-90ee4a3d500e4ca4c36fb70296e45483.npy +03991062-762ff1483169859d44c183864792bc2b.npy +03325088-f1cc1b5b92f010a73321831d2245cf06.npy +04256520-e3ce79fd03b7a78d98661b9abac3e1f9.npy +03001627-4966ef665c6ed17d4240438e2a9161a.npy +04090263-6571520aee22fe52eab5ee569c9de1b1.npy +03636649-d2d645ce6ad43434d42b9650f19dd425.npy +03691459-f858ecde18c5dae2f398d0c5832df00e.npy +02808440-189c1ffb58c74c3bccd0340812259a39.npy +02958343-3129657917191e101f0d59cde6139796.npy +03001627-8e93fb99aaf17b9504ca5aa564aebd0.npy +02924116-27f138cd6641ce52b038a1a418d53cbe.npy +04004475-b2ff768db80d2d723e6c258d47d0b669.npy +03211117-d8b955cb8ef35cd22f2d2270d816bf3a.npy +04379243-ca7bcac6b92b5a7d377b9297f3055210.npy +03636649-8261f96cc33ddb264a7f20ad39e7a642.npy +02992529-b91bbf0a0d09d2eb243525d45e430520.npy +04401088-ef34d9789a83659c9f8f9b52e89f6554.npy +04256520-bc8e9f4d4076ce4f6b4675882670d943.npy +03001627-d50b0c6c006936f8de03ab2a27ba7531.npy +02828884-1c47c37d6c785d4fe7fd9a18c19837e5.npy +04379243-211d17b0424b10c539d3717288022c20.npy +04401088-831d6d9118e1a2fb71f2e8f64dc1f509.npy +03593526-8e7b2732b637559976fd405e95f98511.npy +03337140-5ab4826be1de80dab7a33532f4904aca.npy +04004475-1d2a6082238f011c22d3f170937c6a0b.npy +03636649-84b093611cca35f86f104b4f395219ec.npy +04256520-3aba6ceca44f747b29a72cc7a32af9e5.npy +02818832-1f11b3d9953fabcf8b4396b18c85cf0f.npy +04379243-a44b3e23fa01c205c3bd24f986301745.npy +02924116-43bab6803534b01f52470de2774d6099.npy +04256520-d4a80e7a92e2c4f98981b7cb87854e68.npy +03636649-32e9d8a4b5a141a2615efc34c3b36ef0.npy +04401088-74a65213a90e1f2d850a112e6048afc4.npy +02691156-a00ed5d078c6244c37678474be485ca.npy +04256520-181f594fb55e7d811b17743c18fb63dc.npy +03001627-5ee976518fc4f5c8664b3b9b23ddfcbc.npy +02924116-183c1ef7e783a05a8aa27cedfe9e8bf6.npy +02691156-5524fd6b35f47d5ba8cba409c4409ba9.npy +03467517-2dbc73ad4ce7950163e148e250c0340d.npy +04379243-449c32cd053b97ac623f20df7a811122.npy +02828884-220ab2896e0b5d87dae58dd9656897ad.npy +04379243-5912cbf7bd756d3bf51f77a6d7299806.npy +02876657-ffa6c49aa8f7ec19971e7f8dbfabf375.npy +04256520-2eb0a772c36144eba3f22b4b00de6dfb.npy +04090263-54ed1b7f842914285488420adf4edfd0.npy +02801938-b9a555f6ce431c8a3adfd94cc5954055.npy +02691156-fa4e8f24d7f0ae1cc1ccec171a275967.npy +04256520-62b02c1b27a5793fef188758bf2e3a30.npy +02801938-717f1009cff7c62e741621be11e9d307.npy +02818832-5cdbef59581ba6b89a87002a4eeaf610.npy +03928116-9b3fde7f4559be2363915d3d0e86b8e1.npy +03636649-5ef8a1aeeb1b25bd63fba60e6c90121a.npy +04401088-a1e51e185a9f24354b8478bdb97333d3.npy +04256520-d28912450f62b4efa8699b6183baa203.npy +03636649-5d45d41ee7fea0187cbb0b604dd1148d.npy +03636649-a5fc64e1faa85794de03ab2a27ba7531.npy +03001627-1c2b230840baac57df3c82bbe2e3ca02.npy +03467517-4590e640c4828cccd57700c05b1862d8.npy +03211117-20476424cf10985610b144a5a224780.npy +04330267-d98da0d1b24f509d6134c153bee8ea0.npy +02691156-396c8e232192a44be1a9c234926c21e2.npy +02876657-78f5db072e28145db1e647730e72f91c.npy +04379243-d14dfaade3e105306ebc5c7b8e36e351.npy +02958343-b76bdcfc277f54007f3efc94c2d31dc5.npy +04090263-a5f55a60971922fff3059fae889f5fb2.npy +03001627-700b11e2ea3e941faffa8ecba9b9d6f4.npy +03636649-ff43ef647c75b5a4fcb8d8c6d4df8143.npy +03001627-c9288e09458ec0e9bbc45ba666751519.npy +02828884-b852e63ad5983f1a8ccde000e771fc1a.npy +03636649-bf2687bb57e94f4071d7520e3757f3e9.npy +02924116-b4ad2006f3c6e09adab8f5f5224d1d8a.npy +03325088-fcfe9beedd2970f3b362845c6edb57fc.npy +04554684-d78b4c3dc263a8f9c5243a0ab191990d.npy +02691156-1825c91c5f2da4bab12962b43f188cbb.npy +02924116-d48362c5a290701f78194ea2c3f9c38b.npy +03001627-c41fe0605cfe70571c25d54737ed5c8e.npy +04256520-f23636645d46b743ad4f8dd77b0e70fc.npy +03691459-b2ed74172242cd805b2ae1f253050025.npy +03001627-7aacb2d4940e1af772ee08e78374a212.npy +03761084-5f51f5e0607167b4178e7d331e641179.npy +04379243-e37262abd76852ac00ee852f6d8aa3c.npy +02828884-8141d9182908d7288be87af3b9c7b4c7.npy +04256520-79745b6df9447d3419abd93be2967664.npy +03991062-c19c6178ed0f6f9da989559b7c93527c.npy +02691156-820c903c55d7a1908f0d19519a0ef908.npy +04379243-3889c517afd62ac5dbe9c90af547c85d.npy +02747177-5eea24527c8b3124cb2a965e75be701c.npy +03001627-b987a2ca54c6ddecb74697ced5978572.npy +02691156-3b86245a5cd388ccf12b4513d8540d7c.npy +04256520-4271d43fd97a7baa591cc7aab9026e54.npy +04379243-cb87512d706828e1e95cd0dc8c2f0e83.npy +02924116-6c3e80092fa36371cb2ecbd32dc2119e.npy +02691156-e41bbd12896cdc724d210d9468aedaf2.npy +03624134-d78c656d1847b92ddadc002e53eaf226.npy +04530566-816efac46f2f3c99452a4c76a476a0f6.npy +04256520-3f8523f11a622d8d6983f351200ac6a.npy +04256520-19192524e6ae1e85cdca798c54fdf54a.npy +03001627-2ba1779986eb9546f51f77a6d7299806.npy +02992529-6f63df7ca322514f41ced50d3a574698.npy +02958343-d22cec9b9f500ade28e9ca8e8fb04e0a.npy +02691156-8b9a404737736ece774a720fca15e35b.npy +02942699-2153bc743019671ae60635d9e388f801.npy +04468005-e5c8853f28328d0c2511f68da65f4c4.npy +04256520-f6ccf5b4afd9171c818b86d9fa7a616c.npy +02828884-32b62bb2758b4c7fd2b12aa6a0f050b3.npy +03001627-7a79745b6bba49114ee3d18ae9bb4bb.npy +02871439-d616e70071825c91281816ff6b8d922d.npy +04090263-41fd7683b4e722b716b34c3751bc447d.npy +03513137-d516787b65d08365480514d7f2edc0a3.npy +04004475-c2579f3b815ca02d9318709b609c3a71.npy +04379243-e49b95f478df00bedbbc9440457e303e.npy +04379243-4d56ccf8487a0a64fbd58bd1e0b7491d.npy +04530566-eea06d3bf1f7ce6cb538a15c6737824e.npy +04256520-4f863fb727ffab64ffffee5f2b1293da.npy +04379243-a5c6be40bd9332e873d4ab618ffba803.npy +04090263-173dd045c9da9aff6099a039722df68.npy +04379243-fa0580ea9b8940dfef1b7984700142ff.npy +04379243-bbf0968957f58e78f00f21861968ae14.npy +04379243-8ca1fd346eb62580ffc6e457221b9271.npy +04379243-5fbbdc1e83a45d258d1c65d617ea0b5e.npy +04554684-8c122f99b5a0aa047ca3f903b5926fb1.npy +03928116-6806f3e6e973f715c114a8120a565776.npy +02691156-2a856d0462a38e2518b14db3b83de9ff.npy +04379243-99737ff619cae25d6effbd64ad6b71b8.npy +03211117-d6039aa6de8b5992af6cfa169befaf46.npy +03636649-d6ebf710756c5839f8d3a35c7c106515.npy +02992529-7fa841359a3dce3dbcb8492ce3867c34.npy +04379243-2b39330072a4d5c83825a5bc524f67c9.npy +03001627-5fdb10483f79355581f5ac91b0c9e99b.npy +03211117-d89cb5da6288ae91a21dea5979316c3e.npy +03325088-840c861dd22947bee3f7a74e12a274ef.npy +03001627-3e80bf14b5e02aedeabde033450b7299.npy +04256520-2459280764bc155554a99e49f597fe94.npy +03636649-9de2685230d41d58c397356311cbeea4.npy +02691156-7932eddb8032b6f1e4d2773f0358b43b.npy +04379243-38d5b6ad3077e8b1caa22a10624245b6.npy +02958343-100c3076c74ee1874eb766e5a46fceab.npy +02691156-38edc8fad5a5c0f0ac4f72bf08dc79a6.npy +03046257-3182826d3c212720c4440dd41b08b3f4.npy +04379243-ccb1c5fecc863084391e4d6c585a697a.npy +03001627-39c629e6f9e752964c6ea7add0063fc3.npy +03636649-b736ffab5afcc08ace1d463bed0d7bb4.npy +03636649-52cd206dd4674bbd4fbd95145f67665c.npy +03593526-99f6281962f4b4e598910e50f05b8001.npy +02924116-abbb6509d2f4662452470de2774d6099.npy +03001627-375dd87b163dc8a3a3c9394112c76917.npy +03991062-28cdf1c93d91dbc671fdc118f95a3db8.npy +04530566-63d91bce2f3d26abdeb3e56da26a6974.npy +02958343-584a78bbf7932674d4fdf31cc2d78fd0.npy +03046257-b4604066f95413ffd2d25e908d9cfaf6.npy +03001627-ba5054bd7c2598ed832fe5f29a662936.npy +02808440-72685559e732565bc394d70fcc44879d.npy +02958343-2525b83c84bd3afbde2d51ea8231791.npy +04379243-23d68e01b77089ae76ad4f5e7c7020eb.npy +04468005-afbb150345afadb35392bb73ff1a60c8.npy +03691459-b40b4cbf6309c3519fa340262d231abd.npy +02958343-21eba3c73a705597db2c2b0116c82e56.npy +03991062-caadd7927e891931b27dc9f9b9dc6f03.npy +03467517-fcc1d297e1c4be5d93f0194265a9746c.npy +04379243-b3477e3ea9fd1676f016aee3d784d83c.npy +03001627-5a960456884d2a3b04cb542e2c50eb4.npy +03467517-bb36b42935f0a1bfe5ef386e39420701.npy +03467517-275c4f98ef07f2b393f0194265a9746c.npy +04379243-e75ddddd62dac8a119fb4103277a6b93.npy +02691156-23e30666530887e69a6e43b878d5b335.npy +02691156-de863b025e53c9a63554ccf8c30febe7.npy +04330267-7963f2d868a8cbb01989a128e43b35b6.npy +03001627-70eddfb0000447c637b2bb75885cfc44.npy +02691156-7f0c20bc26b08a163e2ffe63fcfe09ec.npy +02828884-152617f1e955e8baf4fb4dee5181bee.npy +03046257-6fd5c3b0efc04f3986c439c0403660e8.npy +03513137-4f0ae9814adde64f6a12484fa9d9be10.npy +03001627-5f0f17c97234b510b4bb271cfa904d13.npy +02992529-4303a97b71a1bb894208dfa1c5fa1065.npy +02958343-2c6b14bcd5a5546d6a2992e9465c023b.npy +02691156-7d19ed245331582c3fe7930fce05ded.npy +02747177-45d71fc0e59af8bf155d75bbf62b80.npy +03046257-ef17c03de89a1ce3b1bb46d2556ba67d.npy +02828884-ae2605e9e8c47cbfad5067eac75a07f7.npy +03636649-ea8eb3f3d917d61850c421917af4a474.npy +02691156-2818edd47cbd2aa1afe30fe053f7a977.npy +04530566-adb1b651af34dc6f42534f02c8e8b5ac.npy +04379243-7cad0234edde1e90edd9ab1253e1a9c4.npy +03938244-218f86362028a45b78f8b40f4a2ae98a.npy +02691156-cf6fa8a054ed7bce5de04aad18bd94c3.npy +03691459-3dae5a52602e2fe58a0181490cb73cbc.npy +02958343-59c39dc0b47f338c25a535f4350429ed.npy +04090263-52fccffbaf93c3de71e857afa9df271.npy +04379243-343838f40056270a738e43095496b061.npy +03636649-d526a340408764d8ec0f2eef0b7e551e.npy +03991062-95fc36833cee2525ffc6e457221b9271.npy +02828884-49ab2a5a9005eab9d2b12aa6a0f050b3.npy +03636649-33d0e0731c771712eed9bc72790ab85e.npy +04379243-b9aeea4fbc8db8f3a08ae93bc9509b4e.npy +03001627-ef4f9cd2b498a10a614871b18a2b1957.npy +04401088-2703b7edaf11d79a6b203c09a4932f5.npy +02691156-a69c25f93540eaed6370c33da8a7988f.npy +03636649-35b23397ce08256e847d4e46a1f9f05.npy +02691156-4d3fca1d1cacc27beeefea58691b769a.npy +03938244-9451f92833603bd3630771196b76eab9.npy +03513137-fe47f10f637b54594e5e6ac3ef6bff73.npy +03790512-dd38890e85c6dd91138452c33de4a3d.npy +03001627-4ed25bf015585031490ad276cd2af3a4.npy +04090263-2150ef6d0dd9333ad1f5735620433167.npy +04379243-8f27f3da43406402bd5d9cd72de2e1b3.npy +02958343-dbd67f5f505a795161c6c61410fc904b.npy +04090263-914cae3548759cbeb351750c5651f2bc.npy +03001627-918145be863f7aeaf050758b903e6054.npy +04379243-81148566eef063bf6b1cb83d86c19bfc.npy +02691156-f44c0e1e55a3469494f3355d9c061b5a.npy +04379243-ca484b4b04e546938c9e244e3fbf98f0.npy +03001627-bfa5964a53730c783136fad73a1be67b.npy +03636649-9326c0efeda12e4642f42b7e6beeed8.npy +04460130-75f72747ea9ea6cc459aed24ffc76d42.npy +03001627-26891b80550301721a648655355dc699.npy +04330267-a6d6bbbf60c1a5829d76e54b77715d6.npy +04379243-52ed857e6f9965886b429fe8da4d4ec5.npy +04379243-23fa6ee1004e6c6ef4b6538438a0b930.npy +03790512-5037cad0901fb395b37378f3c85478b4.npy +02828884-190bc3dfbed8c9ad4e77259b0944c35b.npy +03001627-e3f1f899d63ab008492d9da2668ec34c.npy +04090263-58f9adb6b5065dd6ad2b8e02a4932f3e.npy +02828884-67bee18dec77f305e4af5827e8177766.npy +03001627-70ef2b4c4b287c4e3c00c853d8b7ab22.npy +02958343-e97d26f05a68f833cd89498c213958c8.npy +02828884-4769720a332fd899d2b12aa6a0f050b3.npy +04379243-3ba656a9bbc2a38ba22a3fbee2fd609e.npy +02992529-e48a2eff0b0d0a39a0eb5a85db887292.npy +02958343-1687b77b048d1aaf635b88185c42637a.npy +04256520-42dc453547b31f0b71a782a4379556c7.npy +04379243-af65bb882c818f9861dcc050524e1d17.npy +04530566-bf47c2f0b5d1c6fef37a9c459d3dd62a.npy +04379243-742524cb455a050f246c3d7aafc9b697.npy +02818832-b96d8d6400e319eb8d6ee799b331d163.npy +04379243-76b32980bdb108df1b17743c18fb63dc.npy +03001627-74500999671b4c99d7bf6fb68df7f786.npy +03001627-420709f63a0b15ca35836c728d324152.npy +03001627-b8f4ce34b44620cc9b9f2eb77f5e247e.npy +02691156-3b41c0837f22555871d03b466c72ce41.npy +04256520-8cb3672d113ac9aaef188758bf2e3a30.npy +04530566-8a3a23f85c4c4fc4f2ad837508eb2db7.npy +02958343-fcbf9e1dd55ab172ce27281f3b76d1f5.npy +04379243-b514d9ac72abf291914858ee6a7fe3b8.npy +03691459-da9317e5776ed22b732bda87f2718525.npy +04379243-449491be7c2586bf261efd8e659b02a2.npy +04379243-4dae8fbaa2411c5598e0d1738edd4f19.npy +04330267-35f6e6a770258328c7667da8fd923578.npy +04379243-945565e4684886ea9db6feaa7eb1b013.npy +04256520-a7908e8fb217aff63d6e282938a47f9e.npy +03001627-f2440b15f3773299490ad276cd2af3a4.npy +04379243-4cb84e424122cfa7b9148a949a91556.npy +04379243-e285d68fe197f968492d9da2668ec34c.npy +04401088-59a168f51f8d7dd9e59685727bdd9ae9.npy +02691156-7e092d9460157e968b96ae1a0a8b84ec.npy +04379243-7eef97cfb1b73681f1755b5047ed68f.npy +04554684-9b744b01aaed2d603ebd14c45634ff71.npy +04379243-37726dbb4357739bded526a7be77b30e.npy +02933112-29c6f3ce118576724da5feafe6f1c8fc.npy +03001627-6d30eabb3b56d8f897842bde7f51d0cb.npy +04090263-e63bbc4b3a28f6fce5f887ddc636e202.npy +02691156-395afa94dd4d549670e6bd9d4e2b211f.npy +03001627-9a75ecc1e677dfe755d57295806b2c59.npy +02828884-cd385ebe6cd0c1262acc546c71bed8c7.npy +02691156-2a2caad9e540dcc687bf26680c510802.npy +04379243-c0ef2c3ec04860e5b0e0dee6075b101d.npy +03001627-c1e8b1bd34874c83febad4f49b26ec52.npy +03636649-68b79b143cb1538c3087f84b199fd297.npy +03761084-f9ab08ad0d7d8bf626587cb13c78fb9b.npy +04379243-c8276ccc8fc631104a7dc8b5b1635d46.npy +03759954-f8b19d24d53102805495b39f8c929b31.npy +03624134-a966fb3045e83dec68661782af60b711.npy +02871439-b1696f5b9b3926b1a523e28192de797e.npy +03046257-b8c0cbd2f9c6e9269ba80f08c401fbed.npy +03948459-d13986cc2403a2034b4b3d2a28039009.npy +04379243-b588c0169924f8e32d6a698a89d341f2.npy +02691156-52764ef0877372245ddb9958cad651ae.npy +04256520-3bde46b6d6fb84976193d9e76bb15876.npy +02924116-5354c4fdc8585838cb2ecbd32dc2119e.npy +02933112-ba1230fc38050b1bbf1d236bec6d905.npy +02808440-9fe14f7850411851ccd0340812259a39.npy +02958343-ee9b3f31f40a0161b1fa0b2eada93a95.npy +04256520-33eb5d4c6ebbd6b1327289c00b6dc9ca.npy +04379243-a224010a537bc683104e417f71823787.npy +03636649-809ed642119aa5799e8bf807e902261.npy +04379243-6777718e193b45c4f2b931201029bc76.npy +03691459-d11f1c28831e85a920363e2561dd589a.npy +02871439-db5b6dc38fd82fa7cdfa73f789b383fe.npy +04099429-5408f17e0356fe547462fea59b81b370.npy +03211117-536bbf9f697bbe881df9770149d6661b.npy +02958343-b0f1e8e11aea5f622fdea40a56b4c57d.npy +03001627-d959b7666dc2fda41c691caf3fc2f46d.npy +04468005-21ae3c4b2d31b10fe810c01b1498aa2b.npy +03001627-1e3fba4500d20bb49b9f2eb77f5e247e.npy +03211117-4b29b207acce575dafb07a946d621b3c.npy +02691156-ed709305e61acf6a9b017c80f62649a0.npy +02828884-613e9e33ebb303b0e9e2744369bf17a3.npy +04379243-d5c3542c080d61462c45f75322191dd7.npy +04256520-784093cacaf5a2fcf3598efd14e493d5.npy +04379243-bd25dfa62c3c2cf772bd03149507655d.npy +02924116-b2204b9d48c30d7c28a7c1b14d47bfcb.npy +03636649-6dd3bf7b105e88e79d3154c451a33fc0.npy +04379243-7e215b6386f3fd4156d1d06c447a736.npy +03211117-2b70ecfd4dfd162d4a5f5cae871f39f9.npy +03636649-6be148a3e219dc68e6597d391ab6fcc1.npy +03636649-5f3f11372141da8def0b2fc3511b6fbd.npy +02691156-ce3c18550fb997d1107e1ecf38d6ca93.npy +04379243-ff58a52586bb1f692c95f6d76cb3094c.npy +03001627-103d77d63f0d68a044e6721e9db29c1b.npy +04379243-babb0963a0e17bb59cd0aef0207ac8c6.npy +04256520-3a72dc930392152e27787a85c3bfabc6.npy +03691459-a1118bb5b6afd77e6f11d65f7a59b6f5.npy +04379243-cda580f16378e12c3002761e7a3ba3bd.npy +04530566-71fb9e98e62ae65f6a8fde3b294e520d.npy +03001627-5a28539d01a0bbfa8ccbef2c1e41835e.npy +03636649-62ab9c2f7b826fbcb910025244eec99a.npy +02958343-714e69d3b56560ec41a5d15a014fb347.npy +02691156-78f32f279a50beea216b327569dd806e.npy +03001627-4f22f44c331ad407166390f4a0367453.npy +02933112-4c4043756b3aac2ba80ff03f6dc10926.npy +04256520-271cb05be2eb02c53b2e058a33951560.npy +03001627-4c52204e49ce9449492d9da2668ec34c.npy +02747177-5c7bd882d399e031d2b12aa6a0f050b3.npy +02958343-eb59c9376d1e04ab49352dd33f95cb9e.npy +03211117-9a64fd5e660a8725ae95d460d60954d6.npy +03636649-5bc478e9c4e0bb8180936c51aa7ffcf5.npy +03001627-d3f31fd0fc99f45e8b3f6b4a44a70e52.npy +02992529-5e6ee0c5d155d2298b13932a0c28e98b.npy +03001627-635906aade1c775df6cfab91d65bb91.npy +03593526-5d3c251a9c593929c268c38e2d88a8f5.npy +02691156-62c875c3db8bbc512842bbbd2f23c97c.npy +04379243-eb8bee4832b65d8655252a6eccfc24f4.npy +04004475-dd749c531fbe92ea882c1cdb32ffe2e7.npy +02924116-6d22bb9007a4b85e76dbcdc2c193a074.npy +02828884-78ff35f4e229d1306f08940aa2c35d2c.npy +02933112-d0421fb0b59291df7eee615e75bc3b77.npy +03636649-ff07372af062502af47e57eb62ec59ec.npy +04379243-d8e3d77a83528e5cdc1206c3c8202eef.npy +03001627-1016f4debe988507589aae130c1f06fb.npy +03001627-bf91d0169eae3bfdd810b14a81e12eca.npy +03001627-6db2255a51caf84e823e7e244bf84209.npy +02747177-658247fdcc33f379cb2a965e75be701c.npy +03001627-6dadf2259bec12c6a51c26819f8dbb51.npy +04256520-373b91686b4ac7859829306a513f9466.npy +04379243-d5d1e750bb492dd5391e4d6c585a697a.npy +04379243-de214239a28de6b9d00689b1b6482b4f.npy +04530566-f5812d814e114a185c8b6bf3197caaf6.npy +04256520-17bcd5b12b4c3f96d8f5a246b73a66ee.npy +03797390-162201dfe14b73f0281365259d1cf342.npy +04379243-4bbedd35668b06514b3c42e318f3affc.npy +04256520-36980a6d57dac873d206493eaec9688a.npy +04090263-5df56f5b5c339b15df46f2ecb43811d1.npy +03001627-fcff900ce37820983f7e27638e63d848.npy +04379243-7f28dee9ae1a39f1700e86b51ee00536.npy +04468005-deff7415ff1e0424b0b2e6e63122009.npy +04256520-9875190ff87d3eb6a510987e3d5db7c5.npy +02958343-9907db7f1b96ee9a8b55a52bfd1cce7a.npy +02691156-b26d238e335c59b567b13a456b2224a6.npy +03691459-343678f49806ebaef09c0ee854308ef3.npy +04379243-7fadae39394c5622c3bd24f986301745.npy +03938244-55a09adb1315764f8a766d8de50bb39d.npy +03001627-4a45b026317349130e916fac260c672.npy +02808440-38773e1ff9871cb33321831d2245cf06.npy +02691156-64a0f304fa3c113bc817819d30841d0.npy +03001627-59f9d0acb4cbb1465611cca00f1f427d.npy +02933112-2dbd6cb6a14805297812c3baf25c5bb.npy +04379243-9e97c5ba09adfc481b17743c18fb63dc.npy +03261776-6475d0da1bfe0006c78df40cf2e9097a.npy +02946921-90d40359197c648b23e7e4bd2944793.npy +04379243-3fff3e35a4b68352820018801b237b3d.npy +02828884-423a75018428cffd46c340938e2ff1c.npy +03211117-56a247c3688af350723edebb30e0215f.npy +04530566-201fdafa7287d2fe8a55122197709269.npy +04379243-3154c61c595bd600e56ddd87eb888f65.npy +04256520-fcbff3584d926ea3f13ce777d031b4b2.npy +04401088-1292caa1282ad8cffc3c4ad908ac06f4.npy +04530566-3c3161464bb86b2d3ece64552d44d319.npy +02828884-9d68ef4ac84c552819fb4103277a6b93.npy +02958343-54dfce0866b65c4778254b98f5b75eb.npy +04379243-a452252cd1112d346cacd811e7524a0d.npy +02691156-b64f57298cf3e4328b96ae1a0a8b84ec.npy +03636649-29f2e3d2815a018ba77f16c25b1f7f4d.npy +02946921-85fa7911905e932bf485d100eb31d589.npy +03001627-313bfbd7bc2d516e14d782de5388fe8c.npy +03001627-2aa1d5cc784b0b65f51f77a6d7299806.npy +04090263-689a9c745c6a776021d9cbc846872d86.npy +02933112-1eed828f325b45bf5f960aba13b9c630.npy +03001627-758173c2c4630eab21f01d01c8c9dec6.npy +03467517-624e93d139be86a7e46203898ce1124a.npy +03001627-30f862f46bd96da835836c728d324152.npy +04379243-6bb2a335613e8e2ce26ba91c6bf4ff82.npy +02828884-1a40eaf5919b1b3f3eaa2b95b99dae6.npy +02691156-35ae2885a0e645fb7843a50f3dd2047e.npy +02691156-f57c74e194cd2b2bc8727b27ee96a4b7.npy +04074963-cc5571508716b1e5808951ff5fb582ac.npy +02691156-5df7124460d8cd14fd17e1e0553418c6.npy +03691459-5ee19a13a20ab65edaa5dd7053bcd03a.npy +02691156-f3cc7d5c4089b842df6e254b0245ddcb.npy +04401088-8ea128f9035474394cb30fc798a4d976.npy +02933112-7fd938d174a81474b4aed946870413c3.npy +03001627-ce7cff543f8cd89f8d1dabf86742ec3c.npy +03001627-f595abef9bc7320944b2fa2cac0778f5.npy +02691156-aa3a317001bb8617f7fe0727acb55c39.npy +02691156-d5e01850a9d1f3ac5fb48d488d5dfafd.npy +03001627-ea06ed485ab0833a2ebeb1e6a8111f53.npy +03467517-437b134bcf55f69e9c66a84603388766.npy +02933112-77df125bac962fbe4c5470734f591843.npy +03001627-c06b5a7aa4557182f51f77a6d7299806.npy +03624134-431b87d480ae0699a95c6095f89cd899.npy +02691156-ecb0d8d1c592bcc11bee3078a673c2ae.npy +04256520-6caa1713e795c8a2f0478431b5ad57db.npy +03325088-d1971a4133203c8976c18e71fd49c4dc.npy +03001627-69d6d2835bdf709b6df61a30cc649b07.npy +04379243-60f273bb4993eac8d4c42dd307b636f8.npy +04379243-d732f1d1e8a8510ff68e7a883fa7f8e4.npy +03797390-f3a7f8198cc50c225f5e789acd4d1122.npy +04256520-1bbc63fe00a7c3e2bbc7a6acbd8f058b.npy +04379243-6170a0a35febdd19129dc72c6879c0ee.npy +02691156-14ec1da5f5499d83bc0909d98a1ff2b4.npy +03636649-4bca3194ec4308a837b2bb75885cfc44.npy +04530566-306aa8588bead6f3ccbb877d944b8a64.npy +02828884-3250f6d70feb1e77d2b12aa6a0f050b3.npy +04401088-e3291bf83de108ad98b4ae7d0ad0f9.npy +03001627-69e6f0a5e903cda466ab323d8f805a57.npy +03001627-f4cec47ced59d95a3002761e7a3ba3bd.npy +04330267-7325f7bda50b7dc41965be83b7745a.npy +02691156-52e27aecdd55c1bf5b03388497f76a9e.npy +04256520-4b529738e7b5f910288138d7d3420148.npy +03624134-6061ca49f854f6e5e889573847ae2a32.npy +03636649-3591b4c764217d2833e4e0fe8cce118e.npy +04379243-15b495c101881d96e2367b9e27f16a71.npy +02958343-f11d669c1c57a595cba0d757b1f2aa52.npy +02808440-ca14dca61e50a05b3048063251585afb.npy +03624134-34cb3fade2a5de47ffb638a278d56097.npy +04468005-dc71a910775b2106995425f067333fd3.npy +03513137-1f3aa976ccfc9e66780b70108bbf4c51.npy +02958343-127b9ba77b54ba59bda733a39f84326d.npy +02958343-74f7b559d6af926012f2e446484bbaf7.npy +04379243-323ed7752b2a1db03ddaef18f97f546.npy +04379243-4c4675bc602b2a95febad4f49b26ec52.npy +03085013-e9e5d448b7f2da86edb8bbed3955f432.npy +02747177-fe2b3c0ca29baeaed2b12aa6a0f050b3.npy +03636649-e15defcb3dd448094fffb007974c9976.npy +03001627-efc62fa0fd71d739d42ec7e303174a87.npy +03001627-b9027939e6c71d844d256d962a5df83b.npy +04401088-c7407877d3325f7f391258277c122351.npy +03593526-29b41e593f8c1db24b3c42e318f3affc.npy +02958343-12243301d1c8148e33d7c9e122eec9b6.npy +04530566-99acfc63ec4f4ad09f97ca916781e800.npy +04379243-35e5159ed908c99c8fc6229eb64e56a.npy +03001627-c953d7b4f0189fe6a5838970f9c2180d.npy +04379243-3b7fc97192e483ebb0bf045ee98272fc.npy +04379243-baf006da82e4007a2d79e73bf7425e50.npy +04379243-22f298bfabc8982691a76c36d0ba1ac.npy +04379243-2e4fbab46e264616d93768e7b9b1eabf.npy +02958343-90ba6416acd424e06d8db5f653b07b4b.npy +04530566-108d62bb197c948c60c7b57bf6d67c74.npy +04379243-e7abcb9f3d5876962b70eac6546e93fd.npy +04379243-f7ada05f68013e2dbcedcb5f4c7257b9.npy +04090263-f730043e6a9843befe2133a365e39c7.npy +02691156-735466165c04f71f62b600da24e0965.npy +03636649-6c19af16f46fa4699b2dd2b9747d7d2e.npy +02933112-bb5c331b32e39d0d3ec45bd2bc895504.npy +04256520-f5639e976f7b8e70a6fd13ab3827d508.npy +04530566-d4fcf6486fd18a4982266a2b21a2294.npy +02876657-9edfe64416a9646e30612f5c0ef21eb8.npy +03325088-84496aa6efb270c9b362845c6edb57fc.npy +03467517-50647eda7b5aec4b1994831be6654b30.npy +04256520-821bebd7ac070a0550fc88ed745bdb67.npy +04379243-d4f8060cf95edeba6ac2b0edda2c907b.npy +04090263-5c59e7cd62f20a8bbb0bf6d0a9fb50c.npy +02691156-2f5c1ef50794aa92a55d095b876bb574.npy +03211117-d31610e1a17c5d31631465dbc2e64814.npy +02747177-5f14eed855c48a7f63b2acb037dfbcde.npy +02992529-2725909a09e1a7961df58f4da76e254b.npy +03948459-1226a05aba30d0987deae9192b6f5fdc.npy +02992529-ab96be5a6e3827932a6d73bcecfd73da.npy +04379243-ba993afc907987b33087f84b199fd297.npy +03001627-7121296a75c725aee8f8c11a24c52ebb.npy +02691156-62bd247f0e8081a171d03b466c72ce41.npy +04379243-25aae534f3aadc9c9aa9d7f676c1fd7e.npy +02747177-e8878aa23064c704ad5067eac75a07f7.npy +02808440-c66b0bdad2628150ccd0340812259a39.npy +04379243-67d11f49bb73a66535836c728d324152.npy +04256520-9428c331f2230e33a066c1f884f0378.npy +03642806-1ce087aba42caa73b8152979f6537fad.npy +03001627-453be11e44a230a0f51f77a6d7299806.npy +04379243-6cb965ebd6fe2e3bd8d12f352b5e1839.npy +02808440-6abb270bc9fc54fe4c62bee40dcdc539.npy +02691156-fd8d7742ee03905df446f92b52bbd82a.npy +02691156-1d4f988b009edadf54a2210c7b2aa25.npy +04379243-963bfaef4271c4e6955824885d6e7dc0.npy +03001627-b9415bc240e074837e76245c0a9e51ab.npy +04401088-8b17963baf2e54f87a0b781a26650bed.npy +03001627-fc07472e4dd1b6698ae97f14e63e7e01.npy +03001627-4cec451d0ffae39b79e99a4e49de900.npy +04379243-b160e3f80850d23755f46d55537192b6.npy +03691459-b93169c2360aa02ea14443313213c384.npy +04379243-594564c315e37c57925b56a4db8bb70e.npy +04379243-e791f274c6cc7ded36a36f8fd7d27134.npy +04379243-a6543278e970aa7a396d452ec85b027e.npy +03928116-282e61eed4ab9a06bd049a07b95e6725.npy +04090263-5ca0dccd8b0f6357d1987c07c912c6e1.npy +04379243-d9a0b526a354225dad1da5f59ea6f4e3.npy +03691459-9c1bc89152d90500c92750b56fccbe69.npy +04379243-3736ae6b32d288fad832a3fe59576848.npy +02876657-dc192dfce3556031fc0310aa34dddc94.npy +04256520-7b0f429c12c00dcf4a06efdbafdd7ea.npy +02828884-fefc87e051b4776a2d8a6d5087fd263.npy +02691156-a1ce38065b93520335fc197bbabcd5bd.npy +02933112-10c484963692d3c87d40405e5ee68b4f.npy +02933112-81bef552e83476ad3da27ece6ae88fff.npy +04379243-711de3c464c11233a82ebea018a340e4.npy +04379243-7cf3167e5a469fcb4c7384dbb75cab0d.npy +04256520-8c29f480d31a1a521908c34adf823c32.npy +02747177-b4b4f2d95de89e88b693b28f9c9c2143.npy +03046257-8797071b5219973daf7c7ad2549a1b15.npy +03636649-cfaf30102d9b7cc6cd6d67789347621.npy +04379243-e7bf775ba6774a2e278d386bfa54545.npy +02691156-96600318559071d48caa71b1fbf7fb98.npy +02828884-89326f54e97f65d82056b4bd5d870b47.npy +04379243-2f07c59d4099b5762241dba92389a637.npy +04256520-13990109140043c919fb4103277a6b93.npy +03691459-7f7ca259133096cc4d8df313232fc497.npy +02958343-d07c8208ad9dc35780e74058ee862f05.npy +02691156-6d6b6777cf1c15106540a0ff73700634.npy +02933112-4e0cc6a0dbeeb87df51f77a6d7299806.npy +03991062-f7a32f51a03a37f3e422be95e44ce930.npy +02992529-db058088ec098d9bdfbc59eb47b047b3.npy +02958343-ad1d30f2294f40dc622ac2f50deaba1f.npy +03636649-9a447967a9fb5938bb3deb7fab7c9b7.npy +04379243-b4fe4d5be595c1158c1cf3f7d7f0373.npy +04530566-e74a9275bf24d3e47dd35385411db37c.npy +04090263-563097fac348e6463d476be0564f2b74.npy +02828884-f343599b3eb41ae3f155d75bbf62b80.npy +03642806-9a0cafe6dfafe0503fe4aa36ea0cc020.npy +02876657-5872e807edaf985878fe949fc1419876.npy +04090263-2fda76fc28c9133d8428b8de1af34c50.npy +04379243-6581edd8565321685512673aa47c7e3d.npy +04379243-f37348b116d83408febad4f49b26ec52.npy +02933112-2817480c23e4a106c59350d819542ec7.npy +04379243-259125651db34085a4865f78beea84b7.npy +02871439-37ed10ebcb9c0cbc932ec7aa2da5961e.npy +02691156-d3dcf83f03c7ad2bbc0909d98a1ff2b4.npy +03261776-937cdf200b33bdfd1aec2282dd8bc87a.npy +03948459-edec08542b9312b712b38b1d99376c0b.npy +03790512-31a96fc694f0e58cd5dde04c96fd8146.npy +03001627-beb4c42cfa1c3b282811d30bba54859.npy +04379243-33c8b21a29bef56645de94e1bc93a4f6.npy +04401088-c3b9cb70c6a80ed686a04ec9e4169973.npy +03467517-6f3e9247e77897989ce06ac269757e69.npy +02808440-ec840887e7cae5b6ccd0340812259a39.npy +03797390-73b8b6456221f4ea20d3c05c08e26f.npy +03001627-516d94f2658b2258d79b19c7c4f0e293.npy +04379243-b8ad178c1d78980472dc9d42e683347.npy +04256520-1bce3a3061de03251009233434be6ec0.npy +02691156-71a3888c2229715b694188e21796efaa.npy +03001627-a40133bc1af575291bd0966183650a4.npy +02828884-e223e77b8db4aea17d8864caa856253b.npy +04256520-cb71cb7b36dbcb6f826fc8d57346a2e4.npy +03001627-546c4449b8001f0815d1fabef5f236ab.npy +03593526-dd37047caaffb379f9215f842248bc25.npy +02958343-1a87a329781b15763820d8f180caa23a.npy +03001627-177849848dc83fb9cb85ba5866080618.npy +03337140-97d83d7e969a309991c352d02061b3f7.npy +02876657-9fe7e6a7bf8ca964efad53eb3f0b36fa.npy +03337140-e4497669bb1457c655b2aedb5bd199c6.npy +02871439-301c2df72793fd33d42b9650f19dd425.npy +04460130-df8591577e0ef1095ae4226ec4ca9d4d.npy +03001627-58d39cbcd842cf6eaa90ad3e0254ffab.npy +02828884-bdf722327e02a0f0ce7719c693f5802e.npy +04379243-91cf4849ad3f7ac2a81005b904311cb4.npy +03593526-a4f56aa9a291cffb80067e3fdc6db24c.npy +02924116-ea3e697424a86f89f607cd34b3ff94c0.npy +03001627-bdaaebf065b112da492d9da2668ec34c.npy +02828884-a380e75d8efcb4192f550a4f461edf6b.npy +03691459-48bf5d4693bb7ecfb4bf1edf2dd92af.npy +04090263-3240b627007008146a2345809e2bb169.npy +02691156-60af3c930040c8b915d4d2fdca08573e.npy +03001627-eb59a4b8deddc6f659fe320c015eae2.npy +03467517-83e4f00f3c5b50ceb470346f25b26583.npy +02958343-e717bcb56d012a48b1bb46d2556ba67d.npy +03691459-d04ece855d678568d74f2f4a7f5598c2.npy +04379243-a68f06157d6ba8d4f51f77a6d7299806.npy +03001627-38e904bee502bd31e8b2b8dc0c816caf.npy +03928116-39d9f17c8fc14f6b8dd4b8aba823ee77.npy +04379243-4506f150e4f43633fab6e40cce6926d7.npy +04530566-85481518c0938a6eb1bb46d2556ba67d.npy +02691156-8de793e2e964f40a26c713777861983a.npy +04090263-97a75366f7c6ef24b8d6e958e0707d71.npy +03797390-10f6e09036350e92b3f21f1137c3c347.npy +02958343-6c7ed2d306fc7cfa4ccaa6b556a5ccc5.npy +03001627-2bd045838a2282ab5205884f75aba3a.npy +02992529-312c430f8b1a3fc80249ed612e14df4.npy +02691156-5d1d88958bd1c9c573328938c756eb4b.npy +04401088-e006061cc51617b9498dffe5de12eacd.npy +02828884-f061967a9b5ab9b6fecb38606c52659f.npy +03046257-ef6c1b823990c0f4f51f77a6d7299806.npy +02871439-1ecd9316bf586354ae25f6fe802a8997.npy +03642806-40e0263822860cc5d69e26904fa68e7f.npy +03001627-bfa242a09f35dcaa38fba5f798d10731.npy +02691156-14c954d5d3c8e954b6b87e72ead132ed.npy +03001627-97df0e7773e51feb331fc18393f04d2a.npy +02958343-af2f10112f943f54c730b513773cf286.npy +04379243-ce56b5a3ab23e12489aad4e9e4feaf9f.npy +04379243-1c00da8a9bd6f7403b846408f8d3469d.npy +03467517-a2c1ee6a7ddb50a493f0194265a9746c.npy +03624134-d9a9c77250224c5c9037640567c760d8.npy +03001627-3622d983fd6d7b98e3a73d090627e9ba.npy +04090263-aad61c4d490d4a8b6dbd8278fbb6bf38.npy +04379243-3c899eb5c23784f9febad4f49b26ec52.npy +02691156-5abe1e80846dd485c3e7213e9e8493f0.npy +04379243-58475b1b20ece0c5eeb8d422649e5f2b.npy +02876657-c4b6121d162a3cb216ae07d515c8c56e.npy +04530566-d5c7613bf466d33e94daa4565dd30535.npy +04379243-50480d9733231475eaf288f952624966.npy +04379243-1df409cfefbb51658b9b51ae4415d5aa.npy +04090263-b3ccd1643cffcabce37934d75f36098d.npy +03211117-314bcf37588dac1ca802f44e0266ca93.npy +02828884-745ce171571074decb2a965e75be701c.npy +04256520-19dd57f04ed04422c528d33bca1ac2.npy +04379243-4c7931492b41f960d50eef20e0914a48.npy +03325088-f4c37e34ea1d940a50da8b99982a3057.npy +04379243-77ecc55547840f06d42b9650f19dd425.npy +04256520-3a98a93f381ff5fb4b3c42e318f3affc.npy +02691156-8ac8c21b63ff535fca8607f540cc62ba.npy +02958343-c4f6540454e65939921cb81cb1632a5e.npy +04379243-cf24aa524055dd5ceebb0db1929cfe93.npy +04379243-8b0480b9d0bffa6e8d740231f5a3de96.npy +02958343-9ff9c8287fdb49be8b55a52bfd1cce7a.npy +03325088-607ecd0df535e60176c18e71fd49c4dc.npy +02924116-3b90b61ecb49cc2c65b80aea88017aa7.npy +03001627-33bfe7ad9544eb93d7f25634a7c65cae.npy +03211117-dac5376988db376b7700ed9200d31a49.npy +04379243-4b887a7bdcfbc4ca7e04e68609264bc1.npy +02958343-173669aeeba92aaec4929b8bd41b8bc6.npy +02691156-bc3f4d2bf11e1c6382328b5e05417037.npy +03001627-c5d58dd0119f0e49503aeac2cbb6e06a.npy +04090263-2689d78a4fba15bbf3998727b15249db.npy +04256520-e70fb6dca41fc8bdfebad4f49b26ec52.npy +02691156-74b0d11834cd8ec258a4fbb6b625be1.npy +04379243-34e260786b78eef475e2a70bd3d8ac6f.npy +03636649-81dd7cff35cfcfba4b3c42e318f3affc.npy +04256520-f644e0ae72dbe83d72ff9ec64cb596d.npy +02876657-725c3906071ecad52701ea82a42c662b.npy +02801938-1ed60448a8cc4b916e6624d94e2e0a1d.npy +03691459-2ecc5b85b343b20c2ca06fd2350bea43.npy +02828884-6f630f561e5ae2a5423efd8c02bd12f7.npy +03691459-6aa3bca1ec6b261edbddba07a492a0ac.npy +04530566-1f4e0613a3ec7b5a975be43df8325f3d.npy +04379243-565c8256aa446f152685733c782593df.npy +02924116-7c79103dfd1dada03690a69e4cb84963.npy +03691459-6d28e2683df5f013c9d5b08933b9e0c1.npy +02691156-bc140e3c54b27bfabe13ce34aa7c0c1c.npy +03001627-6f194ba6ba254aacf51f77a6d7299806.npy +04256520-3ffc1c26db51a3ac948a3bd895ea5ecb.npy +03001627-f029adb6cdf37c402b339ec555ba3bfc.npy +03001627-e4b40369894a16ce6821a1e68ba5ebab.npy +03636649-4ba237c2c40313f373b3ec02b97cb0f.npy +03001627-8fe0e6780b3dabbbb098f5649ee97d24.npy +04401088-9dc1088c4f5de29ac78df40cf2e9097a.npy +02933112-382b6f8e93e1f576149dc0f3c5ce899e.npy +03325088-4eca4ca3fc1a63ba50da8b99982a3057.npy +03636649-e43996a9154a48e0db039d8689a74349.npy +04379243-7dceb027969fed5e2c0a7b8ff2381a5c.npy +02958343-e7c4b54fe56d9288dd1e15301c83686f.npy +04379243-cf63d0c639cf4d36da1aea1fe709296.npy +04530566-25677ae07e0257955dd2c581ea62184.npy +03001627-440e02f574afa478ac38b834d5dbcdb3.npy +04460130-a07c8e2d0127b26195405124ff912ff6.npy +03636649-44820a27f86f13e7e420612cf7bb547c.npy +04256520-f8998de3b4d36dea4b3c42e318f3affc.npy +04379243-dd4f28a0e0d3f93c614a26402360d21a.npy +03642806-2134ad3fc25a6284193a4c984002ed32.npy +04256520-a28a2bf7c899fa38baaf4e0b7520fb81.npy +03001627-89f8c12dafc877009f8c3d2002c77ddb.npy +03001627-5bec8011c4042baf14038d588fd1342f.npy +02924116-59db922e827def242aa8b7caea8a1807.npy +04379243-57fd351d970d60fd60a25ec0f32e89e3.npy +03001627-4344509d0442364d3f9d6e0ade5188b0.npy +02691156-24968851e483feb237678474be485ca.npy +02828884-5cce62b38c0486d74201e10f9a6fb035.npy +02691156-3e0561d70c7fd4f51c6e4e20f2b76086.npy +04530566-3625522559a753b78dd2cbb9124e6d20.npy +04379243-1f47bcef63468cd9b90b306cee0c8c91.npy +02691156-a4391c7977d990142c20743f866e1a6.npy +02992529-3dc95447a57f8d06c1e615a94e798da1.npy +03624134-ced1a454c0e5fadd567f010bb1e0a2a4.npy +04004475-e0b4fb5f282bab11d18dff33f5d779e3.npy +03001627-971a98d242991e2222ed3259ee7e608a.npy +04090263-4e4b42da5513ecd175d25d68bfc74949.npy +03001627-e6b822bea1d5a5a9f7b783634bf3f92f.npy +03211117-fe75bacab7594206ab0b172d4dea80cd.npy +04530566-ae93355992a29c428064e4301e947b0d.npy +04379243-15dfec695110505227c1f8d037f650.npy +02924116-fc6c9de9bab5154e481aa8b5531c68a9.npy +04256520-ce863933e9e5193322d11432250c3331.npy +02691156-6659e72d40cef80be07c29b23ef67611.npy +02992529-d7c350e5d29074c9b4c216fa1de7d5a1.npy +04530566-c46aa66acaffc37af4a06efdbafdd7ea.npy +04379243-2c6741a965bc580072f9a9353d57f9ef.npy +02958343-3ada93d04b72256df63ee8a34069b7c5.npy +04256520-8159bdc913cd8a23debd258f4352e626.npy +04256520-ad1428e73eafd4a6660dac8da5753e14.npy +04256520-1ff1912cc74a76c3b2152dcc3ff6a477.npy +03001627-ca1bf3f8bac2927cefda51b1bbd149fd.npy +03001627-323bae92774d8def78aac1ce4ecb73b6.npy +02958343-4af41048861594b4897e805df74453bf.npy +04379243-6762370303178268d323d6bd8db8de5b.npy +04379243-7aba44f7a5ca1fd9a35da04de92b0f11.npy +03211117-2c4bcdc965d6de30cfe893744630a6b9.npy +03691459-414fac13be35799d19077496eff9d4b9.npy +02924116-6aadcf70fc49873ae14cb463f23a6803.npy +02828884-1f0c3038d2a9bb391b305ee09b6b9906.npy +04256520-acf23f78322f00f219fb4103277a6b93.npy +03467517-6554f6429eb7b67585e3c97721f726e4.npy +02958343-8606a6353a2c0f7a453660f3d68cae6e.npy +02958343-51ae6558e6914920253c03b7df20edd5.npy +03467517-a5825f1ffa48c72f3754416ec24e02bc.npy +03636649-d13f1adad399c9f1ea93fe4e1ab627a2.npy +03467517-bece1efdae5f94d0e4ca9fc57c06f078.npy +02958343-8320c70894c3cdfdff1370452e3a0154.npy +02828884-cf24c6b52b12c56ced8d4f003c2a833.npy +03325088-9df6805f555e98fe944fd4e41cc8d418.npy +03691459-a29485bfe6a688f0ce3ab2c820261e42.npy +03991062-bedda59ae84775aa37b2bb75885cfc44.npy +02958343-1328a95d69cefe32f200a72c9245aee7.npy +02992529-a2dedd1d1369d4ae25bdb70a4d3731d4.npy +03928116-b11213949b59e6bdfbed28a02a11bd9b.npy +04090263-b8970e3d0eaa2880dd0a2071dde26395.npy +03001627-1d1c829a54f0ae426cdb122727dd360f.npy +02828884-49a07e9db250cb5ea17702c02a7c3b1f.npy +04256520-a0bb04577e35ca2440ea7eb155c4e420.npy +04004475-9df2e49709f014d242eac36fac92c11a.npy +04379243-78a81cbd2a5720d93a938fdd57fac3b4.npy +04256520-dc6308addc91fd9eb9e8bdc9c4a49aa2.npy +03691459-db90e043486f216ead1d87becf13ddd9.npy +02871439-3826a129f5d8324446ebf4f1147c3f0f.npy +04256520-b672f2487b04c2e72a7455a9948f4f3c.npy +04379243-f87ef5a5c13e7b29d810b14a81e12eca.npy +02958343-efade459a90b2b143337cb9d908ce86e.npy +03046257-73fba47ad11432dd14daed0f93827804.npy +04379243-c0ec7cca02bd2225f1783a44a88d6274.npy +04530566-5a84b0529edd7101d3ca4877ecd2c01b.npy +04256520-ac96d2fa0e2052a790a9ce3e4b15521e.npy +04379243-d0220473a40678ad137619fe8083152c.npy +03691459-113aa3b68f515427205b075c6f63f661.npy +04379243-8f73278956fecb80327289c00b6dc9ca.npy +02954340-18387b36aa7b2d4af0d11ae402ef940e.npy +04090263-1220880371b176f9a06a81572261e82e.npy +02828884-d03199998c84839a844cd843a27223e5.npy +04256520-77371d342cddea8d8b424343280aeccb.npy +02691156-b87cb85be0d8eedb44bf3710e93f8cf7.npy +02924116-a6799d14b9d42a85d4ccd960d9711d72.npy +02924116-d312082e00d08d43aff1be9b3d197e11.npy +04379243-5b04e4677f1a45d3609211b089fcd35a.npy +02958343-3ddda21d4496fbc693680c5a9a367b4a.npy +03001627-bfbc5e6ebe1813a5d9fad8aba2c312b7.npy +02691156-5eff54a76d8ef89d7e1c97634acf0214.npy +03991062-8a88fff550a841c5fc2b7781f0f02585.npy +04460130-64f50754e6b67305ea3f1ffc49ae6b01.npy +03046257-67f8adff4cb252bbf269315e1b3458a7.npy +04379243-bcb51814564c9308b27067c40cfa2f80.npy +02828884-5c31950da8e2eb09929ce23741435ae.npy +04256520-163af537cd485a75e73748f506e4b955.npy +04379243-516f73ee8b530042593ebeeedbff73b.npy +02808440-11955ce486dd9b6954d7082b34825ef0.npy +04256520-31b21dc34d770ce8dca17035ebddd61e.npy +04379243-bb521fb4f1ec77a0ebf17edfda20712b.npy +02691156-284e6431669d46fd44797ce00623b3fd.npy +03211117-a57682cb8ebc224eedb8bbed3955f432.npy +04256520-b821fbd0ea6086ce9670b99b613138c4.npy +03991062-b4bc7d35f20935f9aec59741c69cf7.npy +02691156-bf54b050d092d1e35b5e900e37653d26.npy +02691156-3c98bc293d33375a9a6e43b878d5b335.npy +04379243-13f7210d5d472518febad4f49b26ec52.npy +02871439-45f111fa4aa4bacd6153b9900b1cf5e.npy +02933112-bd7cae3c39773a4ed0a0c43e4971be14.npy +04379243-4eb395cd5dfe658318a93a45bf780820.npy +03001627-1f8dde91813456e87e777e4db5dc272a.npy +04530566-4d5d231a701433110a313d673794913.npy +03001627-3bcbf7c8c8eef525c5b0fe224c67bd68.npy +02933112-cb75de930881a633f51f77a6d7299806.npy +04090263-f267ad7ff7c3a5dd763221be209af140.npy +02691156-b74611a3b3b3ac72ca8607f540cc62ba.npy +02924116-c327201f40fc6a03621930cd3ccccaef.npy +03001627-3bbcd9e945c6ceb8d3c29b715a9f3afe.npy +04379243-59d780e98c0c3a6f41c78a933c3b0bad.npy +03636649-62a5d7a59b87d150e6597d391ab6fcc1.npy +03001627-3372fd42f389a36a762ec387b772e9e1.npy +02747177-38418e5ea375d66a56f6fc4b4ce1db04.npy +04004475-4280940636bc0c3686f436bb2260061.npy +04379243-d430b0c4136e87327e72463702194870.npy +03211117-d96fda816cfd848e9aefc6fb585e9617.npy +04379243-bde0b499bb218666c6f42ae239fa6819.npy +02691156-5676893c90ec0f6dab81b7399bdbb6e2.npy +04256520-e37b46236accac968cbb8bac2032149c.npy +03001627-ff6e6b7b7c7f1c0f15f78c98555ab41.npy +02946921-147901ede668deb7d8d848cc867b0bc8.npy +04256520-c602f932c692ba2714038d588fd1342f.npy +02691156-124a579e0635b8eace19d55bc5e6a406.npy +02828884-397ac4bbb11796902d92929fa159facf.npy +04090263-56b409a50c8404afc24d00518a3dd6ec.npy +04256520-a23357a29af9f63ed26fff8ae28c5292.npy +02924116-4c5cae9a12252e1db1626da45836ca54.npy +02992529-a9c181d7378f92cfbc59a3627d9edb6f.npy +03211117-7e1212c48c877b87eca8a38e13335285.npy +04379243-9bb816d6a3517a5ca74c2333655a11dd.npy +03046257-7b1f529f00ea482a788a9e26a791a23a.npy +03636649-ef612752f6192e8d29eb9d04ea723179.npy +04530566-2ceb5d34a15b73393302308333adc4be.npy +03337140-abd27e76be6194d84c3aee8e9d3a6ffa.npy +02818832-e2532c6b9a56fe984bef72f03d7235ca.npy +03001627-83f74ff9d96c4d77bc5804ffb7fec416.npy +04401088-2ea4a3d502b12c61707fb0d61a11775f.npy +04530566-973b398bbcc97c3fea9bd4954e1c8c49.npy +04256520-1c4bfbfceb9e579c708f430fbe4ae8ff.npy +03001627-646ce5490817ceef4b6538438a0b930.npy +04090263-73903a9846293890a1ce1dd4c7e01188.npy +04379243-70a17261539dd92fce1403db8f7dbbbb.npy +04379243-cdf0a34dc3504e40643beaf431c0975a.npy +04256520-7d4113d5cbf4ba376efe57da6d3d385e.npy +04256520-e3c42f99d05348c6d456f2c60deb666b.npy +02958343-fe2e5f0993bbd4726fadd0e0ad926818.npy +04530566-1dce61f6dd85dc469811751e3fab8939.npy +03325088-63b97b5f2f209f667ef3547d02ab05dc.npy +04256520-af9d9a0ffad9c2dc8a243182cace7dbe.npy +02933112-b2b89d3ec5918f69c59350d819542ec7.npy +03001627-e682c43e2f4e7463d0ad32b8d8cec005.npy +02924116-8b95a88f6be4038841cefd10ce5d6cc0.npy +04460130-f679821836f140f39ebe905ef4009f84.npy +02958343-c558c64b6b97a529658e57fd275f6bed.npy +03691459-71b4fb2d151a9d70fb0a4dd466ef3d66.npy +04379243-fe99a1127734f7852b70eac6546e93fd.npy +02691156-e511258df02edf1046ed10e8f7fe336e.npy +03001627-af34090f13146fef15afaa91253fa857.npy +04090263-99957708f69cc13acd0bf1b7ed0a63c9.npy +02691156-52712e1c07ea494419ba010ddb4974fe.npy +03948459-30195a2d2fe56a1f6887cd98a5557c7b.npy +04379243-c93aa39b76980ff655f46d55537192b6.npy +02958343-e7141fa81a2828841e8bd72b0feca0a8.npy +03636649-fa6f034a8beb74f6fcb8d8c6d4df8143.npy +02876657-e90e0506fd00fe93f42d6bd378df1c70.npy +02747177-fa723633a3cfed271e74a5e93d408a1a.npy +03593526-930e0e91518dedaf8b5a342cfa6159b4.npy +02958343-e66cb97aabb79193da5cb3be8feeaadc.npy +03636649-ed4f7f214ae7042cfcb8d8c6d4df8143.npy +03001627-1cd152cfd71cd314e2798a633e84d70b.npy +04090263-350c4bccc1509f83583c7e128cdb4e36.npy +04090263-c26b3833f66cf4691756b5d674acc4e5.npy +02924116-b52d68042ec5e75e193d7855ecfc1bd3.npy +04379243-fe3a8b30aad625ceec56aed2da084563.npy +02924116-21675fd70633384bb1626da45836ca54.npy +02691156-b81339a2f1dbc0de9598ceb95c7f0752.npy +02828884-2e8f1b6cb9b4f568316a315354726289.npy +04530566-3632e9d36e280dcc6a6cc078f0eef937.npy +02691156-67d9607d84fb51435fc197bbabcd5bd.npy +03691459-54fadd7a6c5c04d752560296120d4cb.npy +02958343-69e99923c3cbcbcca9fe1734a6086750.npy +02828884-a4d107815780161ab7ea82317702e856.npy +02958343-aebd98c5d7e8150b709ce7955adef61b.npy +03001627-40ee8ed17f6ea51224669056e0d19a1.npy +04256520-221e8ea6bdcc1db614038d588fd1342f.npy +02933112-984c969b9948fea738e43095496b061.npy +03691459-f64068aad93d502abd1cba733b111584.npy +03211117-5fda7abf1b684ae8f464a4627ebb5e55.npy +03325088-9ff3b5c3aa7c2d5c36fb70296e45483.npy +03211117-b569ba9d9d74e7d5184dd44a99578080.npy +02958343-7e7b757052225615a73f47f4261c01dd.npy +04379243-2a44f4def2a20e7f4b3c42e318f3affc.npy +02958343-efe74cae23f8061382fe9569faf087db.npy +04379243-50bf2749c1963d319d84faf1493a1f98.npy +04379243-c5ea662fb31f56cb2a155afd9dbbb0a.npy +04256520-d84ffaa12c52d6a9994626ba7fe8ddf7.npy +03211117-c19d616f13bb70d39306959137da47ca.npy +04379243-f18c9ab4ebdcdb8ac8595ea32135ffd9.npy +03001627-54e2aa868107826f3dbc2ce6b9d89f11.npy +04379243-9cd301c49dd65c68819b97ced0e92930.npy +02933112-ade25be3b1ee38bff51f77a6d7299806.npy +02691156-422700fbef58a0ee1fd12d3807585791.npy +03001627-a6ab184a68bc67d179b3e1be3524f72f.npy +03325088-95d17d2a88d82812b362845c6edb57fc.npy +03046257-8af7cb8b42d0c8b1f9e8cd846ef13776.npy +04379243-1f2c84d387bd1af9609fb05dbd8681bd.npy +03928116-90af8109ae86f1d4f7895369e50c9000.npy +04379243-2f257e35ef61553b63c9ead28992f1.npy +03467517-4d98e1ec983e315f8e7905003bf56417.npy +03261776-c6d19db35f69bae7b6d9c2cee7f2f72b.npy +03211117-68dd0f25329c5779be95cd31e095c9d4.npy +04330267-650ab459ed284b4349bd139dfeecc324.npy +03991062-eb485c8d5b0acd5dff67c12005f72d2.npy +04090263-10439f1f81fbee202be79d8b285c1e.npy +02958343-606c0050a2ed4e19d834dead2eb68d68.npy +03636649-525109ea19096fe8eeee03ae21af2d39.npy +03325088-bb5589eac797c14db362845c6edb57fc.npy +04256520-bdbdc31c4ba48868bd91edd7a65c1323.npy +04530566-7f05275eddecedd06f3d18c7cf5f8b6.npy +02691156-d59d75f52ac9b241ae0d772a1c85134a.npy +02958343-348fe55c1976b64c45aa033a20004998.npy +04256520-bc0971df7f259c581d38890680ce527f.npy +03001627-ac9cb6f769bf90c824d8364776ff163c.npy +04379243-7853c9da0f57af87e649091ae21aee74.npy +02801938-9e2a1751b9129b1132fd0b3f17b0d6c.npy +04379243-58f8fd169c9578e62f81cb887dc35578.npy +03001627-7ad134826824de98d0bef5e87b92b95e.npy +02958343-26b7a9c6c7e74829eabc798aaf5f039f.npy +04379243-a59b2884db9574cd1a72c98fc69f22ac.npy +04379243-de2d98c18293a15219fb4103277a6b93.npy +04401088-6682bf5d835701abe1a8044199c77d84.npy +02828884-4b4c1a775f9a49958cd4e3ad2fcaf039.npy +03211117-87fb8857bf2bd3a7420ada7b49a056b8.npy +04379243-3456178d3ff37ae1e76bc197b3a3ffc0.npy +03797390-8f6c86feaa74698d5c91ee20ade72edc.npy +04090263-caff0ebc560479ced735fa1ab17311ec.npy +04256520-27edeaa6c6e2e670ce4f274577283b16.npy +04256520-735578d3cfa39279d098b24937823a09.npy +02828884-2edcb17b897706cf71a782a4379556c7.npy +02691156-a02387f2b9d73a01a5cbab5aded19a14.npy +02691156-9a9f615801c2dfff4d210d9468aedaf2.npy +03467517-f11881e9363c00f6352e5d4d2615db5b.npy +04379243-6df5ad89a152dbd26e79c14dd16aa04b.npy +04379243-6db77fbd32e0af3e3f9d6e0ade5188b0.npy +03691459-87a0dac4a3c483de6671a3cd2be21041.npy +04090263-7c10b90abbe17fb9935777dcb8deec2d.npy +03467517-890bfa7ff894aeb3ba9e56c15cb175df.npy +02828884-7536b671103f96e5b12a55dfcc392e26.npy +04530566-ad440e99d3a9bed3cd202a4790115f0c.npy +02828884-40279f85fc80e16edccc47bf0dcf5d3.npy +04256520-d9bb77735ff0963ae7e684d25d4dcaf0.npy +03636649-cf0c13fb0e57bad9cb02404e1e21ec1.npy +03001627-4a0e7f1129a9172349bb1cbbf9a4206.npy +04379243-21a5b3d29075564e2314deb821327685.npy +02828884-da92767c2e0fe6bad5067eac75a07f7.npy +04090263-b094f9184c3098a781fbd53a4fc6b7f8.npy +02992529-a3bc032d0842d570348e2c62a688b780.npy +04379243-5c11a1fa21e8671cbafa5bee623d5d.npy +02958343-f03a4533fe681a155b48f89d50b1db79.npy +04379243-5516cbfe2ae44c0a7062f2d72cde5c95.npy +03046257-c7704d12c66e09dabcb557b5b19897c9.npy +04379243-e4a9b9db82ff871a1b17743c18fb63dc.npy +03001627-247dd48e4b6c029e4b3c42e318f3affc.npy +03325088-c1c7a391d18c9ac54392467549e2de91.npy +04401088-1847d3782970e60679510444cc61f839.npy +03636649-67f6c0f40fc9216e8aaae3d020f5ddf8.npy +03636649-2c0177660b7ecc915c118a000b931714.npy +03001627-4c9d9b37b13b0dc720211b71e9c4c8b0.npy +03001627-69933c14a02d65166e28ffc6e1f368fe.npy +04530566-611824dac2873f5b59f280bab375e8b4.npy +03691459-e767a0e8df4e41f4b3b44ad99a214777.npy +04401088-ed0f3e1d20fc722bb0478ec258b0ea3d.npy +02876657-6f4749e802e6b5eb30612f5c0ef21eb8.npy +02691156-617a3d4bb40402679c411d305417ef6c.npy +04379243-79a3bd60b48584b11ea954af295a6a98.npy +02808440-4a6ed9c61b029d15904e03fa15bd73ec.npy +02828884-1ac6a3d5c76c8b96edccc47bf0dcf5d3.npy +02958343-5dd97775bf24ffa2283aaea3c1a7dc36.npy +03636649-ce879c871fe2015b4cbf9a02e3342127.npy +02958343-83491cab81e3a330bda733a39f84326d.npy +02691156-ccb9e8dd6453b6c2a2981e27422ad4a7.npy +03593526-4b35db459bc209bf5d878ba9ec3c0d6a.npy +03046257-6695577b5fb358ebdf5f14f6397a827.npy +03001627-473afe27e45b37101c8d18742f91c015.npy +03624134-665bf5d30d342d64adee73efb2c043f8.npy +03948459-e9e6426605eb6d5952d52701459b1f0.npy +03001627-8a8c67e553f1c85c1829bffea9d18abb.npy +03642806-de2e95eac460c361e862e3cac45aa769.npy +04530566-341905f73563a75717e4d86bbbb01f9f.npy +02924116-1514f0bcc843fc62ad19b94b8069bb8b.npy +04379243-d481ee7e971849339db8ad97fd392b59.npy +04256520-499edbd7de3e7423bb865c00ef25280.npy +03636649-a9f5d780f8303489d8f5adb469ca89d3.npy +03797390-e6dedae946ff5265a95fb60c110b25aa.npy +04090263-138cbc9b5456cfef55d33831e71fa52.npy +04090263-5fa42f48d1d279bb7de50e1a7b436c85.npy +02924116-da69974a1e548e8c95c7a8a79dc0c72.npy +02828884-1bf5b1fa54aeec162701a18243b45d3.npy +02924116-c851c4559c262b77473aeab56f2a35f4.npy +03046257-f4104a9af5a0fb3cf016aee3d784d83c.npy +03001627-1d828c69106609f8cd783766d090e665.npy +04379243-e157bbb54d5a2ffdd6944324b21393b5.npy +02933112-ab7ad8afde03897aa52fef6f94fcc8a.npy +04530566-2c23f32d6eaac557b93dc42f7dcef6a.npy +02958343-baf3415a57e6f282b23c333ee1a445e.npy +04256520-804b776428062f18f024b0f23b15c6c8.npy +04468005-8ed080571013f33e8be7c8c5fdb9bd6d.npy +02691156-56b44fdca08540da71d03b466c72ce41.npy +04090263-e534d084d3bc37184d0af51460733e47.npy +04379243-81b379e6871c97e45964cca694d01a7e.npy +04379243-43bc8b8b33811a2a54afac63dc6bafa8.npy +04256520-e4ac864732a8dc40f99656b78fd61fd5.npy +04379243-95eed587c3728d22601104cd2d998272.npy +02691156-21feae1212b07575f23c3116d040903f.npy +03948459-96fb7421c604f2f89a80640ff158687c.npy +02933112-bfdb60bd61d083536739a7caa0c577bd.npy +03001627-fd5ca05b59b30241d838ae16242881dc.npy +04090263-935645a83387dd25719c27787d6741f.npy +03624134-c7fcf3077b230ce17b635ec9828c6ec2.npy +03211117-5bd1493a07c13d675f1b26547b9ff327.npy +02691156-a3c928995562fca8ca8607f540cc62ba.npy +02958343-5fc83a88645b1869514e3d96995c555d.npy +04256520-8a470e5b043a38904b3c42e318f3affc.npy +04004475-f9553ec63a0724cf52c2b779770ba628.npy +03761084-52000b7c14d7804e976040de71c9b526.npy +03001627-243ab0d808fae5b76f1d1c49624bcfed.npy +03001627-48091b14719964986d075d8d4fe1141.npy +04090263-ca4e431c75a8242445e0c3a4b827d51a.npy +02924116-5961772d9c7dd56193d7855ecfc1bd3.npy +03001627-f550b5413eb040c29829306a513f9466.npy +02992529-aae6554b1abe736c70ed77f7659cc6f.npy +02691156-329a018e131ece70f23c3116d040903f.npy +02691156-7608d7a5a3e3c2b13d4b1f38e3dfce4b.npy +02747177-55e6f6e5a37777b7f9e1e633e708c001.npy +02958343-7bb54d802ac6156ab96212c8f6cd06e.npy +04256520-17e050b62fc249687d3c9de9415fb224.npy +04379243-edfd25e28cc7b003869c91937070800b.npy +03636649-7a67bb268436b3636a578f1b525d976c.npy +04379243-e5f797c0266733a49b8de25d88149da8.npy +04379243-370b45eeeb9b11416f04d49e4de95b59.npy +04379243-198551bcb90f2fd5ef40cf5f2b241770.npy +02828884-b7d0a6ed347a549b278d386bfa54545.npy +04379243-ce998bbfe6fa0d22bd6c42a70e9434e7.npy +04379243-b1384cf261fa99a03002761e7a3ba3bd.npy +04530566-4214845c44563c5fb1bb46d2556ba67d.npy +03636649-6936b0f0e7c88e3bdc22f557e01eba14.npy +03001627-aa0ad3538d0d7b3be6fe3612af521500.npy +02801938-434194622dc684f81de9d8208aaa2d25.npy +04090263-d65e4cc9b69a3ec4691fdeddcb509b59.npy +04379243-a447c1fe6f458a02e76bc197b3a3ffc0.npy +03207941-a2caaa68364f6207f054969eeb39ff86.npy +04379243-cb8ee43492cbdda3bf6f067b2fb335d.npy +03691459-b70c600b20614f4c690135fb845b8de1.npy +02992529-40dbb04ab8f780d6cc571cd3cf8f17a1.npy +03691459-c556fa897131c0c833b20ff045584bf3.npy +04256520-da964fb2d92a461f6295e8bd02084b6.npy +03467517-2292b7ee00d2955723b563ac391a63a7.npy +02691156-f1384d3fd2d59e63f4d6518603e8629.npy +04379243-8a64395b321a34161191025061735ea3.npy +03001627-ea7e09260babc698983c05814b11dc86.npy +03624134-fbce3be99b20b169f1ae0a5e4119d01e.npy +04379243-10e6398274554867fdf2e93846e20960.npy +02691156-b31bbc50a0d3a4366cf1b4a8fc3914e.npy +04401088-595901b2d5b23f58ed756341424d6b8e.npy +02933112-5aee956ff28e337a44221bef0fa3c36b.npy +03337140-6a98c9c55ecc6a2f4c3aee8e9d3a6ffa.npy +02808440-549245920e6e0e7c6b448b8aaebb705c.npy +02691156-fb48754430b17846e3375a6b96a1d765.npy +04379243-2f7a2d27e58224e689035c25f0dfeb63.npy +04379243-fff492e352c8cb336240c88cd4684446.npy +04379243-a09324ab0389029260885f79b3a5579a.npy +02828884-8f24d2e90bbd5855b77d52b64ec9e9af.npy +04256520-99175131585f4cfded403132b02528bd.npy +03001627-308e56be04f6214e50ed95708c70cdfe.npy +04530566-d25531bd6b7b8274ceb0dd441125df3e.npy +04256520-9001c9558ffe9b5651b8631af720684f.npy +04530566-cb7bc049274173df73a75ef44d66eede.npy +04379243-10657fcfce1d326b30bbd4cddd04c77b.npy +02933112-698debfccb32f7404c62bee40dcdc539.npy +02691156-f944c570191885e8ca8607f540cc62ba.npy +04379243-3a36028507ffd1a6ddd15630382184f.npy +04256520-eba5b24b9c3dc8cf9c0ca344f487323e.npy +04090263-c7fc0b36bbaee6382bf26da672b84220.npy +04379243-46957ba752c3554bd42b9650f19dd425.npy +02958343-e6e932a5d92d62251d15f502e679d4c.npy +03691459-65dbba7ce5b4c40192e34403f6f6f5f0.npy +03001627-248e014f31771b31d3ddfaaa242f81a1.npy +03001627-5f1b45295c72cdf03a4a5c95fa1b0032.npy +02691156-d4849eddcd93569ac119f94203b4868c.npy +03761084-4e0b08959229923f2ccf9daeb92717bc.npy +04401088-5bb9020da1d3bdc260a9d7568d474ade.npy +04004475-63c80a4444ba375bc0fa984d9a08f147.npy +02747177-a8b39c32604173c1d2b12aa6a0f050b3.npy +04379243-29f110b8740bd8068c427edcde5d5e2b.npy +04256520-1f8098eb2fe947398dc38b92af981645.npy +03001627-b69ce6bf8156deb155252a6eccfc24f4.npy +03001627-65b21a2af8709510f91663a74ccd2338.npy +04554684-ba5ea28f0065c71cdf3a1b0d597ce76e.npy +04256520-bbf1d8071651580cc79b370d801db3b7.npy +04379243-b7d6030b31b59895ba0b91d2ba672bfc.npy +03001627-ba707bbbc56d1bc319620b61f6587b3e.npy +02828884-88440ae4e218fa6ed4d8765e3910f617.npy +04379243-166cb38606acc1834265eb8d6103818.npy +03001627-2620443433d2292ebed0f46f915a3980.npy +03337140-59184214eb54c1144c3aee8e9d3a6ffa.npy +03928116-5c2a57c2cff7cc06d636d2b2e734dd7a.npy +04090263-b9220d1c981e2824377a1335e81633a9.npy +04379243-9be8aa90001e8f6b492d9da2668ec34c.npy +04090263-ff46f3fdaba78638aa7cb0651220ba4.npy +02992529-df768d07fc99eb30142bee3d28727203.npy +03691459-b0705be54d6220d9a344697865361601.npy +04090263-287f4e9b70b010a29ddd1aa0a00ef579.npy +04379243-5d30966509f58394237c47118f6132c8.npy +04530566-160271b40b1d6822c40386bdd72f9a0.npy +03001627-6251b398004a02fffebad4f49b26ec52.npy +03001627-428b77d0ffe6ab456e06155d245f15d6.npy +03691459-8dfa9921e51e0fa3f99860cd321d6c67.npy +02958343-cc7dfb5ecdf370a178c14a9d99ecf91.npy +03642806-aec07e314b2fdb8a60a676833b21afd4.npy +04379243-2698d4b8ff59120179b3e1be3524f72f.npy +03001627-c12ea730ea29f8945914d57d976758c0.npy +02958343-a75ff576da012340468bac13e007a6e9.npy +04554684-c18dffc90a4633d191219aad82abc053.npy +04401088-457b4310870bcf047f4e0c14aca1a926.npy +03001627-32d243fc56b7b8658cbd400aa99bee96.npy +03636649-9ea81b2f43dca29c5412c66cb6f267da.npy +04379243-4df369ee72ea8b2c3da27ece6ae88fff.npy +04256520-dbadee62f27c31e9214c7379b0e80b7b.npy +04554684-30925e14af2a92814b35a7d7cea7130.npy +04379243-fcbc0127388b446b7d6b442f66caef56.npy +04379243-ce422cb06b1f372c561f802d2e81cd69.npy +02691156-9f18925334b6f37bd560687a81f263dd.npy +03001627-9b82e2d4714b97827eaeab1f0c9120b7.npy +04090263-6cf13d5b7791b8618af39b443dc477ce.npy +04530566-18f650bbd1068f0589c6f1079da7a8d4.npy +04256520-5f145696aaef1e6f342398ca9dc32672.npy +04379243-d9512362b43efd8f91fee7773e951339.npy +04074963-9716c839bba80514906ed109a4ea50d6.npy +03991062-636b7d403c7717c3edad66bbdfe0c434.npy +02933112-367044e655cdce1f109be8beeb87a681.npy +04530566-5573567872450417d61794222ef2800f.npy +03001627-73970143d9af7218c8687ff9b0b4e4ac.npy +04004475-1d8d5d60023482dcab0a8ebbed30d677.npy +03636649-176b4495ed006475bbf899459f3f71bb.npy +04090263-bc135e8d9571775f20b92c47b3d5c1a3.npy +03001627-4fe364b3390d3e158afe76b3d612e00b.npy +03636649-e04e5a96efd77a6ed2f5c44a5922d7b9.npy +04379243-a3f3c3f288a750de83d38badc3559dbd.npy +03046257-23bbab353b849d3a6077d83faabf62af.npy +04256520-a97a1e97d08a236a68d1b9a1d97e2846.npy +04379243-e03d534f3ce3c77d19fb4103277a6b93.npy +02958343-c5b67d87b22583dc13ca2951bd3ea3d2.npy +04468005-429f55d65314335592428dddcdfd8a50.npy +02992529-5c8d554075a904bfa7ca3fec59d82214.npy +04379243-e3e1762fa7f935b3f6287cb48a47c45c.npy +03211117-28ec688f444eeb4a394b1e418d5c594.npy +03001627-bb9027dded04f7da2b3e9b6eb52d35df.npy +04330267-e8838770de9a6e4595feea036c244c98.npy +04401088-6d85b3dfd681eba530400184d5d3220b.npy +03001627-2e62d5829f60bd7758df8eeaf3dad1c.npy +02992529-bf2f0de18abd3bebdc858d428f2620a3.npy +02871439-35afa1b806556803e99c79bad29da781.npy +02933112-c3dd5d3f16f231c7cb0c0d433974e32b.npy +02691156-a9cdbca070047fe61e9dc95dd6a9f6.npy +03593526-b1271f402910cf05cfdfe3f21f42a111.npy +04379243-d1b4a4f43818c34e490ad276cd2af3a4.npy +04554684-e0bb2eefa09251a6149c1768202b4e64.npy +03001627-e31c6c24a8d80ac35692a9640d6947fc.npy +03001627-c64691882dd54d0eec1a944671ba8259.npy +02958343-7bce50c36d8166608e35db9103756ad5.npy +03593526-59deef87601c4a86664b3b9b23ddfcbc.npy +03636649-58d8496e15d6945bc562b0b258e20992.npy +03001627-e2cef660d0d7a4629976735d0dd7540d.npy +03636649-280fa01686e780ba3501c961e91ff6d7.npy +02691156-24db19ddb06fcd3f9a6e43b878d5b335.npy +02924116-ae4ded29e55b2173481aa8b5531c68a9.npy +02871439-131b5b691ff5bff3945770bff82992ca.npy +04379243-df63a11436240ec7fb906a2c84fd375f.npy +04379243-ddae5f8a28d8d616e4bbcfa1dc6a2906.npy +03636649-73ed11936acd99a627ebefef2b2130c8.npy +04256520-a0eeb4524c84f7a0b8a09f7075b904cc.npy +03691459-ca3d4a62e7a851816463df620b7b4cbc.npy +03513137-10dee7587a785cbfe22dbe8dd678fde8.npy +02691156-64da2f66ccfb98c6c511571426f8b16d.npy +03691459-6b5458409e54d8b99c5da70959a4c7d1.npy +04330267-e8deb7d4453601a5a53276bbe109327a.npy +02958343-7582e942f3e60a7c1477c1a2d9ef8312.npy +02992529-c145f0b0f18d4afe99aee91747c9768.npy +02691156-152d35bcceab5592eb1a0518c224975f.npy +02691156-c3454da26509937d4b4c1e25039af4c8.npy +04090263-ab0fa4305623f6c3cdf27c4099cb6beb.npy +02691156-130422d62194cf026c8067e570d6af71.npy +02691156-c64e43e18b01fb5eca8607f540cc62ba.npy +02958343-c83458f94ae8752f63ee8a34069b7c5.npy +02691156-b5d0ae4f723bce81f119374ee5d5f944.npy +04090263-8935329f244ca398cd89d443b4b6353a.npy +02691156-2407711ff7759994101cacf58b339533.npy +02808440-986351819dec1974fe52ffd0e748a1ab.npy +02808440-8c4d0c92f26217a84c62bee40dcdc539.npy +02828884-8861988f97b2e8c722da8c30c5c6c8ca.npy +04379243-9d57cb805345d761beedb4c8fd29e2d1.npy +02933112-3e4d14a8716d2418999b33727fe6db14.npy +04530566-7ba457477629beb8888d5ca4abf8aff.npy +03001627-2a2e5ecd0ef6ab2f80360680c1602c7d.npy +04530566-c3d22ce3607156466ac9421934926ab8.npy +02691156-4c3b1356008b3284e42e14fe98b0b5.npy +04379243-a94ea7183f27073248c0c0980e363341.npy +02958343-d142c919254dba0e41ab8016efaf0266.npy +03337140-db9fab17bc383c9e91c352d02061b3f7.npy +02691156-ecc50d702133b1531e9da99095f71c63.npy +03636649-ed1de19103e97b74c30ba10ebbf8ea21.npy +04530566-2fcb8c472f1cbdef185cce17ce166549.npy +04090263-899e86a8dc53568694deaa9fff391d41.npy +04256520-6fae3f21375b43b24ad33b69f9597739.npy +04256520-6bbbddc84bc4d3a68eb3bc6c6d15f9bf.npy +03691459-9de3cd602d12d178887e8faf8f33b0c5.npy +02691156-aabbf242aabd1af7766c6046535346e7.npy +04468005-fc21dfd12e8eb8ded4fec646771c576a.npy +02691156-32637024c9aad5289a6e43b878d5b335.npy +03636649-2b1817fbc0f3ddbe8220566e85550c0a.npy +03001627-ba747d0535cb7fdfbfb5bf9fe49f43af.npy +03642806-ebc59a9b4291ce274c3c121820623e4e.npy +04554684-aa9d1a55c1a546a1df3a1b0d597ce76e.npy +04379243-d177f7632a4bb3405073c32a9cf4a6a9.npy +04379243-f6f3b8e08af617e44733824eae5cd9ae.npy +04256520-16bb3ec52397cdf9cf01bc59d215f0.npy +03211117-646b0bd4e03fba8d566636e42679cc7f.npy +02933112-c060caaa105890d74da5feafe6f1c8fc.npy +04379243-28fb9a81898f88c4ae8375def5e736d8.npy +02871439-5c7914575a4f671d4b209708994baff7.npy +02992529-424ccff9ceea33451c81652b127a0ec9.npy +02691156-f11d14402a759a1465f50257ecdfa5c7.npy +04379243-103ad97126bc54f4fc5e9e325e1bd5b8.npy +03759954-365742901915252a9c75eb4326997fae.npy +04379243-7d6d7984fe8eeb3099e8bf807e902261.npy +04379243-c2c36909e461e10adaaaeef365d8f6e5.npy +04256520-11d5e99e8faa10ff3564590844406360.npy +03636649-e7e45a8f0b0ab311c754474f0ac106.npy +03001627-26e85b84b3b6eeea21711c78ff413696.npy +03001627-19d7da928d179a07febad4f49b26ec52.npy +04256520-5c39c2691a36d9e5a8f59bb67a917984.npy +02992529-612466085d24ce50b260ba4e94db1a27.npy +03001627-7b8e24c31b7509b6dec3f6fd3a03085e.npy +02691156-32e8412ce01e63c1a47575cd04a1d851.npy +04379243-b7e3aef758749005c3bd24f986301745.npy +04379243-7eb961d3f19080983ac416718757a350.npy +03001627-3021054d61c4862bf29666f384be6c43.npy +03948459-ddcab81a79b6d9448618c83c15f2c76f.npy +04090263-96c60386a5888d2094deaa9fff391d41.npy +04379243-64dedff769355d281bce08795c661fc1.npy +02958343-4036332be89511e31141a7d4d06dc13.npy +04379243-a96c429fad0af4c6bd1cdc725a461877.npy +04256520-638c8ca3dc94b152f6d79b8d34aa426a.npy +04256520-11f47772cbe2a2d0a5f9d52c12457194.npy +03001627-46bd3baefe788d166c05d60b45815.npy +02808440-5ffc44cc5b953a4b572c0ed39433d683.npy +04379243-3e42e3386f4aea9277cf3bb06f394ad.npy +02924116-35bbe8b3dc78680f2232a4c7acb57248.npy +03001627-b1f311d5fd262efcbc47c7f012e5fa27.npy +04256520-235c8256c6e973de19fb4103277a6b93.npy +04379243-4a579619524b60aeba18ade30e563d37.npy +02954340-a3d8771740fd7630afd6b353b2d4958f.npy +03624134-fb1f385d487d13d7aa0079d6fb0f853c.npy +04379243-97cb53b5e54a2abedf6cfab91d65bb91.npy +03636649-abd8a95ebe132c58cf004563556ddb36.npy +03001627-7224a8114ee2daeb0c0a8b87064ef09.npy +03001627-a7f0f0dce71747624671d97b0fd17f51.npy +04379243-a4d149a48607de3d92f4c88fd91c6b1b.npy +03938244-3b5e274f653258a737f437b479038901.npy +03001627-5f4af72ed8cd633a14038d588fd1342f.npy +02691156-30b317e256e9bfcb1f17e8416b3322a8.npy +03001627-2dd12e29d36c2b5519fb4103277a6b93.npy +02691156-959044f10e27b89ee664ce1de3ddc8b4.npy +02958343-96bf8cb730f728414a383db4764d5432.npy +02924116-e3c8034ece8bb14ac72758c329889173.npy +04256520-484259aff803ddd6f51fa0238791f5dc.npy +02933112-c7165635f2288945585ed17f54616d23.npy +04379243-f580dcfbb898139df6cfab91d65bb91.npy +03001627-a996cc501faa4ec841c6494d29fffa82.npy +04256520-6a6c10088c857de114038d588fd1342f.npy +03211117-830b29f6fe5d9e51542a2cfb40957ec8.npy +03790512-efe1456e80e2a8646350c50e0a456641.npy +03797390-c6bc2c9770a59b5ddd195661813efe58.npy +02958343-5ad845ccc1a5795ecc19d582c2bc11b6.npy +04256520-f7efea85176f8cd01f274b4885739ec6.npy +02958343-4eb9dbe42616e407b112e5ac235c21b7.npy +02828884-aa2571b8067d6d5383c4907a93b0fbc1.npy +02958343-586da8cf648767222a9eb0f146e94477.npy +03001627-c08c39b6ae7a44ff3935ca98160cbcab.npy +02691156-1d0c128592385580e2129f6359ec27e3.npy +04530566-3fb4fa12a4718cdb2001fe4ad7074729.npy +04530566-7890b89eba662af0ce90854bc9efdc95.npy +02924116-2b5dd01279b39fbc128fe65339f3ddb2.npy +03001627-b33e6d5d6bdab020af7c7ad2549a1b15.npy +02691156-2f7253f8fd1a6a999a6e43b878d5b335.npy +04379243-424c77a1f39ac41620dd2dd4d7d7656c.npy +04401088-6039379abd69be2f5383626fb6f0dbda.npy +03691459-4fca42120b49baa526841583f16744a.npy +03467517-b4fac38edb5b311d4fa7c0fdf6bf7f60.npy +04379243-700f59abde33ee3ec2d043ecbc42284c.npy +04379243-14624a2cc43aac50e3a031805ace4a99.npy +03001627-4148f94098b428095dc3653f8341633a.npy +03001627-7ec2388fdc271fc4ef22b31268b1b7ab.npy +04379243-d236d890ebc96f9ddaeb6f944439aef2.npy +03211117-df81df82811b2b2fe2d8a7cb76d59615.npy +03046257-b53a925ecca75b04455baaa8ae183248.npy +04379243-855e3ed8e5f233cd2b722fc42ccb4c6a.npy +03642806-ab21f75b97d6b1054f22ce0a3592d5.npy +02933112-29b34b5121639a65c59350d819542ec7.npy +04256520-b1b2195e45bf0495593ebeeedbff73b.npy +03001627-9e9dc51a4e0db2e4c3bd24f986301745.npy +03948459-7bd66b182aad44e79a2ee232a197081e.npy +04401088-d62ebc23fe1a7e6a985b19765176f4ab.npy +03001627-a58e894d520ebda28f94476574196c14.npy +02958343-702edad0d2fa9eda2a9eb0f146e94477.npy +04256520-effb1b260f100f5919fb4103277a6b93.npy +04256520-2d3a484f14ec3d4d7b11ae648ea92233.npy +04379243-259775bd1af2954e30bbd4cddd04c77b.npy +02876657-8a23e8ae357fa2b71920da6870de352.npy +04530566-6d537a1a09de6b13f5678db9e73ab77e.npy +04379243-1bf9ee6578bfbcb0f4b6538438a0b930.npy +03001627-5a2c6a6f832b14ed31251f4428012eaf.npy +03001627-f14fd8433dc1b43efe9f0f410eddfda5.npy +02828884-694681de16b492987170f3141eadbf9.npy +03001627-a1949183ec03f3ab2f6cf9c2cf79a5.npy +02691156-bb6bc2b0786734a79b2acbfd8323f804.npy +04379243-4f7c024d01141f23f51f77a6d7299806.npy +04090263-955021cff365f5907ed475464ab76870.npy +04379243-f07cde4ef5e76ae6c4cd9efc031e94b.npy +04379243-dc5b7cbcf45e557f310af74324aae27f.npy +03636649-6fbc93ef5b90b06ffcb8d8c6d4df8143.npy +03691459-9a35e159b52a7b1897bc8a58bf164429.npy +04379243-388d9e7b2b8a8f909492fbce0bd54e2e.npy +03991062-2399ba91d5263c913666eb1bf2ae701.npy +02876657-2722bec1947151b86e22e2d2f64c8cef.npy +03467517-e12d45cde8e886c463e148e250c0340d.npy +03001627-f05cdaa4f262ebfba16baf954c1d99bc.npy +02828884-8f52743c3cb564f149e6f7df978f3373.npy +03636649-581ad338a34dc3bc30f6e0ede20c4525.npy +03001627-66b5fd596ac18aa79c1db271ad9472a7.npy +02946921-be67418a10003cc9eae3efbc9dbeea.npy +02992529-d8ee6baa8b57a89add62317fcd30f203.npy +03001627-523a54d33ce5fa9aadcbe68a4d5871f9.npy +02958343-53e7ed598e9c3a09405f29f7fa3f25df.npy +02828884-360d4f846b37b7fb5b9049c85f69b9b4.npy +03636649-934981825fbc4e14ff458e602ebccbb0.npy +02691156-8338cdc32688a863bc0909d98a1ff2b4.npy +03991062-53b0b1db08024807c995f1efad0eebc3.npy +03001627-c31483b018ba90c30e62accf4408263.npy +03001627-bd867ce1ff2dd281a0f7d9635ddf7a01.npy +02691156-1e9ef313876bfba7d02c6d35cc802839.npy +04090263-3860f5c1ebea3de7fc3c7341bf676efa.npy +04379243-5e8452a2014eadd5ea8049eca11c54ef.npy +03001627-d040157682f60a7ddf6cfab91d65bb91.npy +04256520-17fbdd9d8e8b3e8dd2afe8d5254a0d04.npy +04256520-4a11e50e8e5c79e82cc460e9d064e57d.npy +04530566-6729875f6c9b48cbe4707b1374ec004d.npy +02747177-555f9430c2ca273ccb2a965e75be701c.npy +03211117-b7a259bd391ad43c69b642ba22680f87.npy +04256520-1e70ddc0e4cef3a832a785b4a7e37e67.npy +03636649-c233bd44815828b08bd5065c89cb7063.npy +02958343-ab8b6d39057d2f6cc86779a6788ad464.npy +04379243-7041d4ec390b8b12234a98794d9f2b5d.npy +03046257-4325f0de6001e3a195f577622f465c85.npy +03797390-b9f9f5b48ab1153626829c11d9aba173.npy +04256520-4653af854bf098f2d74aae0eb2ddb027.npy +02880940-154ab09c67b9d04fb4971a63df4b1d36.npy +04379243-6b9c15484369406919152a83d1ba40ea.npy +04256520-7b7c14e8fd0521bde4511d9a59e40339.npy +04379243-4f70d14dc276a9539a83764a2641fc5c.npy +02691156-2767994ce3078824f38bce64a8733419.npy +02958343-c73e146596486bdac427f8508e3d634b.npy +03001627-5da96a876b66cfeb922f1115ce03b77e.npy +02933112-61b9d7c12ba7aed4c59350d819542ec7.npy +04379243-614c37441ed33c338a3c75a1023723f3.npy +03001627-311e72dd86f0daa981a172d69c52a28a.npy +03325088-160bf4447843d769e6460c75101f5b6.npy +03001627-6df81788b1cdd1c3ab93f6188b226527.npy +02958343-f9fbc58e3692c4d5583d20ad0a6b981d.npy +04530566-5a4e0cb4562b2e0ef647317afa6ffdd4.npy +03948459-948732c47471ea808e75bb5638d14ce9.npy +04530566-aec5ec913aa2084b543941eaaf04581f.npy +03001627-c5ee6b77f9f84adeed52100e321c9f3e.npy +03001627-2282142b6b136a6f2ebeb1e6a8111f53.npy +03337140-fea46326afa3180a4fb42087918269e.npy +04379243-da7310bedd8595879daeea1362fbd792.npy +04256520-1d4e0d1e5935091f78b03575bb54dfd4.npy +02828884-bff5fff9215b5c412056b4bd5d870b47.npy +04530566-e57c1a72d265147548c2e07e979bc75.npy +04401088-67b3696286a96a8c171bc7a10f38839b.npy +04090263-56a8f2d9908cb417609e2d916fa0da27.npy +03761084-7acbd3fd7d1425e38f029c88b393c0c6.npy +04379243-4e3d100672af00842dc02296076d8ee0.npy +03001627-d554adc917b635c0fdef1c01cbd4ae0c.npy +04379243-28ff86c01e0faad758df8eeaf3dad1c.npy +02958343-c31891b69780886ffb907109397a6c7a.npy +04530566-860e632b27b9d2469f1deb04fb8ae481.npy +03211117-d9bc4b2da5df08b7eedaa5970dd41792.npy +02958343-7fc1cbdf81a1edf5bda733a39f84326d.npy +04256520-69e8d0b7366591dc578d107c71db28ac.npy +03001627-537924063294eb5f46ed025f8f85e067.npy +02691156-77ee6ccca238ceec5144962e2c20b832.npy +04256520-b2d70313d7d408f729404a50338e24e7.npy +03211117-e1eb75d031091e422616600cb9fa6226.npy +03593526-3ca8bda43d9d5775499773b0b5888ca6.npy +02828884-50ef39d633520df0855931d119219022.npy +03691459-dc9f8240a57b7be77fd9594c37158b0.npy +02992529-f48cb1a242e99745ab905891b6fa1a.npy +03001627-6b796faf03a2806f397aec0de5712401.npy +03001627-5d92fd12417a9405cf004563556ddb36.npy +02691156-b8df5a1fb0fa198a9a162c818d22a620.npy +03001627-eac0a44a4b4bf460f37e11038ce8fb27.npy +04401088-7f756e697cd03ac821844676433a0aca.npy +03211117-7525e9e986fa5059f64945cf4aa3c1a6.npy +03001627-1eeae84f10df85cd74984b9cd0997a52.npy +02691156-95a79d9ea571592bc3e5025cb598f546.npy +03790512-115a5200ff80b5d0b37378f3c85478b4.npy +02808440-c6ff7725e2e3832835b3d63776480dcf.npy +04379243-8d3d9f1bdcb245b49eaa55bb236fb6e1.npy +03691459-40f0e44f749ec0c7b3e0a2cf776be56f.npy +02808440-fcafadf19df05ee11bb088904f7cb154.npy +02933112-d68b1b0c95408b95380188eb80c957bc.npy +04256520-d6f7727a3e5736437b9c6deef486a7d8.npy +02958343-48f5446e6ac9c1b51f1446551412bde4.npy +03624134-81ba3f06ec38eaa46016d22b1dfacd4b.npy +04379243-e476ca4169c3d0ca490ad276cd2af3a4.npy +02871439-6ae80779dd34c194c664c3d4e2d59341.npy +03001627-323ab1a1a81ef0f51f77a6d7299806.npy +04090263-db313451e6581570e16974ffd95b0c65.npy +03001627-6f754a2c354b17642c0eb4a518e123ac.npy +03325088-a4bb5d2f36b1319f50da8b99982a3057.npy +04379243-b3371ffc36150f817bb281f66a49b55.npy +04379243-ed20a233783090839039bc4ea22a379b.npy +04379243-41fb180e6e8b19a14ee40fa7f6af487c.npy +02801938-bd11c268ebb14e2d7ae6f33544c233fe.npy +04379243-ae6594f65639a51845f0e5dddef26b1a.npy +02880940-6501113f772fc798db649551c356c6e8.npy +03046257-90526ad050d212adfc00df8700518cc6.npy +02691156-4853e07c17127af7df92be10876fa000.npy +04256520-71147c7ef2258b894a1a4db9532622c3.npy +02691156-5fc63354b0156d113136bac5fdb5050a.npy +02871439-f5114cdda24d49216638e88207c822d8.npy +04530566-9b300840d96e46f08c173f7caf7ef0ff.npy +02808440-89ab13233adb2f879d57ee14f8ee702.npy +04379243-8d84471c4af977d917271868b642acd3.npy +04530566-4b54d54c1e9cd6cbff5cc490d863ff3d.npy +04401088-8e9c97d54060d1282085d549612807d7.npy +03001627-7f8d63acb7b4b5e84d2f52566c6c4e9.npy +02924116-9e14792c344aa053e78cb83d32b44564.npy +04256520-a73fc5b447cab6493ca57f5648ff1b0d.npy +02808440-5b8d1278d408864eba47eca8aa80094.npy +03691459-91ae8db92f3dd88b55a8aec4bacc60b8.npy +04090263-c7f8678e3ea91a99de50356926b60476.npy +03790512-25ae9e6628ed05d81e32f79edfad8027.npy +02808440-e34dbb83a23b3b019bb88ff9c0d772b2.npy +03636649-4d44c896993e80a11391d5b018495c2c.npy +04530566-f2c8239dc51b315858e86ae676396826.npy +02691156-3a6d6534045b1895e8ed194c80e0b1ef.npy +04256520-aebb3daec0cf81e695b2988c41a35527.npy +04530566-99d12cf62a1b5cc3f4352ea917328a5b.npy +04090263-6cff6f4bd6a5d73e8411da876c84603f.npy +03325088-e10b62f9792ecdc1b362845c6edb57fc.npy +02871439-601359d274c2c00a1497d160eced5e7a.npy +03001627-8b3d1c34753e095cb05550de345b6d0a.npy +04530566-e456eded209aac05a8b0c9e2ebd8eeb.npy +03001627-e2c3729e9729b75f40ef1c8b63a628f9.npy +02924116-fc5863dd1595add5f95dfd5eb5f06d19.npy +02880940-aa70f5e55fa61d8dac6b8e58caf61f95.npy +04379243-30820b470df63087afeb21083ecb38eb.npy +03001627-8e945aa01bbacf7c3fbe480a485feffd.npy +03001627-5555c24767e66a3384633b41c8a09fa0.npy +02691156-86e19045d9f27bfe269856bd6e519d10.npy +02880940-4fdb0bd89c490108b8c8761d8f1966ba.npy +04401088-1ecbb2ddeca087b5fd71b7a0b881ae82.npy +02691156-bb5844976bf8ec479e8d5aab043eeb56.npy +03636649-cf09b30a89f70929cc67b3de75c44c76.npy +03991062-f33a6fd8d570b5de4e7284648d65204e.npy +02958343-7c4aa4b3f916d26c9cdc71dce6a3b485.npy +03211117-993e7df9e8166312af8f68791a7d624.npy +02808440-60427211b9845f4e9ee028845f1b68b.npy +04379243-4ba447371db8c37c74739c2c9ecfb3ee.npy +02808440-5592d42aab84d67dd27bbf2d1aff38ec.npy +02880940-13e879cb517784a63a4b07a265cff347.npy +04379243-8bb3a7e1cb24fe6febad4f49b26ec52.npy +02924116-57e1aa38fcc42438d3a958737449e7cb.npy +04256520-b24e1117e49c75f817b431cae0dd70ed.npy +02958343-b2f06baf5851e7a36df8cb2765f8ec95.npy +04401088-5ccde0c95cc0538ef39072555215f568.npy +03001627-4afbcdeba648df2e19fb4103277a6b93.npy +02992529-83f766eff3c5c12c781fb7da315db2c1.npy +02691156-aac4ceced7042e4c1a6d59f1fe711d12.npy +02691156-7f895411162624e92023ec956848b741.npy +04379243-ff5a2e340869e9c45981503fc6dfccb2.npy +03001627-e401be99c5a51d8bef8e9284f76f3024.npy +04401088-294d1fa4193f54528db944c07f28e3d8.npy +04468005-1fee0527788d5f6fbefe0ffe2abbe914.npy +02876657-e29e8121d93af93bba803759c05367b0.npy +04401088-1cd8004a1e0dd825c33f370fa5b41cf7.npy +03790512-d91a81a1d57ce78a739936b7765e22ae.npy +02691156-4385e4300e72e49e90b1d6deb98feec6.npy +03001627-c79532846cee59c35a4549f761d78642.npy +04379243-712a7d7ab58960829408655f72318aa1.npy +04401088-4991cd37af08577070346e4935b9a42b.npy +03325088-d40acf58d3ab13763321831d2245cf06.npy +03593526-17bd8e7317498f21f0afc55e2266b11.npy +03325088-80b9619326f25bac3321831d2245cf06.npy +04379243-7122eeaaedc364fab5e360679943d9fe.npy +02828884-238825520fbdda8e6a4265f8860b466f.npy +04530566-eb1b91b2e6458a813f6d8df212adba77.npy +03636649-2e32934d4a49c374b20bab10aa3ece03.npy +03001627-4dde5285971f0b73ba4ec8b7deb104ae.npy +04256520-9cf60525ffd70735edcb0677ec04fe0f.npy +04090263-8d5c7600f31e45482249915e95f55f08.npy +02691156-e726c8e6897130439a6e43b878d5b335.npy +04401088-9f3ad4e5f16f40b3d0f9f958bc79097c.npy +02808440-3a5a6113f20f7462c0f3ab010f0dece7.npy +03046257-4d7de5c46a7644fe8b7965c971f6e497.npy +04554684-880a6bcedaeaed1fd095418bcfa348eb.npy +04530566-55dce6844c2bb0145368bed34e5564d5.npy +02691156-e8409b544c626028a9b2becd26dc2fc1.npy +02933112-140ec01582235e15c59350d819542ec7.npy +03211117-fc0b4809f5a1a613496b87cefd345586.npy +04379243-aa3eb180a4f6d8d42de421c2ab5cfb52.npy +02958343-86c31c04c436f5932e877e82c90c24d.npy +02933112-17ad636e45c233bef79e00aae9a7dcf8.npy +03593526-7333b1ae767c03db2396ca3dd50467ab.npy +03001627-bd0b06e158bcee8ac0d89fc15154c9a2.npy +02691156-688c6d406c789b8d71d03b466c72ce41.npy +02992529-f6679591247bc328afb07a946d621b3c.npy +03001627-a63d7b6e62333b23ddc809959e304d48.npy +04330267-55878303fb7fccc58e4d888a487bbe11.npy +03797390-4b7888feea81219ab5f4a9188bfa0ef6.npy +04379243-a39677e069564a7ea7e7cb173e141227.npy +04379243-f7ddd0ae5b0107efdde6d22342684df5.npy +03001627-e594b1e2f7a7f677492d9da2668ec34c.npy +02958343-92c882d35dfca864acee48fc4abca0f4.npy +02747177-abfc82b4f2071aa6ad5067eac75a07f7.npy +02958343-6ed2957beeb7940a9fbaa69916aaebda.npy +04225987-254feab290d4b460d4e77499b42cadd3.npy +04090263-c640c5ff1527fde7929ae5eb653afaef.npy +04530566-aec79b6f0379b1749fb6fb8ca3454a08.npy +04256520-9d1e8c37315e292f31a50841704a69bf.npy +02933112-31a142710610023cf51f77a6d7299806.npy +03991062-7c1303d3a19a1cef51f77a6d7299806.npy +03691459-20fa8d1542e7f835efaf604fa2300241.npy +02818832-1101146651cd32a1bd09c0f277d16187.npy +04379243-e6b61073fa46571df71e06115e9c3b3e.npy +03325088-9199954a99393c6e6d0157e3e7a8917c.npy +02958343-4cabd6d81c0a9e8c6436916a86a90ed7.npy +03001627-cc1dac5070d0bb7d5c43d2b61614d0d0.npy +03928116-d9b103dda28d8d20bab3d34d85dc6ddb.npy +04530566-4e6313bce5ee3698909d4348e3fee2dd.npy +02958343-7c5e0fd7e8c62d047eed1e11d741a3f1.npy +02808440-73baa3af38c96a52c85e7a9bf0779313.npy +03046257-8978869197f846ab31a50841704a69bf.npy +04256520-e014e3cecb1bc2b949a3c1009fa79820.npy +03636649-98ae07e021f3227711d89826bd8e0670.npy +03001627-a0196df591bcb5f7e404848d22e4a58b.npy +03636649-833d33785c62634b192fe29c2d3d296a.npy +04225987-c190e478faaca09baaf812076502792.npy +04379243-83952bdf5c426c4a85cad391c250db01.npy +03691459-99dce9c359b0bf4afb33d0031815b3e6.npy +02828884-6eaa388bfa782df4392580629414747b.npy +03211117-732dde95416888ac21d25a6a55757584.npy +03001627-3c363c3a75aa1daee8f8c11a24c52ebb.npy +03691459-37758713e7a31d1710b84d6f34c2f2e1.npy +02828884-8d3e69ee2d0168a6d4d8765e3910f617.npy +04379243-1b1f24767e5555d8c3bd24f986301745.npy +02843684-4357b7e7d5b0607d961dc4fac22bbd1f.npy +03325088-667db69a5d07b34f50da8b99982a3057.npy +03691459-fe977bebc78501995996c3a82deb78d6.npy +04379243-a7ab2b8bbe94bc89b41f4c6c5919541.npy +04090263-ad945e636e38338d8aa7cb0651220ba4.npy +02691156-38a8e07ed9b0da99fa7918e5874b2c16.npy +03691459-38007ed3e5ce40ab13dd6eafe1477be1.npy +03691459-86adab79cdfbc284d7872acf770948a1.npy +04379243-2d4005749db552232430716fc386281.npy +03790512-177c8a8394f5a78772408d74edbb952e.npy +03001627-f31a13e903da7e865e61ef8e2af97499.npy +02958343-36d0b6beaffc68ceafe1d4530f4c6e24.npy +02691156-213cdfff847f32135ae839ffe09b9d31.npy +02871439-dda1bce96f08098ad072fd39a51dc44c.npy +04256520-2a154c6f14a749179f6fd848d2db8a5b.npy +04256520-57e1cdb6f179cbdb98e0d1738edd4f19.npy +02933112-8b24699e1351a78ef8e7f2c38fe37243.npy +03790512-3a94134ec9698b74ec5901a85efd6b67.npy +02958343-44108b58784ea6a1b5c12c7484d0ec31.npy +02933112-4ae5df17829fb50799dd23ec22c4943b.npy +04401088-58d40261b05f9a148abea0092096036.npy +02876657-d3ed110edb3b8a4172639f272c5e060d.npy +02691156-167a44b60adc37319ba010ddb4974fe.npy +04256520-9ea38e213819c55680dbca6e7b64a4bc.npy +04530566-afcafaf311af722a5446fdbcaa866773.npy +02992529-7bd964021c9c26e0e4b68d3b17c43658.npy +04004475-4a49d478c563bd7dad3955f0fcf64b8a.npy +03325088-19a3ce38f92f792376c18e71fd49c4dc.npy +02924116-fe66024bddbfb69310c9db2520d67003.npy +04379243-b390566645360e5d69fb38085fbc320c.npy +04379243-f5526d438b53a244bda2eee2725ec127.npy +02876657-3f41aaa42a237fa3c785f06f424b9d06.npy +02958343-695bc26f67e001e65bcdedfa3370f5e1.npy +04379243-c67b454761d7c84eb2a155afd9dbbb0a.npy +03691459-102f9164c5ae3846205b5aa6ba4df9c8.npy +04530566-2552d0de59d21f1bfbc6fe0b6b7dde54.npy +03211117-7a2d9d3d185cff794b85c79082892df6.npy +04379243-948f1bc3a1d574196086aaeef17e8c87.npy +04379243-54c121f22e8fb768b129901f80d24b7b.npy +03001627-497833f2073ba6ff70d45c28bef72613.npy +04379243-2362ec480b3e9baa4fd5721982c508ad.npy +02691156-81b67bd14fbcacefd67fc01cbf5eb7c4.npy +02691156-8c622c7e0b15a0243ec67cba9d24f2c9.npy +02691156-d109c08886c2a3dabdf566b587d6b21.npy +04379243-596f93940a4d97866c752a9b08e87ad3.npy +03325088-c5ec1e91a2de288fb362845c6edb57fc.npy +04379243-5c1f92f1c0bd459386a48a74e08b1cc6.npy +02958343-61ff6beffb91b6a82a9eb0f146e94477.npy +02876657-547fa0085800c5c3846564a8a219239b.npy +04379243-adbd3814cdb655a7b11ae648ea92233.npy +04379243-7d0b868cce75a059a0ab1d82ef09f78f.npy +02933112-55f08c36c20f161be186198f40d88f09.npy +04379243-3237f2e39e0f2f38c3bd24f986301745.npy +02691156-536e1640461854957a86454b5377c47f.npy +03001627-9e8e454c76cc6815dac5061520ffd33e.npy +03636649-e519ec9a23b1612dad19a449ad99c8fa.npy +04379243-6962e8f899bf60393d9c503e95bc363.npy +03691459-39ade62ad13e3c79206861ce7df4037f.npy +03001627-d323e6d19dc58526f2c0effc06a15c11.npy +04379243-fb6d011741ccdb374a00834418a35d1d.npy +03691459-e2d6a0851b9357141574d21c0c95092f.npy +03001627-954a964459d33b8a71a782a4379556c7.npy +04379243-ffa71bb0a75ebd7f93ad7cfe5cf8e21f.npy +02691156-3f80ce1461f3dbfe16af5d7a0b735543.npy +04379243-f695567555986b6a71f08386b3af436f.npy +03797390-34869e23f9fdee027528ae0782b54aae.npy +02958343-fc86bf465674ec8b7c3c6f82a395b347.npy +03691459-4421130ffdb720c7421e5649908a4a06.npy +03991062-1ebbd0a9e447cf62a2c59a4d90e63212.npy +02691156-e0058b4948f87d3b87697d3904b168b.npy +03325088-98b09e32fd09e51ab482922dfbcdcc.npy +02828884-4b495cde98399a83d4d8765e3910f617.npy +04256520-366c86849245170262f6790b971792e9.npy +03001627-76fe7cf10c5dbf1edcb466b6f48b5810.npy +04090263-fe21904b4e1548ba5bd1f946b0dbc061.npy +04379243-3c5281bf572e2b6f2b70eac6546e93fd.npy +03001627-8e779c0b252d4b5e118ddfdb81cc6068.npy +04530566-3f35daa80c8b364fb7b1411b0ad3bd0d.npy +02871439-1c1795169de018b97948cb8e1d9ee487.npy +04379243-c0b74c61865b563067dc358060e3c47b.npy +04256520-d0842064c9900af698e0d1738edd4f19.npy +02933112-e619cf6aa221424cf80ff10f4838c137.npy +04379243-f83f03cd8d6d787f73678cf8aa86fc01.npy +02828884-3f50c37f196c541e776d8bc79b9caa2c.npy +02691156-f7bf32d3aecd197360c9b6e4c75a092a.npy +04379243-bcc14b683930f8d33924adb2bfcfed72.npy +03001627-92cae2e67b788eaa9dcc460592c0e125.npy +02691156-25a057e935aeb4b6842007370970c479.npy +03624134-6128958f839431276978912735020245.npy +03001627-ed97d1c954fca49851ceffe90913a32.npy +04256520-509a533e17fa45572814c9aa90ee14e.npy +02933112-a53a96efb6b9f29a490ad276cd2af3a4.npy +04379243-372d52845e1c620fef3b6dbf349349be.npy +02691156-310f0957ae1436d88025a4ffa6c0c22b.npy +04090263-6a62d0d41a2351af7f683793234d478b.npy +03001627-8a1187956642c3895331e304403f2050.npy +03001627-5b89de55ce0f464221f824bda064425c.npy +03691459-8562c442745af497b5b6356ddd072fd9.npy +04379243-8ad09d90888f71dfcb9cf5f7d536cddb.npy +02992529-c71acd79ec4cf1cdd11ec2c68afc26e4.npy +04379243-b97a0bc7e2213913ae96150e4aa362f9.npy +04379243-3cb17903afe49e6962e682c9809bff14.npy +03691459-acd123e2a1fd25366cde9ab9486e09f0.npy +04530566-b9dde09099e081e65f76b0776a50c136.npy +04379243-4fc00c3e48cdee77883679e873099585.npy +03046257-ddc323f128d4bef76463df620b7b4cbc.npy +03046257-b0cafe0b5efb6cb44cdd82d9cdddaedf.npy +04256520-28e546337f4a5188e6fe3612af521500.npy +04379243-b7eecafd15147c01fabd49ee8315e8b9.npy +03513137-8e624ace735e6baf96c3bfb1b184602c.npy +03636649-3ef55697cf7f68061173b43d09e96094.npy +02691156-f9fb41a3b1f59bb027745e9b6b461e93.npy +03001627-aa2242ae4ea1074bad0881e4ef1ff29c.npy +03001627-1166b15756ed9b8897317616969032.npy +04256520-ec4948183b308204e4d5ca1617e68f91.npy +04530566-fb8206abb1fde4c08abe79d18310fd73.npy +03593526-d67ac9e710ba445089035c25f0dfeb63.npy +03991062-a30eea3bbb52b3d4f13ce777d031b4b2.npy +04379243-10e279c69b5678d39a45b69dede1154b.npy +04379243-f4203c90d740596f70b396e6f5e48bfe.npy +03991062-a2970be7c866fe33a2c59a4d90e63212.npy +04379243-7e967a3c6d2a46c3e2d62d6f0e6f01ec.npy +04379243-5d9f67dc1f1518b6d5f8f84e75452c7.npy +03001627-e9c9d998f7b0de3ca6afe5903a01a59.npy +03636649-2fa7dbc66467235e2102429c788ba90.npy +03211117-d2f37af28550950f4161e123a102b12b.npy +02691156-d3580448933d00fd90b1d6deb98feec6.npy +02924116-fd2ae226f9c957e8bd69e36f5d4705c8.npy +03761084-c597a020f422d48a90071898148dca0e.npy +02958343-66d4d1f28cdbe97559139efcde1fedcb.npy +03636649-878d76c9657bec71fa58f9bd5c78b9e4.npy +02924116-75fc875e3d2bd8fbf01129d246a5d1a5.npy +04090263-3b22c066b7786677b1c46f058c033ec1.npy +04379243-ae3f65ef020c8170cd80f9971acfba.npy +04256520-3ddf9a51c44970fd5e4b35ff1ea95f37.npy +02958343-45738568b9c0eb2ce2915d41189be12c.npy +02958343-2d9b790608d32763ec2f3f4c642b88b2.npy +03593526-c673160553979cebd37947b3ce04a083.npy +03624134-824ef824c95632932ec2ef9f7cbb064a.npy +03513137-179b3b1df301b95ccc34b900bb2492e.npy +03325088-66c916bcb881f8b13321831d2245cf06.npy +03001627-8fcff2582b55291389e2d345fb844f4b.npy +02958343-d34b0494fc4d756ab927782fc69a1fbb.npy +04379243-5e68b3e485b9e033ab4d0308b2ec6512.npy +03593526-ee07000195ef7c93e89c405d853359af.npy +02933112-5b2201c133876813f8333d818f5f80e1.npy +03636649-f01ce55e789efa7e5127e0873cfaa7b8.npy +02691156-1280f994ba1f92d28699933784576e73.npy +02691156-7e52ac52a2eb74ac26360e1e29a956c7.npy +02933112-27cfe222aec3463bc59350d819542ec7.npy +03636649-e2e7f45670fc5e369a6c869309041adb.npy +03467517-7068e37ced4e8e0ca9f121364bea84ea.npy +03261776-9cffc684f6f3a077c0a508349d9ada60.npy +02946921-8cf26f6912f4a9e34a045a96d74810ea.npy +02958343-9f610a7b0be81dfa3a0daf3e5400b95c.npy +04256520-d9c184cf0d80efa6150855094a28ed1d.npy +03001627-5073d7a546b9a4d0e810eba61b778ebb.npy +04379243-9012c6ca245c1bf4e6c5cd45aa112726.npy +02992529-37846d5854ef7da646e4b9487666a2f7.npy +02946921-7b643c8136a720d9db4a36333be9155.npy +04530566-c48e3ab1cc01521cdfaef96860d73193.npy +04256520-2b79edc3da006592395a2b8836b4be75.npy +03797390-e9bd4ee553eb35c1d5ccc40b510e4bd.npy +02933112-33ebdfbed1aff9fb12d532e9deb7e02b.npy +02958343-e7c5fb8f7a553da7d7755e7baabe8a6f.npy +02828884-5a96b6b335bada106fa8ce57c8ec2e09.npy +02871439-68042811281ce35a3d80c564be8c917f.npy +04256520-c44ab66d4938052a36e4b0ae0f52067b.npy +03325088-7aefdb866624662114b35a7d7cea7130.npy +02808440-f629c8296f95491d83fe9e17f17632f1.npy +03001627-a7f9e2612d0764a0656a19d1d18fdbac.npy +02958343-8ee2dfd1460eded9473f10e6caaeca56.npy +04379243-89b478643e53d3d6285c99063fc6fcf8.npy +04090263-8cff6a796ea47a9cfef144202cb2b935.npy +02828884-ef018d0bcb3d4c89601104cd2d998272.npy +03001627-79a3115a6f96eef7c151419181ef256.npy +02843684-a842ad87774e1948a89d6f0a00bf90fd.npy +03467517-2c1b6a4fb58b04371a3c749a0d8db8f3.npy +04256520-130c64a2c0232fd03fc2ef4fdfb57f60.npy +02828884-fce4206a99792d47cfb87ab5efe3dc31.npy +02958343-bafacc7f28509d4157abc6fa0d632bc7.npy +04530566-dc38553436df0e4bb129901f80d24b7b.npy +04379243-43906b48471bc76e7571d17c374fac42.npy +04379243-1a35db5eb4f931a3eba0693b2c2a423b.npy +04256520-a1743777bd7c796b57ae08c3105b4e6a.npy +02992529-f649a5368586aa77eecb4e0df212ad9.npy +04090263-3d9907c402689521d8a2f3b4102511.npy +04256520-681d226acbeaaf08a4ee0fb6a51564c3.npy +03467517-3463e9eab1648fdd91c260ea88c0b690.npy +04256520-c837f4472115496cc93e5ef112648b04.npy +02691156-47331e4c26dd1dbc66cf1b4a8fc3914e.npy +03001627-866e7248434968051cc7750d0afca796.npy +04379243-f38a18709e55e4647ee217c21e683487.npy +03001627-b596b505cbeb456e763d8d4012bcdd98.npy +04256520-12766a14eb23967492d9da2668ec34c.npy +04090263-4d55fbf2ec19dc227359b134afde902.npy +04379243-f166eeb3434b9ea4d79a1acd1a8c2d4e.npy +04379243-e603bf3c3d2d26f9579e0a60e99d2683.npy +02828884-e2f79a5d9126b25aed98cca8f0ccd5f7.npy +02876657-6d652a95363bb682b692b490d9871ff1.npy +04379243-bc29a2ba03444764c3bd24f986301745.npy +02828884-186da14db8a38403612d80eb7de76ff.npy +04379243-e046b02e2d5c5187fe38a836aa59c483.npy +03991062-7ed1eb89d5463580a2c59a4d90e63212.npy +02958343-56cca58a4f37323bd0889537a7d54003.npy +03636649-8843ee2b220a702e5dac14d8f50c13f3.npy +04256520-93e652f343412a3e1c8509b1d97a23bb.npy +04090263-99a1608f8e848bf6519f927f2bf92da9.npy +02933112-731733f855e5ec4ae4c30caf4bfa735e.npy +02933112-bcceb065b8c433b99a87002a4eeaf610.npy +03593526-998c2b635922ace93c8d0fdfb1cc2535.npy +03636649-7634fbdcaa6b304d62c83ac1e3a4ebaa.npy +02958343-e75846320e6aa623960b997a49ac99a7.npy +04379243-1a2abbc9712e2fffc3bd24f986301745.npy +03467517-a541f89066da370693f0194265a9746c.npy +04530566-848164edcd9aa41594daa4565dd30535.npy +03642806-d31e025e9ff79c58db3780255bb0fd19.npy +03691459-864546c6fbf636a2d0d6252a768bb9c.npy +04379243-4e9852331e1d5d8dc3bd24f986301745.npy +02992529-ef57d8665eb5ef7cdb965514105122a4.npy +03001627-64f6991a3688f8a0e49fc3668cb02f74.npy +03211117-887fdc9a9940ea57bd59d5b2d356dfd7.npy +04379243-4ce62e31dff3ac18ffc6e457221b9271.npy +03001627-9f5add46af4a41a1305e886266e302e1.npy +04530566-8d8e8de880b4d7dd12ce033f7610a23e.npy +04379243-a2824ff9eb173055f4b6538438a0b930.npy +03636649-d1948365bbed9de270bb6bcb670ecdf5.npy +04379243-818258b7cc1925031b17743c18fb63dc.npy +02958343-ff794bcc5ffe460169e495ca617c20a7.npy +02691156-882c6bdea5fc5e82a3ee83e6cad78356.npy +02958343-8c1741a5ee03b865bf5aa6fd28a4a75b.npy +04004475-e103e8c985edec6ddca809889e6575d9.npy +04256520-ff73fbfb9f4a273be738f481f8560d58.npy +04379243-531381f5bbc69e485769b3af36a2ff9f.npy +02747177-dd2ebaecb3d046d2cb2a965e75be701c.npy +02933112-b0f01584cbb37d2ff546596ce7364503.npy +03691459-5aa9c76ab234dc2234560c18f9de360.npy +03642806-760b1f82f7133ca1de7d2830be38218d.npy +04530566-2defbf22a2d6c97d48f817470e1b499a.npy +02828884-99e759db1e01bc3196ca2abd33a2baef.npy +04256520-df70c07c2b0a066382241d99b4e87f38.npy +04379243-c1254fc0d8d0625b8738e7290b6f3237.npy +02933112-123994ddd751ef58c59350d819542ec7.npy +03928116-6f5036645aa28645a2b96515f0a8f928.npy +03991062-7d4aeb5d950a335cf700ea08eca56581.npy +04554684-64e1c85034dfe93ab7dc65d7950bd55b.npy +03593526-b2507913d631e8b8bcfad79fc308fa6d.npy +04256520-b42e4fd21f39ff4a19fb4103277a6b93.npy +02958343-4ac021653126a29e98618a1ba17f086b.npy +04530566-f791188138166b4d9db44e8b39ef337.npy +02958343-ec18723333333a6e2fb4628a7a8b337f.npy +02933112-f939cc4fa30511963fe047712e43e185.npy +04379243-5883da6d43e3b9743087f84b199fd297.npy +02958343-41d9a381c12ee3e2b7863a3a9a8d5d0d.npy +02828884-d0ae223012be978a49a531253b5beabf.npy +03761084-a91fc98fb71dfa46eed4b2bb88c072a8.npy +04379243-c8dc82f68335fdbe6b41b8bcd0404ec.npy +04379243-2a896f1d6925cc61dc89a28b5e6678e0.npy +03691459-211cf10bd078f91c01c4160f17211fe.npy +02958343-e3dff7195a2026dba4db43fa521d5c03.npy +02933112-c7dd92386b9d18bac502b42dc3551a09.npy +03642806-47583d8af57c13d94145b5f47fac09a5.npy +04090263-3907ed2cfe0cbd22853c6f214c15e60f.npy +04379243-ff1c8d1e157f3b74b0ceed2c36e897b8.npy +03759954-e074316e42dcf9e15c8e7963449f8577.npy +03636649-a47a54ea870ac35396280c8d384f22e4.npy +02958343-a70703613b83063d27c34dcc9b552d03.npy +04379243-d9fb408a6fd11e6c22ce72a02bf771ea.npy +02933112-346419b6e2131dda5785f58f071c8c43.npy +04379243-2f9f15a48b674ea25c87325f4fc53794.npy +04401088-6c53f579c7a8da15c7ef7dadd1baff8.npy +04530566-ad00fa76c831858ebb4a6ccf078584ed.npy +04090263-c88aece300c3c4e05127e0873cfaa7b8.npy +02828884-35554b4c00816a08b50485c33b91d8c0.npy +03467517-168cf0014eb65a479c3e3fc875294773.npy +02958343-9aaeb0852a4cca28471ac7b6a0462075.npy +04379243-580373e581fa155d3ec45bd2bc895504.npy +04379243-5f274ad7c2989f5119fb4103277a6b93.npy +04530566-75947361891546713c3d3b81c7ce4f52.npy +04379243-9b56632bff0d00dbd626c689702869b7.npy +03001627-f2aa3808b870ba95429b498f2f24a42.npy +03636649-6e51353655289e10ad885ade4bf3150c.npy +04379243-5897116720fbf6b5d1308d82a3302eb3.npy +03325088-a0e8cc8bc5f9c00143c5a4b82cd776a3.npy +04379243-2b8961b3c1deaab8cba466d56886cb4f.npy +03001627-af96bf24c341e56436b0f2a1430e993a.npy +04256520-273e8e15b6740e5932a526e2e9a7e9ae.npy +03046257-79e6df3c7e4cdd027ed10ef1927ebd15.npy +04530566-bdc39427c6267262c541ae04c251c7da.npy +03636649-776e4b38023091002cd2160e449d45ae.npy +03797390-32e197b8118b3ff6a4bd4f46ba404890.npy +04256520-20050b94da092fb8803805d815ede61.npy +04401088-f6b4f01d4c9c09e6af1fe3c052ed3a8c.npy +03624134-1db70d6edd9d27cd45e6ffe8c3b08de2.npy +02691156-de7cc3442b1775d46559a92f80e3672e.npy +03636649-b990d515ee1cfc214a200f5f1797d729.npy +02958343-8478439998e4af846602d94d941a9c9.npy +03001627-27574a49bb8055ace6fe3612af521500.npy +04256520-5cfc913387c753f114038d588fd1342f.npy +03001627-85f1b136e6935b7baec8a763854c53a1.npy +02691156-13daaef458d6bb11e1873a3963e0d14.npy +02958343-ab7eaf660f1bf4db23fa56f2e03fa992.npy +03001627-813be9a8485050571563f0911e3e5fc0.npy +03001627-9e519ddc82bb9417813635269a32e293.npy +02958343-5c5908b7a19d8df7402ac33e676077b1.npy +03001627-b944154f00e7cf1fad484915511ccff6.npy +04256520-2ccd286e8d5963199201f2703b45dd7.npy +03710193-4ef4cdfc65eb235aa26a056a2194a6f0.npy +03001627-e4214fa7a544e12a37b2bb75885cfc44.npy +03001627-a578b0027e7d9ec7b2ca3ea77e53abe.npy +02691156-4afcc2cf695baea99a6e43b878d5b335.npy +04379243-c418195771c7625945821c000807c3b1.npy +02958343-56dafc275ef1367d307cb03f4c762959.npy +03001627-5cbd738436d0523d6996454765a52e50.npy +02924116-a642cd8a3cf8de31797ce0caffb8a237.npy +03513137-272cd30169e040d3aac6013f3e2b09f9.npy +02828884-65470e16a5880d4dcb2a965e75be701c.npy +02958343-f90ffde4e5ac04bcc627f7f719e1032.npy +02924116-e13587cf4367206627787a85c3bfabc6.npy +03207941-66725b8cad4355a03735baeeeb56a00.npy +04401088-ac8d3abc6a6f7a939260029564d4cf0.npy +04330267-a98941af1bff5bc6843f813f752a5e35.npy +03001627-62d160f560c31e0ff1d6726679b21945.npy +03001627-6def527e32885b7888dcbe86402c7c15.npy +02924116-2292b067ccd1bb2dff93e4ecafd3dedd.npy +03642806-7f6bd9a933f6cbd33585ebacb5c964c2.npy +03467517-5fc56e6d220d775e381b7fbf79296afb.npy +04256520-485fd17a8679ebea638c2f4fcd9a8e7b.npy +04379243-53bad3b72a7b6c1bd810b14a81e12eca.npy +02818832-1e820e0daaae16c7c3bd24f986301745.npy +03642806-5baaa726f51cd09b507f3bf1d3472684.npy +04379243-34157148280e9342d810b14a81e12eca.npy +04401088-a3bc032d0842d570348e2c62a688b780.npy +03001627-6fd76577d0df60669b9f2eb77f5e247e.npy +03001627-8bd8c34158a3aa04f91663a74ccd2338.npy +02691156-b70b049cacaee0f210af2c858faa12b9.npy +02828884-c81cf82daa56a165271513b292108db.npy +03691459-576fbdcf1aab3887e4e65d5ecb84eef4.npy +03624134-948e15ec5f61a445f21c57f8caa5d803.npy +04530566-3c041c05395b37782c8a76ae283dd98b.npy +03467517-6422681d33a052c393b667ec2f48a310.npy +04256520-787e23d8521faa3a6b3538efbf4faad.npy +03636649-34020466b4342812218c9f1216abefd.npy +04090263-85a1d16ecd3989cd2e3059b0e19cba0b.npy +04256520-6a42a50f5f6d959ec036a40816608369.npy +03211117-300b49e25538c0ee5088116dfed138b9.npy +04379243-d4a7a1dc0f1a51986f15d61c214769af.npy +04379243-778d75fb125165379d297e74104d3ac3.npy +02691156-407135e4c3c7cf2523c853ced7da0343.npy +04379243-1600f311c31ad47fa4bec68446bb57f4.npy +04530566-b9a6e086fa26907897eb0d3a9685d3ed.npy +03761084-95bc6fb98624ea3229d75ea275a1cb4e.npy +03001627-e6ea5e70c2f29d881e8fd793667dc14f.npy +03467517-214f6a08b78670de2cb522418d5742a0.npy +04530566-b31884906c966b4fa54923b7d85aee7d.npy +04256520-5d2ff1a62e9d58baeaf288f952624966.npy +02958343-4c456e47a09ec8c96c13d41607812b45.npy +03001627-e67c305a676930b123c95a77265c8dd.npy +02924116-c4d20747c3ba3ab8d4a3ff2918680f4b.npy +02691156-5bd21df38ef89239ba4ae55719e5e195.npy +02876657-488139f06d9905d830ffab76baff35a5.npy +04256520-55432fbc7604292ed9993d66b5a0e2be.npy +03636649-8f85c2195890ccf671f0940f5ed452dc.npy +04379243-5be1589df948b227c955e5ed03ef3a2f.npy +03001627-710a0a005ba7b0cd6a6b5838ef6b356.npy +02691156-3a72adcf14ccec9965f50257ecdfa5c7.npy +02958343-bc8e978655bb60c19fec71e8f4aac226.npy +03001627-42c27211881f1377d7f7a4c4609b0913.npy +04330267-a0cc38afc62d6d102c026fed19c0d206.npy +03636649-be5b76136b37205738e43095496b061.npy +03593526-2a7c0beb84e99d6636b0f2a1430e993a.npy +03691459-e314110b72e1d310dae4b8efbd2ae014.npy +03691459-c72753b17403466c51fb196f32308d0.npy +03046257-bb0b0afc8059701076e9713f57a5fcb6.npy +02691156-b9fabfa6d5fedbc3a8e091cb544689d5.npy +02828884-2cdd25a716ab2ac12056b4bd5d870b47.npy +02808440-b657b07733051ef83c7c1f545abb6527.npy +04256520-aa7489c9c7cd0c1dc3a1be62b60323a7.npy +03001627-4fd4cda3d713bb29c8687ff9b0b4e4ac.npy +04530566-5f5490a8a7af2898b1bb46d2556ba67d.npy +02871439-9c1781c13cd9bab154b4839e5dc7b736.npy +03636649-e86e6469000a7e7deb39e694585254c6.npy +04401088-767205e25c8755fd89d59b774c6bc1b3.npy +02691156-edb916c2cdc2d3b9ce2cec85ea6ae00d.npy +04460130-acc8313c1f285a51d3a20b36eab6731d.npy +02958343-b688cde1a09ea5d3b1bb46d2556ba67d.npy +03636649-58588e4f7c57007e11bd92e9690e7fc2.npy +04090263-fee4130baaca04225516c1e9dd717741.npy +04379243-149b59e69d25ad09c3bd24f986301745.npy +03636649-2a5e2e5ec5eb986385bf3590978fc71f.npy +02958343-a9abdcbb5cddac8117e76f36a4eac3ec.npy +03001627-c7cd67d1a9def55aa192483aa282f8e5.npy +03325088-642752ced8ceeff0b362845c6edb57fc.npy +02942699-e3dc17dbde3087491a722bdf095986a4.npy +02691156-958c54f8da7a1359cea2c06142ecb1b3.npy +02828884-866b0fab7a3e54053555de1e3169ac6e.npy +03046257-d512e75fe5142f9cc23b8534bf62ba29.npy +04379243-5510ca90cc08d0c4e825832d1f6b3273.npy +03948459-c34d4ec7a3340f375e9786b1603f45c8.npy +02828884-faa74f8980fadf504777535b9098089a.npy +04379243-c8ee4a8b703180992985858e6f5832da.npy +03211117-d8a44fc1f40d0ec271d096a6914e7333.npy +02933112-a5ce16faa5ecbc4bc6a5c971c030877d.npy +04379243-cbf3470a35aff67e483fd274b1c29225.npy +04379243-63606249852d537ee958df2e8332e31c.npy +04379243-2aca16abe2e5175281faebbdea6bd9be.npy +04379243-53c11596c3fc36a8a5094cb6d104b35.npy +04379243-ed964779023b7af85f6276ff8d24e520.npy +04379243-1f7e4805b267e71f21da01c0bdc324b2.npy +02933112-7b02f0d94886f66a121859336e292a5d.npy +02958343-6d7472ea15dd5c18433f1e7c64b884cb.npy +03691459-c7b58eb662984d701df2664cb33da9b9.npy +03211117-7621d8ca26b9296b104dc10235c6ecca.npy +02828884-b57079e504413f02ad5067eac75a07f7.npy +03001627-3b5eb8c85130476a38dc42f802aebe31.npy +03593526-b8e8182813626e7a3792407aee21900f.npy +04090263-5b99c77733a74f36b74ae5e50aa93037.npy +04401088-54f1cca754751ec14857f88b08630a42.npy +03211117-786f74cbab946ef78517036a5ca6b1c7.npy +04379243-6c0fe6541769a3f6ff4f2504a49d0458.npy +02958343-ea7ce310216a5a64a1bc65068a7d3cef.npy +02871439-ed6e541f87d15abbe76bc197b3a3ffc0.npy +04401088-80d73417fa12508d7d6b888b4eb1ac9f.npy +02924116-bbff113e57da6566e99562689078395.npy +04379243-614b46cfcbe04994d91158b2b7873a40.npy +02691156-dc3bfc83bc2d1db643afdb9c81ff2967.npy +04256520-dc079a42bd90dcd9593ebeeedbff73b.npy +04401088-2f468e01f4fdcb54d81a607e3ac2f927.npy +02828884-5f0e28d1324397d9c0b027ae5b223d6.npy +04379243-65e4bde475632e5bbeedb4c8fd29e2d1.npy +04379243-9c5ed0a888a5807ca9b8d9d3b5cf54cc.npy +03467517-fa6e4f4c21032d4befe0d4e1eba2e3af.npy +02958343-dcfdb673231b64ea413908c0e169330.npy +03691459-f153783eb4ae84f2405c6851258f4dc0.npy +03001627-e51df025a8c64a483147d51c94487639.npy +04256520-25f1d50f80494d624b3c42e318f3affc.npy +04256520-a55140d6d7b1148519fb4103277a6b93.npy +04256520-2853c28f2690b0a48888e7425bc4b85.npy +02958343-5b7985f5dd37dec2c2509a0026f2a07d.npy +02828884-941c1bc0f10560a2310d80140e59b9e.npy +04401088-774bec08bd534dd28a1687774f473322.npy +04468005-5824eaab128d5e89109becaa93f86177.npy +02691156-a49a75d2b22c9eeeb87697d3904b168b.npy +03593526-b55c349c1a770df62edec63e41367782.npy +04401088-5f919ac1f790280f563028cebd5782b.npy +04379243-f65decafeb2b8518dcfcef693e7ec696.npy +03636649-53d7272eee54bad2f841233486fac2b.npy +04530566-5b6d80dac7d626baa218acf6a387078.npy +02933112-96969d7adc540bf686d53ab0fe94e911.npy +04256520-608936a307740f5df7628281ecb18112.npy +04379243-7823530be7179f50e08668a8b378b020.npy +03928116-336e206fa25555adf4e0e15368c84346.npy +02924116-d54947552a72fd70a2ffe654fbdaa117.npy +03636649-2324e8f0e334c218f7248d9dbed7a7b8.npy +03001627-341a2d3df9800314fa260f4362cac599.npy +04090263-f05e17d75e8f3e2ce378cd9d51dc5be0.npy +02958343-17f89c25a3142ee09d2b99af43da16b3.npy +04379243-2325ec6e77f29578d9b00ae2f30c0a5c.npy +04379243-1deaeff17e093d1c8029e7f07c5ed73a.npy +03636649-76db5f1046bfcd97fcb8d8c6d4df8143.npy +02828884-8d9903f1a197ea9af4fb4dee5181bee.npy +02924116-3c1395041fc842dd193d7855ecfc1bd3.npy +03001627-97febe7745f35b9183e0de42574c850a.npy +04379243-da76df9a506534fa5eee45c00c4de9d3.npy +04401088-ae0b011684a6c46c10bc2436075f6a52.npy +04379243-3d01fd2f13ece278e27790b0ec8671f7.npy +04379243-86eea3415d5a61df490ad276cd2af3a4.npy +03593526-9b9c50a911bbccb0bd16d4490a10a752.npy +04379243-2144d79a6310f1e2934cee69ace78b94.npy +03046257-184454aa3ff239ccb16cd2a45f8cec20.npy +03001627-8031478c3fe31ddcc337647acafe65f0.npy +02691156-828176e6eaee542ceb532c8487004b3c.npy +02958343-cfc8e5925bbec93de20af544ce47dd47.npy +04379243-776732bc127417f28a7219d923f4718.npy +04256520-4ad0739a957f27dcad2fb8cd0793fa9a.npy +02871439-8fe314abb1af4d23e7ef9fff09638f8e.npy +04379243-7a33f3e6c8a1cd0c9ccce4c6d5bb195f.npy +04379243-9b673972e8873bc403c57e7ce69f902.npy +03325088-6b48e8d129f22956b362845c6edb57fc.npy +03001627-f19e8da9d8f369c531e63f1270e2b445.npy +04468005-30b543e0b45fba65e810c01b1498aa2b.npy +03001627-884341d10af51df9737a00f007529fbf.npy +04256520-2ff7a54101b3a51283c1014d9ff52cf3.npy +03636649-1852cf691d561b97760c1770d1a1230.npy +03948459-da0dfb17cd9ab1459be47ac7c7e37815.npy +03337140-a23e4375e78df8d0e7ecdbe73ef4323c.npy +03636649-f0421826cd511f401592f292ab531da8.npy +04379243-1e5db720b375205315bb540f42facfa9.npy +04090263-ba49c58d6d320357f1cb19f636b1c2bd.npy +02808440-d401cc66a61e9177355e3146e6882aa4.npy +02691156-fcc94cf74fb886b7bbf3143b1cb6076a.npy +02747177-f8b6bcf0dcf240e567e4c36fcbad1d04.npy +03001627-e4ac472d21d43d3258db0ef36af1d3c5.npy +02691156-56ec4638067cfccd3dd4ea7aa5ac3a5a.npy +04256520-118a7d6a1dfbbc14300703f05f8ccc25.npy +03001627-b5350feacacdec9e1a4c9a8c5e7ae925.npy +03636649-ae37dd444b0813b8fcb8d8c6d4df8143.npy +03001627-1f82011c2303fc7babb8f41baefc4b12.npy +02933112-4a4ae602159a711c824662341ce2b233.npy +03761084-15e1055bb947747048407a54b1fbfda8.npy +04401088-ab9c56981431ec70f7b18034d9df056d.npy +03691459-e911bf2418eae6241574d21c0c95092f.npy +03467517-fecefd8313bb5bcdd86d4f3257dfa437.npy +04379243-86c467981ec229909b21a1a3552b6ab7.npy +04090263-e4289a32092b3e667f8cba909d4faac5.npy +03948459-2ea634a6b6e9323a035111f6a92f4e5.npy +04090263-6efe78a38abb45bebab70e35b0e13530.npy +03001627-fc66e46fe850a243f51f77a6d7299806.npy +03046257-57c8fe2fb023b648ae29bc118c70aa10.npy +04379243-bf29f1397cfcf056febad4f49b26ec52.npy +03691459-94ffa3ebe53ca46327eff743d2137fff.npy +04256520-f92dd3f4d0b4475514038d588fd1342f.npy +03211117-1e6d8cfd991e829ae441f5bb6f88ca61.npy +04379243-96dd123d4b16ce2afc62a892407efc0c.npy +02808440-3fad29fafe787406b362845c6edb57fc.npy +02871439-4623d2cf0aad860bed729ab50bba7ddd.npy +02808440-881043bb57784d4e3b918969f743aebf.npy +02828884-1dfcce44c2f98d2c81e7c6cfefba0d68.npy +02933112-9aedc18053d412048ca998f0f87d0c84.npy +03001627-ca804e0f760537cac4545d2091e9ba5d.npy +03046257-4e979d296586eeb880aaaa0b0a5c59dc.npy +04379243-f41ff2d573ac836dad3a17b61c0ca09a.npy +04256520-4760fede61ec9babef410cd6a99ddc.npy +03636649-fbb4a4faa8f2faedd661ff085a0f14b7.npy +03325088-eec7f9256d78d41ac5e10683f58486dc.npy +02924116-d53912686e1fb1cdb687507a46e99ba9.npy +04379243-91aa75800ef385e9f51fa0238791f5dc.npy +03001627-ea62254f0a5650579a8ef44e1d2c5b75.npy +03691459-24cb5019659114d5176545ad403d244.npy +03001627-6d5d42d1272467953b63c9ead28992f1.npy +04004475-ce2e32b26627c25a64368eb37d895c58.npy +03001627-6caccdad9f8d4f0a7f1cdfc0a8f38f2e.npy +04090263-e06992f45548f0416b34c3751bc447d.npy +03691459-cbfa6c888ffd893b31b5f9e34ff03906.npy +03001627-9a37886efaa98354317e912dcf9f9b6.npy +04090263-c8b9fc62a220f63fbd6317b3418b592e.npy +02691156-a1a419007c828bf290b1d6deb98feec6.npy +03948459-ca7ae7fa6fb11ee460956dfa3cfbfa04.npy +02924116-96aa88bc3fb67b5fcf8b2866c5b881bb.npy +03001627-30f077da43f30e64c862eec8232fff1e.npy +02958343-491df319c52dccdafb5c1b0f759e2bc1.npy +02828884-65aa814b10f778b2056b4bd5d870b47.npy +04401088-39b78390f8d5067e983a0c5c52bdbaaa.npy +03001627-b4584ca6fe22a0be599937922ec198cc.npy +04256520-57f383c1eba6bdbbbb07e1e44f4c30aa.npy +03642806-dda1832a36858f06ea791b47ef8b531a.npy +04379243-98440aaa709af51192d5b25c536d8044.npy +02818832-21f11dd1eda2b1dcf51f77a6d7299806.npy +04379243-b130260b9f5d05bb5510d59f3ab1ed64.npy +02691156-8daba5f5c906b3b331fec775e1dce6b3.npy +03001627-61fb89fca404e37f598bcf8ac674b63d.npy +02958343-b4a0711a46f9e2bdba3e2415e22cd45c.npy +04256520-447281db87623862413102507b68bcb5.npy +04379243-238a974ab3fd46e0ba7b07dcdf3d00b4.npy +02808440-6787698a1fbd9a6d44221bef0fa3c36b.npy +02691156-4b20c1736440ff9d90dd6eb126f6cbbb.npy +03211117-66a71f2cb778aa726321867cfa9ee57c.npy +03642806-cbcb79f534518dfbcfe78be5b7b99c8d.npy +03642806-13330d1e7b199dd82530b9c2b65d3f86.npy +04256520-1dcb4a52dbd349ceb9b8611336bc3051.npy +02828884-f0df158b0694ee1f2056b4bd5d870b47.npy +04530566-f31b394d652f0bd0592f00ecf480857e.npy +04256520-7d04346070eb5b9d19ea2628fa9897e5.npy +02808440-d2a511578a387365ede9471c962dd6ba.npy +02958343-ea76015145946dffc0896a3cd08800fe.npy +04004475-b9a71c2cefd6da6ade43eb83c675552b.npy +02828884-f5d370e9fe5b7452dbbc9440457e303e.npy +04090263-7ee51d04734c82198ca4596df3cbf136.npy +03636649-d3a3d52234e722825208aab875b932bc.npy +04256520-f2edaaa8bef11dedbac8a2db6cabda6a.npy +02933112-7359539c1b62cf1e29a50a2b3c5e5b6.npy +03928116-4935addf7de12539c273f5d1e0123211.npy +03691459-5adc7f63a154a43be9bb042b8623f922.npy +04090263-faaa98e92d722d0ba7dd22c0aa3913f0.npy +03001627-31d026a65b64c4d5f529761e946287b2.npy +02958343-6acb271397e6f9b9e858db1dc3499392.npy +04530566-e3923f2d2fc2d1d39263b5578aef09fa.npy +04090263-404acdd4cbb0544eeab5ee569c9de1b1.npy +02828884-276195bc09970fdbec0de4d645145eaf.npy +04379243-f36f3912a86717146b82340329d7ca26.npy +03691459-995ad1befadce7771148996e35417db6.npy +03001627-4918512f624696278b424343280aeccb.npy +03636649-85dfdbe562059fa058b65cbe3be2c45c.npy +04530566-eaaeb5f4195eb55c1cec93449f0f44dc.npy +04090263-f71fd8ebea347bfa3ed1dc72750c6f75.npy +03691459-635db4f2e3fe1f918e14a32e5ed95bbe.npy +03207941-d08a36f582d2acb5b425b904f1063e75.npy +03325088-14cbcca59f500f5835efe6970c23032d.npy +03691459-196d5295dc5c62d513bedd75622dc40a.npy +02691156-96a69c2add6d55379a6e43b878d5b335.npy +03001627-3b606ca14c5f968319fb4103277a6b93.npy +02691156-8259a1fdcb9bca7526360e1e29a956c7.npy +03636649-ffc3e351b9ae77b0d42b9650f19dd425.npy +04530566-2c7a846828d3584f2e332a83fed6fe76.npy +02958343-b9e20b751d869418ce2714c5fa8be19d.npy +02808440-15c43d52c1c50d373321831d2245cf06.npy +03467517-7e49ef6e1b1dbc8dfe96ea0860283ff8.npy +03691459-6592d33f84263ef435cd53a06b1d2317.npy +02691156-aaefbfb4765df684cf9f662004cc77d8.npy +03991062-25a032e5624789da843bb865a04c01a.npy +04379243-3ba61eb411ec52c41586e0414b03ff10.npy +03337140-f5c863ccfd78cc6591c352d02061b3f7.npy +03325088-372e27ec3af50a91b362845c6edb57fc.npy +02828884-a8c8aca72463418581faebbdea6bd9be.npy +04379243-e9faaa484cb11948cc89f898f3cf6588.npy +02691156-22eb91041de27ca4936b2c59e7c43ba.npy +03001627-634524d6d74142ecd2b12aa6a0f050b3.npy +03636649-af93ccabac8d1aa9f4482a3d4ebf4782.npy +04090263-a52c4c07d951fcbc3068951f59ff267e.npy +04330267-af07fd43dde94e02bba2a247817a4593.npy +02691156-9a8aecab136ce50db7ef47444625afb2.npy +03513137-3497a6217d54da094dd343ea1de55435.npy +04256520-d5a11602655790bcdf6cfab91d65bb91.npy +02691156-5d5aefde5935fc9eaa5d0ddd6a2781ea.npy +02808440-ec1d737b5962bd306e12d65bc1882e95.npy +04401088-b7ebfa514d14036e2da685d55be1eb.npy +03211117-1063cfe209bdaeb340ff33d80c1d7d1e.npy +04379243-a69b27f76baf9f75d612e9885a7318aa.npy +04379243-a133b092d24da436e7d9f0fed41b005f.npy +02992529-73339a7ed1e72d89aef10502d58d4967.npy +02992529-4e8cb66f915fb5ac5fdc2445fe061736.npy +04256520-4146baad4a04882613f96345312df593.npy +04379243-760d38c2740eddfb8b38796afe7ee552.npy +04379243-6cae7a045734cfcecf03af5e7a1277b.npy +02958343-9fa56c19e4d54cca99c8d14f483ffc82.npy +04401088-ba669a9b03186ee8108c9111b239151.npy +04401088-29cf2bce2e67ae76264e721f309fb873.npy +04379243-615417f66fc542c6f51f77a6d7299806.npy +02992529-774bec08bd534dd28a1687774f473322.npy +03691459-17ba9b90304be1b4ebe67d9b32c3ddf8.npy +02871439-fef03ca588a2b475a7bde56da6d9a270.npy +02933112-42c3c76c8c8912c61b17743c18fb63dc.npy +04379243-59cd90e24a68f3f5f1783a44a88d6274.npy +04379243-29531549b0a6a0f5ed403132b02528bd.npy +03001627-1803116582841b39a8ecfcf20e8cc0a.npy +02691156-58fe58e9f7431a1a428659c2b5124968.npy +03046257-422505904f773dddb441e189e5a85c02.npy +03337140-afaa6975c6000ecc4c3aee8e9d3a6ffa.npy +03001627-375aab9251b2df59b7a68845946bb67f.npy +03636649-367773a008b63a2c5208aab875b932bc.npy +04468005-277c840eeb343b7d85b408a8edc983b.npy +02808440-6e0d5ac416c002d13321831d2245cf06.npy +03001627-99996ded94b8bf974cddca4ca9fe5080.npy +03001627-a1adf14b24469f8835acfdef2ece21c0.npy +03001627-e50825b2477ba5a0dcc52ca811e565.npy +04530566-340a4a4420b4d9c0406483a4cd65b281.npy +02958343-12d7c4013415ea147f5b0cb87a91de52.npy +02808440-52f17cc850b55edd54d7082b34825ef0.npy +04004475-e00f543043e36ba2199f2eca998ded6d.npy +03001627-5aea2a227125a81bccda8d28b44378b7.npy +02958343-c4744d66623e04b7518f93fcf50bd8df.npy +02691156-c2e38200a238177ebbf3143b1cb6076a.npy +02992529-2293983c6f234d94e304974abc9afad9.npy +03211117-d32688a505930c96e2c8e43c97ec5a85.npy +02933112-2e6c2878b005b5c8bd7feb85baf9225b.npy +03642806-6fd01f7db45bff66cf01bc59d215f0.npy +04379243-455df1ea3058c48e33c1aef7ee7c6797.npy +04256520-d0bdb5de2ae0de1adfa4ff010b8b9d1c.npy +04530566-cc3957e0605cd684bb48c7922d71f3d0.npy +04256520-6f08148e6be15ec812ad7c55c944504a.npy +04379243-539d207a10c615fe76bc197b3a3ffc0.npy +03211117-61a9c9dd90089425769ba004c0947e77.npy +04090263-c7e59e374c2cbb7ed33646b0990bb4a.npy +02808440-e814a58e52652f43e702e0688ba77bb0.npy +02992529-2601fb1cdef9d37223d5a55215ee8f43.npy +03636649-89ad10075443cc8ece868a9ece283694.npy +03001627-ed9a4172130d3d5baf1a85b857ec9afc.npy +03790512-5a997a42abaf1a0d52ee90e577613070.npy +04379243-7a0ec4445356a79410643b0cbd7095e7.npy +03001627-2641f174d2d240ea788a5c6586b10c59.npy +04256520-a84ff0a6802b0661f345fb470303964a.npy +03636649-9c2a936a664a59823c10371ef1aaa57c.npy +04379243-c26d26e409d01e8420d2507f5cf72c4c.npy +03636649-3fb06dd95ac94436f51f77a6d7299806.npy +04401088-436d7a114f72dc03d4713685ae50fa13.npy +04379243-4b82103c9ee9ae4f98e0d1738edd4f19.npy +03211117-21d627f21efd9298c9b80153270af5ed.npy +04530566-215e4b59683247378a3e8bd3a4e48433.npy +04530566-a4d1ec9841281a3cd1e97c10e2464c2d.npy +02933112-a01619556405ba3f2633ff66beb9cf31.npy +02691156-19604020a86ab1790b1d6deb98feec6.npy +04379243-e83930a4a62413e1187ef2b10c31bd17.npy +04256520-c49d9fb6c8b32b265beaf00da5b709c2.npy +02808440-24bbfd544bd0db74ba2cb2a05654d738.npy +03624134-6070b6817869c14ff02ee453ff283e26.npy +02958343-45953aa831508fb51e0d92ae9d1b10cb.npy +02691156-9e8ab1862683399f570726399d67ccc3.npy +04379243-4ceba450382724f7861fea89ab9e083a.npy +02992529-a0efaa2ba04bf091adbfb30d8d1b297e.npy +02933112-4b2bedb7014636afd38913e96bbf2a5d.npy +04379243-7fd8601b0b0a01c9beedb4c8fd29e2d1.npy +04256520-c304687f0778986c6f1e631ee7d027b9.npy +03001627-658c983e6982f6a43b48a711df82173e.npy +03211117-2ba6e0c4ea459f84f5f79806bd65844f.npy +03624134-94f20e34be2d0a6dc728559272e2d712.npy +04379243-4d6b0bcf351183bef8c4b4cfc2702232.npy +04256520-9808424960998ae93d4d11ac89066d36.npy +02958343-149978eefad83cbafd8e7b05498794b9.npy +02691156-9a4bd6fa35e2e59689437db5f9b0a8a1.npy +02828884-348c52c333d7a7953722bf980385c3c3.npy +03636649-4a868756ae6404a5c0bc57897eddf6f.npy +04379243-ff9bb9597cac5ef17a50afc9c93f8a50.npy +03211117-d10dcdae2d7645ebcfe78be5b7b99c8d.npy +04401088-f2245c0ff356a85dda10b9c82531bbc2.npy +04379243-cea242a600c342fd33891f25755e1e1c.npy +04090263-b01199433137d6123547ed4d05d19f04.npy +02691156-a53846c68d0df55fbaa5dc5e42189b81.npy +04379243-f4f000158796b9593002ed4dcf002f44.npy +03001627-fbd234dca7bb201c1bfa4cc8d66175d1.npy +04090263-ca25a955adaa031812b38b1d99376c0b.npy +04256520-de1fc3a00a11e87af62af8489541547b.npy +04330267-87530f4483e4f4a0b8183a4a81361b94.npy +03211117-ffc224f284b63b17b0f6d70666df2668.npy +04379243-47aa3e340eb5be093fccb8cf9f00542f.npy +03624134-f5abb706dd1c1e931fc43d5b32fa230f.npy +04379243-532a4a4b8ce7b6feb9ac39a10cc48e08.npy +04379243-db6561b883e56b9072c6d81e4b9f21e4.npy +03001627-2a05ae00b701fda36567137a59cb1a56.npy +04379243-e9fd9958920adc279943cffe175cad01.npy +04379243-8e424220b8f053c81ee2805756841071.npy +02691156-ad85ce4dde9fde14a13757cba42c461a.npy +02808440-31d9bb666cd262004f535519233c8e8f.npy +04530566-eb90fdddcb1f25fca60ce6f0a0028c13.npy +04379243-1b84ce3667a99f1d30bbd4cddd04c77b.npy +04379243-e64876f5590e6fb7c3bd24f986301745.npy +02958343-da73c98813b82014d94cee2a22cdfdd2.npy +02843684-ed8eecb25a61ce8ec30aa7d959330a5f.npy +02828884-137fdd05ae4e69c7a68359455a0ffe24.npy +04379243-2783c8d705a1a146668ae11a7db5e82a.npy +02958343-be28d4b681ab04ecca92a4cdad802b45.npy +04401088-c0969979d6ff51f3db27d84853613218.npy +04379243-7cd2c11133d7470db9278b13f52df097.npy +02924116-ca75cad248b081a52470de2774d6099.npy +04256520-13169bd2b9b02ad44089c2a25bbcbf23.npy +02691156-2bfd3dc8b0630de9e1873a3963e0d14.npy +04379243-a186ef9f36fb95c3bd24f986301745.npy +04090263-fb62c74f88a285a712b38b1d99376c0b.npy +04074963-28f2a5df4a926c3e140a527375fd6757.npy +02691156-5a1d4af1f417d28566cf1b4a8fc3914e.npy +03001627-c76b2d2e9b7cc59e82eddefc99ebacfd.npy +03046257-39be4ef0dfa6833e49c9c494c2fb14ce.npy +02691156-d05cdbdddb68865d2dcd3faa5a0a5f24.npy +02958343-785cb635a01fb7ab2a9eb0f146e94477.npy +02871439-5dca62207dfe3e0e1adca12ed8c544ac.npy +02958343-b0a659083ec6e936ca92a4cdad802b45.npy +04256520-5cfec53fca53be4cc9fce74028b97ec9.npy +03211117-339950e98c5d943a20685b5a7e34b501.npy +03624134-198a109dc6c19ba4c09190536c002dc.npy +02747177-c0686f7b0da06f36cb2a965e75be701c.npy +02933112-98d2b95fc4f59c426ba8b3973e201d74.npy +02933112-7aca460dbd4ef77712de5317fe5b354f.npy +04401088-b35c2da756f8df5aa0eb5a85db887292.npy +03337140-3259ed5798f633c8784168ad9d1dbd5b.npy +04090263-b20e2aa33c1a54fba791c4f82c7b99c6.npy +02871439-ee00bd67de87106cda268e3f4aab0907.npy +04401088-f9418c13ca82fb887f75fa9740df3aa6.npy +03928116-e83cec9fb3e0d81d82c5b9bdae127001.npy +03001627-47b37ce8f304dd0bbababe11fcea8796.npy +03001627-1ace72a88565df8e56bd8571ad86331a.npy +04379243-6176df18ef54e0a3f12d7184a2ad3430.npy +03593526-353015291fdbc5589de5525299ba58f.npy +02808440-bdacdeb89e174d743321831d2245cf06.npy +03691459-adab0912bc0ad1271ad88f716ea80910.npy +03001627-9fd3f3034d3e867336587f5b4db3e782.npy +04379243-aa03428d48a820697a138f06ba3ebae3.npy +02958343-65e3e2893669a09cc7b48e36e31209b9.npy +04090263-479adb86f868044b82771a19d76c960b.npy +04256520-c4d472c94921bfc63a36ba9606d732a1.npy +03001627-e1f6a4f5c856ac07bf80985a99195eb8.npy +03636649-75e788db909c6e07bd4160ae8a5798e4.npy +04401088-2bb42eb0676116d41580700c4211a379.npy +04530566-22a66588db3822831d20b5ad5ef1cb1b.npy +03001627-82d8391c62e197161282d4d9178caa92.npy +04256520-2b9612dac350a3d6764a784715fb668.npy +04468005-43ef3b9a4b46aed5e17c2efe05365fd.npy +02992529-e6f4ceda4907fcc13c47272ccf8f316c.npy +02691156-2997fa1441eb7bb735fc197bbabcd5bd.npy +02871439-abe70fd61bf0b6e0504af6e1321617aa.npy +03593526-41dc952ae902bb2d2a087337e55e3e2e.npy +04379243-de24c1b05f0ee7dc58674871bd9b2e6a.npy +03001627-cebe4dbc363265ce46746f657ed598.npy +03467517-280e5926a81270463e148e250c0340d.npy +04379243-589d2e18f9b85e4715dd7d7985e749c1.npy +02808440-ace556a5c45fcccc1c17aef130ed6213.npy +02691156-ca91bc0603ac0b808303d346f4be7d4f.npy +03001627-dfdb73c6bb358fec18c4d7ee5b83ed4.npy +02828884-f123b8da77f6d17e50f9fc0e2c94dd76.npy +02691156-d532217c7fabf1d44e8b48a4c01e36f8.npy +03761084-753c4428f12b2233b5d3c5ea5d496caa.npy +04379243-a757f06addc26f314b3c42e318f3affc.npy +03797390-ca198dc3f7dc0cacec6338171298c66b.npy +02828884-8f102661c3efbdd184f92715bac39b74.npy +02691156-f80343ac3064e74862347b4731688b0f.npy +02691156-4a9d3df03a7d41d77209009cfb89d4bd.npy +03642806-818a8f85eb37248f7e51366b0cf7747.npy +02808440-b65f30d853b7cc96f86926db87a5c419.npy +02958343-b61f6554d83c50684fa22c482c32995d.npy +04256520-b4c1dafcdd5cfe67d070a4f9796238.npy +04099429-f77daf9340eb6faa262f035db428cc4b.npy +02924116-f0947e7dbdd0c5f1a70590fff7a7d815.npy +03001627-5695fd37d1e673cebf964fc57f6a7d6d.npy +03001627-85f4e9037425401a191c3762b497eca9.npy +02691156-db4e26b10e48f0202eb17a4a1756af76.npy +04090263-277fd403270ca32b72e5d9d5746d6da7.npy +03636649-540335c2788125cbc9dd845c88786daa.npy +04379243-91dbfe4dac593d3e35836c728d324152.npy +04379243-5808fa88b17592217caed426d97afe76.npy +03001627-d18f361e22f7626b707cdefe012d0353.npy +04379243-ccf0059e0697982ecaa22a10624245b6.npy +04379243-10c25bdfea5eccfd153555abe935e806.npy +04256520-95829021770f25fe15afaa91253fa857.npy +04379243-7df9115b511668bdde98d10ab5975b59.npy +02933112-86905b35aca5a3f11f8d8332ee17945a.npy +02933112-3b577e2c7bbb8ca4c59350d819542ec7.npy +03642806-2f9cc3e20647ebb1cb8118818e564f96.npy +03001627-47db22433821989e35910b9c436db932.npy +04379243-7a1e70d3b087970a23fe3501bb9e7193.npy +03001627-a8da22b87a249bc9c9bfaa062f2e9d4c.npy +02992529-f760cdb0f8cbc6fa3c28e819722231b4.npy +02924116-e8a03353afa0253c15a7b5ba389301f1.npy +04379243-f81301719860a0e14626b1c05b10e40e.npy +04379243-cf046edeff204b81cdf7280ff8af6720.npy +02691156-58e967e02a183d49bc0909d98a1ff2b4.npy +04379243-2fcc875b28c5557dcfcef693e7ec696.npy +03513137-7f03445e003b692f3fd0acbaa54efdfa.npy +02828884-ca238683133f6a7f38f6614f37ed2984.npy +03790512-8fd0238d882c6f45e3e8453287c65951.npy +02818832-df4d5db0d81fd245c8b7b6fe706a520.npy +03211117-5757f2fe8b1b4b559ee60daa6185f65.npy +02691156-45a4b43dc4c77dea6818e4a1f2613507.npy +02880940-5f2ef71aa9b94edbb84959963148f2a2.npy +02876657-aec6aa917d61d1faebe67d9b32c3ddf8.npy +03624134-b16961b5dc1404d4df0719d707e5d64e.npy +04379243-520b83f501329fa955f46d55537192b6.npy +02933112-a2dcaeb9f64566672027cee422df2aa3.npy +02958343-bb5264bf7306327abecf71e2e014ff6f.npy +02801938-80765e61d1305e5936b0f2a1430e993a.npy +02691156-990431d8a1ef435bbc913a3935f0ae10.npy +04530566-1f883bf1bf0f6bc7a993db466b6d73d3.npy +04256520-aee5c13c32775f24b1e5b4bb39b2ab9f.npy +03636649-f6eeb5d67c32616648fda83c10428379.npy +03467517-e0d7fbacf037855393f0194265a9746c.npy +04379243-7d22cd72bf2762b19a4b266ed4d507c9.npy +02924116-73eb995e9b1fd1377cd3cf23748abfc7.npy +03636649-66cf69a98ff895e2b55fde51a411949f.npy +04099429-9f71204ece40e327c4c8e4ace0fc3aa7.npy +04379243-442546c2af24d782d197f67767b32741.npy +03691459-f1cab229b68c9ac1c4dc2c94f81faffa.npy +03211117-9b66be71bb69a85b3e6db88fd9485c19.npy +03211117-9852ad45bb14a66fce2fdea99c5936e8.npy +03636649-639c2bfefe1bb6af1cce8c25b11ccdd9.npy +02924116-ab13c9869343bd8cdde6e3a892dcc1a0.npy +04401088-320d0f9256ab9cc3a046bbac53886364.npy +04401088-7114283643761bb4a5545c1d5c84020a.npy +02933112-253c1fd3743c47234da5feafe6f1c8fc.npy +03001627-e4cc5cee7b011df316037b4c09d66880.npy +02933112-c700103d0294eb186c66754c2bdaefab.npy +04530566-c8bce97e59665f2811b9a587ace886f7.npy +04379243-c1dcefb2613afebfebe4b9fb2707d260.npy +04379243-4b21a06b433b563f450195dfcfefd1b9.npy +04256520-9ecd7b01b9be890d19fb4103277a6b93.npy +03001627-a7579c588d289fee4671d97b0fd17f51.npy +03001627-5ce98a1c247f0a2d623ddc7262bf3bc6.npy +02933112-4068c751d46ca222de650492e45fb14f.npy +04379243-33f9152bf617f22a16a2b5862518c93.npy +04401088-14726c2482a092d3a9fe1734a6086750.npy +02958343-abd0aa2e0ca4fc4793249f89773e858.npy +02691156-d25572a7c7bd40a72d716a8ba99beff8.npy +04090263-502bcd962340e12838bd5e76f1ee812b.npy +04379243-9cf9313fcb038801815b2b467e8e2eac.npy +02691156-a28b92f0ed237d6d13256b8319a93100.npy +02933112-a6d90c5628a598a1598a453fd9fbd988.npy +02691156-6fc4f30540b2fa9dbc0909d98a1ff2b4.npy +04379243-53e8fff5ddea1b47d44dc16af152638.npy +02818832-94855c7a018d53e3dbfdb9be425ff2e5.npy +04530566-8d7c4ca5e08a8a3a6d4334e260ec617d.npy +02933112-6e2beb63c61144f54da5feafe6f1c8fc.npy +04379243-1a00aa6b75362cc5b324368d54a7416f.npy +04379243-3779ef1608ed12dae074517a246f1e65.npy +02691156-bad95673c40e3bbd66cf1b4a8fc3914e.npy +04401088-b7ab1b6f7dc5026dea8f4709e6949c8.npy +03991062-2ac8e00463d247119201f2703b45dd7.npy +03001627-11f1511799d033ff7962150cab9888d6.npy +04379243-2d11e38388d212634cafc8d32c041834.npy +04256520-db49cbcb6a2ac87657b1c0b6d5084bcf.npy +04401088-16c6403551e81a3eeedfca8b846d3b01.npy +02747177-24884ef01e9a3832d2b12aa6a0f050b3.npy +02958343-f723dd6b7a95e230c75bcb366ed55ad8.npy +03991062-106676e68e8031e51085ede6a3c1fc8b.npy +03593526-8354259c3fcf12fa31f42a72ddeda489.npy +02691156-541db123c3ae32cda91f7285bb2efb4d.npy +02691156-707da8b9f37fd990bde4f466a45d975a.npy +04460130-8074bede148f1cbf8a982597ea241696.npy +03001627-9d2cf09ddd9a05fa1f8b303c0da5108d.npy +04379243-d8baf8507ff705dc2787b53b27e2d44e.npy +04090263-b548a4e02e014405de423072102e0bc5.npy +02871439-edab7fdfbcef3ef2f77e23ececdab4d8.npy +04379243-9b18c8de0d9d2882166ddaef2c2c61ae.npy +03001627-b1c221e3ec7fe34782b50ea5cffa80bd.npy +02691156-9d7e431ebd35cdc2bd46d022fd7d80aa.npy +02691156-cf402c23d4ce807d847335355bf4459e.npy +04379243-1cb5ed66917df7b3615b3e12f53b391d.npy +02933112-9140ef4099eadf73887c1a82cf8c6eea.npy +04379243-589e7c32a63816b1d4a147733422d301.npy +03325088-ec1c146241042d2c25faa413356e0316.npy +04379243-7988dedacce42552ab610b0c94236463.npy +03001627-9d7d7607e1ba099bd98e59dfd5823115.npy +04401088-25152b4f593e5c0555940ab8fd747fc0.npy +04379243-4fdb53755e578678cd7f32327bdc729f.npy +04530566-6d71354936e0e1e8c362d63d34a4d0a.npy +03001627-78c9204b2eac432b65b77a565916c7f.npy +02958343-3344ba7f18d9623d549733b112275285.npy +02958343-39957ba700c2461d6b6786771012aae1.npy +02933112-165c00d292773865ae6eaa32356aaf3b.npy +04090263-15cc5a007bb325a3405d5eab6bdcff6f.npy +03938244-2fe82cff107cbeaeb357233991a61d01.npy +04090263-2ce39c653c42982948b7bcada24e2926.npy +04379243-f46d7f7da9a056d7fff16555386d173d.npy +03691459-ff383dd89f76410a49c18a2c5bf89a47.npy +04379243-8c81742da70c5abba7574b4673f4d777.npy +04379243-af0206602e75c8bbdc6a693174c70feb.npy +04379243-798598965a343fc9b0957d845ac33749.npy +02958343-6b44be4025c966d4672601793664460d.npy +03211117-3813c5f6f50bb28a3e2061cce7606c61.npy +04256520-4b9c06e04d329213843ead12644a79bb.npy +03325088-393fa5f93b539b1914b35a7d7cea7130.npy +04379243-54a22269051c9674cfdf2d08e1ba2a48.npy +02880940-2c1df84ec01cea4e525b133235812833.npy +03001627-ce12614d019f86e840ef1c8b63a628f9.npy +03001627-c375f006c3384e83c71d7f4874a478cb.npy +02924116-2bde632f14fa5a8377940b0d988b91df.npy +02958343-2fc99d3fe3f1f3b3b5e3401710af905a.npy +03261776-719b4249339e7eb4c030d1f2c16e4c51.npy +03001627-103b75dfd146976563ed57e35c972b4b.npy +04530566-85ca7456e200e8cb874f0e42f84eb4f5.npy +04379243-98583f22ba708ddb4b3c42e318f3affc.npy +03337140-6125e3064e7324f8e4e346ee2650d150.npy +04379243-e3e1d9e88b396e6b8cae28243a4ae130.npy +04468005-887636e0984bcc7984ff53e2628fd6d0.npy +04379243-ffb5e48fde2cca54518bdb78540c51ed.npy +04256520-6e97f3391a8de74bc862eec8232fff1e.npy +03928116-89e4214536b63bb13fbcdcb4c54d4ba8.npy +03001627-bbe63bca5688ac6b7236a8143b10600f.npy +03691459-f657a906298e9151e3178ebc750d175.npy +02992529-17072ff9ec47bfadc3fd2392bc923b2f.npy +03001627-fd5f6ed4a873c5ec300fe8666348bd38.npy +04530566-d4ffdf377bda1aa5f650f4803ec7962d.npy +03001627-f4b141ab64a6c4e771a782a4379556c7.npy +03001627-18f57a3d41117140ed98cca8f0ccd5f7.npy +04090263-ff6e6c1fd1069b92116f3b4758e85d85.npy +04468005-97ef43be022c84d334a4f565076f7529.npy +03691459-65dfccb2d5e47538a24143eec482cd09.npy +03467517-defcf80fcef4b51b3f431ca2c1260d62.npy +02924116-8114866e788441652b4948f27a5833ba.npy +02933112-a46d947577ecb54a6bdcd672c2b17215.npy +02933112-90e6262b1713ab09fa3b6936d7879478.npy +03001627-c5e3f6da9e818851618dd45f797b66b4.npy +03001627-db0925930500d67d7094f114e4783e96.npy +04401088-2e6c1cc7d262bc36c1d28dd38097a536.npy +03211117-b72579335543691423c841f9d5051936.npy +02933112-a81a218a06fa2cbabc78261b35f7ff55.npy +03797390-ec846432f3ebedf0a6f32a8797e3b9e9.npy +03325088-ec3a09d4e06843823321831d2245cf06.npy +04004475-d12512c99c7836c0aa4b3fb09d44650d.npy +04090263-d0d4e25322d8fd3a1f58b8bbfc791148.npy +02880940-eff9864bfb9920b521374fbf1ea544c.npy +02691156-94843fffd7d2a8c0dfb86dddee1d6ac3.npy +04401088-3993102ecafa0826ffd1164158ab2e9f.npy +04256520-853707d42be3a24c3eb520ff7cd241f0.npy +02924116-43195339c363c8f1cfcd1fbe1cf0ecec.npy +04256520-9955ce757c0bfaa5843ead12644a79bb.npy +04379243-55c2262e68f311fea5526f91aecc0c37.npy +03642806-1b5ec8c5ca53caa5ad6be7ca8dcfc55b.npy +02933112-18a1c4eb2e4b31fce83221ad0d21775.npy +04379243-f85e243539823dd56fa63795f94c4d8c.npy +03001627-2975a651cf06a21260902b587804b688.npy +04379243-15c32aa0f0dcad130bbd4cddd04c77b.npy +02808440-2e61279ce7db97ab3321831d2245cf06.npy +03790512-57a7a9e163e8f087fe11eeaa72c8aa36.npy +02808440-55f7cefd2fd58bd4f4dbd7b2c34ea2f0.npy +03001627-9dad5d3a04753f69febad4f49b26ec52.npy +03325088-1de8f72e190d7ef1979c556124bee033.npy +03928116-3fb81f5f3a3f0d69be3ca6e34dba44de.npy +03467517-dd95faf803299254d57700c05b1862d8.npy +02958343-2b5a333c1a5aede3b5449ea1678de914.npy +03636649-a26a9f9ddb5f345fcb8d8c6d4df8143.npy +02958343-58f2baf01b8a3baf24da76692f3228e0.npy +03001627-ce50c6235cf3ad8855afe589a9f09982.npy +02876657-80a3b56c86f906e5f913a7c27a7e15b9.npy +02818832-8ce474b9f38b5e11130fdafa1dfb8326.npy +03624134-5e15d63317014f30ceea8802f71596b5.npy +02691156-d75ce9ee8a64adfd98459325335edae9.npy +04090263-e4540723eab9ff0bef0c52e20895a77d.npy +03001627-23299a939a6ecacda5817f81a1efa3cc.npy +02818832-6e4707cac21b09f0531c83488903771b.npy +04090263-e998d23c1e691a33a0d2eb90fc1468af.npy +03636649-2f216bc398d3da98cddf96969ede3013.npy +03001627-3f04adffb69b5ebee95cd0dc8c2f0e83.npy +04379243-cf7c2cfb403f2819548cdb167cc8bdd.npy +03691459-6b621f006878b74f2a9eb0f146e94477.npy +02958343-666beb2570f33c64f64801ad2940cdd5.npy +03211117-8fb07bba1524168f7f6853a06fdb3f45.npy +04090263-f92b4caff4bc0f6d9352b002a7d38daa.npy +02691156-787d2fbb247c04266818a2bd5aa39c80.npy +02691156-f592e88114a240cc61a8d3163a0a75a7.npy +04256520-b216efa7925318b1e466d83a76d6230b.npy +03001627-faca91ff3f9e2b93a87dbaf229daf408.npy +03001627-d00a7550cf050fb3720daf9b94e7a5a.npy +02958343-8df9feeed8678aa6bdc56c6b6d74b51a.npy +03991062-a641529c7e3cea2293df73cd41b59aef.npy +02828884-d7eec9ea272f5fc9cb2a965e75be701c.npy +02992529-447cb44311eb5dda57e80f5278d5b50.npy +02958343-a3e7603c0d9ef56280e74058ee862f05.npy +03001627-c790496caf5f2904f14c803eab703899.npy +03636649-b2116d5a9b93a0704f377bc8602186f5.npy +02958343-d86119f06459e996897844133a297d65.npy +02871439-f4143a20243d832152e2d18963a75b4d.npy +02801938-a0e69e333f8aceaa24ad83a2d67317f.npy +04256520-cd47287d6da7492e64810cc21086da42.npy +04256520-4fd35417e08ffd8597e11b0362ef2f51.npy +04401088-383a304edf67f757769dec5ec0157054.npy +02946921-fd73199d9e01927fffc14964b2380c14.npy +04379243-be7a1bb508905459f51f77a6d7299806.npy +04256520-511168d4461d169991a3d45e8887248a.npy +02958343-e9ae93e6ddd5bc1e6047f64eee8fcb68.npy +03001627-ca764efc4e76a8b48d69616377752ecc.npy +04379243-3144ba0c286cc61f490ad276cd2af3a4.npy +02924116-c54d49c3e1d9c53f1a1d4468b3f01868.npy +04379243-8569c03c2a233f7b4b3c42e318f3affc.npy +03636649-eb8466da51199e0ecc4c445068949125.npy +03001627-7ee46c6f7c028fc6d661ff085a0f14b7.npy +02691156-697b269a890237fe15796a932d10290d.npy +02933112-2f2e54607ea04be4c93bb8ae72b9da71.npy +03467517-bf7026f9814230414269db3f92b7aa5e.npy +04379243-1480684381add1e7fff16555386d173d.npy +02828884-a2ee6b6eb6f94856c35213a917b76486.npy +03046257-8fcb8178010667392f84cb7932f866fd.npy +02818832-ed40b57386714d23940d5ff3114b57.npy +04379243-59a2490719d49a25aaf15b62af6b513f.npy +03001627-ef66111933d5cb32e46ed8e42660ff49.npy +03001627-6ddb87a44f7f68b89c0ca344f487323e.npy +04379243-734271cab27abd133d0f9f8a61342808.npy +04379243-60fe09a5de2a484f45613f5c2df1029a.npy +04379243-1de679dd26d8c69cae44c65a6d0f0732.npy +02808440-3db95e318c29a2ccb362845c6edb57fc.npy +02958343-c6038e4cf08de1a7c805dfe4ca9f2fdb.npy +04379243-1c20d8cce30ded086ee08f750473a436.npy +03001627-9f7dd8cb949fb0971f6138b700829a47.npy +03001627-614347b0e864cdc7492d9da2668ec34c.npy +03642806-4d3dde22f529195bc887d5d9a11f3155.npy +04379243-7b504e7d89d9e8d822a33e080d0e71c.npy +02828884-ab131feec69007a42250bf58700b4d8f.npy +03211117-2f12da0c7460b22cd3ab2bc0f53ca878.npy +02871439-c9a603de83e6914199e8bf807e902261.npy +03001627-c1a0882e6e8f8b082b722fc42ccb4c6a.npy +03001627-5bfb8edf221c7b0e84edfe802bb43dcd.npy +03001627-1033ee86cc8bac4390962e4fb7072b86.npy +04379243-672af8a6cb34e00678a875f897a47818.npy +04468005-22880ed187b2c5ec95f2655a7e810da.npy +02808440-c3524cfa04be2a427568fd1ca5bc0200.npy +03001627-bacdce8bc1974ff82c528d33bca1ac2.npy +03001627-989c95491d7e823fa413908c0e169330.npy +04379243-5c938860481a2d0f62ba00e4e73bbc2.npy +02992529-af983238a3e47692f90d7ee51bc3530a.npy +03211117-cccbf9be5d578b49bfba6cd89592cf9e.npy +02958343-4a8aaa19c413328d2557e2b5350c7e1f.npy +02828884-913cb50bf5d336238b0239afbed4a626.npy +03001627-ca05bd1afb0ffeaf6b9a484dedfb7d25.npy +02691156-65511fdb2afad900203936772104a82d.npy +04090263-1ab4e79889c1288995f22290198b089.npy +04090263-f7ce17ee88cdec33973c46c285b944d7.npy +04090263-7faeeb69a870d18a2850d4a1a9c25bca.npy +02691156-823de294a08784fc879e4d613e8d4e33.npy +03624134-19dff8164764e2a259f37b6e82c5e93.npy +04379243-bb027ed892722b1f3399de188dc5ee56.npy +03001627-c0d25cd4481b3c2a365f491f6e3dbc3f.npy +04379243-54db32cdda20128ffff16555386d173d.npy +04379243-7a6cf20a719c16cde8258fa1af480210.npy +02691156-a3c1b9b0c75af9a65cbd1a70b5b90a8.npy +04379243-dace4e7f0ec285abcaa22a10624245b6.npy +03513137-6f41517d1eec863b52fafb0cab311e6a.npy +02992529-53cd656555da181db6d41c42f7ade8c8.npy +03001627-98d37b373c0207915dca6305fb9f97ca.npy +02958343-144d0880f61d813ef7b860bd772a37.npy +02958343-e06082fd22dbd3d425da9962b829b47.npy +03001627-7a7273d390ea180db857892c38c46c13.npy +03001627-5d02aed0e9c93e829b9f2eb77f5e247e.npy +04379243-1f59698c02bd1662dbbc9440457e303e.npy +04379243-4f35874fc0301d015cd4f7d5b0608a.npy +04379243-fd07e0a8265d1e15db11d29991a4fad8.npy +03691459-26369dd5c4cc8c55e9e3ed40810044f.npy +03001627-4ae919ca418d3625d30ba6a673002f3e.npy +03001627-b7a04fb7a5fb790d96626c84a010ee5c.npy +04256520-2314a3400230f50d14038d588fd1342f.npy +04256520-32464457314622264587e90e2fc67ac9.npy +03001627-46c8f742ae31294cb4a4ddb21cda79e5.npy +02924116-e0275ff6dfb3de5ae550942ea36e5443.npy +04530566-602df167ba6cb5f5443efa8c2bef3b97.npy +03642806-7da524a31c9cfe22ea8725c845547c21.npy +04379243-b696793f05faa0debc5c12f67106b799.npy +02924116-154eeb504f4ac096481aa8b5531c68a9.npy +03001627-d8f7e27824e61aaa81dff5c2e57ad46e.npy +02958343-48862b67f5932cd4473f10e6caaeca56.npy +03325088-5f9c1f87d28294153321831d2245cf06.npy +04530566-a0f1e4ef99b57121a9142e7277ee08f1.npy +04225987-f52d56b5f81f1258c70ae17ca06472e1.npy +03325088-4de8400e15f1ce79b362845c6edb57fc.npy +03991062-da871256377ad8fa53d040168a517ac7.npy +02958343-b0c2225ab347e28f1a48cf85d161a723.npy +03691459-7a7193771ada6796a1b0d9ebe362f8f3.npy +02992529-4c9760ac0bbd2003151c744078238922.npy +02933112-1e200d34c5555634c59350d819542ec7.npy +03001627-52d747ca443134da81dff5c2e57ad46e.npy +04379243-37dcf713a1842b93a8699b6183baa203.npy +03691459-596f7a94c6d1443870896ebcdb67d8d7.npy +02691156-6b6cb0c71731aacc277d303e3a640f98.npy +04256520-9c113b80d75659ffdb8fa1712f9ee93.npy +04379243-e5c44394471f29d874739c2c9ecfb3ee.npy +03001627-7644e30dc0d88481a3d974b4624d6717.npy +04256520-de3589ff77017c7df15e23b99997e42b.npy +03085013-442a30c7e3d4f820cb07c68667cfdc00.npy +02828884-3a91034ceb33784b562fc21c99684e03.npy +02828884-cf14c102e6da1a78e6d475a101a6dfca.npy +03593526-1a9dade4e4a4c47589035c25f0dfeb63.npy +02871439-f605462946e280e6ed46ddfe25ee83ba.npy +04256520-98546869c4ac8516febad4f49b26ec52.npy +04401088-3dc95447a57f8d06c1e615a94e798da1.npy +03691459-ea944f309ec70895c9fff209a296912.npy +03046257-51b07fb2a039850c384368499a680cf1.npy +02808440-c118e19caa1c626431f28caafecd610.npy +03001627-6ec9b7c65db28eb32342d056300eceae.npy +04256520-32c1445f65f4ceb23eec26c23f5bc80b.npy +03001627-2909a46120ca93afff16555386d173d.npy +03593526-2fa653cd90c27f8fbd16d4490a10a752.npy +02933112-11694171ff49a7521ee0429e004db48d.npy +04090263-55966a1b272679b256dafdacf26ff875.npy +04090263-5d8c7291e06122c14eb1cb28584abf8a.npy +02747177-22cac9601407b70bad5067eac75a07f7.npy +04379243-38aab2d4679f51a7d70e365688839034.npy +04554684-2ba54a5656c25096174c6fb6a5678c41.npy +02958343-4212ae43231ba858b1bb46d2556ba67d.npy +03797390-6dd59cc1130a426571215a0b56898e5e.npy +03001627-8e0832b4ee38c9743b8d5c0ebdd194c8.npy +02843684-bf9a6c379d2dd1ce5bdd1b5cdc787a49.npy +04090263-48eaec39f20dfafa7e270f84701afcd4.npy +04379243-623c9a5812ff9ac920768660cf080d12.npy +04530566-dc422a7fdde68d8bbfc744c1348ee017.npy +04379243-8f7cbae92fc1c6f9327289c00b6dc9ca.npy +02958343-709774861793cca453da660a6567c5ff.npy +02958343-a1b7a3cc11b25b3a82c0a051a54c0e33.npy +04099429-5925619f2bcb830aec83434daf14e347.npy +03001627-57c6cf844c09c5d8b40f0ac0fb9a650d.npy +02958343-1d2c5ee3b5ef205164bd4e0c23ded276.npy +03211117-b5f473b7fb7cb7a7cc12bab62e8ade64.npy +03761084-a4a556292a3d9395230584014222e685.npy +04379243-bdb44c3f5215ca84b6d51da3ac2ed48.npy +03710193-e29e2eadf4e79ed6b34538f1e32363c9.npy +02691156-8a343fecfe2b8660d0fe0309648c1f07.npy +04090263-181d88c9e36d9ab88aa7cb0651220ba4.npy +04379243-e300cdc549ff426723fe3501bb9e7193.npy +04379243-6fe854efba4d9ddcd4cfbd0aef5a371.npy +02992529-e55ef720305bfcac284432ce2f42f498.npy +02818832-51223b1b770ff5e72f38f5bd71072746.npy +03211117-18dd6b73f3ac2fa26da250acc5e18ffc.npy +02933112-83db7fe5bdd2df12824662341ce2b233.npy +04530566-f84196260e558ff5abb59ca95d19016.npy +04379243-2c1d79e1e1533bf1f51f77a6d7299806.npy +04530566-8dd5ad35a45f72a64bad9b80eddb4cd1.npy +04530566-d8d0fcfc22f1b587308717e0a8b6a9a.npy +04256520-be19ff23b9cf375d6ee717407316be0.npy +02954340-60104a0945f83b063f30fadefd6911f2.npy +04090263-587cee5495322f18cf1584c5b09d332.npy +03001627-6d5207270292fa01c914a9f52c152c86.npy +02958343-c29ff3df2cb0139f635939ef1a7d59b4.npy +04379243-5b5532f71d63a7a772051d450c32f58a.npy +04530566-143df6dce1d90696874f0e42f84eb4f5.npy +02958343-da34cb394fb3caa58dcad5127c74b8e0.npy +03001627-2fca00b377269eebdb039d8689a74349.npy +03636649-1991d403d8ade0ad338afc540c33f34c.npy +03636649-ae67ee6392fe8ab94e7cb04dd663c825.npy +02958343-27f7336ff6ace6d460c94cf1a48e53cb.npy +02691156-f74cbd91e6fb40dfce5965228d7e8c9f.npy +03642806-a7069a96e11b8825483afc91de6851e4.npy +03691459-7f2cb859eb00046d3bb72a8bf55ec27d.npy +04379243-3ad4ddfda32220c388eed60433632c64.npy +03467517-824184668c5a297a5ece9c83df74def8.npy +04379243-5326de43a392840657f40ff86fe708ff.npy +03001627-6be3e544deece8441191025061735ea3.npy +04460130-9c3a256496120013d444bcd674952301.npy +02801938-55f00572c277b1876effbd64ad6b71b8.npy +04379243-f4fecae627f0c8906a4e86536413f450.npy +04530566-90bf73b91185303139555c8c231d0eb7.npy +02933112-5d765603dfb0f151e367f8f62a7e9398.npy +03513137-5021db37ba1fb177202339ec5396045d.npy +02828884-e6f7d84750ac46b260bedcc07a9f285c.npy +04225987-db4c8bf323465e4c537d393009a79347.npy +04090263-e74ab615b3008320e2bb19fbad3e4596.npy +03467517-77095861248c816693f0194265a9746c.npy +03325088-72863e1ef3c0a6fbdd5cf959690bb73f.npy +03948459-7f3ec97cfaea31137504cc74f24f0eee.npy +03001627-6c554635dcd6123a35fd8a41e49d8421.npy +02958343-2a07432c2860b54becf71e2e014ff6f.npy +03325088-e76c3dd5d8baf0c5bb9760cf9cd1a953.npy +02958343-a49107f738b26379428df271ebc70bc0.npy +04530566-43f7e9f8ad44e8236557d610dab4f1b2.npy +04530566-768bb9fbc3a5e3724f42eadbd9a0b820.npy +04379243-20edff7e1500fc4ed45f502ecff9e44f.npy +03691459-4a0278285d649ac779b2745bcc82f6a5.npy +03790512-de4d518333b82995d5dde04c96fd8146.npy +04090263-e4bbdf84d07fc208703494a0657c2b45.npy +02691156-457c12e05d0f5d15762c3bd1a2b3f377.npy +02876657-541c4dc1d1b42978648ed39e926e682f.npy +03001627-4960144353a6dd944c5483fab67d9a50.npy +04256520-ada8ce574ee473827c373e0e7470a338.npy +02958343-f795a928e1c7136f94d732a98738804e.npy +03001627-73b37c243cbf23e0b516c05d046e8e45.npy +02828884-b3548e858e4fa7e0ff3245f22be4d221.npy +03593526-8e5595181e9eef7d82ec48ff3a4fe07c.npy +04379243-322b055809086143c7860707e3deb3e1.npy +04256520-fb1bcd50b847a99d7948cb8e1d9ee487.npy +03001627-35f94bf244a7fdc5f51f77a6d7299806.npy +04530566-973a6d80a9dfba962625c670c48fcecd.npy +04379243-83786b4a5d955949a495869179e36802.npy +04530566-d1a5a246ffc956d68c841014ca8dc002.npy +04379243-21ce94947b07b5d1f91663a74ccd2338.npy +03467517-25a108bc4c106249480694b9b5582e9e.npy +02924116-26c334c2faacbbdd9f46749e28e16975.npy +04530566-a034dc83750e7b8144c1f09f7df84b24.npy +03636649-1e91664763d371937dd73da65dc0e6a7.npy +02773838-5d4f774fdda6fa1dcd99ccc7ff441abf.npy +03691459-61add6842a1dc131b59e9758ae7f41a7.npy +03636649-b8c809f74a592a91ad5067eac75a07f7.npy +04379243-e2cb95f03f5dedf9f198b94f669bca91.npy +03636649-9c62735cc43add358f63636e145483fb.npy +02808440-c4d230faadf735c3ac7bed72580dc30f.npy +02828884-7bdea368f85d9eb5b47a47f71cb78bc1.npy +04379243-38ae45935dcc83fcc8c2a1a2edf00686.npy +04379243-2700f6693447c32d66c64744a4252d3.npy +04379243-bc15e43c4af5a6d0f51f77a6d7299806.npy +02828884-3749b110a6f7895afdb310510a9dc39.npy +03001627-75369f55718d5adba0bb10bfbc5d4718.npy +04090263-194a4d0bcc1443fffcfd5149a4a15414.npy +04379243-1ab95754a8af2257ad75d368738e0b47.npy +02691156-b97b9cde30c23b4d71d03b466c72ce41.npy +04090263-c02b44f51d159cc4a37c14b361202b90.npy +04256520-953196a4e8a813e8fc909e63d58b00ba.npy +04379243-3134eb0e0dae6dd7b26d198318b74e09.npy +04379243-4b1bb0475e67abe029426a0f57e4d15e.npy +02828884-71b9976c657291772d07d128adae16ff.npy +02992529-9644fb6a1520af7fa90f3ad3635b46d5.npy +02924116-9294e3a8412a9219928aff27104da001.npy +02958343-e2bc765fc68afde6afe717997470b28d.npy +04379243-3a44efd1fd14ea66dfa4ff010b8b9d1c.npy +04379243-af90af72a4808ea767c8e42cd3ac65ef.npy +03001627-f9b24a3b88f9037e4b5cae2ecfffe51c.npy +03001627-cb17f1916ade6e005d5f1108744f02f1.npy +03691459-1eb0b35e8e8ca4da85113402a7623535.npy +02691156-b008491b09894384451efd5041dc713.npy +04379243-3bf20deddacf5cc64b8710a3469971b1.npy +03046257-844b4e8847e4612d30949acb87806dc4.npy +04256520-b6d1a72c1f27f4cbcd701e9c04d3cf7a.npy +04401088-fddadcb723b843eaafb07a946d621b3c.npy +04379243-8519a614ac4b1c642b70eac6546e93fd.npy +03636649-b07acedb329345f0157f5033576317e1.npy +02871439-60a48fd8f1191133664b3b9b23ddfcbc.npy +02958343-9e6156aea0c7e60ff7d6fd2038bf9a11.npy +04256520-7b57ecf4b5e9617d6282231ccf88d909.npy +03001627-117930a8f2e37f9b707cdefe012d0353.npy +03691459-96ff36cb731b29a61ad88f716ea80910.npy +04090263-5ecb203a4b00b9a5a6d1f73319179578.npy +04468005-9261fb7f5dfdb35f92236fdea0aebebe.npy +04379243-f6cd420f08155054803d0f5bac2abe4c.npy +04401088-652a6fd052491909ab19ce2dec0d1925.npy +02691156-7089929d7a778403e91b0867f5d9629f.npy +04530566-74480b3e812f7c1428cf87eb5ebe5e6.npy +04379243-7634b09c8ce172ba71a782a4379556c7.npy +04379243-735afb29934346513d41bddf307a46a8.npy +03001627-6782b941de7b2199a344c33f76676fbd.npy +04379243-a546045291e8f61c8163a33a6bfa14ec.npy +03691459-702c2f9c3e8770b534943af333340cd2.npy +02691156-b82731071bd39b66e4c15ad8a2edd2e.npy +03467517-305367bd8723cce9d57700c05b1862d8.npy +03636649-8bd35721e2767dc43225afab722d9fd2.npy +04256520-210076a2e26d5d53adc3470b30138f3.npy +02808440-35576badda1a56e6ead5604ea0ec0346.npy +04256520-af0c4f45e0444ecb01c58badc8bbc39.npy +03001627-6fc581beb03eb73349c9c494c2fb14ce.npy +04401088-12f2156b99444e955d73afbd7c310e93.npy +04379243-87ff92c179ed5ed292f4c88fd91c6b1b.npy +03642806-7f75b94bd59d649958dd315c54df0c15.npy +03691459-869225f275f3dee12a42340e65c9f0ec.npy +03691459-2cc52cc8e9de5c12f398d0c5832df00e.npy +04530566-70744087c22ee199a51aab4cdab636bb.npy +04090263-d3795e145d8fb811d735fa1ab17311ec.npy +03211117-68206e7d85afe3619d8d0b45bd2b5b8d.npy +04256520-847ce2a3541a085ccc9651014a82e2b9.npy +02747177-2a20ec86e1aaf196cb2a965e75be701c.npy +03001627-a6a7b00de9ccce0816a5604496f9ff11.npy +04379243-aaf6be1d92a8c61fdcfcef693e7ec696.npy +02691156-1f86a689ea6c35f0d9da70c3ab6dcf3b.npy +02691156-deefcd290f7f2f1a79201593c1eb4b0.npy +02933112-552b14104b7add4049cca13fb3e44bf.npy +02691156-1a04e3eab45ca15dd86060f189eb133.npy +03467517-18da35f3835f75bffb5c1b0f759e2bc1.npy +04379243-9ff56887e5f00cff412a0eaf6d0f1809.npy +04530566-dde98d21d4359f24799c6c3b2fff049.npy +02958343-860b7d89728a27b1afe1d4530f4c6e24.npy +04530566-320683da0d8bd1f394a6427195fa0bd9.npy +03691459-841818bf97827792b6fb1533bcae7a75.npy +04090263-638b5b75b9e7b0c4bb6581a048a6fb18.npy +04379243-599cf052b675ac2c8457b637f6fe1690.npy +02818832-b7abde250c295574d26ae70d41aa7c7b.npy +02808440-e1315ed591ae2c6af6a9cd46986959f7.npy +03691459-4c5b7420078b23b098935bd14e27f0a5.npy +03938244-c9f732b5bfe7b1cd29c99526bacef0da.npy +03624134-47d1191bc5bf94bc625ac64d4da8b7e4.npy +02828884-eeb6784f5812bcebb281680297eb79f2.npy +03337140-820868b702c588e0ce5d6e9371bb5c33.npy +04090263-1d9d85fdf5241ec31dfb190851825aa0.npy +04004475-99df53ab6417e293b3b8d66c43b5b940.npy +02958343-1f9a735052840d4fba1ba1170e0a8dd9.npy +04379243-934f8fd5d11af1e6e75232ab5942fa9.npy +04379243-db5f1c46d8af7d17db073a02eddafbe6.npy +04530566-87a750e55b04395e668e250d23d1f86a.npy +02958343-57aa7560dcfecea81edf5a868fdffb8d.npy +03001627-cd5ad4afabaed0d3e762624dc3c8fa2a.npy +03001627-24bbe7f32727901aa6fee8e2140acec9.npy +03001627-c50c2887ba2b5535c32fd7e88552aa9.npy +03325088-da28d9077b9bf42876d20e73c57c9a03.npy +04256520-e2965d9df7974ba25369e32fb818f337.npy +04256520-7c9e1876b1643e93f9377e1922a21892.npy +02933112-452ef94b9cbd238dd869694b17a45f49.npy +03636649-238138a3b01dc4fa68f9be495c6674d2.npy +03928116-82e0e96bd89956d9f330eedffaf3339e.npy +02691156-33a4f9403600f29c281f657e8f8481a1.npy +04530566-ae9ab937f6c1998fcc34b900bb2492e.npy +04379243-84c52a5ac0f8d1d060ddc468fe733ed1.npy +03001627-3a91034ceb33784b562fc21c99684e03.npy +04256520-c309f25d69ad12dd4733824eae5cd9ae.npy +02880940-4b32d2c623b54dd4fe296ad57d60d898.npy +03691459-48720ac336dc7012d20ac02530d96758.npy +04460130-10be0ff0e5eb12584edd82d34d189d0d.npy +04256520-a259b6ff6a4a787b4c30acd2d55583a.npy +04468005-1cc54ea296582d76793d6971ed960dd.npy +02828884-7cd1d8b686ac0059ad5067eac75a07f7.npy +03928116-36b6209b6450a35993680c5a9a367b4a.npy +04401088-77817771db0788d3241d076ab53023c1.npy +04090263-55518164337571f9ad0854712de182c0.npy +03691459-cf42a073500a1a222a9eb0f146e94477.npy +02691156-d9c080cb6634a902ca9f0727e23831d9.npy +04379243-4b11be42b0c0482dd94faaee2b20e2bf.npy +02828884-da52e5b3a29c06b1eb8ae9cf8e3a676c.npy +03691459-78efefe36b492b6e5a31d91ec836a511.npy +03325088-9cc5112d89d6c79720ea64e16f9dc224.npy +02933112-ebc49b9b624dfb55f9913e822d5318.npy +03001627-ca1cfcf4d5060ead8610f0b48b38e644.npy +03001627-5752f7caf0dbbe4d94210977e5394f26.npy +04379243-c50794596b14605421c4aa1c0e1daae3.npy +03467517-3f94fd316d4f2ca1d57700c05b1862d8.npy +03001627-2a8d87523e23a01d5f40874aec1ee3a6.npy +04379243-43c1a78d9d8b3735f2b931201029bc76.npy +02958343-67e2f8985a28e895a592cf90fabddd34.npy +04379243-6d9be8619f48e3dad096bf408b606360.npy +02691156-6af4383123972f2262b600da24e0965.npy +04379243-74983e99e7606eb114708467db3d00e2.npy +04379243-6724ae69c0bde4c09b7dad6c9c46bcf1.npy +02933112-81cc63cbfa6e492154cd2a0ea6cb618b.npy +04401088-9c5952804e0b2ba3e1fb8c5792a5768b.npy +03001627-9b40015761a54e18c29f8b0ac356b8ca.npy +03642806-eeca77a4ae8aa0ce3bef19ecc8621d89.npy +02958343-e9b2aebf673e516d1f0d59cde6139796.npy +04090263-98572b8a17031500c2c44977d8755d41.npy +03948459-61064e4a00abaaec589c07868201b17e.npy +02924116-59d03143935a47811bdb28bea09e3a92.npy +04256520-9381eb770cfa95bf6bd365389d6dc6e7.npy +04090263-5f356bfdcf9cd4218d4ca42bc1bef451.npy +04256520-27f0c4cde547763ab8a40f9116438027.npy +02691156-f222d51d7c6fedc2db73445864b72015.npy +03001627-eda92b7bd76d8bb0b083574fdbdf0a98.npy +04468005-214442a4247d8c049cbb6423d7247328.npy +03467517-71574955078e0e6191437d7de92c7dd7.npy +04379243-bae99f3e4af5bd5ad9b53420a5458c53.npy +02871439-5cfcbeccf9c9681220192a5319e3e2e4.npy +04090263-2e7c6e5ee2f07f3ce19905e7053d006d.npy +02828884-54197739c383e3b9ad5067eac75a07f7.npy +02828884-843cbbdda45de37970709281289b3745.npy +02808440-a78afbaa1c7e8795e44d45504b29e834.npy +03001627-734ac9809aada180d18df440db206fb1.npy +04530566-395ce591ad2e2d9be47b958d3d1f5177.npy +03001627-9a8dfc7a6831749f504721639e19f609.npy +02958343-49888b45d4bf55a530855e8db75dec30.npy +02958343-56478692749392a19dfd5136ef0f2af.npy +03001627-5f7152813631754bba07a29886846807.npy +04256520-82c4b96fb61723aef3598efd14e493d5.npy +03636649-fa9dc903c8324b85e3d605ae370b7c5c.npy +03928116-cd53fdcb3213ff4a9012f53cfe64e327.npy +03001627-2c5e32bb738a5306e27790b0ec8671f7.npy +04460130-1ec4566d10cc58d7a2f3410d5eb66b3d.npy +02933112-ad4ca1e6d178dedfbdc5348d65406054.npy +04530566-907c179103304ce8efcba30d0f49b70.npy +02828884-26c48cae38ed374e786f181221f27278.npy +02691156-ac026df0c0add322f37f38dedb2f1219.npy +02942699-3019eea689e5d9c1fb045022c5d3b1e2.npy +04379243-a3064f61346b7891ea0464486db6b687.npy +04379243-4cef53c3310bc0561826247b46b2ae8.npy +02828884-7be476ad18fc7b40d201085e80edb26a.npy +03001627-4a17e5189aafa9afc8687ff9b0b4e4ac.npy +03211117-917142dae380e5591ae30faf8d21acd7.npy +03001627-d1436d73b3060f2ffd6176b35397ccd5.npy +02691156-a3e15e215144dda0a03ebab0e8b8f7a0.npy +02828884-874577f61fe70621a1370c1659f8eb45.npy +02958343-18c7b5644290ce2caf0c754abe32de.npy +03001627-5158aa43b78b81a0f7628281ecb18112.npy +03001627-7e4e9703841f16194e045e9030a39002.npy +04256520-742d1d33eb66d91014c0ce0d45458397.npy +02958343-233ac4ee75d1ff0c6d111cf7e70d924e.npy +03636649-6778917189e50370a894da3d4a669d7b.npy +02747177-8b8668ba154df43bad5067eac75a07f7.npy +03636649-b7a6c5c6c27273b3253cb5b81530269b.npy +04090263-cee56f2ecf92cdeca0834a5219dec81f.npy +02958343-a281de4b24f5500d4c40f34de8f3bdb8.npy +04379243-9b7352c3a8d69c2a1185ac82ed4da80d.npy +03593526-2ec608cc4d3287bb92e0b07fda7527d0.npy +02691156-c00b97813a9cbd72ec85c5551a78ef2b.npy +04256520-d992ee06ffa2455219eb0cf70882af88.npy +02818832-8589909841fbc75a11099baf02792d0b.npy +04090263-c44c0319f2f31c455814fafedc6971c7.npy +02992529-855a8a4c39e8fe81a060e584e7409aab.npy +03001627-2fe5d78dfd82bafbcec24f0586fc0928.npy +02958343-40313368870df2c0df59ad08996c77e8.npy +02808440-980d4377aadf1fe1b362845c6edb57fc.npy +02924116-60c6d162776e07178c468c10bc96961e.npy +03001627-eb6e55bb557701e37df0e9a69c97c97d.npy +03642806-caa4afd404f24d21275c1147a304ed86.npy +02691156-123ac29b0aac8c8e5d07633dda45110.npy +04379243-aa6a63745fd7ef284084fa5d51d65c65.npy +02992529-8a26be623e40850a203d19a168d29f04.npy +04256520-e922a4ef330ad87ca37f3fc191551700.npy +04256520-951e63303cf5eed1cd4a89b0fee32930.npy +04379243-3b91620452041b664b3c42e318f3affc.npy +04099429-2de8ee55ff69502863098049d14fe32f.npy +03636649-7293f886dfe144f3496d07587574cede.npy +04330267-54b9ac27f2bae92627a11dcb35000f7a.npy +04379243-672cf4b2e0deff1e693e54627de491a9.npy +03642806-62cf794fb5fb174aadbfb30d8d1b297e.npy +03593526-8ec888ab36f1c5635afa616678601602.npy +02691156-e42443669339a6c1a5a118bd15e6e34f.npy +03001627-ed0d65c68a1fa5c485e2f8b1d3a373fe.npy +04379243-3a651c78081152e77bb4e437e41d3c3f.npy +04379243-17a5f7fd90d2bf98b40f0ac0fb9a650d.npy +03325088-eecb6ef43e0902eab362845c6edb57fc.npy +03001627-ed51660fd119dca819fb4103277a6b93.npy +02924116-c150b150e25f4bd438f13d421c59f8e3.npy +03642806-1b67b4bfed6688ba5b22feddf58c05e1.npy +04379243-70cfb2647d8246971c81cfce8a9fa8b.npy +03001627-c22ce6ebc2b5bc9b59a44e6453790000.npy +04090263-b28e6d6cb4bb868ec27f2d9f006d69eb.npy +02691156-6c3593d0cc398e715d058822e4c8a2a8.npy +02992529-bf1f95958ec4d3e8d485372bb746f3c7.npy +04379243-575fd4acf0112feae2b24d5cb1e4e616.npy +04256520-7a32d6d22231a58d32388c13cc4a0ba3.npy +03001627-78f5b44157269f99fd60059ad8523f1a.npy +04256520-9beb39285a581fa1f2e202d571b458dc.npy +04379243-f0e98a20a4ad33b15578685df571d8b6.npy +03046257-8c8c6b1c3d201d55490ad276cd2af3a4.npy +03624134-d69e028056c9291069654277b747a908.npy +03928116-508962b8f60b4b0d8c6ed1c74b495e08.npy +02691156-e332fb3eb2c4016ec1f9d235878ff0a9.npy +02958343-cd5223d35c9cf611ea7efa739175072.npy +04379243-517683d0866085dd2beec56b24479ed1.npy +04330267-ab95b15a38c246c3cace11e1dcfb4b5.npy +04379243-7ad4285694233688105ea47d266f5adb.npy +03001627-2a417b5a946ff7eb2a3f8f484e6c5c4f.npy +02992529-effeac02fe96f769146071e83265f12e.npy +04256520-b3d216ad7575478d202316dd49948ea2.npy +04256520-396ee2a2333e80815b903ba10d2ec446.npy +02958343-36a5117c64d8ca6ca10cf495b6dc4ef.npy +04379243-f9ca04891f79cf2871124212e03fb7de.npy +02933112-60508a8437c09eb2247353095dc395a2.npy +04530566-36fba9c2f4c256dc4387c5ea62cbbe8b.npy +03642806-21c0187bf2174c1684c4330348773d0a.npy +02876657-40aee078f0390b7134076b5960251711.npy +02958343-59a8ea75a9c70f51a0e1f1086c88ba71.npy +03691459-e6e09672fd21f3d887695b38431695f3.npy +04330267-b23b39522e810d8d47605ecd69fe97af.npy +04256520-d83aea7de9d3d4242c37553db37ec752.npy +03001627-4dd8f21d05f7d9a99e48f9f4020457c3.npy +03636649-15211f5ea7c7432686c701087a194026.npy +02958343-262a03114b8095856a1de667a28251e7.npy +04090263-da2799e2d7b9334ef0b45b4b4c7e33b7.npy +04256520-e963f9423720600cf506f5cb7d8ce57.npy +03001627-b89cbb45476e94a5e65235d5580cc3e0.npy +02958343-34ab29cea66952f16f48edd113a40fce.npy +03636649-4dc9f86110ea40aaa570c6c691c987a8.npy +04330267-a18d795628d848a5589577ccf07b31e7.npy +04379243-305795f4aec83b53a51d50d3f9ced065.npy +03467517-86788d23472ba4de8cf17104f488ed2b.npy +02828884-66adf182075ea88177f32db2e5e73311.npy +03211117-48edccab11f0698be441f5bb6f88ca61.npy +02808440-5a67b4165fca8f4a34558e566e818bea.npy +02876657-a87fc2164d5bb73b9a6e43b878d5b335.npy +03001627-5392f55620f601471a782a4379556c7.npy +04379243-fd7769d0eba554c53def89b32cef8e45.npy +03636649-8b674da68033700333d93f57729688db.npy +03211117-d72732ab9e03ca861d73f583f51a758d.npy +03928116-71bdb3a149c93be6834096795cc3cf10.npy +04256520-45d96e52f535907d40c4baf1afd9784.npy +02958343-832a8f6cfe462e48402013bef9b89b74.npy +03691459-aed74c2fb80bf363f5776cc601097c0a.npy +02691156-49917fb82beca4beca8607f540cc62ba.npy +02958343-7a0f252961e5bffad95840a0da458be0.npy +02691156-c7b1ae292fb3d011511e2f9385a386db.npy +03001627-c826c65111c867ab45a1df43bcd9e471.npy +02958343-bd33b9efe58ebefa99f8616cdb5dd27c.npy +02691156-fe58e1c34a7fc8ac7f6b2c9a3874dfdf.npy +04379243-303ac20ea2febf9ec3bd24f986301745.npy +04090263-d75ba8d56bf868b75a950bb73f1dbae4.npy +02691156-b9168b74c6d459e65a73760c6feb254c.npy +02958343-ee2b541ccee732254c938921b509ee11.npy +04379243-dcca76b81c747e76a65e19246f8119cb.npy +02958343-57a2d812153fa225c740046119b36696.npy +04379243-b595da70965fff189427e63287029752.npy +03001627-61bc4930719717a9492d9da2668ec34c.npy +04090263-f32e61f7124ccf327aba5d123c068416.npy +04379243-db0685c490a05ac7c5facc3cc8dc041e.npy +03691459-32ce47d38aede60ed614b9a1d2062a4a.npy +04379243-83433f0c0a3801942eca57a2fad76f58.npy +02691156-21827b0be78dd3e17dd9ca9e282b9209.npy +02876657-f0a5f6d2cf8fcb72c12d8e00a78db6e2.npy +03211117-9fc580b2097a1d3beaa3086aec501406.npy +04256520-1b0432fd7b56f7e219fb4103277a6b93.npy +04090263-5f3487876c91c0b5ddd7320ddee77bde.npy +02808440-96777ae57747ee41ffca1588abe4e39c.npy +03636649-59e852f315216f95ba9df3ea0397b1a6.npy +02924116-d39202ebc7b025a012128d25485af84d.npy +02691156-854c2f430e7aa00f4d210d9468aedaf2.npy +02958343-c916164d0e5c667a75ef328fc121b1c5.npy +03948459-36e0d91630f7c958d4ca42bc1bef451.npy +04090263-1be1707593a15cf9fa9286f039319ff7.npy +03790512-5a34a535ced91869354ab1decf4fe605.npy +04530566-7a1754186937d247ad78ed9a26ab1091.npy +02773838-220f08ff0c1d2a4542282fc88db7886b.npy +04530566-e0845c8579c5d4acc3e7754d5a998758.npy +02691156-df8bb967a346ccc25e9e2656aff7dd5b.npy +03325088-dfd23237c9ccc149b362845c6edb57fc.npy +04379243-919b2b8877c90f6885718c281d7fdf61.npy +02958343-5089b134ef31941edacf4de272c1e30.npy +03624134-1e491eee214ee77eb71f7555d9f1768d.npy +04379243-64298fc3b7cb8171eaf288f952624966.npy +03691459-10d16ee9c9402e6df2e5d34c7b677bc4.npy +02843684-b6348429292d990be67195cc1ecf4787.npy +04530566-6f36c486675210cdd566d7f46e9a16d3.npy +03001627-53d88f50e3abc2888dcbe86402c7c15.npy +03624134-46723d416c8a27ba104aa0e918fc8fde.npy +04379243-268a263f41b82227f10f2cd5149de8c9.npy +03211117-288a8917e51c57deb0957d845ac33749.npy +02691156-969455251a1ee3061c517f0fe59ec7ee.npy +03001627-831ca4306245810435836c728d324152.npy +03325088-184fdaf0ea2fda9c5dc3653f8341633a.npy +04379243-68c76bd1d8ddd433dcfcef693e7ec696.npy +02691156-d74767519393a937f73e5bc170b7e2be.npy +03467517-b6f67c7088197a76f4b498e11fb60a4b.npy +04330267-be935d47bfa0fd025eb64c1003065596.npy +04256520-8a5a40fe10eb2b2eb022c94235bc8601.npy +03938244-8b0c10a775c4c4edc1ebca21882cca5d.npy +02691156-20f2a121d9dbbf9e98494085d68ad6a0.npy +03624134-1ecb37ea8f0c4abc20fc54d2500eb7f1.npy +04379243-13c8f06bf87c074f9b75b6346baf0c12.npy +04256520-24178c4efeadb8bbadd1969a2adc38a6.npy +04256520-47ad0af4207beedb296baeb5500afa1a.npy +04379243-3e915e96e22f15a1af9174ac65b8d24c.npy +04379243-ec91cae6576b5149484539ed1814944e.npy +03467517-ce5aa7d561bd83122d1748032da3d7b6.npy +04090263-192309e06577f893bb4594cb67b6eaa3.npy +03211117-e3d94861020f97eb37fe7bdc65e35547.npy +04090263-84a95f9216f5c3255d3426ee101e9f8e.npy +02946921-3fd196c22459cc66c8687ff9b0b4e4ac.npy +04379243-724b8cfc8c4b8e16300009db8b7749e9.npy +03001627-e984974d54645e8328c54e8f8953f499.npy +04379243-889654f30ea7b4c3ce84b253beeae59.npy +02691156-9daa49ab2f97fc14d85e5191b992b560.npy +02808440-768acba240b21a492beec56b24479ed1.npy +04379243-d41c8af82fe98a019fb4103277a6b93.npy +04379243-c826802d2a084845979f073230404b25.npy +04379243-4d24a0d4ed77db9f4b3c42e318f3affc.npy +02828884-bfaad1f9dadac9b6a385f05be5d65f80.npy +02691156-a591b49406ab0d2abbf3143b1cb6076a.npy +02691156-13f9eb29d699488a99eab31c7df6f5c3.npy +03001627-906608e3146548e6a4e733e4e18a6d05.npy +02933112-35faa6d255a474f3dde9018a607defc5.npy +03636649-e2343ffc39e5f4bf85a18a4e86f89dc9.npy +02876657-200b3f3d859c8677ad5067eac75a07f7.npy +03642806-95908e92aba3fb46fc588a8e4bb2f15.npy +02933112-bd55f9190cb5c9ea3fe047712e43e185.npy +03337140-75b534f907b9d89491c352d02061b3f7.npy +04530566-77d2d34922964c7b57c58fd0f9b1d74.npy +03691459-ccffe9befaec2d1c4ffa46d1fcb77f51.npy +03001627-e1092c9dfe55273876f83644d71a31ee.npy +04379243-c46135263f88cf68bfca5f90d2eb0e0.npy +02747177-d30c7f6073bb8565c8a06b09a9a18b3d.npy +03642806-51dad6ff8c00b7be288d8f1144f7979f.npy +04379243-3e51742cb382aa1f79b3e1be3524f72f.npy +03710193-cc208bd200cd7cc5276cc2218f09ba08.npy +04379243-4cd11ae56eba48684733824eae5cd9ae.npy +04256520-25bcc7d412b1b3f27713a8d3e281895a.npy +03001627-7114ef00fe68d053cccbd142483bf2e7.npy +04530566-d14c92a31d848b1371090852934fa2c1.npy +04379243-ddc6ea7906f28cace8e2c411e1e93d03.npy +04379243-24bfb2f2e403e025d5b708f09789d978.npy +03636649-a56224d991c3eedf77d8f08447bad584.npy +02924116-1e10538e90c43ff33db75a4ec21446d9.npy +03691459-c55edafad476d908d17058acd487e2f1.npy +04090263-ee01a3d156cfde95b6f73775a54c59c6.npy +03325088-721de72c2dd58fb33321831d2245cf06.npy +03948459-dc50408025d922eb1c81652b127a0ec9.npy +02876657-cf0a733f9a63f4f5664b3b9b23ddfcbc.npy +02876657-ed55f39e04668bf9837048966ef3fcb9.npy +02808440-5e9c7ef153807504a58a5ecb2008fd42.npy +02828884-87dfa3332d118867d0d69b51a45f7aff.npy +03001627-4b7cf20cac8f2344664b3b9b23ddfcbc.npy +03325088-872a7873bbb56f1958c88d30f502a452.npy +03001627-a287b508914a00a6857b1bfbb80503.npy +04530566-dc3336883fae5239d76134f29a265550.npy +02933112-a746b71bbbb56c93c59350d819542ec7.npy +02828884-d2193ef2753921aced98cca8f0ccd5f7.npy +02933112-243cea3dfd6619944b8710a3469971b1.npy +03691459-b7a6e59fe546d81cdb2e05daba43d6f.npy +02691156-f59470cae839ba0e9b2acbfd8323f804.npy +03325088-bf4dbc47f8688cf2b362845c6edb57fc.npy +04379243-c6442db6d5fc94a62744bf8869518694.npy +02828884-2e016658e44247bd2056b4bd5d870b47.npy +03797390-1eaf8db2dd2b710c7d5b1b70ae595e60.npy +03636649-b5c4331e5896bcec1119ad686ed3f611.npy +02992529-cb80f0eb9d3566da655b6157f54b4abe.npy +03991062-a5975549391ef2215d2b72e86737c92.npy +03691459-87d70f424653c8c9e2a6fc5932a88f35.npy +02958343-15f605c6fffea827e7436c0fba14b4d2.npy +03325088-b8e1178589c797e5da12673acac7d94f.npy +04256520-7e40a1af933a05a6ab610b0c94236463.npy +03001627-d9156f5552178de2713decb1a0563b12.npy +04530566-65577c66f22fd84d6eb9a4c3b55eb0c4.npy +03001627-94461b3e6212f63265b1b65ffcd737a9.npy +04401088-2a38116473099355498dffe5de12eacd.npy +04256520-7eddb52d83f3d48eee5580e1b1723da0.npy +04090263-334ee6c5bd30011af8edafa0d47e47db.npy +04379243-1e4bf6ab2b2be368614fa2de2dbe583a.npy +04256520-2f85863e90aae79240ef1c8b63a628f9.npy +03001627-4706461c517a755d4e6ea835fbc6facc.npy +04379243-d49d33a379000a8d4b2ec20c30ace65f.npy +03691459-552dd48f9a264d721574d21c0c95092f.npy +04256520-4dd014b6e5a87cf462158b7ee658e910.npy +02747177-b401be1a08b87882f4fb4dee5181bee.npy +02876657-abe557fa1b9d59489c81f0389df0e98a.npy +04090263-5e2661c632995b4e40c568d90bfc809d.npy +03691459-ae66dc3ecd9c8932fc459988e6a7eba7.npy +02876657-2927d6c8438f6e24fe6460d8d9bd16c6.npy +03001627-d388617a719f23a191d0dff7aea42471.npy +04379243-e21392ebcec0e7cb1a3a884dfddd1bde.npy +03467517-e0d1720034ed6333542e93670cfd32f.npy +04379243-edffc05155544431436e6787c76ef3f0.npy +04379243-72c957a020566f4bfca61b0bec17b8d3.npy +03001627-99a9e829fd4bece8f5f520af1365ee71.npy +03636649-ab999b20d88829d5efb94709f30ce0d2.npy +04379243-40ee6a47e485cb4d41873672d11706f4.npy +03636649-e20889cbe2d917787d616ef0c11d6a7f.npy +04090263-26c60364ecc5858c80c2e60c312b0f09.npy +03691459-da9c218b79205d489c4dd878242c44b7.npy +02691156-448ff32981729dd38eeecfc1f147b56c.npy +03001627-9e140d4e30a90721b459fd126141e9e6.npy +03636649-49cd0dd4d1c008edbbc7a6acbd8f058b.npy +04554684-74dc1a59c3585ed746cde67a6a1ea328.npy +03001627-79b65e898b52b197b11ae648ea92233.npy +02691156-4e4ae13865bf47f41adbb4c4e06ad649.npy +02880940-468b9b34d07eb9211c75d484f9069623.npy +03624134-67ada28ebc79cc75a056f196c127ed77.npy +03001627-ff3581996365bdddc3bd24f986301745.npy +02958343-6ee903e016ebbd66921cb81cb1632a5e.npy +04379243-7a7590d19cf8274dab610b0c94236463.npy +04379243-dd86b0fcacb9990914038d588fd1342f.npy +03001627-d2b334ad08ac9857c3cf9ae716575390.npy +04379243-6bf4bc4a845bf639ce65ba7fab42a621.npy +03636649-1ce3f06d80025d9528eb8d149efa4062.npy +04256520-c9ebc7c6abcc9432560dcae81449eed0.npy +03636649-683118b2740958303fe64ec32ae84891.npy +02958343-e300d58621f7d0e963d444e16188727b.npy +03211117-62188618e7d0b2f23dabafedd9562ca6.npy +04379243-d4a1fb16866d22287db09046a5e7a0a.npy +03001627-8b1af8f7f37c36bb4368753867df1156.npy +02828884-46a1e2560a1e96f3897fc31a9c059e16.npy +03642806-7dd0b4787a78a9b6ec6505914db06723.npy +03325088-5732785a362a6f0135cab19ce2dc6f10.npy +02747177-16e1950b2d507f532056b4bd5d870b47.npy +03001627-4b4773ef582c002b5bfd842976fb7956.npy +02691156-e70bd95ab764bc1b3465be15e1aa6a0c.npy +04401088-6bda193370e2c7e9a30edee0b4a86a6c.npy +04379243-421d60140736eb03d098fcb46b95c.npy +02958343-bd8654fbca233e41ddb8f37b1865d989.npy +02924116-3cec0247f726e9ee41cefd10ce5d6cc0.npy +03211117-600fd2598fd5761eb9099be21c212692.npy +04379243-8e5866a0c093f5a17eaeab1f0c9120b7.npy +03211117-e477ab5ea25f171172249e3f2c8f56f7.npy +02942699-cda4fc24b2a602b5b5328fde615e4a0c.npy +02992529-c06c6362fc6d1c9c5677057f93c3c270.npy +03710193-5449665fcc96c12175becd8a4c3f1866.npy +04468005-6c7a374d85da1ac0ec8621169acea877.npy +03001627-6393b49ccd72e8b312cef4e6ce7bea86.npy +04401088-a1c60f087535c7726fde3adc6768fe52.npy +03790512-7b58dca40a1e09dd393c2e9c64ac953.npy +03001627-47c540c2e9c3483ce79a6b87656a120a.npy +03991062-9dc765021f27a4772e079ea2858e15fb.npy +04256520-336ac1316e0d5cb7e6fe3612af521500.npy +03636649-bc218fcb647e7127984fb9ec7e40829.npy +04379243-f46c84466664f3162f023f89cad43868.npy +04379243-fc9f18e509b363fcac7bed72580dc30f.npy +04256520-b1d7bbccf07f38d34338dd5307c2e704.npy +03001627-u45c7b89f-d996-4c29-aecf-4b760d1fb2b6.npy +03001627-7275cb0572b1c0042725cbc5586c6d7b.npy +04379243-3f10bef75e979d83b32d32632cd702eb.npy +03001627-5974ff38b45265bb352fc7e973ba7787.npy +02933112-b154cb1a8dedb14345ef69cff7e6d57d.npy +03211117-597a278f80d04db46d3e11439c6c22c8.npy +04256520-2b8a9009d91dc09863d467b618e97922.npy +02808440-86cc268fa01fac6b9f4775ea8562d2.npy +03710193-d81d64c36914cce9252e123654a8206.npy +04256520-f157bee08e60f88ce6fe3612af521500.npy +02828884-d58239c7178651ed1fb7397472fde3e9.npy +03337140-33715bab747f569e4c3aee8e9d3a6ffa.npy +03001627-463fe7f155dd7279a7635bec8b4f9183.npy +03001627-709204dcd233483f242f861207c6d189.npy +02818832-359c25c700ef86bfb4e9891cf4a003db.npy +03211117-2f3bdb6fbaaf9e60eeb8d422649e5f2b.npy +02691156-e88ce288726375ff87bf26680c510802.npy +04379243-9b4acfe0ed67b32a63848853b5b7618f.npy +03691459-9165f1681f4c5df6f63ee8a34069b7c5.npy +04530566-5f1956ad3dd52a69d3a2c7c88c74aa63.npy +02828884-78f68a5f65ef88482056b4bd5d870b47.npy +04379243-9130392b20b977813c41e9c62d62dbcd.npy +04530566-c84cc7d62a9112f7b9d24c378f086d93.npy +03001627-8a53c692453e7565c1fa182c22e95706.npy +04379243-e5140547647bee72490ad276cd2af3a4.npy +02691156-aa0802b8b940b7222296d88107d065f6.npy +04090263-98205844a3267ac6423adc2e6f1b28d.npy +03759954-63f5ef382e8bd0e0727b9c4a6cf12d11.npy +03046257-8426dc58f4b4d94bb43e6e0f22ab9ac9.npy +03636649-1833ac3f2c14e6bafc26f53456c58834.npy +04530566-4d9a23b8b75a412c82fc4dc31c839439.npy +03636649-e34d17542b26773a84aed1cd93567b2.npy +03991062-57a0bb44f5a68151ffc6e457221b9271.npy +04379243-462d928e94689592cb2a965e75be701c.npy +04401088-496270f12655bb84e38ab39b0490e043.npy +03001627-26d0416a064d23f1f9aec59741c69cf7.npy +03211117-792427e9b92c4de63b1969d0afef691a.npy +03593526-ee10db30b91b9683f9215f842248bc25.npy +03624134-2afaf2674a25fd16d444bcd674952301.npy +02828884-690aa4622c4d3246ea1bc0d82403165c.npy +04379243-49f7fadfe67b54c478b3bb39df25d28.npy +02808440-52160c130b4c132244221bef0fa3c36b.npy +04090263-31a0c1adeefa95f488b9635e60aa884.npy +03991062-1cf2f201bb36708be053f54949c9bf20.npy +03593526-7cd890d57c3d5705a0c6f54ff9ff2ca5.npy +03337140-76881763d22c637ee7ecdbe73ef4323c.npy +02828884-597cb92a5bfb580eed98cca8f0ccd5f7.npy +03467517-67f24d338d812f8049e3c7e37819c26e.npy +02691156-3656c9bbd79f6e29f6439977935c2784.npy +04530566-c1b48711737649616a740b8023d40f30.npy +04379243-c9857deb88989a67b5851007eadc6f74.npy +04460130-46a090f0bd14180bf1a48a667d61ced6.npy +04379243-ebae52c84acf994e9e4da01b847d5cb2.npy +04379243-d1e9a83ee99b48a49856fa70a578baeb.npy +02958343-98fa551211d228ef6a089bd459bbc1be.npy +03001627-6bff9667fa51178ce9930a50732a44eb.npy +04090263-59159483028516c55de49355f870af76.npy +04256520-17a768e79ba434b91ca25a4447d3477e.npy +04401088-452b924abd2ece2d58932236a22029d3.npy +03001627-d7e5de817d603fefa123ce0dff5bf4e6.npy +03001627-d1f76ed6072b9332ee558d9fec5dbe41.npy +03797390-159e56c18906830278d8f8c02c47cde0.npy +04256520-4ba2ad7525a7da6c4daf5898cf18a390.npy +03001627-9d9992f7da4c888c7d3c9de9415fb224.npy +02992529-24d22e3257420bc2b785a4ac4a0dbd73.npy +03636649-fc6ca834ee897c2be13f009579d33764.npy +02828884-7f67934afc4f95b014bcc66f599f3e46.npy +04530566-544ed8713bb6b697846f1b9d68a7eecd.npy +02691156-cf61af3c52dae1e0651e8da9cf70afea.npy +04090263-37681c6cd8bd88d1d04b05b0f20a897b.npy +04379243-b95e59bfc90c4a0a266a96e416bad065.npy +04379243-e705fde0d14090d05f2733e561547b29.npy +04379243-827166feab020929811cdd52f3d07553.npy +04530566-c52ab3a375bec0baaff407511d7dfc96.npy +03624134-3dcaa6f00e9d91257d28657a5a16b62d.npy +02691156-cf93f33b52900c64bbf3143b1cb6076a.npy +03001627-753452a3a8f44bd38b69f185154696a3.npy +03337140-b766d5783ca2e1ce4c3aee8e9d3a6ffa.npy +04379243-7960127aa69c0447492d9da2668ec34c.npy +03691459-8bd1d73922ebc098627a66821130f814.npy +02808440-b2a500b97b21c4eeb6adb81b8de263a3.npy +02691156-5c7ef3d5de5ca9a1ca8607f540cc62ba.npy +02691156-ecd761d36abc0fb5250e498b1554a6f.npy +03001627-9d443b06a03742b9bf6931cd2a81bae5.npy +02876657-dc005c019fbfb32c90071898148dca0e.npy +03991062-c03bbfcd33f310155076fe09061f1a7a.npy +02958343-19d49c8015948b742d60c8689a64d7a0.npy +04401088-6e6d7c2ffadc2fad2fffec7af390883.npy +03211117-bfa95d845671c54c26d3b1eda72fa17b.npy +04256520-cb3bb5481f214d6bf51f77a6d7299806.npy +02958343-8fc3cde1054cc1aaceb4167db4d0e4de.npy +03593526-e4c871d1d5e3c49844b2fa2cac0778f5.npy +04379243-9162c1cfbd1e42db9ccce4c6d5bb195f.npy +03001627-fcd25e25dfffff7af51f77a6d7299806.npy +04379243-97b1b1f674df7fd08d413b6cca5747d1.npy +02958343-6ee1f28244a72fcadad3ef3f3ebed150.npy +03691459-6bef36ab570225cae7d74840e6097218.npy +04256520-45ff5f465a6a907488e82c4bb71ec6f6.npy +02691156-99c0ee178c5a4dbd8d8a353a30b33dd.npy +02958343-2ab27beb8a37ba37ac00fd1150223027.npy +04379243-df2d80be5033d200e2af4d98190aea8.npy +03513137-91c0193d38f0c5338c9affdacaf55648.npy +04401088-625e2b043a61452b80d5f0084d375f75.npy +03046257-bc66e7f0d88274ac58308ff4b09ad476.npy +03001627-66312d6c06a24772a8e75a1a0cf7490b.npy +04530566-d76ad4ffab09bf27f3e39f2e17005efc.npy +03001627-e68bb6f55e2454fac7f1f7c0570e288d.npy +04401088-d0c5bdc45a59669a39a4971adc53c51d.npy +03691459-dd3f884d9b5b3c0de7b7e97e5332a9cf.npy +03211117-9a8487c37ea68b49e5a14a547274f040.npy +03001627-33ab50198c84645ef91663a74ccd2338.npy +02958343-a44fb2514e9ab51f79138cc3f6db7577.npy +03001627-7a617f62ec5bb2075e7faf7f49c2907a.npy +04379243-3f4e117f6172555bd7691f54dfc57244.npy +02958343-f36ce0c0cd0cfacba7742c4ce47c2229.npy +02958343-de78fc3652596d3e9ceaa43540dc0e9a.npy +03211117-7a89e5ca49a48bf6fc22823f73266007.npy +02691156-4580804c798365a094a6f19fab16fe62.npy +04379243-2d0f4d977d61aecf89c33ded8af67808.npy +04379243-52ec1d25f2d6aac661d4e2b4b8b99e7b.npy +04401088-88c64c14d4b6ae5aa7636d58d56f8570.npy +03001627-d07675c29d0bd535580b0de4af0eb56b.npy +03001627-7ae6518311bf2f66e1a0327ca4c4d5a5.npy +04379243-f82473746c17ef04f2baf097673c64e5.npy +03001627-dfdc94c658a98c79627fec6651ed13bb.npy +02808440-29aaa8f337632ec125fa9990176f0d5.npy +03001627-7fbe0c40524fd37465ba78ad9601cf1b.npy +02691156-a162465f9664d92a94eaa56dbee38b5b.npy +02808440-302618414a9991de3321831d2245cf06.npy +04225987-55da5b37f4fca69947d4c8697a40872.npy +03001627-3de9a7a40851ceb971a782a4379556c7.npy +03325088-49a6f4ee7fabf08cb362845c6edb57fc.npy +03001627-d62051da1ac1ef21faf575cbae5008b8.npy +04256520-e6cc5fa521f970874c6deb9ede0648df.npy +04256520-68fce005fd18b5af598a453fd9fbd988.npy +02691156-6f96517661cf1b6799ed03445864bd37.npy +03928116-e8f207efd9bf825bb9683248e4a5465d.npy +02992529-31e8327ffa4ba6a87790cd6f6e8952aa.npy +03001627-99ae1b3f970c61fd5b56aadec5c0be6b.npy +03593526-dece4e1eb0d2f202150a45ec52bcbd7.npy +04379243-55b586076edb416ea169b9ecd9e046dc.npy +02691156-4de653411d132abdf1e2558bb9cfc329.npy +04530566-cdaff2fe98efb90058a8952c93ff9829.npy +04530566-e70fa867da6276efa65562f270f71c81.npy +02958343-d9ee9de8527d309cc0c0cae12126488.npy +04530566-bdf142a3fdc97a23af018ffb2ed4ff85.npy +02958343-bb1afdd76bd9555abf3af70ab74680f8.npy +02933112-70b15dbfed77ad2d4da5feafe6f1c8fc.npy +03691459-b06106540932feefbb9b205a4c97698a.npy +04379243-37f684f64af84541609fb05dbd8681bd.npy +04256520-5d27c5cc1395586c66eb0dcc2b2e2221.npy +03691459-f8aa418d093076c4c194eaff7ea54233.npy +02924116-29c7615460f943a36ca2b6e5474aad11.npy +03211117-6eaba6819fa9b07a37a807a435008662.npy +03001627-fa7f42b395c3cfce520ab6214a789faf.npy +03691459-a55295b8538238ad6ab2ad957c1db573.npy +03001627-fd3d59ad4d0ddb44e15475f0b1eb22aa.npy +02818832-3797bd46f01466f8c3bd24f986301745.npy +03636649-3bd2db092bede98957e3b0a0099797c.npy +02876657-83620edd3ecbce0de3bf00cc25b4223.npy +04530566-35857ac61388f9fec2912ef1a1302821.npy +04530566-25164e1af059f8507129983ba40a1750.npy +04379243-8438555826c5a19079368d1198f406e7.npy +04256520-80c143c03d0d7b3087752c136d371e3f.npy +04379243-3222d3e3c90f4a3238b3634f169dcc74.npy +04379243-52989e315ee1d3839ccce4c6d5bb195f.npy +03001627-486863b7fbd169fe67903707764646db.npy +04460130-8af5e20ddd4ac314d3e8c09edf9de80a.npy +03467517-aa8f6fbdc184a732cf45555a18e7351a.npy +03467517-85bef84a26a91bff9ce363b13bdd195d.npy +04379243-3ab1e5d4f889f8f1cb7b25164a43bff.npy +04330267-c70176038a545f3f9a6c869309041adb.npy +02933112-92aa3075799e275a3fe047712e43e185.npy +04379243-f2893a87ec37f8b3781cb4570305e329.npy +04401088-1d53adf8f82d223db0a79e28606cb167.npy +03001627-fd31b09de6b3a75666764c53f1bb4495.npy +02958343-50af70a51a2db34d777b3c68b2536729.npy +02691156-eb4396ab17012b3c9a6e43b878d5b335.npy +04379243-336c81a0546a4ebaa71c812e027f94d9.npy +02691156-71e9496397481233a8cba409c4409ba9.npy +03624134-cff4276a47f1a4e29d5aeb7097eddbda.npy +03001627-459a01afd2d5d4225267ac530b1d88dc.npy +02958343-a0ba66028d22cef6975be43df8325f3d.npy +02876657-e37cfb42fe03034842ab55d7ba3461f.npy +03001627-88058de808184f3937b2bb75885cfc44.npy +04379243-6b9b672041acc540e61062b89cc2de3b.npy +02691156-3c6c4be95d2dad2937b25178f54477f4.npy +03001627-9518130aa4876f146ec0232dc7739bc0.npy +02958343-f605c1f4d1be8d00f63ee8a34069b7c5.npy +02691156-e9df546c1e54af0733d72ae4e2c33411.npy +02992529-ee7d2d986f2c989ac66dc18b3cf1700.npy +04379243-f2bca089598c94f71d246659f49791a1.npy +02691156-86f2c71ef3700ca2cca362d2a61f33e4.npy +04379243-b685208ccf38786a6f1e07a56c129dfc.npy +04379243-1aaaed47c3a77219f2b931201029bc76.npy +02808440-7e32602a20e478ddb362845c6edb57fc.npy +04530566-e5c3835b9f3ae3634a27b0b4657ac8b5.npy +03642806-33b46231ff0ac2e46c8f71c9d7a79dc1.npy +02992529-92ec69548761efc61f74e5d5bf005208.npy +04256520-dd6f44f5b788d5963d6d3c2fb78160fd.npy +04530566-f81ae8a4452ad290aa9bbcb26e1c5ea7.npy +02871439-1e95c521f70972a2f5758e5628273c4e.npy +02691156-3cdb3a166a13e44dafd477f714c68df9.npy +03642806-606f4b61d81085d1adbb6cf5d72fbe37.npy +02871439-962a500ebd7175dc702cb0c2071c40aa.npy +04379243-7327bdbb165b8d034761d0d07b9cb991.npy +03001627-a113c1f24b803d37bc5a6eb75687367.npy +04530566-b1dea53e9995486c1b4a375734e87fc5.npy +03467517-f288cd2146b8f4c1f0e1c0df18936d05.npy +04379243-c103c0f93c690f5067dc358060e3c47b.npy +03636649-9cdc3191bede2d0eef3a2c64cef919d0.npy +04379243-e9e47d6b53c915f3e12186cc8c5022c7.npy +02933112-d6523ff3e0acb768490ad276cd2af3a4.npy +02808440-e34616db6be63a881c17aef130ed6213.npy +02808440-7c9e7480ab034225dcfe5e111166f221.npy +04379243-f3164e1781a296597f6f00dc967c386.npy +04090263-5005f42fcdf718e558f55d364b38127b.npy +03211117-3c495b3a2c2af890acc9692a1d1e7dea.npy +04090263-e6ef0c7bb7c73e4bad4c449f974dc221.npy +04379243-f7ef48c7de69ae03cea3bc3a9009695.npy +04379243-b9943f2962f4ac9840ef1c8b63a628f9.npy +02924116-b9fe8bae926d5cd8e5a1c12b50998c10.npy +04004475-70dc97e3f5f7465e9a4c189047192f81.npy +02958343-129921679aaa3009e44df9b78a00d12c.npy +04379243-13c680c1fd4d1ab4bdaed8eb424ecfdb.npy +02691156-7b3bd63ff099f5b062b600da24e0965.npy +02691156-b4de0e888e562f40873ec74c119307b9.npy +03467517-8d9fa6f14ab6bb3293f0194265a9746c.npy +04090263-bf89af91f6f699a3b758d4b2d9dccb00.npy +02924116-6f2436c52c0a78947d2d874548544c4e.npy +02958343-8aacf6e90bfa4610becf71e2e014ff6f.npy +02958343-2c407d592623011eda2ff65a113288d.npy +03001627-764abaffc5872775f0dff71ec76b46f7.npy +04379243-6ab805062d5d945d53e946fb2184f0c4.npy +02958343-6ae21b4b5aa92db4c79d3cf109867c13.npy +04530566-6f5df8d6d0d77039be286ae2fb79c470.npy +04379243-cc2a9dd5dd6fda66e02a8ce45e810a15.npy +02808440-1257e60da04ab350b022c94235bc8601.npy +04090263-e1ba58d83c23c6d1fd4f49e0598b199b.npy +02828884-b9263e32f3d7a9ff81faebbdea6bd9be.npy +02828884-aa88a7bb135e074e2056b4bd5d870b47.npy +02828884-42be414abcd4f66113c01fa2f350f6d.npy +02958343-55e0897c0ac089a6da5cb3be8feeaadc.npy +04530566-461517433312704299986cc2d8a2c28b.npy +03001627-dd0e48963b73476f7fa93550ab8061c2.npy +02958343-e14a04dd31112dbcafe1d4530f4c6e24.npy +03636649-71dffdee89efe07cdff00b2637ddcbde.npy +04256520-207c81a9bbdccbb8e8058cf23f6382c1.npy +04379243-175b6c97de52974a8f27e336794e60cf.npy +04401088-ceb47998c0ffa704f1cb19f636b1c2bd.npy +04379243-27a463aebb289175f51f77a6d7299806.npy +04530566-876a4bea4fc35db067fd6c1ab7f8324.npy +04379243-4cc695f3d582116fc655d08d986ea26.npy +04379243-14c35137c3612fd0d409d3400adf2d96.npy +02958343-c314a4de4aeffc0854ae303007921fb6.npy +02773838-39381a2718d2a1d4d5f008f38a566dee.npy +02924116-42bc15ea6374ca6652470de2774d6099.npy +03211117-65d100a427b8078de1fb8c5792a5768b.npy +03001627-2ed8d45343a442097869557127addfc0.npy +04256520-1cd54be30a2aa4effe3e4e51c69744ad.npy +02958343-1feaf720692bdacc27a1a7fdc1941283.npy +02691156-6cdc9acb022b2d7d98aeb62a3dfc01d8.npy +02933112-cb4234b5106ee84dfba786d6c256035b.npy +04379243-12e1f83d5fb0af107d0cdce142e729b2.npy +04379243-64e65f881d846d9235836c728d324152.npy +04379243-80b2eb0e500bca46f3412e3273fc1682.npy +03593526-9bf9f7dc9f7160cf82db9fca4b68095.npy +03636649-e515076a09191d075fa6da97b9eb4a2f.npy +02691156-d5b08d1355502d325f83a2299c09f64.npy +04090263-823b97177d57e5dd8e0bef156e045efe.npy +03001627-1b6c268811e1724ead75d368738e0b47.npy +04330267-8b3b891df4dfbe2d41965be83b7745a.npy +02933112-195b0fd745df898d86d53ab0fe94e911.npy +04379243-79e7911ce615b63078831722644c29c3.npy +03001627-1c08f2aa305f124262e682c9809bff14.npy +04379243-a882ada8bc14e42080d6227ff9b21190.npy +04090263-42b7e8c381cb392740112771efe22586.npy +04379243-86a7bbaceee66eb36b63d78a2e71a26.npy +02958343-3264f78bfc3bc58c9213ea6cb12e4e3c.npy +04401088-cb9e8cd0a29cbb26b6d41c42f7ade8c8.npy +02933112-dca6f5a582517758eab2bd7322386ffd.npy +03642806-fb641fe28d0f5e73d51fce576fbd4600.npy +03691459-e270c383e0d9c8e0ce029fab54b6cfbd.npy +04401088-ecab7b7bfef8d7f423575ca8cfe7da9.npy +04379243-44a3f66a0a40f21119fb4103277a6b93.npy +02933112-134055516ed892913ba1c51b82b58419.npy +02843684-589760ac1324fcce5534ad7a7444cbeb.npy +03001627-11506b96d41f7d3dd7c4a943f33e0384.npy +02958343-3cd83324de4a2fecbecf71e2e014ff6f.npy +02691156-707cb24ab99bff07e2aeeb16e93626f.npy +02691156-a6693555a4c0bd47434e905131c8d6c6.npy +02747177-9e2a1751b9129b1132fd0b3f17b0d6c.npy +02958343-5a91741d3a0ca58cf200a72c9245aee7.npy +02828884-117f0ee18ed91ea2d4d8765e3910f617.npy +04090263-5ca2752062ddaa0e21fa7072ad9ba0ea.npy +03001627-c69ddb5376e22cb8c4e8952b27b5f370.npy +03797390-5d72df6bc7e93e6dd0cd466c08863ebd.npy +02992529-77817771db0788d3241d076ab53023c1.npy +04256520-ab2f0f582e3fa5b1780c9f3df5b1ce52.npy +04379243-e5aba07854af35d89e6a137715910e1f.npy +02958343-1d4eaafea3ae8303ce94fde2d6224f79.npy +02691156-c4433144c905ad0b71d03b466c72ce41.npy +04256520-d8087961b06c9f7d4b3c42e318f3affc.npy +03001627-56cf253d14abfeb92c528d33bca1ac2.npy +02958343-fd3b75f7f1e9172fb6f657757c95f74e.npy +04379243-bbe30ffa9234cb3af268f6180933aa3.npy +04379243-658138c87c9184f279368d1198f406e7.npy +04468005-2a89a00cd90ca5b844b1f4461f7a073f.npy +03325088-8267bf624e6234f776c18e71fd49c4dc.npy +04379243-7135fed6de70df8d25fc264b1d80bb27.npy +02958343-8feac5dae8852d2e175f8ba1fccc4d0a.npy +02992529-9728d42d4de74ff69ae0ec37bea5341c.npy +02958343-18ff13d7f181e7625fa21635eac9e4ed.npy +04530566-57b3fb45b6c484c8cd9052ebaae01826.npy +04379243-97661c4a58929ff2d9886e45007f4f88.npy +02958343-cac12f8e291f3d1fe43409f9be327bbe.npy +02691156-6778c46aff633538c0676369cd1d063d.npy +03001627-2364d6cbee1425fdc3bd24f986301745.npy +02691156-d0b7060229617935d2a4e6ac398c976f.npy +04379243-392b7f2c8b72ba54d05b3855d81c2ed0.npy +03001627-c88eb06478809180f7628281ecb18112.npy +03938244-ef5ee3879df49ce7f5b2cf5056edd6db.npy +03001627-54bdda983ea87dc9d727e9f790cd597.npy +02924116-b478069e03e9bc07583e351622462335.npy +04379243-dc61d1287fff3ebdd2afe8d5254a0d04.npy +02958343-6e5340cfe979238998ff545c3abe3e44.npy +02808440-2c217197bee9dfbcb362845c6edb57fc.npy +02691156-9825919cffec79701944f01d3ab2091b.npy +02958343-e21ff1f90750ab24b8085998d32fb54.npy +04379243-6f8f9aa1ac705db9fcbe4e14ff0c4707.npy +04379243-cb48a015b203b3084acc8059dcf0a054.npy +02747177-c3b31dc8c48265ecfffc97a61124b1a9.npy +04379243-39dcbf2d99d0e7e778104ea7bb00d557.npy +04379243-e3da34a62e53689e82028a475156419.npy +03046257-c04f2df69acd7361bebd3c0c0c70fb03.npy +02958343-c887bed724f4a30c31d6c59225b395cb.npy +03636649-1833ca8ab16a7b7a43448fccd73e2957.npy +03001627-77fbfd2f194ed73975aa7f24a9b6003a.npy +02933112-15d3297d200f8979c59350d819542ec7.npy +04379243-372a6ff9847c899bfdb026c58bb97e2e.npy +04090263-6bf8c32f62fb38bce1f2a1daf140ac9f.npy +02691156-b77aae4fdee662f487dedd9dfc0f1d4d.npy +04256520-c81d3992ddcf2fb41b17743c18fb63dc.npy +02924116-bc544e6a141e26227c0e7feb0b8d987a.npy +02691156-885b7ba506c9d68ab6ecbbb2e4d05900.npy +03211117-9727d690fe514475ac5153554deeb14e.npy +03001627-3b342f2ef792ff6a6006cd11c597105f.npy +02828884-9f5ae162a075ec741e85d47a2a5461b3.npy +03001627-a272771d6e9a29c2f4eefa83fb709ec6.npy +04256520-556166f38429cdfe29bdd38dd4a1a461.npy +02958343-6a8058611e45e7d243ff4cf09319bd2.npy +02924116-2f1b2510d1481e9573ba5c85a4ea149f.npy +02691156-22d0561f06900e165140beb2199de2af.npy +03325088-b6a1fb06d6658d30c36fb70296e45483.npy +02933112-b99b7673b0927283b1732c7d45a02ba0.npy +03624134-681cb407b784758b74d6554e3155d415.npy +02958343-26e2b2920a2330b2cdb8ce1e61248143.npy +03001627-2ff12e3a324071c0525a3d382a240768.npy +03624134-43ec2092d43691b4d7d3985b6fde9645.npy +03001627-a69c999cd76e29862f8c68dc62edc38.npy +04256520-83ce58add39dd471d314007fddce52b0.npy +04530566-597975f72770523eedb8bbed3955f432.npy +04090263-fb9a94c179ce70c4561dce3fe08634b7.npy +03636649-a500dac5ab226476b9445129e5607c02.npy +03001627-4363eb3e65ada91ae3f7a74e12a274ef.npy +02924116-239459cc296a1b4a995425f067333fd3.npy +02876657-7984d4980d5b07bceba393d429f71de3.npy +03001627-6fd485a2345c3dd69233bf560301e53.npy +04379243-413ceae95ebcb6b5707cdefe012d0353.npy +04468005-62f8ee99e2961024834b1a533ffa0490.npy +04379243-4cdfd605352adcb0da13974b3533fb59.npy +03207941-4442366563c116fbdcddd0cba5e9fbec.npy +03046257-22d83db25a203f8535208cce48b17170.npy +04256520-ff51b4ea697e7bd2a59fc0a73ebddd23.npy +03797390-513c3410e8354e5211c7f3807925346a.npy +02958343-8545a6862135379c813e8e6859b9f2f6.npy +04379243-6b5cfd0de413ce8841b160b9adc112fd.npy +02958343-1d82451a55d19cdd711f9e3a79a13dcf.npy +03691459-c37c230e15f8c561ce029fab54b6cfbd.npy +03001627-6333b3de61610070cb443b1c1b54049e.npy +04468005-367904ef57b82d848be7c8c5fdb9bd6d.npy +03001627-23af2a09ca2509f817dc12307fee9432.npy +02691156-d6b4ad58a49bb80cd13ef00338ba8c52.npy +04401088-68376369681e50847e814a763437cd9.npy +03001627-c59cdd1537bd75ddd0818327fc390a5.npy +03001627-50e97407fe2f7ebaa8135ec53db502ee.npy +03001627-1f343169e6948a2a5b7d8e48ecc58356.npy +02924116-22509148f79b14e09afb67dd284d342.npy +03001627-639e40029ef06d6f7e67c36deaaa271e.npy +04330267-f4a1b9d53784e55682b4ca3750aa2fb.npy +04256520-50a4aa069dcd171937b2bb75885cfc44.npy +03991062-b036923580ff3db6eab2bd7322386ffd.npy +02958343-6f1888091dcf4ca550577cf04f3bf74a.npy +04256520-3b7f2867c3d56290267536df1b0cc6.npy +04379243-e460f8b0797b44b06a20dcde106482d4.npy +04530566-507e097913d1364bba2dc6b0ec935a93.npy +04401088-8b08eb5ebea05e49a3ed2b429444c197.npy +03467517-ae52de8945d1626e79138d56f2e3aef3.npy +03636649-8937a2d361775c68aafd61baec633e88.npy +02691156-c5e999752db444eb91a464c5de1b632b.npy +02828884-691480901ee9f047ad5067eac75a07f7.npy +04256520-3319a9b24416ecea7ff6ace05b36a5.npy +04379243-5ba5f9648b50ede83918f23e2305ede2.npy +03001627-b709b41d6bafd77480cef45d94d1481b.npy +03001627-d6e0a95f00c7af6fbae0ffb97058b7cc.npy +02691156-f3e2df468c15795872517bb0a6b4d3ef.npy +02992529-71240556952395e0925bda4660525f97.npy +02958343-886246c286351bc6cc010a80df5d3c87.npy +03211117-6e26dd3afa4eb0a889cc5332e945f058.npy +02828884-77ed241c90b88a189f197237213064cd.npy +04401088-bc301249d58b89b638d913262f25e96d.npy +02691156-4f3a64164fbe16f54c2c88971423d0be.npy +04256520-aa86df339042feeba4d9f38918617d27.npy +04401088-5ec85395159a335221844676433a0aca.npy +02958343-98a4518ee8e706c94e84ac3ac08acdb2.npy +03046257-fac633a56e88786559d14889fe22f10.npy +04090263-280896ad10aa1272ba11c8c9c0c3770d.npy +04256520-7a6c2247a36d93b6f4553a0692c9821.npy +03046257-fc5e57ba9bade79a86a499d1a4d80ea4.npy +04379243-cb31b6293506eb639a3528690d225ee1.npy +03991062-4d054c0a0c2fd8e4503adffe35460705.npy +04379243-80a2c69d8ca29bd136b0f2a1430e993a.npy +03001627-be50a399623910e1fd03f420a0b8656.npy +03325088-5978d6e26b9db10db362845c6edb57fc.npy +02747177-e6c0e2578876d6fd808bd51049b82b48.npy +03636649-5849d1a237cb493c659dda512294c744.npy +03593526-90c112fd862cfca1cb497d0953a32f5.npy +03636649-859182efd11b40669018dc7bde518d9.npy +03001627-a7dbbe66942a7b7c40ef1c8b63a628f9.npy +04090263-a8e185dcb791be07ebf69cf03ff6f737.npy +04379243-a5071459f9774ff43215fffb0cc2c59b.npy +04379243-2dc57230d14506eacd6ce29440b718cf.npy +02773838-45f56ad8c0f4059323166544c0deb60f.npy +04468005-61a269d35f68a189ceeb72b524f3e0ca.npy +02691156-893c03e02dd0e1ad7d64cad20089f027.npy +03691459-5584bebdc80ecb42c9d5b08933b9e0c1.npy +02691156-7a80f3950b5e31f6b0d51feef5761dce.npy +03593526-b20ca8a345790b03d3dad974dc098fa1.npy +03001627-7d0467dcbd13505f2314deb821327685.npy +02933112-b30ee0cf13247fa7f51f77a6d7299806.npy +02691156-934b1ff5cf72b25c4310636931b68fdb.npy +03001627-4362e715455f42ba9b9f2eb77f5e247e.npy +04256520-36a6725f30a73f0e91ffcd1d3522e1d6.npy +04379243-d91c5659ba4770b3650590f03418c5e4.npy +03991062-2d815a9139dc24e5adfef0837ef69723.npy +04256520-85bb2ac1c8896881837d598c1c392d83.npy +03211117-4270cebd8ca0f2593dfb5aeeb86be115.npy +02924116-ea4feb09b8f4c7be41cefd10ce5d6cc0.npy +04256520-8981c0ffae1af00a50fc88ed745bdb67.npy +03211117-42fe49800a1e65d18a6b1cf8170af1b3.npy +04256520-b7cd67499b36cf60417a8f1d2c94eaf6.npy +02992529-8ec3b148b8c608a0562c671ec5000f23.npy +03624134-a385e6b7a1953838a1c6ab435d705f36.npy +03211117-e42fdc1419328bd7efdd13124d5ebc47.npy +03991062-fc7ba0ce66b9dfcff155d75bbf62b80.npy +03691459-a2b1f43ffd80d53aed46d95e646228af.npy +02924116-c97f1811bd4104e652470de2774d6099.npy +04530566-b998ce1c2a335d80868bf275e08c687.npy +02954340-8338e10954ae6c5296b84415a3f1393b.npy +02691156-dfa36bffe436a98ee0534173b9189765.npy +04256520-fed8a89a89c96271490ad276cd2af3a4.npy +04256520-8243278b0b5881fd41ee82033240ca28.npy +03325088-2a7001af4f018827d86a78ce9bac042d.npy +02828884-aec1143f9e7375846555a8578c9b250.npy +03624134-d1c757548ead4a4d8d03ca4865da5b6.npy +02958343-6188f5bafcd88523215d73d375c978d5.npy +03207941-85f3f3bfec4b787814b35a7d7cea7130.npy +02933112-d89866af0e191e40c4ac7545c4775b33.npy +03211117-46c594660d9fd584c8ec06d23612ae6a.npy +02691156-750000e25d4078f64e61a0c2eaaabe87.npy +02924116-6b5c172c49f15064e550942ea36e5443.npy +03211117-542ea1fa89d51f12dbb15541d28bf6f1.npy +04379243-c5b83c681c085f2195493ccf8f26ab2c.npy +03691459-300d579cb4dea9338cbc76a30015552a.npy +03691459-b859938280d0c7346583871b5c274818.npy +04379243-d3a72603f65b921b391e4d6c585a697a.npy +04090263-5fbdc4c221b31d5b93153dd7e0ee121c.npy +03337140-a4a939a0bd8f8cd9492d9da2668ec34c.npy +02747177-6d21c75bbe308322513c73fd461b230a.npy +02924116-4faf2b87d20ef1d6ca2b6e5474aad11.npy +04379243-5f31ed4efc21b67711a59b122fb65ee9.npy +04379243-e222abacac76f2a5470d3ca356fc4190.npy +03691459-70d2fc496ad0da4aa7f1b033d01e1364.npy +04379243-8f440a7c0e2af79f3ed0ffd59feeec00.npy +03513137-50c322394e1587c54e5e6ac3ef6bff73.npy +03991062-5dc2fd41c59a87e1a2c59a4d90e63212.npy +03691459-cb320fd1f48f60d347e20662b9cc792d.npy +04379243-485b69363fa53a5ec35131da26f8061a.npy +03991062-312b2a3cc205857ccebb4bcb108e5022.npy +04379243-c1d44782ac45d6fe3671949e4f99cc76.npy +04379243-b77556086eea0ab181187d9890753294.npy +02958343-24b9180ac3f89ba4715e04edb8af9c53.npy +02958343-998f600899c76e4583653a771e25099b.npy +04256520-e1fe7e3d2dbdfda9bb5bd941c6665c21.npy +03467517-ede91ce18b53368484d922f11bc5db6e.npy +04379243-b62d45745434ac46c4cfe384be4426c3.npy +03467517-de9ca0c3e32f907dcb61cf5d9c47c2c7.npy +03593526-c13437979b41c607cbcddf7f55015a5b.npy +03211117-b47b05891c5161189722ef9ae1c74e1.npy +02880940-cda15ee9ad73f9d4661dc36b3dd991aa.npy +02958343-42ad4b456bb964e1d57c4849288ce494.npy +02958343-43be650d6fd7468fd9952f9e00a53f0e.npy +03001627-4b785965d54454a4e82cbac5cad4b7d3.npy +04530566-de55eb89c357cd5baff407511d7dfc96.npy +02808440-f7db8bb845d6024e7935a3238f63108a.npy +03001627-3b2c9428da926e939ae03736d955651b.npy +04379243-33cb211cda607e9b922752cea2acdd17.npy +03691459-58c7ab29b2cb73171e652fa812161367.npy +03797390-f09e51579600cfbb88b651d2e4ea0846.npy +04379243-f472e9e63984b443f155d75bbf62b80.npy +03467517-977d172a08113bdc1082f2ea630bf69e.npy +03790512-5742426c4c9fa2e4b37378f3c85478b4.npy +04379243-1f239239d1039d60ad8e5e47362bc281.npy +03001627-5c9d582488732ee0d7f7a4c4609b0913.npy +03211117-8798383e9e4181d3f4c39a35147bf949.npy +04004475-1773dafc24ded61cea3aa8137e136b5c.npy +03211117-47cc124678ef84c53bb4a1304fe504d3.npy +02992529-45301b15dce2724e483a0f6665d9ffe0.npy +02828884-5a0f0d22870fc83b2056b4bd5d870b47.npy +04530566-ca586d3aa941479ed95226c21abfd72.npy +04256520-4a7cafc9f91cde86200f88c4e37ac5ad.npy +04379243-dc868ad981c23d22f91663a74ccd2338.npy +02828884-f21333a7141e7fbdad5067eac75a07f7.npy +03001627-570ee99e247c6cb0492d9da2668ec34c.npy +02958343-7486c73293cb8af3175a3b42530b4c51.npy +04379243-6daca3df48c0e8491cfe337d09cb7c35.npy +04530566-6fd433c69f9c498a12d1578498a3b488.npy +04379243-caf7f51add1284ab7ae016d7bb06fd0d.npy +02691156-9a007813a38638c379a04281ec8c6618.npy +02691156-a7a0e7eddf4ffb8c19378fd691582500.npy +04468005-506ebcdee663d5ba52470de2774d6099.npy +04379243-fc7ec69f0402424de27790b0ec8671f7.npy +03001627-d13eb19745344ae5fb0eb7e753c06942.npy +04379243-d0578233f05855fcf58998c8c192d0a9.npy +04256520-c344088939a4d4e4c8687ff9b0b4e4ac.npy +02933112-c99ec52d66a6e89c3c8d0fdfb1cc2535.npy +03001627-7f14058e6bf50047ea1d47b7c8c17fea.npy +03046257-b029b05ae3761f0b582ed853b74eeebb.npy +02828884-3e59aa33fcf672b8f4fb4dee5181bee.npy +04379243-4021d983b2359b2d4354f9eea413cf2c.npy +02691156-b976a48c015d6ced5e9e2656aff7dd5b.npy +04379243-124583cd4b54d9c01b17743c18fb63dc.npy +02933112-9f07ee5bcf6a4b11151b305e5243d9f8.npy +03636649-1e0f7ff92144792ac3ab13a0474803d5.npy +03467517-ca3930d49357ef676d9376f644442e99.npy +04379243-b0b704778e9e06ee22dc61df4cdad42d.npy +03691459-f9a615ecebfe7ae1b27175774c9e33e9.npy +04379243-a422fe1fc47fd85d59a230640e61666e.npy +04090263-45c8f8e154fe9642220da6190e4d5a0b.npy +04379243-3253af88a5568d6e5e0e77e9cf965949.npy +03001627-69314c01e2b6ef2a95a4f7ae0be930ac.npy +03636649-102273fdf8d1b90041fbc1e2da054acb.npy +02933112-cece5afa11b5ea16d2096b2fa6f98cc7.npy +04099429-cdc4b9b25334ee6f789a31ba8b4b1248.npy +03636649-5c8da21eabad2dfe3d59e2f2ea85dc18.npy +04401088-912d81dbf33f20956aedbd2a02b96953.npy +04090263-9f4658773bf2c31ffbf44f447f38c175.npy +03636649-928505a660acfc20c7e400d2701a92d3.npy +04256520-42b297f23638f17e27813b202e608c61.npy +03046257-945d98aacfb5842f8e8ef5f0615457e2.npy +04379243-7f3e2154bbe217d4143e713a73e832c1.npy +04256520-1a477f7b2c1799e1b728e6e715c3f8cf.npy +03211117-5c79b27734380b011a9e831992816ab.npy +02958343-d8b50ce6cbfb56a4786993ccbbbff425.npy +04379243-dcda90e411cb4e35506d1e1cc84da713.npy +03001627-5623d0ec9efedbc9d4da89766e80607a.npy +02958343-2236a1b9cde71eff13d31c5a107f3c4.npy +03211117-2ca1353d647e5c51df8d3317f6046bb8.npy +03001627-8cb521c0e96b349d65ba78ad9601cf1b.npy +04090263-da50ca3dcd5aaecd8bdd85f9e4c21fcb.npy +03211117-18371c836b01c024b41d52ced3f83dc3.npy +02958343-d9867d92edba3d0cb96212c8f6cd06e.npy +03001627-e0276adea0d4f4bf1783a44a88d6274.npy +02958343-dfec37059dcbf6e64819e00d73fd49e1.npy +03001627-fc0e86a20a9606493cd6abbbeca4e2ad.npy +04379243-8d01e61b216324d0f9814818e8ac1c35.npy +03001627-6f8dfc86a34548dfb0380c06db6e7e.npy +03624134-fba0688dcfa8e2d6b9db80316f5d0ba3.npy +04379243-83ce738c3cc05c54283b00891f680579.npy +03337140-7d08f0d49ba912bc91c352d02061b3f7.npy +03261776-ccf84f2cbd3ebeb247ba1bc05b9a0f37.npy +03046257-f36af79f59ace6f3b48a711df82173e.npy +04530566-e88c7403ff401716b7002bddf0942f8e.npy +03001627-3452faac2f4ef4d1f89f4ae158f2441.npy +04379243-db4f8c9f1c62e421efca4f7cb98e0c29.npy +03691459-8aea25f1090e419c9f78b1e1185445c4.npy +03636649-c7b77a991430bf08b8812f80908a0273.npy +03337140-1bee7b073a38d30a4c3aee8e9d3a6ffa.npy +03991062-f74e2aa18622de8872652f4081ec5a77.npy +03948459-c29bc7b0dcdbc2b9e1f2a1daf140ac9f.npy +02924116-7e1ebfe89513837f4b49e2e4c84b2e43.npy +04225987-c4b7db8e09375b4d6830ad3775f4cffc.npy +04379243-eeb6784f5812bcebb281680297eb79f2.npy +03797390-e16a895052da87277f58c33b328479f4.npy +02828884-fc301ae04efc46cfcb2a965e75be701c.npy +03001627-d1e9d5b534c77a2a14b96b665a8ac321.npy +03642806-aaebdb95de0459f66a51abe62a0f8cce.npy +02958343-68b4a03cd8d49553e98e65cfc071e8a0.npy +04379243-139c9b504cd85237c5984c8ccbe1a38f.npy +02958343-50e3333f66829c8fbe40bb45ea25a041.npy +02828884-9787c8521ba8d46b5b83c5170da4c6c2.npy +02691156-c5c726006697aa19b5666ac9dae008e8.npy +04225987-fc5c4986b2661d848fc8944fc8bfc667.npy +02958343-3a0c0927ed24090355f11dda63ed3832.npy +02691156-47319a4f6de68c2966cf1b4a8fc3914e.npy +04379243-3b391b1f9337fb5490ad276cd2af3a4.npy +03001627-90bbf2bd1acca50fd684faddec3c0090.npy +03636649-fce6b0ca06f8a565b45df535caecae62.npy +03001627-3a95602170ff3fa89c0f0342c78089af.npy +03001627-d93133f1f5be7da1191c3762b497eca9.npy +03001627-8a9630332c2cb42644ac83b3e97ad658.npy +04379243-da0ee60c93c215a05b30881dc0ecdd7a.npy +02691156-dc74cd06430b61f478d9c09d692f9057.npy +04379243-9c71de3e26788e20d810b14a81e12eca.npy +04090263-7e13df65e9fdba575814fafedc6971c7.npy +04379243-5094e6f7e49f2006e6942c5426df6055.npy +02801938-a2038457c94b4a5a36b0f2a1430e993a.npy +04379243-2e3037a285fd8b5c1be2a853ec4f9e8.npy +02691156-b2c69aa6c8d78b59f119374ee5d5f944.npy +03211117-801812bb859e6c91f9786f6e93041cd8.npy +03624134-c67be2da5eed3d10d50d1e618e5eb2bc.npy +03211117-9329eb153c1e8b4d8479362ee6ff3679.npy +03001627-64067f7029087ee07eaeab1f0c9120b7.npy +03001627-51375e5aaac17a8ef7628281ecb18112.npy +03325088-13b8c245f4fdf1238d28f213d83c9d3e.npy +02958343-c4c21e09e91292b03f82402961906323.npy +02958343-5ebc7e111e9d0b5d473f10e6caaeca56.npy +03624134-93b1e4a02037c52e679c9e94dfb2276d.npy +04530566-4ec2f4afebc5933638d037116a032a18.npy +03001627-4a367285ab5c22d07548800e3d70d83d.npy +02933112-5ff7e1be775072e5824662341ce2b233.npy +03636649-1f4df93fc1ca81c985bde43adc8959db.npy +04379243-224be4e98e6edc46cdc7385b337a3db1.npy +04379243-2f4d4e41a5ea61df8cb5d9909aeb1309.npy +04256520-a0a164ffbbbdac8d52979c729a1f9cc2.npy +04256520-b2f2058ab083cfa0a8055fb11b774454.npy +03001627-3776ebfcc23e6d87cfab10986e008a3c.npy +04379243-376a1d212ab8971125f61c02205f9a5c.npy +04530566-409ff4fbba1ba94adab1bb7802748e9e.npy +04225987-871516a54b6c8689615c01c6c616fbc8.npy +03467517-e0d74618e316b0f16d9376f644442e99.npy +04256520-dca3a1737e2e3c5c6d0fc9460109eda7.npy +02958343-49defa8dd73d03f1a7fd25564c2e888e.npy +02876657-2eba1ad799a00142938c8d9daf9b36f6.npy +04379243-75234e713a2baed84d5f12fa5114b4e.npy +04256520-1667fb24efa940b9527e7f2c027f7469.npy +02933112-9c87e3b439c20e177f1513678f5ee92.npy +04530566-29c5c9924a3e1e2367585a906cb87a62.npy +04379243-1d3d621e02b8a6edc6fcb6f3205734.npy +04379243-75fb953aaa9924d1f28b9459ae3635d3.npy +04530566-75078bd36089fd98243f62fe7d2ba690.npy +02992529-d944c42ad08401651e5d846d206adf3d.npy +04090263-af960bb41e705a579a6e43b878d5b335.npy +04379243-f54945d1d185b387659dda512294c744.npy +03691459-d458f71eedc7146994fa1ea146084110.npy +04530566-7baed55a551f03efa27ad5a09bb4c2bf.npy +04530566-bacbb452a0f6917a663e90eaf6b4ca52.npy +02933112-147eb60e7a6cadde4da5feafe6f1c8fc.npy +03636649-62e887efeecdc1a31ebf42c64df00eb6.npy +04004475-fc9bc191134f08ad18dff33f5d779e3.npy +04379243-83c5f5d8ab0733093fa313db82fc9cef.npy +04256520-8e7d422141080fee59f8e31ca87c470e.npy +02958343-8549c4948c7285f438acd89c0735f4f7.npy +04379243-b158eeea059f2c7484edd435e02f1ecb.npy +03001627-d5d18ba694ad228346b9f3b6ee20ff4b.npy +02691156-221c079c90d4d5779e9cd6cd13c91bb9.npy +02958343-ff809d58a66fb4e85174ee1075ae80c1.npy +04401088-2fe9e8fd2a7c512ad1f278e1513f3b7.npy +03001627-c5be8052dddf9e92283b00891f680579.npy +03467517-8c14b3b474245ce9465b60d363b610aa.npy +02801938-242e6c21d53890a236b0f2a1430e993a.npy +02958343-52c0adae9be5dba12e877e82c90c24d.npy +04379243-fa5dce1043f44c06ab88e3acae6e8bc5.npy +03001627-274189e25f44397f51f77a6d7299806.npy +03001627-e344e50eb6754cf890ef7803f19df417.npy +04379243-7e725fcf5f56b74bdfef331c9e51db71.npy +04379243-2ca0370bb8ba5ad0e46a4046edfd3265.npy +02958343-fd243c10d91f08e46e282bcaec079702.npy +04379243-b305fed48f77f5d3b40f0ac0fb9a650d.npy +04090263-d96e0f2fdcdfc47cf1cb19f636b1c2bd.npy +04379243-44ebc446b2cb44b0c12f5058c05b3979.npy +04256520-e9017aa5115303957be8ee92c39a9d4b.npy +04530566-fe84b8e3bf172880f54a2210c7b2aa25.npy +03001627-961396e0e5e46a4a208462e8bafe70e8.npy +02828884-3d470843f013f9d8c9fd4914d3d18461.npy +03991062-e089186adbcdf495c0781ed2e47426c.npy +03325088-34faf4adaf07fd9dbd490710936da71a.npy +02958343-919b95beccb25d2eaa3fe7369efb56d4.npy +04090263-2315893467e8b5eea50ef3fc203c6ba0.npy +04090263-ed9225ab8a02b0fd4b349e4b3dd5565e.npy +03337140-6b4a0b4d90640e45c78621ab7e0ef193.npy +03467517-ad2711786f1bd2f3bece9f494cab1c6d.npy +04379243-21d141b130a76e0e497b98603e1cd1f.npy +04401088-cf7973f49aa611346be7f66e5722d994.npy +04379243-39f6dc2839dc4e1bbab624e35355496d.npy +03001627-59879a7a34ee2ca840e8b85dbf5f349.npy +04379243-46184eb6f03e8d2afebad4f49b26ec52.npy +03325088-adb985820edec4577eaeab1f0c9120b7.npy +04379243-416f41390bcf0f87a961b86aefe617fd.npy +04530566-5261e8e52d1581d2398589a18564a81.npy +03001627-34ce485c1fbb9af578785e24320d5ee9.npy +03001627-3d703ecc2358ea0ff51f77a6d7299806.npy +03642806-dbc61cbed5f7f2b33c1abb78f1519c49.npy +04379243-f850a69b0d308fbc19fb4103277a6b93.npy +04530566-b4f254a5c49748a2db2b485c26c9f191.npy +03636649-d438e1e1b540a30b1f329c416dca6157.npy +03001627-93a6876247c7a015d84b8ba651dfb8ac.npy +04401088-97669779da217dce4f37c101c765cd3f.npy +04379243-2a3297e263d9931b814465edb1048711.npy +03691459-72d2729801d56aa51f9f3ce366e030fb.npy +03001627-3269630cf8dd9e87bfd5f349b1ab226.npy +04379243-e7abab128d0edb033396b0dbcf4d4bc7.npy +03797390-62684ad0321b35189a3501eead248b52.npy +04379243-74db7acb40bca6eca707ebedc87d7580.npy +03211117-402938797a9a63bee270f79b60ac4232.npy +04379243-3253f2c59e6bd2a119fb4103277a6b93.npy +02691156-aa0b34d9bc5b77e0d86ebdaa02a63c4b.npy +03593526-72a7b73460850cd777939c607179153c.npy +02691156-35e2eceef33804d8196c5820729d438f.npy +02691156-9483e1b0e4222cb4f2b0736dd4d8afe0.npy +04379243-e3c8c6e7bc421e52e4721974983917c4.npy +03691459-9e2230b0d4d8d33e4ba7340387a30ad3.npy +04256520-9d6ac979ebf86ea9f37af16b2893f1d4.npy +03991062-fa2f25665c561e7be4179a13aff1e10.npy +03337140-53e1d0645ff2afc54c3aee8e9d3a6ffa.npy +04379243-66255a0a235927ea1b81a92ddeaca85c.npy +02828884-831955faf1c5eceb433fb7e44afbc69d.npy +04225987-1d527bbed4d12817fa3bb91f4e3cd35f.npy +04379243-7fd24508190c2e5351d3c864cc68e22e.npy +04256520-80e34c832c4881c1c1acd07b40d583e7.npy +04379243-5a04d5055cb9e3c3e45ef4135c266a12.npy +02958343-d849e0fee026c98aeece2324fbbe339.npy +03467517-af69a061bed20d8a2ccb8d77f3823711.npy +02808440-44278df837544b8a412deb0d2b0f3dcd.npy +04090263-5a79d10c5665b9dc895b56cd0d702185.npy +04401088-e5bb37415abcf3b7e1c1039f91f43fda.npy +03001627-4f42be4dd95e5e0c76e9713f57a5fcb6.npy +03636649-42c6478d294d71adfcb8d8c6d4df8143.npy +02747177-da9ee9282a5e7c77ad5067eac75a07f7.npy +03325088-4f3871c661ac8ae6c36fb70296e45483.npy +04530566-9122c94c6aa76d9e652b5e55e45d0bc1.npy +02828884-88f9fa58ee9ce3de1c863a93a9948fe0.npy +04379243-62bb78bfca7f4bba6113140c4b8aa3a.npy +02691156-78bd38a7282a73f8b184ba15dd506a2d.npy +04379243-7e51fe2b0e56f2e771b7a1511b87f5b.npy +03001627-59009d87f73ce9385dc3653f8341633a.npy +04004475-dc5354098d9fa08d49843c4f9ce432be.npy +02818832-8c1f29ccd64da4a6eab9455d2e880746.npy +02808440-9c2c7ae1ddbbf166eed6cfa9fc6d794c.npy +03001627-e78f25a1f66c19a38a63c123f2a561a6.npy +02828884-20222f467d257022c8bbbd98dee48cb.npy +03001627-a6d850761adf6003dc89a28b5e6678e0.npy +03001627-e017c5c8562ae50882eddefc99ebacfd.npy +02691156-c353ad7ae6ad2b9df1cb19f636b1c2bd.npy +04401088-393ae1877a5e20478139dd63d55edc44.npy +03991062-b3c256f5013d9c2244c183864792bc2b.npy +04401088-9c8bd4fce744a7df5d4e1af18c85258.npy +02933112-1e40a4dfbd78455812de5317fe5b354f.npy +02808440-2a83a721763cb79df15dc88ff54e5f9f.npy +03593526-4b5cfef99f228397cf0c9e00a1c0d141.npy +04256520-408199b4b50fca50f415ddcc43feede.npy +02747177-f0f6b79c748c9598ae1c1abea367249.npy +03001627-91ffa0718376a4fb3f7e27638e63d848.npy +04379243-6ab612b7a5d4def82454f22008de5a3e.npy +02933112-895de6b9d3e0f1ad11b65536c08c170d.npy +04090263-2ed25f939dd286cbf4c4f1f541cfa2a7.npy +03636649-2071651fb8407e4314038d588fd1342f.npy +02691156-aebc4c46b3cb7c3bca8607f540cc62ba.npy +02933112-ca9e248cdcca240f11a59b122fb65ee9.npy +03593526-8e88eb643cde1363ba5342d638d0c267.npy +02933112-39d9512e482ef253c59350d819542ec7.npy +03001627-9e1b32f73908cae7e8f8c11a24c52ebb.npy +04379243-96ef0920cb6be395e44bad6fc9badfe7.npy +04379243-1408914f71c66166febad4f49b26ec52.npy +02924116-dfacef652f7f414e4b88ac4b14fcb8bf.npy +02992529-ceb47998c0ffa704f1cb19f636b1c2bd.npy +03642806-1971fd62c05b664a816d6ef08b9362ac.npy +03636649-e94aab17400945413225afab722d9fd2.npy +04379243-8ed32fc808a31eb5ecd447b0bcf9cfb5.npy +02933112-8b0411fcc2d48f9a4b8710a3469971b1.npy +02747177-ccd313055ecb8799f155d75bbf62b80.npy +03001627-e6b0b43093f105277997a53584de8fa7.npy +04090263-a84652cb6886d873643ae903098a314.npy +03325088-7793cb4f3cb7f664979c556124bee033.npy +04379243-a0864018495ae55cdef39da7703174e8.npy +03624134-385bb539629cd6991dd89e5fcd05911a.npy +04379243-61198aa59e0aa31764d8b0368afacc65.npy +02691156-20dbfa169424bb8ed7b90ecb4a11cd32.npy +04379243-db77ba0cf616e2908369c37b40e82efa.npy +03948459-f6e410358d5a095a49a3c1009fa79820.npy +03001627-f0fe5f6030e999be3b9dbfb07aa21fc.npy +03691459-fb231e827089f9db69a175548b8cecb9.npy +02992529-3c0801c11fc7e4c5f31b75c4a94a8879.npy +04004475-4d246967795180971ed16b27fcde478a.npy +04379243-8fe842d92037d55be6942c5426df6055.npy +02992529-f7cb2d921f246c00cc8eea03ea8843cc.npy +03211117-f47b9fc9a55a731a7bc6032416bc8ae.npy +04379243-900afcc9f0f5fbfd858699aaad4acee4.npy +02828884-9399c7769b01d4742591fa6348c25a73.npy +04379243-abb1710ecb79812d93f55c796c857bef.npy +03001627-600f6f126d0b6c046dbda90cc7f3517e.npy +04379243-bac7bae00f0553bac88c75598a661012.npy +04379243-a7536a73ce066981c6641602bad03c73.npy +04379243-594a7dedea7abb21f77e460087130a90.npy +02808440-85bafd18f0457795810b41e4924ac586.npy +02958343-e3181dcc6b60432f658e57fd275f6bed.npy +04090263-45d3b7dd92a80269da4044967c19cf99.npy +02958343-3302dbdd74d978eeb1bb46d2556ba67d.npy +04379243-421657269cac10f7492d9da2668ec34c.npy +03691459-64058330533509d1d747b49524a1246e.npy +04379243-127e202f77eee5725d02cdadf545c773.npy +04530566-65e829c5a8a52b9491347c63d1dae43c.npy +04379243-613888be9e80b92fda684e203423d5f5.npy +03001627-582b375411f6a4565ba78ad9601cf1b.npy +03325088-4349f60256e8bcca76c18e71fd49c4dc.npy +03636649-66fcb967b951c0f11bb088904f7cb154.npy +03691459-93927ab6b44bb95a1c4980134f4ff624.npy +04330267-3e8165c41c526ea45eb64c1003065596.npy +04379243-104c5225ef0a288ff932326d9778e21b.npy +02691156-98ca06c300ad5a6bdc9181d6fa468db3.npy +02958343-598f0aea814b1d0f8db98a39370e7faf.npy +04379243-c842f85477f9bac0a7a7a90dc2dc5bd.npy +04379243-c6dbc7938060818cf51f77a6d7299806.npy +04379243-e6ddcae1c08b880811d3792a7f546aa8.npy +03636649-ae25da30c4293fcf230584014222e685.npy +04379243-b82e94209375e92a17b431cae0dd70ed.npy +04004475-29d22386bead2931a066c1f884f0378.npy +02876657-5566f264a6fa08cd2a68e506fbd6eecf.npy +03948459-d7e86e0e5b1982d4bf0ab4d7096d87f2.npy +04256520-1cfaa8ba4979b36ea60b4d749290e4f.npy +02808440-f15b0f42feae8d75b87c8f5e7f9beb6e.npy +02924116-cfc817de0241de11f5faeb3213703480.npy +03636649-380a312c4eede2eb72ce68571bfc4bb2.npy +02958343-e0b9bb886c578be86e9dcc2d1ea2784d.npy +02691156-997cb29f544d6f2726360e1e29a956c7.npy +03761084-c75ebd7c340649ba5ad304c2564ae1df.npy +02924116-7796efe8e1b0dede4c949161e83c47b5.npy +03691459-7c02e1c88907e8426b424c689f1d711a.npy +04090263-b52e26101ea750dfd1f50c75142faa8a.npy +03001627-64e77e9e5887ce95492d9da2668ec34c.npy +03691459-1e8aea643deed7cc94c70e7fd262be3.npy +04379243-92cbad40c55de5843002761e7a3ba3bd.npy +04379243-ec07a28c3d57d3275c6a44a505804654.npy +04256520-ce6c597847e7dd1e55eab99951962891.npy +04379243-ca4ce5ea2835b9d71e9c9b11de2def7.npy +04090263-81d26c915198c2d857f253aeccb15f0a.npy +04379243-cc1a9fc08b4c481c382c5a0f87d73d23.npy +04530566-6f61d84f9373f7c5c05557706bb20c4.npy +04379243-ee642ce4112cda8c229ab176c921b2b7.npy +03636649-9358ffb1bae027166aea2f18ee404fd5.npy +02808440-24c288011f4c14463321831d2245cf06.npy +03211117-3783ec2d4ac3b097a7f97cee360e8d0f.npy +02958343-97970b4b0f351f5a9697635485e4aab7.npy +02691156-12e6e5f07b3aad3c5b9f44d7cd72a051.npy +02958343-8cd32df8c0c566b2fbeef84a1ff2df7f.npy +03991062-471fe0704ba80876a9e86fec93eaa6ef.npy +04379243-34ca15546a48e34798d5fc0473d00a1c.npy +02958343-685f2b388b018ab78cab9eeff9aeaee2.npy +03636649-c4d62e5fe71fa71f1ba2f806cba87b47.npy +04379243-56cee7545143c9b67bcb070cc655f13a.npy +02958343-c54dbefca6290ee8a3b392b986583.npy +02691156-e025a1fc1bd71c2aacf77e718d93f3e1.npy +03642806-621882a4afd2a126369873c1090720a1.npy +02828884-f1252c297d7ad9a47c51ec7d2716b33d.npy +04256520-1a713136ff3c0a506298eed3ee847aba.npy +04554684-c1e9cbae0d223f9135e770f723375070.npy +04379243-2087680eed2edc0a20bf3b65a70accd3.npy +04330267-e4c8385cdd91eec0be8b4a628af8a88c.npy +04379243-52eaeaf85846d638e76bc197b3a3ffc0.npy +04379243-161e0ae498eb2b9be3ea982be8e701e5.npy +02933112-b56505eeac0de779289f8cbfc8541c14.npy +02880940-6930c4d2e7e880b2e20e92c5b8147e4a.npy +03325088-f3f585885793fe4814b35a7d7cea7130.npy +04090263-d31008f7c9b5d67678fc07d6c8069b8c.npy +03001627-9f6b1b905ee5ee9ddacbd849c304f00c.npy +02747177-1d5e46b18684ede7ffe3432ba4f2e6d3.npy +02691156-ab06b28f95e4c2caca8607f540cc62ba.npy +03001627-43fc49e4d4ff831b7df0e9a69c97c97d.npy +02691156-ec531add757ad0fa9a51282fb89c35c1.npy +03928116-accff92f4636f077396d085066c4d70f.npy +03991062-5e59e0970a6b05a5d67c0e209ce7200b.npy +04379243-14c9ffa70653cde3492d9da2668ec34c.npy +04379243-e8300d560b8d60244cbf9a02e3342127.npy +04379243-ed2d7f09d80ec3a259577d199a67fd7.npy +04379243-3f0e61a567fe7d366349f6b5431fb3d1.npy +02747177-74949d20ce6f5162ba6cf6cbb9f4c2bb.npy +04379243-ad461a7b5e8cc66efebad4f49b26ec52.npy +02958343-ca5236a5d06b9bb13fcfdd465734daf8.npy +03001627-35bcb52fea44850bb97ad864945165a1.npy +02876657-3f6d549265532efa2faef6cbf71ebacc.npy +02808440-c52b603a212365a4670204dee97dc037.npy +04379243-9db8f8c94dbbfe751d742b64ea8bc701.npy +02933112-c55eef8d5b4d3db563b3c67777442463.npy +02958343-7e4667d837e39d0945e930a0b8a8cbc8.npy +04530566-d2f2ccde17f68aa6f0a2921fde94663d.npy +03211117-2eb7069d227393558ea0068b966c5177.npy +04379243-b03bb928a8842c7ab748e35bbe935720.npy +03001627-c09cab69cc04378cff24fe90298ffa71.npy +02808440-7ea685c4ca42c7df63ffebf86d8dd00.npy +04401088-3d5c17c3e60a168bdaab9d410eb59af2.npy +03691459-dafd6b7408e43ae5ec3b2e05ce8fd39b.npy +04090263-45272a2a7c41e0095c97ca64716dc6d5.npy +04379243-c715a29db7d888dd23f9e4320fcb3664.npy +03797390-403fb4eb4fc6235adf0c7dbe7f8f4c8e.npy +04460130-376cc07140ada8e0b21a5c4b7083cf07.npy +02958343-2485b755d54f95b17461dc7993bb5c2a.npy +02958343-c34ef43ef8ccc3a701a8678a1e8d9e5.npy +03691459-2daca96a8e202949c67b8955be358784.npy +03636649-c6b545ae1a7b180879c251b4a7838829.npy +03642806-d838fc238fc640b83bba289a9fdd2a7d.npy +03046257-25f5f0d55feb7662f546596ce7364503.npy +02828884-64cf18fe86206f6e1b1a00a31bfed97b.npy +02828884-733cae1ea9a85122d41f2c02e27f6d9c.npy +02808440-f313673174ba24de1c17aef130ed6213.npy +04256520-16dca17207a6a2b87f6fd4fd84c364f4.npy +04401088-2d26f853e710b3e894088ff49a6baac4.npy +04530566-7a188a5ed26af4b360a251068e7dcf6d.npy +03001627-4a89aad97f4c503068d1b9a1d97e2846.npy +02992529-71121add7e94b024fb88c3d40924fb73.npy +03691459-62fa02df51eb19a5679c9e94dfb2276d.npy +04256520-ed80dfdb4a552b189d4d5dcd2cc33826.npy +04090263-1e83ef6ed5d0b78b7efb854782e23566.npy +03636649-1ea51a962ebd04f5775b45d31226d2b3.npy +04530566-91fd8bfce87a0e7d847c4e55bb965ab0.npy +04401088-11e925e3ea180b583388c2584b2f0f90.npy +03593526-c5fda0e7168d23ed89035c25f0dfeb63.npy +02808440-f0836272c93c3c40b362845c6edb57fc.npy +04090263-b9b2f960a937bb22643ae903098a314.npy +04004475-528e663093a892594eaf2ca511fa4e67.npy +02808440-a1774ed7dd03d7b717e29780ff39c480.npy +02691156-6ba3a181a40ac7aa35fc197bbabcd5bd.npy +03001627-fb3cae311c16eae32b18cbea175ad66.npy +04379243-8fae5133d952b2ddcfd3cc1d09bc8fc6.npy +04379243-511a939f29ca6763f169404e5c013db.npy +03001627-33319915ae51cbf33542091189dc62b5.npy +04256520-fc48d6602ba4904b5bbac631310d500f.npy +04379243-5918b05f59251e8c24507ea38c2d7c6c.npy +02828884-f11c39810334bc2a45bf743eed1481df.npy +02958343-ce93ae42d9cba64c8dcad5127c74b8e0.npy +02958343-ae54e2952eae6ce4473f10e6caaeca56.npy +03593526-d9ec6c788995408997e88473b28104.npy +02691156-2ce94527ad7f57333bfdfb6cb363d727.npy +04379243-c0b7cf5017ba0f21504c7f76533ac19b.npy +02958343-4c8280d581df259716abce8cb03e7794.npy +03325088-eaceb24407c702da3321831d2245cf06.npy +03211117-fb62e62c2b1584b45d32c81b99496e1d.npy +03642806-ca98fa6fe9c91b8b8b0a7ba4456e7659.npy +02880940-2a1e9b5c0cead676b8183a4a81361b94.npy +04379243-46e097e8c17a4098593ebeeedbff73b.npy +04379243-f6ec4343f78b94b42553cc33364504d5.npy +04530566-92fec5e70e9c972130327a4f3a474384.npy +04379243-d78c722ea1a1b2d4df253edc1fde0322.npy +02691156-7568400ccaa12eb9d972c9dd75ed77d4.npy +03636649-6e705a94eb0a7210e0ebca47533963a7.npy +04330267-bd6f0ae37e25089e136ac3990ab77b2.npy +03001627-974afa9a51eb74245c26acfe9040fa59.npy +03325088-b485f4d94b00763b362845c6edb57fc.npy +04379243-d12b589d464fab1862ba5d2f24e5abbc.npy +02924116-2a20a7a3da107ee749ce6dd3d22ed666.npy +04379243-5fc08f3f8c3aacb8456cbf78e1e89022.npy +03325088-182136abd343be8b8fa6d5040a6c641.npy +02828884-c5625ef76473a5cc7c3efce71c4e8d70.npy +02871439-3fe283e402ab8785937a1594070247a0.npy +03948459-d7ac2d2fafd9b9076314c3b6a3a65519.npy +02933112-6fcae7f06d9f86b2ce5d6e9371bb5c33.npy +02958343-f04f2fa810b6a66994abc9429888948c.npy +04256520-813597b7f538820ef51f77a6d7299806.npy +03593526-e4bd6dda8d29106ca16af3198c99de08.npy +04256520-c47bb0485a3aa2407252a102efb37f50.npy +04379243-e8f5c6944e41c12840d79382490f0976.npy +03928116-bb8acb49245b8f6ee8a1430c80ad4e85.npy +03636649-ec2806b889462892a84fca5de7f98b9e.npy +04379243-2ba8eb5ec0a05694593ebeeedbff73b.npy +04530566-502f848385718cb76e1f79eab597a3af.npy +03046257-4c0d048f0414e92e1b25839d42de8df8.npy +03001627-20e71125748a11bc3c65ef99d4b819a4.npy +02828884-1e4eacc8dc69a40e414354bfb060c386.npy +03046257-38b77917fc05e5a390e588f8bb3fb0c.npy +02992529-2d5f1105a92045c8af0fa49592cf7bc7.npy +04530566-29a895c9367516c1de08ac29282054f6.npy +04225987-9d79847df77172f5ee8f98672c31bd1.npy +04379243-c11829ca8ee139283d2617f9171b5ccb.npy +02958343-783bafaa18e8e5a0bda72093f9b5aa73.npy +02942699-290abe056b205c08240c46d333a693f.npy +03001627-c4f9249def12870a2b3e9b6eb52d35df.npy +02828884-969f830a531682cef155d75bbf62b80.npy +03046257-bf476938942c3e7e510ed2bc209ba71e.npy +04379243-782cef41b14a2009a71c812e027f94d9.npy +02691156-208114e3aafd381ef27c5ff0af8b0e80.npy +03001627-7220dcc0f3f95da3a84d309c7a35a478.npy +04256520-68c58177f6ead1ba9f2349486c570dd4.npy +04530566-4e6264af2f2c3e135a15c264bb25007a.npy +02691156-c4111dbb21e1f17043afdb9c81ff2967.npy +04256520-2a7fb9c95b0e8eec8de75bb03756213a.npy +04256520-6600d60c9d3bacf8d34d30b545306d1a.npy +03001627-d9159a24fb0259b7febad4f49b26ec52.npy +03467517-b8e67f04491740ac2be4d2d80280cd11.npy +03001627-21f2927b04e2f22830ddb6ead95f49cc.npy +02871439-34411a9fa3e00f668cbb8bac2032149c.npy +02992529-983b045d30322f96b102e855af58e521.npy +04379243-30e642f1d7b0d8818430b7446f9e1252.npy +03001627-535289ef7d9bdba8a69bcaf4198ba9da.npy +03046257-557a521bb01e092b503c5b0dd3b93560.npy +02958343-9e136de952f33de0a1830153974050c.npy +02828884-de00838284782bfe97fb25ec4f973add.npy +04090263-48f60ed3a4e32891fe00453e7ccbcad3.npy +04256520-fa5bb6d18535f66219fb4103277a6b93.npy +03467517-6dc4a1063fe83275a693a2475d32392.npy +02691156-577ef32f6c313a5e4ca16f43c2716caf.npy +03636649-7d7dfd2bd5cdcc4cfca61b0bec17b8d3.npy +04401088-b72ec892f88ab015433d4f1444243caf.npy +02691156-ddd729a8623bcb6e8699933784576e73.npy +04379243-adee49b8f5251efeaade78cbbf8fad3b.npy +04379243-fb158adc15a6b5aa75a82b88fe6e733f.npy +02876657-6a96b74beea7f5b316aa41fc58452f78.npy +03001627-d93760fda8d73aaece101336817a135f.npy +02876657-244894af3ba967ccd957eaf7f4edb205.npy +03691459-4f228d116af6e6ad88a3e0e92891ad5.npy +04256520-207e1410735bcf5a62556536221025bc.npy +03948459-14357d3397d55ed2ee0f9a97b71d505.npy +03001627-116a9cd5ac9a008ee8cb931b01d0a372.npy +02691156-b831f60f211435df5bbc861d0124304c.npy +03513137-7da461d2b7ac1454e5e6ac3ef6bff73.npy +03001627-ec758c4557250ca79f2349486c570dd4.npy +03636649-4b43b17b960930af53b1634376cbfb93.npy +03467517-c3c9bc3aae8231ba93f0194265a9746c.npy +02933112-26979d498a0425b6f51f77a6d7299806.npy +03325088-95e13660ebae4953b362845c6edb57fc.npy +04379243-c477235c02413bfc44d2ca62bee212a0.npy +02808440-b08d711c39561b793321831d2245cf06.npy +02958343-6fce36e4df1eac4fa7fd25564c2e888e.npy +03636649-f7495b2e74c906b5922ab3cc7ca1ae2c.npy +04530566-69379ea3029bb2f6ee5140f12d845ca9.npy +02691156-223b0ac8399bf9c5ea1bd6f2443b43e7.npy +04090263-fa811fb70a13c68f95eaa1471ee21cd2.npy +04090263-91b0c8975ce241d69557371cff545901.npy +02747177-de31ede76692c36271c1c4a28b10d064.npy +02933112-6081348fd96b21c3eca22c501ad0a77a.npy +03001627-fa0eb1bb05ebe3f2dd3adf3090c701f7.npy +03001627-ce774c6584d282ce843ead12644a79bb.npy +03337140-c38a124eac2adf5b91c352d02061b3f7.npy +04401088-caa0cf3c7bf2cc4e50e8879f012090b1.npy +03948459-a2439ac7a1f3ac841ba5cdb283b62da5.npy +02691156-be02fd401a12d23822362be7f5226e91.npy +03001627-c05ed12b1bb79ef6d8e8a8a207ee5bd2.npy +02691156-3fd97395c1d1479b35cfde72d9f6a4cf.npy +03001627-7fbde9d7cd67587712ad7c55c944504a.npy +03046257-71eafda69c77150914038d588fd1342f.npy +03001627-352aae8597fc6ac679c251b4a7838829.npy +04530566-19df5aa5324f265d4de203ef6842ee61.npy +03001627-c109b45b290d4cacb161f36d4e309050.npy +02828884-4c26d27e41726d87f359d99f906f117a.npy +03001627-c5be3a0cd25402f0242f43e6bc9e11b1.npy +03948459-d45435235c262f179f433921788191f3.npy +03211117-3bb7a8505b99216a53227dcd0d547ba6.npy +02691156-d629589ee52d48ee4d210d9468aedaf2.npy +02958343-baa1e44e6e086c233e320a6703976361.npy +04379243-788c9d078cc971bf91a6d2f5a0fae0.npy +02958343-8fadf13734ff86b5f9e6f9c7735c6b41.npy +04379243-d3b644f9eb32ec9cbe1fb1bc0addfcca.npy +04379243-f619501cf26b4d533b7f931c53ba66d8.npy +03593526-7becf46a6f6428404bf49568516d5f0e.npy +02691156-91a00801903a1f64bc0909d98a1ff2b4.npy +03001627-d25b6ce1b5ad6198dbbc9440457e303e.npy +03636649-1feb0beac92a26bcb0aa15078ea6f391.npy +02828884-723138769c7c84eb5006d092e9ad4f03.npy +03001627-e8187497dd464b62f91663a74ccd2338.npy +03337140-b406aa9ee044a9f039e7e5a97caed0d0.npy +04379243-b1335d826d7d60726e066e11deddab75.npy +03001627-6dddf2b95ca09bf5febad4f49b26ec52.npy +04379243-c8ddf2c234adc19b6e848052f86fa0c.npy +04379243-f090d4f5e82b3c25f63a1cc836eff7a.npy +03710193-a305c425f2409d562e33f9f68dbe6c42.npy +04530566-9c41a1bc835ab6d81194cbd9c0740031.npy +02876657-22d18e34097ec57a80b49bbcfa357c86.npy +03691459-c7965a5da1143830538cf6df9faa9b65.npy +02958343-b12e8616bb73f5daccaf7041f92bc85b.npy +02876657-a1bc36109cd382b78340c8802f48c170.npy +04530566-51f269a4ff48c2214de203ef6842ee61.npy +04468005-26d7ebe6f434ac67e810c01b1498aa2b.npy +04379243-a10ed77ab3a714f43dbb6421d614c0d.npy +03001627-8b2949a4ab8f5a7d84c7dc40ac6d743.npy +03636649-a58ef2d9168f9b44de195732ce36834c.npy +02958343-36190ce6fe041e452d647b1c17442c93.npy +04379243-e88f6f4e0ed6d01effc6e457221b9271.npy +03938244-b4175523993f66e8d330ae3d046a415c.npy +02808440-5540561e61ad6e063321831d2245cf06.npy +04379243-62e723ad4ee0ba9d65579260f47a2d77.npy +04379243-3c65571a506b6486db5ebc3f027decaf.npy +02691156-2d33ee87ee5230c335fc197bbabcd5bd.npy +03211117-50575a330ffdc66ff5a91610a18641eb.npy +02691156-bad8f0b4602df33fbe4274edc10c1c8e.npy +02924116-eecc64e912b980241e797b014c500fad.npy +04379243-aef9ca5d1b98b85186ac7f2dceaa530.npy +04256520-72988c811a2c88b11206ff076758ec85.npy +03636649-ed57181b9e7644a3f51f77a6d7299806.npy +04401088-d1b34149a8faba42faab2c6c450c7c1a.npy +03636649-adc8129076715686b3742b0325c8aa1b.npy +03928116-2c740240be7df1958148161f751e44a.npy +03211117-1a92363c2a155ed3c397356311cbeea4.npy +03046257-f764a6a70636d54cafcd02e9a1a7ba34.npy +03691459-5acc9b2fd33a9568bf19c71eb972f14e.npy +03001627-6932261b5c17f0de4733824eae5cd9ae.npy +04379243-d7dbf6005f2e8fccf6ef7bb1183682c.npy +02958343-f4fffa99e8c2b9b627a00642873b9759.npy +03691459-fbcef568b50216e3e180a1a604561d3b.npy +04074963-f3366e751820f0f77e1c85c5c15da7fb.npy +04090263-c1e4e78ba2b714175814fafedc6971c7.npy +03001627-3e2375ff9e7af8002861ed753d5b88a1.npy +02691156-8200621d7b5cb84a6b7bd17e458d0dcb.npy +02942699-98fc1afc8dec9773b10c2418bc64b141.npy +03593526-1ca73dffe31553efcb349a60fd15aa15.npy +04379243-e71012d27b3b3eec67142c6ea337b7b8.npy +04090263-ad5165b445e67c06cd1b85350f224c08.npy +03001627-50aa55467c87774b7215a1e3ffbff428.npy +03691459-c91e878553979be9c5c378bd9e63485.npy +02691156-fc5dade8622f686b4aba1f0cb15b1439.npy +03001627-3837e94954187dbf93b0969ba78346b3.npy +04468005-d8cb93fb3dc3609434754e47237bb24d.npy +02933112-d5058b014492f748220c986172788383.npy +04256520-532e2a8e2ae6f5616bfa0701d875ff10.npy +02992529-df23ff3151aa1f0a3cb2f20e21cb06ff.npy +04379243-cf076ced8264a480cce90f0d61ed7a70.npy +04379243-e5b4980736c034257de96030404c16e9.npy +03046257-e13f5f28839b623bcff103a918fa8005.npy +03001627-4b71f633ddb55c6e309160eb001312fe.npy +04530566-e853f137948055b188d5590328ce0ddf.npy +04401088-4e2f684b3cebdbc344f470fdd42caac6.npy +03001627-6367d64115d665ef51f77a6d7299806.npy +04379243-dbb28a435349c9c76b1cb83d86c19bfc.npy +04256520-85a8fa447231a4fe2d19175e7d19b7cb.npy +02808440-25709b9ab8facc1b3321831d2245cf06.npy +04090263-8325595fddab7e47dbf42f7773eadf2d.npy +04256520-44503d9ba877251a4b48718ea0a8b483.npy +02691156-40fefe66b018c17b4c2c88971423d0be.npy +03691459-93c54cd14ea713d34d0c24eb0094dc21.npy +03636649-a5b8eda3cc13acfbbc8967b0321bd9d2.npy +04256520-aa36fd4d76afcaf8bdcda0bf7e7b4744.npy +03001627-cbcc5cd1aec9f3413aa677469bbdd68c.npy +04379243-d7edd292f614e9dc58b7984178830447.npy +03759954-e9178d7aa6d35cbd76f6deb1c78dfee8.npy +04530566-ac93c084dc99fa8a1613e32ab05e546d.npy +02933112-90f66de8ce581ee39aa778fe3a2080af.npy +03261776-e8195dc3c0235dfe49852b2ef384d236.npy +02808440-2a28b3c0318590983c8d0fdfb1cc2535.npy +03624134-b918bf1a07d71b4f1b9c8e2fdbfc1118.npy +02958343-54d525937d9c6921afe717997470b28d.npy +04379243-9b17a95b794b3dc341a298cc53deb86e.npy +03046257-854f8ec7013d30aae6fe3612af521500.npy +02958343-fc25e4c1bcfd9167b376886260eb15c1.npy +04379243-1a9036f081dd51683a9bf8c718fc345e.npy +02958343-ba0c32b3feba49b0b40adee184c371d0.npy +02933112-22e77a41cc388839824662341ce2b233.npy +02958343-cb5a320fbd846fac28e9ca8e8fb04e0a.npy +02933112-60ac3a02f8c1116b5588a2543ef0b0b4.npy +03636649-27623aecfdae2d887eaeab1f0c9120b7.npy +04004475-f065815f98d3f2e52711ed0adf8251d4.npy +02992529-df816deae044cf448e53975c71cdb91.npy +03001627-9eb0c534624408a6ca9b40e76e725878.npy +02828884-8afe9533153bb82b157f5033576317e1.npy +03001627-a3ba5f8fdc8f17ee95bea7c29e873d16.npy +02691156-9465be8f818fbf94b01a0cb11141e033.npy +04460130-2b6257595edd2e62159e1f7290c9a432.npy +04379243-e7c350f18bab885bd0bcb58c58eddb59.npy +03636649-41c1e411592ecabcb7487183c0e206af.npy +03001627-41ea9182aa12effef47265090d8660c7.npy +02933112-9d75f1513c57e433c8f56fd282ce5ea1.npy +03001627-f9e386d968653602d68fb8f5d99affa0.npy +04090263-981b30a44557ae28caf05f9cece7ada5.npy +03001627-bb380888cf0ac2e79c0b027ae5b223d6.npy +02691156-c2ea74539ffe96f8be4274edc10c1c8e.npy +03691459-f2a13a030a8153d9133aca0b3ca7f0a8.npy +04379243-cd0dccabc5966b40d42ec7e303174a87.npy +04090263-298d300e70d6bf24e1f2a1daf140ac9f.npy +03001627-fedfc00265711f4193c1e619801da0a6.npy +04090263-641157eaebb2183ae96eacf8990e6676.npy +04379243-d67265ea100ceb32ce11183544874734.npy +02933112-740f399fea35db05490ad276cd2af3a4.npy +03001627-8920c0e0737409e29f2349486c570dd4.npy +03642806-ef8ea9a542b06adcbd6e55f88e701c4.npy +02992529-c8948cb8ec0f10ebc2287ee053005989.npy +03691459-2b3e7da84b849a84d3dbdb797d2f78b5.npy +04530566-a9eda0d90297844cf92c4a072103d4f3.npy +04460130-34e391f9e9a72f97c5e86946f2168706.npy +03001627-6cb3d99b20e7fbb5b04cb542e2c50eb4.npy +03593526-7d71fc51ce793a44befd8bfd61b07f5.npy +02942699-2c0b4e318766e01723cd81bf29b64a1.npy +02691156-fc44636ad5fd9754927b6179bcc6e892.npy +02691156-6187d076d53429aa67c54439d6177032.npy +04379243-7ab9eefef9fddaa416a2b5862518c93.npy +04090263-acc7a95f567e94355ce192ce2ee187bf.npy +03001627-5f9fd9bf28da76ebed2eab6efdeec5f8.npy +02691156-68f26c36ba5340ede58ca160a93fe29b.npy +02808440-1c908b81867d6d85b362845c6edb57fc.npy +04379243-4726a178bb7b40544b3c42e318f3affc.npy +04379243-8b5c74d6fc057bb24789ee5c8d247b09.npy +03636649-94e8b7adb07de08e714531f0291497fd.npy +02871439-61ea75b808512124ae5607418ff674f1.npy +04530566-ffffe224db39febe288b05b36358465d.npy +03593526-ca00e43903812f9bf8f2e9a6f7085339.npy +04256520-3230b6c7f396afff19fb4103277a6b93.npy +02933112-a593528259cf4d78c0f947750540fb22.npy +03636649-8ef9c1ffaa6f7292bd73284bc3c3cbac.npy +04256520-c1ccf7d15c32b156cc2af5791bd669b8.npy +03001627-498755187e526e5c1cbcc2e1b14b6d41.npy +04379243-7c46b661b94fdfdd34528a88ad1d85d3.npy +02828884-b95994218ee416f492d9da2668ec34c.npy +03211117-274acc511daf0161bbf0c65ae96423ae.npy +03691459-61508357d7d9ff38a605f453cefe7e92.npy +03001627-3d63ad34e3deca1982db9fca4b68095.npy +02958343-492f36ac59d2d3eb450d7227edc25975.npy +03636649-2fc19897a2f384ebc77d45d65dc3714.npy +04379243-da9d681e20d2c123604b3895514420b1.npy +04256520-697161cff5d04992a4dc2316a7e66d36.npy +04379243-91fa004401e96d0797059057d5df0d8.npy +02691156-137acaae47b50659348e240586a3f6f8.npy +04379243-680d4a8b5a30601a4b3c42e318f3affc.npy +03001627-6398eb498fa1c291ca22b08889f6ea0c.npy +03211117-9716c06d43de24387103ae93fdb3bd5f.npy +02958343-aa78d4465ae18312711f9e3a79a13dcf.npy +03636649-2ab86b983d36642141b0e36ebdbf4b7a.npy +04090263-c5c335bfc5858d11137e0f55e7272392.npy +04554684-957ddf9eb718876dc2180858eb6a5f28.npy +03593526-c03bbfcd33f310155076fe09061f1a7a.npy +04401088-5e5c0391952208e81213f8f7891e7fa0.npy +03046257-1710033fefac979deed60df91eb05a5b.npy +03948459-2a66595c64d5e6ded957eaf7f4edb205.npy +03691459-ae39f8cad4fe0981332d76467c18dfde.npy +04530566-733105c0a74ab0a2b83ec978f31c7f76.npy +04256520-99a3e307a8e08afa575f974bef523d40.npy +04379243-22a19599946e4db6c3bd24f986301745.npy +02691156-6693d4bd6edce2a7fd3f94e9ae089f96.npy +03001627-eaf231f17fccb96d81dff5c2e57ad46e.npy +03001627-d2815e678f173616e6cfc789522bfbab.npy +02691156-7578bae68447de8498427765723d5e48.npy +04256520-d8a5ba127550669d55030a5efaf6babc.npy +03001627-6831b0aaec44c01f5d0b6dbf2c4992eb.npy +02691156-a5cdc19967a8f69fedf24d76037ce02d.npy +04379243-3c5b03a212d8cd3951f776d3ed05550a.npy +03636649-9b1c1def3467c1a7d197f67767b32741.npy +04379243-75f2e71073707ffd9ed6e8a0d47c5a7a.npy +02828884-9fe85429413af216cb2a965e75be701c.npy +03325088-482e8134a2d5461b14b35a7d7cea7130.npy +04530566-ce6e40c533159b2db9e8bdc9c4a49aa2.npy +04090263-86886a49bb69dce3fb5c1b0f759e2bc1.npy +04379243-f7b8a1d716dc1725aa7cb30470f3273c.npy +03593526-682de86ee8578339490ad276cd2af3a4.npy +04401088-5298e9c7eeca74f8ff2988f561e515f2.npy +02958343-f60f11a1a8c8f89992691fb966926839.npy +04379243-edb7dfd7fe00c08e25c8be43ebcd1add.npy +03001627-c8d6e4e789a0c6a7eaeab1f0c9120b7.npy +02691156-fae6ae6ef62cfa107b164268a44f7712.npy +03337140-cd37ee5f404f393cf3a0b1845ee9aecb.npy +04090263-da4294d14502707a82cb4f2e118e48f4.npy +04379243-5ce75eec38f8437c8a64c4f643bb7cf6.npy +04379243-11f2882ca78cd85c9c75eb4326997fae.npy +04379243-ec8a05151bdfd44779368d1198f406e7.npy +03691459-a12a46aa47ce021a0ac302bb9c69c6f.npy +02958343-47748464909a5af473f10e6caaeca56.npy +03001627-cbdfedbf2dbeed3a91f6e3ed62ffa5d1.npy +03691459-7263b5bed1c020d3fd8284eaee3b0fd.npy +04379243-ad6fc60679879c234e08ba22112c59b1.npy +04225987-eb6246b73afb6383b77008f97c3030c.npy +04401088-b45f58361ed3ae739d2375e90e0e0425.npy +02924116-dd932656e7f1d74452470de2774d6099.npy +04225987-54b9d9a3565820e17f267bbeffb219aa.npy +02691156-4788f4d5afd92e151df8f3faa46a0206.npy +02691156-bc16d2cf6420432cb87697d3904b168b.npy +04379243-72f0bf15522498993f10a8b8beb12d1.npy +04379243-dab06bbea57f6051d0b93fa304cfa755.npy +02933112-180154895560cd0cc59350d819542ec7.npy +04379243-ef02c88a34b3888a1b1a00a31bfed97b.npy +04401088-8873af9392bc7506f1cb19f636b1c2bd.npy +02958343-2e27309be42276bebecf71e2e014ff6f.npy +02958343-163786646ae2578749a5fc144a874235.npy +04379243-f5d97731def4d875f51f77a6d7299806.npy +04379243-e2d5de278cfff9cb55388518b8ef9c17.npy +03001627-816d1c517ef6bf7890a9ce3e4b15521e.npy +04256520-fb74336a6192c4787afee304cce81d6f.npy +02933112-1caaaa5c1da4dd2dc59350d819542ec7.npy +04379243-d950e75bf7eba6ff35836c728d324152.npy +04379243-60c942ccc194a8e88d4313dc14de486.npy +04256520-8aeec0b2dc06c3df9274d508495753d2.npy +02828884-1d94afb9894bf975e76bc197b3a3ffc0.npy +02933112-2993b6f0fa043f2744b0bdbb4386e313.npy +03001627-90500d52ac30dca9f51f77a6d7299806.npy +04530566-76dc1a35fee28991a5103c3a2f33a5e9.npy +02691156-132fc603f8f69b08e816c75152573ee0.npy +03001627-a9cc6920422b9d9c2af8b1d491b7ebc.npy +04090263-fbba8fc424ed0ad6f8edafa0d47e47db.npy +03790512-6a05091b7b1bae0352fa4ad29a1236d7.npy +03991062-71421e76243826a8a2c59a4d90e63212.npy +04379243-5c94122a5a3682bdb2d2900ee0ae7e0.npy +04090263-1e7dd1677a62d3caa672357dc73b83a6.npy +02691156-a05cb1f091b01cc87aaa57326478bd1f.npy +04379243-ca9bbb0ecdcde978178548484b14e6f6.npy +02808440-916c3b82c5ce6bda5be62ca6b91c7ede.npy +03636649-2f6f1fe66631572c6c5b8009db95f66f.npy +03642806-877b995954f127225df8529b323d6f29.npy +02958343-b48b8791a3b09753b8d3554bd033ee9b.npy +04379243-4639656b53d21ab1278d386bfa54545.npy +04256520-4954953090ca7442527e7f2c027f7469.npy +02876657-5ca994bd512be485db3bac7ad77ae88e.npy +03001627-4c97f421c4ea4396d8ac5d7ad0953104.npy +02747177-7a73f3cf362ef4fa619b1cc3b6756f94.npy +04379243-3cbd3d2da993a389fb05cb5458b1da64.npy +04530566-8676b1989d68f3e970c565b5a7d76650.npy +04379243-fc8b1310927ce3e6d8d12f352b5e1839.npy +03211117-c5d14b600ba28289ef2d91f96fdec842.npy +03691459-d233b0a03f171cef47e72126a394af4d.npy +04379243-c9e09052118e6fc112e2da326535f859.npy +04256520-d65ef2797ae836ca8930422448288ea.npy +04379243-4949aa2bb737317225f1bb0febd3472.npy +04379243-4775e71d37374444febad4f49b26ec52.npy +03642806-d9acee6657134387c664c3d4e2d59341.npy +04379243-4f7f8af38b1a13f67c1b348241918030.npy +03642806-b913c80eca0afa4a1b7e0829f0e4fe61.npy +04330267-48d103efdc593eb9397a815191739e2e.npy +04554684-ef6d0cac2707dd6ee262a7452d41c334.npy +03001627-7d4aff5680062f0b1143841839c8c312.npy +03691459-eae023e4c609a77799234ad1a4f88718.npy +03624134-ba521f73a0a69280f5125275d6943657.npy +04401088-36760a27d679f058c4a0b6f738c144f4.npy +04379243-1f0df5b240c73a5078dd615a59de5f05.npy +02691156-800334df5da57266a4642ec4b6f68a.npy +04379243-b6ee1aa4e11df2bf8f5708c6c7585cb.npy +02992529-9c8bd4fce744a7df5d4e1af18c85258.npy +03001627-663f02b2ed46f991480b0456bf1622f1.npy +02924116-4e1fdafd569814c241cefd10ce5d6cc0.npy +04379243-860995856455e258fc0004571aec2fa2.npy +03636649-e053e531fc4341b5fcb8d8c6d4df8143.npy +04090263-66e287e1d2e9c9f6e71e857afa9df271.npy +02808440-bdac92a52bc53cb4b362845c6edb57fc.npy +04256520-87f103e24f91af8d4343db7d677fae7b.npy +03759954-3484d12ad3b2f06b35cd53a06b1d2317.npy +02954340-7f9ddfff396634f17790cd6f6e8952aa.npy +04379243-fc95d34ab1afb92b9118eee0b123125f.npy +03001627-f4f1aba65ebe48eb70930286c914896b.npy +03467517-71d0016078dea05a94ca7929d4ba6d2d.npy +02691156-86bba8b007786db7be00b7fbad2ca0e8.npy +03759954-1784a6bea782ef4af50956e9de496e43.npy +04379243-21fe96bc7ca206cf4ce89debb609dbc8.npy +04090263-ac88c6856c21ab422a79dd7a0c99f28d.npy +04090263-8ca120d9501983b312b38b1d99376c0b.npy +04379243-143e612ff081f2fc3dd0bb3e608c7548.npy +03001627-8e1f9f4e3cd226bacb916d8f4f1ff996.npy +02691156-ff6ab0fe13f58e22962a5697e98a94be.npy +04090263-e01eee98a8d18a29a2d71a426315b93.npy +04379243-b7820dbf7820befb99860e9353bb52a1.npy +03001627-434cee44934612a81f98c0761af40e04.npy +04379243-591a2b1a6c44e5ae535089b1cfcbf17.npy +04256520-306a6efdecd98ab1456cbf78e1e89022.npy +03001627-28445d445cb8b3aa5de04aad18bd94c3.npy +03001627-986058a64eb343c6781b8c940ab86a39.npy +04379243-9dfcd3488a7109745b5b328c62af5142.npy +02828884-5ab38425eb09fe33cac2a982f1c2a5b5.npy +02691156-b55af8905ccc3b35102bb5032a53eed8.npy +02691156-88c4ef9645eee90866876073bf7a9ab0.npy +03046257-619cbd4aa6ae5578f5635ac8b18fdb9.npy +02808440-f96cd761f71daf3354d7082b34825ef0.npy +02691156-816f1a18692bca2abc0909d98a1ff2b4.npy +04090263-d0f3ee45d483cd659f433921788191f3.npy +02691156-4fb10ce02887e35efca1f1143bb6bc17.npy +04379243-36770c30c74a32e16dbc8927361b2733.npy +04090263-57c6c69a1406e9be21d9cbc846872d86.npy +02691156-78a63dc99b3b68962b600da24e0965.npy +03001627-48c0684d1c5e279dc3bd0b373cb604dd.npy +03046257-555f0083553a7cbbe4bbcfa1dc6a2906.npy +02880940-a0b34a720dd364d9ccdca257be791a55.npy +02691156-740e79be16a92efbf1f2e10bfa81e2b.npy +04379243-a7887db4982215cc5afc372fcbe94f4a.npy +04379243-839af4cf455c049347839bae1bc65257.npy +02933112-203ef2b06c3ad6033fe047712e43e185.npy +02691156-c2e047aa11190a0f3523242fdf9b75a7.npy +02958343-854881671316e926f63ee8a34069b7c5.npy +04379243-6f85f70a77782307f4ab13f4b49ac318.npy +03001627-1959a7d986720364c8687ff9b0b4e4ac.npy +04379243-9eb1ec4c70696799851f4ba6aaedaaa8.npy +04379243-6b4800452f4655e7d34b068b4d9c2c60.npy +02958343-5aac7e6813771b2f22cd6c209adfc63b.npy +03001627-d764960666572084b1ea4e06e88051f3.npy +03001627-e7aa94a2dd59a5ed492d9da2668ec34c.npy +03636649-7c23362b39f318cbb18d6f615cb18bdd.npy +02828884-88a00b80d432ed5a577e7964e0284adb.npy +03001627-cef1883847c02458cf44224546cb0306.npy +03991062-d6209472e79d0a2422b13c48c34706de.npy +02808440-9dc757fba512200b167a3045f56a81f2.npy +02933112-1e73a722906872b64da5feafe6f1c8fc.npy +02828884-324257d878597916bea0f59596aee501.npy +04256520-b50519cfcc841200e8f8c11a24c52ebb.npy +02924116-1ddcb6107e5b08f39206ca9600b83578.npy +04090263-5d3a612df6585a90cc34b900bb2492e.npy +02876657-7712db835816a52b250241e1ab69b97f.npy +02933112-19127cb1f535bf2c62c9e7b595148d6a.npy +04379243-5d2c769d1afa6e3742f75bc7df727ae.npy +02924116-6df43a1f0bc546a71759ca9eefe0e251.npy +03325088-7f10cd36ec471aacb7a867e9b35a1295.npy +02808440-f1910f9ad5c58ba7f5eed355a820c382.npy +02828884-b6c745406a599dddad5067eac75a07f7.npy +03691459-b8d62dc24152a3463d91ae2b92426394.npy +03001627-97cd4ed02e022ce7174150bd56e389a8.npy +02958343-aadf8736528b0f46857652684714945f.npy +04379243-bb1aa2cdf216d348e76bc197b3a3ffc0.npy +04379243-6bb78393aaff36b8f42467d8c501ee9.npy +02691156-c854bf983f2404bc15d4d2fdca08573e.npy +04379243-46f6cbaf4897aa45aae567e8dbab47de.npy +03046257-5f4711bd703bd262f51f77a6d7299806.npy +02691156-6a3028e1c7205b22ad6a38fcc21e6e9e.npy +04090263-df531a3c9ed88efcac074df1dc27122.npy +02871439-3f543bc217133f7369867582939a3cf7.npy +03642806-535edbd064647a2d21c4ab26dcc5566.npy +04090263-1a1c0ae2b0a3cf3c80c2e60c312b0f09.npy +03001627-74518f7c342b49191030665054ebb2a9.npy +03636649-1ae630bed26fcf4d448e1c9934d83117.npy +03636649-6c90f92219fd4ba74719088c8e42c6ab.npy +03636649-c02a408b63a91d294cccbece4754c7cf.npy +03001627-3a96b4ac78928fadcfd33d85f931f6e8.npy +02876657-6d3c20adcce2dd0f79b7b9ca8006b2fe.npy +03691459-9a8a760dd2094921bb476b1cb791329b.npy +02691156-967b1afce4221816cf67c0b63878e138.npy +02828884-263f629d385be2b1601104cd2d998272.npy +02924116-fb65524daf2a034bbfc1f7b38863194c.npy +02691156-26048b00f9227a9f8699933784576e73.npy +03642806-67e882442eb4c03255e8ddeaf1791474.npy +04379243-e7eb326a867912fe16b2b5432674ae6.npy +04379243-4475dea2d05c1ee4fd9792d1e260da32.npy +03636649-300a2c57c5c0a31c35836c728d324152.npy +03001627-57dfb295c3e699ab2875319f84a135b4.npy +02958343-6c28f87aebb33c294386e619c2d3f83e.npy +04401088-b159743a482e73baa56eeaf8467b96e.npy +02808440-fdcc9d0d2e24b4f854d7082b34825ef0.npy +03691459-90a050674ebcfffe475649efc0ac5403.npy +03211117-df8e098d4dbcb5b2ccc4d915989bc424.npy +03001627-18845d9336d8be637b11ae648ea92233.npy +03928116-9b3e41030538e8b459a6208793b9dfca.npy +02933112-515df524aefbb9c2376a431c347bc40a.npy +04379243-95301825e69b3b2db04cb542e2c50eb4.npy +04379243-f1bfec97b7e9f7b776a402eb60ff1f9d.npy +02992529-f973c91a4c239da9dd14866f469b6370.npy +02691156-151550551758af098b96ae1a0a8b84ec.npy +04554684-5517868119f44388a027ae047c88a1b9.npy +04401088-b514d253eefdbfdbddfa02c62bdf0f8f.npy +03001627-cf975250fbeec5148b01ef724ff374fa.npy +02958343-e0762bd3cd381408bda72093f9b5aa73.npy +02958343-557315ec87e7ab9d3189f4fd2261a1d0.npy +02933112-a69a97674b732b6e951c1fffab4f5807.npy +04256520-b58291a2e96691189d1eb836604648db.npy +03337140-eeffac7af3c013f2492d9da2668ec34c.npy +04379243-3281ed5a4af3494f67990f5b8451542b.npy +03001627-1e7c8833d231178fdcddd0cba5e9fbec.npy +03636649-ca8e73b360017dfafcb8d8c6d4df8143.npy +04379243-650dd98cb20580cb99860e9353bb52a1.npy +03211117-d4d94e7a1f75a67e3f7b7c3393bbad8.npy +03325088-3e208d2bcf317a2b362845c6edb57fc.npy +02691156-ef20d432f2a7b1752c164e0c5ea74611.npy +03046257-fddee751fb9c7244b3c42e318f3affc.npy +02924116-3c45d466c7e1c27367aa983983f9bf36.npy +04530566-8d95b6ddd06a8a80f57109a0257e61dd.npy +02958343-4de80d6104368f4be194052f3f12cb2e.npy +04379243-1bc326fc94e0cfc1cf5a37a70014c623.npy +03691459-e30bfb0ab456101cc0b5947ffe18a468.npy +02808440-2901f503b077e7a0fe52ffd0e748a1ab.npy +04379243-a003e49331f19341b0449d422c1e5657.npy +03211117-bd3df021605a8aa24c619b8a18eba62d.npy +03325088-2439d924018a3b198616812464c86290.npy +03207941-503b4dff71b404dabf195d81040cc60.npy +04004475-dd8927d6710e354479510444cc61f839.npy +03991062-1e2ffb73f4912932cfc0d4d561c11099.npy +04401088-a9c181d7378f92cfbc59a3627d9edb6f.npy +02933112-71bca48ccefa3cd080f94e6470f7d263.npy +03636649-25bd069704996e073225afab722d9fd2.npy +02924116-4e2154c96b2268ba52470de2774d6099.npy +04379243-7d358a01c9467815a9505c473725122e.npy +04379243-57c21a71a3518b6a1af550e7b4aa14c.npy +03636649-9004c69559c8e6f99ea7ba54de81fa1.npy +03001627-7dc91406f30074777b707c797539b200.npy +04379243-1c6eb4cd121175f5d009c98a5b96836.npy +03636649-f97506704760741b460fa882e24b7e4a.npy +03642806-b9b521a7e25caf837b18e772ada5a339.npy +02958343-eb46e6071b4f72659bc0c5b67eaafbc.npy +04379243-37ca38d0074d19978c9e244e3fbf98f0.npy +02691156-49131e925ef3349566cf1b4a8fc3914e.npy +02958343-80e839edb7aeae0bc54427e2c0943fd5.npy +04379243-29367fd1bfe6b23827775562146ecea9.npy +03337140-bdd91f5a44301af0ce5d6e9371bb5c33.npy +02992529-692e5fc16bc6ebd23737433332467411.npy +04379243-1f326aac412e727b62ca3aa650ba65f5.npy +03691459-fd421313164e2d7f1be6fffd725195b9.npy +04256520-a53114ab5cfe2048f51f77a6d7299806.npy +03001627-60a5795c905f3bb157f5033576317e1.npy +02992529-7f5b9c8fdb46cf7c562c8e1ac545ef78.npy +02691156-ae4fff8877a5a64b3ae1361afc45ac52.npy +04256520-dc097b47bf15ec8e7934a0d24a61231.npy +02828884-a7096667d133db73cb2a965e75be701c.npy +03759954-98b0e21d5ca46e222afc25cef0918375.npy +02924116-74ec0dd3a200686f58c7dd2ef106ede3.npy +04379243-d6c68f9d1844c3bfcb002c1e2b5fc68b.npy +02747177-126ae26edcd76f27ad5067eac75a07f7.npy +03046257-7d056103f42dff83788a9e26a791a23a.npy +03467517-dab53ffe5ceafeb198e9e7d2e581bf6c.npy +02801938-9e4a936285f32194e1a03d0bf111d109.npy +04379243-254bf8d40be1fcb025a517a55e2a2141.npy +03001627-9ea39b8f5a9b88d56eb9b08c8a74d159.npy +03691459-460f07680e1d50866f6dffbb7673354d.npy +03001627-1a6f615e8b1b5ae4dbbc9440457e303e.npy +03046257-ad41efed0f69060fa86b76551c6a3b2b.npy +03046257-44930d69dfc35c71f5b59380f08b08f0.npy +03691459-8c919e992db7cb081e5b68ee10358ea3.npy +03636649-b96c8cc6529167bfcb8d8c6d4df8143.npy +03636649-9d9ade887a3fcfee89d70669fd6a0e5a.npy +04090263-4081d740a9bbdc7eb5e784742c8f0ee.npy +02871439-b2f525e82668cca251aad687ca458e7d.npy +04530566-e23e4845d3a990d25fc186cfb5f359d1.npy +04256520-7fe0602271e7b31f52db1d2b4104f173.npy +03928116-14755c2ee8e693aba508f621166382b0.npy +03636649-7691ae0488f3be56f92cb63577c2f16d.npy +04090263-cba7b6437ab3621ef0fea2ee98610322.npy +04379243-5767cd2fa0c64c92a0263d691f98a9af.npy +03211117-73895e2bed7007fb2df5ba101cd14a11.npy +02828884-88134efda194f8f422f9a913dd25c68a.npy +03948459-1dcdbb1ee028412253630d3fa9f23590.npy +02958343-b57bdd19852e0084f7a5eccf728c3b75.npy +04379243-5153292b91b93dc772ee08e78374a212.npy +02691156-bc58ff3369054fa68f52dc705c3109b9.npy +04379243-d43d8df70f357bcb83776366d314ddd7.npy +04379243-575e42b02249f2b3b87a068961a20739.npy +04379243-339092b2aeffea998629cea277916e93.npy +03046257-ad385337f0737d9df546596ce7364503.npy +04256520-b146fb259f64cefaeb6c29873b08c02.npy +03636649-c8b19dd635c346a4bfe7d977deb71340.npy +03337140-eb572820ef16a7bf389e94c9d197b196.npy +03211117-5664e1d072c3f39dc39fc02d4c9e2419.npy +03691459-ab651261126de20c145adb610a878e88.npy +03211117-eb75ac8723230375d465c64f5322e86.npy +04090263-58f98b4bc889c7f580b72a37a25b7e72.npy +04256520-e1a653600512eaccc862eec8232fff1e.npy +03991062-23d866397feee7a4a2c59a4d90e63212.npy +03928116-b2203c3500e0040a1baefda9f87f2d8c.npy +03759954-dba3e5a0273880c8773583ede7320303.npy +04256520-fce0bff765d0c49777ccdc3441fdc624.npy +04379243-5b9a7b7952996844d802aa676be38da2.npy +03001627-b4ff370c931ce57d1705b902738021f.npy +02958343-f91d1032b7cfae618e4e882feb9b406a.npy +02691156-5ac0cd21410b2a6a341877ff7a6c751f.npy +02933112-d5fc42532aac8ea8ad046fea8c3e99d0.npy +03948459-19e45672a3109f18be4927dbd39f74e9.npy +02958343-2dd397a57b35e57f2c6000457712c234.npy +04379243-2e3ff4aad6da120784a05e54516915de.npy +04090263-a2f3ad5b5e88482c30ae0c71c8e3e486.npy +04379243-608f7cd5e647e4a4e8258fa1af480210.npy +02691156-1930a979c7a9a2d662b600da24e0965.npy +02828884-cbf9773bfebd4321cb2a965e75be701c.npy +04468005-7d337d1be2d02b624e38abcf1c844caf.npy +04379243-a9dcc147e83c2a0619fb4103277a6b93.npy +03001627-20310d1bd22d8e28890eb7072fc1df21.npy +04256520-15410f94aefb4982ded10515704c9720.npy +02992529-fc1675526d043e81a2811061ff7e0824.npy +02924116-c970097584110627b012af5689af8c1e.npy +03467517-75b204a6aadb6702d3193ed047bef161.npy +04090263-fc1cd79a8643fe66def607f4d4140edc.npy +03001627-90eea7c7aa913fac57b8f616df7adf9a.npy +02843684-9fe2e8fb0e94a179b9e8bdc9c4a49aa2.npy +02691156-cc60baa1a796f5c14c3a35cee92bb95b.npy +02691156-f2f6684e930651df3dffb45955223d25.npy +03001627-108b9cb292fd811cf51f77a6d7299806.npy +02871439-28570547091748edc2cd59b38b35eb54.npy +02828884-55c97131574186c0d4d8765e3910f617.npy +04256520-6f27ca8835f0d0b54b3c42e318f3affc.npy +03001627-d76ec8373d0a8f0dbb44d2e3e3af4857.npy +04379243-4b2222cc86f2324f7383fb84b914b75f.npy +04379243-746f953a49a68cc2b76e29c9c43bc7aa.npy +04379243-de1d6e1294552606a625499f7117f27c.npy +02954340-357c2a333ffefc3e90f80ab08ae6ce2.npy +04379243-ef56ffb992754ef9efd9e6e4dec9682d.npy +02958343-4c36e3b0210fb9e899232e04f9a28249.npy +02958343-7a756a1c54cd3a5a1b3611fc576bceff.npy +04379243-242b7dde571b99bd3002761e7a3ba3bd.npy +04256520-13de905fd21e501567a4cd2863eb1ca.npy +04530566-1c89943a24952d1737f4612124cea14f.npy +02933112-6bd87f32df22ffe2854a6619c08bff6d.npy +03001627-341ecb71545d84835ecd29875b6f0d44.npy +04090263-3eb4bf4ca864e428ce168de955fd5025.npy +03636649-d82a17b1f646e95dfcb8d8c6d4df8143.npy +03001627-2a2d705d0238396488422a4c20c0b1e6.npy +02933112-21d4a168aa6fd6c74da5feafe6f1c8fc.npy +02958343-b6abe0f00fd452fa4101e38beb790a92.npy +04401088-21056b8560bdd1a9f63375fea17cbfe4.npy +02876657-92472817f72dd619467ca2ad6571afff.npy +03001627-e40d5fac8951692e3849910c5019154.npy +03001627-3b2710b509c3df0ea5e8cf3aa1686d66.npy +04379243-48600b28f63e0dd2de98d10ab5975b59.npy +04256520-1e887a97e283f6dc4b3c42e318f3affc.npy +04090263-a4509077129f900932dee48b245ce100.npy +03001627-fead8d07aa53de5871c3cf047830ec1f.npy +04530566-834dead664b43efb1ca19e5e5c1d5766.npy +04401088-4b72058b03234d188a81847056b4708.npy +02828884-be2bcc5a5ddedefa80065a186bd67f86.npy +03991062-3000b6de1c5ecbdca2c59a4d90e63212.npy +02958343-b09f4d5af99be6c5f5f45e906b41d1f0.npy +03211117-1a92ca1592aefb2f9531a714ad5bf7d5.npy +03001627-e80ade8966a54fe419fb4103277a6b93.npy +04090263-897656f468deb1b9e96eacf8990e6676.npy +02828884-91e169ea3ceb587beff42b9e13c388bc.npy +04379243-9ce40bd942c332644ee9d52ff0ec4dcc.npy +04090263-520ebb92353e7fae6f21883e4b04581e.npy +03991062-5488022c54116756a2c59a4d90e63212.npy +02958343-49e8bd4cf55ea566d97f019cb91636fd.npy +02691156-51ebcde47b4c29d81a62197a72f89474.npy +04256520-a3c1bd440f319a39dd7092ed47061a36.npy +03593526-151a80ff1ad2fe11c8c4893204f16cf.npy +02691156-95a6c003f5bd8a4acef4e20384a35136.npy +02933112-df55c6665781293cbe53b3b9f1274310.npy +03593526-be28bf161b022a1c178bbb7623060b16.npy +03001627-969375970515e5f6492d9da2668ec34c.npy +02992529-878135eab6ae9aa181471a5ba59fd0fa.npy +04379243-7b3dfbd70333485d219a1300d9489f4e.npy +04379243-dce2d814513f5035bfe64eef3e5b93b8.npy +02958343-f4814bc5063ee3a95f0ad3f281ff385b.npy +04530566-7380c6bedbd13059eb2c303a0e0d287b.npy +02958343-fda43d663587c7a9caf180c847b8b75.npy +04530566-e50e4b01588116c69eadbed0f2d15378.npy +04401088-6bd7f7a17a7bbd2d68acf22a03600648.npy +03636649-e4d491fdfd795a9339de811989288fab.npy +04256520-89b66c5a15e9c00b9b43c20267c98bff.npy +04256520-fe56059777b240bb833c6c72c4b62a4d.npy +02871439-d5064a4f00528425e89ebcecd11a393b.npy +04379243-c0eda75ff5b23100a6536c847a708e24.npy +04379243-179841c6d26cada5d75fa3d7e144089a.npy +02958343-80b5df2ecf1051fd61c6c61410fc904b.npy +02924116-9525a66bc137613399ebcb8df4d39cff.npy +03001627-3374905da20ad76f3c9c1464e55d580.npy +02933112-5366e82cfca7382729f1ce9399524695.npy +03624134-96eec3afdff1ceb0d7d3985b6fde9645.npy +03636649-e688f147080f123828eb8d149efa4062.npy +02828884-1b6a5fc808388138cb2a965e75be701c.npy +03001627-45833f137eb7b1fb77591d1bf8931b62.npy +03046257-b4777d47dec08048fd0c7dcabf865c9f.npy +04379243-4c907aab76195556d728db1e986e0b74.npy +04256520-f846fb7af63a5e838eec9023c5b97e00.npy +03001627-fd244782842c611b6443e5551f9d3958.npy +04256520-f8a6cb92786bbafce8f8c11a24c52ebb.npy +03636649-6bf0f3417f775d2c2cd2160e449d45ae.npy +03991062-a3cc533ab668af4ec0708f7bc962e512.npy +04090263-471f57562c00a5c7bb6581a048a6fb18.npy +03691459-ea95cdbe8f4114107354c46aadb2b2fd.npy +03642806-ab9321d89df4d58e78c854de246ffde1.npy +02933112-89ddbdf6366df2a93c2e50348f23d3d.npy +04379243-53bc187c97cc02adda5d247a475c516d.npy +02958343-dca8ed788347b28c171cf359a50c99bc.npy +04379243-d5c3aa73e043303b7ff6ace05b36a5.npy +03001627-7293291b3fe8233fdef1c01cbd4ae0c.npy +04090263-68cf8f5e1bfb9ff8e71e857afa9df271.npy +03001627-22086876a4f3bba0504721639e19f609.npy +03001627-265c564e26071961e27790b0ec8671f7.npy +03636649-aa6cdecffb9d4e403ec7ad443e0ae81e.npy +03001627-bc743137d2070eb1f51f77a6d7299806.npy +02691156-718b6f112f70146c62b600da24e0965.npy +02691156-f1a4a370f9e50890686c25eb09ee7de5.npy +03691459-ff8251d486de70545272b3489d12484f.npy +03211117-e2e40536be6daf7615000ab5e56184f5.npy +02828884-9bd9483c8eeeb703cb2a965e75be701c.npy +04379243-1a1223b411a9cf92e7c7920f6a65a54d.npy +02691156-db4079b8c7d3d674ca8607f540cc62ba.npy +03691459-1f6b0aa7568e70675c91d2edd70c353.npy +03001627-46c7367eede2d9c5ca2ed12df13a916a.npy +03001627-e8c1417f4eec96d228a7992bee4d8cde.npy +02871439-a3bfe9cd86ae43ff36ea1eb6542fe7e.npy +03211117-631ebdea5af51e499399ee63318a21b.npy +03211117-2cfbaf480d94552c43c8f1cd479ffb1e.npy +02958343-330a8f1243e7bf8b2ca8bf2993ca245b.npy +04379243-df03ded86df8fbd2ebd284456950c944.npy +04090263-3bdae6ac0efbaadb49a3c1009fa79820.npy +04379243-2555c9df5fa919692250bf58700b4d8f.npy +04090263-e69cc1d337df7c83cc34b900bb2492e.npy +03001627-2a75b2bb82d7f77c3f9d6e0ade5188b0.npy +03991062-129f9498c8f842b837ab51e1f8240a33.npy +02946921-2eeefdfc9b70b89eeb153e9a37e99fa5.npy +03001627-43e74f15a986eb626a90f735365ac29e.npy +04090263-6b14119033dccaa5d735fa1ab17311ec.npy +03636649-f7627b6ebf92fca6d3f6d823f04dd65.npy +04379243-9bcd5f77b6eb92ec415434d4384bb66e.npy +04256520-a6cfaf6913d9559b7e66b3e5c11f24d4.npy +04401088-d7b2a9546b6f68bfd0659574aaccef0b.npy +04379243-932079d89ba2e7ead16260d4d73b56.npy +03691459-bdfa20e11d204ecd35cd53a06b1d2317.npy +03337140-4106f81820af1541ffe3432ba4f2e6d3.npy +03001627-3dc39c34c37860da2ef1c225dc7772c5.npy +04379243-5f62b83cebad8dd1473f10e6caaeca56.npy +04379243-88789f9c90fd644550c5faea6c3af4f8.npy +04401088-aaf1159cdc4e6ce5b2ff1d6fc3caddc1.npy +04379243-832607835e99761c276b6f6d90ee3a83.npy +04530566-c89c8eca488d5072cdd34f38f87d26cf.npy +02942699-f7e2afd70e37f60ad2b6f4e920e50f96.npy +04401088-c3ded7599240c96f8bbff91b1135bb3c.npy +03001627-432ed2387d4982a635836c728d324152.npy +02808440-fd415d5823bea51f44221bef0fa3c36b.npy +04379243-9fecccf2e75e7c8e1099144def22d76.npy +04379243-b1a5b2caa2b7dc95f51f77a6d7299806.npy +03211117-c4e4d46434173023ddc138ff009971cc.npy +02958343-38f9aa4c68327bec760191d847b7480.npy +02691156-4def53f149137451b0009f08a96f38a9.npy +04530566-d795b03f47dc7cd5525c5b030c9fa146.npy +03001627-c54a464d63efcab2c389b3ea958c8248.npy +02958343-ed799c077fdf7dc47e5246097b57ccd.npy +04379243-64e572ed8f8f23bb815b2b467e8e2eac.npy +04090263-aeba4ad00dae0c78c79f92df566f8c6b.npy +03642806-195e2a65e5396271bc7eb7ec22211551.npy +02808440-27e0851e99c4d04470374408dad00379.npy +03001627-8ef2169d274aa2e9b16dca03855925bc.npy +02871439-5e60b8632d1d2c665dd0ef7a12d95543.npy +03624134-24c6c5c56fe9bd3c37b23f392db50c63.npy +04530566-a51410ca51a40c2529412f6cb23454eb.npy +04256520-ce99ea72f222e7d58bf939d21e50c410.npy +02691156-5793a442744f4bcf7af203abeca5ce86.npy +04090263-49e4708854f762ae9c27f9a5387b5fc.npy +02828884-b51ae78137662b05d2b12aa6a0f050b3.npy +02958343-4bb89ac11d478c0a71fc473170b0a51b.npy +04401088-ad0af9e3dc8473296841a8d53aa30506.npy +04225987-cf04a6f4312be2c0d6f39b72607d85d7.npy +04379243-e696a670af11d5431234386b1304ec62.npy +03261776-20e16ae7c65d81269c1db271ad9472a7.npy +03636649-70e29a12260f811d8f1b70ceeb5e9a89.npy +02691156-e380f6fa720e1c15560a4691498bd2fc.npy +04379243-bb794c54a628a3db6ff454af1e8947f3.npy +03642806-68adcb59ad19c431676394b063daab40.npy +02691156-aea5192a4a7bda94d33646b0990bb4a.npy +04004475-2b1e3a43701dd4c31f49b1a1e04897b9.npy +04379243-e501ac06884534b5d5f962f170e40e8e.npy +02933112-688102337377c19d1d860ee2ad2a42e1.npy +03001627-901cab3f56c74894d7f7a4c4609b0913.npy +04090263-604d962eb17dfd5166c0c88d96ba938f.npy +02958343-decdf28e46edc632bda733a39f84326d.npy +04379243-c45633a0a85fb4d0631c3671ad15929d.npy +03207941-b1080bd937b04a44575f4e5007488531.npy +03001627-1a38407b3036795d19fb4103277a6b93.npy +02958343-fb8adbcf67d858fc28044fe9244db50a.npy +02691156-6fdf55a7ca1e64ff7d7b38cb4a2969ae.npy +03636649-7869e39e4fcaa1b7ab26a588d1ab0ca4.npy +02933112-8a3f6cd19f3f92fe7242f2b1500945dd.npy +03642806-6b78948484df58cdc664c3d4e2d59341.npy +04379243-76338ed3326689b249524cfd5973a145.npy +04379243-a16a6d438d57667bd3299846d5c00f08.npy +02880940-a98b76254bcd32c05481b689f582aa44.npy +03636649-a4c0f3aed58f0e092fdae21c212bf119.npy +03001627-1cc3513e4d81516267510d684b7bfd11.npy +04379243-914293e9cb32a51c880e543f747aeae.npy +02691156-4cbca5f95cd6cbc6e59552931a2cfd3c.npy +02828884-49eda923afb7fd21456cbf78e1e89022.npy +02876657-da2703e6d87a28e75887f1f81e7530ec.npy +04530566-bf5112a856a8f6a3819d76d0172b8abf.npy +04530566-4140a889b730d00cc613c8345c33a85a.npy +02933112-77342f11ba666144d71237b3923fc09.npy +04379243-57dbdc49bd549a508d1542df8403619f.npy +03001627-6b9149d69d3140da258ce5fdea186c4d.npy +02691156-cf71f5442c4120db37678474be485ca.npy +02958343-515492715a04d8756a2345809e2bb169.npy +04379243-3c04f4e0d183976a7e7cb173e141227.npy +03001627-3e72bf47e31aa669f4b6538438a0b930.npy +02933112-80a3b5b036021b8e404dc8be84d677e3.npy +04554684-bb609567ff4d46a0a44768a940557d1c.npy +04379243-33b081062b2195e71771ee930e861b13.npy +04401088-5828a8259ba570bbd24e3068806a8c67.npy +04530566-5e8ce498a93fb7eae1a9c234926c21e2.npy +03211117-6bc1a795d199d952f97ef3b999ddb957.npy +04379243-26305aa1754510f79b3e1be3524f72f.npy +03691459-9f90d7bf89231ba94f5aa6ea4540caa.npy +04099429-5a7f14f4b25dd99ceae5cab1248d1ec6.npy +03211117-b08085c7aad830e3f45db6a75d78cb47.npy +04530566-92f08b4bd8aed9bedc2616ac929c8116.npy +04379243-a4f302ce157687e0861ac00f334ea98c.npy +03325088-a06f174eba7c6553b362845c6edb57fc.npy +04256520-a3a22ad51e59d79a2fe54017cbc6c7d7.npy +03691459-d69d5cf7868651effd28950562697757.npy +04090263-d03854e6d6c6eaa19be81fcc2b07ba08.npy +02747177-ef22cb2b0800568f63b2acb037dfbcde.npy +03046257-8883b1a1a421a178ddd3f1aa46ac1f89.npy +04530566-efa50c4e3e691d3bda1b3e013aeb1e59.npy +03636649-49d9e5b7560eaa89819e369e3c49bff.npy +02828884-b58a0307a86959bd564f6f5de611dfed.npy +04530566-ca3d2f904f53f945d02db4eaa8d7ba76.npy +04379243-ef575c402b734f8d810b14a81e12eca.npy +03797390-4f9f31db3c3873692a6f53dd95fd4468.npy +03001627-131edf0948b60ee6372c8cd7d07d8ddc.npy +04379243-627b977736bac8b0a1f97bf2d7a10a96.npy +02808440-c534e117a4fcebf67843fb4efdc19510.npy +04379243-50f52f9ce377596fc955e5ed03ef3a2f.npy +02808440-95b7632f605a0223321831d2245cf06.npy +02933112-9f17f45a28d063e7391e4d6c585a697a.npy +03001627-52469c47362e41e719fb4103277a6b93.npy +03001627-3f60205b1eef5555a4bf007e7299d9cb.npy +03001627-60e36f3ad1dad5cf71f761119ebf0b45.npy +03001627-3f55885c27d84e5951ae1a6e89264401.npy +02924116-65af4e2e5f2e31431e797b014c500fad.npy +02691156-2e3c317357ecb038543941eaaf04581f.npy +02933112-24b3f8b6bf4a9a7391a3d45e8887248a.npy +03001627-325bf2aee84a1fcdfebad4f49b26ec52.npy +04090263-58f7db3c6be48a83537e3f6cd50ed63c.npy +03636649-9802abad61f4ea7c37c99625b0c170be.npy +03636649-7260ad08488a3156f78e32cea3be35af.npy +02691156-78646117554e23162c00431da4ecd526.npy +04256520-39a79339b49d7cfbc16a7f7cb5642902.npy +03624134-ba31cc5e739da65b8295dee32711a98b.npy +02691156-b6da5542f0a81fb5aae46a5cc955c766.npy +02871439-5b794f8cee0075b53e96e486ca7cfab0.npy +03467517-41262de6af84aa8b57e59dddfaae7826.npy +04090263-64e5444076a4f4f53d69fb2c36f9ef2f.npy +02924116-de287261fce4d8df114c8eea6eb81d0d.npy +04256520-7b2ee63737854db3bd16d4490a10a752.npy +02958343-5c8f71dcfe980f714f3a54559bf4cbcb.npy +04379243-2e666b458f1641f248cb96c78f6ddc11.npy +02691156-49f400e6574c75554c3a35cee92bb95b.npy +02691156-b0b164107a27986961f6e1cef6b8e434.npy +04256520-65ec93f47687b6b4926f354063916d1d.npy +04401088-7a458ea841e4e67a11ee7ca4f000feba.npy +04256520-ed394e35b999f69edb039d8689a74349.npy +04379243-a4fcd8afe8b6de585beaf00da5b709c2.npy +04379243-8b7175b6c74385ac87187471eb78d702.npy +02691156-cf310fe73705eb85a099666f6cac75b0.npy +02933112-d2dc852235fe39ca1112a51947cf2b61.npy +02958343-b7f957411c3353432fedd0aa3d156746.npy +04090263-e9fd75b68e06c18cb056c98b2e5e5e4e.npy +03001627-f4db2e2e90e83c759b9f2eb77f5e247e.npy +03001627-bfb93705c05ecd0d31e7ccd4db190c0d.npy +04090263-36e0d91630f7c958d4ca42bc1bef451.npy +04401088-453c590f0a1b37c1e0c2427da07ca8c6.npy +03691459-78d16c052215997b925c6624a25951b5.npy +03001627-92242be674537e3df6e4c3538272fb27.npy +04330267-3c7cb5ba87684ffaf5f4f288fb912362.npy +04256520-9d77156d64599e9b1206ff076758ec85.npy +04256520-de5ac6717fb307e6b01c58badc8bbc39.npy +04379243-9e0284056aed2a097543d7dbfecfffbe.npy +03046257-10ce229d913c23d56b08f078360ade39.npy +02958343-fea2f9ae1e25b74c12f962c15d41de4d.npy +03325088-f0d703dcfae9e2aaf38c4a12750d961b.npy +02958343-3c310afdf363201cefe5f291bc2f5fd0.npy +03001627-894f033f10abba014038d588fd1342f.npy +02992529-e8db0c85b07ac581d409d3400adf2d96.npy +02924116-4d2d4e26349be1f3be2cbcda9b6dc9b2.npy +03001627-ff3a6eb4556b2c0eb04cb542e2c50eb4.npy +04379243-ae5b18b3515c84ee39683a06407f7f3.npy +04099429-b3956a68fc4a62ed861cd78a675a5737.npy +03001627-cce9ffdcc7ca8ddea300840c9d7bfa74.npy +03211117-3cbe9bb95e5004eb342398ca9dc32672.npy +03046257-81dd20fc58ca6855c0c2cc2dfa2c0319.npy +03001627-3037c7d4d9dcb8f535b063aa516d32d0.npy +04379243-30e0f3d959b16c64473f10e6caaeca56.npy +03337140-2fc468b98c0cd227c8830fa1ef6e3e71.npy +02828884-ed9e22eeb11ee9669fc351f487d31208.npy +04090263-79e07478f6a0a2305ee5dde2964c294c.npy +02992529-25e03c305f41c5dd226bc3b9ce9ff2a1.npy +02691156-29f514bdcf72e779bbf3143b1cb6076a.npy +04379243-d826ce80b06bec855e5dde99dbb2920.npy +02691156-8e50f707e506f65f66cf1b4a8fc3914e.npy +04090263-b3ae08dad4ceb33c16b34c3751bc447d.npy +04330267-9aaca16b41037ccdb4522b651100b435.npy +02691156-313758cb2eacbb576d3e60add9f0d715.npy +03636649-a82af4e7e81334f8876b399a99a15c0f.npy +02747177-36d4caf867e0afcd56f6fc4b4ce1db04.npy +04256520-42486ef061ba8d2e9deec47d8412ee.npy +04256520-8568498cce4c2441ebc1a7ae7c4c250d.npy +02958343-56e0fef0632aed0f1d27be7764701cfe.npy +03001627-b09e3b329eb11c7dae659483f300cdd5.npy +04530566-5059b4e973a0fc7f928a2a26ac296b52.npy +04379243-c177762c0445d57ab20aa91e9e90c311.npy +03046257-f4877fa753aa6f515445e46058840642.npy +03325088-f095f7f95edff9ae54d7082b34825ef0.npy +04256520-11a47d5cdd42a5104b3c42e318f3affc.npy +02958343-3045cc22be31372859139efcde1fedcb.npy +04379243-325d922d3092f7bfc3bd24f986301745.npy +02933112-ab072b1506cbfd921b7554913e3d38e6.npy +03001627-ba40e15e28eeaabb9fad3726e97eca06.npy +04530566-b270ca5a6051053d88e2183678696c9a.npy +02942699-d680d61f934eaa163b211460f022e3d9.npy +04530566-3efda6b0c4e70f7decdcd70d755bfc70.npy +02933112-b6ec38384c0904a666023b6076341c23.npy +03593526-1dee9988a1ece53e4b3c42e318f3affc.npy +04379243-293f2e28d5570bfeaff8240d22dfd73.npy +02942699-87b8cec4d55b5f2d75d556067d060edf.npy +02828884-68df3d5c8ef4cb307cd7dbf0f3d6d9cc.npy +03691459-9a017f96829a34a2b17f090763e2921e.npy +04225987-f74a5dfc0094e2d5561dce3fe08634b7.npy +03948459-35b5b01801304bd9faea005b8f19889.npy +03642806-51be62d456a272fe96a7d658c4b5ee82.npy +02808440-f356aa82f68fe7d9adbcc9ee28cee4cb.npy +03211117-d4d8dd7053596249bc1905b3bc668597.npy +03790512-485a6b42bc4f7e59d373c34785838ee4.npy +04379243-348b2880842cbbca4ca84d60642ec7e8.npy +04256520-2f87e4958b3c1d80b5da5256e41fa569.npy +03691459-b0ba01e0a7f3553897950841baebd2bd.npy +04379243-276d614d42ecfd1490ad276cd2af3a4.npy +04379243-67eaa2b16399f3e88809fffd0cefbf72.npy +04379243-e448e3e40395d4d679414e04132a8bef.npy +03207941-fa01ff7f1d217850df3a1b0d597ce76e.npy +02933112-995a40846929e9753da27ece6ae88fff.npy +03948459-425abc480a0b390d7cc46b39c0cc084b.npy +02933112-dfa0bf0f2b48ea33e3a031805ace4a99.npy +04379243-3e504f94b63c77c34b3c42e318f3affc.npy +02747177-c5d49f41924ce872b7a97a3c2b004475.npy +02933112-c66e77615d80399466e506c113d5d05e.npy +03636649-412cac2afa6299c3f42a90fe4baf4591.npy +04256520-3aebadcd37bd3edd8f5ae2c97614087a.npy +04401088-74314be9ad38b02171eade9e9bdd0f45.npy +04379243-99ebb9278165f04f72559100997b742e.npy +03001627-22b287d232fd062bf51f77a6d7299806.npy +04090263-6a7244726ee48fc560238d65d99cb6ca.npy +02958343-c41580019d43348d3a3afd30f2e86bd7.npy +02958343-a2f658d639f46d95c6d2c2010c35d0b9.npy +02691156-daeb27ada93505b1e24e4b657f0a298.npy +04554684-1ba5e13255aa9d4840b559ef47048b86.npy +02958343-53507d1d09b3c2671cd97374110efb0a.npy +04468005-cb800fda25e740bf9f97ca916781e800.npy +04379243-1ae9db7da9a6bd449453695c10a417d6.npy +02691156-4d0898c7cac1199a4b0853084d4042f7.npy +03001627-8ade0afeb517ce00aab45a6fe87e3c10.npy +03001627-7e81b5f79e6899cea570c6c691c987a8.npy +02691156-ccf4e9c074c3395c26360e1e29a956c7.npy +03691459-bc522596f5da2ecda32913968eae7f30.npy +02747177-99cf791f4725be642ad490d4d7fae486.npy +02818832-9c203361eac308754b8a0e1f781de28e.npy +03691459-7b7d7bc551ca91b3a03d35fe89e56e4c.npy +04256520-d01ce0f02e25fc2b42e1bb4fe264125f.npy +04379243-2425d3befad0440febad4f49b26ec52.npy +03691459-b0f209faa41b8f0879da6431b0766445.npy +03001627-eeaac38269e8f591e55fdfa049133df8.npy +03636649-927e0654427c4d0b82241d99b4e87f38.npy +04379243-22c2431d6be8a3a8d6983f351200ac6a.npy +04256520-ccb08f869edde5e6d8adf1ca87495d41.npy +04090263-c414225a3a0fd0211513ff7357dae269.npy +04379243-f52e52094d8240b2dcfcef693e7ec696.npy +03691459-68bbfac3232f153c6ecea800f06e81d.npy +03001627-9ee5eb90d1176e2547dcda54be6a23ae.npy +02691156-3921f5f454c5733e96e161ce7a956a8.npy +03001627-eb8d2003087a27cf63e9f3319eb5ebb.npy +03001627-715530026c6459873e8366d7fa2c218f.npy +03001627-5a30a8edad307d8b04cb542e2c50eb4.npy +02958343-6f1c766eeafc7740e5424e4e99c9576.npy +04379243-279351131d06222cbe9bca6d7b2e5b3.npy +04256520-c8b49063b5c805ff62a510b8f97c658e.npy +04530566-d350936cad33863bf2ad837508eb2db7.npy +02691156-99c13d3c3f30c34dca8607f540cc62ba.npy +02871439-a976a61f71a8e700876ba2153f34d1b9.npy +04379243-bd9257f538038fac2d9fe390e23fd20f.npy +03636649-f29a94f969dd55ffc35131da26f8061a.npy +02691156-12991e9529a2b2bf9ac9930d2147598f.npy +02801938-97c3dff51452522814513156cf2b8d0d.npy +03001627-78f722590b0885a61efc6aa41666df08.npy +03001627-6c7a07030e673b0b9c9eed7651b77d0f.npy +04074963-240456647fbca47396d8609ec76a915b.npy +03691459-5a943e38dc477bac4310636931b68fdb.npy +04379243-b0d1fc9676e551849e25afd4f06934a3.npy +04379243-db8756b02359c6553f28718dab796f68.npy +03642806-894e47a6adb76680d4eb7e68e898dc44.npy +03467517-e90e8c13288718055216163257dea99c.npy +04225987-ea25b5f1fc8d76a36a1b26eff73443ff.npy +02691156-fb110c5d01f1b3fc59dcf12563d8fce3.npy +04090263-7c426a52358e8c1d64c4db7c3b428292.npy +03211117-a1e844489abee455972d35c68e1bdca3.npy +02808440-3b59f9cff3d39a0b602ced3945939e8e.npy +03691459-4014de6b20178cb92633ff66beb9cf31.npy +03001627-fbf085824e25d7c440ef1c8b63a628f9.npy +03325088-63268b9a020fdb0e2f0f992e258eb5f2.npy +02933112-29dcadb19ddb448ad98e761e6d91dfc8.npy +03691459-8edca4e07dee64e0a08ef684995f5adb.npy +03001627-c435de7be7f5bcba65ba78ad9601cf1b.npy +04530566-ed397dd3d2ca4c8a69852296a4bb593c.npy +04256520-53ce13a6f6a1a5f9f15e23b99997e42b.npy +02691156-f2171bb2d715140c8b96ae1a0a8b84ec.npy +02933112-1a658b76afedb342490ad276cd2af3a4.npy +04379243-26a97ad8dd79eb1ad0c63a304a95442d.npy +02958343-293c7cf5fdde18258acb0ff76f4aec7d.npy +04379243-7bbf01c219dd51fd7d8864caa856253b.npy +04256520-7822a1ef8d1eca8af51f77a6d7299806.npy +03261776-301d3c7e7a8cd529c37e70ff83bcc2f.npy +03325088-80d6971df918758f871adc8ea82b7293.npy +04090263-62d97682c57a0a14758f3dd6623cbf27.npy +03211117-937190441ee0d2568b7ba679b8625927.npy +04256520-9bc53cf72e1b969deda761b10992452d.npy +04460130-d9b4d966b63ba5e12a83093ac1bb2d64.npy +04090263-b73a819d88bde44c24d00518a3dd6ec.npy +04379243-e77d26aa88ec531cc17e7f250c5222bd.npy +04379243-384dc1f8ec0a0cc2ce152ffe2d789882.npy +04379243-9052a28510a4240d49d36f5b69384ad6.npy +03001627-b239fa34b4cb5a8e9b75b6346baf0c12.npy +04379243-7da66ff46ecb79e52225858d7500e21.npy +04379243-831985fb385a5b2a9ae2d75b4fc35b7.npy +02691156-e028fd73515465da5e9e2656aff7dd5b.npy +03467517-d155056f08e7bb10ace273aa67d227c6.npy +04379243-67c246e981ece9aa9f0f464e9e8e09b4.npy +03001627-77ed9ca45b928542266f89139e159db9.npy +03636649-33caad3abdb4f5192d48ab934af26487.npy +03001627-78393a855f214f387fdfb54d66251309.npy +02992529-27c4bf6a96c6439a86a04ec9e4169973.npy +03001627-3bb2201ba3b8709523f4da4464aa0c0b.npy +03593526-8fb8d64e04e0be16a383bc0337fb2972.npy +02828884-ca6a1a938c160036a0f31147c37537e5.npy +04530566-35e1639eac2c9b96cfea3d4fc15719ea.npy +04379243-64fd4269b04f91ecc68c5db94fe444f4.npy +02924116-fb659ecfc831c9915b4eedf3392260a.npy +02691156-d405b9e5f942fed5efe5d5ae25ee424e.npy +02691156-9912e7eaab960bf0e3639a60ffa58b1e.npy +02691156-b3135ae5bad8cc23cbaac693398e53fa.npy +04379243-1b4bc147baf68d4ff008d8a3590fb522.npy +02828884-b6da9b2fefbad3d9693697d8506b1c6d.npy +03337140-5ff8f64baed1c8ea4c3aee8e9d3a6ffa.npy +04090263-64276d3a962f6093923f5cd444c75b1c.npy +02691156-150cdc45dabde04f7f29c61065b4dc5a.npy +02747177-fc7ba0ce66b9dfcff155d75bbf62b80.npy +04379243-21691795da12fdc7bc95db5d49def9cc.npy +03636649-d6c6665366854e6abec99d5b4657d5b1.npy +04460130-9b1903c94dc60e7e38cd8eb23853c009.npy +03001627-c0fa1417c0cf2f20593ebeeedbff73b.npy +03691459-a10f7be978f78f085e2bf91b698938de.npy +03001627-91b738d40201bf18a413908c0e169330.npy +03001627-ca9f1525342549878ad57b51c4441549.npy +04401088-901a0180abe1011b3c629b56d283e7b8.npy +03211117-7cff26e6dc84bd02c598d38a6a69ad2.npy +03636649-60272eb623298fd190a9ce3e4b15521e.npy +03001627-a6bdde9da1322bd5116162acefe23592.npy +02691156-dca7f88e151f196b8179909e06795c03.npy +03642806-b233163860361eda8cfacef5204026d6.npy +02808440-506a041b7ad271813321831d2245cf06.npy +04379243-bcceb065b8c433b99a87002a4eeaf610.npy +02691156-85743f17e13271e0709eb7790ef48e0c.npy +03001627-5d8736041ded1ac7de03ab2a27ba7531.npy +03513137-27e52dac4cafdfee2a04c68bc263be.npy +04379243-a1dabdb19c7e5bd1426cd1b7e837ebc6.npy +04379243-48efd13f8115e3cb855931d119219022.npy +04379243-67e32538a35a5011a0ab1d82ef09f78f.npy +04256520-8efa91e2f3e2eaf7bdc82a7932cd806.npy +04090263-30270408f4d258d2feaf99d0c6c9094.npy +02691156-1807d521bc2164cd8c4f5e741c2f9cdb.npy +02958343-aec393b8c73d3a8ae4bee94a37836d67.npy +02958343-48debbfd63725a743978555bf44cfc9a.npy +02828884-11e98db089a66426ad5067eac75a07f7.npy +03001627-588ca1d34f93eddd8ee30571b0da74e4.npy +03691459-8675e32f2e122ea5c13bcab6e4ecd7e4.npy +03001627-5fe6b79e75130974e8f8c11a24c52ebb.npy +03001627-3823798ca4fe0b439710e093c764abec.npy +02801938-87b731ecd900e291c763c9d0f7bd78f1.npy +04379243-57de7158b2547dbaf2a235c3708accb7.npy +02958343-e738466fb6cc90530714334794526d4.npy +04379243-c1c52930adc815564810cc21086da42.npy +04379243-7d14ae7d0b7338bda0ab1d82ef09f78f.npy +04379243-a7ab34edcd45d7573da27ece6ae88fff.npy +04379243-7e261e5b2b11cddc557e22af3c71c6c.npy +03001627-f439a2db6341cd85f2b931201029bc76.npy +02691156-33d955301966e4215ebedace13b486c4.npy +02958343-63316c4cff51de417fb21fb4ec0d8d1b.npy +04379243-17d336aa38bb77fab1b6b0c5ddacb607.npy +02691156-4100df683795dfa1f95dfd5eb5f06d19.npy +03636649-d5e278feb6007ccb88e7662971dc736f.npy +03001627-8bb332c5afe67f8d917b96045c9b6dea.npy +02828884-ea4740ede10b7620c09352f205bd9134.npy +04401088-f2db6829e0c0298140d50eb4da376b1d.npy +04379243-745a2b060d0f692bf4b6538438a0b930.npy +03991062-b2e03341b4648a3d63b2acb037dfbcde.npy +04099429-3c43ddee5e1d4723db652c825617e3be.npy +03761084-255a0ce59720bf24a53276bbe109327a.npy +04256520-b10ae372f7988e3bc242632b2a8c3129.npy +02958343-bb7fec347b2b57498747b160cf027f1.npy +02828884-153116d4415ee016601104cd2d998272.npy +02828884-3d5cf677f2aa9ad978d4d2afb777f33b.npy +04401088-3ca1d72d2416bee6f4e9c7b80248eec1.npy +04256520-1db7c7411c5d957918f52c8a4cfcbe33.npy +04379243-6dd08b216592dec6a6797fa823fd42d2.npy +03325088-ad51249f5960d841c36fb70296e45483.npy +02691156-78c5137e361e02cb24624455c20aef91.npy +03211117-4ee8d3a617b574ee30582dab79e5c58d.npy +03691459-35196460460f022a105260687f2b18b7.npy +02828884-f2c542ed9750ee4668db2d7865d1f724.npy +02828884-ddb2c6abe41b2063ad5067eac75a07f7.npy +02876657-df4ec460683acbb89d789ef7917b7723.npy +04256520-6f6a4f12041ce6d2593ebeeedbff73b.npy +03001627-53fc74fb69742cab20768660cf080d12.npy +03211117-9da823886a808f7da8f1d83a370a51c0.npy +02691156-16d40e779903e77863b132896d8bc65d.npy +04379243-a1896691fe875eccb9968f25875bdef4.npy +04530566-bfe67a6080ff5bc17ac1d5790f13a22c.npy +04401088-df90c50a892611ca8536be73396b323e.npy +04401088-2c03ac9bbb3d918411f02c4c36ed7f25.npy +04379243-d1296da8d3a45ac88aaae3d020f5ddf8.npy +03211117-ed7d00e977de27e2bdfd4afbfb3ee4a.npy +04379243-872e9d0bc078b4c8b9a1f0848a4940cc.npy +02958343-e5ba98879f06d013b2d3f2371f6b0762.npy +03513137-51ee565cc330e131b20f6e48f6a30cbf.npy +02958343-c6191031c1d685d580360680c1602c7d.npy +04256520-cbe2e3145eea246cff40be78d008f276.npy +02958343-8f87755f22470873e6725f2a23469bfc.npy +04530566-a848decbfe26833c4a27b0b4657ac8b5.npy +02691156-eac2573ef637a0dbf31cac033b2c0831.npy +02924116-6885092b0d1fbb6a8db35146c0a9b3fb.npy +03001627-71eca23b5fc484cc59fe89a0706f1a71.npy +02691156-a762fe69269fc34b2625832ae05a7344.npy +02691156-ff28d340bf0b5d9387b2a887422ab97.npy +04256520-33f47039e62a39e5febad4f49b26ec52.npy +04090263-5a5f7025b960f4bc745f2f3a558dc3f8.npy +02691156-9052a53f45d5f8487d64cad20089f027.npy +04090263-c9b540abc1cc7a107d0c348381a9a6e4.npy +02691156-67dbb0de722cf5cd7a734abc5ba1db0f.npy +04401088-1f4e56064de606093e746e5f1700ce1a.npy +04379243-eeabc27816119ff429ae5ea47a8f21e0.npy +03636649-ea235afbbaa6fcccf32735686fcd8ec8.npy +03001627-6aa1ba85285feb756306d83fc23a955a.npy +04401088-9c26b9b0584920f1539baeab407f4a02.npy +03691459-b7285ba6fc6628a1a43ada367b02a4fb.npy +04401088-2df0bc8b46ad3cb858932236a22029d3.npy +04379243-94a53bc306d106708bc6f322a9608b07.npy +04379243-b67fc33298d026033e0a119fd0be5d3f.npy +04460130-fe5ca50ef83ab52438cd8eb23853c009.npy +03636649-414d4397dddc0134fcb8d8c6d4df8143.npy +02924116-6c0b2009e8496a1b6025f5d96fba4d9e.npy +03001627-f229c56eca8c0ecdc3bd24f986301745.npy +02691156-accb9ee4edf6af6ce4080dcedcbec993.npy +04379243-71115e3a391785be853acd6c98b3fb18.npy +04530566-af07125f24a17476eb2c303a0e0d287b.npy +02933112-7dac6c932ca4f2fbb1cbe768f98549bf.npy +03001627-78b7f3cb97da38c41471b11f88c7b46c.npy +04379243-d1cc46478cde981b9a980acf1a5058aa.npy +02958343-c721c1e89e68e01fec4be884ee173bab.npy +04379243-1b43b4892ab3a4612e85eab6bca44d5c.npy +04379243-968714b674baa3152cf0938654a53e55.npy +03636649-1b79210962721517fcddd74ee6c69025.npy +04379243-76c01c98aba64318fafec1d6d9ed06d.npy +04530566-38189a2101b5e6c3da32b7c218678a0d.npy +03001627-66e204998b6c4f06ffe5cbaf6252d67f.npy +04256520-f6f563d47fcdfe82d67386763ad34603.npy +03001627-d8d5829083c66bd4f4b6538438a0b930.npy +02691156-10e0a7255d279a419751c7a6f15617f4.npy +02958343-ae0058d9ae9bd33d51a95aaa6caba1d3.npy +03691459-e51ccf3bb4413ceb61775b840d882da9.npy +02808440-18a3dd79ce17724bfe52ffd0e748a1ab.npy +02691156-4ae3924f14d2c0084c3a35cee92bb95b.npy +02924116-b5b6404c3267e782f446f92b52bbd82a.npy +04530566-a230c555488ec2664b07b7d8c0d68c50.npy +03636649-b6989c99bba1226539b3360f500ac52a.npy +02933112-4392ad03e7d769a6180dd1b6c5060a26.npy +04530566-203c2cac2c46e06c320fa6e2cd857828.npy +04379243-f09cdde03794151a17be1b91fdcd9df.npy +04379243-b602636c7967016f7305052ff007b248.npy +03001627-fe99f16c2532cdd07ba99ad16fdc05cd.npy +04468005-a89aee8719ab69704da9f355ed79f620.npy +03691459-fba87f3cb973b06871bfdb4b1c2ed05e.npy +04379243-d62417059f78e8e79d2be74cfb51ade1.npy +03001627-b58a0307a86959bd564f6f5de611dfed.npy +03325088-a951f273c8dee77f96a7dbf21dc55841.npy +02801938-2ca614e0e17d4e93162da3dc7be329d5.npy +04256520-f20e7f4f41f323a04b3c42e318f3affc.npy +02828884-ec79d41034e8deabf4fb4dee5181bee.npy +02933112-7fadf6464f6ba381921dd903dd0b8b17.npy +04379243-7c29fac52d4a061140b4c5428883e585.npy +03001627-38c65f38e51df0746fd487bdb55ad0b9.npy +02992529-72e61015d1e4fcee8739b6dd0f9695f.npy +02691156-b3c7044fcd6f15c24b0a1bcf2fb497ec.npy +02958343-8b090b8ab3172dad2d7a27ffaafaaddb.npy +02958343-8efced0ecbd1dd99713391d1ea8d388.npy +02828884-756c2cbd2d42644052b192b5b7698446.npy +04379243-1bdb9df06d749be1a7146643e6b355e4.npy +03001627-668aa5d430fd6d4e8f7d9678498f2295.npy +04256520-7d804eb69e0eedba450447b3239e17e9.npy +04330267-9fde0df9146d61f119bea36737d5c9cb.npy +04530566-1b4268c4d812e54943bd01645155d3ee.npy +03928116-22ea33abd17d1a24c87275f53cae84a.npy +02773838-f72de241037d474e76bb31db0358e9c6.npy +04004475-bed705ad5e375edb5f8fbe378caeb270.npy +03001627-60637687ad5682ef2b93a65c5f642e3a.npy +02954340-1fd62459ef715e71617fb5e58b4b0232.npy +03467517-fc8cc32bfeaca537c39ad9186be3fec9.npy +03211117-66d6590ce707340f1c7075c2bc313334.npy +04256520-20b12dcbb70869c06b5c5023b0ce157e.npy +03691459-4d264fc57f6ea6bde389c9be84ff7ec.npy +04379243-2b9153514eb1c46bc6a830e27533d086.npy +03691459-36206fcd5fd8821996ee15847b17fe3b.npy +03001627-d5b132a3e903e8fc8ad3a7d07aac2767.npy +02691156-5aa22f8c52d2f777a80799ffaf21ea7d.npy +04090263-7744efae453f26c05e9263096a26104d.npy +02691156-4063fb031d8fb78e505ae8d422ba349d.npy +03046257-d9543e5f16e6574a8e9a0e51a554788d.npy +04379243-ab55372db393e4259ccce4c6d5bb195f.npy +04379243-d19c946f825a9786db6175ef18ad3f80.npy +04379243-88b227c5fb3906ce47c638c0eee4a2b3.npy +03001627-2ad0943e70c0bd1481f667e2a25e0619.npy +03636649-6faa72d18f52d7172cd2160e449d45ae.npy +03001627-9ef3323c6ced7dfef313a0fb5fd4d79.npy +02992529-77f5498dd2277aacfd71ce99fb45ba0c.npy +02954340-9bd54e0123d3cd70a52821bf1aa3b19a.npy +04379243-bbb11b745f7c75fdb5b101ae4c3e9377.npy +02808440-c473362142f5cbdd8dbde1890f8a76e.npy +04379243-9d71f9424fc659e17a50afc9c93f8a50.npy +02691156-94ce3a5ad2576e73a5cac89017eae8d1.npy +03790512-e30b8ae3e945d7f5a40fa6b4bae5e67d.npy +04256520-76a9d700dcc91a5fea4a3d2e6628d0f2.npy +03691459-2e40fbdc900e69593971c6f4f1d0a4a0.npy +02691156-b2ceeee3c5b75962ac4f72bf08dc79a6.npy +04379243-e0940f2229e42007d98e761e6d91dfc8.npy +02691156-cf911e274fb613fbbf3143b1cb6076a.npy +04256520-62e50e8b0d1e3207e047a3592e8436e5.npy +02933112-11b8fd945de0ee99642f6fb37a230b5e.npy +03001627-69e35c579a68fe146045fdc35419ee6c.npy +03938244-d534e22b823ad56f630771196b76eab9.npy +02828884-d21839a3d4b5b30f55f46d55537192b6.npy +04256520-24223e3bbba442ffd19c4e0cc3eb15dd.npy +03046257-2451f214bcfd8ed9f3a54fdb52b446ad.npy +04379243-8af3fd230ea7ac6518101790733ed6b2.npy +04379243-f7d727fce5ee3007984a3b60f45af7f.npy +02691156-fc0097a6ad81e5cc1c2daaaceea98731.npy +02933112-acd46f0b09a84c226b987ec2db2ce6b1.npy +03636649-852feb3fca95b6d5dc3653f8341633a.npy +04090263-1f01ba0f7e0948f56108ae6b1ec0f04e.npy +04256520-d9d61f08002dfae421cfc6e95839d798.npy +03636649-8c410dce9de0c632ecb14096838a20c5.npy +03593526-ce2508ec4476b2cbf51f77a6d7299806.npy +04379243-7c770e38383d59be279e896561802d26.npy +03211117-c08e59a3d09cbabf6002a1da9aad9f4f.npy +02691156-fd67c89ff247f9e7442ed26ceeb35a60.npy +03691459-ee962ab0dbd24bcef78c4384b551bb5e.npy +02958343-e2a4635c392e750abecf71e2e014ff6f.npy +04256520-cc644fad0b76a441d84c7dc40ac6d743.npy +04401088-18cb51f36acfe30a487d18402ebe69d5.npy +04256520-1589b8a09c8bd67551d07d3e9ad67a2.npy +03624134-581ad58ce8664d2d4ff0e6230d32c1e3.npy +03001627-9b42da9217caaed8f51fa0238791f5dc.npy +02691156-97ec5b82d9757b639cb1b92881e8e76.npy +02933112-56031b004d5306954da5feafe6f1c8fc.npy +04379243-4a41fa511183aa138cbb8bac2032149c.npy +03928116-b36576fa2483c97a3c81f7197f981187.npy +04379243-f1324b15b7cc9cd48e689df3ea785530.npy +04256520-d08fc6f10d07dfd8c05575120a46cd3b.npy +03001627-3075380de1f28ced3d290591da43d03e.npy +03691459-164ac6f6252e22b5f5c320b27d54d683.npy +04256520-7994498bd9b426cd37b2bb75885cfc44.npy +04379243-8c65dd783d2afcf468cdbc8b02ff160a.npy +04379243-1cb0232d2ec82f9ead135ea7bc8aeff3.npy +03991062-8c3c0ec3779a163098910e50f05b8001.npy +04379243-34fba2f856e97796b0a6e87d5d5521b6.npy +04090263-ed941e7672a4cdb0bddd549216d19f7a.npy +04379243-f023a5489450b924520ad20925ff9d2d.npy +03001627-c20dcfe55ce58c055c10b08ea69398c3.npy +04379243-b1c80d73aa4114811011cbc4b5232a4a.npy +04379243-f4692dabc20f58e0f51f77a6d7299806.npy +02691156-24cc8816b384723510a7b8c5fa89c603.npy +04530566-2988a53fc376653aae529ab4a75c4af.npy +03001627-8e2b4f8e0a38d2cdfe74384b8bc69dda.npy +04379243-c1c81b60f786873262379fe9a26f5cb9.npy +02946921-4d4fc73864844dad1ceb7b8cc3792fd.npy +04379243-629d09ce8c10a4f866603970dfcc17a6.npy +03325088-327d16b036d840a2e1bf57430463e143.npy +04530566-571a2485fb205e5fa9142e7277ee08f1.npy +02828884-f7ffdf91b66c0c989c9513cebb0fb44c.npy +02958343-edf4007e23cd00b359c19df2d1879464.npy +03636649-b89c79537ead39c1cbf3dda885c64a76.npy +04256520-ca81512a7d7934d0b8e42b2c59ee19ec.npy +04530566-59585673328efdf2efa33903c8f77ab8.npy +03001627-c8713376eb588f422c0e1e24bb9eb3ab.npy +02958343-3d85915d8726cc1845aa033a20004998.npy +02958343-c8fd6ee4bdbfa5cfbda3e4f05af7d436.npy +04468005-9b34d4118d5d72e9ed2f8e1c74f9fca9.npy +04460130-c47a34f2a3acdc0bce8973e274e9f27f.npy +04379243-19c2fb727de9c13c51d3c864cc68e22e.npy +03001627-72a86c2fc8d5cb3713d2510999d0f1d2.npy +03938244-2873ef9354972727b376ecd25749b977.npy +03991062-61fb1e91cb867fd930c7810cba6da248.npy +04379243-82346c794fd098f77a1f550045b16384.npy +04090263-4e007e41bad1b1cd735fa1ab17311ec.npy +04379243-f1c64d90ecf5212fac0d0a08bc077486.npy +02691156-8e2e03ed888e0eace4f2488af2c37f8d.npy +03691459-e40e7c3dea88a733eb15975241f6a53c.npy +03001627-3a3ddc0c5875bae64316d3320fdfa899.npy +02958343-470f53291d23cf0abecf71e2e014ff6f.npy +04401088-e0ccc0cae4dc414cb4e7b68321c9d305.npy +04379243-592296965078028282db9fca4b68095.npy +03325088-9797db191dd9813b14b35a7d7cea7130.npy +03001627-379f0efc898d7a7e9fe74a48bbc553d7.npy +02828884-c2e0cc96c3ae97932997d70e9237dd6b.npy +03636649-5850799c5af71d58c13933f92cd75682.npy +02871439-3040f51df4b6f5748abbce8b0b4c2d45.npy +04530566-307a956fb5eaf7a629d81e9641dd535d.npy +04379243-52e0dbbb53159e0fbd8980415d183a3a.npy +04379243-60b2e4ccf3ec715ec3abfe135b5412af.npy +03337140-a3c7255f5ec832c3492d9da2668ec34c.npy +02828884-fdf0f799b897b0c99917ad57402f53f1.npy +03691459-81eafc16db11da806583871b5c274818.npy +02828884-750cec373ccc38a3a3d37e70863d948e.npy +04379243-3c3c0da7a2581f20490ad276cd2af3a4.npy +03001627-dbf235de67b39c2d25e2408bd7177733.npy +04379243-3f48840eca0de14ee693975eda4e3db8.npy +04256520-6ab5321efc4b3772492d9da2668ec34c.npy +04379243-c4071718e45630ee5510d59f3ab1ed64.npy +04379243-7be495e700afefe6cfedb1d8b135cde9.npy +02691156-9f90f3298d7b6c6f938204d34a891739.npy +04256520-37939caae967b34da14c5748cc240cc2.npy +04090263-425279eb4cbd51a48bfbe54b5d01550.npy +03211117-e71f7231406aa6ee4019d3f83e009e77.npy +03001627-b4c73f4772efcf69742728b30848ed03.npy +02933112-a9bc0de459504729eca1c556848f5db1.npy +02747177-1b7d468a27208ee3dad910e221d16b18.npy +03001627-a3cb39c5271c3232feec1f13d2353f3.npy +04530566-511befaedb0123cd96600832daa83ed7.npy +03001627-22b48b577aab6201bb99d7af794753a2.npy +02801938-8ba662af65531fad1657aaca7aaa9a5c.npy +02828884-6a474cb5a494c1e6ad5067eac75a07f7.npy +04530566-bfd8b473e1a8fd650eb615eb69452b.npy +04401088-237b8445c70b1749ce2eca356a0e3474.npy +04256520-4e43e29a68b72d9fd9246d8a288bd77.npy +04256520-eab4334a06fafb7171c3cf047830ec1f.npy +02871439-712d0b79acf23e674dba58e91f113bcf.npy +04401088-3a6a3db4a0174fddd2789f496481c83e.npy +02933112-e0393e80702d9a698cbb8bac2032149c.npy +04530566-ac736a87ca813c6d701c68e1045b606.npy +03642806-1f507b26c31ae69be42930af58a36dce.npy +02828884-77aa33479c2ec92f610c2a68437007d6.npy +02691156-cb8fb401a278fc36bbf3143b1cb6076a.npy +03261776-c5e47b627cb7818f17e22b7299bb7bc6.npy +03211117-5ff51c478471d1f15468776e191863a2.npy +04379243-5525e36ebab96f98d989c9f989a09ff.npy +02871439-46579c6050cac50a1c8c7b57a94dbb2e.npy +03001627-5923697231e1bc86af38a3b0483df58.npy +02958343-e8c48b9ed916910ec800bf2938639a70.npy +04530566-be357b15497cc2133a18a4a0def966f.npy +03636649-6d7aeaf3c1705cc5fda82f1d3dffb320.npy +02691156-842e5dcd452f34aa8caa71b1fbf7fb98.npy +03636649-a68678b3e52fcda2bd239d670cf7d8dc.npy +02958343-a36c53acb3255d1e84b1aa0ed7e58be1.npy +04379243-fbf5c95ec6febbeb07cbf788ba0557c.npy +03761084-29012d42054b3a1087bcae7a654cc37.npy +02958343-260f0644b293fccbfbc06ad9015523cf.npy +04379243-3ce4b963a4869248febad4f49b26ec52.npy +04379243-d91619d6c9915368e6c5cd45aa112726.npy +03001627-d350f40e5f04360565ba78ad9601cf1b.npy +02958343-86a9eacf6b362ff398494085d68ad6a0.npy +02876657-9ba6291a60113dbfeb6d856318cd1a7e.npy +02958343-c2d2eae7ef1a34e1f500cc506a763c18.npy +04530566-9696dd7f30247c5c573080510ce7a6bb.npy +04004475-3800e1d7cb83b4073ba96e34ec81ed42.npy +04379243-884a1ff382ca00d340d1d1b64916e0c7.npy +02958343-5ef8eeb5ba5d2c6ff6efcf1cf084a608.npy +02992529-45e907ca47e0122c1752adf979b66914.npy +03624134-decf7a4989469d3289eec1cc60f7c002.npy +04379243-83b28dc11de6b2625c8a41baad250b1b.npy +04256520-ad856cfd25b91563c681404257d94ad9.npy +02924116-a81cb450ce415d45bdb32c3dfd2f01b5.npy +04379243-65f9103ab7a64e83cb7105765410e2d6.npy +03001627-54a6748359055b5ae5e2f0eaeb6aa550.npy +02933112-d6138b5bee8f009ebd9c9454e3d4e73d.npy +03691459-2e530fca4ce161902b12aea3a74e3599.npy +03001627-39031caf2b11a7f665ea3fba7f481d97.npy +02747177-8be2cf5a52644885cb2a965e75be701c.npy +04256520-6898a9ca21823570a888124bc30aa1c7.npy +02933112-84f34a2d86cd4f0211926054acb73bec.npy +03001627-be8dbd9726372752412dfc90452742c7.npy +02828884-8893daaecc8c76048e53587ea99de59c.npy +03001627-490941bf4a532b62492d9da2668ec34c.npy +03001627-76dd2d9f0183e09dd835cf838a2f2758.npy +04530566-c3bbda10fd915342c24de8a3b5a07552.npy +04379243-59dd0aee74ce6d1798b8c800ae001b66.npy +04090263-7fb2ec71361813bfcec05e03e317cbf8.npy +03325088-7de46bce9c800cf3979c556124bee033.npy +02691156-755b0ee19aa7037453e01eb381ca65.npy +02691156-cb91205ac0f2f62429dc68c96bb3c4.npy +04090263-6b0c761060feebe4affd759bf1ff6b0.npy +02992529-e3e43df4a3fc1870d4d7de9e3c2bb6f4.npy +04379243-e7b0ff6ffeb24ac2cfde2e560cf498ca.npy +02691156-9ba460913d86466f62347b4731688b0f.npy +02933112-ac4e80d4ad2d0ce98060a555dcc63fd1.npy +04090263-55171896c70646cdd87c63d8b3018b58.npy +04256520-96de367b3365416ac580fdeb5460f6d6.npy +04379243-5e978c92d55f7852185574a5e2255bb6.npy +03636649-77d1b5aaf145f8905ecb3cc57fe87cee.npy +03211117-534d3c5dca2d44641af9a5a7008cc3ec.npy +04379243-cfd7e354a5ae982aa0ab1d82ef09f78f.npy +04379243-398dbb0a34ca527871a782a4379556c7.npy +04256520-332b2573bb3675cf14038d588fd1342f.npy +03710193-fd3227fb95b8d29b60ffa41581e372a1.npy +03337140-4c38f799ecb6cfdbb39d771847f20151.npy +04530566-758c75266d7788c0f5678db9e73ab77e.npy +04090263-b47d65a7c6234d06b349bd01da88f0bf.npy +04090263-9397161352dec4498bfbe54b5d01550.npy +02958343-4a30d2147d0e27d13ded1857c15b5b6.npy +03642806-48e07903fe5057a1d7289d94a5c9ea3f.npy +03797390-9af98540f45411467246665d3d3724c.npy +04379243-615b800fb332525385c5f690e9252fc5.npy +04379243-57d7f4c5b427dae69dac46bde4c69ef2.npy +03991062-45ca193e946b5e19956b2452b4c13510.npy +04379243-3e645e9f5703d14e51d3c864cc68e22e.npy +04401088-6d7a0e701b4417504161e123a102b12b.npy +02958343-ddb4ad84abca0edcdb8ce1e61248143.npy +03001627-2718b1d46ca52df052bfb1d5ec273240.npy +04090263-d64825461795cad2ac2ad609ecafdf83.npy +03636649-fd2f5320fbfbc88a47c71c6d277c802d.npy +04468005-537decdce3079c857addcf2661f94d39.npy +04530566-2571a0b3d1eb9280f26f17fb5c4740a9.npy +02933112-62a332e54cca36f547b925ad5d9d8738.npy +02828884-95cbcdc64b28bbf396f61afd58e50ae2.npy +04379243-f8050e698bff9fef8d1c65d617ea0b5e.npy +02933112-c1f419412a6960a27775562146ecea9.npy +03001627-77371d342cddea8d8b424343280aeccb.npy +03337140-dee0925183a5350732fb9a763fd231a7.npy +04379243-89cc879f005dcf50f1f50f6a678fb494.npy +02958343-3232d99c41dd949a8b257f8b62755068.npy +03046257-a60acab7ef47ad82642c99c10134b38c.npy +04256520-3f5fdc05fc572730490ad276cd2af3a4.npy +03001627-4c0983329afcd06f730e89ca0d2d13c3.npy +02691156-48a9b9c041d377b26012a714b05f25ca.npy +03001627-d57bbc72d1b2670e4209d14d674fb332.npy +03001627-26aa22bd1da8b8c5b1a5c6ecbc81953c.npy +02954340-254e230d31a62470a52821bf1aa3b19a.npy +04460130-6d69bdc0bd266b7af7f1024a921d6d8.npy +04090263-60db20e995801bdcac8247d8f020ed1c.npy +03636649-2d2a1da36b840ecfd49b2e04785f8492.npy +03636649-6068920e350f1fcef04bb0474a98ba2b.npy +03046257-73956ea1cfbaa5ef14038d588fd1342f.npy +02958343-6c85063bf5e983a3d14b144052416695.npy +03001627-d2a1aaba7e047897492d9da2668ec34c.npy +02958343-d513c968e5bfefd2516624d6e93a68b.npy +04090263-c2be1232f61da4b6e79db68bf2508b3b.npy +02691156-72537a008bf0c5e09d1a1149c8c36258.npy +04379243-cc6696abd1d76062f90f8519e58d5382.npy +04256520-b99058a0054ea0f8387625a8fa2965.npy +02808440-76004a2497f3bf98581a5df406f5588.npy +03001627-1eb2e372a204a61153baab6c8235f5db.npy +03467517-4dd3b42e67a19210925e0edb2365fb11.npy +03636649-15c51ecb58bf304fef3a2c64cef919d0.npy +03001627-58e6fa617a1bed1a20b64028d2efc877.npy +04379243-a63d31d92b6bee14febad4f49b26ec52.npy +04004475-510a9921ab03cf6ab331a25788d3c6c.npy +03046257-44d60011d28940a0eef5d83b671bb264.npy +03325088-cacb193f82cbaba0b362845c6edb57fc.npy +02828884-95e97cc6e2f7e2e1d5183890546dc397.npy +04468005-9f0b225a83d16aec84e8a55c6921f1b9.npy +03467517-aa86d20d03b2303593f0194265a9746c.npy +03691459-df678ca1f17e32ec3d65eaf8cbd60895.npy +02933112-2f2a87c3626ff6fe1aae34e8209c4d10.npy +02924116-9c15f5571329510792f19acc54e02dc1.npy +03691459-d3b324de8e23851e55b62c3398327a83.npy +04379243-38bcc47be092398cbc2921df9ee1c4f4.npy +04256520-e8aa02effc458838f2098a9f7fc86999.npy +04379243-c3cd2a7f997a6a40f3017d945b17b4d6.npy +04379243-2ebe5dfb7bd9a50c6effbd64ad6b71b8.npy +04379243-a406ef7c367e9c043ce425098c6116e5.npy +02808440-6ec3dbef4a3e1cb279d57ee14f8ee702.npy +04379243-5b99ce5dc47c76af3e57e49d8269b367.npy +04256520-9ec5fcbfe43af15b851a116903680096.npy +04530566-33692290561c798e780bc2708a85ba9a.npy +02691156-a053f49d808b7b36c8db97d9bc169245.npy +03001627-40f188600cf8362b654ea6737b0d3597.npy +03001627-e6c7e75046f8946b27bf2eac25b523a6.npy +03624134-acc8da45bb6d772ebf103b0ce6f42d81.npy +04530566-6d6e65b938b88eaf3a4406b2a58a646a.npy +04379243-7f1548ee7cdd456fc2b9c3cc12089fe.npy +04256520-5b94025a52c244bfc51d071e487f31b0.npy +03691459-95d01543b46b5e43f398d0c5832df00e.npy +02933112-5382680280ef5b57d0b36851d61b6fca.npy +02691156-b11c03976f121b3537007500db3b770e.npy +04379243-3344c70694e1bacdc5bd1ef3bc48a26.npy +04090263-569416cd964e365e20152153c3a56171.npy +02958343-45e9059c3ac5825661c6c61410fc904b.npy +03211117-9db1c375f76c8ac1db01c957364e77d0.npy +03636649-8f5347fce0d9b517cac7c8ef7fe2392d.npy +03636649-54f858f74a0eb7d5ee11949398abce38.npy +02933112-9402e5123bd831e276f1f48f36df7df4.npy +02808440-370dea2a2719b07744221bef0fa3c36b.npy +02924116-ae5b72aa78a2b7f5708871f5411a4ec7.npy +04379243-e013ba1ff446bd56140a527375fd6757.npy +02992529-a4910da0271b6f213a7e932df8806f9e.npy +03691459-1bcf25863e840c11f806e7110c573eb2.npy +04379243-4d3bdfe96a1d334d3c329e0c5f819d20.npy +03211117-33c639831fef416957015074db1e51bc.npy +04530566-c8414ce9b8848c3c1a3ad8aa8e24c7d1.npy +04468005-b3d1c0e95d344ec1dc14ba0818ee5cec.npy +04379243-b2b4829e281f1ca09a87002a4eeaf610.npy +03211117-6e4c06e5dc03291bec77bb7db6eae005.npy +04530566-cc4f56a126353cd81985296f8eaaf6ef.npy +04379243-c76b1d97bda153f51226a0a31e4f771f.npy +02691156-afd43430bd7c689f251fe573763aebef.npy +03691459-58af19399a5a447e4310636931b68fdb.npy +04379243-882d74e3afe42d0b651fbe0e01830a4a.npy +04379243-40604fdd535fd2b2e393e26dcd2928e3.npy +03001627-6e92bdda1bca7b72f9a4f3015fbf70.npy +02828884-1422f82a72e0b7f48ae1c1abea367249.npy +04379243-852e28dd91e4fdb35c1975633309d43c.npy +04090263-e5a481c9c2e1f17516f51ef194451b39.npy +03001627-501bf2a6d014d22ba169b9ecd9e046dc.npy +02933112-c3755418f2df9369e7e684d25d4dcaf0.npy +04379243-5bfef1c85186b2d836b0f2a1430e993a.npy +04256520-5f531e379365040936a36f8fd7d27134.npy +03691459-923b7f0a4bf93c4fb66814b45dc64bc9.npy +03207941-af913c310f1b978ae6488a574e8954a5.npy +04090263-30ee49fefc0d62c8f14183c264ad03ef.npy +04379243-6b0fc2214ff06578eb3bc6c6d15f9bf.npy +03467517-69721c66520226b3f435ae560621097c.npy +02828884-9d4086be72fa427cd2b12aa6a0f050b3.npy +03691459-f4bb44c3b9a044ebaaa7694cf6c95b84.npy +03337140-dcc1c79e9650b987492d9da2668ec34c.npy +03001627-6d619704ac0bed9827eb00c151c6f711.npy +04379243-668da5fd442fa5ceb74af32735cc24bf.npy +03636649-b2e46fb6018d2cf2d93768e7b9b1eabf.npy +03001627-a42aa59fa23b4a4d9c0ca344f487323e.npy +03691459-5f41f45cd57adc0b885333683933c555.npy +04379243-912589813b9dbedaec85606b5c87ea7e.npy +03001627-8f521c85697cfb73f51f77a6d7299806.npy +03001627-d24f623af8e7da479dbf298bdf3162be.npy +04379243-9f760e1d7ab97519eea323f522c6486.npy +03001627-751342c7107c86f0fa9e9ca2723d9727.npy +03001627-9e145541bf7e278d19fb4103277a6b93.npy +02828884-80f9707a7e4a0cc856853064b332a2ae.npy +04090263-80b03f350a5de86e3a653cb492d78488.npy +03636649-b3a98808fb1ccd892a5041fadf25a502.npy +02691156-81e4cc88fc757ee220152153c3a56171.npy +02691156-5ae05c956af61890b58b3ab5dbaea0f7.npy +03991062-cc71eaf7278d78ce72652f4081ec5a77.npy +04530566-f03f7c963928073227ac692756be9e24.npy +02933112-34e80aa7b579469bb163e775a4d52465.npy +04379243-1aba52edddfad70d1bf0233e4c77d163.npy +03991062-752a32c80e716fb8a2c59a4d90e63212.npy +04379243-a78e8ad852e8d3e3cbb2a1d23fae41be.npy +02958343-bf0e8d944ba4843e94e7e8e27399daf7.npy +03001627-185bcb9bcec174c9492d9da2668ec34c.npy +03691459-63f006488cfdb69bdfa0db1c1e10ab1a.npy +04256520-c15b0bca48207d9d8cbb8bac2032149c.npy +04090263-76fbf623256644116c830d654bd05bb9.npy +03001627-834af6ad2a1d5581492d9da2668ec34c.npy +02828884-76efe392461139df80ac1d1d1048ad28.npy +02933112-1f319101d3c05a16886a4b751e0cc0b5.npy +04379243-d60054176a178d18febad4f49b26ec52.npy +04379243-9aca8b4392e603fcb1763573e754f7af.npy +02958343-baa424fcf0badeedd485372bb746f3c7.npy +04401088-759c984fa6831ad7bf0defeaa770e93b.npy +04379243-c809bf0ed02eef7016a2b5862518c93.npy +03001627-47dde30e987efc6c8687ff9b0b4e4ac.npy +04379243-81bfbd041dfdb827c08b855dcc4d6f49.npy +04256520-bcaf0bf7eebb7d7f4fa36fe4cfcd8f6b.npy +04530566-587793fcbae6a6fbf5abe4b4be4c3d4b.npy +04256520-8fc21752c5c874626b4675882670d943.npy +03691459-f8fde8f5f364087d2d563c85edb49108.npy +04401088-d5561b05a6b84a5489905122ac8b41f3.npy +02691156-d709b3afd41a578ba03df56f69a35fcc.npy +02942699-d1a3482c576f8c50592ecd319dfd8c5d.npy +04090263-577388c27e850a97f0fea2ee98610322.npy +04379243-3239a4e1c62099556ee5c30704fa2d08.npy +02958343-1cb95c00d3bf6a3a58dbdf2b5c6acfca.npy +03211117-31daffe57909195455357c338ec9641.npy +03691459-7e061336b31b8604d34bdc365023cf4.npy +04379243-fa1e6b0591047eaeef78a907ef09669e.npy +04379243-8f841c9a11ad77a6794a9f593d938882.npy +04256520-27781344ab489f2df29666f384be6c43.npy +04379243-29b2aaca87d19a3c5759f4335ff2e408.npy +04379243-5b0185f3a758e481618970cea28848f6.npy +02958343-f6ed076d16960558e6748b6322a06ee3.npy +04379243-e095933fc153f7371ffe260c5a3e6b53.npy +03790512-e5a9a7b8c947aaa1949b12cf3977a48b.npy +03046257-ce4de74b5487d0b0e7c7920f6a65a54d.npy +03991062-518360745bd7eb881255bc546ed0fe3.npy +04090263-322a9fd05f1f68b4dc99cc00991f7287.npy +04379243-c850233cd5ebd8a49725e3ec23636256.npy +03691459-4793c0b78701e47dd529f6660fe10a17.npy +04379243-3b465822b34ed20ca05d3424fd8d541a.npy +04379243-9b722071fde9069ccce4c6d5bb195f.npy +03001627-e64275c95e41605caf7c7ad2549a1b15.npy +03759954-c66b5236940fa0c474d0d70573a389d9.npy +04530566-721a41c68f8d1e1af898a4b2192a12e.npy +03001627-56ab99b69cbc1bb50d55c58aabe6e7b.npy +02691156-16868a30ebe634053dc22b596edc161e.npy +04379243-c6fc21c5f51f169f365368fe0de21d22.npy +04379243-b72bd5538da87c0da54b9afa882a89ed.npy +03325088-35cc4aebc9da75a1b362845c6edb57fc.npy +03337140-8032a28768c3f22a7843fb4efdc19510.npy +04090263-f1bb43c7758ad37c12b38b1d99376c0b.npy +03001627-2d1f6e50aad6d88721fbac718728a36d.npy +04379243-8df054f74a538e72c955e5ed03ef3a2f.npy +04379243-c53b11ceba592177564c88c75bda3a02.npy +04379243-6791c92944c99c029f1deb04fb8ae481.npy +04554684-aef595f6f7c14cf4fe43ff1e45af424d.npy +04379243-c1180df0a7ad92afad5067eac75a07f7.npy +02818832-aff661c669a2bb4fe3fb5e8ccfbdda1f.npy +02828884-fc0486ec53630bdbd2b12aa6a0f050b3.npy +04379243-50f93f2278c3cc066bdbc69440dbff90.npy +04379243-f5cbbe04afdc4697562b835b63cfd09c.npy +04530566-2abe34f72a7ed4eb0d00cfc385a039b.npy +04379243-2cf794ec5ac1f1e0f5a97170d660a78c.npy +04530566-4e341338a4425ea391fb4dce28166bd1.npy +04379243-1e2565b2c28e69d3deb25e31ec3122be.npy +03636649-b02bd8e5ef9cfe354b3c42e318f3affc.npy +03211117-792002ca0c65b1dfaf7869e0a5920f2a.npy +03691459-75112a1fb101921edc1b62a5dd6fee95.npy +04379243-d0b38b27495542461b02cde7e81f0fc3.npy +04379243-c5ae96124c15c734e6c5cd45aa112726.npy +02871439-104874322c6f7a75aba93753eed86c0a.npy +04401088-73b0bcdcf57a8a7fe8d8ad3bdef6aca2.npy +03001627-5748c2c222d1528deb0a72cc21af76ff.npy +02691156-c2d90cc742f17ce828204947d78b9af.npy +03001627-6a152238c2ae02faf7b2f235a439923e.npy +03001627-6fcdcbaa1cbcf217be8211d595eb405d.npy +02958343-933b88ebf7eff4c095551e0d9e50cb0d.npy +02958343-e4be3f3bc271ff71c805dfe4ca9f2fdb.npy +04256520-e59bd11e144f6ca49aff919557ab16d.npy +02958343-fb20b20452ef661f500cc506a763c18.npy +02958343-137f67657cdc9da5f985cd98f7d73e9a.npy +02871439-3c9f48785776ee8efcd4910413c446d9.npy +02691156-30d8f7fe0da9d5d0c164bdcf3c9661ee.npy +02828884-17d085303d4c5121ed98cca8f0ccd5f7.npy +02933112-83a9e08664eeec09c59350d819542ec7.npy +03636649-90e5bd9f10fd5216fbb8cbddab1c2002.npy +04379243-b256041abd83a94862158b7ee658e910.npy +03211117-765526579b03cea972a71697434c2820.npy +04530566-80d381a6760185d8c45977b13fbe7645.npy +02828884-bacb5f46add42da9a53649a80e5aff8c.npy +03325088-8941e1839d0e718bb362845c6edb57fc.npy +02818832-4bc7ad3dbb8fc8747d8864caa856253b.npy +02992529-5a37ad3759b4d93df843a7d4732b1d6.npy +04090263-84b0027c1568c9c3694547efe15425bd.npy +02958343-a88d69e53a01aab9ff1370452e3a0154.npy +04379243-d8bd55abd721dc0c99860e9353bb52a1.npy +02871439-24c62fe437ecf586d42b9650f19dd425.npy +02747177-16ce4a2ff48b8a81d2b12aa6a0f050b3.npy +04530566-62255074b0df6a115fa2a5df3ce5bc40.npy +04090263-c95d2ac372888ef349a3c1009fa79820.npy +03636649-6138faeed623475b43ac09133d4c1d60.npy +04090263-218c020fa843aafc99f5e7ab39748cd2.npy +04379243-5d90c1e74acbae27475bcdf5ead5bfb9.npy +03691459-dd6a03f9fdc339c6538cf6df9faa9b65.npy +04379243-c12147db9b29ef9ee0480c954dcd56d1.npy +04256520-cd280bd68e1ce7f266260c2464355988.npy +03001627-573b3fed3942a148c681404257d94ad9.npy +03001627-c3778a3db3d7060bbb40b038e5e0b7f0.npy +02958343-4f2ef861d32a6f0b45594023db7cd10b.npy +02958343-10e99b1475098c0aaa69dfdc5532bb13.npy +03001627-96e9b84ee4a556e8990561fc34164364.npy +03001627-5b27b7cc16d2b25231f8120b4da8e523.npy +04099429-e7bd2548af6584878b95fd0292417266.npy +03636649-4d08db52c717b74d49c3792a0dc29860.npy +03001627-37e3b1b00196001160902b587804b688.npy +04530566-7127c0b5fbcdbf21adcf800d8263e5d6.npy +03593526-ff24afcf157e1b95bc311577a374c00c.npy +04468005-6c616860e640736ae182c6d0e8257bfe.npy +04379243-44f0353cdb820886be25fbd47cafc694.npy +03642806-b02c7e6b02d1ea5350f2b6c0ece5e801.npy +04256520-2a9fbcc138834d07a6bc98af4c2f54ca.npy +03642806-bcf57a7cbbe77f2e41567ce9c420c236.npy +02691156-d23eecb0437107756c63b8b48495261a.npy +03046257-9b9e9ebdd5c4941452b2c671e4d4765b.npy +04379243-5a6e7c4fb53f27925d3bb412062af8d4.npy +04379243-37ac02e6ef9c1ac2e21111e385a0661f.npy +04379243-48443cc15bbca01f20768660cf080d12.npy +04256520-9f4ad442e9cb51125a31d91ec836a511.npy +02933112-a679e4fb660b3751f51f77a6d7299806.npy +02828884-beece550c6a1bb1cef0add8da8532fa8.npy +02933112-bceca165030250f94da5feafe6f1c8fc.npy +03636649-49647be2c7460c5b8749901456352d5.npy +03001627-1063d4fcd366de4060e37b3f76995f8b.npy +02880940-bd2ba805bf1739cdedd852e9640b8d4.npy +04379243-be1a98a8e06c59311556e8f97439a098.npy +03636649-4924f75c6be38334f51f77a6d7299806.npy +04379243-19bc9c781df1da46824080f516909671.npy +03001627-4b495abfcbcf4b76ad484915511ccff6.npy +04379243-1f3e217cbc871152d7465eca206fda6f.npy +04379243-3cebd4314f773f8ccb9cf5f7d536cddb.npy +04256520-22d997a2ee077e3f48fda83c10428379.npy +04379243-4cabc64d91668d76890992ddacc04113.npy +03001627-be9ced795316066f38620af15fa7e604.npy +02691156-a931895438ae4502a9f468923d4ea2fd.npy +03636649-8a6d770e6b4942c5ef3a2c64cef919d0.npy +03593526-2d9fae9136d41ee2b978cf07d1cb130b.npy +02958343-3bb3b6b85e4e42873680ae1a67758160.npy +03001627-80f9fb95252e6e535bc104fbace43d56.npy +04379243-9d59a4bb0e08150148eaa510713cb074.npy +03001627-57a54d8b1594c399423a79096715f202.npy +03691459-2a59accd6ff9b5265c38e15d823f1476.npy +02876657-546eded3ac7801412389a54fb53b0765.npy +02691156-a675480b02f939424131d9ef9081c198.npy +04379243-3f9200756c2e3aecd028c2e338a88f09.npy +03593526-4996f1c0120f4c62ab361b6be63163da.npy +02691156-1a888c2c86248bbcf2b0736dd4d8afe0.npy +04468005-83dd4b87114ddf2ec51d8e07a45cfa0e.npy +03211117-dfbce5e6cca00c1448627a76b6268107.npy +02691156-34ef846a22c6a6ac5e9e2656aff7dd5b.npy +04090263-43aa82d8c71e6ec69f433921788191f3.npy +02691156-9b5e193416d5b2c09d608d5eb8e56ba5.npy +02828884-62cc45e9d704d87f155d75bbf62b80.npy +02828884-7cab2809bcc7b73a141c96faecd80bdd.npy +04379243-adf35ea69635bade7b9c6deef486a7d8.npy +04379243-9a4303e83aaeae9cb2ee6b27e0eef6ad.npy +03211117-fbe9615a45afa17524f0493013a8318f.npy +04090263-cc4eccfdaa0aaf25efcbb3a4a9f89cf0.npy +02843684-4abad12b5ed565da7720fd193c09c4db.npy +02691156-345570c792fde290d49cdf0198aeb01e.npy +04530566-804e29433fda9657746ffcbc44510229.npy +03001627-36447db5cf7b5a27ab5c60fa85a57ffd.npy +04401088-59e5dc88174971c567964ba700cd97f5.npy +02808440-842839d83fea08eeccd0340812259a39.npy +02958343-44f4bebe8b14badf314b3b3dfd6337f4.npy +02691156-18d123aaef6b911954eefcdc602d4520.npy +02958343-6f7cc4940eee83e57bcd1993e004117a.npy +03001627-bf7e8e0dc4f4038cc2567be77cb7ab45.npy +02958343-550d6c4149699f4f93de227e8a339990.npy +04379243-d48b1d27c46b56f2bde1c279d540fc66.npy +02958343-c9b956006607a48c75dadc997718614d.npy +02933112-3efeb00eeba8a6fa2db3e9b673557fcd.npy +04379243-3c991b31710144c5923e4a84d4dce694.npy +02818832-19d88337c81737d3bc19762eaa7ba40f.npy +04379243-2b567360f02ba48e4923701c409a8965.npy +02958343-b50f9931670e25ef44ccce632b473b8c.npy +04379243-27295a6f585b7817febad4f49b26ec52.npy +02876657-634c59bf37676ca64c3a35cee92bb95b.npy +03046257-2f2e423b7155dbc5844442d12ed656e7.npy +03636649-9c4a3637ca2ce09d4454439c22a43db6.npy +02958343-1c53bc6a3992b0843677ee89898ae463.npy +02691156-420f92d84c88244b9a6e43b878d5b335.npy +03001627-4ed2bc57d5fcfbd82c37553db37ec752.npy +03001627-4608b290c2383d7c9730cb37c9a5f63b.npy +04256520-c05bf63cd7818b6f19fb4103277a6b93.npy +02958343-d0552c332fd0182df3cf3d2cc3dcb043.npy +02958343-fe78ad3863e25cb3253c03b7df20edd5.npy +04256520-a1dbdff3da83425f3eec26c23f5bc80b.npy +03790512-6e37615194e808d3b37378f3c85478b4.npy +02933112-6788de26abc86a8480fa521a9c7198a.npy +03928116-1cc9f441f6633b932d9da001bf4482cc.npy +02828884-8325e5496a7ab8abd2b12aa6a0f050b3.npy +03636649-dc005e462f4941078a3097a6302b0866.npy +04401088-e8d704bfd9b6c7f39af985c9d0dd6085.npy +02958343-92c4d4bcb122509aafe1d4530f4c6e24.npy +03211117-1f4b16094bd83af82d2d2896f4b277fc.npy +04379243-34787e9a9a0c1ff4905477d2a8504646.npy +04401088-471a1ba8c1e1fb0a5b031707d900d7ec.npy +04225987-570fae86bb5e1843d587b281fa5e7b27.npy +04379243-aae0d0d70c13b8c781faebbdea6bd9be.npy +02924116-7930d2ca4a3f4b46d64784d8f0d2a643.npy +04468005-62233a4705338938f05cd1b93df67c5e.npy +03636649-a130ec5d53e62931d93768e7b9b1eabf.npy +03001627-d794f296dbe579101e046801e2748f1a.npy +03636649-9ef7ccb91a25dc988cc413950b617e8f.npy +04379243-be509f0aab6ce96251d3c864cc68e22e.npy +04330267-1a98ec71c011d3c1980d7e8bc442d06e.npy +02808440-c033a70110171a594cc3b7bdfa613934.npy +03001627-8bc130dee1e488925a7b0949b519072.npy +03211117-4abc3db68398e2cf16eb1b6d0ba9133c.npy +03691459-3d18b9cbc81bd83b83247f812f2eaa97.npy +03001627-1e304b967d5253d5dd079f8cece51712.npy +02808440-d11d01a4ab7912347c34b08df917732.npy +04379243-75e206fbfaa7a973eff7102cbb9312c2.npy +03797390-f1c5b9bb744afd96d6e1954365b10b52.npy +02828884-d1190ac57a48b879413d0cdcf1f63207.npy +04379243-8ebe791395cadf8dcdc074d7b3f1e7e1.npy +02828884-b1117a83ebf5a4c9c337a931444a5063.npy +03636649-6ee5804580c170cdf6da603e92626bf9.npy +02691156-6da4590bf9d7bb9698b8c800ae001b66.npy +02691156-c7e74cb0f2dcef904abea106683105f.npy +03001627-2a8b0d30928d3161f7b783634bf3f92f.npy +02933112-7abc6f3fcabd914157d513bbf87f8d1a.npy +03001627-86fed830cd355f591c0f52f4ec8b820b.npy +03691459-115115104976edfdc066b9622c005c53.npy +04256520-8f1ce2b3b4f352254b3c42e318f3affc.npy +03991062-58535fe2845a3427ff1ebd5836684919.npy +03636649-ddc2d39dac6e84506c5b8009db95f66f.npy +02924116-fe216feb2fb07f8dc9a4da29878ca580.npy +02691156-a14b262838529c2c81e1d9f6b27f1a92.npy +04256520-708e7253604979d06d83c04495f2aa08.npy +04090263-5febb85000f9df46c2e0257dfc41d300.npy +02818832-6cda64954ee8f9c122347dcaec583703.npy +02818832-76db17c76f828282dcb2f14e2e42ec8d.npy +04090263-8ec7ce14af18580ea5291b13c05695e1.npy +03797390-34ae0b61b0d8aaf2d7b20fded0142d7a.npy +03001627-37078d0597a05284b05550de345b6d0a.npy +03001627-adfab5a4d020094f98cfd47a860803c5.npy +02992529-d1b34149a8faba42faab2c6c450c7c1a.npy +04225987-7c009b2a37ad02a9a72f80277e176a2f.npy +04256520-56652a99cd43b77744dace04559bf008.npy +02808440-1f5642ecc73ef347323f2769d46520fa.npy +02958343-c00ec8e0880f507ba2e48b029cec5d4b.npy +02691156-afa65aa66f7ca040873ec74c119307b9.npy +04379243-474816f0203184f13ad51ab774fc9235.npy +04530566-d80bd439608923e07610cb1c03c9c3ea.npy +04379243-e6a1c65789846ca8c88ecf8c33c3edbe.npy +04554684-17dd78a433c3840b51229e7d6fc0cda8.npy +03691459-14fb43f3962bef40ce2d0b720afe8196.npy +04379243-6ba59a9ea719aefcd323d6bd8db8de5b.npy +03759954-9a4c236fb8dc6e3e1ef58b31c4ba0d15.npy +02924116-f9a30461da15db801b54449bede4940c.npy +02691156-7b7ebc856120f97a1944f01d3ab2091b.npy +03001627-4610136087e41261f1d6726679b21945.npy +02828884-efe997f288fdce2d985ef0bf52b97bf5.npy +02691156-85da8ecc055fc6cb58328b65a4733701.npy +03001627-ca9023f1c44aa7db82390c5f604e0d9b.npy +03636649-d5400264679eac33ef3a2c64cef919d0.npy +04379243-382889dbc86b5dd919fb4103277a6b93.npy +04530566-2ba37ef44fa116f8300ca77569ad3884.npy +02876657-7980922e83b5461febe67d9b32c3ddf8.npy +03001627-3cc90d903e0ec7aa61e11d707ecb7fa0.npy +04256520-1a4a8592046253ab5ff61a3a2a0e2484.npy +03001627-20b0a82068ae767c34cc22336880d45c.npy +04090263-a159a15c0f0acc22cd8875a52047b4d2.npy +04379243-dccb87aacbcb40a4f1783a44a88d6274.npy +02747177-4c8fc739917e3d4aad5067eac75a07f7.npy +02933112-94d10abadfa0d88bf51f77a6d7299806.npy +02933112-d5c60b873643f0e99f0825ef57cf78df.npy +03001627-e89689500a1e3b95fa935eb36a2e89fe.npy +02828884-7792b15f8c598763d2b12aa6a0f050b3.npy +04256520-cc7b690e4d86b471397aad305ec14786.npy +03001627-4b38f041ed60b99f7fe17e97940646fa.npy +04379243-392ed157b61814e2febad4f49b26ec52.npy +03948459-cbe47102e2e71f8120b92c47b3d5c1a3.npy +04256520-a87440fc1fe87c0d6bd4dcee82f7948d.npy +04090263-a14e353d1bb05f46b785a4ac4a0dbd73.npy +04401088-88c3248ee6950fc3d24be492f98354f.npy +03948459-ad72857d0fd2ad2d44a52d2e669c8daa.npy +03691459-601d696b56ed35a3b4f9aaea3b860d10.npy +02958343-433481aa8cde9b692e3dd7c278f108dd.npy +04379243-e053e9199d9d7f2d276b6f6d90ee3a83.npy +04379243-282b2cd82ba901479f8c3d2002c77ddb.npy +04004475-8f8e4848bc5769d0c4d354a5c6371202.npy +04379243-52896ba4c6c35090d3c1501c166e6b2a.npy +04256520-541e331334c95e5a3d2617f9171b5ccb.npy +04379243-c9675e9b6358165f66ccbd11a6ef0f68.npy +02828884-ab13fb5a4eb5897eaa9fc9f9a28d2718.npy +03593526-58757fb09681ea3236b0f2a1430e993a.npy +04530566-74d3bec29981aaa0efbed58ec3ee6f0a.npy +03001627-2c6815654a9d4c2aa3f600c356573d21.npy +04379243-a7d4b7751892502a9055f83d11955109.npy +03046257-11a3be19e931e77caadb7997f5aa04c9.npy +03467517-772d6017a18caf6f93f0194265a9746c.npy +03211117-5ebad73554fd866830bcd442adebae0f.npy +02871439-5b39e6a8f57199409bda39e34f423da8.npy +03636649-83254a427fd8309a36ca19fb57d01d2d.npy +03001627-d0b06607653b1744a8ff3e07cfca4801.npy +03325088-b56699547687adf76c18e71fd49c4dc.npy +03001627-b0a0f58be9f5dc0d3825a5bc524f67c9.npy +03001627-d15543efce9acacc8687ff9b0b4e4ac.npy +02691156-dbd74d18fa992eee7f1f82f6fc8747b8.npy +03513137-8b6b50321f5d5ba114300f3e8908fff.npy +04099429-c602b0228bf58aa2b5a019b4fce31328.npy +04468005-e7bca1d29be28c92d12132319299ff4b.npy +04090263-75af21a2be51a8df49f0e3dd7767881.npy +02933112-83ce531fdc507e34f51f77a6d7299806.npy +04379243-bfa2808f136b8f7f3c8fd4a2aec82d26.npy +02691156-7edf83742bece6be7cc4b32c704a58d2.npy +04379243-9be919e0f9243b9beaf288f952624966.npy +02828884-206904737710cfdded98cca8f0ccd5f7.npy +04090263-11b137bf4816ed40f4c39a35147bf949.npy +02933112-68aa1ed740374787de650492e45fb14f.npy +02808440-8692ef3bc81aa4c84c62bee40dcdc539.npy +02958343-764f08cd895e492e5dca6305fb9f97ca.npy +03797390-27119d9b2167080ec190cb14324769d.npy +03636649-7a8615c643bc3d96ed6eef8e856a36ea.npy +02871439-89dfc1520f7b2eeed42b9650f19dd425.npy +04379243-24942a3b98d1bcb6a570c6c691c987a8.npy +02691156-fcd7a8834a7f26f15069db69b8c1c70.npy +02924116-afce9683ea4fb46fb14a1e316f26e787.npy +02933112-3c2a50e5907b0fb64da5feafe6f1c8fc.npy +03636649-92e0f64c08f0c8ac3c8d0fdfb1cc2535.npy +02958343-2e0051c6acf7798d2c581ef6c05d52ce.npy +03001627-4959bcf3886dc907108366689dda0d5c.npy +02992529-df90c50a892611ca8536be73396b323e.npy +04090263-a2b803e958f8b80b8903bced1c63244f.npy +02828884-294613465801739b4739fd13bce14311.npy +04401088-cc3f77485b8a18db562c8e1ac545ef78.npy +04090263-a2b9d8c5357fc0aebc6dd9ba5ebd71f.npy +02924116-fc5944ab92962debc374eb2c1ec8a1b6.npy +04530566-95de565a937cc4ccdb024f6e72f57630.npy +03325088-f884c50c7afb527778d17489f52f679.npy +02933112-18efc77e6837f7d311e76965808086c8.npy +04379243-2555bc9595a45e9af36ea1eb6542fe7e.npy +04379243-9c33336af33fd905776d8bc79b9caa2c.npy +04090263-8210a8ae16f55c4bfb6bde4b7e6c6613.npy +03636649-dd278cc37ecff49ce6597d391ab6fcc1.npy +04256520-67708b6fc3e76563ca691253f597ebb8.npy +02691156-1de008320c90274d366b1ebd023111a8.npy +03636649-31ddb926f7e196a7fcb8d8c6d4df8143.npy +03001627-b58f4a6b71759e59de1e664b0a22c4a8.npy +02843684-e2ae1407d8f26bba7a1a3731b05e0891.npy +03001627-513686d6d63a1d8e577b5d737869717e.npy +04090263-91ccf1fd54bde780857835988c6a287b.npy +04256520-2d987393f7f7c5d1f51f77a6d7299806.npy +03046257-e8e68c0919fa0e6f1953882160211b1b.npy +03636649-a4e4446f8ba07f1730612f5c0ef21eb8.npy +04090263-5bb16f97c928f6dc4b49cd65dfcc3a9a.npy +02747177-31d318b5f2a1be9ee88c1d6fc3580355.npy +03001627-6e71bcc876af0e319b75b6346baf0c12.npy +03325088-c83b30147dc22d0bb362845c6edb57fc.npy +02942699-7ef29f8a7a132c46e0afa7d1aded497.npy +02691156-20aec82ef5f61b0bbd46d022fd7d80aa.npy +04256520-f261a5d15d8dd1cee16219238f4e984c.npy +03001627-81397314ef43f59e98cfd47a860803c5.npy +03642806-73b436084ec1697627d962ee5b0a40c1.npy +03938244-f7a58269c59ada7c4b3c42e318f3affc.npy +02958343-7e6da78c8dde0479f30da7304391ba9f.npy +03001627-cdfa898eadf316122056b4bd5d870b47.npy +02880940-c82e28d7f713f07a5a15f0bff2482ab8.npy +03046257-d352b743810b3b9e8c95b6223f519d17.npy +04379243-1d53304accfb6fb3c3bd24f986301745.npy +03001627-1079635b3da12a812cee4bf5d0f11ffe.npy +02828884-aab92a965e310885d2b12aa6a0f050b3.npy +03642806-212bf74d7c711a1634dedfee80b7006.npy +03513137-f59e8dac9451d165a68447d7f5a7ee42.npy +03593526-dde696b23a0fa0d01529e78b4656a338.npy +03790512-90dd1c4d894653322cbca070ad1b4ac0.npy +02958343-90b4f0d3187ad88c26a3125b78368401.npy +03046257-85551ef04a5bf758c0a61ad1cf92b694.npy +03948459-14fe99eb0c105a90fc9c56fb43681c11.npy +03001627-7a7b08cf81cf358a8616812464c86290.npy +03325088-fae7848a58bdf27937b2bb75885cfc44.npy +02871439-d97562d2e2eb296dd096bf408b606360.npy +03991062-ead1acf723d7b25d61aa3db764c0b4fa.npy +02691156-5392580fe70da9043554ccf8c30febe7.npy +04090263-18807814a9cefedcd957eaf7f4edb205.npy +02924116-41bfef394b803a9044f19502064e0a74.npy +04379243-971939c687f63b9eca76c527f185435c.npy +03001627-def03f645b3fbd665bb93149cc0adf0.npy +02958343-b15c72a5ce982b9ddc90bfc1d450ece8.npy +02876657-d3eea69d9d58401c76c2a9de5c96f76.npy +04256520-5aed18ebaa1360229d51a07a5989d077.npy +03691459-77f5a7479859ef79d97a4c09acdc158a.npy +04379243-c68ee4070eb551c84e71b4762a7e566.npy +04379243-66a3fb3a480c2b9e7b22e9efea2f565.npy +04379243-81fc73cf3796dc2ce14c803a60e383.npy +02828884-78585e161ee3e39acb2a965e75be701c.npy +02924116-fa9612f559f3cf53349a6083f1797025.npy +04379243-9b0a6771ddd952a036b0f2a1430e993a.npy +04530566-861048281f4507b45935a8bd0d2fe1f3.npy +02691156-333278f95a359498e768735f27170bc4.npy +04090263-8aff17e0ba5d749f6b2c8bb96250e4a0.npy +02933112-25ed0233d292deb413cf34dbb0dd8875.npy +02992529-922380f231a342cf388f6c7a9d3e1552.npy +04379243-daa7a962994ff710d19f6764502e1046.npy +02958343-70b8730b003c345159139efcde1fedcb.npy +03046257-375bdb86278eed0cafd37229d372aba7.npy +03642806-cacb3a7908b0bde4478a2ccf0e4d84b2.npy +04468005-ee72e852bf1d95c875302cecd0dc2ac.npy +04090263-7f7efcc097dd76ac8c0007e5a8235290.npy +02828884-738f4ce6e01920e72e558e0eb05b86a4.npy +04379243-819676c81556d0d09ed5db740d23ca46.npy +02691156-427240c0fde25a90e6901f9a264cdbc0.npy +02992529-1f565ab552dc89727e51366b0cf7747.npy +02691156-cc23974115a8de15d13ef00338ba8c52.npy +02691156-b43ccbfd5e1d88bd780469afe5e05eb1.npy +04256520-e29fbd1feb9659dc843ead12644a79bb.npy +03991062-15bde6780bccf1cbcd075f7b8318eff8.npy +03001627-1bcd9c3fe6c9087e593ebeeedbff73b.npy +02691156-3fc25f2cd192f7d262b600da24e0965.npy +04379243-f67d8afd7611fcdb45e0993de2a122d7.npy +04379243-6e29806cb341576ae9deec47d8412ee.npy +03636649-cbe4301ef1418bd8b036d6b8e2579386.npy +02828884-738e4ec61f69606bad5067eac75a07f7.npy +04379243-d07b44f271ded6a9c211251dafe812c1.npy +03001627-3ede0a86fff6f79632284c722d808bec.npy +02958343-9d2b7938d426633b28044fe9244db50a.npy +02924116-8757c29fd2ad648c193d7855ecfc1bd3.npy +04090263-bfd8b5214e4a174d589c07868201b17e.npy +03691459-c8b4a5d2588868a7a1dc1681ada9b3cd.npy +02958343-43a723b6845f6f90b1eebe42821a51d7.npy +03211117-700dca3a410b751551d078b27da66690.npy +02828884-b179e972d13ffde523c05fdd9cf000c0.npy +04379243-6a3bc6b44ba974b69c0c9824ccd078be.npy +03261776-1757fe64e76a9630fc176230c2f2d294.npy +04530566-fa18b7197a462d9b87c4e42a13b47711.npy +02691156-e5a7a353d5fa8df844b2fa2cac0778f5.npy +03991062-f509d1cbbe3e5bc7e88c1d6fc3580355.npy +04468005-33bc37e13333430552470de2774d6099.npy +03001627-e2dbe84030167f1ca5aad165050e534c.npy +04256520-483518216d58f2581b7dbdf53d301715.npy +02924116-7ee6884bb0bbf9e352470de2774d6099.npy +04379243-2c3a4ab3efbf12d74ef530b007e93f59.npy +02933112-cdc3762d2846133adc26ec30fe28341a.npy +02691156-a1017765200c668c6ecd5ddc73f570a8.npy +02958343-4c427f14f21f128ffa38d2670ab5169c.npy +04401088-983b362e25c008b1b36be681f90b79af.npy +03636649-5d91d6f6fae09234275d003e423c59ba.npy +02691156-bb8c3e64da2788b98057ec2068d8fa1.npy +04379243-f408befab026f5001e5e1a907376dffc.npy +04379243-6722714a020f703451c4deb11af7079e.npy +04379243-81e991df9ff8b970a2ab2154e681ce15.npy +02958343-2c304c54a6141d214ff3c6764341833.npy +03001627-90f124aab57c518eb866f4a999c2a978.npy +02958343-69c6599f55cbe2474eb766e5a46fceab.npy +03636649-51561910f274337c452b6f7f8fb75eae.npy +02871439-c11fb13ea583b02ef6f1a9781d483f33.npy +03790512-a9c432d1dc4034762a45a87054fa7272.npy +02808440-36a1ff10474e401ae440cc76354dcf85.npy +04379243-19d04a424a82894e641aac62064f7645.npy +02691156-3693696a7d11f2a866cf1b4a8fc3914e.npy +03001627-40db46d8496af369c605aeab73103431.npy +03001627-9af15c2a94ef79844aebea9384ce74e0.npy +03948459-db298a7cb95aea676ecdf20adf3e54ce.npy +02933112-8af204f53bc871a2c05575120a46cd3b.npy +03211117-ad0edcc0855d1218dab76ad0db1f9537.npy +02933112-c9576be714b6cf2d219113a79b8c092d.npy +02933112-5bfc4cb92e9d3b1f79b0363dd1368699.npy +04379243-254cda2719087d58d810b14a81e12eca.npy +02958343-cbe2dc469c47bb80425b2c354eccabaf.npy +03467517-22033c6d7e5a90f193f0194265a9746c.npy +03001627-377fbf95d0d5e9eb90c9244ba8c4eaae.npy +04379243-3af1f6a0d7a8584d719d8721fec72f0c.npy +02958343-808e19aed606f10cf919864ecec729ac.npy +02747177-64976ee2a69d3202956c23e7ddc28c00.npy +02691156-ae8073beb28788809f576466d21c96ff.npy +02958343-df741c5b5cf87b16c85067e81ba6deda.npy +03001627-439418b35f600f4bb10dc0fca58d0b2c.npy +03761084-a193f33f35e42bc473a36a7f4c39198e.npy +04379243-4de159bb2663fa4d58b22e372d13dd2e.npy +03642806-69c1b09e3cd5056d11f9b5b6530d6e16.npy +02691156-1b90541c9d95d65d2b48e2e94b50fd01.npy +03636649-5489ecdeac5c1cfb38bc5dac9ac556bb.npy +04379243-b879ff9d30911558fe2d13a096d8b561.npy +02992529-3921288228020482b305960cf7a7281f.npy +04554684-c2eb080246a97865c4c2cb2195d7bfe5.npy +04090263-149785138bfc9c2011f7dcbb4a32aee5.npy +03046257-9c5997539e0a6309356a0af0abfae2cd.npy +02691156-8c2f2570e178823562b600da24e0965.npy +02691156-e6f0811f15286120cedbd07f4cf21a81.npy +02773838-3edc3bc2ecf58aae40090e51144242ea.npy +03046257-d6242c261709ec5286d51c34f8e7e658.npy +03691459-8b73786c112d262d4852385de47501f6.npy +03636649-dfd06ea82f5a5b324aeb986669a16017.npy +02958343-baa2f488ec67a0a7c66e38c3984e156f.npy +04401088-35dc3f0f2f5fe8d667a434dda72a2c24.npy +04379243-f22dc1d847c5b82f585f699d798e7ecf.npy +04090263-ec372fed4900876350c27b805d1a86be.npy +03624134-390448ff0ec27c20c1abdd9923e0a8d4.npy +04530566-48cfd8b4bc4919e6cbc6ff5546f4ec42.npy +03001627-d50a49368f5d0e7c284432ce2f42f498.npy +04379243-4d1d28d15b19f9101e0e41d96d3d0a78.npy +03636649-ade3cb8149a1fe6dc066b9622c005c53.npy +02933112-583c242abdc4c08e4da5feafe6f1c8fc.npy +03001627-73fee38797aeced4de03ab2a27ba7531.npy +04256520-c81cf82daa56a165271513b292108db.npy +02876657-d851cbc873de1c4d3b6eb309177a6753.npy +03211117-6a759a4b85141936e4157a1ae61981fe.npy +03636649-d2c9d9efe9592eefcc901650bbbbb0b5.npy +04256520-e9ffbfa88c9bf2662f3a69b1a6aa6812.npy +02691156-2a05d684eeb9c1cfae2ca9bb680dd18b.npy +04379243-edcb2dc19b063f8ba8737fcf23389014.npy +02933112-8c7cff4d76ceef7cff900d986c9dc4b4.npy +02691156-827c877ebc70fd01faaf13445ab19dca.npy +04379243-aed5697ff59e3d3035478a6869a3602d.npy +03337140-126974e8219d2fe71fe8e0bfc9ed267.npy +03001627-3309d6cdd3f30ece3eec26c23f5bc80b.npy +02828884-2c183b1b94d94d34ad5067eac75a07f7.npy +03001627-21bfb150cfc23accb01c58badc8bbc39.npy +04379243-f742dcebb1d9ab0cf51f77a6d7299806.npy +04256520-9e0b01fab5d15b768695754f4338760f.npy +04379243-87f355b618f13233d5cb6d178687b980.npy +02958343-1a1dcd236a1e6133860800e6696b8284.npy +03001627-73828d9eba46266c4b2e4a0ad7c25461.npy +02958343-167a645149efed1fdca2ca2624f821d9.npy +04256520-e40e193e6468db644b3c42e318f3affc.npy +02691156-5466493424ca47bbfca1f1143bb6bc17.npy +02958343-c6a7b37a33b5eef728af9bd424dcd6fa.npy +02808440-63c94de548d3536eb362845c6edb57fc.npy +04379243-a53e528827345c7b593ebeeedbff73b.npy +04379243-668deaeb91295739664b3b9b23ddfcbc.npy +04090263-2ad5e27d42573768adfdd35441a4b4ea.npy +03001627-ef03458b97c8775b492d9da2668ec34c.npy +04090263-cbac383f55b031eefe3324230bd9365d.npy +04530566-52f3ad585a3900792de1329cfb242f46.npy +03001627-6d6e634ff34bd350c511e6b9b3b344f3.npy +04090263-d0062058d4eeaafe494dcb92319db1d8.npy +02808440-6af7584c142246a23321831d2245cf06.npy +04401088-3f3770476f094a6f2093f68f248ba9f6.npy +03001627-f3955fc72bd9f91e30e06a011e63236a.npy +04530566-abe4b3c405e1cc67bcd376892ed4f5df.npy +03636649-71491d1e3a4c96412474124825d469e.npy +04401088-76781e8b967f98b5a0eb5a85db887292.npy +04379243-ae2575fb16051c6b668ae11a7db5e82a.npy +02828884-a451f5d4b01cc78856f6fc4b4ce1db04.npy +04530566-c77c30796e80cc291edf59b9c77b0b75.npy +02691156-5e77ccd7794465dacbbcf57b22894cc3.npy +04530566-9c50b10fb651e57fdd93d77eaf89012.npy +03691459-926b6071c45525726d3462e1e02b75d1.npy +04379243-d8fa26d89a3ec264ee1dfc331dd3e94.npy +03593526-4708d67a361201b2ff7e95552a1d6a0e.npy +02958343-817bb8c69e4ac23ec81ddeca50aa3117.npy +04090263-56f810f9af40b569fa57ccfa6a55cc4d.npy +03001627-5c1c5dd72247cb6526428c7519676cd8.npy +02691156-359f69a030d69b3da8fcf7222eacb152.npy +03001627-c8ccac20f5cc12528ebcc1a99d4058f2.npy +03636649-4d6ea3aabaf02bcd29c39f613cc72411.npy +03948459-b2bacf7d683379db2f4c3670d21f5380.npy +03001627-39825fb4341ebd1ccb002c1e2b5fc68b.npy +02808440-b82ff88475f56b66c7bff4dd33a963ab.npy +02691156-24e79ed92be932e19bfb78d2af523ae.npy +03325088-50334e43e1fb8c03c36fb70296e45483.npy +02801938-c1abb91a5a9e2ea36d0c80f3bebb5ec0.npy +03624134-44ac83f91f1c5a3d76dac8bd43cd3e3d.npy +03211117-45c66a24bf0851246e22e2d2f64c8cef.npy +02691156-5b86cf0b988987c9fca1f1143bb6bc17.npy +04379243-e3b7fbed310c2c397c8d78b9aede742.npy +02958343-10716a366de708b8fac96522b26f7fd.npy +03001627-e3394ec3b63fdc255d59dae8d8b300a8.npy +02876657-3ae3a9b74f96fef28fe15648f042f0d9.npy +02880940-292d2dda9923752f3e275dc4ab785b9f.npy +03636649-84f3f1dec806b1df82e8c06333eee87.npy +04004475-f944db0e2716b8bade1e489cf4404f34.npy +02828884-6e77b16c5463bf147756371b6ccc35f2.npy +04256520-f0a02b63e1c84a3fbf7df791578d3fb5.npy +02691156-817add33c6fdd1534d210d9468aedaf2.npy +03001627-5cf7a44b8cd841d01f0ce9df23303cc0.npy +02958343-21e028eacc690c9de13f97dcb961e16.npy +04379243-6a61c9e8ade75fbbc3bd24f986301745.npy +03938244-b5cb58fb099204fea5c423249b53dbc4.npy +02933112-3bb0b093c66b1af37a0a46ab3b36f780.npy +03001627-6829ec525eab85671f2351826b1ffa67.npy +03790512-b1f2ea1859ae2aabe4d4c489303b7b1c.npy +04379243-c15e74a91f0b59d533f68dc899e13f.npy +02828884-45c49b9d7cf74ed261477e162a5a4fa4.npy +03642806-2dbabd43fdc9e21ffae724b4e4a1ff51.npy +02691156-e5bb559c00276ad354eba1f1b35fb0c1.npy +02691156-486f1238321ffd2825eb6beb311c44e1.npy +02691156-7df1ad6363410383f3cc56bc9bfcde3.npy +03001627-55fc24bb7f0cab50a24ad2a1ad4f7142.npy +04401088-68082af238b7973aa4d4dcdfc6fd3059.npy +02871439-e4a1c757cc0564f5ca3d3aba150597ee.npy +03001627-d8592dc28b9f0afa387379bbd607d69e.npy +04379243-1e31a474b6867a7dee32a260ef9debf1.npy +04379243-2ef012ddcf1cca54f51f77a6d7299806.npy +02958343-fdf2a756a86b2946c427f8508e3d634b.npy +02880940-5e2c558555092b706e30831c34845769.npy +02958343-ba0fa0e807fd275e0445fc6d980dd5c.npy +03691459-e9723b5243412b462a8eeb2a1f362462.npy +02958343-b72355cdbf1127f4becf71e2e014ff6f.npy +03001627-bc78aefe3bbceb4617b431cae0dd70ed.npy +04379243-a42ad074c9b1bf2467dc358060e3c47b.npy +03691459-a76f63c6b3702a4981c9b20aad15512.npy +03928116-1717a1704e85103240257030127f8974.npy +03001627-bbe36f91f3f0de06fbbc7c456d85ce59.npy +02691156-99b2ee98a16b3c0b1338b1079208569a.npy +04468005-831d42f28813d72ed3e657703ccaf9a5.npy +03001627-b541d3afd111d86f265d8abf3d2f9c3.npy +02933112-1055dc4f3f2079f7e6c5cd45aa112726.npy +04468005-aaa3e125e77e4d6e5f72adf4b0bfab9.npy +04379243-fe5e1df0653804d6ce4670b160b81e9.npy +03624134-508ca8fa00e0cbb3e168961dc7b88f65.npy +04379243-45e24015d08d65eb8d861be5b561accd.npy +04256520-c460cbeabad41fae963cdf8b01c64c16.npy +03001627-94cc9d6473258381171b03ec6def09f6.npy +04379243-8e3bfa092e83c28d55f46d55537192b6.npy +03001627-871243bc93615a758df4f3f615062e0.npy +02691156-d51bd83c27fc3167ba4ae55719e5e195.npy +03001627-8ff4ba87d700054546992ce9fde1b2c2.npy +02933112-d6724f5b2761dd49ffd5817f210f277d.npy +02691156-aeaa3ef74dc4c60c95175320d65fc89b.npy +02808440-65b424795fe6d071ce163f4a7838826d.npy +04256520-7ca57c98a3557774f251828d7c328331.npy +03001627-b8ca8a0c021d152887bcae7a654cc37.npy +04379243-4da9a56cce188c838aaae3d020f5ddf8.npy +02871439-3edaff50f5355da2666ec9bdd91ab5f1.npy +04256520-b233a919f5d2f6ac2ad490d4d7fae486.npy +04379243-a82406382a5d563099e8bf807e902261.npy +02958343-bd6eb1dc7d16372651a95aaa6caba1d3.npy +04379243-a62114bf11affdb1139408582c8ed98.npy +02958343-402d1624e1c28422383a5be3771c595c.npy +03001627-19c01531fed8ae0b260103f81999a1e1.npy +03691459-b8cf1ee73b068390205b075c6f63f661.npy +04468005-826a31947264bb9abb8a744d2911bf5.npy +02828884-77c25a03784c8ea4d4d8765e3910f617.npy +03001627-cb8f3b4355d891514a87d579b680d4d6.npy +03001627-ac041c720dc66c06d1c83bc8b134e4d8.npy +04401088-aa833540c3f2d77e2915acf4d1de24fe.npy +03001627-fb4e388b57e36e7ceca29403b7226aa1.npy +04256520-b5fcd21b70bddb3fbd16d4490a10a752.npy +03001627-9ddec02fc7a03c19a8699b6183baa203.npy +04379243-2275823b40c3e669be2020f4ae1ea66.npy +03636649-1a44dd6ee873d443da13974b3533fb59.npy +03636649-1728c555de071aad3ea96ac97db63fa8.npy +03636649-609dfe9367c0e64e2b520984c067934c.npy +03593526-3986f7e461d3239ed8a9aa07aad9b484.npy +03046257-be4745a1ccd316a914e970d26b98a862.npy +04379243-4dbea9b679493c3c31ec4caf9b70d4ed.npy +03642806-97be95bc027c84da5a7ade0e7a3afdc8.npy +04401088-8a26be623e40850a203d19a168d29f04.npy +02747177-f249876997cf4fc550da8b99982a3057.npy +03046257-c5fba67f2cd5797e4d46ab71b147ac5a.npy +02942699-46c09085e451de8fc3c192db90697d8c.npy +03797390-6e884701bfddd1f71e1138649f4c219.npy +02808440-f8df3a70da926ff2d53f422837597b30.npy +04379243-d3a8019633567d71b20716e5484f7807.npy +02691156-1e155559446469112e690fa6dfd5d610.npy +02924116-6a9fbc6a3b301736191c3762b497eca9.npy +03928116-423d14787208578580ff80bf789cd.npy +03001627-277fb4da6bea894c19fb4103277a6b93.npy +04530566-f10162679968fb0d8f21fab201b7ef8d.npy +02992529-5ec85395159a335221844676433a0aca.npy +04330267-b296fbfbbe5dccf09c12d6260da9ac2b.npy +02691156-bdfa5ff6aefd3fb8a57854d2ce086d65.npy +02808440-77c08eaf01312160a967d8a8714fbc16.npy +03948459-3b4def7c9d82c19b4cdad9a5bf52dd5.npy +03593526-24d09682cc8ead67191c3762b497eca9.npy +03001627-7aad83423b294c59f4b35f4029eb1ecf.npy +04256520-1d9a26feeba782e3f91663a74ccd2338.npy +04090263-3af4f08a6dedbd491703868bb196594b.npy +03001627-53f01d977de993442ea98d69e91ba870.npy +04256520-75d52bdc003e828af2ae88c7a945acd.npy +02871439-1b3090bfb11cf834f06824a9291300d4.npy +02691156-70ed0fe305145f60e53236e6f2fbeb94.npy +04379243-9cd3cd9e93ac389e82db9fca4b68095.npy +04090263-bc79d0cc0c27731a3a04e41b7ea7de8d.npy +03467517-b83a81b2476ec59e59610f6f40382499.npy +03593526-2ebd0fb6ed39fcaeb72e05c63385c6b5.npy +04090263-fa4dfabf8e55704532967a44e902e4c2.npy +02808440-198f8c170347741c54d7082b34825ef0.npy +02691156-b4575e5e6161fd497b164268a44f7712.npy +04379243-b47d8874381c5a03a561edf54b47b109.npy +02691156-fbc429365ab7136be1a9c234926c21e2.npy +03001627-b7012b9baf6a71526cff9b44fdf0517e.npy +03636649-d2d76338428129f62ffd6bbc7610ab0.npy +04379243-6558819685f96577c0f947750540fb22.npy +02691156-5d0d3f54c5d9dd386a1aee7416e39fad.npy +02691156-ebf8011ea1f4b4190b1d6deb98feec6.npy +02958343-9025ac13eac31cccf5cb3ca022cf045c.npy +03001627-fde328d91eee1480fc0035da39bd5e1.npy +04379243-70500798fb5d593be76bc197b3a3ffc0.npy +03046257-3ef61322360370ad81cb5f482735cd59.npy +03636649-380d313b3c277f5e1735ea0e092a805a.npy +02876657-632a0bd7869cb763780bbc8616cb15f8.npy +04379243-bc33b97457ce7a0a569537f38fcb7202.npy +02828884-17b7a0e3c70dbc3d90a6b1b2b5522960.npy +03211117-16e6d2d5b895f04dd3e94baac7a5a368.npy +04379243-3c9c9adaebd66ebc5fceaa39a8353bde.npy +02691156-63dda61ab3ccc4304a3b534252984039.npy +03001627-96c0ecd1ef80e818c8687ff9b0b4e4ac.npy +03636649-229b7e36459a9857ef3a2c64cef919d0.npy +02691156-36ce6d61721805abbf3143b1cb6076a.npy +03001627-b5b0a880ff4e26c1a48e53188865c070.npy +03211117-ec77fd7cf6e4810ea0a7b8ecc42036d5.npy +03001627-5eb42c663aa7c8afb05550de345b6d0a.npy +03001627-51591397480eecccf58894a68fdb6cca.npy +02958343-2861ac374a2ea7f997692eea6221681c.npy +04256520-5f50fabf8c2012034d4134b9987a1946.npy +02828884-5ed9651c928575aab719144d1cd30cfc.npy +03691459-2dbb22fe2a25064a7e95eb283a46224.npy +04379243-c93685c8343e995d760858b697ef756f.npy +03636649-a26918d26e74fcb796433fd91744c67a.npy +04379243-a99b37edfd721010bc7eb7ec22211551.npy +03636649-66a7a9a417660413e2364c65f912dcd4.npy +03467517-740e196e2046c18c352e5d4d2615db5b.npy +04401088-396fba35f02a9cc9bc1f690a77fffa14.npy +03001627-1d6f4020cab4ec1962d6a66a1a314d66.npy +04256520-9ed01e198c9d70a5df6cfab91d65bb91.npy +04530566-bad5505a49b50dc8b89145155e320b60.npy +03991062-c53bab9d7a20250d6a74b20a76e8ee44.npy +03467517-fc49acc3617915075756f5593365c94.npy +04379243-b0abbb1a540e4b3431540522caac8407.npy +02747177-ae33867e3c5e1703f155d75bbf62b80.npy +04379243-34bbe284f7499df071a782a4379556c7.npy +04330267-f093b08c4997bf631b3e6b75a323070.npy +04379243-631c8be7f3559e4e5691f959a7121ab2.npy +03001627-f979d2ead3517a67f20b781026d21763.npy +02808440-2bbad1610128749e1c17aef130ed6213.npy +04379243-45d1e19ee0b79df377e131ed5f0fcc86.npy +03211117-fab433a56c7734aa16eb1b6d0ba9133c.npy +03636649-353224cca3fc3ea6e5da257192cf051.npy +02924116-471005e286f5626b6eda31c44364df9f.npy +02828884-44c720c5edf8942798cfd47a860803c5.npy +02691156-45251b4f76c9a840139336f03eb955d2.npy +03928116-7cd35ab229decb47c05575120a46cd3b.npy +03001627-818c483496ce96745eea3e3d89293379.npy +04090263-2c2abe6a7d754a95c79f92df566f8c6b.npy +03001627-951f1376751fc7294b87db09ac4cfa73.npy +04090263-7c31ae88ca4faa649a2ee232a197081e.npy +04090263-7d03cdedf8e023728d00a96649d5cda6.npy +04379243-f0abcd11d8987f7fbeedb4c8fd29e2d1.npy +04090263-f3ffbc00ec1a1aa7ff5653e278e7cd2e.npy +02933112-e72235ca5b0f9b5de485c93908cf58c1.npy +04379243-6f2ffe8c014a6a458af30108ea9ccb6c.npy +04379243-5fef79348f4bc7b8c710d14956729baa.npy +03001627-74f246c1f7633eb31d1a08d58541ab5.npy +04090263-1bcf4a290a2fb6d288be2a30dd556a09.npy +03001627-4dff2fded7130c631a8db2c23945f1fa.npy +04256520-efddbcc9852c0584e235eb1ec8984f53.npy +02818832-c2b65540d51fada22bfa21768064df9c.npy +04530566-a7b07a2aad642f3f18b731fab8bc3743.npy +04379243-d1ecfd2ca0baa6ad47efcaa87d68903f.npy +04004475-18306958742f8bfbab0b172d4dea80cd.npy +04330267-993d687908792787672e57a20276f6e9.npy +03467517-1ae3b398cea3823b49c212147ab9c105.npy +04099429-d68e08b2be825d1946f4fa69a8f7f711.npy +02924116-5b69ff9c8fa61143973f659238edf3c3.npy +03691459-999e0646b798f67a5a60f8212273313d.npy +03001627-c8df724ce6f12ca2d86a257784298546.npy +02958343-8824c06f737f2888e35db9103756ad5.npy +04460130-3735b272459f1b15db439ec9067ff33f.npy +02828884-a5befb3443b070f8d2b12aa6a0f050b3.npy +02924116-29e5a19b6acef3113a06539f92e15e9e.npy +04379243-b3c5ef225f841cb59725f8348364f5a8.npy +02828884-110d24908bd4f49b93d3c9c269b9b9e3.npy +02924116-c2640c82f7bf960152470de2774d6099.npy +04379243-592420fc90be625a8b83086412477462.npy +02958343-df34c25a1e1abe9428044fe9244db50a.npy +04256520-c23747cbba5d5f9edbb047330001d95.npy +03991062-92ca0eac025afb5a5d8d4d8a3cf8b294.npy +03337140-a25ab4cc7a9df73a4c3aee8e9d3a6ffa.npy +03337140-bfb230a906645dd14c3aee8e9d3a6ffa.npy +03467517-6734fc1b08d9572d372fd8fa16ad068d.npy +04379243-77b60e760e8186bfee18bc48b60b36b7.npy +03001627-a18a82b239fc07cf433619555ecca8aa.npy +03636649-28d35fb9035fcbfffd5c9a0fa28996b4.npy +03001627-e5b0325d624a692467d783b4714d4324.npy +02992529-b18f0d53dd3db1999410a04d09c14d1a.npy +03636649-a711c673d5b6a4b350075206bc274050.npy +03001627-387600bd541f7b502d7ee37bd88bacc0.npy +04379243-7178d8a2f91a9e1c713656cb7b79f97c.npy +03001627-9a8bab7a07a869d1ac822f8036859e60.npy +02691156-ed1d51ac367d0fa5f830b2dc9bf63133.npy +03325088-6ca769c3a4429e4150da8b99982a3057.npy +04530566-7703ba29545cc381acf9e4b0d73d2434.npy +04256520-559019119818194931df860464c5f16c.npy +03513137-37f55552b517eceb501db4f27570eeec.npy +02876657-dd686080a4d1cac8e85013a1e4383bdd.npy +02691156-743670f7f3a8042e6ad6a28101cd3ecd.npy +03211117-d965c9192e2ef568d36eadf9dfcb1300.npy +03001627-2f296d487ade29fe770bec7a2461d9a3.npy +04004475-4475cadbae94638fc4ad1ac611778322.npy +02958343-209c79dbd4f7ad944ee32d005103a21a.npy +03001627-da335ee36e78e24988dcbe86402c7c15.npy +02933112-60d7e8aba1f692a8c2185cc0ca1b306b.npy +04530566-6834c4f307753dd1427c8de062c1497a.npy +03624134-5c6c271d248294e0e0b68f51ad1c0011.npy +02808440-d446c087555f507b412deb0d2b0f3dcd.npy +04379243-85e359daf7e56d6a94ec70278e148371.npy +02828884-19399a9aac37442359cbde03ded257fd.npy +02828884-c06a17f2c79d01949c8a0ee9a6d1d4b2.npy +02691156-78edc61edc8835b5bc0909d98a1ff2b4.npy +04379243-d2f884d5637c979214c06184923f6962.npy +03001627-daabf4a2afac24c97eaf5bcc4a8beb17.npy +02958343-abb2cf2ed0d8679e9cace18601e5d3b5.npy +04530566-10a57262251f03b28b27d51d442cae1c.npy +03001627-564f5f96bc718194166420d06689fcf.npy +02828884-18000ed6034007caf4fb4dee5181bee.npy +04379243-e469e53c260a5ca47d2695833906aa3a.npy +03991062-a19b10e509f6ebb758c88d30f502a452.npy +03642806-36bf7cd2652ccf48dd42bb2503ef78ef.npy +03636649-89fb4886797187e7f63bf7d908efc575.npy +03001627-bc4d7324d2438885f4b35f4029eb1ecf.npy +03001627-eb04d1bffae6038c4c7384dbb75cab0d.npy +02808440-b811317b75610314f7bcd99767bf77f4.npy +02933112-a49eec529b5c44eaac00fd1150223027.npy +02933112-aca4241639feb8f0921dd903dd0b8b17.npy +02958343-e9c2c31da871e0d6c203986ffbbb5e4a.npy +02691156-552871abb864d06d35fc197bbabcd5bd.npy +02691156-4508864390ae424d663e50e76f163b3.npy +04379243-7207fb41b7f9a0669223fc014b68160f.npy +03928116-a2dcfb6f77a72be8a2b299c40b68f70c.npy +02958343-2f7cf2c2d170e3c936f37029483b3e41.npy +04379243-840ab934a623e29d4253be890e153964.npy +02958343-8c710a2319c1a5683f86d898378e5d97.npy +02942699-d5624d29159a4cdb7e1c85c5c15da7fb.npy +03001627-3aa81c6d6d7d7d66c08256cf85537e.npy +04379243-2764d2783f999fd0214a15a5a42c49c0.npy +03991062-d4b9e1085ebd4f226bc258c0f0234be0.npy +04379243-4b6276df295b3967601104cd2d998272.npy +04379243-f797885ebb3b15fbf417851aee42d8cd.npy +03211117-7c16ddd8f3d099dade6274736c2a6b68.npy +02924116-424d411c37fd30384f224d639c7b7c72.npy +03337140-abe41b86df0dcd5a3da04ac9f7df60de.npy +04256520-dd36ab979c4ff93038dc42f802aebe31.npy +02958343-90902c72c195d3ce8256c497dfca7529.npy +02958343-c3e49f8c560ccc216108f064aff2426d.npy +04379243-c74ea23fce212291943df36e40894fd9.npy +04090263-8650b7b809ea14be6314c3b6a3a65519.npy +04090263-fcc1826e28e6f512b9e600da283b7f26.npy +03948459-b4341b7259f66d529f433921788191f3.npy +02954340-48052012e0500fb5a52821bf1aa3b19a.npy +02828884-a393945aad7a2cad5067eac75a07f7.npy +02958343-215da971831129bf63ee8a34069b7c5.npy +02691156-448b45ac858784e9b020e22bd5fe2e73.npy +04379243-3645a90e02d16f0584aa8fa8b66ba302.npy +02808440-dd544ed9e15f9a0e3321831d2245cf06.npy +03710193-54cb538cd36a060bf145bef7cd14676b.npy +03325088-8e8173ea18dec2c8fdbe2bf897d8a820.npy +02828884-5870d0ad92321f8cad5067eac75a07f7.npy +03691459-b18b9f87117cbc94c274436d9bc22f7d.npy +03001627-d20de927fd1b15ef104c86562c321749.npy +03211117-70c042c5761072bda543b6c4e1dad166.npy +02992529-6e183cdeba6b83b3805062aaa3bb7665.npy +02880940-36ca3b684dbb9c159599371049c32d38.npy +03636649-9a0fc544ab771054b45df535caecae62.npy +02828884-76463803e8be994e6716685cf333d2c1.npy +04379243-6da3c94506cd3e114a163d2b227b320.npy +04530566-abb6fe97ba97e1f84e3f9dc2fe7cec4a.npy +03211117-e3201a9e4ac0a8a9e255d96ab3987a.npy +04379243-197393cdb4c836a713c18ca5acf69765.npy +02871439-2c86a69902c2df5f6831079c2c481dd3.npy +04379243-7ee773e031400d09b4fc0a2b20c3cddd.npy +03001627-b24ed89d85b74771216fff6094e6695c.npy +02958343-1dbb02c20bb93af81c1b3b2ed8d13bf8.npy +02958343-ef2406c5f2f280f366cdbd877f6ab1ad.npy +04379243-48ce2cbc14f391e7d7262b1b986920e7.npy +04256520-4c0aeda1ff524383ce4f58889c7849e3.npy +02808440-45b3975a2935d2fe3321831d2245cf06.npy +02828884-9a2d51fbd6b58048c955e5ed03ef3a2f.npy +02691156-d605a53c0917acada80799ffaf21ea7d.npy +04379243-cb374c698a5339f3d6fab6a6a552905a.npy +04401088-f18dbf3cbc7d3822de764ca2f457c756.npy +02958343-9a63aef0a99f7bfab2c2809513f396e.npy +02828884-a9aa868b77c3769ba873941124e3356f.npy +03001627-3612bf5942858c5976ccfcabdd2d6349.npy +04530566-18642f35971d1bec86c51c3aa93bf029.npy +04256520-f85f8e6cefe5aaba4b3c42e318f3affc.npy +04090263-b63023bf7697571912b38b1d99376c0b.npy +04256520-2de1b39fe6dd601f1e03b4418ed1a4f3.npy +04379243-6ac583c624b9b76b9d6741c36fd1cd2b.npy +03001627-94ceeee26248a275e8e2378aa23e4253.npy +04379243-b9bbe91d581fbedac8ba7a179c3a36e0.npy +04530566-39ee3af7e07310f494daa4565dd30535.npy +04401088-33db5943a8942fdfd998bbb6a9d203d8.npy +04530566-cb89a617351ec4c4eb2c303a0e0d287b.npy +02818832-90e5b3c4b760b0b5c5df8e3012a84650.npy +03325088-e53c6ac72d0f1bc13321831d2245cf06.npy +04379243-77e24ba0c290ac3eff87aeb86717e73.npy +02691156-2087ba820bd70001243402995adcdc4f.npy +03001627-60d4a780abba84d20c5de2052b8e2de.npy +04256520-137589e785a414b38a2d601af174cc3c.npy +02958343-7c768295f93290391d0ca8334e014176.npy +04090263-26829f9c5626be049be47ac7c7e37815.npy +03001627-60b3d70238246b3e408442c6701ebe92.npy +04379243-bc2a117e1c6b9d0da9f547acc5e1dd79.npy +02876657-799397068de1ae1c4587d6a85176d7a0.npy +03761084-b8cf469bc1b42ab64a44340bf227e40.npy +02818832-50e6081ee2b47031efc3b1f471c445dd.npy +03636649-b9283738780e29c23a5fb687d9cb4ec7.npy +03636649-40bbb4b123d9df2028c187222995b2b5.npy +04379243-41b492376a6774f9cdaf1a853214fa9f.npy +04379243-869bf2bfa51062c47b8ec2c9a49686dd.npy +03991062-37c60cf073b86328a2c59a4d90e63212.npy +02958343-9ca127580ac4f9712aba37016d02e162.npy +03001627-3fdef0a7606c397331ad067823a3f0ce.npy +02691156-b7b0068ecf75d279afd477f714c68df9.npy +03001627-56262eebe592b085d319c38340319ae4.npy +04401088-ed52bccead5926dfa9fe1734a6086750.npy +04401088-b21610e986fa4c9c7cef36fa43392c52.npy +04379243-13ec1052a32ca23bfd60059ad8523f1a.npy +04256520-49d28b2dbf11e3975e4b35ff1ea95f37.npy +03001627-5c8ea11840795cb5f1783a44a88d6274.npy +02691156-f79fce6480d9276facf77e718d93f3e1.npy +03642806-9f8cc20d6b78fc3f2c545442439c8b8.npy +04256520-272594b65264b90192fe219f5eb82836.npy +04379243-d237260f66c00364dfe9cab879fd37e8.npy +03046257-5a1a2e257a862cabc5d70d7dd4a0dae4.npy +02691156-ff6e377e8e5b3757cc34b900bb2492e.npy +04379243-61ed0adc69dd8eafc3569a6df9a670f2.npy +04090263-2da91be46310f550fa6c79a0c671edcc.npy +04379243-6cf6a546e2ecbffe815a7efb12912.npy +04379243-a9dfd3433837da823fe4267232c5893a.npy +04379243-324f0d772a7b728c36350d50e191a45.npy +04256520-5509f181ac72de8478eec18a8a3356a2.npy +04256520-acaf2b81121c78f6acacae5381781ae4.npy +02828884-a6947bdac4ebc97517b431cae0dd70ed.npy +04379243-e834ef941f7bc9c9e7df9f1005942e3d.npy +04090263-869ba7b568be23521c63053ffe1a64a7.npy +04379243-b14a14cc2f3c38c9e3def9c422df2282.npy +04090263-61064e4a00abaaec589c07868201b17e.npy +02691156-162ed8d0d989f3acc1ccec171a275967.npy +03211117-611a15a623643e12fab31d1a99fa2e.npy +04379243-3aebb428c4f378174078a3e6d5ee40f4.npy +02933112-a234f5b48a26fe1d12de5317fe5b354f.npy +02691156-33c8abb3658f2d4219e06ee1b2e7b1b4.npy +02828884-62ec527e6093cd007a9af08d0375df56.npy +02958343-cded640727157c18c6142312719d87cf.npy +04379243-5ebc9d8f82e8bd9fd3533dfc6ae82761.npy +02933112-ca3c48798200a14050e21024808d3b59.npy +02958343-2cb6de89f5b6e702b626f6a649199824.npy +02958343-98b30f0a29fe2a1ba7fd25564c2e888e.npy +03001627-9d7f79e306288aeac6bcadaedba80eee.npy +04379243-30dd74f09af6b1c2fe5c8ffd0f5eba47.npy +02958343-4eeac6360031021b8141ca5f94f1242d.npy +02691156-de45798ef57fe2d131b4f9e586a6d334.npy +03001627-5eb6ad0960250dddffc127a39b3c57b1.npy +02876657-6ab0ef1973477031ad5067eac75a07f7.npy +03928116-20cda8719140c1dafaf5a63e8f4fada.npy +03001627-502116e5b87d1fbe69e92c4e191537ef.npy +04256520-5fa872fc2e0447fe75fa15ccf4d13b00.npy +04379243-29b70ee8da440240de98d10ab5975b59.npy +02828884-52e921d1e558e6cda19b1c45fadaeb5f.npy +03325088-4af74fd7eaac11a2b7a867e9b35a1295.npy +04379243-98416e9f15b3f80fe76bc197b3a3ffc0.npy +04330267-eff23594cc0aed121b3e6b75a323070.npy +04379243-4ec8d6b5c59f656359357de4ba356705.npy +04379243-bbeb870f0ad9a17af84b0be7f50940eb.npy +03001627-294406eb0453d6a74aad3d2faf99eb1e.npy +03001627-1842797b090ce2ecebc1a7ae7c4c250d.npy +04379243-98b4af37112000d6bbd07219dafd2111.npy +02954340-6cfb76b40fc41da2a6e67635b9d1cee5.npy +03636649-b1ec680145762d1eb784faac204319d9.npy +02808440-a095cdd68d69912b44221bef0fa3c36b.npy +04256520-12aec536f7d558f9342398ca9dc32672.npy +04401088-388415634e1056942ab70120fece57c0.npy +03991062-4224c4923f50229e8cb30b9253efc371.npy +02691156-380e9e8c3ef07372acd7e882b88d2b.npy +02828884-61e3c4fcffab96b9ed98cca8f0ccd5f7.npy +02933112-94bb7157062d59a5f51f77a6d7299806.npy +02691156-7631caf6989bd17e4a51f4b900f5eb50.npy +04379243-ac2f8d240e2fd36ce2acfd5544378c96.npy +04379243-400a2dd6c371a2d446de2420e311135b.npy +03001627-cfb40e7b9990da99c2f927df125f5ce4.npy +04090263-ee4cf4706ce605bd37e67c992a0a6e51.npy +02691156-4f0bf26c62bb7c8b7e1c97634acf0214.npy +02933112-c5eb5577e728c4c1ab4753fa80886181.npy +04256520-289e520179ed1e397282872e507d5fff.npy +02933112-bcf7688f64a642e3fb266533561ee98a.npy +03325088-33faed70ef14d4b362845c6edb57fc.npy +04379243-728ec88a2fe37abd4a2f90e76b7328d2.npy +03636649-7b1fef0071908d4bd93768e7b9b1eabf.npy +03467517-72e8c3d93b75d8c888bb86092c911c95.npy +02828884-4790c04ee2586772d0768f88bbc39dbc.npy +02691156-7fec4732aa03b54e7db7c8d619fa260f.npy +02933112-4298f678b53d370dc59350d819542ec7.npy +04256520-1d31309c617d32b51652e2e95099f284.npy +02958343-7be86bfa8edd04fdced2b3ef33cc51ac.npy +03211117-d54253b71f017565b441e189e5a85c02.npy +04379243-7d0e1c7c5ef289bf94d582a4a37a8dbb.npy +02828884-f1fe8c6c1f9f28321739c3c7bfb786a5.npy +03001627-b2b359d7ce583ce5ed105888ecf0e97d.npy +04379243-eae36b396f6b5f97664b3b9b23ddfcbc.npy +04379243-bdf183022c888426fdda2d9537f811d4.npy +04090263-608c126f0acb73dd7e338aebf530613c.npy +04379243-284831cd2c3c4641668ae11a7db5e82a.npy +03624134-e688f0697b9a970c6402b8f491cd92c7.npy +03513137-e0b4672fbbae71a49617e37e5a669a71.npy +03001627-a33e91aea2b278e0c5ee4aa82bd336ce.npy +03759954-5e0d940640c1808a4fdb7f619836e43d.npy +03001627-5a871d6613216ecebda72093f9b5aa73.npy +02808440-878767d96ae00079a1ad4813ad2137e.npy +03325088-4ce9747bda12fba68616812464c86290.npy +03211117-89f3262d8e06acfdeb0ce5843fe6b264.npy +04379243-daaa70967da2bad4e80de6380bdd8c21.npy +03636649-e5ff9311bee487f5ca4aaad7dc0e3a16.npy +04401088-158f605ffbe6b036436916a86a90ed7.npy +02691156-63ee010741ba665c35fc197bbabcd5bd.npy +03761084-ee586138bb142e67178e7d331e641179.npy +04379243-ef4bc194041cb83759b7deb32c0c31a.npy +03991062-9dab2204d0e6a31114038d588fd1342f.npy +02691156-b95510fb88096a208fc2d09ac4aa4e78.npy +04090263-840eba6d395c192c40938a189bac3257.npy +04401088-e9352850a60bbee4975308da62ab2e39.npy +03001627-8c4ffe44076e9d4a15f62f0f1afbe530.npy +03046257-cb73394b6bf07fd61b17743c18fb63dc.npy +02808440-a57f7ca2555de207a6ebaf0d97eea08.npy +03691459-d8023575778364b035cd53a06b1d2317.npy +02828884-35948e4d06a9b07e8ba8ff316aec8d3d.npy +04090263-8fca9344f9583ed9f433921788191f3.npy +02958343-bc86f6cdcac3e6a5afe1d4530f4c6e24.npy +04530566-268110d849a3aafdec2f14500e179e92.npy +03001627-2ed3b981a9827fb0392642605da2a1e7.npy +02958343-f9584908ada1c74bc2b93f7e42be3ac1.npy +02958343-6ca41d6e48d8cda0e7c0978ffb411d3f.npy +04530566-abb16b391d1634a84de203ef6842ee61.npy +04379243-d40aa82ee8ef7f674e0fb7a6bbb665d.npy +03001627-6419d67905503bf7a09708b19d8be603.npy +03948459-d5be7a5fc72f11498ce08763cba10343.npy +03085013-7e984643df66189454e185afc91dc396.npy +04401088-ae86fa976ddb0f923bb35aa9d5fb636b.npy +03211117-4714a692a7e425285d534b823e951083.npy +03691459-50ab4ba93bb4141320dd2dd4d7d7656c.npy +04379243-1c76a8a55699eb9694605bb30ae47fb2.npy +03636649-fb279afc9faba7ec36d735c5e1c16d13.npy +04379243-244b56d46b9eec86f51f77a6d7299806.npy +04256520-d321d0c149d7762acc8bd7a04c9659f1.npy +02958343-558404e6c17c58997302a5e36ce363de.npy +02933112-b6b378a05bf6982b70c33714b19283df.npy +04401088-5101c0131cdf76d03f9d84f9a87a44e4.npy +04530566-f4f66aef4ae1ca243146aa85e47ab8e1.npy +02924116-9e66732bcbcdc461dd0aaa1eb6128474.npy +02958343-a07227a41b866d26473f10e6caaeca56.npy +02691156-4303c9458a723504d972c9dd75ed77d4.npy +03636649-ca5a19cc0a5f34273b8ea30c1700f67.npy +03001627-ff3ca63c75482c31f51f77a6d7299806.npy +03001627-564b9543fe715f9e1a4047c09ddc83bc.npy +03691459-64b14af80e246549a82acc849eb5e81f.npy +03691459-ef720d2b2de59184e775d184845c9f5f.npy +04401088-1f565ab552dc89727e51366b0cf7747.npy +03636649-85335cc8e6ac212a3834555ce6c51ffe.npy +04225987-99130967461623c37ca71234c2ec5470.npy +04256520-90b1058de189e4589215045784774049.npy +02880940-f2cb15fb793e7fa244057c222118625.npy +02958343-30ad4418703c8cd2f1da888faee23fa4.npy +03001627-4dd8862c73931cafeaf14273fa406ffc.npy +03691459-9c8dd83df9678d3bc33323f64a5f289e.npy +04330267-fc05549add432c08c5f3208c32f3ec87.npy +02691156-a48676cfe44fd9bee40acb87a6be88b3.npy +04379243-8f940fbfffb9b3cfebad4f49b26ec52.npy +03642806-85e029acb2edbd3a86a7e0484f5238e4.npy +02691156-85a62cdab580058925149ab881d5692e.npy +02958343-6af0ad6553d3f42f21f6e2b0f75cf9c4.npy +04530566-a64d2249cbe63b5f9cbca1f73829701e.npy +04379243-f48d32cd065088b6a6551b53c4ec69b3.npy +04379243-8147ebedafb763f21fd3f440755dada6.npy +03046257-408a3303ef2731a48358026595a97ae9.npy +02828884-afa7876470b8b7881d3a1f40308f8b8d.npy +02828884-1d0dae2db37fcb6ab078c101ed808ecf.npy +02828884-3a8490a38cd7f21929bffcef22233b9d.npy +04090263-51dba7756ad837615e561f212b7229f3.npy +03948459-f33f1645e9e35e6ef4de29b99f103946.npy +04530566-5a0ca7a6df97542e69c3c818538357ad.npy +02933112-148638f9a7c72ab55a0e5699b3040a35.npy +02958343-7197ec7776d4e23f10a4b3894aadc04.npy +04256520-536cae63d37ef32265ba78ad9601cf1b.npy +04256520-3a1cb5501dad77f360257b24d454e22f.npy +02691156-c93f76888cf5a14c93421b5e4ff654e0.npy +02871439-96c6507b07129f4ce0e03ec44119b17.npy +03001627-df9eede2969408d0bd2b1bd66a734698.npy +04379243-ada2aa7ccc81977d4ba437934dd25596.npy +03001627-bfe3afaa774eab6e29e17f7efc5a2421.npy +04379243-e77bdb7d3e12d6231eb51344489c49f3.npy +04256520-35da4cce6961e4f2ce9d15b850baf786.npy +03691459-aed97e60cd2802ce7ffb47acd56f396b.npy +02691156-384e72f69e6f24404cb288947cda4a2c.npy +03001627-d72f27e4240bd7d0283b00891f680579.npy +04379243-f8c37aece2b1c730928918e6ee92e0f2.npy +04379243-2475fc0196ea39aea81329004b7398d4.npy +02828884-ff5c5895622d2123aa979e53c1a67c26.npy +03790512-86b6dc954e1ca8e948272812609617e2.npy +03001627-79d7e50715b3b00cc2dd59754f61bab6.npy +02958343-f4498022df553505c35f22936e5aea5c.npy +02933112-3b6042e3f223da66200ec3fc5b3ae5f4.npy +03001627-74625aaed8902197f51f77a6d7299806.npy +04256520-ea49f8fc66df2b1819fb4103277a6b93.npy +02871439-a02dfaa200999ab05e61ef8e2af97499.npy +02958343-18927999d0c5a9687ba2618ede0d52ff.npy +03211117-77f4c991478ad1c26cd5a1d5c8bb85b9.npy +04379243-5e0e607f01cdf9ed93f709c6d6d99cb9.npy +02828884-394563d19e157c126f2e3fcce6bbeeb5.npy +03001627-3ea40a75f22515557dcf230d8b7d162e.npy +03001627-3d9dce1953180fe6f9c9f9697d1ec60.npy +02828884-122a480cfcdd742650c626aa72455dae.npy +02828884-aecc04ab28ca258181dea46b799d4f46.npy +04379243-6ca66a443e651c1423500a5b036df62e.npy +03001627-b1a30ad2706247b53c5f24f851caaab7.npy +03761084-9174b5b1b7306e1edf3a1b0d597ce76e.npy +04379243-a0b11917da240c98391e4d6c585a697a.npy +03593526-bb46957091f2a282cfdfe3f21f42a111.npy +03624134-d5f29a19d7523c8df1f105747d69ebcd.npy +02691156-177ea8d43905b1646ee4da51ee0005c9.npy +02828884-d0fa12d918d97314738e43095496b061.npy +03001627-d04d854533d618fbfebad4f49b26ec52.npy +03636649-e6cd04818644ee6f23acb241f0917910.npy +02828884-161bd345833d982325953d410324c2ee.npy +04379243-b112088ed4afade413b554f4133f4b49.npy +03691459-bbb7275f2a0224eb90146e2a0489a257.npy +02958343-9a806af16e5a102786d01a5629641c74.npy +02958343-3ac08e66bd7da4c35da01f298003d56.npy +03325088-cf9b1dabebb64e20b983088451bda93b.npy +02691156-b6af488133a67825881b4ad693eafd3.npy +02958343-a3d77c6b58ea6e75e4b68d3b17c43658.npy +03001627-453e8c067c8cb5d8f51f77a6d7299806.npy +02691156-9f75309b9744f1b54eefcdc602d4520.npy +02958343-f238821689b42db5d95840a0da458be0.npy +04379243-d1a80144a7efe02e585ed17f54616d23.npy +03001627-629117f474a4bd482d7c2f5a9f32d6bd.npy +02808440-edeee2a9acec49ab44221bef0fa3c36b.npy +02871439-bae48c009fe2a954a4e1718e2dd19866.npy +02958343-41bd68dd23107cc4b0aa56928723eca5.npy +04379243-a1593fbe3a78c7858795000a72749c36.npy +04530566-6b7284918634488da1d10a704f5ebc89.npy +03001627-a4b690e66e3937c88b42931b6e108d6c.npy +02691156-389dd6f9d6730b0e29143caa6b05e24f.npy +03325088-8aebc9a91265216e843f813f752a5e35.npy +03691459-6c71c0791b014bbe7ac477bac77def9.npy +03948459-e534d084d3bc37184d0af51460733e47.npy +04256520-35503a69108fd2a790a1391b3fdfda26.npy +02876657-adace8a468fd575037939c05190e283f.npy +04090263-fd95cf27de958d85827b7030399884a4.npy +04379243-161b5260bcc6f8fc9befe610bb4b9f25.npy +03636649-183e79a892e4294d65666d9a7426c2c8.npy +03636649-38f3a721c7ac21cb8a1a0260fe4e4cb9.npy +04256520-c3cb7d181b205d58a72e1f459869ef30.npy +04379243-38b5da2eb70009d6c045ebb62fca20c6.npy +04256520-548f0e39d6ce5adac036a40816608369.npy +02871439-12766f3b398d1cbd071cf06b697010e.npy +03001627-f239fa77c7b8aa2e81f667e2a25e0619.npy +03001627-d1b2d8868ca506f2a248097aeae36abc.npy +03001627-3853339519aca1bdfcd4910413c446d9.npy +02958343-634b6b50c7e8912f2ce3f1cb66884331.npy +02958343-fe0c5b57b5cf4226bda733a39f84326d.npy +02958343-841a80eb66a079e8e0f3abdce6812423.npy +04530566-2c0b850acd7d11dc428659c2b5124968.npy +04468005-3b4e18c6cfc37f5b4f1cb174d735547a.npy +02691156-fdb107ea7a600f5fe3f3aec01b086ba.npy +02828884-40280757b447eb3cf4fb4dee5181bee.npy +04379243-4517f2aee2482e904da62592caaeb495.npy +03211117-6c56f6063ceb2ba4de1b0b03ca051f02.npy +02691156-e1fbbf2ea1989b49fb2ad20449a93a60.npy +02691156-fe0b8ab916cd568d749f4ec7f5556c32.npy +03948459-1b63a4a6fad149acfa040b4405acb380.npy +04256520-fc786a8d62aad7e7e6942c5426df6055.npy +04379243-8cb6234ed889390df198b94f669bca91.npy +02958343-d67f5ba8950be214aa69dfdc5532bb13.npy +04090263-ae688f34caf5bf7bf1ef0cb5613661a0.npy +04379243-aeb34b796044d26f2705f56670a32884.npy +02691156-c107063f573cbfb3ca8607f540cc62ba.npy +02876657-8d861e4406a9d3258534bca5562e21be.npy +03001627-cbc76d55a04d5b2e1d9a8cea064f5297.npy +04330267-9191df20dc5559a38a68adc64e25938f.npy +02924116-9e117c48527ec9b741cefd10ce5d6cc0.npy +04256520-588556b08760e93b928c76b41dda6e10.npy +04401088-5deb3e8911dbef1adce6ba04fb42df.npy +04379243-c14e9980452c9411aaa05ac4e55dbacc.npy +02933112-41d9c4bc97447c4530ed3cf7f7e32c4a.npy +02876657-af4ff1c4a94383e9ca017e2245ec1dae.npy +03642806-f00ec45425ee33fe18363ee01bdc990.npy +04379243-32a7a2b6974a2e5ccd79ad97258166cb.npy +03001627-e3079223f4714116ad484915511ccff6.npy +03001627-483308834b307b75d5f1108744f02f1.npy +02808440-191c2a4444cb562554d7082b34825ef0.npy +03001627-2a3a847a3d4c39c1b17743c18fb63dc.npy +03467517-8d45c79841bf56331108db7cc39bd3b1.npy +02958343-2c08c221f7c6ccdcca92a4cdad802b45.npy +04379243-fb4cfc22ce88e69625d15f7f2ce4065f.npy +02828884-f8651ae6dc32338ff7010d9d85b1eb2b.npy +03691459-6d83986459f72abd4884161c20b458b0.npy +04090263-7c07a31eca316cb83f217b945a063dd2.npy +03001627-257deb231ce652169f2349486c570dd4.npy +04379243-ef3ae300317c571b490ad276cd2af3a4.npy +04379243-1311cade594e030fe497c7dfb96f4c60.npy +04090263-88cb0215d342a49abddd549216d19f7a.npy +02876657-dc687759ea93d1b72cd6cd3dc3fb5dc2.npy +03001627-bd50871647e3712f79121b38af0e3f47.npy +02828884-f70fe48c38bda53282c132e825d0d08f.npy +04379243-5365dead8b3f7d4166ccbd11a6ef0f68.npy +04554684-a9b39195ae8c707474e92060c1aed1a2.npy +04401088-5b826c910108d27a684b810d277e0e9b.npy +04256520-281330718b2988624b3c42e318f3affc.npy +03001627-249b40a630dd751f8023b347a089645c.npy +04379243-62b7145b5920a67aba18ade30e563d37.npy +03001627-9db1302f2fd980cf3cca2657c9d0b9e4.npy +03001627-d97c5945e9449a58737e4e0df09d751.npy +04379243-f878dcc6987a7a8a4719088c8e42c6ab.npy +03001627-e1e3796be1c4313f9a59e20336b93b69.npy +02691156-2fb78c8d2f27598826360e1e29a956c7.npy +04379243-14f18c8b697d79e099e8bf807e902261.npy +02924116-a08a579a7225b564fd952eb662903548.npy +04090263-d7da6065a37b9b42bc352a3301e817d3.npy +03467517-ed68b19f2f34368bc029bcb600cee01.npy +02691156-56c605d0b1bd86a9f417244ad1b14759.npy +03642806-e6b92cc71ad04a775872a8d7ae27b927.npy +04379243-b6758a9b899d540919fb4103277a6b93.npy +04530566-c3119babc97b4cb374f75d9e92dd466.npy +04468005-bfca8640e2b87091bd76ea3609a7cd12.npy +02958343-1cff510c0630c3cc673ddeabdcc8c6e.npy +04379243-5a09bc1430a2918d1f191e8de8001d7d.npy +03211117-e2fab6391d388d1971863f1e1f0d28a4.npy +04379243-8be1ff29a5088b482822b5101b06e070.npy +03991062-5ee97eb2f085db76993afecc2c675915.npy +04379243-177f4749d22ccddbf4ae8c93f4db5e6.npy +02871439-6cb507b4c8931bc51e006d63cfdcac0b.npy +02691156-ce9246d409f1c688bc0909d98a1ff2b4.npy +03636649-c9a0c193805df62accbc9e602dbf6a4a.npy +03001627-d2f844904a5cf31db93d537020ed867c.npy +03001627-850b424d90dbc66f4d68bade576979ab.npy +04379243-f50603a59b5c2ac7650419cd627ce18b.npy +02880940-b4c43b75d951401631f299e87625dbae.npy +04379243-667a88cc3ca1cef8f37af16b2893f1d4.npy +02691156-84d5ab52436c832d36813a9f7d8d3045.npy +04379243-d0b6fa6b908473b05213cec267286d18.npy +03001627-e05172ca06db0781a0a34f494d525bb7.npy +03001627-27fef9fcdec5a001f8f60938be4e769.npy +03207941-7fce8c7fc6ce0364fcd4910413c446d9.npy +03046257-327182214670d929f51f77a6d7299806.npy +02828884-1b78416210cbdcf1b184e775cf66758c.npy +02958343-2cbe6850de4fa5a34a6a7ab072f22d7d.npy +04379243-184f3a06dc5eaa52881e214542763909.npy +04401088-89f17a3563941ba9f2fdbae39bae1eff.npy +03636649-7075ee8d16f012e350a4c7031a41d126.npy +04379243-f875ff7c72fdada820768660cf080d12.npy +03207941-ba66302db9cfa0147286af1ad775d13a.npy +02691156-d63daa9d1fd2ff5d575bf8a4b14be4f4.npy +04554684-25b6e21ae9aa70824657977e55055ba0.npy +02691156-c271badfb6842c882fd5ed7e39258c7.npy +02942699-6ed69b00b4632b6e07718ee10b83e10.npy +02933112-fdf32559c6b7a6643fe047712e43e185.npy +04379243-d0891a7d205203a9beedb4c8fd29e2d1.npy +02958343-891aac401b4a3273afe1d4530f4c6e24.npy +02958343-8577f3f82d5ce3ecc2fe329dd557eb52.npy +04379243-3c12d6e9cef0adaede2627e1e10e2802.npy +04379243-fd7380eb29fafff3742728b30848ed03.npy +04379243-e750a8adb862c9f654f948e69de0f232.npy +02876657-8d27a39b1a33dcf9660045a6e369fc9f.npy +04530566-d35a759e08855e24dfe2d17b28f48786.npy +02691156-5d6334ae2a0dbf70bd46d022fd7d80aa.npy +02958343-d153b871182b8b3df6aa1413413c923.npy +02958343-97119a85ec049e1df59757e1209f2c7.npy +02691156-18d0da47a238945abc0909d98a1ff2b4.npy +03624134-308f294e2fd166f78000bd932f680a79.npy +03948459-706a2ebf066f3cfc8af105e8848bb6ab.npy +02933112-1a2c199d7c8cb7f83d724fd1eb6db6b9.npy +03211117-3c4382b40b0e9400279326882e8430cb.npy +02828884-9c32648f1412d8a6db6e463bda4c63ae.npy +02933112-6ed6e797fbb6f0c9b4979bfe197a8c89.npy +02992529-271bc457eb5f8f4d2bcf2225e929a245.npy +04468005-9ee07849ff9cfec39954eae9164faecb.npy +02924116-c68f0a21d0c6c4018ae96729cd441b.npy +04256520-7e2fb2fd4c604bb1ef6c510e24348d3b.npy +02691156-5f2aa0bc5a7fc2beacf77e718d93f3e1.npy +04256520-4e925afce2f8fcedec9587880f9bd7d8.npy +03691459-98db1220073f905159f43e87f0a59fc.npy +03636649-a9ed31fba7eacd42f51f77a6d7299806.npy +03001627-d8ea454fb35e38887b11ae648ea92233.npy +04401088-5c141e299b50f1139f24fa4acce33c04.npy +03211117-be2018563a5bf1a088fe6ee2419d9481.npy +02691156-687ebd7d2b1e1475459cbe66a12329e7.npy +04468005-cc206ebaaef18bf3d4fec646771c576a.npy +04530566-c21024d97247df5ae922b610a625137b.npy +03001627-7316e49785de77b9630abf945d2f3e0c.npy +04379243-6110d87def4fa88c154c6bbaeb7d331f.npy +03467517-d3eba720791d85401e67b43145c3c515.npy +04379243-ffe02f7b3b421ee96cff9b44fdf0517e.npy +03691459-7cb1aaaca10a8efa8d8155ff8532e190.npy +04379243-cfb7e0b0f44819c5e2f409c9efab99cd.npy +04379243-c8dd6d63b6d82f8399e8bf807e902261.npy +04401088-5f03b8d583798f7fac18d1d66482053f.npy +02958343-63b0fcfb7a1ac7efe8d8cc304201f02.npy +03691459-710c0a8ede7edb6eb31ee294b2971a9.npy +03001627-4855971647f786b642e1bb4fe264125f.npy +03467517-8a68dc60f7ceebfcd3728028781ec3f.npy +04379243-4bf61d3643b7e6ba19342061b16c380c.npy +03211117-15896858de30017d8e75bb5638d14ce9.npy +02691156-f0b22be59432dc8bca8607f540cc62ba.npy +04460130-a739f388def3e027a72b66695a920fe2.npy +03797390-68f4428c0b38ae0e2469963e6d044dfe.npy +04090263-105c9e30b6fc033d96e5f13299458076.npy +03325088-2559df6172ff5b1a840312071e438eeb.npy +04401088-df816deae044cf448e53975c71cdb91.npy +02691156-296c3ee559f87c9354eefcdc602d4520.npy +04379243-3ea2fc7c32abc9f758df8eeaf3dad1c.npy +04256520-5c66c3e86a131bb969c8f7b0ff61e3de.npy +02880940-a5f42bbfddcadf05eeb8d422649e5f2b.npy +04530566-aa0be5a337baedac950c27aa880e8898.npy +04530566-2f4d7a1873384f5a7301f2b895d332ac.npy +03046257-605c9deae76d0f19b9ed8f64c2cdb8b1.npy +02958343-f9cbd331bd475e07dc1fa1f50eb490cc.npy +02691156-98988dc4e5c62dfbc0909d98a1ff2b4.npy +03691459-35815951ccf18e3eb1f6750101befd14.npy +03691459-acf4daa2ed704ef36a27540a4ffd1b08.npy +02691156-ce00bc7519d595c525a407b55f350179.npy +03001627-3baff0f05a4ac225b872c385efc13c74.npy +02958343-65b9b2df0985821463e6a626b8b4d07a.npy +02958343-79f4f7378074d3478e42313717d27982.npy +04379243-1893e7831f8852a2f51fa0238791f5dc.npy +03001627-9795162b409011c2a6fee8e2140acec9.npy +03211117-3531ea4e850159dc43a6722dac94523b.npy +04379243-11ac24d90fbc20bc5d714c9d7df1c4ed.npy +03207941-14877e33095c0595a86b76551c6a3b2b.npy +04090263-40267f5d09bb0c422c4683dd00deec1.npy +02828884-919f90e92283eff8febad4f49b26ec52.npy +02691156-a1784ead19fb7645b6dd6448cb8a70ee.npy +03761084-4bf44e878bc9bc41ccd4500d193ab05f.npy +04401088-93cc80bca9e1812a64a09de5345a6fef.npy +04530566-410b12d445e5deb49588e71e21de9f30.npy +03001627-2a8bb463e116e51de58b00a9dd2403d.npy +04379243-5554b586330150ab6d5ac6b606b81bbd.npy +02958343-78c3bf6ae1bdf75419b43924bf120208.npy +02691156-69a7b9b7265a70f1a9b2becd26dc2fc1.npy +04379243-da9676ff70b2e78a0a7b8ecc42036d5.npy +02958343-93f82393df6d4b7c315a637e839f5286.npy +03211117-2c1e2873955b563920685b5a7e34b501.npy +04379243-c0c836c630cdb4bb664b3b9b23ddfcbc.npy +02933112-11beea78b1d558d4b246c4171f2c393b.npy +03211117-44bf642d0b33752628fdea86734e40fc.npy +04256520-8bd993fc6a605a63ac4c87b0cf5278e7.npy +04379243-fa29ae17ed1482ed8aaae3d020f5ddf8.npy +04225987-b6074c8d74b58d31ef566954f332b813.npy +04256520-c951d9b4f3da0b5519fb4103277a6b93.npy +03001627-51e14c516e45ec3b18ed59365c9648a7.npy +03691459-1e6a6ff6f4168459e5c00598c3e9532c.npy +02992529-2964d10d72ea38cf4857f88b08630a42.npy +04256520-7f0a1abbf748d3b09a91829e64097423.npy +04090263-948d90262559d560886a4efa4119c824.npy +02958343-57f592c3ec49318661c6c61410fc904b.npy +04379243-8dcd27d37c9b8bbad0733ded25052299.npy +04090263-f8aedbd628e010a64033826da8c9e89d.npy +02691156-146533404a778665c93b40751084c22.npy +02691156-987e67ef16969b93663e90eaf6b4ca52.npy +02828884-40cee2893781b47f50f9fc0e2c94dd76.npy +04401088-709a0c498dfa2b32db9f110046803f4f.npy +02691156-7ea57db538494a2fc1ccec171a275967.npy +02691156-480ee59947a01283873ec74c119307b9.npy +04401088-ccf2058300cac188639e45fae4b57d2f.npy +03991062-75afef7dee74151936b0f2a1430e993a.npy +03325088-a0b96fb7f9ac68cab362845c6edb57fc.npy +03001627-917f2800d9fa9fe8c862eec8232fff1e.npy +04379243-f80cce35d167ff9b855931d119219022.npy +02691156-d4d61a35e8b568fb7f1f82f6fc8747b8.npy +04401088-743b747a119307e8e3785a46a5c831bd.npy +03325088-497e448f82ef1ad3321831d2245cf06.npy +02933112-238e8b7747e7a2503c4f66791e25960f.npy +02933112-4c99fa08135a52d04c62bee40dcdc539.npy +02924116-ce961fddcde47dc972a38ac2b8f5cd48.npy +02876657-d1792ebb96fe73ff30612f5c0ef21eb8.npy +04379243-7918d848b37db85ee1495fb833264cc9.npy +02958343-8d78c8489dc927dcb07f27f3519a9cd4.npy +03337140-99b060ca274d8613540291e94bc8ddc3.npy +02876657-b2498accc1c3fe732db3066d0100ee4.npy +03001627-94c8b873c9214a726e18d8b0769ce75d.npy +03691459-7ab21928504c8f5983247f812f2eaa97.npy +03593526-46eb2397e694c01e2b0ee99af125a449.npy +03001627-603351f3a2ae3259f2b931201029bc76.npy +02933112-886031ff2a514f86c59350d819542ec7.npy +03691459-4294d3cc2e413bafe45b40770dd7ed5c.npy +02691156-40d6a54bb4f276afefe0d4e1eba2e3af.npy +04401088-b1feb3020d9380ba4fb324159a14f34e.npy +03001627-99ee0185fa2492859be1712545749b62.npy +04090263-1a2038ee147fc6d434837e2aadd6d77.npy +03691459-3fbf353af74136feb9001bf6cb0603cd.npy +02747177-62d897a92c86cb392ab20b9ffcec9f65.npy +03593526-dfebdbe996e582f453b5e86c4b574a4b.npy +03991062-ea873ee1dabebca4eab56eee78a237c3.npy +02958343-2b075c9c5d85bc779c75e543b21e90a7.npy +04379243-7f52ac1cf8e52a58be46d062a5971723.npy +04379243-cbef425aa02873c0f51f77a6d7299806.npy +03001627-58479a7b7c157865e68f66efebc71317.npy +03991062-d7ec18a98781e5a444175b4dddf5be08.npy +03636649-297d929269bb62da43fdcbcacbbed64c.npy +02691156-f134306ace70df3ac1006ed55bc1a3fc.npy +02958343-75bb1fc144e6d17a6d00e450aa03077c.npy +03211117-d8f4c5160059ef245d79a44cb814180d.npy +02924116-f7f015833b432f60fd856e0e4b7e59c2.npy +02691156-fff513f407e00e85a9ced22d91ad7027.npy +03001627-fbe64bd927721467dff2bb0129eed40f.npy +04256520-7cf34cdf58717ef0826fc8d57346a2e4.npy +03337140-a9e1a1d22b3f9231dc2bad4d8565b716.npy +04379243-8b094873d775f6e21130871dbfe24c18.npy +02992529-e8e9617b4f7247fa3578fcb734a22822.npy +03797390-2037531c43448c3016329cbc378d2a2.npy +03593526-a84361eb6d9f55d99d3d767e1bc88d65.npy +04379243-e1f9b43eda445dc8c862eec8232fff1e.npy +03691459-859ab0a5ce89e271b4607134dafdbd9a.npy +02828884-d3b2e0d1482ead96f4fb4dee5181bee.npy +02843684-42e9aff6647766ed265d1076b4b6c5c.npy +03001627-77c02e92d5628be59db8ad97fd392b59.npy +03001627-bc21c95f766502a78b03575bb54dfd4.npy +03624134-9ca44477e52bf36b5f43099cebc43623.npy +03046257-a91fdf8f83aab0e56e71174964d90e49.npy +04379243-140f12d10c2b7fd5c77467482d6e756.npy +03636649-7b2b1c24a60bcfab2cd2160e449d45ae.npy +02924116-2ef8ecfcff403cc0403492478acd0aac.npy +02691156-bf448fcf33a5349619ba010ddb4974fe.npy +03467517-6c9a9c0e2af9d5b35f713e773d664ec2.npy +03261776-c6dccc2985bfeb7c2b8ed48c6a7daa1d.npy +02958343-df00eb409d4e8fcec07224da8e53476.npy +02828884-8ad9910699d6a21781faebbdea6bd9be.npy +02871439-403a35d06a12b07070048d788a6ab3c0.npy +02691156-65166f18d4ee36a61cac9affde84fd21.npy +02808440-e3cee2a50dcd43bdccd0340812259a39.npy +03948459-820f8b82a945eada1123c3d969d6331f.npy +03211117-385b89320cb3db4b958a493036fc8628.npy +03001627-c394dfc3c8573d1b19fb4103277a6b93.npy +04256520-7a77351c67566e4159a4e5a60d4753a.npy +04379243-1ce87c214e0be0e87dd6aeb162858c12.npy +02958343-dec396fa569fbd20618e9d35559b7aa.npy +02992529-a3c1c9fc390b1bbbb099170e6f5a4af9.npy +04379243-b4c66c291f2c46581c1b3b2ed8d13bf8.npy +03636649-2df829fa60a85466a2f2a5c7a758a47.npy +04090263-e35192fa08101d5db257aa9856dac07f.npy +02958343-db79ceb1bf94fd81851f021b9ed69c58.npy +03636649-78ccf7d2ee6d5e34fcb8d8c6d4df8143.npy +04530566-2615224e88e47ed29e5ca238b1551011.npy +04256520-27d388a77f5b27db48186eab550b0d6e.npy +04530566-490ba339e10c0b7f4de203ef6842ee61.npy +02946921-51f0b5ce9711f63bb15a1cf05bc3d210.npy +04460130-61dfd94f040757892606d242dcfd275a.npy +04379243-62ca9722d848d0d17f74248f969ff9e9.npy +02958343-f934155d32f9ed5b4101e38beb790a92.npy +02747177-d3cab0515bdbf311ad5067eac75a07f7.npy +03001627-3f5fdc05fc572730490ad276cd2af3a4.npy +03691459-d14e6214d7dd4ed62d563c85edb49108.npy +02924116-9e8edbd1e7b79f058b89799e9a2e578c.npy +03001627-4a2b8f9d13afb39f8f1abd08ebea3018.npy +02933112-a256bf234c60a150c226a4421a1fedeb.npy +03636649-3815469d7a7d336ab0a29c51aa6f10ce.npy +03636649-122fb7bfa09c184ca249f8489bc060dd.npy +04468005-82bc9cc9a34fe639e855454b1172ca3.npy +04468005-52b9747ae68db7f3ae4054efdf73ba81.npy +03085013-9d86f895dc2d54c9b09914703fdadd6.npy +03325088-e09fdcf6ca6cc44969f45219d1cec82.npy +02958343-6283a8fcea4976fe47bff85f09fd66b.npy +03046257-36ba88f12840e84bbc3768389c53bfb2.npy +04330267-41292ef7b99473212846c469aaca3af9.npy +04099429-4c553d6096440b7b64b95779c8554990.npy +03691459-7578b2e27851b989a374ee921da07aaa.npy +04401088-7f41f4b186fdf84c7ecaf377af2046d6.npy +04256520-f1241a9c69cf35feb3104e94482ea9ce.npy +02691156-d18592d9615b01bbbc0909d98a1ff2b4.npy +02958343-8a5b15ec0ed8e9aaba44b506f43666fc.npy +04379243-937fba1b3389783684b7bc3f8a9aa55.npy +04256520-8827bca86b63f748b2c9b996c5b9e81e.npy +04530566-cd1d407bf8637a019a6249baee317a57.npy +04379243-dca821b9d2fed090f51f77a6d7299806.npy +04530566-86fafe5bf7013d18248c5646daf6718.npy +04379243-f9ed6c993f7d65e2e5f83d0df19ff934.npy +02843684-fb7402f91e300ead8ac033353d37592a.npy +04379243-10db06b0d15bd4ee72f847ab4bec38ed.npy +04530566-10e10b663a81801148c1c53e2c827229.npy +04256520-1fb52b6bac60286afebad4f49b26ec52.npy +04379243-84a0b93cb41ee6e129cb4c9f87f87751.npy +03636649-587b4419a39cc088ccbc9e602dbf6a4a.npy +04379243-91d5f09b7126c4b9d158bbba9bf9a9e1.npy +02958343-158a95b4da25aa1fa37f3fc191551700.npy +04379243-5aefdd5252fb662df51fa0238791f5dc.npy +03001627-30afd2ef2ed30238aa3d0a2f00b54836.npy +04530566-7bdcc3c9462eed64482170356260f668.npy +02828884-7cf981899878464e2056b4bd5d870b47.npy +03593526-e0af9e8ee2cf2a82813fb41783e5db30.npy +04379243-761a4fba430377171f335cc23d448de8.npy +04401088-bcf3ca7e860d04eaf0fbb92458462640.npy +04460130-166bd86229867093031b562a9def0c1.npy +03636649-5b12386df80fe8b0664b3b9b23ddfcbc.npy +03691459-5daa294dfd41b3c2e01d588c78e60948.npy +02828884-28530ebad05e63d9d9c2d24a3a0c74af.npy +04379243-ec68e1edbb7e9bc7e93cebb6ba9ca43e.npy +03642806-846c5850093a080f54b2a16efa6e7b19.npy +03001627-562fe0ba05c24bdaa52abcb0c06a3598.npy +03001627-7a1515106a9dbd2bae4c6ed7474cdaa3.npy +02871439-c4966c7d5f8aa1216ca79a8390566bbe.npy +02747177-cfb3a57ec847ebefc99e09be54ad23a9.npy +04401088-99fa43c391f71ffd592461222e5fed0.npy +04090263-bc74663ae3ef56508f65605792e3e409.npy +02818832-3378d2b70f083c173f71f25fc2bf23a6.npy +02958343-f2a990659efa05c5452d05118c2bf489.npy +04256520-691785b64177ec582461aedb84ab8436.npy +04379243-de10ce891b1cd33635836c728d324152.npy +03211117-f155df0854fb33a11030e4efcf938b6b.npy +04554684-265d042dcfed6f15c357c21161963e89.npy +02828884-95db80660b4d979f601104cd2d998272.npy +02958343-25378c7370a06c497ef186a2ac298b0c.npy +04401088-4a0cd042d7479d6810bc2436075f6a52.npy +04379243-b2d9065a028e52c7bd1dc9077c6610f5.npy +02691156-b1762428d609674598aeb62a3dfc01d8.npy +04379243-836ddcae13c81d88a58a5ecb2008fd42.npy +02691156-575b8ec48c550f456252573e97057236.npy +03325088-2ae78fcdf7e0bbe0c36fb70296e45483.npy +04401088-854ab60bd57d3d6d2f412e1bfcc51526.npy +03948459-a8aee0ed266811e5cad3066323224194.npy +03337140-cc9f54a7900dadb2f813f0670c9eb744.npy +02828884-d6075b23895c7d0880e85c92fa2351f7.npy +03636649-15332cc15b3de2e7a4ee05a5737b7178.npy +04256520-c6edb435655e832debe45ef6009149dd.npy +04330267-3486e9ea474af3ebe793cc5433bece89.npy +03691459-15fb39da1ab90994a9504db65c138da5.npy +04379243-bd3dddce162f59ead92dd8f41946f1b2.npy +04379243-501f61f01aaa195adcfcef693e7ec696.npy +03001627-47362cb47416904b76e38b52d9aafc11.npy +04379243-f0c5410293e85a695a96bae7b017a6d9.npy +03636649-7b39100755e9578799284d844aba7576.npy +04379243-52c0950979a8572ad42ec7e303174a87.npy +03001627-b8552f663f2a4f4d54e4f80955961143.npy +02691156-5eb91263da1f0bf3e816c75152573ee0.npy +04379243-2b6ce4f0d57ada2ce6a02cdde4c23286.npy +03001627-84f7061e038484492f8cdfb829e0f65d.npy +04379243-8a2598fefd4a81e9c7b11e86284a2e.npy +04379243-797c7f154643169bb07cbf788ba0557c.npy +02958343-a6d494af391a97686436916a86a90ed7.npy +02933112-91ac5c074c7d137762646c8cd54d58b4.npy +03001627-60622d74c0712934a5817f81a1efa3cc.npy +03593526-d4b38a6a694cc2bf55f46d55537192b6.npy +03211117-2979d8814a450f884b8894e5e467986b.npy +04468005-a6379623690fa49f5483aac47b870866.npy +03001627-4206cdb567679c0dd197f67767b32741.npy +04379243-462e8745e766ed9fd4d8765e3910f617.npy +04379243-3c4786ea0997d6bbc0f947750540fb22.npy +04379243-bdd12e21daf8664689940e75c3dc3e7.npy +03636649-a833d2cae8fada7430f6e0ede20c4525.npy +03636649-80eef85b735218b0ab8d22b09768208b.npy +02691156-3826bf5c55ee469cec4dff11e684b695.npy +02958343-83c31a4085063873dc2afbe43bc71afa.npy +03624134-c68e65d16ebb046b2ee0f9a97b71d505.npy +03001627-2403b6769a03c8a466ab323d8f805a57.npy +04530566-91eda08cecf2e0f1c6cb0dfa2f14f9d4.npy +03636649-930d6656e3df0635fcb8d8c6d4df8143.npy +02942699-fb3b5fae94f7b02a3b269928487f8a4c.npy +02992529-d79b59ea51a9d80c483afc91de6851e4.npy +02691156-a2f0c1bdfe1475bdc1a897657d9a1924.npy +04379243-1cc5bcbad2fdc660d942e529754fbd45.npy +03467517-9f938cb5771d594580cbbabb0edf7284.npy +04090263-54001db75b6071eca7dd22c0aa3913f0.npy +04530566-47adcb0683a3de6cd202a4790115f0c.npy +03001627-e3ada26cde5b4de01186ba196e9dda0b.npy +03797390-4b8b10d03552e0891898dfa8eb8eefff.npy +03001627-d2c465e85d2e8f1fcea003eff0268278.npy +02691156-fef1c15a5db21b00a67cc8f661e7890a.npy +02958343-88161acf1ef955c5d76439fb95cdd2ed.npy +03636649-8d1178acdd04d633c35131da26f8061a.npy +04379243-a0379565daf4b6e6579cea75b38cb7ce.npy +04401088-24f3752312dccca3e23b34f33128879b.npy +03691459-2f7b5ea50c09d928b23f3e90fedcfa3.npy +04379243-f2087cbd26a910355c16106acf3e4b14.npy +04379243-c04b363fd824528bd42b9650f19dd425.npy +04256520-897e43119c6e4b8710a82b807fbeb8c.npy +03691459-438dba79401818884987b3f5f9a53cef.npy +02933112-9c15e8897adce40c963aff3ec12fdcb.npy +04379243-5ad2333321746a8b3f222a37719e9945.npy +04530566-1849ee33d087288ebf473eeb55ae85d0.npy +03691459-5976630a3b8452617ae81ddf970c0d9c.npy +04090263-35818f16eb3540c0bc6e84bc30e573cd.npy +02958343-dfa6c32dec07727ee9d8921ebe6d5b8e.npy +03636649-c0644ddc5cac342b565ae30b0a8151d8.npy +03001627-96d9944f46bd330979414e04132a8bef.npy +04090263-ee36a8770c74281b52188a7e683f7f4c.npy +03991062-ff08db7c7c1f3e522250bf58700b4d8f.npy +03467517-601e01d49a1daf2c79f4a19b034b33f.npy +03691459-18e1be943fecbad143662aee1fc05d23.npy +03691459-33d61def031dc1ef256097a658bc66b2.npy +04379243-23fc3f07efc7ae4d19fb4103277a6b93.npy +02691156-fbd800d43c5f0d74250cb4f7fcd9ec03.npy +04379243-5fdde770581fa1fcbae326b60581fb7d.npy +02958343-d6390f62d9e036efb1bb46d2556ba67d.npy +02691156-a2661597dd2e8a2eb87697d3904b168b.npy +03325088-bf8ceca3b60295f5b362845c6edb57fc.npy +03001627-2ba108b72aa4995814513156cf2b8d0d.npy +03642806-7a6b074fec1b8b9c810b27ad0ef73ed.npy +03211117-c906b5644fe468a2b61fb7ca6803b7a5.npy +03001627-fcd8163b26250f499fe49e672436bc45.npy +02808440-63c4c61e156c25d23321831d2245cf06.npy +03001627-e92bcd55d36a2b70ea934df7efd260bd.npy +03001627-5e13ddf9fa4ecf53c62f0847fa177f8c.npy +02958343-c46a940147e6da66ca92a4cdad802b45.npy +03001627-39c5291a2dd17d6430e06a011e63236a.npy +04379243-fbdf9bffeb353474c3a767747b75e56.npy +02691156-d7e8b636d4a7dab67e697b0700f10b81.npy +03001627-d609864ada7d0170278d386bfa54545.npy +04090263-d7ac2d2fafd9b9076314c3b6a3a65519.npy +02933112-902a342783278a9d824662341ce2b233.npy +03593526-57b186ba25a680584289430f919c490c.npy +02747177-76bd9785d3f6e77f81faebbdea6bd9be.npy +03790512-e59b0be8520e4a899cbc1c09129e1507.npy +03691459-44b9054ed15fac2c3a67bba344536c8c.npy +04379243-47a9339b6a731a1019fb4103277a6b93.npy +03636649-aa001d69c5b051591736c5c04ed41019.npy +04379243-db545f0422e72d3379368d1198f406e7.npy +02808440-86624ab3ee7f840d3321831d2245cf06.npy +02691156-19e6717acfa7d2bdca8607f540cc62ba.npy +02958343-51062ec9b0dadf971c65421fe734e7bc.npy +04379243-ca13cadaeff93c58ad0e9e0d146abe05.npy +02871439-1e46876da968e5de233e9dd8288dd718.npy +03636649-8b4cb57c4d21a84d6af65e5aa19d2e8c.npy +03513137-e143d40f9df57d92288d8f1144f7979f.npy +03948459-b42b1c0c621d2217a8ef632591b544dc.npy +02828884-34bbcc05fdaed2e437638a2ced7d0ba.npy +03642806-3f45cde6f7a13138e256fb3794905772.npy +03467517-3054dcbd4fe67597f57c034b5317e704.npy +02958343-dbd0651a6d5bdad69bc489396a21b465.npy +03001627-ce2ff5c3a103b2c17ad11050da24bb12.npy +04379243-56188419e8052c0b36b0f2a1430e993a.npy +02691156-5274742871cef1aca8cba409c4409ba9.npy +02924116-411d5ea3c73b9214a1f49c8e152c519f.npy +04256520-81d3c178c611199831e05c4a367a9ebd.npy +04530566-fd850819ad05f139bd4f838682e34d2a.npy +04256520-2e2f34305ef8cbc1533ccec14d70360b.npy +04330267-bbaaaf017a32d63a15cef3430fd3876.npy +03001627-ecfc0cf5081976323002761e7a3ba3bd.npy +02933112-a909c649ca19e9c9a45565492492fdbe.npy +04379243-a6ffc5d46a146796ac4c0903ae810430.npy +04379243-4185ad2b10b278f83889b52430b1ab3c.npy +02924116-38aa6c6632f64ad5fdedf0d8aa5213c.npy +04090263-8c6c169c326e61df67b9bb226efd81df.npy +04379243-891c1cd45e849766b07cbf788ba0557c.npy +04379243-78c4b505894342269299936b751bd77b.npy +04090263-10bcfa94dafb185411617c2f1885cb59.npy +02691156-f7160900b6ce7bc4e63e266a803d9270.npy +02992529-7a4619d2240ac470620d74c38ad3f68f.npy +03636649-d4331a5810e36726b8c3db3876404c90.npy +03991062-ad6b3774f97b35ee9eff3cfd975ea4b3.npy +04379243-54401b6df397d9464719088c8e42c6ab.npy +04379243-89e9fa41863867de72ee08e78374a212.npy +02958343-7fee48354a144b5604a60621dcde9e6.npy +03636649-20c399f42ea5e6ee748af47e1b2121e7.npy +03325088-87a6968aa7057c61b362845c6edb57fc.npy +03001627-984900a401b412368412406fac9aee.npy +04090263-2c867f76c95134e6d17373579e6fd9be.npy +03691459-707f0e44e935dd55edfd593a4f114036.npy +03797390-28f1e7bc572a633cb9946438ed40eeb9.npy +04379243-2c6d9b85e2be02d9d76ce82841b0eded.npy +03001627-e64562ae2925d5f3f58087d377226538.npy +04401088-bdb87a4218cc7ecd23bb4223d09fa6a0.npy +02828884-9d01b7c51223f973f155d75bbf62b80.npy +03001627-d5cadd520263753b65ae658fdfdd758d.npy +02958343-5ad0fd6e9fd786937aa522cf442e862e.npy +04090263-cbc84bcebe71e468d398c75d8b3af045.npy +03001627-63cce233e9e5c33cd8f27b2e727c3511.npy +04256520-c75ade3248fb4f2f8962005ce0e986db.npy +04379243-a52ca2940a24a916ebadcdfba7971b71.npy +02818832-5e651f1c15fc66f74eae82c629c10c2.npy +03691459-3adf396785cf9dee7bbfac568080cdbc.npy +04401088-73b87e2025cfdb6daf19fa8e8218bf64.npy +04256520-cb93c492c1c3c00a94c9842dcb05f464.npy +04530566-3e7923c788b0b9a67297c18bca670e89.npy +02691156-3788ee24009c65cb4d210d9468aedaf2.npy +02828884-9f17577e34237f74c2f16c13e1941c0.npy +04090263-4a8f8e108cfa6503202be79d8b285c1e.npy +03001627-e3fba8a576d4d875e1d0950dd1aa903d.npy +02958343-2f03e5379f3e9b6857652684714945f.npy +04379243-cdb0bd21fd5d075bbd1f60c111786ed.npy +03636649-95099d85ebd865f46d11dd9fe20b7791.npy +04379243-c683f7280179260a898f72fb23e1ea6f.npy +03691459-46f25e8462258a85a398a0556683e6e3.npy +02958343-85914342038de6f160190e29962cb3e7.npy +02801938-ff796cbcee132bad747e9c0bb7bd88eb.npy +02691156-29ff751f989bdcfc9bff604afc480b65.npy +04530566-a10a3ed95539d9e81f0c83f3777b8bde.npy +03001627-8ddae5e2493ab76af91663a74ccd2338.npy +03001627-48de3e38b0c5fb40b07fa14c34cd0728.npy +02691156-21e9ae6cdd3ddc27e1c97634acf0214.npy +03797390-8f550770386a6cf82f23d8349a133d2b.npy +03593526-386a6dffaef80143fa0d49b618d792ba.npy +04379243-ac9a28dab6b10451beedb4c8fd29e2d1.npy +03211117-75432c09d6b34efd336e9e51cf4eee59.npy +02942699-483c387d6886e603314b44839465ec00.npy +04401088-3a3fb2919b1bd92658c2dcb60645f75c.npy +04256520-2291855068cbe57442b5d6d90d0cc78.npy +02773838-d331a7bbfb0e7301e858db1dc3499392.npy +02992529-64b6ddb847da082d761eb63018291094.npy +04379243-678f5f5a8c95b0508cbb8bac2032149c.npy +02818832-b16913335a26e380d1a4117555fc7e56.npy +04090263-befe2c697ac907f5410d23b0a192e911.npy +03325088-1eb80664e450516e2c6c98851414a9d8.npy +03593526-6f43bf97b213b888ca2ed12df13a916a.npy +03001627-5b43111740009e719159f4cd32e8e02d.npy +03790512-bcabe20e46e5126ed5dde04c96fd8146.npy +03001627-47c04fe5c1f850b784cb23b18bd34686.npy +04379243-ed0b1bd723063c8ee1be359afa82825.npy +04401088-229077bcc4f52356f582eaab37b1c177.npy +02828884-405d1666d90df2c139842e32fb9b4e4a.npy +02691156-7ef375680d89c711c8db97d9bc169245.npy +02691156-77fea5bd4008e5f09a6e43b878d5b335.npy +03001627-99120ec1daa4ae1bad484915511ccff6.npy +02691156-7401bcbb1a184bf548627a76b6268107.npy +04379243-22c5cbe6271736bffebad4f49b26ec52.npy +02691156-eae958f99bad7dcb18b14db3b83de9ff.npy +02828884-ce23a5781e86368af4fb4dee5181bee.npy +03001627-52310bca00e6a3671201d487ecde379e.npy +04530566-b497c390de93b4dcba21fe79619ae253.npy +04379243-d268aa3ecf296572c0806ee26b689c99.npy +03691459-451f3d4fd10530b9d5a56ecdb5a1cd39.npy +03642806-b95ca4fa91a57394e4b68d3b17c43658.npy +03642806-b806daf849a5dba289c212008d2a390e.npy +04379243-3dab0646af0e6945beedb4c8fd29e2d1.npy +04530566-27d32838007b5a07c63bc8fdb41b8eea.npy +04090263-bbdcf803144145e09905a3939c890ad2.npy +04401088-9c1286570bbc6fc78f257ecba9a6ef8.npy +03001627-bb90094030f369e4305a3b2fd9173d6f.npy +03001627-f3499b524c5dbbefa23949c21eddef76.npy +04379243-b1b499e90f17a6332ebeb1e6a8111f53.npy +02808440-429ca6c2fc2c018944221bef0fa3c36b.npy +04379243-631ab9f813568a602b70eac6546e93fd.npy +02828884-981fb231709d4d2cfebad4f49b26ec52.npy +04256520-1b5bd45428de094f593ebeeedbff73b.npy +04004475-7d930b35795c8263ef895f9600eaaa98.npy +04379243-72ffaa15fd437b33dfecba9aa42b51d3.npy +03636649-34ce1de178694f87e76bc197b3a3ffc0.npy +02958343-5caad0d7bc6524531e51722eeef6dfef.npy +04379243-2602a7b129a08e42c3bd24f986301745.npy +02828884-bd51deddfdcae18b3b8dea4a358cbf0d.npy +03046257-a14c0041225ee741d1d1ea91a730b0e7.npy +04379243-f5a673474566ed53a9360d44e90d853d.npy +02958343-d9dd3e204f4aa43f473f10e6caaeca56.npy +02933112-cb84d931a90fbb8e91ea3afb2749822f.npy +03001627-f43eef7e3991f80346ebf4f1147c3f0f.npy +03325088-df36cb46f484094ac2185cc0ca1b306b.npy +02808440-fe063b20427b13bc1c17aef130ed6213.npy +04530566-9902e521bbd9ff3348d84ab7c5cd4c19.npy +02691156-51d6c3bf592a1fc16dfe8328adcc508e.npy +02933112-1a4ff09890565843c59350d819542ec7.npy +02933112-70424e9cde5be52e25194f3c5a4f307.npy +02691156-d3b39374c97d39da7dc01d89d8a05b74.npy +02808440-5db3375f0e4cf84e133dce51d963916a.npy +03325088-a2d329795c7e4c52b362845c6edb57fc.npy +02691156-a611fb88b28c3f2ec231d70e1e0cc567.npy +03001627-e28c5e90a01027bb4e83b37723b7fdca.npy +02958343-31ae8e03d831a85cafe1d4530f4c6e24.npy +04379243-f95f6251339b759b30bbd4cddd04c77b.npy +04256520-e5a4cb87310ec996e649b526d4e1735a.npy +04256520-e323d123c60c2f2e3c777ea9821e1518.npy +03636649-2e3679df6678e8776908456c5f4ff3f3.npy +03001627-862f70e73fa70c9b1a719e2a845bdada.npy +04379243-fb7124d1ea2937f252219cd24638ae38.npy +04379243-fad9dfcbb4c1755811cdd52f3d07553.npy +03325088-752773b189f2557986a0e7208530ce22.npy +02958343-bc533f9881b0775c3a0daf3e5400b95c.npy +03325088-a2154893d949e1053321831d2245cf06.npy +03593526-6e44adec0854dfaa93fb5c975e8de2b7.npy +04090263-5190f781a1fa9b9a733a41fc18f7f056.npy +02992529-c3b9cb70c6a80ed686a04ec9e4169973.npy +04379243-f1afa2f6205f5c552ecfa9be42d43d0.npy +03046257-5431835bca07a47dd274dcf5b21c1a5d.npy +03001627-79d5977609f99087473f10e6caaeca56.npy +03759954-f3bb6ffcfc132f34418c7dc49421509.npy +03636649-6f5b104f7c1cb4bc636c7e486232cac1.npy +04379243-6797d37aae0e1d4339b483f6ce8789c.npy +02828884-da39c2c025a9bd469200298427982555.npy +02933112-1566915c8a69d58812de5317fe5b354f.npy +04256520-f55beebe7409e84c873aec32fa476d61.npy +02828884-7e73d9c7082453987b019ecf3e106a55.npy +02933112-67616bd629dbf7b3824662341ce2b233.npy +04379243-bc4a64f68f9cfb0733286e10d1a7be57.npy +04379243-79fba03fadd8c00ef10b04ee8b1c6914.npy +02691156-57eaa54ff3e4d6f211f78b196c636566.npy +04090263-3d6ea8a01c3330ea8b22dc3851acefdd.npy +02808440-e6c56b5f2265d6423321831d2245cf06.npy +02992529-8f1ec459492c61ff562c8e1ac545ef78.npy +02933112-8d9fd58227bc92e41f3980612faf041b.npy +04090263-dbcad8c956d195a149a3c1009fa79820.npy +02808440-e8a5492555f645cee4c2a47658c3c899.npy +03467517-10c6c59350abb4c3a8a9e1c6e66d8abf.npy +02958343-bef5b9686c2f93f46a2345809e2bb169.npy +02818832-92e4d52351791ce9d9ba459409ec63ed.npy +02828884-6752d9230ae82d1ce67de87b371d4c06.npy +04379243-466e5bcb7038889d9d48ed08450a6532.npy +03636649-d3e339b83170d89629a60d6ab40898d.npy +03636649-a126861b5d720843aaf2b5b6ef88c2bb.npy +04468005-8a8ddf2debe2167c2be8d09ad36d35f9.npy +02933112-cb12bf5a4429ed4c4639ab25a6c4afd9.npy +04090263-eb11f8abbb974b1d12f1ef17d681ef3c.npy +03001627-2588ff9ade9f3c1dff2c92c2a4f65876.npy +04256520-e46d448389af3fe4500158c23c4c5a8e.npy +04530566-aeb094e328468631d3cf225db57b7a46.npy +04074963-ef639e9f766f2c097f2b5660c54d2f8d.npy +03593526-bd3408700fb963b436b0f2a1430e993a.npy +04379243-c83697d186fc799d7bf6fb68df7f786.npy +03691459-f0c6079a6dfd5e0a7a9e31f14ebb8cc.npy +04330267-2c4eb370f10b4667e6a1cd9763fc2f3f.npy +03636649-b31bcdeaae689dd862af18ecbdb58c38.npy +03001627-50d277986a78f9fc3eec26c23f5bc80b.npy +03991062-add11329471685d6beceb95982284736.npy +03211117-8bf7dbdae495ea9c9db805a3358d2d5.npy +03691459-f2918caa3fe8eceb47eac12ec180489d.npy +04256520-d3cc9f995b1f2b2dffcd08faf4fccd0f.npy +02876657-9b9a4bb5550f00ea586350d6e78ecc7.npy +04379243-efd67be7d7fff02d7b9a616d4541ada8.npy +03325088-2b4f980f62ac992a3b717863742b7581.npy +04379243-3be738da92d36dd09db2b194203875cd.npy +03001627-5d60590d192c52553a23b8cb1a985a11.npy +04256520-f4391a20638d415e76e9713f57a5fcb6.npy +03325088-e7ad0788029da81950da8b99982a3057.npy +03593526-b4d2dc40f931fa5e664b3b9b23ddfcbc.npy +04256520-f3a24b3131da1ce619fb4103277a6b93.npy +04256520-5599465b099deb5064810cc21086da42.npy +04468005-2de2972a127607198ed52f6887b0e63d.npy +02828884-30b57b828f961ca8f002715a08c57858.npy +02828884-8417c3b75ce474d217b431cae0dd70ed.npy +02691156-a75977cd75acf0f05ff3feb917a6004b.npy +04090263-6075b98d3dfb0bf5c1ff4c99e4dddd02.npy +04379243-f7196ec7d732af5166decb1b3cdc5557.npy +03046257-33a6aa9cd6a2aaf3636746e397b0c904.npy +02747177-161e5e86fa48686888cad7f6c0e6001.npy +02958343-2e8c4fd40a1be2fa5f38ed4497f2c53c.npy +04379243-aa8bc1794eb3437977de2663bcb4d12c.npy +03001627-a1314dcd76f53519492d9da2668ec34c.npy +02958343-f88b4156c5e8d35ff500cc506a763c18.npy +03593526-8302f9cd5e454de85d878ba9ec3c0d6a.npy +02958343-a886262ac3be5ca7c126a452758c84e7.npy +03636649-fff6acd5b543ae02a9bdc22a1e02e82.npy +04379243-873d8928f314d95045613f5c2df1029a.npy +03001627-89e6839589a9b450a3f6a82f1fd27077.npy +03991062-febc8f9f30673a7af4553a0692c9821.npy +03325088-a9bb6bb33cc438413321831d2245cf06.npy +03691459-d9b205873345a9b35234ceed4dc815.npy +02958343-a471cdae8ec5df5c9e317a6cc797b629.npy +03001627-5ef9991f0985302c2526940b0dd3ff94.npy +02828884-2c76c171562f6bdfd4d8765e3910f617.npy +04468005-e47a49cceae04d4c213c1a52c1de2c.npy +04256520-308f0ebcbcdad58119fb4103277a6b93.npy +02691156-24c499191b85dd55bf4fc6675b9d12fc.npy +04468005-3ed0d2d3fe223c7273f4e1f33d29626c.npy +04530566-f46a84c0b15f8c0492f7f11d4bb65374.npy +02691156-356a633ea047c549ca8607f540cc62ba.npy +03624134-938a7a0692360ec853b59f50e41b1782.npy +03001627-a2e1ddca35161484f4b35f4029eb1ecf.npy +03991062-cbad1d4f7eb51ad9368b14e48c164a6e.npy +04379243-e8d118117b86ab2e8884a069d9619eaf.npy +03001627-43d13e139d0eb78668007dfca4077105.npy +04379243-edfc8ca3568153d7e8ee6c6df61c5951.npy +04256520-73c8bd191a664678f5ba7cb98f498b13.npy +03642806-9ddc0f876f54a784f3655a2ce983ab1f.npy +03211117-a7dfbb06cf1803b0b6d41c42f7ade8c8.npy +04256520-d3a1db19de4e3fcf7cd71f0b7b44a907.npy +04074963-81cbe7a64eb030c6c221cf4c35c835e.npy +02691156-68b5cf1b10331dfa77c1f99ed297e3ca.npy +04379243-9203f560599ca558c16f7010a3b8fdee.npy +02958343-11a96098620b2ebac2f9fb5458a091d1.npy +04379243-af09abc2c30ac934b3c42e318f3affc.npy +03636649-5929c6937d617f3acf7d397dd220c7e2.npy +02880940-2cfecc8ce6c7cd1f3497637ec59e0374.npy +02933112-21224eab2d099f5012de5317fe5b354f.npy +04379243-a0a123a2c7e0429c1b17743c18fb63dc.npy +04379243-fd487468f7a33adbb2a155afd9dbbb0a.npy +03001627-47a707b2804cc98f1a3c0af5880f464.npy +02691156-589e5b24b3b0e30e2620819ddac40644.npy +04256520-453d56b5906989fff29666f384be6c43.npy +02933112-d30f01d6e50f128d2822b5101b06e070.npy +03991062-257cd060f1947fd336b0f2a1430e993a.npy +02691156-78feacec03272b28854fbae23376cbfe.npy +02747177-e519a53461b3b75b66f3eac0b0a36798.npy +02992529-e5bb37415abcf3b7e1c1039f91f43fda.npy +03001627-212e266cab46f1dd5b903ba10d2ec446.npy +02933112-b8be007c703f1a9eb336215553415709.npy +03046257-8f8858484eae0ef5cd94c4ddf9d43fa3.npy +03046257-3ef61faef1e75fa12b47e06a5eec5e27.npy +02691156-596c6e1e27b102aedf9d17a71b5ddec2.npy +03211117-d5d6824b5115b3d65167d3ead22db5b1.npy +02747177-48aca9c3a4006a5163b2acb037dfbcde.npy +04090263-e48d07c71fac7387870906b5178d97bd.npy +04256520-37b3c4bd619d1c6541ec70becd1ecc7e.npy +04090263-1c4361c083f3abe2cc34b900bb2492e.npy +02924116-a9cb2c6d8f3f502ad392e744726eb1bb.npy +03636649-fc602899fa852d6878aa68632c6b1d5f.npy +04256520-241876321940a2c976e9713f57a5fcb6.npy +03001627-8027892aa03a3d2c907a5a34fd8df2f1.npy +02828884-f560aae80e66f50585ef4356ea4ff622.npy +02691156-e9b29777e840e1fb63737f7c5d9fc39b.npy +02828884-c8802eaffc7e595b2dc11eeca04f912e.npy +02808440-e3ecae5ad7f21c683321831d2245cf06.npy +03211117-415324f27ddd70b4ec3d7b1a84909dc7.npy +04090263-b12d95ad4abbf097e149ba69dbb3f6c3.npy +03325088-d440dce04ceb8b83b362845c6edb57fc.npy +04379243-c5838a6cff5a0163a91116f8fe859a4b.npy +04379243-b5548e1e944a31c077ceee024ab73ab7.npy +04256520-6b0254f2a397129a490ad276cd2af3a4.npy +02828884-512511e994adef8c28eac72b6945b61.npy +04379243-3842d805856309df777b6246417c94ff.npy +03001627-809cd21e86d7caac3162de0102da9582.npy +04379243-785f073399d19cf5b000f20a5153622c.npy +03691459-5ab3bc993eec96709aa778fe3a2080af.npy +04379243-87a30f02d938047987b390f69ff83fb2.npy +04090263-333ef51861a0280a561462387555febb.npy +03001627-8d80cc5cdafc4b8929e17f7efc5a2421.npy +02958343-709ebbf3588849b88b55a52bfd1cce7a.npy +04256520-924339df8bd64d694b3c42e318f3affc.npy +04256520-dbe7fa11097535bae7c7920f6a65a54d.npy +02958343-f10f279643fbb3276a78cd0552215cff.npy +04379243-4606eee54ad02693e06d804f36424ced.npy +02958343-1ab80bc91a45b7d0a31091d2234b9f68.npy +03691459-65c24305578ee500dce0005a7422ebaf.npy +04379243-399797977a78c2c3542091189dc62b5.npy +04379243-f1468b16ea560ae551d3c864cc68e22e.npy +03211117-4428b3a883f177c262f318360c3d0c75.npy +03636649-463a3ee50280fddafcb8d8c6d4df8143.npy +02691156-361f57d736cfc14dc8bff13697c27fb.npy +03691459-6a538eac61644b0f84145006657ffefd.npy +03001627-789daa82e0366966c862eec8232fff1e.npy +04530566-a4cf574f52d4e8d4642f9e27aaf0c47a.npy +02808440-ab70496561127a0332d44b56830636ba.npy +03046257-11c8463ba58a134b68661782af60b711.npy +03691459-8b7afc9b056307f3d3ba59ac5475adf4.npy +04530566-cb79681fc1caae04a63e14ddd32fec78.npy +02691156-775120d01da7a7cc666b8bccf7d1f46a.npy +03001627-419520889432730a970d4dd67731c543.npy +03001627-6e50f19c52a760e3cc1159c3b443c932.npy +02942699-3175f1c1d0cca3c6901887a0237c0ac2.npy +02876657-bd6fdeae09b3c00c3ea96ac97db63fa8.npy +02828884-f4a67224c61f79b1733ee41496c73429.npy +03001627-cc5e3fff3e1325dad67c0f41a0da9c74.npy +02843684-9681386c65c676875efd2d175ccffe45.npy +04379243-199676c0434f5e176bdcd672c2b17215.npy +04379243-365bcd79e58fe001243d6e2cf3942343.npy +03636649-816bafd4dd0a04756da1275102abcdb1.npy +02992529-9dcc24af7e0df254525b3f0594400a46.npy +02880940-56803af65db53307467ca2ad6571afff.npy +03211117-49ad86b608403b8ce760531185a75b14.npy +04401088-a635a6b98eda6c1fa436566ba711d6a7.npy +03001627-b19c970b2b8d6795492d9da2668ec34c.npy +02691156-1a29042e20ab6f005e9e2656aff7dd5b.npy +03001627-f5643e3b42fe5144c9f41f411b2bb452.npy +03636649-f36cab1570442a83466f97f37dccbde.npy +03636649-6a1af043806ddc96ac789d813ddd2d16.npy +03001627-e79b6815925c07acb0957d845ac33749.npy +04256520-17e3db80502cd515bec7eb09198824ea.npy +04379243-a9cfaeaa85dcb7663ca57f5648ff1b0d.npy +04379243-38ef005583b3cfd955357c338ec9641.npy +02818832-3acfa3c60a03415643abcff1f32a8b0c.npy +03710193-786cb8e6d57a7912c3366e417a4acadd.npy +04401088-649c8024460077cce8f3b203d0634c16.npy +02691156-a90230831ba263e5f7fe0727acb55c39.npy +03001627-10a1783f635b3fc181dff5c2e57ad46e.npy +04004475-5259f995c2453ce52af8f68791a7d624.npy +04379243-351d39fa6f9b659f2377f2addb49ed93.npy +02808440-9b55067f02fd4a80ff2ce0138c86aa24.npy +03691459-16d8b1fde755f7f96bc5197cc4c47fe8.npy +03636649-71b7341f69f50e35e86c35c1c8efea2c.npy +04379243-75bde51fca930e35dcc7ddfa72357b1.npy +03759954-5e912251c54c316ea35a7666f0cfa5bb.npy +03001627-75acccc933a08ebd2afe8d5254a0d04.npy +02691156-3ab1e94b6c3a1730c56cc5a87f567365.npy +04401088-decbc541efe459a742f1242fa6dff2cf.npy +03636649-f672eccfe1739e962dcf15e1dea29cf0.npy +03001627-a800bd725fe116447a84e76181a9e08f.npy +04379243-f3db554c71dcae06a40d3d325dad76b5.npy +02808440-167bf252d547bcccccd0340812259a39.npy +03636649-a6ae06e879fcaa019e26fe04e3dd51db.npy +04379243-2b2d827267baf5e75510d59f3ab1ed64.npy +03325088-5ae9420bed69471576c18e71fd49c4dc.npy +02958343-239783ded35d9a4e9f40394aed156c70.npy +04379243-11aeb1b72f433cac279f06792ea23384.npy +04379243-18fa0155b4fd12f9a829287b9dedcaa7.npy +03691459-1a33c0bb3949cd3213f068fa484fb314.npy +02808440-3d6afd4a791e5bdeb022c94235bc8601.npy +02871439-5e2cfde5b2195a923e4ff93cfe0b7fde.npy +04379243-6dedce56f7f60da423f7198a00163bb6.npy +03001627-a5f8050192680e993e6a70f59cdd19a6.npy +03691459-853f3c53280aa44fb63369d5dd85d25.npy +04256520-5d94769d9581fa85295994a5a65844cf.npy +02958343-4b94cdc9c703d00fef3ecc8551d2c1fa.npy +03467517-854baed942f075b4d1f4e3beb8257c5a.npy +02691156-4396510f1346f13050586f69625e08a2.npy +02876657-b35973652d9a526c64848cfde3847b25.npy +03001627-f619416ed17ca24a5dc688388b7d266.npy +04379243-1bac0eef0193952558df8eeaf3dad1c.npy +04468005-72e2827b801a1908c645871d38c7adf9.npy +02992529-a120a29467045d34c3f199bb1cdfc734.npy +04379243-8d459a20748b23b8c0c6e803b020a614.npy +02958343-265f0587e4018f7aff6fa400d1cc4c85.npy +02933112-c08dacfd5dd248374e9bcf25298f80d.npy +04090263-47879a6571648aaf5a5d51f7f565712e.npy +04090263-9079c787f6d944d69a6e43b878d5b335.npy +04530566-7114f947ac296d8034d05799e615961a.npy +03467517-bb9ec41d15fc2a1bf9412922790d06f8.npy +04530566-1b00f29471a41f59e92b1dc10fc46551.npy +03211117-9cd4467976a27ac9f3b65283778dd624.npy +03691459-5d3c3b2e6645df602a328c65e88727a0.npy +04530566-c8f5f746daa5bd96b34ff70ac6c9e4d5.npy +02691156-c641785e297cc8ef74008994fb1880b.npy +04530566-45351c87f019646115aa5b227c027ee0.npy +04256520-9d117d7cc29c3ef314513156cf2b8d0d.npy +02958343-a51b3b0cbd9c24f3a7fd25564c2e888e.npy +02933112-45c91d543ef3c1a829a50a2b3c5e5b6.npy +03636649-58e32cefd2f0ca13e938fdd9451c3206.npy +04256520-6c930734ea1ea82476d342de8af45d5.npy +04090263-59ebbe41c7427a30967ff5ed297c1ff9.npy +04379243-825c5f7bad217f49d96790493cac7283.npy +02958343-3d3a1207dac28b9340d2ba94749368ce.npy +02958343-f81db986082fd0562ac826a3c82da491.npy +02691156-c78cbd0e53900a1ef34db3de24263f32.npy +02691156-80b9b2807547a2d3ab94ae13bc67d41c.npy +04401088-27ef3bc1f4a05157bcff4302eb453f85.npy +03001627-e27cb29cc3df4d0330989b15eb158e03.npy +03636649-2070e39377140bdd7f32712aef0efc5a.npy +04090263-4ce26b6d23caecb3cc34b900bb2492e.npy +04256520-cb6b81f8c581bd2ee6fe3612af521500.npy +02691156-4d97f6fcb6886f49cc14f1e6f4f4f49b.npy +02818832-76a7e959f3f752405d72770c487fd7e1.npy +03001627-498e81334b1dfe98882ebc6f4e497cd2.npy +04256520-8520016e497352aef51fa0238791f5dc.npy +03001627-5fd2d226435431976f283df3449ca535.npy +03001627-5ef73c9bee1b4adcd019a8a03d4a2a3.npy +04379243-938ea1c89e7a62a9d6d49cce41472b6e.npy +02828884-c0d3d5f8941c8014ad5067eac75a07f7.npy +02828884-ab92e0151866e32a9ab1f232db58cef2.npy +03325088-f9ff34cbd52103d3d42b9650f19dd425.npy +02958343-e1c6002b98b4cb2c32f56cbc65681ab5.npy +02958343-1e3f494626a24badf35b4953d8add91f.npy +03642806-37b5e63e9f80e2402052a3b22ea3f616.npy +03001627-117c0e0aafc0c3f81015cdff13e6d9f3.npy +04530566-ae65e1f6bb539fa775e66ae917e551ed.npy +03467517-81e02a57da5c936df4b498e11fb60a4b.npy +04379243-86fcaf63c9e6542c858699aaad4acee4.npy +04530566-5c54100c798dd681bfeb646a8eadb57.npy +02958343-c4d4de90ce7839107dcee93b87532f65.npy +02933112-a46373d86967b3fce9aee4515d4383aa.npy +02958343-eeac3253fc4c0b429092ea6b09901598.npy +04379243-279b9a722b9b203b341625d524f6398d.npy +03001627-9183a9f6e6237492c90fb40095d2be6f.npy +04401088-fe39a57b8137ecbd5b2233351507f22f.npy +02958343-af08f280395cd31719f6a4bcc93433.npy +02958343-435d3d83b7511e39f44e15caa8fd94b4.npy +02958343-4de61edaa8e41c3a53c5346b68828e77.npy +03790512-98ed7f86a65ed6ad4a6b6d001599a1e5.npy +04379243-c71453f2c3fbd5fc56cc009699d2a2b8.npy +03691459-8b0544e065d43369588e71e21de9f30.npy +02828884-f1b8f4c4b2dc4a63c2dbf50c3528525.npy +02691156-daedff5e78136a8b507c9a5cb0f72e1e.npy +02958343-1cf08633fc7e8d193d21cf61f69e40a4.npy +03001627-57285ae595c5cc67eea9006d9d8918a7.npy +03636649-cbf2fd4e3b923f9ffcb8d8c6d4df8143.npy +02871439-6ea3f59ca5b732f01bc471cd5b795bf0.npy +03691459-58142a4c3a71147a2e8dbf40bb4c181d.npy +03991062-b2f08901afcc55e3a2c59a4d90e63212.npy +04379243-bdeb03b610923d868ee99ab78c7c9d6e.npy +04379243-f2ba8040ab2d2745febad4f49b26ec52.npy +02808440-c3fc4231f0388188125fa9990176f0d5.npy +04379243-757deea50fa00eb4e5595fbfd7d35143.npy +02992529-5fea05a3cdcc05756dba92a4e2177102.npy +03001627-9b76a0424563e3f4dbbc9440457e303e.npy +04401088-864b69db6dfc4bd0d4b4ae2ff4c58b57.npy +04256520-e084204cf0c6a345febad4f49b26ec52.npy +02828884-7c40c1a2e4476afbaca9cc236210e91.npy +03046257-ae564765e5ba2f037bad031e1feab327.npy +03467517-f7645b3c690d954682c2412261cb8600.npy +03001627-21a8b1ad63a8d19dd7f7a4c4609b0913.npy +03691459-185315ddc6baf393e0b4198d87217c56.npy +03001627-cfc758bfe8a1cd478c159f8d5e761b17.npy +02747177-f67bf3e49cfffc91f155d75bbf62b80.npy +02876657-6da7fa9722b2a12d195232a03d04563a.npy +02691156-22944fabf8a9763f28132d87f74ffe13.npy +03211117-5f73ccba7af987789744d3b3ee0cc03.npy +04468005-8e6d28abeec94d171b801fa323cefa6c.npy +04379243-d0b6d6210a65f1e4e50369287c07141d.npy +04256520-99b87ca5f2b859988b424343280aeccb.npy +04379243-8e9954ebd739a4aa10234beea2422457.npy +03797390-6d2657c640e97c4dd4c0c1a5a5d9a6b8.npy +02808440-519fae15db7dcd017b39ab85244ee8e6.npy +02808440-7f7d48994b6915d8b362845c6edb57fc.npy +04090263-38bbdc92fcc8e310405d5eab6bdcff6f.npy +04256520-9d2bb2163cba8f54c0e58de02a99f31e.npy +04256520-4a747546b39003dcd59517820ada1bea.npy +04379243-7d8ed7685620a16db2c48fbe46b01575.npy +02808440-c6af9be0c0038798ee5eb4c41d8a7ecb.npy +03636649-a7f25e662466f59dfcb8d8c6d4df8143.npy +04379243-72c8fb162c90a716dc6d75c6559b82a2.npy +04460130-dd82af6c4dc9e26cd9bc2d75eb1cab87.npy +04379243-7f4a5479c612805bb04e388f56884ae1.npy +03691459-492eaa948ae2f795a6d5deb42d3af608.npy +02958343-9bc421a5b0bd481b4e76a17e357a8d36.npy +04530566-b6ec93c690df4cac711722c32e47b894.npy +03636649-d83fc71f3978130e335fe03ac3704320.npy +03691459-b6ec9f482f055259f2e5d34c7b677bc4.npy +03001627-55185010b0b6e42eb98f36033d4304b1.npy +04379243-91bf48934d3b52ea36658c6705d0c08.npy +03691459-164bf28ed57e29a6293982b5acb5446c.npy +02691156-8b65813c6ab0c972ca2bd098b9203af.npy +04530566-d2f5b582c65ee9567f79d93424b708f0.npy +04256520-2bbd5947aca68a81d329e53feaade57.npy +03046257-1c4cd3b790fddfbe2f87b9fc1ad90aa4.npy +03325088-56c35d8a53c2c5d9fb930e40572ccf2f.npy +02958343-99a7f916d137e69bf2cdad303f49c9f9.npy +04379243-e2dbb55cd453fc2ead852a56afc15951.npy +04379243-7d517ccbf0d2b16c50fa82c2f036109a.npy +02924116-18d6a93468a1d0dd41cefd10ce5d6cc0.npy +04379243-875758df9f03fab669a10a3a70c69e8f.npy +02933112-d4277bc8f1301983a77c359d9fe71e62.npy +04530566-8ff4c7162259b1d5cf816caaec167fbf.npy +03691459-e7588cbebdae5863629c8a4be6c1e509.npy +02958343-29ea7766414de256cb34360716066a25.npy +03642806-2cafa6107fff001f7a470f4d014a755f.npy +03001627-a10e8dc1cc9522b67a80d424f0f4074d.npy +02828884-53f19d1ab0828e3fcd3af3995946ed40.npy +03001627-c0f2673cb32574014e972edcee1ee23.npy +04379243-d9e3a8c4f093d66f3e474b0005d777b5.npy +02691156-dc7a703f94b3b17667c5e3041553656b.npy +04090263-fa9f56b25119ab802ca888e33c9ff27c.npy +03001627-9d472f3426868826c43cf68e273d1539.npy +04090263-a38da7d4126b4a4912a8e5e6e6618c8e.npy +02691156-8bde5a00c3caf9771d03b466c72ce41.npy +03001627-c7786437606ac263b04cb542e2c50eb4.npy +04530566-703e4a7096ac1aba8f7e96a8530f50cf.npy +03001627-2724c02bc7797bd1486150a9b7f2cf18.npy +02691156-3360b510b0408682bbf3143b1cb6076a.npy +04090263-1723dcee921fd152d43bb185feff0470.npy +03001627-a0436bbc1e00d9ce6aea2f18ee404fd5.npy +04530566-e92386352c19221ac99bbfcf5650bf52.npy +03001627-fde8c87a485a33b78fa2f6eb9fb1de7c.npy +02828884-cf3821cfe979f0214d84fc9b190bb79a.npy +04379243-d57bb12175463d188aeaff3bff7f4413.npy +02691156-35055f849da2cf0ec3fe7930fce05ded.npy +04379243-1cce1fd7a0184a48cbb8bac2032149c.npy +02958343-9909e197f7383a976d07c55cf995503e.npy +03691459-79e5aa259b3c148789df8842b5523a86.npy +03261776-17c9866b42ae1831df4cfe396cee719e.npy +03001627-bbf89164385610221587835cde687661.npy +02924116-5faa6ec58602029168fc806428a57830.npy +02958343-552233e882a65b6431f5c3d8b8dbfe3.npy +02992529-87aeb552057c3d1a65a7971ba2230c53.npy +02828884-d2d4d92195546a1ecac503d0f3cb1d7a.npy +04379243-1ae856def06f8ee36bec1b6707900b50.npy +03636649-9b34aba70145f08b3ba6f328e4cd62be.npy +03593526-dd815275fce18cdfd138a53ab0d038a5.npy +02958343-fb6c92a80dd9af59b528c0abff96f586.npy +02828884-3e16ff75bbe7ed27464e1d2ff524a75b.npy +02992529-3a6a3db4a0174fddd2789f496481c83e.npy +03001627-70cb8d70d961ca48b04cb542e2c50eb4.npy +03001627-4d7cb35d1d9f2434ccbcb819724fb563.npy +04256520-3cce581fbf55c31b8ccbec49bbc083f6.npy +03593526-5c589d9495c87d7da2fcca81c767066f.npy +02924116-3b5e31b2987f158e9f46749e28e16975.npy +04379243-62d2038ffb8b9df253041c49040be3d5.npy +04379243-711d439d6638b4c33efa790205f68f8.npy +04379243-bf15d331be699886a005442d4981d053.npy +04379243-de6f494dbebd91ede057b217c7790618.npy +03001627-e065edba45aee481490ad276cd2af3a4.npy +02958343-270b0846304e3d66bda733a39f84326d.npy +02747177-af1dc226f465990e81faebbdea6bd9be.npy +04256520-758895bf2fa5e4b5e68b9e5f5c3d0eca.npy +02992529-46261b630244bdda533775ea6714a372.npy +04256520-bc2c0cf666122cc68f5c37fe197319e1.npy +03636649-886ff4f5cd90c6ad39b3360f500ac52a.npy +02691156-1d5708929a4ae05842d1180c659735fe.npy +03636649-c2378f62797cbcb26a5e440d54e375dc.npy +03691459-f7023235e0282c797f357b05b0dcb89.npy +03325088-8cecc2d6db8756683321831d2245cf06.npy +02958343-100715345ee54d7ae38b52b4ee9d36a3.npy +02933112-21f3c0d4604587b4da5feafe6f1c8fc.npy +03001627-a128eda00983dd01fb7d9615be5ab4b0.npy +03636649-ec876529d01d4df490ad276cd2af3a4.npy +04530566-a89cda9712b67a97d1e97c10e2464c2d.npy +03001627-1157d8d6995da5c0290d57214c8512a4.npy +02958343-71b00ea32b1810ac373af83f3f2fe606.npy +03513137-d736c45c5b2397219092826e64279378.npy +03325088-b19d6c949c76e41c9be6726a83c38aad.npy +03001627-981adc1bb90e7cab666bebf1a1d4e946.npy +02691156-ee461612837ce39eedd03f781ec3ebcf.npy +02691156-75b151efa363c18d94b9c9a92aa36f8c.npy +02691156-e9bbeedf2681b8ad154c6bbaeb7d331f.npy +04256520-de82cd275086d50e41b160b9adc112fd.npy +03001627-c6cb59e7645dd14d661ff085a0f14b7.npy +04256520-854c9e951c2cf2e3492d9da2668ec34c.npy +04379243-578f935f182c5cb3bc5c4c571faa8806.npy +04090263-13ff0ba1e8d79a927f71da36e5c530dc.npy +03636649-2577723d02fd914eda113afcb6c5e140.npy +04379243-80f036ce585b1ef648ff063e62e02115.npy +03211117-28b6e44e37586fd797e8123bbbc761d8.npy +04379243-f907cab3a8373d56c3bd24f986301745.npy +03211117-9e087d56d1264f0bae8d825afe55a6fb.npy +02691156-5fe313e070d6fc4e2620819ddac40644.npy +03001627-f428a799c3185ee0c8687ff9b0b4e4ac.npy +03636649-30e5d9149ddfeef27357c8b8283e0cce.npy +03046257-c084297af1373b36b4cd1bd556007aed.npy +03636649-79af7fbe587692a583768a4ac1607d73.npy +02828884-6233b6cce0da0615d4cfbd0aef5a371.npy +04256520-1441ae85e34e1564ad33b69f9597739.npy +02828884-9d47deb11cac29f089345002d2594e4c.npy +04379243-67584a2261e175ccfbed972ae4fd63af.npy +02747177-12c4048e0d2f26a763b2acb037dfbcde.npy +02958343-3ed07ff8b46b2bdcb1bb46d2556ba67d.npy +03337140-2bbdcfcea1a8c5f3ce5d6e9371bb5c33.npy +03636649-ad7dbc3a78d37b4c8616812464c86290.npy +02691156-6a75658fb8242b9c590874dcd9dc8481.npy +04401088-16549bfa3cd0f53d2110cfd44d2335d.npy +02924116-83928dc21ca6588f67aa983983f9bf36.npy +02691156-b1835836e541766882568aa50e4e5dba.npy +02933112-39b50a129ff530efb4ba4a53b97265b.npy +03001627-f3e0042ea11660d0ff2c92c2a4f65876.npy +03513137-6ff1a99371f10144e5e6ac3ef6bff73.npy +03001627-b7403875e1d7adea331fc18393f04d2a.npy +04379243-e6d8569c0957e7453002761e7a3ba3bd.npy +02691156-d22521d217d89f8d5b1bb801ea1e2db7.npy +04530566-e11279543f1e3ea015ebc00dd3588bef.npy +03001627-5456ffcbb7bd6b3e4460d09678055ab5.npy +03790512-9bc8441b3b70b7014a4c9ebcdcc46c40.npy +02808440-e23251d421d5f7d6b362845c6edb57fc.npy +03001627-5df875e6f0cc0e37f838a2212356e267.npy +03001627-6dccf79814289bca5a15b6547f08c8fe.npy +03211117-61645237bf8de4df77525a753bdd4f00.npy +02958343-8285dfa786cf25b2c29fde65e51f52cb.npy +03001627-a33fcf84726cd862d866e3aa112e4663.npy +02828884-96ab21db41e4da2d848b05feebb5193c.npy +03046257-27c132708bab56bd32320778c4ce7485.npy +04090263-87e23cb3540dfc59c89145ad6791be51.npy +03790512-f521fe88cdfe3a291d87d0fbeec0e0ff.npy +04379243-97718e2651d22b3a74740f837351e7eb.npy +02808440-52f74ddc2d35e8e900a91cbf836390b.npy +04379243-d4acb5110512f5c38369c37b40e82efa.npy +03001627-3de3774ea9a05f51585ed17f54616d23.npy +03691459-2f1446816ac58936361167c63c6bbe5d.npy +04530566-d9ca42c1199196a8f8785957fc1b208.npy +03938244-2ec52ad731536d294b3c42e318f3affc.npy +03593526-d2b8e090125199c49edbf2f02d126923.npy +04090263-e8df7ab8879ae3f895bcf48dcf4517b8.npy +03001627-c67b7b62e529295dfc30525e763ef5eb.npy +03207941-fee1215825c04d1d9c12d6260da9ac2b.npy +04379243-8d900764c04127df4b3c42e318f3affc.npy +04379243-294d38860c334c4954a61dbdbc1ac262.npy +04379243-a59f0a9956137c0735962325b2299f4c.npy +02942699-317a7ea24e661ce3bfc146552c7aa5d2.npy +03046257-26150fdcce285cf49fb73a07dc7d819.npy +03001627-fb5ba735ef95fe417ca68e217a316e15.npy +04401088-3f95b3ecbe55c83e9c3a7294039d408.npy +04530566-f69f4b2abc707f667610cb1c03c9c3ea.npy +02992529-a7056690a5bf34d24ffbcf8cf904ca12.npy +03001627-85be4b6c37bd1e801d45bcf0f68506fa.npy +03467517-29a402726ae7c4ebd440718bd2c795cf.npy +03467517-b15aa0998b1453ba830536956f5eb8d1.npy +02801938-e9b6ef7375650b54ad2fb8cd0793fa9a.npy +03325088-9b65733ed1e66f1dcf87dab359f38253.npy +03001627-e505ab84808920d06031c9bf940ea7ea.npy +02992529-2dccc7cfff6f9a28aca331f9e5d9fa9.npy +04379243-bab2fefad03208b0935d906e24c18439.npy +04530566-6a7ce5d7027678c299429033f40f0f8b.npy +04530566-7ba19c8354c66edbb74e6fa236ab84b4.npy +04090263-1813aaa9a82a98789c82b3f5ddca589c.npy +03624134-792f252dcb06f042dd56c1edf3f6e336.npy +03001627-5e5121cc58c4fea78ce66f12ba927a2b.npy +02933112-4e2d3dee0f6c8e18754e8957cd76ff02.npy +02808440-dd3667be79294afe3321831d2245cf06.npy +04256520-c63e1750f61af4bc4be7464481982099.npy +03325088-574a71125f559fbeb362845c6edb57fc.npy +03593526-c59aa436f265a75b8f9c4ecc067067e9.npy +04468005-b5e64ec8070fdd8d299a59bfd8e7d284.npy +04379243-4f79ef44a08bc2ff4a60c1a189046dd1.npy +04379243-46165d8076918c62f51f77a6d7299806.npy +02958343-787ba4e958f1bbe88ec77d0d80815cf8.npy +03691459-f682ee3b4f4dc3fcce029fab54b6cfbd.npy +04379243-48273349239e81b64b3c42e318f3affc.npy +03211117-9536f9fd4795dc2d70ef2132a4b991a.npy +02808440-934bc8fa879c3f0244221bef0fa3c36b.npy +02691156-eac05be6e7f3bfa99a6e43b878d5b335.npy +02958343-22428fd70b02b83ffc567bb1bd08c1ae.npy +04256520-ea581514b73f4707febad4f49b26ec52.npy +04379243-2c671dc7902c140d3b52a6690de3e81d.npy +04530566-2d189012a5b5a64aeb5178df7a9bd7f4.npy +03001627-5bd08666f29e946c988a5637d6d8f36a.npy +02924116-4ead9b28515b97fdc0e2e9e9ade4d03b.npy +03046257-50be9eafe3abc283ecb14096838a20c5.npy +03337140-55054f56f1afd25ace5d6e9371bb5c33.npy +03001627-3b513237d90a4cd1576d8983ea1341c3.npy +03761084-a65e74617ff51c661b1fe5e2144bf114.npy +04379243-b9328275771909fe920de219c00d1c3b.npy +03325088-4a03d0bf342959e7c36fb70296e45483.npy +04379243-6e446bb5adf14b0b6121178eafd002fd.npy +02691156-1e40d41905a9be766ed8c57a1980bb26.npy +04530566-6271c832e8f629b73c83f6e156ad107a.npy +02992529-4b96f974453ef59ea2c7c5886f4bbc93.npy +04554684-9b1b90b033d6c6a42bf3161ae4fda942.npy +03642806-82edd31783edc77018a5de3a5f9a5881.npy +02958343-82d37fceb984256bf200a72c9245aee7.npy +03636649-7e5dc9256f9600d9fcb8d8c6d4df8143.npy +04401088-91240b6e6ca6136dd25ac584f0a4b696.npy +04530566-bcf9572e3f21a9505c0be177939e290.npy +03691459-85e8d20d51ce13cc7fbc060fd555478.npy +03636649-aad5c7256a7c6ba92a4d67a8ec314d2a.npy +03001627-787a4db5b3452fc357a847db7547c1f3.npy +02933112-30ad23a8f6a3a4479725f8348364f5a8.npy +03001627-4e438ade91769be8c8687ff9b0b4e4ac.npy +02958343-1be81460e620aea65cde8c99e4b182f9.npy +04379243-ba6e6f8263e961c243f6b77085610df6.npy +04256520-ede1eb2acb5ba12e7282872e507d5fff.npy +03001627-afaa508214b7515a161d68600952d375.npy +02958343-45e69263902d77304dde7b6e74a2cede.npy +02933112-586cd9ce3d22685f2280e8623aad43f4.npy +03636649-9000cdad54cd0285e6597d391ab6fcc1.npy +02958343-165aec174bb93968a114c8c036e29a08.npy +03691459-a3f012045e4b62b2789df5bd89bb3ea.npy +03691459-44cdc1204fa555be2633ff66beb9cf31.npy +03001627-e5cb5334f18c13c15a7f6c1314f7ac2.npy +03001627-524e4a1041ae53154b3c42e318f3affc.npy +03691459-bf83a8cfb72a6208432eb33b78f3e334.npy +02933112-8a7f0dd58fbf14a4c59350d819542ec7.npy +02992529-a2953e7ff6dcd4465af22172f09754fd.npy +04379243-6f6d4abfb84b9eb527c3aad6317cf3db.npy +04379243-c31155f4beed339e855931d119219022.npy +03001627-c53fa6829ec9a947d13b7d13ee32497.npy +04379243-be9a0901f9ac115d71b883b95236fc2b.npy +03001627-af0831d39fd8f794492d9da2668ec34c.npy +03642806-71907a4a567dce3bb0de1e7a6809fd90.npy +04379243-c393265168bcc56cf3ced7613d1c130b.npy +04256520-b0aab89e3318b09724a8d949d07d1308.npy +03001627-866552d994de3a252ea98d69e91ba870.npy +02691156-3a82056ea319a442f64801ad2940cdd5.npy +04379243-553213ef2a7657fa9ccce4c6d5bb195f.npy +02691156-3e9ff76da8ca4885d0635288642e63e.npy +04401088-c4dcbb047d219cfeb4018979c856c916.npy +03467517-fffc2fc5a90254de9e317a6cc797b629.npy +02871439-495deb98f5096b3be3241548166bb146.npy +04090263-354d382fe282ff567ce76669ca87ee34.npy +03467517-3a50cba9f6239bd037d3e9143e987d83.npy +04330267-50bfe9e46388341c3f175c5b5510099b.npy +03001627-3f12570d87da2383492664434c74d812.npy +03636649-cec552e824883875490ad276cd2af3a4.npy +03211117-2772ad703e5d4b73cf6f327fca156fb.npy +04330267-d8e0d47be86833ffe8cd55fcf3e9137c.npy +03211117-817aa8a9ac7f57f9dd936ff7b4023f05.npy +02808440-d498df3b7c7f53c6f74d83b4be105200.npy +04090263-32d8874aadbc73daa50ef3fc203c6ba0.npy +03710193-7ec679d4c550daf149400676d2d9ca64.npy +03691459-464da0c0df4ed3c0dfdc04b8b8434e84.npy +04379243-e65066d6b0b83719c3bd24f986301745.npy +02747177-b838c5bc5241a44bf2f2371022475a36.npy +04530566-87f68a979aece6f71f29de30ec1bf6a3.npy +02992529-19b1c1a790c6824578bfad8b5ed8c4ef.npy +02828884-dbacfce828f0598ad534c2812395a1c1.npy +04379243-4cf6b0e3320f0740521fac473c90dd4a.npy +04379243-1cb2fe52097b5304217ffa735084910f.npy +02828884-3b688abcaf09a495c62ae1031b767cea.npy +02691156-95bc1c56fd50037ce3f3aec01b086ba.npy +03001627-79780c35666f045d7ff7b6423ebfebc7.npy +04530566-80d9d9fc9c6138c4800a0120f3e757a2.npy +04530566-3a71bdf6dd3e42bd6d08077e9257af3.npy +03001627-cc2930e7ceb24691febad4f49b26ec52.npy +02808440-8c181fc92fbba230a341228b21d337a9.npy +03636649-ee8543345535674822aa4f44d9f697ed.npy +02808440-2f65f22224a48d26ead253ec715c9744.npy +02747177-9fe4d78e7d4085c2f1b010366bb60ce8.npy +04379243-313957e318bb7849febad4f49b26ec52.npy +04401088-678ed514423f067fba55419d0f0e294.npy +04090263-7a79d63c2cf6df519f605c8c86eb1ec2.npy +04379243-9228f548332eacc51287e03b5b76fc86.npy +03211117-c514d99259ffe1abe441f5bb6f88ca61.npy +02691156-a9bbba73d3fb7688b6b87e72ead132ed.npy +03001627-98f923c006fdd918e6d206b2ed87676.npy +02958343-dd84236f0ef27765a134736201a79843.npy +03211117-877cadd597775369ec059109909662d2.npy +03467517-bb4a5712da8f63330d758421dd01f45.npy +04256520-6ed0a767dc4c570e4cb7bc8e4c7cdd90.npy +04379243-5ba371858d595d4ef645e44148cef56.npy +04379243-9e6aba6596ffbf95a9bdc22a1e02e82.npy +02747177-1c3cf618a6790f1021c6005997c63924.npy +03001627-25d40c79ac57891cfebad4f49b26ec52.npy +04379243-2182028f013e7eb530bbd4cddd04c77b.npy +03928116-6d52a20b2a723fda16a0adac6af4232a.npy +03513137-7721ee80bfa4cbc583ce6bc80d855733.npy +03636649-52284fc0b5822495ce140b3448f2e640.npy +04256520-7a379a92b40f0efb3920d120afd003e0.npy +04379243-4b9ccbb4884f12376a5e440d54e375dc.npy +03211117-22e8d055ae154efbd12a1bc232f6622c.npy +02691156-bd46cedafa0568b070d98a97e17b4da3.npy +02958343-7a2cb890271a361799b92ac6181b3e5e.npy +03001627-c3bc47657b691c51e6fe3612af521500.npy +03691459-90cf7907801560fd27766fcc9fe2f132.npy +03642806-f28fe2f836cb0dfaa8f4918d18e28074.npy +03046257-2dc32ccf8ad7e74faa45d7cfa7825fb7.npy +04530566-acc71731a16d074f5a11da1e572e8f01.npy +03790512-c38b3d9be97383c2ebe67d9b32c3ddf8.npy +03593526-9cabda39008f86316d075d8d4fe1141.npy +03001627-f09af71bebd4bea8a2651abaf391628e.npy +04090263-d1044b04ea67ab2d3e10bd7b040a4312.npy +03636649-3aec7c839e247954a38859fd71bee28c.npy +04379243-8e3a98ea6d37d14c59a230640e61666e.npy +04379243-f10473382b623504d79b19c7c4f0e293.npy +02992529-f9023b680f219f7c363111a4e20c10d0.npy +04099429-66e0f9388b2eb6bedb7e97e28dbb721.npy +03467517-57c71d56ec72bd8d63e148e250c0340d.npy +02958343-c34f37b1bdd6fd62247035fb6ff31a15.npy +03325088-2007abffa44d274d25074a00e97604c0.npy +03991062-fe9ad9b2af48f5c28ddf4bbff6a47d4a.npy +04379243-4333e8cd288f47c4e0c9d6065dbbbe16.npy +02828884-bc6914d649379349ab3be97afdba4e8d.npy +02828884-d71d9473e08c108d2f210d96281fe860.npy +03001627-60647c98b5fc96b13002761e7a3ba3bd.npy +03325088-e8a23ca5394733a0b362845c6edb57fc.npy +02933112-1f4ccbdbd0162e9be3f7a74e12a274ef.npy +03991062-657913cf3b4a83a2557ee26019a883fc.npy +03001627-32b56fa66c73c450a86b76551c6a3b2b.npy +02958343-e5236427b42606f4cac26de9a01eefad.npy +04379243-81db02f2b3686761f51f77a6d7299806.npy +03636649-684b06c007aa83873c2e0b170f2ad8bc.npy +02691156-37cbf91baa58d6577dc01d89d8a05b74.npy +03211117-8a87846412b40900ab610b0c94236463.npy +03797390-43e1cabc5dd2fa91fffc97a61124b1a9.npy +03001627-9a91a491a9e74ab132c074e5313866f2.npy +04379243-23a4fc50f123d8801ec48bc3c478566d.npy +04379243-878414eb6e86494d9a8ef44e1d2c5b75.npy +03790512-582e995c76ba36a44f5a72a02a218ed6.npy +04379243-c5230678204a1bb8dcfcef693e7ec696.npy +02808440-a67047070d8693d2c2f0673fe60ad9d3.npy +02958343-96905400f6122662473f10e6caaeca56.npy +04530566-bf4386d3e823a09e57a4e26112104eae.npy +04004475-36391c79c1025c3867964ba700cd97f5.npy +04256520-dc89ccf0f13d42a83abfc4d0a5688916.npy +02691156-ca45f5d7efba158ca35e371359a547.npy +04225987-f5d7698b5a57d61226e0640b67de606.npy +03001627-2745c7d9f2027d605a9f35e635b7e48b.npy +02876657-405ee743f0d8601551238db1f507a8c7.npy +03001627-99d4e65625b32a1d151f08387c3363cb.npy +02828884-66304c61af32ca5aad5067eac75a07f7.npy +02933112-c129e7434b33f3cf1b17743c18fb63dc.npy +04379243-e5567158ce772a43fcf7d910cd22d7c2.npy +04256520-b048119e0f0828d5758f6def7204bd6b.npy +03001627-5c6c95a9a99d452e1d2651c636d3967d.npy +04530566-34c099dc4cbcb0ee7c304709a8c6cd35.npy +02691156-3391c664149308cb4f95630cc18536e0.npy +03991062-8306708f6aed84dee47222ca7f3cc9f6.npy +04090263-963506132e08855de5cf42144086d22a.npy +03642806-39e80a6570002a431181170a86d04637.npy +03636649-85a73c46a97649fa6d0c88a73d7cb14d.npy +03691459-6e542a3dfae28b1cf852111eed0a5c85.npy +04379243-426a9fb4da504a96db3e66b0a511465e.npy +02691156-1d7eb22189100710ca8607f540cc62ba.npy +04256520-9aa3c3c03d111640490ad276cd2af3a4.npy +03001627-73d534b85a1416eefba3e6a55f280fd.npy +02828884-d074449720d6b421e44204a7bf1b3ed6.npy +02924116-59e0e8d9a082548a103ab07d448b13c7.npy +04379243-4cbfd25faaa706daea0e09825584e0d.npy +04379243-234ca609205d8d80a1e28099cf3c0efc.npy +04330267-ffd3126859fdd15ccf0517eac2f2d331.npy +04090263-6f739c0ca5834e825dc7ef8b006fcb7e.npy +04099429-bb07f8aea99dd2cd533e0927d26599e2.npy +04530566-a02fb3d1e8e9d34ffdd29529d1a15514.npy +04468005-e0486cf313d2ad90eff204cce5c18b06.npy +03636649-6b0664c9fb1a4fd1fcb8d8c6d4df8143.npy +03691459-5eb44c2aa29844391f9f3ce366e030fb.npy +04379243-791987a0e943f009b5872b4cd3f92676.npy +02691156-40b916f7c41ad451494ac047ec5b052e.npy +03001627-2d74dcc00e449a5462a510b8f97c658e.npy +04379243-3fc1002b5a538aee50c9fe3e733d8740.npy +02958343-4dd97a6805c2797d18d95feceda870ca.npy +03211117-ccff142a647e673dc24648b5216c0d5.npy +02933112-59263293983a99d3de650492e45fb14f.npy +02828884-9a58d783e013b051d87d55641461d6af.npy +04379243-120f8e2ef276fc6b9a45b69dede1154b.npy +03636649-545672cd928e85e7d706ecb3379aa341.npy +04401088-283e3f79ecc4b74d1e4e60ebd003a0c9.npy +03624134-654ebe35ec5c1cc676b32b03a2729ae2.npy +02691156-cf2bbaaebcadfb282933085759cb1f25.npy +03593526-b22a31918c21981a275d003e423c59ba.npy +02933112-1d93291de09fa5c876e9713f57a5fcb6.npy +03001627-2bf05f8a84f0a6f33002761e7a3ba3bd.npy +04379243-f298b3663ae591a2276bf4bce35c96fc.npy +03001627-566e4f05071e86bbf3c9c1464e55d580.npy +03001627-741fa23c22d97ea81bd5f87ae5f3f83.npy +03001627-8e76d0002b592ef91663a74ccd2338.npy +03001627-bbdaf1503b9e2219df6cfab91d65bb91.npy +03691459-c2598d72d508a33060ee9c7e2ec5f91a.npy +04379243-38c184010d3dbed1d0c05eb40b42c942.npy +03001627-2b110b833111b38c420adf24e49f74c8.npy +02958343-8b722405131e569db927782fc69a1fbb.npy +03001627-6a28919186eb55ecf69d0cf4fdc89b12.npy +04379243-fe2c951f711bf1971a12d98ab62a7b8e.npy +04256520-cf81e26374530f8fc08abcaf67cf0417.npy +04090263-262990856b80d83d4382b46c76d2521d.npy +02828884-b711e64c92fc594c18e830a47a552b39.npy +02747177-d62fb12c728b273b1aae33b6f700ecdc.npy +02871439-abe8a3e6a25fb925cdc110c18589b6ec.npy +03001627-17aeeadccf0e560e274b862d3a151946.npy +03001627-fb9f11f128e006d2498725b9a1405ebb.npy +02933112-a3407d2fdef7386c278d386bfa54545.npy +02691156-1e2de00cf19a0a33554ccf8c30febe7.npy +03636649-2a3267758a3caeb7cf353869450feb9a.npy +02828884-7a5ecec36bcb9eb24c080f2371a3ed2.npy +02691156-22795c32b54719dffaa7ec7d870d2e09.npy +03636649-96b71e055f40cfc21735ea0e092a805a.npy +03211117-d9c951f1008183e69755c35f0639c9f5.npy +03593526-72b25fa022376928e4feabc80d16b5e4.npy +02992529-93cc80bca9e1812a64a09de5345a6fef.npy +02828884-72b6c4e1d8b93b21c2bf98e7124e149.npy +03001627-8169b36ef1ae45ec19fb4103277a6b93.npy +02691156-62ca091091053afd9a6e43b878d5b335.npy +04090263-73695c25b3ec4ae372333100c25acfb3.npy +04379243-af3ad492135860eed8fe1b8aaa4afeb2.npy +02808440-85663f3daba8a0d51c17aef130ed6213.npy +04090263-27df401605241825fb5c1b0f759e2bc1.npy +04379243-fdb61d6d639b1f51851f4ba6aaedaaa8.npy +03001627-c8bd3d33ff8cd4abf189bc4b6aa309bf.npy +04256520-4a01490054b15c90ea5adc188e5a2fc0.npy +02828884-a58cb33e8aa8142af155d75bbf62b80.npy +02691156-d28a3cd771b2bf1e71d03b466c72ce41.npy +03636649-5f4bc8ad5a1a0dd4cccbece4754c7cf.npy +03636649-5c324a7cdf6195a5303c85804d402599.npy +02958343-eb471949c658f39eca736b1d30b87e32.npy +03691459-4c722ef308bd6362d747b49524a1246e.npy +03636649-d16bb6b2f26084556acbef8d3bef8f28.npy +02691156-9cb21d68582e1c4ec1ccec171a275967.npy +03991062-e9f6c53454e068cb2ff65fa033da81db.npy +04530566-159d09a7bd7d09a59f1deb04fb8ae481.npy +03001627-7f70642500b9a3ce45881d7eab1353ba.npy +03001627-884a239f3dc6a91cad484915511ccff6.npy +04090263-2416892a9f7688b01638241f3ad71c10.npy +04256520-c37832a4b22cc13e6654a522b30cb96.npy +03337140-501d1a430865e6d7492d9da2668ec34c.npy +02828884-55ca4cb17b26110d3b160521ef1e85fa.npy +03001627-19ff1d5665c1a68677b8fc2abf845259.npy +04090263-db2916f1dbff9d9232967a44e902e4c2.npy +04090263-ea212437514740bb8b700cf351204203.npy +03636649-e9df996dd33c009bfcb8d8c6d4df8143.npy +02958343-cc7f51159a1a12fea7fd25564c2e888e.npy +04256520-324d7108aea113f5b60d98504d0756f4.npy +03467517-44c05e219618a6395b3335548350bdee.npy +03593526-dddd30f41cd6543e25e65d4b5f3b6456.npy +02958343-2a771048127cf0b85dca6305fb9f97ca.npy +02958343-3975b2350688e38c65552c4ac8607d25.npy +04530566-b89d4bfad9c9b64d476a01ad767951be.npy +04090263-8adb587e61fa424ad199d75ecc2a48b.npy +02958343-fe1ec9b9ff75e947d56a18f240de5e54.npy +04530566-5c313324778eb79ad976d6ec0305833a.npy +02691156-166d333d38897d1513d521050081b441.npy +02933112-9d59bf323b297b327885a2b9445961bb.npy +02691156-35bb733b13c48bbc839ab492b6143b9d.npy +03467517-9768ded42e36d84363e148e250c0340d.npy +04468005-dbe69c9cfc9d5ffa9e7fa80af2c89cf2.npy +04530566-5fd1b1b185638c49c13c29cdfe828247.npy +03001627-1ab42ccff0f8235d979516e720d607b8.npy +04379243-a18c4bd95d90f37091829b477862aff6.npy +02933112-8fa86c85b7985962598f1102685df4cd.npy +04090263-680162d9443e8a408e62f59b444d701a.npy +02933112-48555a476cfcd222c59350d819542ec7.npy +04401088-25e03c305f41c5dd226bc3b9ce9ff2a1.npy +03001627-37a05e83e529a1e044f23566597ec464.npy +02828884-f197553928fccdd2b12aa6a0f050b3.npy +04379243-5e14471dd0ac3e47765ee729adbdf968.npy +04256520-c3664a4a708086a448b7e15d7b3646df.npy +04379243-d6874aa362830375ef8af3aeeb9bcffa.npy +03636649-63da6d6aff4d14789bc41a35200a3af1.npy +04256520-761b8ef3b41a84b82f84cb7932f866fd.npy +03001627-969730a19872b564fdb60f509d2616e0.npy +03325088-903c4ce576afab5e979c556124bee033.npy +02924116-53772463c870f1a1d76caed74eca6172.npy +04530566-fa3ed7b176b0794d5b4b8b1a2a708ac6.npy +02828884-4a9a7e5b88cc4b79b985467c63dd34d8.npy +02747177-def815f84e0cc9cfcb2a965e75be701c.npy +04530566-459decbc3c6bb150ba2abf2ecc57eeda.npy +03691459-b3a4bcdee00ab993ebc29484102f14e3.npy +03001627-ba33781b222ca9346e23a4fabd87b2c.npy +02924116-fb5b5a60d254807e6af3f354644c5a9b.npy +03593526-133dc38c1316d9515dc3653f8341633a.npy +04256520-96ce3abe2e2d4bd3ff24fe90298ffa71.npy +04256520-abc6cff85c8282cf6fe2eb61cd6e74e5.npy +04379243-4391d4d7984a245be0182fa3e963fc11.npy +04379243-21925c161a6aa5bf6d65f86bdc92afdc.npy +04530566-189668ffa80d37877622984b5941cfb8.npy +02808440-12e0842f9f1c8cf02c3aeda648e0cc4f.npy +03691459-26778511109e9e76d936ebf2a7172ccb.npy +02924116-bbe7d3e157ff918541cefd10ce5d6cc0.npy +04379243-52837fa3e281763aed88854fc3e3ce05.npy +04090263-a5bfb8e604bb2d8173db096a9cda49d4.npy +02933112-31ab6947975f5747c62ff677c806df30.npy +04256520-46e6485e5bea085a2b450c5933dcfcb6.npy +03991062-d1b50f008ab9e3d7da7a4e0a62ae3e2e.npy +04379243-d5e79960180078237062f2d72cde5c95.npy +02958343-3e2c3cb4f4c65b9cde9d4070fcdfa604.npy +02828884-27539b0c42068420cb2a965e75be701c.npy +02828884-ca0a5a3a4c5e255b20768660cf080d12.npy +02691156-86b11ae736659136ca8607f540cc62ba.npy +02958343-ff5ad56515bc0167500fb89d8b5ec70a.npy +04379243-fb89493e6389039527d4fc401a34f3de.npy +02958343-60d8d7776789b4b1fe11eeaa72c8aa36.npy +04401088-20346d307d39aa7eb6a804c25e3218a.npy +04379243-5bbc7d606ddd5d17e492aefec5dc15c7.npy +02828884-2c47d12adb8437ed601104cd2d998272.npy +04090263-8c2748ffe88d346ab9915b62040615dd.npy +04379243-60c580efa09c28a91ceb062da003617b.npy +04379243-3ffeeae04bdd3b51c3bd24f986301745.npy +02958343-2d817a6f23d35494d991a658ca89186.npy +04379243-99224f3ab2705aa9985ef0bf52b97bf5.npy +02958343-588c2d2567fd900aefe5f291bc2f5fd0.npy +04379243-e20f1fff2b84f8ea71ba8e8bdf40d1ea.npy +04379243-7efc699b5fc94757f93239519b75aa98.npy +02876657-e656d6586d481f41eb69804478f9c547.npy +03211117-b097e8761c3cafe5a35a7666f0cfa5bb.npy +04225987-113783f51974426b92ba7d308c045fd8.npy +03467517-6f9d1467eb39f8abfae47f572c17b9cb.npy +04256520-a181227b44ccf1ce6199ff1c1ae229f3.npy +03790512-6ebb8ff387bc2510c17fa08d127e11f7.npy +04379243-e339e8b8f1bd5eb9626d7e3d07da8352.npy +03991062-d7e47dbd3b50a3688cbd3996b1c0adf8.npy +02992529-d0b5b899929975558ee99126b119afe5.npy +03001627-d52e7e39bed3ed954f62c7a282978009.npy +02933112-247ef69bd111e8f026cd8d83e7ef5b6d.npy +03001627-df2b3ab36704f9e944ebbc705ad8c07.npy +02958343-23e8adb3bf1961f85332d3b92481b499.npy +02691156-9facc516914dcfee6c32d954b1c7f41e.npy +03636649-7a2362fbddbee9a4d197f67767b32741.npy +04090263-a2015aca6b4268c4dfe6ef2726050c2c.npy +02992529-e483787b7f9c606042f892024869e751.npy +03001627-cf20398c0c3e0359fa2037e5e59ff423.npy +02691156-98011d15300361e54f0e6f5b218145e.npy +04379243-e6cd72665faf3180f2cf6a9bef44d625.npy +03337140-9f17166a3193a8284c3aee8e9d3a6ffa.npy +02808440-b188074441f74c6e1d17c7bdc785739b.npy +03046257-98e52f275290d28bdb54f0ac1f9f81ac.npy +03948459-7e90dc936dc1a725fef144202cb2b935.npy +04256520-250f7b0081d2be215cd6dcd866c8e6a9.npy +02691156-c68efb547224f1dbed4212b3ec7c4371.npy +03761084-2352e8aa50465297df3a1b0d597ce76e.npy +04530566-6974280e14023bd6bf984c00fef39915.npy +03001627-4e37b83cc4f762a5f51f77a6d7299806.npy +03001627-1f83e49ecdf209ddd7f81f50826c13f0.npy +03001627-e5d6c3d62f96e28db3d655d5fe021844.npy +02828884-702cebffa33a19f019f079d1b712f46f.npy +02828884-e7bb6ef568db1c986dfe473551340375.npy +04379243-bc644d8f492e3c25febad4f49b26ec52.npy +04379243-ea5f45fc61e1e26bf994e2a430ba61bf.npy +04379243-6fb0076db4a74b73cde18cb90697712d.npy +03001627-9c9f007599018973f51fa0238791f5dc.npy +03691459-afcd98e6a91b3d16569e2e0d2caa039.npy +04225987-94fc692e0518c0b0537d393009a79347.npy +02958343-1f604bfb8fb95171ac94768c3754c895.npy +02691156-9d230551c65af968b207f792ce9b3f25.npy +04256520-d1a40b075d8aaf62e7c7920f6a65a54d.npy +02958343-e2bdf01abc79a8d054b49557f8ea8b42.npy +02880940-c6be3b333b1f7ec9d42a2a5a47e9ed5.npy +03636649-a0a87d63af355b45615810b8eabca5b3.npy +02924116-6f2a91e27189d62f8bdce51dfacd37e8.npy +04379243-30b176f8b5e7e04ceed0bb714b97ca82.npy +02958343-49997c6f094c0f5e785c95dc3e37946.npy +03046257-3ceaeac7f8a243babd4bf7024dfa167d.npy +04379243-e588e603f5d0e366490ad276cd2af3a4.npy +03797390-b7841572364fd9ce1249ffc39a0c3c0b.npy +04379243-72ac0fd17bbe76375af983a27c524ad0.npy +03001627-313ba5c62a7e746d2974cfd5336a9b09.npy +03001627-1459c329e2123d4fe5b03ab845ae95c.npy +03636649-d0018775e9f2d109fcb8d8c6d4df8143.npy +02992529-43f7d0cb3f0ace029bc144914804a8be.npy +03337140-484a99e5ec7ba9f4b2029d92310f4aeb.npy +04379243-a6b54c79a942cad5a6589c01f678d8ea.npy +03001627-2df8d2af1bc4b9972056b4bd5d870b47.npy +04379243-689fce16d1f9099b9aebadb76803631.npy +02880940-2ffe06ee50ec1420adbe0813683fcfd0.npy +02691156-e0bb0ddf67462f4a8b686f76be476fe0.npy +02691156-7c4e1ab21e8d6549a46ec065c01b381.npy +04379243-e18b448f7e5f6ecc1baf720a45fc5c38.npy +04256520-c529a567cf7e69e2c16bd6fd1b8c7eae.npy +02933112-5556112e5f36cf2755f46d55537192b6.npy +04004475-75dafc4c55f370dd85cac25b72167160.npy +03991062-f6bcfc4694d8841596716aabcb2fff20.npy +04379243-785c03a00ad37ffb8b424343280aeccb.npy +02691156-96430e8f2174428ecbc790a63192d2ab.npy +04256520-c41b7b7d81b7ea5c60a641d065bc7a27.npy +03001627-c447f8e63d691e6f44d8225a445f54eb.npy +02691156-fd41d04f1aabbaea3fddedb0bf24c68a.npy +04379243-b97cbaff986d5db4490ad276cd2af3a4.npy +02958343-354c1c380911fd2f4fa6b747e2cb679.npy +04256520-ab347f12652bda8eab7f9d2da6fc61cf.npy +02747177-cf158e768a6c9c8a17cab8b41d766398.npy +03001627-72da95dd6a486a4d4056b9c3d62d1efd.npy +03046257-e0276227890674bae7169d15a0f0c88c.npy +03325088-1fbbe439f321bc2fb362845c6edb57fc.npy +02958343-d443e86ae023ceeb16abce8cb03e7794.npy +03636649-9936875de81346fafcb8d8c6d4df8143.npy +02691156-dd949574a91719eb7ab25516d117381a.npy +04256520-d6176ad267c3ef92f51f77a6d7299806.npy +04090263-fbee616945eba3a3dde107ed8a50fb4a.npy +03691459-12e055813ed50b7b85d581c11aa2371c.npy +04256520-16f90b5e8d9a36fe35dda488a4bbb1e1.npy +02818832-fa0e6c923694daab5fc6df6674be3b9c.npy +04401088-ff1e484e02e001bdf8a0d9b8943b4050.npy +04530566-67b312f1ecd5e4a9810b5070d24f8934.npy +02808440-babd4a4655d271b8ccd0340812259a39.npy +04090263-7bfdd659a04c412efa9286f039319ff7.npy +03790512-e3de3a51ebcc57f2635b931be375e37.npy +03001627-39b1cdf79b58062dfff16555386d173d.npy +04256520-f36535e1853b9aa5fbb258508605d4da.npy +04379243-535b4f96f57a03b2bea4b6e7618432.npy +02958343-ccac541c0db2044736815730d7fe4119.npy +03797390-bea77759a3e5f9037ae0031c221d81a4.npy +03001627-e89c76bae2ce47bcf4b6538438a0b930.npy +02958343-e3d7833469729b2024da76692f3228e0.npy +04256520-e817922063c3b24ca296c91af58589c8.npy +02992529-e1a4ea72b1f98e92d265c94f4d41d924.npy +02691156-ee30cf94a209a45b91d43bb96e1bb0b1.npy +02691156-6df2cf3685456b4c2e78e1154b9a2647.npy +03691459-bb304ec80f4ba31f8a0181490cb73cbc.npy +03046257-e8d35dc16f04ec9b70012411145e4fe2.npy +02958343-d4cec810b46292ff1f759e96682e340e.npy +02958343-1ebb7511feac4d62381a9e1cee6d0b00.npy +04090263-a8b352220fa53a06a0834a5219dec81f.npy +04256520-e9d6a366a92a61d979c851829c339535.npy +02691156-89a6407ce86efaeee1211756a8e887aa.npy +02691156-34d467fc26232f53f36024ed2c0874a7.npy +03691459-d5c3db96ef6559cbd867c39c06b7c506.npy +04090263-69cc7f3dcec397cd3215e5c5313f5f42.npy +04379243-ea5f31892496ab5457c6852b34adaf61.npy +03636649-e613b3c2006c457ea35a7666f0cfa5bb.npy +03467517-7ee2e600f132bb6f93f0194265a9746c.npy +04379243-26d22dde8b0bf6a345891653421dc140.npy +04530566-10fe40ebace4de15f457958925a36a51.npy +03513137-587ff99119fe5c0efac6099f3d4830fe.npy +02958343-1bb6b1ff46096f592dfac2620a0cf07b.npy +03593526-8c8f6d2b7b2d8dfb60cbb0bb881f838f.npy +02876657-be102516d65bcf23ff59f7e635b49cca.npy +03337140-1201cc45cd7348c94c3aee8e9d3a6ffa.npy +04530566-92e4ae4dfff684832dbef90d406185fa.npy +03624134-faa118fc5de302338ba8cbbd590b1b6b.npy +04256520-9e014bda9022a09095369230ec06c72e.npy +04379243-f9509165955416a79b4cf10910d2df7e.npy +03593526-477932969f473792433f5a7a254e9685.npy +02958343-81655a19f4ce2daa8fd988235de2147e.npy +02691156-71dad8605fbc699623fc69eefd95e6d3.npy +02871439-efcc1769d931a17878f02ba681da30b5.npy +04379243-1460b1e3fb02755e67db1ddda25e199f.npy +03211117-85e99418c109b98e8324c9a156c64d52.npy +03001627-8844e3830bbc5610d5cba62773b8025b.npy +04379243-3a8c86ee236ad156c6542d86974f9497.npy +04379243-e3aa92f57f96a50c4ac1ecd2766586e1.npy +04256520-777aa4f75debc4e8acbda81da5062d85.npy +04379243-1af43a3e8d164168e563c86a0b8645c8.npy +03636649-c7507804ba5ceca79573a52ffe6bb4cc.npy +03001627-5875ca8510373873f51f77a6d7299806.npy +02691156-858c0e466deead2c66cf1b4a8fc3914e.npy +03593526-73d1c7ed4bdb3bfd2f2318fdd66be40a.npy +04225987-488b9ae283b800b282ec895e014b9eb3.npy +02958343-81c52d54f9719736ce27281f3b76d1f5.npy +03642806-1bb2e873cfbef364cef0dab711014aa8.npy +04379243-2c8cb823e48531fa9d1db1d6d9537bce.npy +02871439-6726fdc49931be21d810b14a81e12eca.npy +04379243-6e18de4fa33bc9bcc0639593f50066f.npy +04004475-e12178732037ca9659e0838386a22482.npy +04554684-cbf8ea778b70d1c5ae0f84ab89df135e.npy +03001627-821c88bc79af232bf2acefc3b3178108.npy +03636649-26f2f40fa7fc0c5538b28f94c165f833.npy +04256520-34117792b1a8c180796c584ff1fcf56d.npy +03593526-8c9ffa8ee8f3b497e987f10c30c67205.npy +02691156-7336bffce72ea58b90baeef8ba5b93e5.npy +04256520-d29d2c5a1b35b85b40f0ac0fb9a650d.npy +02691156-f3660119189d3eca4c3a35cee92bb95b.npy +04379243-76635dc55e9783b6c8c2a1a2edf00686.npy +04225987-1e5fd1de723cc66cbb1ed6d4d8526a19.npy +04379243-1a5062241d7903076f88aa1b7f7cc6c6.npy +03991062-7cb2622fdebdb03736b0f2a1430e993a.npy +03790512-40b7a63fd9ede0cf48272812609617e2.npy +02691156-eb7bf553e500b9b544bf3710e93f8cf7.npy +04256520-9504e9be67514fe9c862eec8232fff1e.npy +04530566-deae1ec7a6e340e7c500d4aac3b87ab.npy +04530566-4cb135ddc5d3211c713a67cd30c1e1dc.npy +03593526-311399898943198de59f529cd1b6faa8.npy +02992529-521fa79c95f4d3e26d9f55fbf45cc0c.npy +03691459-5fdb0bb9c3c18d50602d6239bab56abc.npy +04090263-8181c6ea706bff129f433921788191f3.npy +04379243-1455ee780321fd14c3bd24f986301745.npy +03593526-3ce3a0a7adbaaa518e43a810a63361f0.npy +03001627-76d5bec920a9796a5e91295f1f8b2c67.npy +02933112-4e02dea48a1bed6bc59350d819542ec7.npy +03467517-d2cbbe7311f3699cfa3f3bbe4549e789.npy +02992529-2163366f7c3a7a0e6c63b8b48495261a.npy +04090263-c394a39997adf53d319f02af7c25cd6.npy +02933112-217d29a61745991f7aa75dfc74adc93f.npy +02691156-154146362c18b3c447fdda991f503a6b.npy +04530566-123c021333485d698a75485f44bcc744.npy +04256520-f78da0aa23162f3850cf3715818ccfe8.npy +03991062-f4fd4566ce4494b5a2c59a4d90e63212.npy +02691156-90612205109d7458e84aab2e1d454e3c.npy +04379243-3b57aa434803b0ec189c2d5c093a2652.npy +04256520-fabbe9b0db0846a8a823d9fb27aec30.npy +04468005-f6583ccb70cd71aa5ba3252cb57e6f4.npy +03001627-86a94d95c2aadcff1a1584303f0b5ee9.npy +02691156-3713302f0330f960970864f653fa080f.npy +03001627-518c58b170bf5847ff2c92c2a4f65876.npy +03001627-e9043a68f672c1f3a8699b6183baa203.npy +04004475-870a4a67312cde4562b4217d4b905122.npy +03001627-3797290f1dc83a3ab0e5659877cf3f6c.npy +03001627-1eb1a8acd4185f49492d9da2668ec34c.npy +02992529-4a0cd042d7479d6810bc2436075f6a52.npy +04379243-9dd5b7e6f90ee322b56d92c5d7b06038.npy +02691156-bcf7743f0dc85517bc0909d98a1ff2b4.npy +02958343-338eb8e836639e09f8f1f8fdb364ff3c.npy +02992529-fe39a57b8137ecbd5b2233351507f22f.npy +04256520-c55d36457611e7fb826fc8d57346a2e4.npy +04330267-3005a944902cf639fc1390934d948e09.npy +04256520-3e4a24e15c63edb95554764d7c3c0e03.npy +04530566-8b335b0be37debefd85e5191b992b560.npy +03001627-30fe29d73b410c3855efe429bf27a556.npy +03636649-d59202f9d1504c8cc65f1ed6a348c8a9.npy +02691156-d458335c758930c210b8e0008ef5faf6.npy +04379243-679e46c5c67fadd5c3bd24f986301745.npy +03991062-c1923b90d48f2016d86b59aca5792b15.npy +04379243-3441002a52b1cb2946b2a76c074a3f45.npy +04401088-16d7d7be19cde848dbe1e810cdc7471d.npy +02808440-c5a860b9e3a4ef5915aea01a869de65.npy +02992529-e7bb86cd04cfd98758f1d9dcdcb62d55.npy +04401088-fc07770a57d7a87022d3f170937c6a0b.npy +04379243-bd78847e636133c179c8c70bc853d3a7.npy +02933112-d8d2e500860312bf98d5fc0473d00a1c.npy +04401088-cf3f330fb6e3e034449ec657800ab951.npy +04379243-281f296380a0e4a81db7abc68608fde1.npy +04379243-98e8e686225b86aedb7603860ca917fe.npy +04530566-da675d2149827fe56ba3edb0853a984f.npy +04379243-b98dd46e9c1101e2214a15a5a42c49c0.npy +02691156-521916cfab629ce0b6ed9420d56b12a9.npy +04225987-bebaf2c5077b901e92ba7d308c045fd8.npy +03642806-2211a40cc77a085362c091e763f81d3.npy +02924116-791ea9a0664cb42a2f88d2c3eaf53e87.npy +03001627-4fe20ed873d1a80e21d25a6a55757584.npy +03001627-b11c616a19d702cdd7f7a4c4609b0913.npy +02691156-73945c1b294716e1d041917556492646.npy +03691459-e465af1099b63258e17b9e33c097dbff.npy +04468005-6c2c6c7e47c573ac636b52a9d219d297.npy +04460130-a422b6788bb8b2d5663d09b37dd6bd68.npy +04379243-2406cdcd4c60c84132884c4c87a2e061.npy +02933112-94cc8a8df8c78f5e14038d588fd1342f.npy +03001627-48fb419e9273c10a936e8f01c80c6ffe.npy +04379243-8a91b91802db34ea409421506a05b6e1.npy +04379243-49ad167497a2af8c9672e39f89e4622e.npy +03001627-31a3884f500d9fa2025d98fb9de28cb.npy +03325088-70221de88e240b1fb7a867e9b35a1295.npy +03001627-611a76dca411bf089579c5df0e7fa96.npy +03001627-774b94fd956a6601194565c2f3f896dc.npy +02992529-a3f4cae960ac74babc54d4bc75a1a826.npy +02691156-ed7e1a38fe33830b87697d3904b168b.npy +02828884-aad17ac8d5a1ccdfed98cca8f0ccd5f7.npy +02958343-4af44c67c14a477661c6c61410fc904b.npy +03790512-75f2dbb8204c01a4e1720743367d35c4.npy +04379243-4bf64ea69b9e7c85cf004563556ddb36.npy +04379243-9112b638a62b432e3521fe8ac6222005.npy +04379243-c4bfc29898e5a1b490ad276cd2af3a4.npy +02958343-a2a795ad86d1fa12f3aaed7e86215c7b.npy +02924116-d40461c73eef2a7ccbdda2562495e10b.npy +03759954-1d4ac8a8704792cd8e4c2796345a20e9.npy +03642806-20d42e934260b59c53c0c910fd6231ef.npy +02691156-72761d1c2c7e1418d86ebdaa02a63c4b.npy +03691459-e1385ebae6a7869d23a4cda08ffef080.npy +03001627-586b90e4b5e0530935836c728d324152.npy +03636649-75db7c2c9adbf2bfae18328edc91fc39.npy +03001627-d0fa70e45dee680fa45b742ddc5add59.npy +04379243-d1fe23dc2b62082121f2d1de8124ec62.npy +02691156-909548225096784cd5cf6c89d6cfc357.npy +02958343-a81d28a70bb06e18bda733a39f84326d.npy +02958343-5b0710d5e9467e847d80f0c0ccad8837.npy +02933112-d4e6002f0114461df879b7d55192442a.npy +03001627-402e47d9e3f825dcb9d7c2fc41e80228.npy +02691156-b5589ad89ceab860123d1d349cb8cfb9.npy +04379243-628c4fe12881efe2bababe11fcea8796.npy +04379243-a624ebf0bf0451a8d93768e7b9b1eabf.npy +02871439-4e26a2e39e3b6d39961b70a6f96df2a4.npy +02946921-d44cec47dbdead7ca46192d8b30882.npy +02924116-66e9addf909a3414e99562689078395.npy +02818832-41af7173657860b9dff53899485f7c2a.npy +02933112-9dfac0132596ff09b13b0af4c7a59aa0.npy +04379243-bb41a57386b1594c218a519212ed7c98.npy +04090263-1c292bec142b39a5aea3c9294e3d898c.npy +02691156-5608c1b40a0c2fc9c2912ef1a1302821.npy +04379243-ce82dbe1906e605d9b678eaf6920cd86.npy +04256520-cb61e530b7c20409512941e37c7d7dd6.npy +03001627-6895e7aa3c739623927045b355fe1fe3.npy +02843684-7bf5608a4d2c66bac5c86021644af7b5.npy +04379243-2bc4caa1941fed746500462ee46bc39.npy +04256520-48834ca61f0b759583e21877a4e60599.npy +04401088-d41b332b9e6efddaa0eb5a85db887292.npy +02958343-7aff83bed75b6778e5e8ebca62d4509c.npy +04379243-e38b1f4d210fb038c97f93e2910df644.npy +02871439-3e6962cf9ab0ec6d5a7942170a4965f4.npy +04530566-30e45246151fa36a9cccee214bcb0021.npy +02958343-8601cca4ddfd28af18bc22abef3f86ce.npy +03001627-bea7cfa3c0e7e16e63b2acb037dfbcde.npy +02691156-19a624cf1037fc75cda1835f53ae7d53.npy +03001627-7ad6cfc9aa35aa058573c953964a33bf.npy +03001627-226704c72560008421ceb39dc3069834.npy +03325088-b8bdf56796b123cb60cb08c7d22af96a.npy +04256520-46f1ec4173d32c0bf1af69e9778c153f.npy +03001627-d75b618231bf0815492a611633bf8558.npy +04379243-209b2271f9434cb3c242632b2a8c3129.npy +04379243-4fa9bcd45574827d4f0331b81f3e1ef.npy +04379243-48045af90c7959e5738e43095496b061.npy +04256520-b2aaf37365cd30776b9a660069df73df.npy +04379243-49a5c5f524eb73b8391e4d6c585a697a.npy +03261776-de3b9b253e8f1aaf8b15c58b209760b5.npy +03001627-faab798b13ecba08e9f0f0173ae2f184.npy +02828884-411f68beb7d27135d1dcc55e36186e4e.npy +02808440-76ebf4756a43b187753793048d44830e.npy +04379243-aa118e3ed06f00a85c886bf880a258e.npy +03001627-ce463d63d8771c5ccf19858fd1963d10.npy +04256520-7ddd55ed6481457d4211cc92ec35b195.npy +04530566-90c5c6b05a71381cd97a7aaf09adfff5.npy +04379243-2b1c1e0fad3cb3b8fad46760e869d184.npy +04379243-5f726d7fca7ec04131ec2883e34b06d0.npy +04379243-836157300c030c9a246b9f2ca347e8e3.npy +03636649-e4e93d5bfcfac3d72518f0b5d8933d6f.npy +04530566-406e7646609bc8bd8a53c9119bc523d3.npy +03001627-6a01eed3a575987211e48e4bcdc4a2a3.npy +02808440-e696c5d9b42ff5a0fe52ffd0e748a1ab.npy +02958343-825fb860d71c78a477c771b4b7eed82c.npy +03642806-6489453e322cdb53f9f3c6290096f50f.npy +02924116-805d11fea9dc852bfc319b95010c3346.npy +03001627-11d8814ed60b54002449009b96f8a6ed.npy +04530566-3d4b80858a5ae3d694daa4565dd30535.npy +03211117-9de3c0365edd0c0b3e487c876d55197b.npy +03636649-a1d2540e0ca159ec0735e7fd8e163ce.npy +03001627-4f81153b0a3d2fb25f5359f3b8f96a06.npy +04530566-54cf5783ca03b3e015ea3a1685d773da.npy +03325088-c2a09f60c43de534974f28a8ba184023.npy +03001627-9265413a74278fb5e45ef4135c266a12.npy +03467517-8a867571a5ba0e9b3de1a463b8ceba0c.npy +03642806-a59d3d87068d313c2656684d670220c2.npy +03467517-58de2533b7ce80b237058b1eaa7b4b1.npy +02801938-4b520e02e5bfed6ab8183a4a81361b94.npy +02747177-65d2760c534966f2d2b12aa6a0f050b3.npy +03001627-5d7b94584595d7a9118486d21a76684f.npy +03467517-83d6903f31a3e64c14268fe96e3c901b.npy +03636649-c4dc0ac169c91ff29f8c3d2002c77ddb.npy +04468005-79b834190bfcf065bc7069dbf29b2330.npy +04256520-be129d18d202650f6d3e11439c6c22c8.npy +04090263-5b6bf22e5c355592882cef3540bf556.npy +02933112-985eb4a8f9914873738e43095496b061.npy +03001627-89d2cbab56c5a1d7297056ac457c1c31.npy +03624134-4e39d4aff37d8502a0fefbd3658c7966.npy +03001627-ee03232aacadee87d4266d69a5c6f129.npy +02992529-b8a2c7c7df404ab8e7ef9fff09638f8e.npy +02691156-a211208ba6b752b1e75e6a02e772bcee.npy +02691156-51f51906f12681a1dc82b8fee1057b30.npy +03001627-6a20911ef197f358efa66822a012535e.npy +02691156-5a6eb0f2a316f23666cf1b4a8fc3914e.npy +02958343-3363bde33b9abfbf7c5640de9da0cd4.npy +02958343-66baad4c6e4bfa08cfd826dd468a5497.npy +02828884-17ebf60b6ba61ae949e6f7df978f3373.npy +02691156-149702d4e275568c18b14db3b83de9ff.npy +02958343-c4bad2da39f8021b3554e683803baa4c.npy +03261776-32b0b35517ed72e5fc176230c2f2d294.npy +03001627-3f7808c221b01668b4d174e5c61f344.npy +04379243-e4c8211dafa5b903febad4f49b26ec52.npy +04401088-44ce10ddb982c8ff72152988eac576ab.npy +02933112-72048f89b480cd411b17743c18fb63dc.npy +03001627-e7b1407e16d9d644c681404257d94ad9.npy +04256520-7cfbeb2c5af830a26a97150bb2a72733.npy +03337140-682ad244abc1c36991c352d02061b3f7.npy +03467517-e54a1fb20957d39dae8a6b22091f0f0a.npy +04379243-6a5ff41fa5aaadf84c29eddba1f2e390.npy +02933112-72d950ea1c029bf2369c46027bce7af.npy +02691156-9314289f486e58caa8cba409c4409ba9.npy +03467517-c73e40b1c97e24d8a1f251d725bedef2.npy +04379243-88c9c7a40227e935487003545673a337.npy +03001627-c0f18b32a4124eccad9a0199a27b3d8.npy +03001627-4f4b6167ef11ae4e8f8c11a24c52ebb.npy +03513137-7f8767aac7a5bbefef6f32a2a0bd4e8f.npy +03211117-70dacf62da510868a5ff93a193b16554.npy +03001627-63b2f7846c561efc20768660cf080d12.npy +03636649-1c003aabfe3e12976fd90c386180831a.npy +03928116-ef21ff42091957d19df921a933a453c5.npy +02880940-7995c6a5838e12ed447eea2e92abe28f.npy +02992529-d7ed512f7a7daf63772afc88105fa679.npy +04090263-b76f8c041122b2dbf112f20f44aa16b.npy +04530566-28be32d7361adce59e5ca238b1551011.npy +04379243-f09ef9a34df9b34d9420b255bb5956f0.npy +04530566-421db3c87037e7d6c2363c2f18a57bf4.npy +04256520-3ab95ff520d0970b6ae963205db1109f.npy +02691156-9300dc1ca5f16b074f95630cc18536e0.npy +02958343-9b4324a33b1dbad5a7fd25564c2e888e.npy +04090263-afa74746fa10939d153a22537579621f.npy +03211117-45a4d128553abb329bf8498db368caef.npy +02958343-949f6240e1a760992dc53e2d2dfd58d0.npy +02942699-7e677756898b40dc39513d756da531d0.npy +04530566-c74fe97df26a078facae7037c88ca7f5.npy +03001627-a7d124f0c0d9b27479b3e1be3524f72f.npy +03513137-b166d9115ed7b7638e75bb5638d14ce9.npy +03046257-435fcecdc24372a09e4965f0106e00d9.npy +02828884-eacb2a4fc51d03853c7e5bbf72a5f5ae.npy +02958343-b4d258dc5a12f9f7ade7f700b19bcf4a.npy +03211117-7c06bba1afa0553225a454369d791fb0.npy +03211117-15e7231a97ccf7953aeb14563b37e04a.npy +02958343-a7b76ead88d243133ffe0e5069bf1eb5.npy +04090263-fdcaebe1ef2f44406f21883e4b04581e.npy +02691156-560e0890ae86aa7624a25a765a1075c2.npy +03624134-223792d53b9d4d82ef1f81f15fbe736c.npy +04090263-82686f0ea15a7c24783a7c2adc432e76.npy +02992529-36b3329dc0bbd86989704dab2d2a8ab9.npy +02924116-de66b87e4f485c7f1e797b014c500fad.npy +03001627-6ecbaaaebb241ec34b3c42e318f3affc.npy +03642806-76005568c6a76385c8f56abbf37ac61c.npy +04090263-3a8526095bae7e553c79ad8cab094d8.npy +04379243-89c095a52766ecb05d2ac47f638a4ea4.npy +03759954-64af172f468f76a89675998826ae9066.npy +03759954-d9f87094f6a26f8ea2105179d0c9d51e.npy +02801938-615e24df86c59f4536b0f2a1430e993a.npy +02773838-68e4ba38895d820df6fec4b901a12701.npy +04256520-37113588c2d2566b4cf08511890c3458.npy +02958343-bccf69e2dd7de293ab2c2809513f396e.npy +04379243-9d832f72888892e66d907bf61e189d9d.npy +02958343-ea7d39fcc3cf045dfc73a41845471b0e.npy +02843684-ff90921e9631cd73c5c86021644af7b5.npy +04379243-54ec14c2afc2b7e37c5d07ba5fee5aad.npy +03001627-f268849e43f64861cb3a30f2c37c38a6.npy +03207941-f45ee6ab44e4be364f31b34e920051c4.npy +03991062-4765238a39e2a6f8ee5c4d873ab1a054.npy +04530566-1d389060e50915e223676ae79aaa08f7.npy +02880940-8d75c3c065fa3c7055f46d55537192b6.npy +02691156-214d7c0720b860091f21e5fbc0306e3e.npy +02924116-f4ec3e8621e5f7c88317d5418fbadd64.npy +03001627-4a63afd1da7fd633e6c5cd45aa112726.npy +03001627-df8bb7ecc402ede384a05e54516915de.npy +03948459-a3e6dcfc074489fd8ec2966c0323533e.npy +03691459-4d276aacd5e4c510de7da340cde8d034.npy +04379243-2c094e4bfe5958267da1098dc15ca7a2.npy +03211117-de5813ab2771ed36c3c11bfa5a6c7ac9.npy +03001627-951fb0d7ad8ab2bec5b5bea66ef4576d.npy +03001627-bc80b0b638f8a4e61a54bcb8e47577d6.npy +03001627-910bbf8701a4846c2993aa294808121b.npy +03991062-6cccc41151a9578d4b3c42e318f3affc.npy +04256520-159a8e14ee6dde05f7628281ecb18112.npy +03691459-f6958e13ea65bd521b45df3fb820c9cc.npy +04379243-7170910538470c80738e43095496b061.npy +04379243-515460eb527d3439e76bc197b3a3ffc0.npy +03001627-c0e3582a0c8273653c4f66791e25960f.npy +02958343-816f9a529bf7b14817d5c90faf553cc9.npy +04090263-561430988b5af11bd04b05b0f20a897b.npy +04401088-bcc1760ef463671c825b62bd6c28eac.npy +04090263-4327920bfe590d3d262eb9a9badf3c08.npy +02924116-bc65e17577d368674568f0f5b16acc69.npy +02691156-cbf4dc1c144ce656ffa79951b9f955a3.npy +02958343-9eef7b2c492bc1181f4a259ef9bb479d.npy +03938244-84693d928bbec2d18b14db3b83de9ff.npy +03636649-940a5e53f69e193ff42a90fe4baf4591.npy +03001627-d8c6c9fd4919e7f1c8d01774acf97a.npy +02691156-f5a8cae96024e709c1ccec171a275967.npy +03001627-e6a4d6fbdf722dbcc6ec74cc40a0a09a.npy +03636649-368188e7a9b9e1d3c24c2251620b1cc4.npy +03001627-e6b9b5d8b55df575cee7fc32eb84f3e9.npy +04379243-2b34724248743a36a71c812e027f94d9.npy +04379243-bb838e62bfa44f538705931e60ead6a0.npy +04379243-44a525e7793e37c5d340e35bb5304768.npy +02958343-107a17c6f2dd9c488924120dfad0e290.npy +04379243-895d688a910d8ba0bd647f71fcfdcbe2.npy +03046257-8f6b5dfebfdf8e34b3c42e318f3affc.npy +02958343-c6ca5b48d1e5f5ab89442e34f9143192.npy +04090263-6a283eba0e45bc63525c1baee1f19994.npy +03001627-8e5568ec663ae1b7e7526b618f37b43f.npy +02828884-7a8a8c523bcaa364a41bbb5eb703e15.npy +02691156-16b2f62791bd9f003554ccf8c30febe7.npy +02992529-d4407c240737b0c73455cac94a339dea.npy +04379243-1826930f388f5398e0c5923879d79f21.npy +04379243-bfa36cca677c512357f3bb43ed044708.npy +03046257-9a4b06f731898365afb07a946d621b3c.npy +02958343-f378404d31ce9db1afe1d4530f4c6e24.npy +04090263-63c944adedf86b80f8915bea3ae2769f.npy +03001627-d601777b8862bdc8b04cb542e2c50eb4.npy +02958343-530234273d5e31a57c7baeeaa3dedfc.npy +03928116-9de441eb54ec578a5b39a37797d4a0c4.npy +03790512-ef5e9989d2e00fd0d95f95e5406fe921.npy +04256520-9f1de8e71c8a85f23087f84b199fd297.npy +03593526-d447f75ce8f0fcbbd5570174b221bf0f.npy +02958343-52ff21d1ba10add4bda72093f9b5aa73.npy +02691156-6c8275f09052bf66ca8607f540cc62ba.npy +02876657-77a2242bf4ea8f9fc02fe00a7187a6a9.npy +03001627-d97a4a6f84f40854f51fa0238791f5dc.npy +04256520-42265c6cc8d24be09cd3f9e8648111d1.npy +03001627-cb7a4324fdfa690e96dd43aa0ec847c9.npy +04004475-97735b38d3b229d5e8be809ecac11dd.npy +03636649-4d63d3865d635b2be7c7920f6a65a54d.npy +02828884-8d7f97ef9187d6fff4fb4dee5181bee.npy +04090263-9b1d60945756d2bd33f9b4d665d32f82.npy +02747177-ab52671bb9b66e7663996f7debdc929e.npy +02992529-54bb14aad2406a124ce28f0f1b509eda.npy +02808440-6f0f8249e994c288ccd0340812259a39.npy +03001627-d7307a92178e74e055c774cb358c4539.npy +04256520-5328231a28719ed240a92729068b6b39.npy +04379243-5d5fe5537c5496f71f344185981b2096.npy +03001627-6e6ab9da02b8e3bd9bcd01fc6568d728.npy +03636649-918b197d2a157d70fcb8d8c6d4df8143.npy +02691156-2af529843a47df7aba0d990ae229b477.npy +02691156-c27b08dad98f802488a89a28f04ce622.npy +03211117-42c0246643c8ad0a2af8f68791a7d624.npy +03001627-32c1445f65f4ceb23eec26c23f5bc80b.npy +04256520-e49c0df0a42bdbecc4b4c7225ff8487e.npy +03211117-2475d02352162243cba9caf4d254cef0.npy +04379243-f917474a20558aa33bbab77a66bc3671.npy +04256520-819038a4b8db3ed24b3c42e318f3affc.npy +04530566-e2e0d0dbe736e3164947b319a9e09fd.npy +04256520-68a1f95fed336299f51f77a6d7299806.npy +04530566-e02d395707464e692ef42ab47be9662.npy +04256520-c51dc6c9f8db03f51e8fb9cbb32d2cb3.npy +03691459-6fcb50de7df5381835cd53a06b1d2317.npy +02691156-8baeb2c664b0bdf4ca8607f540cc62ba.npy +02992529-1f93dbc9622d83de7a9f0bb7b1eb35a4.npy +02992529-f2158f4f4141e07825a703f74bf22d93.npy +03001627-5d3060a3470d853dfebad4f49b26ec52.npy +04379243-f3efcbd9745da90619fb4103277a6b93.npy +04379243-217430853f56075915dd7d7985e749c1.npy +03593526-49f9a29866f0177bcc4cd6c58bd35c0c.npy +03001627-4dcf1f64f70f22d7b4569422e5e8ba0.npy +03636649-913ba6b6ac6aea3356c82fefb25b338b.npy +04379243-4cb4f4d4bb4771dd1d1d518ba4f78d6c.npy +03636649-9b5d13550ee386e686c0096e326e950a.npy +03001627-38fed916a35dd43d7c8c503b4b873379.npy +02958343-361f3fa1f09d25f07a5533ecb7691f17.npy +02691156-b59a7cab8e95f6eaf3a7414a84b5637.npy +04530566-4a886c242f8d02c8b5d16f91270f7fa2.npy +04256520-1d5675c6d28fcaa0f797b840852566c8.npy +04256520-a4fd0a514cabe8c34fb315ce917a9ec2.npy +02843684-88d4727a4c13ceb5613af97d40709241.npy +04090263-59ff0c5e24abf33f25ff9d2d1e4772c3.npy +02691156-2f988bec20218fa19a6e43b878d5b335.npy +03636649-c54d3a5a9c8a655e46407779dbd69b2d.npy +03211117-5318296d6d07e4e6d40cd81b129905bc.npy +02933112-4ac617dbce5ab494985850bfaa8d58e8.npy +04379243-95bb0549666284168d2b632e2708f79b.npy +03759954-179d23a446719d27592ecd319dfd8c5d.npy +03624134-a55c89bbd589071aee8a029f52654d3d.npy +04530566-614aaafb767bfe62dcf47132cab9d51b.npy +03467517-da8ee6c488a2f4e093f806b1ecaee483.npy +03001627-4019ee7cc7cc5f9e74dc49346c29fd4d.npy +03948459-42358a5cfc9dac388dcf178d0ce30874.npy +03001627-5c86904bdc50a1ca173c8feb9cba831.npy +04379243-6a9c7e9f19cd3583be92df29bb41e437.npy +04256520-26b508c478a9d363f51fa0238791f5dc.npy +03948459-1568357acf75987586ecff2582325794.npy +03642806-62036dabbd9ffa71549c63d8891393c6.npy +03636649-a700451d593a56b45369e32fb818f337.npy +04090263-fd2223d0b93e34dce3bdba9430565083.npy +03211117-2cb149b137f5182ec2c4d83da2705396.npy +02691156-a05347463ea86f1ecc777fcc6b5f19eb.npy +04256520-262833bd44fb0e522535fd8b96de1b55.npy +04530566-4adb08a459076889574b6f4c9eeb8eea.npy +03636649-1e322c9d236ed96d32acbbe2387ce75b.npy +04554684-22c6787bb43651f0f6eb1856550bd229.npy +02691156-fdc1a422b48a16f67341d39902b9e2e1.npy +02828884-7f1f873921ae0c63f155d75bbf62b80.npy +03691459-dbfcda5d40ebc2148bbd829479b32606.npy +04225987-8cea38648128ef1ddc75c30c88b2f7a9.npy +04379243-5bd924058c668abc269aba35b84eb82a.npy +04379243-dd46ae4a6d6cd1154b3c42e318f3affc.npy +02958343-17e146cb10c72fcfa2b80c598d71bf14.npy +02871439-fe571828e5b34d379d0a249a140da12.npy +03636649-b8e25e0825cb5db7765609a3f435fe9d.npy +02933112-4c94892ca2cd066e29a50a2b3c5e5b6.npy +03001627-4e8d4cffee2c4361c612776a678dd571.npy +04468005-34be2cf5c79e6648bb9715d4fc6aab2.npy +03337140-1bca7b1a5b92f44f492d9da2668ec34c.npy +02958343-234902223d35129de74a9a0d75c085be.npy +02933112-78c4b505894342269299936b751bd77b.npy +02924116-7c32b9a627f9f8ba41cefd10ce5d6cc0.npy +04379243-8fc0e4d561b5f551dcc34b96ec9c53d3.npy +03001627-7792861e0bdb95a270a43c2d978e502e.npy +04379243-ce1e09dec6387f715fcce4c360a80a36.npy +03001627-57a20ffcc530b8693b48a711df82173e.npy +02933112-580add3e9e4bd75939a06c149bd5b5b3.npy +02691156-5294c39d2a57bd7e5cad6226edb8e82.npy +02924116-27b7d3f2497848f87f0c75734d52cbf3.npy +02924116-98a557ce95a4e0fab0551d95e7a31051.npy +03337140-34e0bcd04523ae59d477567e8c8a6c59.npy +02691156-bb38d29611ba34572af1006be0f51835.npy +03001627-4a50449de8e26e82eacb498394990f0d.npy +04401088-c4b66fac952d4ef7d9039fb3a1715e96.npy +04090263-7d286b812a03c60e310bbd45bf9024da.npy +03642806-f4c6dec2587420aaf92e5f8fe21ceb0.npy +02876657-25b8ed5b02f07b6cbcfad79fc308fa6d.npy +03001627-c40ea8f03ae6407462e682c9809bff14.npy +03691459-63f06aff0721b648f322c3e7acea58f1.npy +04256520-dd1e9b6cfe8c2ff65ff61a3a2a0e2484.npy +04401088-2274e1f494d6d2c3226bc3b9ce9ff2a1.npy +03001627-25fe34942b619a2eaf7a219828cdb9da.npy +04379243-17e5a64889ca085fa5526f91aecc0c37.npy +02691156-ecbb6df185a7b260760d31bf9510e4b7.npy +04530566-c48ed09355e7ab34275e12937d8e1776.npy +04256520-c8e172e5708b1357545508cb156187cc.npy +02828884-4e3d100672af00842dc02296076d8ee0.npy +03001627-3e08f5809c2abe523ebc93db58e716e.npy +03797390-1038e4eac0e18dcce02ae6d2a21d494a.npy +03001627-9915f9247f671893b89b3e01b90fe955.npy +03001627-337050c0a5a7f965cc5cf3ad66086732.npy +03691459-76007907d4e0ae438c2ccb23eb70d81c.npy +04530566-7e16ed13ded8aba83f59687345e725a.npy +02808440-2ebcb0c668523047b362845c6edb57fc.npy +03001627-a1d217ba806367cbc13a0d88b632af1d.npy +04401088-85841bf9d27c85a26062f54263899d21.npy +03467517-d91b0745e57f6508dc6782957fd2f5d2.npy +02691156-e3dd7fd80f9e53be6ec2a8147a044691.npy +04004475-20af8c248e5719e6aa76432aa0a31cb.npy +02933112-2c1af98d2058a8056588620c25b809f9.npy +03593526-4c2eb778f9b6485480067e3fdc6db24c.npy +04530566-57658278fe1fe0571711b4192259c7f2.npy +04090263-8f70b211673e64c9c97e9355e94c4f15.npy +02924116-8b4bf94aeebbf8a652470de2774d6099.npy +04379243-82130114fee63442f51f77a6d7299806.npy +02828884-f136c5515364f62ed98cca8f0ccd5f7.npy +04379243-fbe97577070afd195c1975633309d43c.npy +02871439-e444eca1d18130c318f52c8a4cfcbe33.npy +02691156-ef0d51f895cee0e04485f82d9fa383bf.npy +03691459-5028625facbf77991a622b6f91cfddf.npy +04379243-fd79c30bf108dced1b17743c18fb63dc.npy +04530566-99ccd811a0e3052634e1b4a71050e6de.npy +04090263-60fdb51a9cc4011289172d41dca064d9.npy +02958343-8db161338795c215b1bb46d2556ba67d.npy +04379243-1bce2f4937d36446a32c566d71fa585c.npy +03691459-1e3da9e2f274b6a89585fee86900e65c.npy +02828884-18f57a3d41117140ed98cca8f0ccd5f7.npy +04256520-baaf2c0d399f7329e4b6769f60f49f2b.npy +02828884-dbd0698df1623b0391da37ff8bdd2524.npy +02876657-6b8b2cb01c376064c8724d5673a063a6.npy +04379243-dad614e8c01b8acd618778e799bced5c.npy +04379243-19e80d699bcbd3168821642e9a54505.npy +03636649-8e34bb5570f790b0796c584ff1fcf56d.npy +02880940-8d457deaf22394da65c5c31ac688ec4.npy +02691156-bb976c45b6812b9254e2b6da60f72ab3.npy +04379243-f726fcaa1d031391b2a0fa0a5d25776d.npy +02958343-be1929020e6bb4c9c2920de4c5efc2ee.npy +02691156-89887eb7413e51a55970a7489fd4b4fc.npy +04090263-16aade23487b928b8084b8c11aeb922b.npy +03636649-397f450de4fc6fd4fcb8d8c6d4df8143.npy +04330267-aad8160404996c1b73c03aee5e8475d4.npy +03467517-1b1c78a14841a4ce3630a3b40acf3144.npy +02992529-6167bf752533508dfd6e968ab91bff17.npy +03467517-5ac1d8b6d9ebb18d48385c672f40e577.npy +02691156-803fd1bf9b85da0aa79201593c1eb4b0.npy +02828884-7a7ca24c50662907bb808757415d8a76.npy +03211117-d475b620ef72756f795284068bb430b2.npy +04530566-5c695e7aa51d16ee557500503415b4e6.npy +04256520-35ba544cb0a342e529404a50338e24e7.npy +02992529-383a304edf67f757769dec5ec0157054.npy +03001627-6ccd1ba0e0d4408e56c513edc77abd33.npy +03991062-c8efa3566eb1ce9bdbbc9f7db3c7138e.npy +02691156-f258c40371334a4e90b1d6deb98feec6.npy +02958343-30c2364393514c5b1c685cd768514e67.npy +02992529-f77811bd35b9215dfd06b6d6f44d62dc.npy +02808440-bde516127c10ceed3321831d2245cf06.npy +03211117-880cec9f3dff564af81b347089add3de.npy +02691156-6058d6701a0ca4e748e8405d6c51a908.npy +03001627-c2d0bea1edd835b6e874cd29a3bc467c.npy +04225987-90dbe261a4d56dcf1082f2ea630bf69e.npy +04379243-5ec5b95d9c21b05ea9af104529ef47c3.npy +04379243-9458b7fef8e84b819f2349486c570dd4.npy +04401088-a4d81a74a416b88948637414dbe9de8d.npy +03211117-7560f6f70263aeb9f5b8dd4ebdc4068b.npy +02924116-4306dc8fac0e49749f9d6858184e60a0.npy +02924116-f735f0310f9240227037eba625e09a52.npy +03325088-804b09dad62f32653321831d2245cf06.npy +02933112-b56d8e21ac71f5d184296c7704cc40e8.npy +04379243-5c466b385c17f36dda6f252b9392c507.npy +03691459-bc3e89ef012a5904688bf677a786d0bc.npy +04379243-1581d2682187764730bbd4cddd04c77b.npy +04090263-8ac5aa7414e3c30030dd2b88f7efae34.npy +02933112-14e612a7cd0311905b539ad6c08a7283.npy +03797390-214dbcace712e49de195a69ef7c885a4.npy +04256520-e09afc136efcabd0dbb841c441320b8a.npy +04256520-b526808fe0903b4484e132150e6e3ece.npy +03001627-57406cae1c2978b40c306db1f141b05.npy +04379243-f0cee441d88de6dafebad4f49b26ec52.npy +03636649-f0b19b0258e8f551d5cb6d178687b980.npy +04090263-8fb14c7aad8e829bc6e84bc30e573cd.npy +04379243-b29e6b183014b61e49426bcf3088611e.npy +04379243-c9a3680859a722a0858699aaad4acee4.npy +04379243-dd363031a195991631b72d9d4e0e505a.npy +03001627-4fd654bdc7fa4658b0957d845ac33749.npy +04379243-424f30af1472fec6668ae11a7db5e82a.npy +02958343-856c62efeff8401567f6fefc01cc7126.npy +03001627-5a85b2ef58145949213c3458a0fe5598.npy +02691156-4d223d7a0e8162cabd46d022fd7d80aa.npy +03001627-98dc530eeece9f0ac3d18d4b522a4e80.npy +02691156-5739574537212a72b3f2b01de37c0b29.npy +02958343-3c6d7c6ce950917b3a93df79ef2b80ef.npy +02691156-7c76d7d8ecfca9c2b1bb46d2556ba67d.npy +03636649-75c15dd98de4ff17bd4bf7024dfa167d.npy +04256520-b797650c894719b99fd71c29e8052396.npy +03001627-23e726da58f115f69b9f2eb77f5e247e.npy +03467517-36dee516ac98dcadb6781382c9d625f6.npy +04090263-72405e2f1e4ad22027a9eb2a0bf0d0a9.npy +02691156-a516f9a6947bd0d639cb1b92881e8e76.npy +02958343-3c059c7851eafc192a9eb0f146e94477.npy +04379243-9200682ed0382e3f931e98da3a93e73e.npy +02828884-b2394480df328a98ad5067eac75a07f7.npy +03636649-7092dd68172560f410edd100dffd8d85.npy +02933112-727a4dbadbb74c33bf1b16662b6673df.npy +02933112-391d1f98ffc6f8cf4da5feafe6f1c8fc.npy +03642806-d2d90e352b2d0533ab0b172d4dea80cd.npy +02933112-12cb11dbb135ca9ac59350d819542ec7.npy +02880940-7c43116dbe35797aea5000d9d3be7992.npy +04460130-99316252e1dfbde1d810b14a81e12eca.npy +03636649-41c5a45c63f07f46c1c74fb098c415cf.npy +04090263-31da90b91370ff74f30ef438bb75825.npy +04401088-d8ee6baa8b57a89add62317fcd30f203.npy +04379243-d14752f7aa2f7ed5d684faddec3c0090.npy +03948459-2d573d37cce5b48b9f433921788191f3.npy +04225987-ac5b849680f5e3791bb7158ebaf7e1c8.npy +03001627-d334e5ab55188d62680876614ed35a7f.npy +03636649-de26f9660d34449f6838f5d4fcdeb579.npy +02828884-1f1f0cb43e65903d1d06bff8f83d7c23.npy +02747177-91a4d060d380409c2056b4bd5d870b47.npy +03642806-2d45f63c9ab71376a1b657e38449a62.npy +04379243-baaa6943a8adda4173705bc397297991.npy +03207941-785d6d568e0c7ea5575f4e5007488531.npy +02958343-d306a61faada97eda43f80a4a74d521b.npy +02691156-b41f477cd3c6843094b9c9a92aa36f8c.npy +04379243-4e9394f9f64859aef4ef86403cccc399.npy +04090263-22d2782aa73ea40960abd8a115f9899.npy +04530566-845426b7dd1b0e55a9142e7277ee08f1.npy +03211117-2963a8a608ba6833b6709846a0e82dc3.npy +03691459-90e3a0488b8ff079d207241113bee327.npy +04379243-6d6123585f79a8a54fa2fb9adc6e6779.npy +02871439-51f7a721c24712f35ce62bce310fcd30.npy +04256520-3ea6bec3578d7a0a24e449d22891bdba.npy +04225987-26cd3bfcef1e254f82b02baba7166175.npy +02691156-902b39a955eeb2bf35569910818956dd.npy +03642806-6170c9238fb2b5da2786f83874f709b7.npy +02924116-b19331d0683fe1ca402dc8d46be324b6.npy +02933112-b0709afab8a3d9ce7e65d4ecde1c77ce.npy +04256520-7104877ee2b4f68516cfe1233e767967.npy +03001627-8a9d8dad6800d55ff37af16b2893f1d4.npy +04090263-7083c94366b7c405330ab9259a8b176.npy +02871439-b079feff448e925546c4f23965b7dd40.npy +03948459-af9eaed1d9574387ab2c2809513f396e.npy +02924116-2de2984722a5bb59563e41b6f7313ed7.npy +04530566-d6ad84cfb652f5dd27ac692756be9e24.npy +04256520-96425edfd54c925457bd9a2a12d86bbc.npy +03001627-6b10b9f8b8f38cfadebf8d14d5516c20.npy +03467517-1300e8bafb819c8e1887f40a4f62df44.npy +04530566-70af463b4a51f0819330265a9fff38de.npy +02958343-6d03ff05596201e6d8df13fb69e08d76.npy +04256520-89155c23787c151219fb4103277a6b93.npy +04379243-aeb33188a1d1f0aaeb1b6e7f54488efd.npy +02958343-6e0e38fa4613df14af3abff6cd36a38e.npy +04401088-ec549f2ce1fd9acb634c1ac38a055513.npy +04379243-a4bea095f35a74d0e6c5cd45aa112726.npy +03593526-48eaa8465573a112bba080e9e0b1ed91.npy +02992529-e4a0f08d8a6d487ac9de9dbf8ea0d889.npy +03001627-dc182335876fbebbe6fe3612af521500.npy +03513137-176bb6178d49f5ace01c07526cf2aa4.npy +03211117-1fa9b1a775b6fd32d8d030206053b340.npy +04256520-b9a1600948000fbbba50f3b3c1c84054.npy +04530566-968848dda6faa772a9c79146773bd1b6.npy +02933112-170be0087472182bc59350d819542ec7.npy +03691459-91bab54d8d14100161d3e32ec60a98b7.npy +04256520-f17b64b1f764ba323bddec837aa40d6.npy +02958343-86d9b82220d7ba342e56818be5fde856.npy +04379243-c8e516785cbaa85259f8e31ca87c470e.npy +04379243-35e821cabad939df664b3b9b23ddfcbc.npy +03001627-96b4422833f806cecb092644051ec279.npy +03001627-e3adf2e6b3c3b015b63c025d1a57d1e5.npy +04379243-7625201ed0ef311eb65b71636c46ae49.npy +03691459-2e44c37aaae8052e587dcec4a739e277.npy +03467517-78a75ce8dc8dc197dc2b574e941c815b.npy +02958343-e914040a57618eb6d3e11439c6c22c8.npy +02691156-167250e2014c72dbb87697d3904b168b.npy +02958343-5ac9d85db6c0d396249cfd7cdcfe814e.npy +03790512-b1ad4777e9a8ad4e6e90540cf031a0dd.npy +02992529-4e2f684b3cebdbc344f470fdd42caac6.npy +02828884-3a93bccaa0b3161afca6ee915b120ce0.npy +04379243-9da02326599123989bb37ee549c6e937.npy +02933112-d7fe9a6bf2c5ad924c62bee40dcdc539.npy +04379243-40addb4af618318dad5067eac75a07f7.npy +04256520-99479cff448798a358db0ef36af1d3c5.npy +03624134-c50af8af50613e822bf26da672b84220.npy +04379243-2a901fa05ae444eff4b6538438a0b930.npy +02691156-9a5d4e2d21506f11c503a3776fc280fe.npy +02958343-1f37a6fbdf7c807e7d439639178556bc.npy +02933112-6059f5f009c40b814702663c3b3faf8f.npy +02691156-b46244d196a7f66635ae67400a94a6fe.npy +03636649-9f47c287c921e4b429eb9d04ea723179.npy +02933112-917de5653765673f8c2611a5a36e83b4.npy +02958343-28151fb21f5a3c94887b6e2409779132.npy +02933112-d917ca3f60dce05aaf31a22c7bed177d.npy +04256520-4fc8fd0b2951d0a0b035d20a1a3ca345.npy +03001627-c8cb59cef2f091e78a44b4d4aac56cc.npy +04379243-1908f2afe36335ebd97122acd7517380.npy +04379243-6402177ad47a8a9514d771bf63ae2f60.npy +04530566-2a492069b6009dec37363131ac7e8139.npy +04256520-a3d8fb85de7cf56fb2d2900ee0ae7e0.npy +03636649-f15294a164747178851f4ba6aaedaaa8.npy +03337140-a102f4ce970e4389126d9e54867801ff.npy +03636649-e30444ae7a929b6687d4034dde63c4f7.npy +03001627-1c685bc2a93f87a2504721639e19f609.npy +04256520-e12cf322cdec8ceb63860d683ccd0da.npy +03001627-34d3960d35d8d5219b9f2eb77f5e247e.npy +02691156-abc465975af79827dfb86dddee1d6ac3.npy +04074963-4e73215ae0f33d23a5e3ac6ff4952f3.npy +02691156-52747021197c7eeeb1a0518c224975f.npy +04379243-47ba08a0f617efc7a71c812e027f94d9.npy +03593526-1fc8104630b00416c151419181ef256.npy +02818832-9725ec5429b19ba05ac28d2931a0cac6.npy +03001627-8d0c04c99429ba8919fb4103277a6b93.npy +03046257-b7b62ffd6555121df546596ce7364503.npy +02691156-7c96e824c287f684651713cd1e90c5f4.npy +03207941-c9e020b0a288dde22404817055fb55cc.npy +03046257-fed6d8a816207b71af7c7ad2549a1b15.npy +03761084-506ce52bbfc7adecdb94e9396a25f7f1.npy +04379243-98bc840471b4fd568e6da51641e48238.npy +03001627-2cbbe7f1f1f75e34d28b52ade6c7e48.npy +04090263-86d90ec4c1e8437dfdf24ee0428a2075.npy +03001627-9d9b5f5b3fd41136244d7c2690850fc2.npy +04379243-50ea883b804766c458a565d8b69ccaf.npy +03797390-9d8c711750a73b06ad1d789f3b2120d0.npy +02691156-6f473d567942897b9908db9f2ff495fe.npy +03797390-ea127b5b9ba0696967699ff4ba91a25.npy +04379243-54dc32618be1ff18b3c0ea2ca7165b1c.npy +04379243-d89d8aff18d0f4fa6262f7bca314d953.npy +03642806-125c93cbc6544bd1f9f50a550b8c1cce.npy +03636649-71c9e25ec4fe08cbf7454c09d6230a4d.npy +02828884-146fb2790c11c7f1aaf6c17538652a1d.npy +02958343-b6749c2b917d4aad949b12cf3977a48b.npy +02828884-db4f8c9f1c62e421efca4f7cb98e0c29.npy +02871439-b60b0839b5cf71d997000b44d733da.npy +04256520-402ccbc3f5f26c095f8ca2b92d19277.npy +02958343-73a58e58e26e7e20e55e3ad998a1ecb4.npy +03001627-cbee0f33a45bc8231adfc48ece0d7031.npy +02958343-28bdade3806ef2f328044fe9244db50a.npy +04379243-25f69a74efbff4d071a782a4379556c7.npy +02992529-73d6b5dfb0f2bd8f5c351e299b24e355.npy +04256520-4f2c9a0709eb8cb9202316dd49948ea2.npy +04530566-3948782a95f084b92336765b86c93d9.npy +04256520-349402b08cc7e5e9492d9da2668ec34c.npy +04379243-fbdd516e90ad48902872e9c941f7c819.npy +02992529-ffe8cc1d33f3fb83d954b120b2d50f0f.npy +02691156-e523ba4e79a48d31bd46d022fd7d80aa.npy +04379243-c266a3883e001404721f5f36cb42501.npy +02992529-56a32f9e4785d3928a4adbc089030705.npy +04379243-f7e0e36f618039dff39d7554d3e63ae4.npy +03001627-7c68894c83afb0118e8dcbd53cc631ab.npy +04256520-225661a6dcd77e7dbd05ef637b36b199.npy +04256520-518cf789a696965b5e723252788c3d6e.npy +04401088-fa1088998ad523edf85a324c5324329e.npy +02958343-609f09c6ce74d6c44c06afea25f8c085.npy +02933112-1c87c14a44982206df3a1b0d597ce76e.npy +03642806-eda651202abbb90c94daa4565dd30535.npy +03948459-eff3abfc08348cf4be0132953bc535f3.npy +03001627-507a5070cde81fd867936ca58e67cec6.npy +04379243-9af7a071bbd432baa5526f91aecc0c37.npy +03642806-dc264eab83ca12b3da4c0d8596dff972.npy +04530566-5ae9838a4646c0551780f6e6561db9c8.npy +03085013-4a14f442ed519225a17d66eaa6c79db4.npy +03046257-b13143d5f71e38d24738aee9841818fe.npy +03085013-3714f64af44a135f6d3e11439c6c22c8.npy +03001627-5b3fd3199d1bc950c1ae25a29e9d46d3.npy +03636649-4fe9a79b382d30fb1735ea0e092a805a.npy +03636649-d779977c2417752b815c6de5374a8dd2.npy +02992529-b7049148a4ffa22fdfe197f9f37aa72d.npy +02691156-468e504d8c28d8c9b8b8dbe00be04f1d.npy +02691156-9695d544e326baeaebc75cd68927f0b5.npy +04379243-a45a7ba9a2842a55634c21965ee6bab.npy +03001627-c48014610839bde3b8e687cbf40e9e47.npy +03710193-98d4f56a842a777b28610e22176f685f.npy +04379243-b69d9e876e7a80a29f2349486c570dd4.npy +02958343-7d4fd8ed77355364fa98472c1d231070.npy +02958343-21fcf7b6cfcd2c7933d7c9e122eec9b6.npy +04379243-ece1e39b8c5f851b9eea323f522c6486.npy +04530566-d617c5194daf4f7298a97ddfb532e08c.npy +04090263-9a4c69fb30dd08bb5bfb24d81b25af8.npy +04379243-3fc6396e6a1270bdbca69f936e89647.npy +03001627-3a0e5dbb68e58cf543fad16a067ce812.npy +03593526-4cd37983220c5949946c2e1ea428382a.npy +04468005-31227f3fc286c00714c06184923f6962.npy +03211117-a17e2808f0176f87f1f3662486c882e5.npy +02958343-4822076e48b366371f0d59cde6139796.npy +04530566-b5b320871c5dd884a24134966691a2dc.npy +02933112-285864fbee3a4038178e7d331e641179.npy +02958343-7b8bcc3cafd34efa8b7227eb0fb9adaf.npy +04379243-4d81894947d08922beedb4c8fd29e2d1.npy +02924116-b01f3b4d7d18588b219d4a071eee0cb9.npy +04379243-b738d1a4caaf4dcb9cd431573238602d.npy +02691156-bf77987a13fc34b5b6c7da997b0e5e3.npy +02691156-de543fb92592aa48236a74f773a58aa.npy +04379243-7ce1b7444c3ba89e74f1cdda9579594c.npy +04530566-377ea2491f8db13c4808655181d482fb.npy +03593526-c42115bcac36e3569f8c3d2002c77ddb.npy +02946921-dc815e056c71e2ed7c8ed5da8582ce91.npy +03467517-b54b9a0eb5be15dd57700c05b1862d8.npy +02876657-158634b1d7d010eeebe67d9b32c3ddf8.npy +03001627-97a87f40f5eb6f04af7c7ad2549a1b15.npy +02843684-75bf6f6a98aea049ba5342d638d0c267.npy +03001627-85b16941984902f8facfa12c7d71c89f.npy +03636649-e44408513c20d08f37aef4415914e1d0.npy +04530566-dde0cd836238f7946cde899c8674e2a8.npy +02828884-3a60057b27f90ed64910664c4d1311f4.npy +04460130-6372299ee506123b52f2aeb043ecdce8.npy +02924116-2acae4f14a734f4972cf25af66dc82ce.npy +04401088-2874447c7552c6b942f892024869e751.npy +04379243-302ba9e290485f9c310cd758d9b7cf.npy +04090263-58d4a585abe57ff59a4b8c8271f09050.npy +03001627-57b4898f5b94a5a89d297e74104d3ac3.npy +04379243-bc7d143f0c666d816f80e82f51b5db7.npy +02691156-57575cb42132554af64801ad2940cdd5.npy +02933112-46629a0cff77972aa47e6c0a5f3e8240.npy +03642806-a4d779cf204ff052894c6619653a3264.npy +02924116-1584a923c35a42628dae4ffb029d1905.npy +03001627-64ef0e07129b6bc4c3bd24f986301745.npy +03046257-8b52d84dc97eb3a74740473002adcaee.npy +03325088-3a32f3b62d76fbd8b362845c6edb57fc.npy +02828884-bd88f333baa6cdc723d95f4309ade30.npy +04530566-ef666f3eb17ea5cbd56c7296613ec69d.npy +02958343-788612c1f9b2efccb1bb46d2556ba67d.npy +03991062-e0f429ea9201e20ed523ef2d2597224a.npy +02958343-72f56235cf1e18cf1ccbd9e5bb82dd04.npy +03948459-18a19c9d7ecf8ba9437e0b38fdbab2a8.npy +03211117-29aaace957daebc982c69f261576200a.npy +03691459-79c0d4ba54cb08ccec29f84f96a7e29f.npy +02933112-14ef9da3809148601b17743c18fb63dc.npy +03001627-582c67ae4d746d121b356ab8b24c147.npy +04256520-e55e87415f0c23baa1845d2858b500eb.npy +03513137-be9812128882a7957e167bb4cf1b28cc.npy +02933112-d15097b4c6fdd9001b6eef8565b06678.npy +03790512-8020984fc6e83ac1331b5e6778e27aa.npy +02958343-a9ae1558ff25e5336436916a86a90ed7.npy +04379243-19678fdb9bc926505e4b35ff1ea95f37.npy +03467517-451678b1ddcaf9e6d26aa1b9cb124738.npy +03636649-7ad15667f654fc08664b3b9b23ddfcbc.npy +03636649-348d6ddf9e02cbddf647dc544bb0ab61.npy +04379243-92499724962a368d53743fbb4759270c.npy +03001627-37d7029722aa0d91904cae5fc41c2d5e.npy +03337140-5738ddc421b5bb0291c352d02061b3f7.npy +04460130-5b0dc77df3bd924c25ed5c2b422915db.npy +02808440-b08727e640554b493321831d2245cf06.npy +04090263-7c6a21d8b91fd12a1b7837f7a64e3031.npy +04379243-52997bb331942b64f84b0be7f50940eb.npy +03593526-470392ec218fb13d63d977b06bbd429d.npy +02691156-db567b8afbaaa95060a762246a709d46.npy +04379243-980b85a3109e66562bbf333b6ea7b79f.npy +02828884-8d28e56cf5d2bfc8c3deaacdfa0e1e8e.npy +04379243-747f70e41b927e13b73481345ae9d2cd.npy +02691156-84615b34a2c8a2868699933784576e73.npy +02958343-e2ea542d46c76a002a025f627835d975.npy +04530566-4ee0ed0c56540273a6dae8586082d789.npy +04379243-a1da0c1db8220563b6b0dd2a0b939a74.npy +04379243-88ffa9b795f527b1969b9778c8fec586.npy +03624134-331bf2eb28033c1d1138511a51ff0534.npy +03325088-81a70dd1b34af19d92f46099482aad38.npy +02992529-b02d8e0fb3ec903b4a952171144f2812.npy +02958343-ae852f7f30bfdbcdf9d73bbb584eaa42.npy +03467517-ed978355ce673ab01009233434be6ec0.npy +02691156-f46df635ac669a9818b14db3b83de9ff.npy +03211117-f06cab8286ad4f7cecb44abbf263be08.npy +02828884-72d098aad341ae4c436455e65b78c0e3.npy +04379243-1033f41fd2decfa938da3ea2c9e0e4f.npy +02958343-1f43243b81df21277925d1ea63246010.npy +02691156-d1d308692cb4b6059a6e43b878d5b335.npy +03001627-55c9891ac274e076492d9da2668ec34c.npy +04090263-4fbeedb2f1f43293b95520b5e9aadee8.npy +04256520-64dc2fa7007421f9cf46315936cd9301.npy +04530566-d651a1f3e02593772b23aad8ba1ba03a.npy +03001627-8617fc907ff8cb36597976c675750537.npy +04401088-b1d1d6a5f46a30894884e1105772427c.npy +04256520-8173fe7964a2a06319fb4103277a6b93.npy +02828884-50cdaa9e33fc853ecb2a965e75be701c.npy +04379243-31f47d0373170683f6c84947abf8f003.npy +03001627-8b552c23c064b96179368d1198f406e7.npy +03624134-e43c5d6241344913c40c6b891c4913bd.npy +02958343-94b3689f899c8cfbd575863af568c85.npy +02691156-4782920ddfdeef4ef6bd63e31c40dc1.npy +04379243-224ccf4c3cfd4cc1b9a0f5d18f1ce54c.npy +02808440-56a19ee862125b28cf8c584ddfde6324.npy +02808440-af7fedb716fa3b119b5b1575bf5ce108.npy +04530566-88ea6d51dcf2cdee3a6f102e22936e2c.npy +02691156-e53547a01129eef87eda1e12bd28fb7.npy +04256520-44d172b5cd523df141b965cb8ba50814.npy +04530566-a08180869abc48b75b0cd10627918af8.npy +04379243-24181beca16bb46bf9931f8a466b18bd.npy +03211117-3a9dfefa52a6d2643ed8be9ed4b2b6c8.npy +03211117-adaceffcf1d89f9552b499dc8d840804.npy +04379243-8700e5f711dd180bef207763b5f4c54e.npy +02933112-6f56fdbf225247abcd8f3fe9ca2145e1.npy +04530566-25159673c007368b8b44023403d275d4.npy +02828884-43cae409bde302d4c88fd5e1f2929cbf.npy +02691156-5a12bc3a78c510cb366a5992755f2322.npy +03928116-e3be0badd5278d1825e1cdfd03ba4126.npy +03046257-191812cf4abfd6166e71174964d90e49.npy +04379243-1cd6a00b71f02b06430c2c15987e4cd.npy +03001627-113016635d554d5171fb733891076ecf.npy +03211117-6c8f7736660f2e97e441f5bb6f88ca61.npy +04379243-2cee786a3480113a2241dba92389a637.npy +04460130-48a1e31e57862a63ff679899febcb0d4.npy +04379243-e4089e22c991e2dcfd277d65d018c82e.npy +04530566-750f5d76abca0a05bdb69bbe5cb6055.npy +02924116-1c6d79edc1ce02b8ea89a7009dca2424.npy +02691156-cc14512d5fe6e8489a6e43b878d5b335.npy +03991062-6f96ea1f948bdb5a72652f4081ec5a77.npy +04379243-31b972951e7a8ed323fe3501bb9e7193.npy +04074963-6f6ed9e0d29b64e714be24585075d395.npy +03001627-c91eb95b40e4b6f8e83221ad0d21775.npy +02933112-48ad79b48a76fcec4da5feafe6f1c8fc.npy +03710193-133dec6c00923805f423417965ceb17c.npy +02992529-da24f27173874672ed7485a1aa598365.npy +02691156-1abe9524d3d38a54f49a51dc77a0dd59.npy +03001627-b3fd987b330d0d2acda56795a6fbde1f.npy +02828884-c6ccf94d3e512ad510b3ff08c68acccf.npy +03001627-7f6bcacd96d3b89ef8331f5a5b032c12.npy +02871439-7c93c71c1ca57d5c9c71f681ea4c5bae.npy +02958343-f7da98a59900ab60becf71e2e014ff6f.npy +02992529-bcc1760ef463671c825b62bd6c28eac.npy +02958343-b17929063c2b3d9a52aa494042b7c9db.npy +04256520-e4e660790950c277cb1362eb0fa793e9.npy +03001627-c9d8573a048c0e959c0ca344f487323e.npy +03207941-4e9832bbbb077f9c5c5adfeaec1397f.npy +02933112-891e56eed3fe1debeca22c501ad0a77a.npy +04530566-71d6ab6979e5a313dde8c025d72da437.npy +03001627-7e66472eb05cca212e77b4bab2489170.npy +02691156-862d685006637dfef630324ef3baae90.npy +03001627-605ebc9107c71d54d8f5adb469ca89d3.npy +03211117-bb6392ddfeb98b19822cf0bd2945d4dd.npy +04379243-2bf3e370da5d2f73ed403132b02528bd.npy +02691156-4e3e46fa987d0892a185a70f269c2a41.npy +04379243-f907cd8cfb723ee6d6eba0d14df5347e.npy +03636649-33e210ccfa79a0ed581fd19c35a5c8c.npy +03001627-e3479f55f5894bb3c7f1f7c0570e288d.npy +02828884-bbb448ee06bd6d83d838ae16242881dc.npy +02747177-93d5f21e94ac5fb68a606c63493ddb7c.npy +03636649-2848ad36017ecc69b4169e4cad9bb63a.npy +03636649-27b2a1bb96fbd760316fa82a71600dfa.npy +02691156-7bbe33ebb5429a0a7a9e881131950954.npy +02958343-94edffd805dc965ca5626f7e1b38f05f.npy +02747177-8675c75413c9938dccf149c7b4065e.npy +02924116-647c7b4faa7473aa54d963fd62c89fef.npy +02933112-4d79731efe402b0d635469b95109803c.npy +03636649-e98c05f4cc8c7afcf648915c85184f8c.npy +04379243-40ae20513a1ddcdcf6cabe1df6f4c9d9.npy +02933112-d8bf8dcbd5cae04094beb1f48b8b494b.npy +03797390-345d3e7252156db8d44ee24d6b5498e1.npy +02808440-19a77323e724b7c43321831d2245cf06.npy +04379243-bda51fed12335c5e999b33727fe6db14.npy +03001627-c5beb566f512bc8d9e989ccbad3213ca.npy +03636649-5b4856005da0ab61d18826cccc613430.npy +03001627-710441e3719c99e04b3c42e318f3affc.npy +03001627-24082b0254dd180c490ad276cd2af3a4.npy +04379243-4fc0bc3fb6438dffab1d1edf764243e3.npy +02691156-31d5be3944350915efde2c2b27dc1843.npy +02691156-bdcc8077771968d67c54439d6177032.npy +04099429-3f3232433c2598e779169036b64ab0d9.npy +04401088-8caf79a2bf3be9fabfbac23a8087e8f4.npy +04379243-c728329a22124fa7e8dd400ae08fade4.npy +03691459-7ec487384a050ccb82d710142ac471e3.npy +04379243-aa219609a504b01047c527f581cb7384.npy +02924116-45ce077a3cb5c211690493afe1d3a073.npy +03642806-7c1eb7cc7dbdb68268981420d1da6237.npy +04256520-fce717669ca521884e1a9fae5403e01f.npy +04379243-b909b35804e9751daece045e8bdac80f.npy +02958343-f1f78226ed08465f801b0db1d49ea10c.npy +02691156-ff554f038a338ef322031be9b666aa96.npy +03642806-f72dc1ffeae0168aadcfd37206a0d18b.npy +03467517-b48531b4e111f30d8388889c8d3c7bea.npy +03691459-cc6ebcef8d2e674690146e2a0489a257.npy +03001627-941720989a7af0248b500dd30d6dfd0.npy +04379243-90c19c729cabdb864b8710a3469971b1.npy +04379243-90992c45f7b2ee7d71a48b5339c6e0da.npy +02808440-63e2922c33f79afaec72042a273c8bd8.npy +04379243-6afd8ac8c1a2e31cd42ec7e303174a87.npy +04530566-aa6a256cce6f8248b1bb46d2556ba67d.npy +03001627-74c97be038139e9792d9ebeee84a8909.npy +04090263-ed1647e209a3f661e1f2a1daf140ac9f.npy +04256520-ef6ec9f481a67015ee3907b60a74e8f8.npy +04460130-6b78705cd18a7b7767b959cddc3d22e.npy +03761084-48eecde6f71bc1a2f99d92708f91e592.npy +02828884-7e2433a3cd020f53588060c928db75ed.npy +04090263-700b82751c12e8ea3745d03a006445d.npy +03211117-609dffc42c3507212492d8a3aa63f4f5.npy +04530566-5bcfb42ffc3490c4af802a9d0ab09410.npy +03467517-8f1f54d337bf6ccac782e6226a4f593e.npy +02958343-2e1178d969bdb3849ea5c205086e2a63.npy +04256520-583ccd71c56aed45f14c803eab703899.npy +03593526-9f62aed6538caca130612f5c0ef21eb8.npy +03325088-49553eee4f0403f850da8b99982a3057.npy +03691459-3c8dd5506a17628fa43ada367b02a4fb.npy +02958343-d98b63a9e35f50b46a835a8530f31f70.npy +04379243-cb242dc225308003de21d22522bdaf.npy +04379243-688bd4df748faa62820018801b237b3d.npy +02992529-407e5ee21fb23fd92ffe71e0e78fe3b7.npy +02933112-c33ab47f610b64e6ccab809eba079ca0.npy +03948459-4bb890182e9f01b26c63b8b48495261a.npy +02933112-b37d269e1ec64992ee71ee29c2167097.npy +02958343-87918f9d328b535befe5f291bc2f5fd0.npy +04530566-c45f67b42b7febf52b249fd16295bbfb.npy +04401088-9911b2ee8470d6dab2098fa3046754f.npy +04401088-fbd120d2c01484d56c95c6d882af3c0.npy +04256520-264d40f99914b97e577df49fb73cc67c.npy +03001627-c5e6c2b4528c371378dd615a59de5f05.npy +04090263-bd23795276854614182f019eac476ad2.npy +03797390-c2e411ed6061a25ef06800d5696e457f.npy +04379243-3eea280aa5da733e95166372d7ac113b.npy +02933112-6e6a324c244158325761a0b53ed37cec.npy +03001627-d75d41af68f4bf7f9af4053b8815b239.npy +02691156-ecb4ae05d7dd135a619550d2af0b6117.npy +04379243-3f4cb895d754dbd3ce47b13319293999.npy +03001627-93556cf01e19f638bf80985a99195eb8.npy +03991062-e74feb8fb03280e639c837a9524b9dac.npy +04256520-18f8fb3fd6222959e8f8c11a24c52ebb.npy +03325088-1e038dfd194d74863321831d2245cf06.npy +04256520-8458d6939967ac1bbc7a6acbd8f058b.npy +03624134-6f01f7579d0ba8238bf4d4792a57629.npy +04401088-cd7e6ab98a2d090099b101e0ce243aa5.npy +02691156-7eef160cf5e4188a5a8c25d312cc3c6a.npy +02691156-47bf091a7c919d1c90b1d6deb98feec6.npy +03211117-7034d396585632ef5450caead37a1c9f.npy +04379243-5292f2930f188e0a7ff6ace05b36a5.npy +04379243-e99a4c2fa99a0038a2aa7d89ba9aea43.npy +04379243-26432bcd60baec3182c17278756c0a5b.npy +03624134-3460fad7c54b8e54801723dfdf7a7a7c.npy +04256520-1512e3c41de7a461e10a48f2bbb9bef4.npy +02828884-275249a603cf7f6df064889421ac8911.npy +03991062-5afc3b1bd57bf6482c2c0fe8f75ba056.npy +02933112-a640e7214f7c5393a5b7c9f0974d595e.npy +03001627-473cbfa40ff731d92e75d78b4c7ea93.npy +04256520-faf387a11f3f944a75dc34583b0239b8.npy +02958343-8b4879617bd256391738f25e3015f92e.npy +04256520-ed1aee9100f58e26b9b072e1f62798f5.npy +04256520-c51e57530257f6e0e0771d4c079a0ec2.npy +02808440-12976a1c355efee1ae51c8fb67762055.npy +03001627-3319a9b24416ecea7ff6ace05b36a5.npy +02958343-599aede2de805313a87928f1d77303e.npy +04379243-b95072f2b12a3274d810b14a81e12eca.npy +02691156-d72a483cf8a0cf2bbbf3143b1cb6076a.npy +02691156-3c0a871ed33a1c6a296ee999ff54cc3b.npy +03001627-4ecb13c40d55bc24fbcb0345af819bcb.npy +02808440-66bf814e881c1c1a51c83dffb1e07a0e.npy +03001627-eee8b6fafd8af9d1ea54e1e7afcaee9.npy +03001627-bce7ff621a5440bb34ee5c94ebdf7f1d.npy +03001627-595b9c165214bdf0b0b1b4239165b394.npy +04256520-42eb9cb2f34c1ac81be5c5f8d4f77343.npy +02691156-e409d714620161c132fa725d7a62a02a.npy +03001627-a07ec767c0a395e53cc720af04c21ce8.npy +02946921-a5bab9546d6a1baa33ff264b2ec3aaa9.npy +04379243-f0d5eefef970fa4b9f2349486c570dd4.npy +03467517-28c3903b29f6b38363e148e250c0340d.npy +02992529-decbc541efe459a742f1242fa6dff2cf.npy +02808440-4033f8440d4b5e83321831d2245cf06.npy +04090263-8036d88d38432a11ff18bc1311316304.npy +04379243-ad0c4c25d7a4d4c296db593b49da23e5.npy +03624134-2d6e9b23e171760c3e332fb3cb6ebe50.npy +04379243-fa7a8f6d4c33a4081f4e3943babe5979.npy +04379243-d7de6b2deca39eb0b20aa91e9e90c311.npy +03636649-a122a15d97594ebcfcb8d8c6d4df8143.npy +02958343-a8ab20351c2e7542912749d867981a40.npy +04530566-4765a72ac8a0eec3993eb1c02818be1e.npy +03636649-78b8718a36910dd32534572dc403ed94.npy +02828884-bdce8b3475f59d38f4fb4dee5181bee.npy +03467517-bb895a87931f51c893f0194265a9746c.npy +03991062-8d2c6ce685eb1fd9368b14e48c164a6e.npy +02958343-b5938ce8c35aac9b46f8ee02bd8f9824.npy +03710193-73cd7f3ea1579431a97f238e46bc2221.npy +03211117-6a9dcf34fdfe8ba82d8b18d11bd45e6.npy +02828884-f5d5f659c9cda6d0ad5067eac75a07f7.npy +04379243-3c514c4f53e3f1ed4b3c42e318f3affc.npy +04379243-49230cfa054929bc718a34fa24049f1e.npy +03467517-4ff4b6305e3d5e2ad57700c05b1862d8.npy +02880940-3f6a6718d729b77bed2eab6efdeec5f8.npy +02871439-de3b28f255111570bc6a557844fbbce9.npy +03046257-a245bbf8367d33ec4b3c42e318f3affc.npy +04379243-bbc685f481cee10f668ae11a7db5e82a.npy +03001627-728fb292d234b43d49a71f577ceadcf5.npy +02933112-2e38fe7e4cd74bec76e9713f57a5fcb6.npy +04530566-ba5723d5cab50a0b7d86b3749977e29.npy +03636649-24c91045ef1c6a91e4407e92c4b0344c.npy +02691156-4e67ea4fbcd0d9a4bfb056e4de687088.npy +04379243-d5f5388411866fcd6f349f21cf5447af.npy +04256520-48a44ed3050ad12dd5b24cafb84903c7.npy +03325088-589cc2df7bf5a6243d7d93e47bfee597.npy +04379243-cdee5ccae3613c507e1dc03b595bd36c.npy +04256520-7e2d4791502378f2593ebeeedbff73b.npy +04401088-27085a2456319497f1cb19f636b1c2bd.npy +02691156-376466b562217c2abc0909d98a1ff2b4.npy +04379243-c1660471a22c98a9c7cdfa94351d0f74.npy +02924116-731b13f29603a7a183c8e6d5420def84.npy +03001627-2cf960825840947aa903b9ef0ae7fb14.npy +02691156-788548a68d7b46ec179febb7e11d3625.npy +02691156-16f81f41ba16edebca8607f540cc62ba.npy +04256520-d8892d8a902616b1669e5c8c05e138e9.npy +03046257-613a7dfb6cd136e3df6cfab91d65bb91.npy +04379243-42bb37f87a9a758ad43fe0060c5249d9.npy +02691156-af69c8020fa9b68366cf1b4a8fc3914e.npy +02933112-7b7067ed1bfcfb62377b9297f3055210.npy +04530566-a8455459a7b93aef9e5629b793f22d35.npy +03337140-2b37f9944a63ba4b4c3aee8e9d3a6ffa.npy +04256520-5b06dcaf32f92e7eb3878cedd8c8fe6c.npy +03636649-7893d0b50a7b6a768ec45924afa4ac91.npy +02933112-68d23effdc37ff8ab59213b4b43189c1.npy +02828884-14688c10826a81933792407aee21900f.npy +04468005-9241faa02acfe08f1b3165b3174f01e4.npy +04379243-6a72d6a26d28b02bd626c689702869b7.npy +02933112-3775c10b5502d12a1190e285a2cbc9c.npy +02933112-3d21c803cfa3bf504c96d44e0e286fe7.npy +03211117-b228f0d5208fd9ac30ae9117a5a20ccf.npy +02880940-cfac22c8ca3339b83ce5cb00b21d9584.npy +04379243-45b839c347e02c86b20aa91e9e90c311.npy +02691156-e533a1a758a1752b187ea8c086d9f2c.npy +03991062-c94497750ff15b998578f0cefc281dbb.npy +04330267-83be70da0f3def9cc1b69d6ad297ed35.npy +03636649-6196ca0c22f9f7271110d567ea61aa61.npy +02691156-fb92c2e96fdf6c37595dc3191c718398.npy +02871439-c214e1d190cb87362a9cd5247487b619.npy +04460130-4059fb45b27d8b1f148a76a78b10eb5d.npy +04379243-4220d2a91737c68019fb4103277a6b93.npy +02958343-c98c68f41fe8747fb376886260eb15c1.npy +03642806-ce13a85fb71694fcb611830890d7aa97.npy +02924116-4ed9d6cc9a4a71d73aa5bf64bbf56692.npy +03211117-6a08ffb169d2929cda4553545dd45630.npy +03636649-7b41e8307e85ab0b87e834be7739917e.npy +02958343-96e164d8347ff4d8d61b6a34f3fd808c.npy +02876657-c553b7e594942f0a4c0bba210aa0d1.npy +02691156-ac0234f2b9f195e3cc1281a5f11b5a5b.npy +02958343-23f31f379d6a5136ce27281f3b76d1f5.npy +02958343-1836f75baa094cd9372ca62e6806c5c3.npy +04379243-4cd119aa7b11f3f54b3c42e318f3affc.npy +02933112-30cf0cedd661880e86d53ab0fe94e911.npy +04090263-469427702fd95c3c6314c3b6a3a65519.npy +02691156-5b815e2726656685823df672991ed66.npy +02958343-c58db3209e58872556f3b9566f5b3b77.npy +03001627-d5439bb962c3cc8579170a5f8beda902.npy +02808440-4d442c72b0083566ede9471c962dd6ba.npy +02691156-896508fa65b8a31c12b38b1d99376c0b.npy +04090263-5f68383c820c1bc4a67ac8a08d7e171.npy +02958343-a944ae569bbff87716abce8cb03e7794.npy +02958343-d4919d3f70b699152b12ea83455b0f44.npy +04379243-78a93c794aa77beb47bc3701b998a7d5.npy +04379243-2f5d2dfc1c8b75666c8f2acb6194d7e9.npy +02691156-4e2322d4f1c0d29df96e777471c18dbe.npy +02958343-2e8a1ae108dd0d89e8a3b392b986583.npy +02876657-edfcffbdd585d00ec41b4a535d52e063.npy +03593526-852c6ad14d32d6272b6168eeac2194de.npy +03001627-ed751e0c20f48b3226fc87e2982c8a2b.npy +03624134-90021da7c71f6bcbf02ee453ff283e26.npy +02691156-94ee700c27e2c05f84fcdb4aed90c145.npy +02747177-69d3b9c9321e3e0bad5067eac75a07f7.npy +03001627-5fe9ae9eb1ece960c423490470c47d79.npy +04401088-42ce5fc532b667bf9f8c6ee75b301991.npy +02691156-525f3ec38c3baa7a4944d3c8bf9547cf.npy +04379243-590128c134fd2fb9c1535160ddca1c61.npy +03001627-9b9a114cfee79bfb492d9da2668ec34c.npy +02924116-ba3a5c4ea765aa6dd01b211d93f47d40.npy +02933112-9dcc7002210e6660824662341ce2b233.npy +04379243-415d7746f792eb1de0445fc6d980dd5c.npy +04330267-cf1a57415ade5703bec56bff764ba78.npy +04256520-25ce64639b8817065510d59f3ab1ed64.npy +03001627-c927b1352027fd6916d8d4903814cf37.npy +02958343-53b6f9eb4337276473f10e6caaeca56.npy +03001627-769f2cb98735158a2334de46509d60b.npy +02958343-c5ef2eaae2b2d8673cd3add5aad1c863.npy +02691156-48c2f17fd1610cddf9b189ce48b45ae1.npy +04256520-c59ef7c56b4d184f9cd431573238602d.npy +04256520-58738b85e8a13c14380e1a7742e001bb.npy +03211117-b95414b9723439a6fd28950562697757.npy +02876657-595e22f425839eac2d4b0854f7611ed6.npy +04379243-fa09f5e809d1c8c983b3f8b7586237f4.npy +04379243-4a9a73e93f19ece06652506d959dc71d.npy +02691156-50e6ab918250ac797a663d343339f8e.npy +02992529-a41e693828a65064e565c13e00bdea3d.npy +02933112-9d2bf81532da5823b69348aaef501740.npy +04379243-9a70b1d07f3027719fb4103277a6b93.npy +04379243-27cd239b41129a13c19a59cdcb309b91.npy +03642806-ef6d92c90aeabf5becae27d182a3e41c.npy +02808440-b768643834bdd3eedc749e0740d903a.npy +03001627-9069ccc5fcf22878564eaedaeaa04f28.npy +03001627-a691eee4545ce2fade94aad0562ac2e.npy +03636649-db759b73923a7e36b9df6a8c2c09592.npy +03001627-c70c1a6a0e795669f51f77a6d7299806.npy +04530566-7d7fe630419cb3e3ff217e1345ac0f8.npy +02958343-35fc22147c160f501636a25380d820df.npy +04379243-6f97636bb2ac5d599856fa70a578baeb.npy +04530566-68d32bb51ab2050efe999a207e6e230e.npy +04256520-fbb78f2c30bfa014703a79ff0df43433.npy +04401088-b207b3f3617db6cb85089a13cc567dbd.npy +03467517-52abaf50a0739bd8cdb542a68600a146.npy +04379243-aa69a26be784dcd2cf004563556ddb36.npy +04379243-3eba5f6a09e87969b76e29c9c43bc7aa.npy +03991062-5bf7954ab8168f24e3849910c5019154.npy +04090263-a66887b692d9326b51cfdb4c9f126c12.npy +02808440-f901b929f8c976793321831d2245cf06.npy +02691156-3b3b2777be8b6b31ca8607f540cc62ba.npy +02843684-cca3e35970a665e56dcb36a8108f189.npy +03001627-5f76562ab6c843cb575f9747ff6fb5e8.npy +02808440-a9d03e90d548a19d412ac8cccf0c180f.npy +03001627-4e50015368a4f3ea4eb6addc0d23d122.npy +03636649-5a502ebda119949ef7dc60c6a4d98c25.npy +02876657-3de5abb596766c5380dd154b5d9c087.npy +02958343-79db6e5fa70b39467df67c910758dfc1.npy +04468005-575289640b8fe387a0c6c5e8898c5f38.npy +03046257-abd4fd596171d33c2d1b942ffb1336a6.npy +02691156-c0f9c28c45e7c8354f95630cc18536e0.npy +02691156-baa3e1edf8870f755f1a3e0b9f8002cd.npy +04468005-e6392c22c70a5735f0f5113376645c58.npy +04379243-707e63122691f0cb490ad276cd2af3a4.npy +03790512-9154fc120f53eaa8d42c4cee3f9bac47.npy +03001627-4a86ad0d870a55e82058afcc28d23393.npy +02818832-415db413b280c69f42d8a8c5af8997e8.npy +02691156-cbacce3a17e061251ab9df4be75138d0.npy +04530566-291e48a99be418846c03c11657c96c60.npy +02691156-8a84a26158da1db7668586dcfb752ad.npy +03797390-2997f21fa426e18a6ab1a25d0e8f3590.npy +02691156-48996e27f430ce286f67a5681eaf4d9f.npy +02691156-c541b8c49b5d2d8e99ad3ba13045dc42.npy +04379243-b420e0461893854bdf6cfab91d65bb91.npy +02933112-9cec9c8b65ec9e4f4c62bee40dcdc539.npy +04379243-d5f55cf498a7562eb000f20a5153622c.npy +03636649-98d9619ca934b01df51f77a6d7299806.npy +02871439-7167cb1a30852249cb08ed38616b96a8.npy +04379243-445528514535ca621d5ccc40b510e4bd.npy +03636649-88153eca8600ecf05b1ab0bf4891d200.npy +02871439-66bc5227baaedf84997000b44d733da.npy +03691459-73f855f34572cf984bb93d09975f5005.npy +03001627-cd47ea438a9387c0ee088de33038f12a.npy +03797390-52273f4b17505e898ef19a48ac4fcfdf.npy +03001627-e777e42470ee9bf270ae142beb408e0.npy +04530566-840d9078c31c188feae47c2aade5a70b.npy +04256520-5d1c69aafe90cc3114038d588fd1342f.npy +04401088-6456bafbb5a656fc487f00a15f77c99.npy +04256520-b0b0186fd16220d4917b96045c9b6dea.npy +04099429-1ada292665f218a8789f2aa296a418cc.npy +02958343-1782558e47730989b96212c8f6cd06e.npy +03001627-a8110dab06c9c72a2c528d33bca1ac2.npy +04090263-16556179cbf2701916b34c3751bc447d.npy +03636649-66cec0a2ab63d9101b6c273f8ff0e8b6.npy +02958343-a5047d31a855ffd1f339a7f0f377393e.npy +03636649-762b4e2cbb8e643790c2e24416edfe5b.npy +04379243-ddc91eea0d38268d616fb9ab42452112.npy +02828884-ec7c3cb273f857ca785c8f27b37ec031.npy +02691156-7442ad61d59fac8c7372dc0a2f1067b1.npy +04379243-7620cd93dbf32cce5213cec267286d18.npy +03001627-3c9bc4876a03093414b65ac180970edb.npy +04256520-385990d0223c92b5f3598efd14e493d5.npy +04401088-36ff3418849b9b8635d9dd2d03e6c396.npy +04401088-183e8d61b3c4edcc90b5b1d619d7013b.npy +04379243-1ba26b0ca7507edd7c8ffa57cf4ce53a.npy +02691156-2ec4d9949f80154b7a571401e6605fc2.npy +02933112-948709ebfb6cd6ff6f2222642bd41c09.npy +04379243-8ebb14fe46f63d5a98cfd47a860803c5.npy +04530566-eb05e72eb8f94a24816427daa1887efe.npy +02933112-786566b66299405a4da5feafe6f1c8fc.npy +02691156-195ca2eabbf7c735a8d66821ccb813fe.npy +02958343-60aadbf4a0a42360ab62a01524fcb1ec.npy +02828884-f1515c5d78429613e80dd430e11432ff.npy +04090263-e8f32ab6ba9ab7713a72dfa25c767709.npy +03001627-d94eeec9f2fc4d6c33fe87c69b83ce63.npy +02691156-f7298a13f6d1644472a4466eb772f128.npy +04379243-bfb2cfb2e454160d78cf5fa17988625c.npy +04256520-25bf067de33706e62bc36def1a7d775b.npy +03636649-dfb6553d8e04cbaae1263552aa9a2d35.npy +04256520-a4b1c819d9b606473decfe0ce0584f.npy +04379243-bb3aa93ba6c9a38afcbe4e14ff0c4707.npy +04379243-df5ac7a785ab39fbb5677466d30ffffb.npy +03636649-357c0ff8a3ddddf5902078d0d905735b.npy +02992529-6682bf5d835701abe1a8044199c77d84.npy +04090263-e9706e37ac92aa199d360253182ac1b4.npy +04090263-71b79bf11ce7ac96b839c45792f79dd9.npy +04379243-3836e0568d0ab079ffc6e457221b9271.npy +04379243-a9dfcb1e1ac5ae67468b43c22b6f785e.npy +04090263-86873de47fac054612b38b1d99376c0b.npy +03001627-32f2998a16e477163c4f66791e25960f.npy +04379243-18b58b179b73dc958c9e244e3fbf98f0.npy +03001627-331e1247f5672328826fc8d57346a2e4.npy +04379243-5d00596375ec8bd89940e75c3dc3e7.npy +03467517-d4b2ddb52e8dcd3593f0194265a9746c.npy +03001627-e14e8241e0bb563f64810cc21086da42.npy +02828884-8b8b59fc52257bea58e51facd8ce1a25.npy +02933112-cc492f2749d63136504721639e19f609.npy +03001627-fe53dcce9a30c5b5348fedb5a291187e.npy +03001627-a85e81c62bed11ea7f4e21263a28c500.npy +03467517-14038f17e185433993f0194265a9746c.npy +02691156-ce0c461237a21cefdb22b838c125a50b.npy +04090263-b5f52968710c4a4de1f2a1daf140ac9f.npy +03691459-7b7904e3d5ac33a65afb688fc9d0c0.npy +03467517-66b24797480ba515d57700c05b1862d8.npy +03337140-412dc6b03934e4984c3aee8e9d3a6ffa.npy +03001627-56c8c9cfb9e6b1b9fdef1c01cbd4ae0c.npy +04379243-d058b63b957076771d6ac856ecde9eb2.npy +04090263-bfa059271ad449e13cf7a43bad229f6b.npy +02933112-295502bcb6d0c0f5c59350d819542ec7.npy +02691156-276908a82ab3728e6283c6757ac506b9.npy +02924116-2270b5b1956c665e193d7855ecfc1bd3.npy +02958343-8bd6b3e216ac44d2d1e34356c50bf8.npy +02691156-f1b3408a3ba452d0c1ccec171a275967.npy +02691156-3a92789dfc5186dcfdbac8c3ccfc63c.npy +02871439-987f3dffca4d921835836c728d324152.npy +03691459-a5e412770440524b92981997d5df910d.npy +03001627-f06d2963ad258feaf5adaa9eef900be3.npy +03001627-b78f64455e41db28341ebff340b2c71a.npy +04379243-e1369c3a3daefef158df8eeaf3dad1c.npy +04379243-c172807c444475ccab610b0c94236463.npy +02808440-129d84a2d2e5242a6b448b8aaebb705c.npy +04379243-8ac2feef21274a23f45db6a75d78cb47.npy +03211117-12c3e644bc371f30366648d52e38fd70.npy +04090263-d21247f000436a8a374d02834a57040d.npy +04090263-de9fcce5174bfe09db181f2efd806577.npy +03001627-a50887c625042b48c862eec8232fff1e.npy +02933112-4db0db06f86fe48f4da5feafe6f1c8fc.npy +04401088-c978be9ff9bfb9c67d2c763bf3599a8.npy +04256520-d669c884e2a9274b1e7ef3c0866377b2.npy +02691156-69ed3801f4f6f4d1e1873a3963e0d14.npy +04379243-5d9f9ee95a7e1623fe9d8ee1a924ac2e.npy +03001627-389ed34a0c989e325fceaa39a8353bde.npy +04468005-1f628dd817eedf50bc80f94fe0a74127.npy +03636649-9c0b48006e3f6aeda1dbdc0360a4cc99.npy +03593526-1da5c02a928b8889dfd1be983f4bd279.npy +03001627-35d62c8a02fc15b1a2c5a50ad2499011.npy +03593526-ad64ff0a281c92b7eb895521e4d63cbe.npy +03325088-953ea008e95d811154d7082b34825ef0.npy +03624134-3a4f0118a57093cbf7c4ed45ce654123.npy +03636649-e569a4ed12ba90c220331d4c3b7d944e.npy +04379243-3683fdc45dc98b8955d054336de5edb5.npy +02691156-3c80dde1fb615ff5ca8607f540cc62ba.npy +02992529-ccfac9fefb0326003f548cb8701b2293.npy +02924116-311dcc47c8f639a1f3f27ff04a4459b.npy +04090263-8aeacdb5884311663716c1574460b140.npy +03001627-d75d1c46cff08f4767c8e42cd3ac65ef.npy +02828884-ab5f53ca60521a231aab721727b6a1b4.npy +04379243-36047e4ed31420904738a251b334366e.npy +02808440-6f1ecf3e720f20e7d63fb7225e5a4313.npy +03691459-8834ec44bb6d291490146e2a0489a257.npy +02992529-f3aac8f54f5f2a2f983ec12a2b33f18b.npy +03636649-b5a0f10269e2f4a6ba5342d638d0c267.npy +04256520-fb0c0e7d7094b64c8e5f5b49c9f5b3f2.npy +04379243-685865c8de58d7dad75b93b39461011.npy +03691459-4f152b01f056d0c35363d5176df02e54.npy +04379243-88140d7ce3a1f6c4664b3b9b23ddfcbc.npy +03001627-704179dd47a2282e676de9b6e111da8b.npy +02691156-4fccf49d6356c756b833a96759a020e2.npy +04379243-3c275368d3e30e775517495984cceec.npy +04090263-1cd506c69f575ba530dd2b88f7efae34.npy +02773838-d9015890f9691fd593daa1a1c18444ab.npy +04379243-6200bfa29b2912048b083202dd9c4b6b.npy +03001627-37b8604d852791651a648655355dc699.npy +02691156-e9c78deefc2950be62b600da24e0965.npy +02992529-9c26b9b0584920f1539baeab407f4a02.npy +02691156-a211cfc04bf47039e933de2bdfbab002.npy +04256520-3b3f44ac9d3245b1e7c7920f6a65a54d.npy +04379243-599f4550ef24f59d19fb4103277a6b93.npy +03001627-ccd49951295cb4cbe139cf2f6f121cad.npy +03691459-774214a85b87204c33dbc1ea1716bde.npy +04379243-4b4ae1bfcf9de312d1dcc55e36186e4e.npy +03790512-46e38cf88b07de0ee2b85785c47c5d52.npy +03001627-6be6d6ae38d8aca4dc2cbc0befb06e1b.npy +02924116-f63095945ba79d10afe1d4530f4c6e24.npy +04379243-75e9e4fd6c512c92966130541a711692.npy +04379243-58c234e30f95394f61aa7729a1bc4626.npy +04379243-1b6bd64fda74bdc4d6983f351200ac6a.npy +03691459-542bc1ef866548c3d24fc75b2f944a91.npy +04379243-bcd046749f03aaab714531f0291497fd.npy +04379243-22c470174c40a0c33dc1643807625350.npy +04330267-c89edade3d122c535eb64c1003065596.npy +03593526-a1fae2bdac896ab83a75e6d000e08290.npy +02958343-73beb19621b7547af8a3d805c6a10776.npy +04379243-7a42b366e7f1da98a5d446d7637cc06a.npy +03636649-25f1a1563f38912250f0b0248b30425.npy +02876657-6ebe74793197919e93f2361527e0abe5.npy +02828884-fc3865756db954685896bab37ddebe7.npy +04379243-65624fa127a2537df3c9c1464e55d580.npy +04090263-8f905b2da32727682a2679e9ffca8e38.npy +04379243-d3a5d161ca44660d4671d97b0fd17f51.npy +04379243-6c10998b950dadd4cea003eff0268278.npy +02828884-eedc7453ee8b1cff9ca96b2737246fca.npy +04090263-8ec183fdbf3fb696e1f2a1daf140ac9f.npy +03691459-be83d48fc695dca62b4e8a84a498fb09.npy +02958343-371c5e74c66d22d451973ec97171fea3.npy +02958343-c35ebd98decdebb9db7706d93442f2a7.npy +02747177-e7682974949a6aadea9a778eef212687.npy +04379243-9472c006a5d35b9ab606ece4189242ff.npy +03001627-689dce303ca3781c19fb4103277a6b93.npy +02958343-7521398f7ab70a073c1d9add3a87bd2d.npy +04379243-889c9aedc4ba47592fb02b79d375eea5.npy +03325088-e9e2bbfded7eaaa99e6460c75101f5b6.npy +02691156-97eb9cf6c8a11a389967b23b351d6841.npy +03001627-9a42cff883cbd358106f706dac6c58f0.npy +04379243-d6577674aee8f8cbe986c6d94503b284.npy +02691156-5a815646537e3b39f51612c193433f02.npy +02828884-16592a1467b7751fbb9faba74eec2c74.npy +03001627-6e06af0dba36d9d8f3f3ee5e8ea028d6.npy +04379243-bb84310d8f022346f2b931201029bc76.npy +03001627-5421802bb8e6e9781ea54e1e7afcaee9.npy +02958343-3373140534463359fc82e75321e09f82.npy +03001627-e0a011619d6c9df19f1deb04fb8ae481.npy +04401088-e483787b7f9c606042f892024869e751.npy +03001627-511a03618c9bf2e7fa762d956b3074e4.npy +03636649-ca6812040234d1ecf57534363fbbac3.npy +02808440-c0249608f553686f3321831d2245cf06.npy +02691156-31a06c63b8932cac8bec85d7b4e1ee67.npy +03790512-e1382731f6fedaefd6207a00f6cde01c.npy +03636649-4f3f01e4b17d018ddaaf0f74e020d2dc.npy +03325088-ba1d52a1f3ea97f7ff8848ee936b8531.npy +04090263-39dae1fb0cd33173d2c901959c439025.npy +02828884-918507f83ae9eb64ad5067eac75a07f7.npy +03624134-4e031e214c34963161eb581103cb1fbd.npy +02958343-72b2c7b2a49d46ac2a9eb0f146e94477.npy +03991062-d7b4c88081a1e59b5117083e4484ae48.npy +04530566-b93e07e84bdfd620f4000b62f164055f.npy +04256520-1bfe2d5a13298b40eaf288f952624966.npy +03593526-fcaab68d0507e3255576bbe3889cc2ca.npy +04074963-c72ecbad07876e71ab0467582043bd43.npy +04256520-f1d1fdca528582dca6c4f2c64bf812b4.npy +03001627-b267d11790325e6cec7cbf3284585a40.npy +03001627-e9068bd3f1f5e59b3fa02fd212ba0e5f.npy +04256520-16a5920c004800ca76e9713f57a5fcb6.npy +03001627-b1ef4c02ac7a0b28632c9ddc45ef4651.npy +03467517-deb865bdb628babd1ea49e67c45d0098.npy +02946921-a7059f3bf782790654976319206e3c9c.npy +02808440-184db8d39477c64f1475ac52df31feb8.npy +03046257-3a1e36329722686c2c406efbeb1811b0.npy +03691459-fba117b56b6829d0cbd549969c6fba9f.npy +04379243-eed0984ed7a72e99cd1c64069cf52e3.npy +02747177-9afa30986badc1f956f6fc4b4ce1db04.npy +03624134-70b6b3ba6a27fd6f782db73f915dfbb8.npy +02958343-62128b128c9a54c6389cb55d070b61d3.npy +04379243-1adc25c3c29e98c454683b99ac4500e8.npy +02828884-fbed7adcac3217912056b4bd5d870b47.npy +03001627-7f1164e82e3a975fcc1908493f380315.npy +04379243-9c17ba009a1f68a5f31d4c4da1121d06.npy +02828884-3abf9811f26c9752a9b8d9d3b5cf54cc.npy +04004475-587fcd5e8024ef687a9cf77b454ff9b2.npy +03797390-df026976dc03197213ac44947b92716e.npy +03797390-586e67c53f181dc22adf8abaa25e0215.npy +02880940-77301246b265a4d3a538bf55f6b58cef.npy +03046257-6766bb45cfe7be90c9fa91c1b1e026fa.npy +04379243-df9a0a4a35c0a1482a610b86c623da3d.npy +04379243-2fd71db402f3939164a62403221fd59f.npy +04379243-335bbef681cee5b46b3f6cce098c8918.npy +02958343-885a8852bda6bad7774c883319711a53.npy +04468005-cf8db3c714acb984239fe5909143a17d.npy +04256520-13d0d8dcb20c0071effcc073d8ec38f6.npy +02876657-d44472ef7086538676bb31db0358e9c6.npy +04090263-7ad1c8369ecca95ffb5c1b0f759e2bc1.npy +04090263-8be6c2867bbd8d27143bcc14d754d44d.npy +03691459-4a4132b1bbc364f573c609379da5b9c2.npy +03001627-ce8e6c13899376e2f3c9c1464e55d580.npy +03001627-cd5007a237ffde592b5bf1f191733d75.npy +02691156-a8471560d4dd5a31ebc34aaab30ca460.npy +03467517-de630541c5d2a44e4bfcfdb26b8cb2c3.npy +03337140-18fc975ac7977ce64c3aee8e9d3a6ffa.npy +03211117-fdf3953c665c36fdeb47c06d7d8c2d65.npy +04256520-3140b8db45212ea0d9b53420a5458c53.npy +04468005-4a4e193b21105f90ceeb72b524f3e0ca.npy +04379243-d6e677600a93bc118ac5263758737a81.npy +04090263-28f2da42122d400d9d5d6d3d4bb65831.npy +02924116-5c718c46b33d804b417efb0412430786.npy +03001627-6c413dd8728bc004d22730b0728b2fc9.npy +04256520-13181141c0d32f2e593ebeeedbff73b.npy +03001627-b81b9e3fe60a49bc55182f299fe41fdc.npy +02924116-47fbe55b7f5f82287e7c9f487eee4fdb.npy +03467517-935eb2290503cc0a343b0b12983b9982.npy +03001627-a3acfe6f313ab881bb088904f7cb154.npy +04256520-d3db0f5bf70b9e32f7823f022ac104a2.npy +02773838-cd1e74f430acfaf0504721639e19f609.npy +04256520-267dcf5952e84873fad6a32f56e259a2.npy +03211117-46cb55835a88ca85eba70eb27950150e.npy +04004475-a945e3df688458ae8075fd3e4c0fdb7.npy +04530566-8bef56b64003be1789f903fb361de4ca.npy +03001627-f76d50f900b034af19fb4103277a6b93.npy +02747177-dfd96d49538de0008a606c63493ddb7c.npy +02958343-8058b048fcc7730ffaf9aa0fdafb5e7c.npy +02691156-e7e73007e0373933c4c280b3db0d6264.npy +04379243-1c2fb38795e6e3c858df8eeaf3dad1c.npy +04401088-1ac1e6fc09611ff049c647f92ae11714.npy +03636649-f79cd66d0a369bdb29a42a0444436860.npy +02958343-a387407d49e209fdeea60824a43a0b.npy +03211117-7c889c3c89dd0933ce2fdea99c5936e8.npy +03593526-aaec691558f7bdd05ca1f314f1afc186.npy +02773838-157fa29bcf6b890d76bb31db0358e9c6.npy +03001627-4bb5877100a76cf5bee7d080c8f1e1fd.npy +03001627-c51937167dd0db45f7628281ecb18112.npy +03593526-b4b7ae650665ff016daef73a0864abe1.npy +04330267-82f134ee4f0dc5ce74dfd914e703ac1f.npy +02958343-186646b16a670b7d69a949ac99a843c4.npy +04004475-e33f0d779f8f0f8127373c7dfd2344fc.npy +02933112-7a051550f229c9a75588a2543ef0b0b4.npy +04330267-a349baf8780207242d3c7a83a255982c.npy +03636649-50683065aa8bd6bec308dc58cdbda034.npy +04530566-78e347c044ac743de2d4c157e5bf1dde.npy +02924116-c20b42745b5b344ef2b99dcb65afc747.npy +02958343-eebc48c480032e45473f10e6caaeca56.npy +02871439-e8f6e0350d99de06be1a3993eff3fa1.npy +04379243-a5f3c1314c027654f12d7184a2ad3430.npy +03001627-44a2a3952ea2315ff51f77a6d7299806.npy +02691156-10eeb119fd5508e0d6d949577c389a84.npy +02958343-da5ee2c950a848f0af8a2e210ebd5168.npy +03593526-92fa811a0cc76fbefffe8e781bf3bc2.npy +04379243-ebc897217df591d73542091189dc62b5.npy +03636649-eb0d19ccdeb98cff88e7662971dc736f.npy +04379243-7147a78bce941b6e9784d1512b6b87bb.npy +04530566-fa8af8f2bedb0d461f29de30ec1bf6a3.npy +03325088-ffbce2bc2d46ad8c3c8d0fdfb1cc2535.npy +02958343-80bdcb908765eb9ec349f2dfac43a4cf.npy +04379243-dcab9aad5876cecd597ff152ef65c9c3.npy +04460130-d4dae64aeda5a50f4f87ba59623453fc.npy +02958343-2a554a704a27618ea37f3fc191551700.npy +04090263-926ced4104fb5d572f63bc22c4d8bf9.npy +04379243-f158c5c293106fb17af2ac6660aa6669.npy +04379243-aba115d7fd94b7cd4bd9e0690b0b191.npy +04004475-41c5dd936949a6a083da7f4ae241cd9.npy +03642806-b3c5bb4eb4c797ae6984b767317d33c4.npy +03001627-ed40add41826f68ab76e29c9c43bc7aa.npy +03001627-758bc4143fceac844224ee0743294f79.npy +03636649-26e6dc505f376ceee6597d391ab6fcc1.npy +02958343-ef8e257ca685d594473f10e6caaeca56.npy +04530566-fed3590199534e0f300dee22a3d8ed99.npy +03001627-51c858aec859bafad1e274d497440a3e.npy +04256520-b598d571630181e171e07968d18a8d52.npy +03001627-56b171b1f1521d27291d12adef12641b.npy +02747177-4c8e43db118f78c85db5515d1151e20c.npy +04379243-73ace155e7a4b1989d24dba534412246.npy +02691156-b65ac56abaecc35bedcd88be6151afb4.npy +03211117-61a81475b820a85aa73340dd35da57bc.npy +03001627-ce9cedc58c77aab4b5a19b1840ec7af.npy +04379243-a7c9de3c0808584ef827070eae09df.npy +02828884-e60121b8e4ef137bad5067eac75a07f7.npy +04468005-e344ca94076866f62e80200f954ca1fe.npy +02958343-e6ec389325de7ae5becf71e2e014ff6f.npy +03001627-522eef970fa6d87b7d9c441a2a657ea8.npy +04530566-6ec6d6a7124542c1973b07394b864922.npy +03636649-356224e2ce466b551218479e9cbf7bda.npy +04256520-a90cf2c399b7052cd4061e538ffc8def.npy +04379243-b37b72a898169c971ff2429be93a82ac.npy +04401088-bcbf0ce42d2b0f91abae9246594d3f7d.npy +02691156-220a911e2e303865f64801ad2940cdd5.npy +02828884-9787be3282d13a159a3528690d225ee1.npy +02691156-afd6b2789e486ad4663191fd557d3a61.npy +03001627-791c488a167bd73f91663a74ccd2338.npy +04090263-2391fdcf2158aebf9c27f9a5387b5fc.npy +02958343-8e308d28d463427f43f0e92e826556b8.npy +02691156-caa7e70beee4543f42c20743f866e1a6.npy +04530566-161d9d8a1550390ff4000b62f164055f.npy +04530566-696136ed6723971649f471d054f6b528.npy +04330267-b947b4dab047cc879d1589237baad02.npy +03624134-a33847e9c32c1afc93ac017b81605788.npy +02691156-a6b09752263b1de2296d88107d065f6.npy +02773838-4a175db3a8cad99b5dd5ceb34f6e33d9.npy +02924116-41b8698a72385b7c52470de2774d6099.npy +03691459-b43daefea1c1e5a5b8cf54556d95458.npy +03636649-7b005e23eae2768eb08c032bedc99529.npy +04379243-eb291380d399ddebafaac116abdd44e.npy +02691156-4982bea0a007c19593b2f224b3acb952.npy +04090263-e5e7552e8dd1b5e9653fe2b064cca38c.npy +04530566-c8f85606ab95f0bd75086ae01906f5ab.npy +02828884-d8a1d270154b70e2aa1bf88d515bc6b2.npy +02871439-ac0710b8484a44fe20dd2dd4d7d7656c.npy +03046257-603ff80e374621a69d4f807ccb693a14.npy +02933112-7ed5c429313f20e079bb09dc5605a57.npy +03513137-3e3e8a71c208d991226eabe1cca3e850.npy +03001627-e967ee5f0790d685286e59f068d9cd0e.npy +03790512-295de7567ed18e692692003428d9fde9.npy +03001627-7fb336186da77367962800be79c6e52.npy +04530566-8790881fbc0331a87cef2df31bcf9d93.npy +03467517-b36971c158d49c94d57700c05b1862d8.npy +04530566-7f8d800b3fce12a7874f0e42f84eb4f5.npy +04379243-8a545c071537d55014038d588fd1342f.npy +02924116-79bf4c4574bc9c4552470de2774d6099.npy +04379243-e653570cc6bcf8783f9f131076f84791.npy +03001627-ec25a41ca233ed096e5a467428553af2.npy +02933112-e0d37d661f26e9eb4b8710a3469971b1.npy +03001627-61fcffc9fa0995dcdeeecaed91450a4d.npy +04468005-119446fc9b593c594f57a4cae005e56a.npy +02958343-335b3ad6f7a96bf251a95aaa6caba1d3.npy +03211117-87f8c79413300052252cde31666379c.npy +03636649-aca8867b962deea91a8781c24b79ae57.npy +04379243-5e84a7deca3e153ce1c2d3f86b7aa002.npy +03636649-78f85448752ae2963873cf6e670bb8b6.npy +02828884-69259c43d80d4815cb2a965e75be701c.npy +02992529-b72ec892f88ab015433d4f1444243caf.npy +04379243-2bd90eb4b9aaff9af84b0be7f50940eb.npy +02691156-7b134f6573e7270fb0a79e28606cb167.npy +04379243-efe6257c1073e003c862eec8232fff1e.npy +04090263-900211102042c2d8fcfb3ae2df2f7efd.npy +04379243-54efc0d108cce07ee166717db5dd896a.npy +03691459-30e85c002b800f2771fd733ac7e95be9.npy +02691156-71a3c6e1c87c8b42233f6392bb87bbd4.npy +04379243-a088285efee5f0dbbc6a6acad56465f2.npy +03001627-b475d6f1cfb6eee21071105723d4cf63.npy +04379243-34bdbfbe94a760aba396ce8e67d44089.npy +03001627-2c40da664d4e736b972d35c68e1bdca3.npy +04379243-601fea1fbb6d791589ccdb4a5b6b972a.npy +03001627-802c4ba91b2d1dde9d03faeacb82516f.npy +02958343-43874d4b5154b6a0e3a6d6259addf247.npy +02828884-393bc2b638ed33fd201085e80edb26a.npy +03636649-83353863ea1349682ebeb1e6a8111f53.npy +04256520-eda8029bfa428c38f6ab3cbe0907fba9.npy +02808440-b3dec10ca40086343af30a3946d92feb.npy +02992529-79912d77eb2866af4e964633a1b1c39c.npy +04256520-e5d5c0cfeea2fdd11b17743c18fb63dc.npy +04379243-dd7e82f0ccddf0cdea3769fcd5f96f4.npy +03691459-ccd635e4cdca96e33b6e05aed261d1e8.npy +04401088-7483bc04eec05077b6d41c42f7ade8c8.npy +02958343-be7fe5cfda34ba052e877e82c90c24d.npy +02876657-6c56bd467b8e6b7912c4d7e462c15a1a.npy +02958343-6ee9f222a540a905e4b68d3b17c43658.npy +04379243-992c576d8efa6d5870c3ad1df4ebf5ca.npy +02818832-a7b24b5ba84a6bc6545580104c9b8ca0.npy +02691156-b848dca797986bd69d175f8055b49b9.npy +03467517-e50dfe2b13d51ea1adb66be7b8c12fbc.npy +04379243-24187332192704e4519259b5fe9bdf5d.npy +04379243-77a115a1ad9d7e687634fef39c2ce2c7.npy +03636649-41fce4197aad78f76fab5a5e55726ee7.npy +04379243-e70d9645a26a4e941832ad614f693f66.npy +03691459-576e85200907fec189d3b4ea8dc19f36.npy +03325088-2a7ffc2172f9a2ddb362845c6edb57fc.npy +03085013-9ae261771f20269a2cc2573cdc390405.npy +03001627-3dadf67ebe6c29a3d291861d5bc3e7c8.npy +03797390-1ae1ba5dfb2a085247df6165146d5bbd.npy +03467517-6565cb5e586aa68730f83c7e8a7d80c9.npy +04090263-8bc74fea7c5e6f05f95499016f29fbc4.npy +04090263-decdf532717c45767a9bdfb16682d944.npy +02924116-10f5a8abbf0caceb34c10c89302b9aba.npy +03001627-f4de0c72715e193deb1f243bab39fb29.npy +02818832-9f71047cd23dfc00d81aa8b56a36ec8.npy +04379243-ef4fa923a1c2a3215f25c76975ee64.npy +04379243-7d4ccf874d0f1060d59c95a5810fd5d7.npy +03991062-e23d3038f81e65f498c5858b88d0229e.npy +03211117-5cb4fac8452906f66ba14bfd91a75020.npy +02691156-35611fc0fecb7a795e02646e6b8fbe8e.npy +02828884-c63561b50109b27bd4d8765e3910f617.npy +03001627-741bf2e8b46b3082720f4a96fb7a3b3e.npy +03001627-519d19f3adebd20aba49014d9a3afe99.npy +04090263-37914b7cd5c02da8fef144202cb2b935.npy +04379243-2a295b1bbb386e2f3ffa3a50996ad39e.npy +04530566-d0afe316f1648d22b5d16f91270f7fa2.npy +03001627-752edd549ca958252b4875f731f71cd.npy +04256520-99ca3d9ee631247f36d8dd30a594b2af.npy +03691459-1f2a8562a2de13a2c29fde65e51f52cb.npy +04468005-ef1ec257503672bd44df2c169375db7d.npy +04468005-1c416135207d17ca3023a62310645ee8.npy +03593526-8f0c5b50ea07f88e59c1c78579056df.npy +04256520-431ed7bd770ecdcafebad4f49b26ec52.npy +03001627-67d296fd51dddfd4bda72093f9b5aa73.npy +03467517-7eaed9980af85df32ab677b65be9086c.npy +03325088-4bcbe4f02228788d50da8b99982a3057.npy +02958343-e2ceb9bf23b498dda7431386d9d22644.npy +02946921-bf974687b678c66e93fb5c975e8de2b7.npy +03325088-bd0a6045194ff62176c18e71fd49c4dc.npy +02747177-91465736fa174801ad5067eac75a07f7.npy +02992529-715a2661c9be051bf4ede441a9f9be4a.npy +04256520-6c8364730b3c64a43fddc4e3be2d83c8.npy +04379243-d1efb527d5cc9f98c1dea9c21912d169.npy +03691459-a4180d6214012dc7363d10d9d37a65e5.npy +04379243-bf899a2e47420008ef1759e0b43f0fd3.npy +03001627-44456e87be145a703c8d0fdfb1cc2535.npy +04090263-a6f0f0aab2ab2591341b8a806253912c.npy +04379243-ef72310b39244eca6aa35752fcfa44c0.npy +03001627-22f7d658bf2d65da2933f312813ce997.npy +02933112-9edead26059cae09e3f7a74e12a274ef.npy +03991062-ed1faa6575c8b1cb31096c6dfcac53b0.npy +02801938-663082bdb695ea9ccb2a965e75be701c.npy +04379243-8e3a92a1f9155845d810b14a81e12eca.npy +04530566-849f7c682fe9160d8c1a083ca347f005.npy +04256520-1bfb1f52f2200860c3eb4329189b69dd.npy +04256520-addd6a0ef4f55a66d810b14a81e12eca.npy +04379243-559582261b021b7e4f987dd564b75f17.npy +04379243-f01768b8b8ba025ee45ef4135c266a12.npy +03001627-74539775b5ff9bfdbd935a20ad27255f.npy +04256520-86c169593e5584233af1c639b9b2ebcf.npy +02773838-8bc53bae41a8105f5c7506815f553527.npy +04090263-9718f974dbf0c599f0e835155cdd677d.npy +04379243-c33d942c6f7d517d346ba1ca782be6d5.npy +04379243-93040a14fad5588ed889130b88839a0c.npy +04090263-63ab37430cb66270b5666ac9dae008e8.npy +04379243-90be5de0faef91ef3f7e27638e63d848.npy +03001627-28673322a55c9935183d5461e0e1f71.npy +02958343-51eb6c713070607db9cc180a886c1254.npy +02691156-59bb001a6f7301b0bb00d3d91443cc67.npy +02958343-d18817af1a2591d751a95aaa6caba1d3.npy +04401088-38afc0467599bd6bfa13d53e5e4a7d2a.npy +03691459-97e93552e141ae2432caa5592532fb76.npy +02958343-332ac5346c7d3c0f8e35db9103756ad5.npy +04379243-d95fe848b19c277a1fd3f440755dada6.npy +04379243-e537c592fdd7f7b7c3bd24f986301745.npy +04004475-f212a6246d96112d4a418e49f65931ae.npy +04090263-6bbfdbeba3b0273316b34c3751bc447d.npy +04379243-21136301f27dc9bf84633b41c8a09fa0.npy +02958343-b9786e1b059a1712ca92a4cdad802b45.npy +04379243-7d0c5e28089c2b7bd99e852ee772dfa4.npy +02691156-d777b1e4ba72cebac5353b0f3cdec54.npy +04090263-3977db3c5730fc7216cf8b1cd2155e02.npy +02828884-a76a3d33ac6c3c65d46c340938e2ff1c.npy +03642806-234155f4192ecf3da97e5dec8972a635.npy +03337140-a0a47668bb5a53769a5d5a8c4f511248.npy +02933112-b12af552392f92b476e9713f57a5fcb6.npy +02933112-aff3488d05343a89e42b7a6468e7283f.npy +03691459-6995acbcca6f9167f5e02330ef435fa.npy +03991062-63c783fe720dfeb06ba14bfd91a75020.npy +04379243-72edff728d75b0b8f994e2a430ba61bf.npy +02958343-ccca16b8302bc8bd13ded1857c15b5b6.npy +03593526-18b41cb029cf7f6c2b151d8b52c53b90.npy +03642806-9297e108b9780fe7da0ccb8671dd235b.npy +03691459-f046081ff90ebb6dce029fab54b6cfbd.npy +02880940-a2841256fc6fd90da518b93bb7233de6.npy +02828884-c3feda2ac776a972b8962f874d138696.npy +04379243-218f7d1742293b9b2f56d03f2a22adfb.npy +03691459-6bf052e16794f2a73e1b2d018c0512.npy +04379243-47c51069048eedfea9646a2bf24db0c5.npy +03636649-79b93ef5e8928141a54a0acb16609d15.npy +04090263-458578892b309b2080c9c53be28cd7ba.npy +02992529-1bb65c38e6b563d919bade123d9b1a21.npy +02876657-437678d4bc6be981c8724d5673a063a6.npy +02924116-46e634c8d00e9f89308dd10eb9e6032c.npy +04379243-c9221b4eef51600ad9deb3f829cc2475.npy +02691156-398ff83ba75191f050405f236096897d.npy +04256520-d13a2ccdbb7740ea83a0857b7b9398b1.npy +02691156-9b60b20ea5fe6f002a2fdfabfb4182ed.npy +02958343-6c1568ee8807fb73aa69dfdc5532bb13.npy +02808440-b1df1ec87212143781ed34698a1642b9.npy +02828884-b90a642198dfd67ba6cf6cbb9f4c2bb.npy +04379243-ed00de0ec65a54c823ed665630afd1ce.npy +03001627-f54c7cbbd49ec8eb429c1439cde9f6d2.npy +04379243-4489bf9e90a6918630bbd4cddd04c77b.npy +04379243-eb984a4ef0dba0eb445e85eb534460b0.npy +02818832-a0e83139d41e3765e2b4cc1c7993e4b8.npy +04379243-318f4fca1278ea7cab0467582043bd43.npy +03624134-a205f01fec2d4c78c1cc4ae0ecf50bf4.npy +03691459-a82329a937432afe8d28f674ed08c521.npy +02958343-468be6b80d1c7dd655ac255cda83e91.npy +04379243-fc31999571a8bf64ad5d470346bc4d15.npy +04379243-a35771ed1c74b778101accd22c701b9.npy +04379243-8334a19ba0063c7faac58be63ab4013b.npy +04530566-4f9d7b905bdd80792b786ce268ccf414.npy +04004475-2af74548033015f453227dcd0d547ba6.npy +03046257-1f7441e3dc465f1291e12c4c8cef305f.npy +02946921-fd40fa8939f5f832ae1aa888dd691e79.npy +04256520-753e1bb8f3164ded7b3ec0bc4f26f615.npy +04379243-6c46312d5a6b81a59e4965f0106e00d9.npy +02876657-b1d75ad18d986ec760005b40a079e2d3.npy +02691156-3db61220251b3c9de719b5362fe06bbb.npy +02958343-d4103822895075e1c6acd56dbe00811f.npy +02808440-2c62b19b80a63f443321831d2245cf06.npy +04379243-78f387d6eee94759db6f3ca49e992ad8.npy +03467517-80f8b25d8dd77add93a644dadab2d1d1.npy +02747177-ded74a76b1a4dc8ecb2a965e75be701c.npy +04379243-c8ba87c9581f9122f51f77a6d7299806.npy +03593526-fe5561103c4e12864725f67267e31c89.npy +02958343-7cd83953000adce622cd6c209adfc63b.npy +04401088-4475473d3a96860621844676433a0aca.npy +02958343-e97af5444370eaa95fae7711b4095f8.npy +04090263-c44f0aa417ed2a77e270f84701afcd4.npy +02691156-150fd58e55111034761c6d3861a25da2.npy +02958343-8c264b10c4ec3e91fdeea60824a43a0b.npy +04090263-ac57851b846a48529f433921788191f3.npy +02691156-a287dc5d0e28d3d3325212819caa597d.npy +02876657-452c562f86da1ca7bdcda0bf7e7b4744.npy +04330267-68bd9efe9fc3373f47622e8cc2e641a4.npy +02933112-b38a8896aa33692098605fee62c12dfb.npy +03790512-f93a67db59f4a29cb37378f3c85478b4.npy +04256520-b6384ee46eec7bd5df8d3317f6046bb8.npy +04379243-6d22194fe700af402b5fb024f65f6da.npy +03636649-2522a20be5c204afa5534ff9c862888b.npy +02933112-4acadee1dadac64e4b8710a3469971b1.npy +02992529-5286f018c374d3ec3f7fe3cbfc3d51a7.npy +02992529-180f36e0bdb9b33f53de6f45c4ae68a9.npy +02992529-c202335fd3dccf9d45e2a4e5729b970d.npy +03337140-81bfa2ff00f5726a336094a98bcf39d7.npy +03691459-f150315ffddd85353ad55e05c29c23ee.npy +03797390-99eaa69cf6fe8811dec712af445786fe.npy +04074963-29310c9b5bc234155eec6d8d24f1fde1.npy +03991062-b4610dd2047073ef1781e1106734ef2a.npy +02828884-a3f987a1f22abe81c01b94c5b8c30315.npy +02691156-87069f21b11c180799a771d197c7b487.npy +02992529-4f3c84ef24e1fe6f3b41ed175964f6ee.npy +03636649-c603039e59ac33a0ce1bab91cb13240.npy +04379243-91919e69d7aec2b740dc81e448174af5.npy +03001627-f347f2a3d85c9a823fa92d98173c06f.npy +04379243-c74f1c411bdf7f57d0efae8dc996b9e.npy +04225987-56c6e4dcf52c32fc1768eb6cdf70bfe.npy +03207941-4a4d00a00e723983df3a1b0d597ce76e.npy +04468005-8f7eca0b9483de30a814ca8f1d6af9ba.npy +03691459-3738550fa707533073312da09abb660e.npy +04256520-325fcce8c386f813e20babf15421d6de.npy +02828884-515716e2bf805c088430b7446f9e1252.npy +04379243-10f3c10837232428c3bd24f986301745.npy +03467517-43884c4afd9e97d123247d005da93d43.npy +03001627-b11640431506c15489452a0032ea575.npy +04468005-2cebb68aab385306f6fb0164eb28c4c2.npy +03001627-3eef51c1ba49a32ef73a9267136cfb76.npy +02828884-4d1d28d15b19f9101e0e41d96d3d0a78.npy +04530566-70d4ca23f31a5c4373c03aee5e8475d4.npy +03211117-8007344358703f62d26c7f75d64f049f.npy +04379243-15d8de2e2c672a445af983a27c524ad0.npy +02880940-bec41cc7f631e00b1bf40e92cbe8569f.npy +03790512-e63a6a3a0c9765433d6587690e56f61.npy +03001627-331bfb4cc56f09e201cbed672acdcde.npy +02933112-1624e80fb20e12741bf2b66b52bf6885.npy +04401088-ef16dd3bd944608821844676433a0aca.npy +03467517-7d81905ed85f66f40c20797381ee39f.npy +02691156-f4818cd7c0701fbe752556d244bfb42b.npy +03467517-3243edb05f5e8803ac61a2f8346a8f.npy +03325088-68a77b120dd7a73b362845c6edb57fc.npy +03001627-2fd314d0a19433c62c37553db37ec752.npy +02876657-61847ebb20b88ce2a62e98cb10d773b0.npy +04379243-c85fffa8b368d05663191fd557d3a61.npy +03467517-a600151f96c1f1ba2c3755be90ec8862.npy +02924116-5f36b7a19c0f8308576927b79fa8f91b.npy +03001627-508306f8ddf1b54c41cc9e8c39b4e399.npy +04379243-6235d7bbd30566e4c955e5ed03ef3a2f.npy +03001627-35c2de57ee36f652492d9da2668ec34c.npy +04379243-d8d504a5e90e5b48c3bd24f986301745.npy +03636649-21e25ed232808a5a6fdc47d9bd513767.npy +03211117-1dccc6eee1ab6f942d692d2ec5374fbb.npy +04256520-fba76a325f400c597178e3cb5f806466.npy +02828884-445230afd5a0eda8714b6900bef4d88b.npy +02958343-794fc3e07d3c5954514e3d96995c555d.npy +03467517-e0e7905f91530fcc633c3142a206ef4b.npy +03991062-25a43049dbe332ed30cd51d117004d92.npy +03691459-5faca1b9f9a94e379a1e7168a7eb421f.npy +03636649-8f2eec27fa65b6b7ef76898f881b76a.npy +02958343-ad41b5992798d44bc350327861730790.npy +02924116-b4911496c498eedfb0912560089ee415.npy +03325088-92112e7fe6e4c131b362845c6edb57fc.npy +04379243-fc1956b87d9cb195f5854716eabccda7.npy +04379243-40fab70cda2e2dc7beedb4c8fd29e2d1.npy +04256520-6897c646edcc98c149d579ea0e00a990.npy +03001627-b22405009444df73d27ba3fc43e70958.npy +04379243-ff127b5ab0e36faec3bec646284d5a6a.npy +03691459-da21a8c569ff0ac4a7c719349406e0b7.npy +04379243-a9206327ea5b37d75fb62d44a047792d.npy +02992529-35dc3f0f2f5fe8d667a434dda72a2c24.npy +04530566-4818277b913b682a3c3bd8d7abbd3fc8.npy +03691459-9821d2e9018233f665a0f3090522e03c.npy +03636649-94940283714fdff6244ba644cf33cb2e.npy +02747177-37f1daa11b023fdf81faebbdea6bd9be.npy +03001627-67fe832a22b91e6c54ddc93d2b7d3d65.npy +02924116-5c7d98a481c9fedb5024b77c58783478.npy +04379243-25bca46cd4b9c517d1bd956578bfe63e.npy +04090263-dce3a4c4ce2fa691e777176cf1197154.npy +02691156-25ae9c70ded5640ac2a9d7232db0ed61.npy +04379243-77b83ff0d0eeb34e6349f6b5431fb3d1.npy +04379243-62fd8ef531c663bf6fe2eb61cd6e74e5.npy +03001627-dac4af24e2facd7d3000ca4b04fcd6ac.npy +04090263-ab1bf0d24526c51db524fe86a5d055d2.npy +03593526-d6209472e79d0a2422b13c48c34706de.npy +02876657-77c9a8391c708ae5940806ade53ef2f.npy +04530566-15d805635f77420ef724cdbbd599557b.npy +04090263-2eb7e88f5355630962a5697e98a94be.npy +03325088-f2db780ff630c097eea9975640c4ae20.npy +03001627-4ebb653961d95dd075c67b3b1e763fcf.npy +04256520-81d5e6d8bef76a51ba6c2a353e21dbe8.npy +03636649-e1ecd3a4734b91fffcb8d8c6d4df8143.npy +03001627-57d4b5a07e67c24af77e1de7c7a7b6e7.npy +02691156-16689e54c884aa01639c7058eaf33ae.npy +03948459-c344176cc45786e35f08fcff2175b4c7.npy +04379243-d16b6d6daed62ead49936479d30607f4.npy +03691459-8c18ef2a9170a8144884161c20b458b0.npy +04379243-c5087fce38b009ae30bbd4cddd04c77b.npy +03991062-93c837235aa98a7ee685b534d1dbc410.npy +04379243-f7bb30d9c073c0be786dd1f2ad4d8c65.npy +04256520-b3cea4461eb14a3164d6551b52610c81.npy +04401088-bef91c1804ec226e5b1c02ea3a290822.npy +02958343-9f7b4a82becac9cd5568b8cbf53329df.npy +02828884-95ee6234a1638f892056b4bd5d870b47.npy +03593526-460055a94c92bc3ed680196133d8b70f.npy +02828884-d7293ad1c563e0ee318b348b36fba247.npy +02691156-31d1cf39b807c856efe0d4e1eba2e3af.npy +03001627-586984ccc3ea15676c441a62670bab86.npy +04379243-d51c7bcf851a368f90193fd5f5187893.npy +02992529-8873af9392bc7506f1cb19f636b1c2bd.npy +04401088-57daa58dd0715c58beafa80aadbc3232.npy +02958343-53895830484cd75d9a68e1b6bb3d1631.npy +04256520-62d40988172e8c685ff61a3a2a0e2484.npy +04401088-e6f4ceda4907fcc13c47272ccf8f316c.npy +03337140-fae333fdef97b004193e4b893d21eb4c.npy +04256520-5ad772a3c728b948d329896bbf26eda9.npy +02691156-947d6b9cd1966e2e719b5362fe06bbb.npy +03467517-a57ee03b7c376eb7b785a4ac4a0dbd73.npy +03001627-4bcf02d408a42fedc399b0e96597941f.npy +04379243-f5aecb6607876495e03eb69820d1aaf2.npy +02958343-aee2d4cae2954ffde51212f97a7d9486.npy +04379243-ad7ae42e620d2ce7e074517a246f1e65.npy +04330267-48b9c0c72db0859cc0fd596e40539.npy +03636649-7a9872f1e0cefafd7d8864caa856253b.npy +04379243-1c2aa66d76302e1f696f6d06eaf4948d.npy +03691459-88c9a7928bc35ab392b9c678bb1d631f.npy +03001627-c106cbd7794c6b6868661782af60b711.npy +03001627-f1fc7d26395549ba5ad8ce80f1a173ac.npy +03636649-b4f166440439171741657e31b569b105.npy +02818832-97f9d6942dfc12c08880edc6251fa529.npy +02933112-484f3660bf095e6f2b8a1a2aaa466160.npy +04090263-9f0b13efed3da628309c2ee598f7f2c8.npy +03797390-f42a9784d165ad2f5e723252788c3d6e.npy +04090263-1fe5ddf1ca0fde916b2c8bb96250e4a0.npy +03991062-ec2c1338e2faae58adbcc9ee28cee4cb.npy +02933112-bd2bcee265b1ee1c7c373e0e7470a338.npy +04379243-6ae63bfca4db6e42937c609387f975a5.npy +04530566-f73392abd103857666ab813654be63ca.npy +03691459-40cd27b2f685afe3ec7f40971ff466ac.npy +03211117-437d1c161da1b9fc57e4c0b864012bb5.npy +04379243-93f94ca2abb0e6aeda9c49a653a829eb.npy +02958343-f1d902e502f474313fdffa7a79289f65.npy +04256520-1bb31ffee286d9687597e1f94410131a.npy +04379243-c7cd5977b531acd76b41b8bcd0404ec.npy +04256520-f94cef3a1dabeefeb26131b3eacda7f2.npy +04379243-d826633e8f45cddbc22013ebab50762.npy +04004475-a553c7b317e25d17b1bc85a6b37e2272.npy +03636649-e7b719516449701362525a4d857f099d.npy +04379243-798a07e42d76013582695d8aaeacccc5.npy +02691156-d13d131a649c5df38b96ae1a0a8b84ec.npy +04090263-c82214579ed998e06bb9681d4604e123.npy +02942699-9726bf2b38d817eab169d2793795b997.npy +02871439-4f0ad9b5b38853f467aad4e7f685c416.npy +04379243-99d329e5aee0fd21c8c7b57a94dbb2e.npy +03001627-9ca1c0357c3033488cc413950b617e8f.npy +02933112-18d84c10a5068315fe5c8ffd0f5eba47.npy +04256520-ae36181b10bbc7c564810cc21086da42.npy +03211117-c0ed587c1ca5709b1c9fef7c3e095105.npy +03001627-462ef3bb97a88a753efde60c5bd5967e.npy +02924116-2d11b02cedb52eb1fc99d03c124615e4.npy +03001627-87de70c9f96dc7edf5fc96890ba7d316.npy +03001627-13d3462293023fe71f530727405d60cf.npy +02933112-3475657660a798a155590b0eedbb2f18.npy +04256520-df4ce626dc8b2a744b3c42e318f3affc.npy +03593526-f02b827d757fcff25692a9640d6947fc.npy +04379243-db94dde04aad570d2f8bc0d6e7c6775.npy +04256520-9d0dd1f2ebfcf0a4cbaaa37255ec05aa.npy +02992529-2a48a703451da580555dee99eadeb47b.npy +02808440-f7233d47ac57e17f125fa9990176f0d5.npy +04379243-c5f14fe692e70a5f668ae11a7db5e82a.npy +04379243-527445c0b9cf1cda27f5c3f15a1b92ff.npy +02691156-80796b736f1d6bc78e8131a047a07ce1.npy +02691156-22e4e0210f80fae813940713146922c1.npy +04256520-ccd0c5e06744ad9a5ca7e476d2d4a26e.npy +03001627-63f6bb7487f81a03bdfa5e0753fa3240.npy +03467517-22b29fbbf99e9cbde1c6f6ff6004a051.npy +03001627-808fa82fe9ad86d9f1cc184b6fa3e1f9.npy +02691156-3ad337dcef167024fe6302fece358e4a.npy +04256520-8d2339ab19665ee3e7c7920f6a65a54d.npy +03636649-286dc622e6f19929fdbe2bf897d8a820.npy +03991062-7aa43d03be94e322e44bad6fc9badfe7.npy +04379243-f831f836f6468b28bebbd6eb70ab85c0.npy +03001627-bb831481ea5166e318656877cdc36a54.npy +04401088-f1f794c3b6ed8951d07b37cd4d789f4d.npy +02876657-77699e08e3824eab47765668cf4023ed.npy +04256520-c8663904bd8af794d9b53420a5458c53.npy +02828884-bd56c556d9514db3500cffceffd2bd2b.npy +04256520-98cff1ad40ad54bcd05576067379976c.npy +03046257-987c21af1a3664b134a81acd9cfadf13.npy +03001627-cef79d398ec49cb3d25229379db8f59c.npy +04256520-682bc1622b438e58dd97e8e261a01f65.npy +03001627-3b2d9328ab28f70122c4f7f8c92935f0.npy +04530566-22bfa8eb9cdce735d90cecb09ba6f1b8.npy +02801938-3e64a7042776f19adc9938c9fceb2ffd.npy +02958343-fa234addf8fe4f7fbda733a39f84326d.npy +02808440-315a621e6159aea93321831d2245cf06.npy +04379243-ef873c6f267860cd43ac09133d4c1d60.npy +02992529-19208607cafce17dcb85f279c97d4c5c.npy +03001627-bb7755090f984ba85dd1bba5b1310523.npy +03593526-585c1079643d859db2236bb2a62ecfdf.npy +04379243-ccb96ea5f047c97f278d386bfa54545.npy +02828884-fe5711dd4a51b102ed98cca8f0ccd5f7.npy +03636649-4ac2d95bbb9c03d1e5fc53e1eb2fc4a7.npy +02880940-c1bad5cc2d9050e48aee29ee398d36ed.npy +02828884-87113624b71e8961e3e484fe1f0aa4c2.npy +04530566-12a01b67cb987d385859fb379730f7f7.npy +03691459-298e3b4149c28821b9001bf6cb0603cd.npy +02801938-5dbf477ba7765febb3a8888e78d004b3.npy +02933112-584b055cbd62b8572d7ead8d9eea29b1.npy +04256520-b55d24ed786a8279ad2d3ca7f660ddd.npy +04379243-828aef6559b4e1b8a9f015dc2ef2c415.npy +03467517-e1c0fb24b0f16a9d5eec6d8d24f1fde1.npy +04256520-9c1565c6bc50ba7668bdb5c1c01fdb25.npy +04401088-4f71662203c45d66cb2c0b430ff869c.npy +03691459-42fe49780429d25d1de55fee5ac2c5c2.npy +03001627-11a06e6f68b1d99c8687ff9b0b4e4ac.npy +03001627-ced5a7469c77e651fff16555386d173d.npy +02691156-f1a917846d46b61f71d03b466c72ce41.npy +03001627-aa5879b3f20ea90c36b0f2a1430e993a.npy +04379243-6c56052772cdc2b66289707fcc0ca1d.npy +04379243-120ac04ddb930aa9b2029d92310f4aeb.npy +02958343-62eda45907bcb75c320fa6e2cd857828.npy +02958343-66be76d60405c58ae02ca9d4b3cbc724.npy +02818832-2e149e4f08f7cbdfed4d676215f46734.npy +02933112-88fd3b8aa4280302c59350d819542ec7.npy +02691156-d3ecaf6bb9395131d563154e026c3490.npy +04099429-15474cf9caa757a528eba1f0b7744e9.npy +03691459-624046a3a0cba1b6c70985f30f25f8eb.npy +02958343-59ed9bf99fd1262fd77312c90516c805.npy +03001627-d343f06da03eccf34c7384dbb75cab0d.npy +04379243-64155ca51be435614c9ef68654bd2fe9.npy +04401088-e3ad9c85b958737ef7c1509e74f67ac7.npy +02691156-1021a0914a7207aff927ed529ad90a11.npy +03001627-3b0ec945e7290c3a6a0677e97a0ab6ed.npy +02958343-2b246a989e9e8be151db49e653372c20.npy +04379243-c73070837a2f9efe1b45df3fb820c9cc.npy +03636649-2419edff383179cbc53c4281a65fe22a.npy +02958343-2359486974efded33121f82ae456ac81.npy +04256520-317cd5686899922e19fb4103277a6b93.npy +04401088-7731182b7b8702bb357be8fc4a9ec12a.npy +03211117-a6a5497848d40c4a46738cc3b1934e6b.npy +03691459-1686fdd7258aa16383247f812f2eaa97.npy +03691459-47a0132d9a497e8ef398d0c5832df00e.npy +04379243-27b9211229e1bf011f3980612faf041b.npy +03261776-c7d59921f034165880403be969162a9b.npy +04379243-920842b21a3c471b597976c675750537.npy +04379243-ba49e13288189be6fcb704ced9323624.npy +02691156-440e5ba74ac8124e9751c7a6f15617f4.npy +04090263-61f01c585c581fdc8ae8d8f46e8d6c0.npy +04379243-b8fb0a7e5d59693780489003722bd0ee.npy +04379243-8d1a33ecdc93bafd727e9f790cd597.npy +04090263-b0ec853833d21d36859a7164d38b0d13.npy +02876657-225d046d8f798afacba9caf4d254cef0.npy +04379243-190645c1f458a934c862eec8232fff1e.npy +02958343-cf176e853cc739bbca92a4cdad802b45.npy +02808440-f4f6e4a355028a6dccd0340812259a39.npy +04379243-24eb7a5dc2b20ab8729c5ef452d153c3.npy +04090263-68c1bcd26d43d80572cad024c77ecfb1.npy +04379243-a05c04a3cad42012fc7ff8f848d1c6c9.npy +02946921-f755800334fcb49b450911b585bf4df8.npy +02828884-438f3246c29d69e73b67a26c84477b1a.npy +03001627-53eaa7cca72c84f6cacd67ce2c72c02e.npy +03211117-dee129ab8c2f74944c58a7782e1dd690.npy +03001627-53180e91cd6651ab76e29c9c43bc7aa.npy +04379243-a886d16c7fffeb874d6c356c3dcebb.npy +02924116-6d53ec3b3b8026d1e797b014c500fad.npy +04401088-c3e18e5d0f7a8709e41b17b375798648.npy +02828884-fec8bee05108531cf7ad31381468cb01.npy +04256520-e66f4bd6f5075d1755f9a00acc25f137.npy +04401088-5413423e80c9f264abe7f17e61fac246.npy +04379243-803fd62336eca9d58797727ac1d88278.npy +04379243-98356e87a3f5db06a0bde355e2e21370.npy +03001627-c73d63f9080e84a91b17743c18fb63dc.npy +04379243-c9b834aeda78274029edbf57bdd3b0af.npy +03642806-74bddbc79d758bcbda39f7cbbf0da6b.npy +04379243-c433bc2bac3eed219c0c9824ccd078be.npy +04099429-dc06f4a16cb9c38d92cea77f96988ae6.npy +04379243-aeb5975090a272b89f2349486c570dd4.npy +04379243-8fc6c8d02b4b0cab14038d588fd1342f.npy +04379243-1db2c973f2a3b154659277e23bf9b970.npy +04379243-3bde1338423d06b4c4fc66bd9d1f7f00.npy +02933112-9178722c21d03d3ca12fd542784d2033.npy +03001627-f04698af574cb9847edf3a3d7d1bacae.npy +04090263-5ba39bccc3073c11e0a54e072367f4f4.npy +03691459-5f3436d8bb1620f4617146ea341ca085.npy +04379243-79e3bca3008fbfcfe635ea97678c24b.npy +02958343-6f9aca876bb1f736ed3696d854eee1ec.npy +02958343-85cb3207e15a1bf8582e5e3e7771ea25.npy +03001627-a16c172406430b6af7628281ecb18112.npy +04090263-bf41504e86804d3d861bbf60d7f925f0.npy +02691156-b29c650e4d7582d11ae96ac7591d0dc5.npy +02992529-ac1e771d6392e912f594ca916b37180c.npy +02924116-d3d9e323a67cbaf9c98c13d6112727de.npy +04460130-e7a492bbc4838de285c7c66844cba238.npy +02828884-86980fcab93e60151f53db693ffe56c5.npy +04379243-4804f348d4028033134ee81f8ff0778d.npy +04256520-e481539e23b4665e20768660cf080d12.npy +04379243-b7cead95e18b570d2c97486f63c12d76.npy +02808440-25164b395b98da1ebe72274d9d6b1d8a.npy +02958343-d353bf0e0dfe3ac29cbc1c09129e1507.npy +03001627-e18ea9d7ff87c3f86a97ad5f72cdc5d6.npy +02933112-3cfebf4fdfa1384da5feafe6f1c8fc.npy +02828884-d1f9f40f8f58394c91cb0beedee33fd.npy +04379243-c365c85ae03b768667fd127a03ee9f72.npy +03991062-a9af3af6f64643cfebd761d74e9ece37.npy +02808440-13b3f78fcad66e2df6da603e92626bf9.npy +02747177-9b0f61fb80473442330afa9b9b51085f.npy +04379243-e0ea31b7fc2626ccab610b0c94236463.npy +04379243-9a01ec707c25dc606199d6fe090be061.npy +02828884-f3ce6a320a9f2791b1a00a31bfed97b.npy +02828884-4a19288db84ea192871543ab797c3d2d.npy +04256520-5148f79f518a42794fb315ce917a9ec2.npy +03046257-f1f87122fedf6e22230584014222e685.npy +03001627-517880899d26080471a782a4379556c7.npy +04256520-db1ca6cab18d4084191c3762b497eca9.npy +02828884-3b660f1b7f7f41be25ebd1cd0b422e32.npy +04379243-21ce3306dc9589dec7cb90e4399b486d.npy +03593526-cf78b551b5d698e5cacc861613759c4d.npy +03001627-4eed9ad9465482d543b9eef399a0841d.npy +02958343-2bcdaa6516a98b552abd245afcc79403.npy +03046257-8b9dac705a205cba1d2588fbbd278bb2.npy +03691459-1ccc688123d1d873ca93bc607b24577.npy +03211117-1bd2a09a9057cbaa2b518e07b1fccf95.npy +04401088-eaf85cce060622c88de42b14089e0e7c.npy +04256520-d1784efbc243913940ef1c8b63a628f9.npy +03691459-775f3b78e226f125b21450114b9ae3a.npy +02958343-792e31b0bc8415a13ded1857c15b5b6.npy +04379243-5d21564e87d0a1f3ea4b8033405be154.npy +03325088-103f0eb370d64fe532149015b3e64c.npy +04330267-5dd1c0efb1907528ff5687b000691cff.npy +04379243-b54d222311420195d9fad8aba2c312b7.npy +04379243-815ceec9c8f5dd754b8710a3469971b1.npy +04256520-e2916cab74b3703763ffebf86d8dd00.npy +03001627-46c7a2ad0abf4463bbc0e8a3b6521117.npy +03636649-23a4572a96dda133d624bbdc22e247c8.npy +03211117-134c9a46684ab57271f27bd49a6cd214.npy +04379243-69a3e5ea90d66d2efd72380f3800ba4b.npy +04379243-68f2795c385859e914038d588fd1342f.npy +03001627-be0b0a9b0a7108c6e4f106360437e8c0.npy +02992529-6449223cebdb2dc9c8c3ac9bcbcd9687.npy +02871439-1f6ba924c72ae8c46612c99aa973796b.npy +03691459-c029e58c26875322a9eb0f146e94477.npy +03001627-979d210217f798d4f4b6538438a0b930.npy +03467517-1e56954ca36bbfdd6b05157edf4233a3.npy +04379243-fd7a579772b195532de421c2ab5cfb52.npy +03001627-4b35795a0ba482cb4f3443b22038d340.npy +04379243-7370a18bebe67690664b3b9b23ddfcbc.npy +03642806-66e3b7c7f2e8e9297fd8853234f5e918.npy +03761084-88e2e2446a3cd2816694e76612a795a6.npy +02691156-e0df97dfc068e3664bf88973bd147a26.npy +02828884-b990e2ecb2650ba548e7a83cf3fe93c5.npy +03001627-fb42c4a8cf7b6d36ec89626a4213fd07.npy +03337140-e2763ac23ee84c6d91c352d02061b3f7.npy +02933112-152dd0a74ed08ef8c59350d819542ec7.npy +04004475-3453629407e6708d6f8a56ca1f74303e.npy +02808440-629f52ed43de72e6ccd0340812259a39.npy +02924116-c43be5262fdd584d1940a53cd312bfff.npy +02828884-957596b8dc4cba37ad5067eac75a07f7.npy +02876657-64faa2a6a6f844af851f4ba6aaedaaa8.npy +02958343-95ea282dbee00d45ffe141441005acc5.npy +03046257-2a979930dffe3d32897a37b9397f0b81.npy +02691156-4fd9c86e43a1dea17209009cfb89d4bd.npy +03001627-f3ece63fb46fb129eb71e9117b10dee6.npy +03636649-4c5a9be10106d239b0957d845ac33749.npy +03467517-10d2c216c70b788485b61f146daff2fb.npy +04401088-9090bc906ec8d80aca54a3214c333cc.npy +02691156-fe0eb72a9fb21dd62b600da24e0965.npy +02691156-325f0b5ace799075bc0909d98a1ff2b4.npy +02933112-79a8b5fdd40e1b1d20768660cf080d12.npy +02843684-2e1fd1d756563937c5c86021644af7b5.npy +03001627-3c4ed9c8f76c7a5ef51f77a6d7299806.npy +03991062-a4762aa34818d514148a76a78b10eb5d.npy +02958343-e915bd270032eb0cafb617f7e8ac7576.npy +02933112-1f822298caef0302143802691fd0e33f.npy +03691459-865356c79a595c3fd3c3c7b74c67a723.npy +04401088-57aa54c9db88e364502122ac3599bb74.npy +04379243-3b45bea7b1b2ab6a20f002682bf71108.npy +04379243-c7e03bba4ab333cfb20716e5484f7807.npy +03624134-13d183a44f143ca8c842482418ab083d.npy +04401088-7f643ee632aa0a3f51ad7743381c8a7d.npy +03001627-2a0e0b51d919f030ad484915511ccff6.npy +03046257-e03d93a19639a6f887a2d41672ab8a52.npy +04530566-e271e4ef2c327dda28d0def75843d7e0.npy +03001627-3a9de2db9d78546892979c651b40698c.npy +02958343-1523402e11400b75becf71e2e014ff6f.npy +04379243-28249c48cb603cb9668ae11a7db5e82a.npy +04379243-d9b264b94aa3aab652f6234a019827aa.npy +04530566-4dc17782858aab6e3308cf743f153e29.npy +03636649-99253484c463e9dd7688e67ac1793ffc.npy +02691156-83ed7c81a011d72a179137acc8d4437.npy +03001627-c7cbed6203120aabe9a3ed4e7aae9cca.npy +04554684-fa4162988208d07a1cc00550ccb8f129.npy +04379243-d382d9e34f365544278d386bfa54545.npy +03991062-c8620917c25de98bcb2a965e75be701c.npy +02691156-8cd5191c587341029aa2a8cabf259b68.npy +04379243-a16d7c49c0899cad8e43a810a63361f0.npy +04379243-f31398b4a1f8562f9297752c3edd590.npy +04256520-b53a3566842e12b290a9ce3e4b15521e.npy +02958343-b22aa9fcad2104a634fad4a395c51fe9.npy +03691459-2c5dde3b43f0b0fc5afcf0aaed5d73d0.npy +04460130-48d4e52fb735e6b6599d77531b1d13a9.npy +04379243-4cd743a60cfa17d6b0a3f25f5d8cb0f8.npy +03046257-d86f29654ad0040114038d588fd1342f.npy +02992529-1d53adf8f82d223db0a79e28606cb167.npy +04379243-2aecf3003735e8b34cbbac005f3700ba.npy +03001627-2bda2aa53c374ca665ba78ad9601cf1b.npy +02924116-7ad09b362de71bfaadcb6d6a1ff60276.npy +03642806-5a63c5f29f0bc0eb12d8efb2f101da03.npy +02828884-9de1b1608e6ffb9afde926512eb9d305.npy +02871439-37c2dc5d7a2c19ecb337d5f45e24e31.npy +02924116-26141fa25522a3b413d4ae6f75318cd3.npy +02808440-a26c4780b14a9d13d84d1b7b18d6e7c7.npy +03211117-d0e4da00e7f9db087bf393182f1ba834.npy +03691459-97bf4aac2d956c1d5d9e9a1d5cade7db.npy +03636649-79815be2cb9b004b1be03639838c9758.npy +02958343-94a78fc51f84fa839ea5c205086e2a63.npy +02828884-26325f047537acd3f155d75bbf62b80.npy +04379243-7216c7ef1edfed4e593ebeeedbff73b.npy +04530566-fbca0e2a510f2b3594daa4565dd30535.npy +02942699-1967344f80da29618d342172201b8d8c.npy +02992529-31a6790b3175d191dca475581a23e66b.npy +04379243-949c26cd898da9855c5e8df5dc8d3d85.npy +04379243-62c6addae5defe8bc62ff677c806df30.npy +02691156-9aa371acc735844efdd77aff53f4b7ba.npy +04530566-9e6d54edea8f2adb41556f795d265590.npy +04256520-fbe08af112773184e6fe3612af521500.npy +04074963-a97a5e1c99e165c2327b86d5194a11a7.npy +03001627-e14803278dcc08c4af7c7ad2549a1b15.npy +03325088-e70d5905fe100117b362845c6edb57fc.npy +03467517-32fed3850b26c82b1c91d5bf986c0423.npy +03001627-3b1f1913f2bc0dc171dbe96559c7bcae.npy +03991062-4706b6fc43ee09358fe24cab2bc152da.npy +03467517-b05152856ba7ceee1e7516298c9158e1.npy +02933112-480a381b676003df4da5feafe6f1c8fc.npy +03325088-4efc45b85110c23276c18e71fd49c4dc.npy +03001627-7ea38c936513f5df3772b104757a4809.npy +03001627-f6f3c3f97b615a19fff16555386d173d.npy +03948459-df2e8011beb752dc44608b3255ca1886.npy +04090263-8d3cc57dc7d9c24ff6099a039722df68.npy +04379243-2147aa5c55a3913c240ea0cdca7b391a.npy +03467517-2be11b43e7a24b4a13dd57bbc3e006f9.npy +04379243-8c7bff49acf7fbc54850c7706670a44c.npy +04256520-4b1598dc0e623eaafd86c4a0427c047f.npy +02958343-e1c7c7fad8802d67fd6539c5080c830b.npy +04379243-9d1485d7d82df9aef4ab13f4b49ac318.npy +02871439-b8166cce2dc8ea4f8c58bec49e6e6862.npy +02691156-697002e0242f331eca8607f540cc62ba.npy +04256520-144cee9408bcdc3ad062f9c4aeccfad2.npy +03085013-5c30c30f543afcec9f695af5ccc7d06f.npy +02691156-715623df7ed5a6fc2296d88107d065f6.npy +03046257-ade988dac6b48a6cf133407de2f7837a.npy +03593526-5543edf23df6527530612f5c0ef21eb8.npy +02958343-fa1b3bcdbda309a439cc19d48e3f4f5.npy +02933112-5d0c82af3d799573eff860318f968925.npy +02880940-3a7737c7bb4a6194f60bf3def77dca62.npy +03636649-994f375a5f371743b5fd9907631a04b7.npy +04090263-c36fa9da71beb581eab5ee569c9de1b1.npy +04379243-7fc2174b2016f76abffa9cc541347f97.npy +03467517-288ac0b24f3ba1a940c20797381ee39f.npy +04090263-c0d928c692fd95b547f0c66d8dcbd422.npy +02958343-4fea9b67188b830f6a2345809e2bb169.npy +04256520-a2d798bef501195c1ecf441429b11ade.npy +04379243-8aa658fb92830e0e62a510b8f97c658e.npy +02808440-63b259b0b462f6f9e59685727bdd9ae9.npy +03691459-36b61e14fedd020a838f7ecc5ce13037.npy +04379243-dd543a069376134aba5342d638d0c267.npy +02958343-5343e944a7753108aa69dfdc5532bb13.npy +04530566-955507bbb3aa0b97b1bb46d2556ba67d.npy +04530566-f2bf8fdce1a33c66a60ce6f0a0028c13.npy +04379243-ecf301eedfbb508dbeedb4c8fd29e2d1.npy +02871439-9b636b7a085ff78a8cbb8bac2032149c.npy +04530566-b2b616535ffca936c9189a1f098bd081.npy +02880940-708fce7ba7d911f3d5b5e7c77f0efc2.npy +04379243-12df0535bb43633abdd9b7a602ec35ec.npy +04401088-31a6790b3175d191dca475581a23e66b.npy +02924116-b7ae96e9df358c315195dd5f75892d01.npy +02818832-218a4d46550ea6fd5a9dc003587438be.npy +02924116-78ae6f2a8b4add0fd110be36252474cf.npy +03001627-b779b6773ef480e8c3cf9ae716575390.npy +03211117-f82e94964e06f23fd6d49cce41472b6e.npy +03691459-767b076382b239a72d563c85edb49108.npy +03046257-a9e4fa90c4e6349ae71cd3b669370f85.npy +03337140-aef1a6861a9b811c7d959b891d79004d.npy +04379243-a54de0e6573dabc0ac42b9d8db52fc14.npy +02958343-219a0021526791d18bb5c0bf5eec83fc.npy +04379243-f60960ae4dc8e293c8ce22a41ea48e48.npy +02808440-5f1145774cb48e7854d7082b34825ef0.npy +04256520-21b8e95a91fe7f044fa89de6e82c448.npy +03001627-70cfdbf8d22c8176f51f77a6d7299806.npy +02876657-cc399bb619ddddf7c13f8623d10d3404.npy +03001627-6b64af50e21c0006f91663a74ccd2338.npy +02933112-4fca24001a151a43d7bd133fd14c164d.npy +02933112-af99a90272d8f5d7776cc3eef7148ace.npy +03001627-dcdb75ba399230bf98f5bccb3529a48d.npy +03593526-4b574003434d2ba041034a9ebee74b0c.npy +04256520-241bf145fb2d14e67ec0186a79b9da3b.npy +04090263-577e1473bbc1e2654fd8f930cee8e385.npy +03211117-b163a1a49784d1b890da575a4a08834.npy +02828884-fa259d97f0514af1814acb3be75bdbcf.npy +03691459-d3817d6003473f1c3971c6f4f1d0a4a0.npy +03001627-46789c1fb150dfaf51f77a6d7299806.npy +04379243-4003c20ffb525c7ee3def9c422df2282.npy +03001627-a54a6ee9263bc1eaf4b6538438a0b930.npy +03691459-bc7a4151d2098374513ea32c8c934a8e.npy +04256520-10e0543e6e316dca30b07c64830a47f3.npy +02958343-de58645e0e00e6be73905da0c7336cf4.npy +03624134-8fbd38aeb89147271edd0225dcc55a58.npy +02691156-b8ed32beb17c3cacafd477f714c68df9.npy +04379243-e3cc0b06be2c972cab610b0c94236463.npy +03636649-8df4dd50d01bb801e9bc18ec03716e83.npy +03001627-68a1f95fed336299f51f77a6d7299806.npy +04090263-7b74f5d8a2ad8aec6ba53cbcffbd8494.npy +04530566-12e012fc28fc8d784de203ef6842ee61.npy +03001627-3dd04235c696c117db6d2ff65cc5b310.npy +03001627-64f885f39752807c6c63b8b48495261a.npy +04256520-14bf301e9548eb788430c9c8b2cd5ae6.npy +02691156-67e8571eceec1ea44c3a35cee92bb95b.npy +03001627-236f75a784ed58d62b3e9b6eb52d35df.npy +02691156-a5d68126acbd43395e9e2656aff7dd5b.npy +02801938-34fd44c46f40044339da77d05979b2.npy +02958343-43319fbb378083669d5b1db3ffcc1210.npy +03928116-6161ea30b60fe86e16a0adac6af4232a.npy +04256520-effe967a116f8098cc2af5791bd669b8.npy +02958343-61abf78387c84ab67bc163a1196fba48.npy +03211117-bfd57bdfa26cea8b5db5515d1151e20c.npy +04330267-9399d12f4ad210cd7c3206b8af68d4f9.npy +02691156-39ce355324ab4bc8b96ae1a0a8b84ec.npy +03001627-808cd961edfc236c11794406b17d66b.npy +03467517-2a3cbbb4242103a9d57700c05b1862d8.npy +04256520-6e0e701ad50f5f8c63a3732f072a64ec.npy +02691156-947a78a898b6aa81f19a675dcc5ca632.npy +03001627-70207d8482c135f8410594e2fa0c101.npy +02691156-8c6ec24418f0af1950e187c1fbdbf3ba.npy +04530566-abbef6c2f909b9719ef9dcee729574d5.npy +04379243-5de144376ad2826329909e9b8d8324a.npy +02958343-4b339f645507508aa83aa2c84a424148.npy +04256520-398ffbc5870c12e1b5c63839abd9baad.npy +03636649-a072cd9c2593414031ae8c8ff1eb3d45.npy +02958343-f2f62db1a9e5823a7aaf6e2fd8453e07.npy +02876657-1e5abf0465d97d826118a17db9de8c0.npy +04530566-83ecbc5daab43647ff790997f2048517.npy +02876657-917fd3e68de79bf69ece21a0b0786a69.npy +04379243-3edf1ef61a9802e6492d9da2668ec34c.npy +02828884-36e1592e13b4f5ed569c11df1aea8ca4.npy +02818832-e91c2df09de0d4b1ed4d676215f46734.npy +02958343-7ee2193b072afa652935bed12a852dcf.npy +03001627-2dc5055b8d900ec7db4b0ee93cf61ed1.npy +02828884-13b28cea086fbf59585a7824ddda249a.npy +02828884-f2a3ac936fcabeb8d1ccbd5d84e5bc86.npy +02924116-9f70c6bc076c1ee09f8b56cd3edf0bc6.npy +04379243-5d46bcc77b2815fca71c812e027f94d9.npy +03691459-8629dacee484080c7ad11885dccb6f43.npy +03001627-881e7a45e9f149d8283b00891f680579.npy +02828884-d2cd3e3cb4ed6ee4e7fbee941d13bb9f.npy +04530566-4bef06fbd04377d4d6e2030b844bcb2.npy +04379243-b10228c0b83a6d436b8cc29ba15869e8.npy +04090263-91729b92eeab3fdb3a653cb492d78488.npy +04379243-ac4761dada79926919bebd2312571a3.npy +03991062-3023f9aa8405195f37ab51e1f8240a33.npy +04379243-4b95230707396e18916c024499b21ce6.npy +04256520-9e63faa55910e20714038d588fd1342f.npy +02958343-56c056544a2fba1614d5081e13f5a1db.npy +04256520-cf4db3515ce7c603cda053036bd1b63f.npy +04379243-2bbafd62a8c5a2d1520ac90ee81efb48.npy +04379243-2cfd6534a6a57548d20545a75c46659d.npy +02924116-3161de3a7b4064ce7d805ac05a89f972.npy +04530566-1117e714368f61ee1fba2cab1ada6bf6.npy +02876657-8309e710832c07f91082f2ea630bf69e.npy +02818832-ac06e06d1d533932d8ab9ec32b20d37a.npy +02933112-72105548b0e01be8659e37b49210f361.npy +04256520-6f98760567bd7f69bd16d4490a10a752.npy +02933112-4fd61ff0aa949a4486d53ab0fe94e911.npy +04530566-2067c22906b79faff877f04737ced5b5.npy +02958343-f2e1db1997b5e2568926f812d9083f89.npy +04530566-8f3d3eb663508afb1143e3955ded9f0a.npy +03001627-7bdc0aaca74cca86593ebeeedbff73b.npy +03337140-bed9025513a46a09bb1a97f41fc4e5e0.npy +04379243-bc9650bb551fc22e1f6014485d7eefc9.npy +02691156-eed299b690be51ffbd931fcaa69140.npy +02818832-fcf45c518cc630c6af372cbaa79ddbc5.npy +02828884-35e62b9c23928bc57f5df2bc47846a54.npy +04256520-642883f79c9131d842c47c8032438a1.npy +04379243-546f5dbed1636d097ee0de88f23eac1d.npy +04379243-ffe2bf44f5d9760b9a8ef44e1d2c5b75.npy +02958343-d4f910cd784c38dc90b4e3bfacd1b5e3.npy +04379243-db32d69c5b2c77ba51b5726fdf67f095.npy +02958343-4f0147c8a158087a4c19dab9f2c7c52d.npy +02924116-699cd83b28bd248d30f646576d932e1a.npy +04256520-d8751c7d4156c98ef09df371fae9d63d.npy +02958343-dc8aef6a8c88997a582e5e3e7771ea25.npy +03001627-9faefdf6814aaa975510d59f3ab1ed64.npy +03691459-2d1302ed4d4f43ca73e1b2d018c0512.npy +03636649-6bb8020fa82b27dde11a3e838aa2c287.npy +03467517-65c02d42310072893ad5c8c907218ae5.npy +02958343-d255a6f670c3ec18d12568d09c2fba02.npy +04530566-fa2580f6b9a29f5454f886603823eb9.npy +02691156-e5c6ba3e7d4f2fde40acb87a6be88b3.npy +03797390-c82b9f1b98f044fc15cf6e5ad80f2da.npy +02871439-850c4cde0bedbe9bba5342d638d0c267.npy +03624134-5391a808f36b46971638241f3ad71c10.npy +02808440-c6dd3b539e5effd61c17aef130ed6213.npy +02828884-d1d433ab6a289a568e95e8a3bb5a538a.npy +02924116-57062cefa79cad6bc6bf3b18b8ca71a.npy +04004475-e7151d72238ef13c2807a549203236ea.npy +03642806-2fbc09c414c80a2d50577cf04f3bf74a.npy +03046257-3bba665dff8dfd6141c01a2987577d0c.npy +02958343-a61488f91b2837f8473f10e6caaeca56.npy +04379243-33bcda05749d01bc4b3c42e318f3affc.npy +02933112-1a9a91aa5e3306ec5938fc2058ab2dbe.npy +02691156-ec4a2a47f601397ea01e5c9f53f20fd4.npy +04379243-8a6e06fbf74e811667d24b304b35bdf4.npy +04379243-29def96b77d4cfe372f9a9353d57f9ef.npy +04379243-f9d5c41dd092dd8e78c10c978f26802f.npy +03691459-6cd4d9c6b51d785bebc9199df8e5ab6.npy +03001627-5e907bb5204ec4a9a16baf954c1d99bc.npy +04256520-9b3c9023e8c570d5b307b2a73ae3e74b.npy +03991062-71082c00e772bc54b79ee87044437bbc.npy +04379243-b6b8ede77085c0a95bea7c29e873d16.npy +04379243-5de75da0a8142dfb17b431cae0dd70ed.npy +02933112-b9967857b0419d44e7312e7851dc468c.npy +03001627-383bac847e38daa0e8dd9b2c07157c63.npy +03636649-90e4219f897af979cbde89e0c48a01bf.npy +02828884-f3a44bf9a27f1446ae23680cee12f145.npy +02958343-844a5b7af9b67510b1bb46d2556ba67d.npy +04256520-3aeae4150fce9f79ed3b18fbf7db0d.npy +03001627-619d9f32db0780187c34f3963ae12156.npy +04090263-b12faa395027a377f7bd077790d66b82.npy +02828884-442283366e5b20c7a136444fdcc3f2b1.npy +03691459-1605c2ea5ce774811e4a701e01e712d1.npy +04401088-77f5498dd2277aacfd71ce99fb45ba0c.npy +04530566-ab9359cafda4fd98a726cf6fcecd0742.npy +04256520-35c611ddda81b9941206ff076758ec85.npy +04401088-1049bf1611874c9cf0c2cf8583536651.npy +04530566-6edd37977522996a9b8e79aa9da22fd7.npy +03691459-a2dc5748b523db72bbbcb091dd094e5f.npy +04090263-e19e9ab7d858842139336f03eb955d2.npy +03636649-6b8790947a71e9a9bc5996932c1238cd.npy +03790512-f8f73c4ee5da94b076ee2dc2a279fa5e.npy +04379243-24a95d1ffe9b8853468a0257ee459475.npy +04379243-f708d5284928431355ce350c1c834503.npy +03001627-2948af0b6a12f1c7ad484915511ccff6.npy +04530566-e12095f9d33eeeb6711722c32e47b894.npy +03761084-42753fd8af1477e019d629b015d21083.npy +03593526-bcf95c3997bf686b4beac2065c0d9cb7.npy +04256520-77f5e753014c5b69b4b4d657a4935834.npy +03593526-f9ae4485b706ab1893fa5ed2239f9b08.npy +04379243-83c24aad3914e61a73376642dd664bfd.npy +03001627-e82fbdd4857adbd7bc0482e18ec51d0e.npy +03001627-2afcb7db7697d552f51f77a6d7299806.npy +04530566-128ab8b74fa037597fe03c0a35dc1886.npy +02958343-47a0e5448c4a3bcbb1bb46d2556ba67d.npy +03001627-79ed181ca18bf71dc8881577d38510.npy +03001627-ce3b2722cdecb0f0b3272b4a93a044ba.npy +04379243-850564e1e8587f35617092ec6e36103f.npy +02876657-a1275bd03ab15100f6dbe3dc17d6cdf7.npy +02958343-bbc4f08aacdff9c7a8ed0bb390c8ebb7.npy +03085013-485b2b3315e2de0698b3a9547b8c6f56.npy +03797390-e71102b6da1d63f3a363b55cbd344baa.npy +02946921-bea7315d4410d0ce83b1cdcee646c9a4.npy +02828884-98971eb747738a6880360680c1602c7d.npy +02691156-78a7cdbbb27dfb21bbf3143b1cb6076a.npy +03691459-431892f5456a2b9ab96497d8dce09d96.npy +03337140-ce57b6b84feef58b4c3aee8e9d3a6ffa.npy +03001627-8d3ea5a8630be8c0f51f77a6d7299806.npy +02958343-fcd90d547fdeb629f200a72c9245aee7.npy +03691459-fae47d104b9111aafd949ebbd292d47.npy +03790512-559b67efe09f141052fa4ad29a1236d7.npy +02691156-e1225308d6c26c862b600da24e0965.npy +03001627-1f0bfd529b33c045b84e887edbdca251.npy +03001627-2b0f0f530011353d15eb60d655e596e9.npy +04530566-df15e931e12c32c38a5d92735846f6c.npy +02958343-5edaef36af2826762bf75f4335c3829b.npy +02828884-1be0e167a93a1069acb4ead41419080a.npy +03325088-42c5ef82f8d7e3b050da8b99982a3057.npy +04090263-84fee75d9736808afa29682ba98e856d.npy +02691156-63f3edb47c67caa29a6e43b878d5b335.npy +02933112-248ff0771f1eb286f51f77a6d7299806.npy +03001627-7a755f08cba6e387ea8f932ecf29385f.npy +03761084-112624e40e96e5654a44340bf227e40.npy +02958343-67e2e5470d27e605d3c820a40c219fa9.npy +04379243-5788395c87b524db79157224cf10b26.npy +04530566-aa83008f44e009177795dd28016933fc.npy +02828884-95b375118d800de7ad5067eac75a07f7.npy +04379243-bfa94cc8557253982efa4e574711a177.npy +03001627-1d37a7fbe0810f963e83b2d32ed5f665.npy +02958343-21b8d0946135481a8772afa45900d07f.npy +02958343-5a56285761f2d6cf261c731730128248.npy +03467517-cc37ee1b4b007f0693f0194265a9746c.npy +04379243-dddacb5f14641b49766aeccb5d872ce4.npy +02958343-cea62d812396c31a88ed7b6315c3b4a.npy +03325088-3f6ac7c3927f9e61f38c4a12750d961b.npy +03001627-5ce323f8499cf60ce51e3cd2b72fbf02.npy +02691156-b3950d8c2c1da884e52afb4158d0847e.npy +04379243-7aaad1c5c2be8c24a9ed7bb5b55809f8.npy +03636649-73378b714c5bfed2b922d818b19db1e.npy +02691156-ee562cc82d73ab212135f3a0e614f115.npy +02818832-6690d593663cd3db81668ccf07209203.npy +04401088-26175bc1827c3569c4b311ecb3af9fe6.npy +03211117-8dd161fa61bb651eaa95bf474e195f02.npy +02808440-ceaf2e69f2c5402ac76194fc117cdc00.npy +02828884-fa2f82cf9275c2078ccde000e771fc1a.npy +04468005-28a465e9c73c5e11e308292e90ed0752.npy +03337140-3711f7ae4f528f7963f393abca61510.npy +04379243-a296a3504163b053e6fe3612af521500.npy +04256520-b403f11f5ea4a6a9d8c9ac981f1e537a.npy +02924116-a9b7fbe4a8dd4d0c44f19502064e0a74.npy +02958343-97128412dfd802be2a9eb0f146e94477.npy +03691459-91a98a5ab36cd751cf99e87135c925d6.npy +04379243-794395f3e5e2d4f617b431cae0dd70ed.npy +02954340-c1436c38beba0005284432ce2f42f498.npy +04379243-5fa362fd2bd9e4b5febad4f49b26ec52.npy +02958343-77e3ac704a2933d0921cb81cb1632a5e.npy +04256520-ee5cfabb3bbf211f4f46734d27ff5aef.npy +03991062-94dc988b968844c944c183864792bc2b.npy +04004475-c3a4c0139cbe53507810fb143767556.npy +04256520-87640cfc9e38bbb3ec563cfb0e79cc4c.npy +04379243-e8bf7ba06998867d653227f952929af5.npy +03636649-a7f071ed220b495d786810c22b062a88.npy +03001627-5eaa2730f10054d0f6cabe1df6f4c9d9.npy +02691156-79d82d0db21dff48aedf20f7099e25c5.npy +03593526-e70b94a9058952643f88f523fa8b6921.npy +04379243-4beaa698e6a7721279a2553310841ae9.npy +03691459-424e95fed6e7fd5c14fdbb071f44a8f.npy +02958343-5a5f53455c2b400579206bf213559607.npy +02958343-6cc0924f1ad64faf8c2e7159929c406f.npy +04530566-78fe059e63f817a296f6c44da3269880.npy +02958343-868af17aaa07b069bda72093f9b5aa73.npy +03691459-c533b4ce486919121cd3f324e5fa80.npy +04379243-85bbafe7db85e0d44c4373a4939914cc.npy +03001627-da918b121ca55feb9b9f2eb77f5e247e.npy +04379243-28e1ba582708bb21b4c161851ed2b4e4.npy +04379243-f597ff7f743d99a3550660cda66234fd.npy +02691156-89bc3fa2ecf1425f6c32d954b1c7f41e.npy +04530566-3e900d7ea70fccaae6100699d3d743a7.npy +02958343-78f9e32385dd7db27996cb12b5662363.npy +04256520-d09b21e5a16c2a0ea29038f04db9492a.npy +03001627-8951c681ee693af213493f4cb10e07b0.npy +02691156-5213a6520cc225a0fb5c1b0f759e2bc1.npy +02958343-a7065cc33270e551a3049d0dcf503cdf.npy +03211117-782655d93313d14726ee873dae10ece7.npy +02958343-1089cbe82dc0e72133d7c9e122eec9b6.npy +03467517-c8b76f91f783d765dae24eae11385498.npy +04379243-7f827b92453712f3504af6e1321617aa.npy +02924116-89a290078b4d987f6f525e79a05bbcb3.npy +02992529-33db5943a8942fdfd998bbb6a9d203d8.npy +02933112-6adbd040ec2f9fb53f07ca1042ba5dfc.npy +03001627-2a39dbeb52262b975babe43b460dfe6e.npy +04379243-249de04d8d7e4061cb9cf5f7d536cddb.npy +03513137-9668f0abd848e943b20f6e48f6a30cbf.npy +04530566-e8b93c451e4278277220891f188bc420.npy +02924116-85fac8cd5ec481ff2b99dcb65afc747.npy +03636649-c226b3469c086c75a1b5ceeca96f6fbc.npy +03001627-43bc4a978115d3f82ff27b24dc18a6e8.npy +03325088-4c1ebf8c47731b573321831d2245cf06.npy +02871439-3cee003b8928f425d810b14a81e12eca.npy +02691156-29374d5ffdb23451e1f2a1daf140ac9f.npy +04379243-731b983cb313634fd018082a1777a5f8.npy +02933112-654c0a2db749c63a56b67b833e192171.npy +04256520-5649e603e8a9b2c295c539fc7d92aba.npy +04530566-bbad61a484ffb3ecf0e4a921fd6a03e7.npy +02933112-cdf33719d80e3f1dadecb2bfe4fe7f60.npy +03467517-2adbf6c3f8f2d9ca7fe36b1f0a632ed8.npy +04530566-58c05eceed8e0a48f3e39f2e17005efc.npy +02958343-476a54545e873ddf6cfecb6c9c824fc6.npy +04401088-25eff75e43287223f1cb19f636b1c2bd.npy +04256520-eeb9c7f343677bc7167c63de52dd6bbd.npy +03001627-3466b6ecd040e252c215f685ba622927.npy +04379243-c0882eb8eb6fba2d8705931e60ead6a0.npy +03636649-cf280956401024fe92225eae846f578f.npy +04530566-1522b8c3c28a9d57ace571be2585c620.npy +03325088-5522e7712d022366c02a95ee51755450.npy +02691156-f34a66147493f0633d5158710d6fb8.npy +03636649-8eee3b5fd2f3abd4bcde6f92ef1f7ee7.npy +04090263-8c769f47d8d5b0c84b681a5f8ea211b6.npy +04530566-a2f46716962afe72b106d5ef46e12c19.npy +04256520-262e433c526d8b4ad84b8ba651dfb8ac.npy +02828884-89d15e96bdf725bfc955e5ed03ef3a2f.npy +04379243-9207224582ee8aebf57b7c8ba41c730e.npy +04379243-375aae9fcedc76438b9b51ae4415d5aa.npy +02992529-18dc34a116734b43bfd324d8acaeb3f2.npy +03467517-9c2dd87f9fa0614466c0cc72d086c581.npy +03636649-dca5ccbc65594b4fcb8d8c6d4df8143.npy +04379243-4702c7f73c64fa81cc19d3672693a8a0.npy +02691156-6a7bcaa4c62779e45e6724a7c6e30991.npy +02871439-efb65556126571c6db6ba5a23e03f3c0.npy +02691156-76811819fc2bf7fbdbe9ce60b93b8bd5.npy +04256520-7d8e6b132c64d909b161f36d4e309050.npy +02691156-54e926e12382808b66cf1b4a8fc3914e.npy +02828884-d27d7e667c5ccd70cb2a965e75be701c.npy +03001627-41fead15a9ade0f090492b0341436fe0.npy +02933112-941289c22ad19099a87002a4eeaf610.npy +03001627-25c61fb5c237767919fb4103277a6b93.npy +04379243-d599b1176343728c6705ae120c2282cf.npy +03001627-9144c2c7b7d9f733ad484915511ccff6.npy +02747177-6d63c096e32feca4f4fb4dee5181bee.npy +02958343-7d33cb52d556c1fe618e9d35559b7aa.npy +02958343-a86ab6f8af60c6afe1d4530f4c6e24.npy +02691156-6cd3028fe03d04fec6f6da58b133bae0.npy +04379243-bae92d56010d241157aaa9693588d48c.npy +04090263-3be7b34984a3e34fde9c2fd0f82cd3a7.npy +04530566-a473fe0a7f11c7ae9041531b90641b86.npy +04256520-cff485b2c98410135dda488a4bbb1e1.npy +03691459-f2e521a8d08e2a2f20363e2561dd589a.npy +03636649-9f2993a2f6cea208d3e2561755f455b9.npy +04401088-142e9e68380daef34eb88be3370bffe7.npy +02691156-e3e6cbc295806a47cf0420e0d05f48de.npy +04379243-548c2b0a10a3f8c798b664231032816.npy +03001627-ebc5bd5566558b64af7c7ad2549a1b15.npy +03211117-50934056d4c1735dc9d02d4e580c2722.npy +02924116-c7139efd6cc730d177b8f563bc1e52ac.npy +03928116-c955fbf41e870dfaf0591fbec6fb99b.npy +03085013-744c65c1a90c7db44f43b0e03c0602c.npy +02933112-25cd31f334358e0260bec33edd014356.npy +04090263-5b1dd450a929e2823b2b25ffabe35ca6.npy +04530566-fdddf0bea9cc33ae81d9d9b1473043a2.npy +02691156-8af730a8f082af9167b9bb226efd81df.npy +04379243-3e30deadc87180b6c3bd24f986301745.npy +04090263-7392b5a3e2ff001f13e4e654fcd57d3a.npy +04379243-268e68f1819a225c1b4b790955c17432.npy +04468005-ba37b06984355766dc14ba0818ee5cec.npy +04379243-c24bc140335164ba815b2b467e8e2eac.npy +03691459-cf85a8c74cb76caf1574d21c0c95092f.npy +03691459-c8e0a46d8a6352c58df4edffcbea21d6.npy +03691459-ab84f70571827b76dfdc04b8b8434e84.npy +02958343-381bf84829066031a134736201a79843.npy +03001627-d915d2f1664bf76e71a70be9f12ce8b0.npy +03001627-2c548222017955df4530ae9f1281950f.npy +02828884-a047cb14c22517e6f33e284fed03c3fc.npy +02933112-aac417d5df45cfd7605de7eae9f0b0f4.npy +04256520-412b9f3244a5cc56b667ca2c169528e2.npy +04379243-ae099c7bf362b3e5c3bd24f986301745.npy +04379243-56ea26c10c478555a31cc7b61ec6561.npy +02958343-d4e611a541a5b01473f10e6caaeca56.npy +03761084-dc5c91c8c01b1c8c506c648223cdabe9.npy +02933112-a9ade7de80ee8cc8ae25f6fe802a8997.npy +03001627-52f6fbe3a36a4d1f19fb4103277a6b93.npy +04090263-95e3e6cb5f3c8cd39eff3cfd975ea4b3.npy +04379243-343b9ae8ea03e45070f79ce36975718f.npy +03001627-b919250f54644e1e326e6d76fa066efd.npy +02958343-5042d8f781a58c4c9be457a8c6fa099b.npy +04379243-45320414e630ca38b96f0049223adf04.npy +04330267-4346f26dfcfd5b9c869bb2e9e5b3d44.npy +03759954-322615cc1d6cedec494399fa6924e986.npy +04256520-6f271a6c941038a6efc579970fcfc006.npy +04379243-e7b76d66231ad077cf004563556ddb36.npy +03046257-f0f2102800fa6493f130e9cdbbb1cf40.npy +04256520-7cb3f49789714865a494798fa117187b.npy +02818832-c7f039115a83939ebbc004a1c4eccc8.npy +02691156-ab0ab979406ed687a8e091cb544689d5.npy +03642806-f14056ee8bbebeecc1b05209f08e5ec6.npy +04256520-837ba605a4ab4a4f19fb4103277a6b93.npy +04379243-b9c756b2ff5d66ddfebad4f49b26ec52.npy +02933112-40470660e2b7a9ad6fa0ab61d9f9d96d.npy +03211117-478dded38f3f8d52934a98c0476fcf4b.npy +03001627-a38cfc9d2003117e19fb4103277a6b93.npy +04530566-e9da320a14afc7098031a892cba81629.npy +02876657-3b0e35ff08f09a85f0d11ae402ef940e.npy +02691156-9baf5b31d70e0d05e98d814cc4d9c5e3.npy +03001627-bd5eb0bfad19c8d9cd431573238602d.npy +04401088-dd996020281c929f73caa5ba625b1f4.npy +03938244-ac2477b9b5d3e6e6c7c8ce3bef5c2aa9.npy +04256520-a7e4616a2a315dfac5ddc26ef5560e77.npy +04379243-7bfd75013a4d7aeb5ba41eea807f5d3c.npy +04401088-8e3e1213e47661506457f8736d1c9e5d.npy +03001627-9027cd82cdc7da4d2541c4d6fdd1e35f.npy +04004475-75e53b4107a95368a3c3591ebf6e2911.npy +04379243-f7c7e05da64f6e4f2aa0f30a1572c50.npy +03001627-6b74546be8d42c76b035d20a1a3ca345.npy +02924116-5beb6cffe93635bd973f659238edf3c3.npy +03642806-464edfe14e9fa45c3394926146371698.npy +02958343-58a0216bf4c8c91d3d2b2fcaf6a55d04.npy +02691156-fbee89bee5338798d4837a4534bf020b.npy +03624134-eaffd07694c11b20afc61ad0921c25e.npy +02958343-82a783a1ea4e34b8d7755e7baabe8a6f.npy +03001627-77c4867b42d73d9bf24f05137699edbe.npy +03001627-ea3723766e96331ff91663a74ccd2338.npy +03325088-a8d7a9795934772d3321831d2245cf06.npy +03991062-12282e4fb29632286bd4d8addc5eb335.npy +03790512-733b75e867591d0fb37378f3c85478b4.npy +03325088-ac026fa4c69669a25b036534f28c2db.npy +04401088-33cd4232a87e1f416a1f7081746396ba.npy +02828884-8d218bceb517f272f155d75bbf62b80.npy +04090263-61008422050513d987bbc659fe543122.npy +02958343-cf32af5869fee4d34eb766e5a46fceab.npy +04530566-33e3b187089a68d3f983f6a1267b9260.npy +03642806-1c035fa183863780e605719767a1e7c1.npy +02876657-5277b4491396a522333769b054e66b40.npy +04379243-c8aaf90c4e66e235b9c440034ab48a1e.npy +03642806-dbcd5a88a9d4f1d7579cfe4420588034.npy +02871439-31368c56e8779b7951c1fffab4f5807.npy +03001627-25871aa50531fbfc741e88434245c899.npy +02992529-1984fb95afb6dae5804722305621f918.npy +04379243-169a72252808f9d12a7ec74a9a907cb3.npy +04530566-40d4cf2e4c0042b81f6b8c144863b7d.npy +03636649-e93f10a58e0da99bb2920cf5c60c4da3.npy +03001627-3171bae36693716126e4d5b5a8cad4da.npy +02958343-3804a264b503d5812e40b8f7ac380eb5.npy +02958343-f296f3a83e09de75afe1d4530f4c6e24.npy +03467517-b620027321650495b266a77a6097101f.npy +03636649-1682d4404196cf127588e2ca59b15f8.npy +03691459-b3f5d033d3fed8e9d207241113bee327.npy +04090263-c578ba526b8ef653e28e3d2f13cad462.npy +03001627-1820138eca42749262e4024c69de065d.npy +03467517-d82fc6db200cdf6ea24eeca91f583600.npy +02933112-7b927d55b634c4aa178e7d331e641179.npy +03636649-44d1dac026839e25f690049a092c5efc.npy +02933112-b28d1c49cfe93a3f79368d1198f406e7.npy +04074963-468a110ac6ede4507d11f9fcb943bcf5.npy +03001627-37475326277845dc1fefdc190019db13.npy +04379243-88670667d9fcd992eadc9f074ecd1df1.npy +04379243-8ac67043fbc976138705931e60ead6a0.npy +03636649-e78c5337a56dca56bd6e55f88e701c4.npy +04379243-b4e356d1702c4ca2febad4f49b26ec52.npy +02933112-4417497ef6af4cad74555f58f0503de3.npy +03337140-43e8231e5f75409e2a78b8689a653105.npy +02871439-d9e0fd4ed360b3abd67579ede6e465d2.npy +04256520-59056471bc89a215b3fdb1a7c9a60207.npy +02933112-198cbe57b01bad9dc59350d819542ec7.npy +04256520-592ad41d80d018a2d614b159c22611b5.npy +04530566-ae1a4397815849a682b5804533e545b1.npy +03001627-3936ef166d22e60ff7628281ecb18112.npy +03001627-5e2d7d43431eea85364b7ec2e28b3bd.npy +04379243-17e171f6714e330d869e5ec10662e58e.npy +03636649-3ac0f4d87162625dfcb8d8c6d4df8143.npy +04379243-16fa03bfc61770652c5d34a902e568f9.npy +03001627-9ce2ea550b049beee64d5cb52244df5.npy +02691156-20bf5bba045e5a53fdd77aff53f4b7ba.npy +04530566-8e0e3c0c19d38ea1696cc0dd628edec7.npy +02828884-6e683e60075bff408f98ac7ca14e08ed.npy +04379243-4b3d009920bd7ff51f5bdd219902caa1.npy +03691459-b0f6ee90a22dda571711eb7e23a7e2b.npy +02958343-a720d17573022d9ac00fd1150223027.npy +04256520-ff143cdc22f23608cbde89e0c48a01bf.npy +03691459-703dbbf27ae78991a21971bc32fb0326.npy +04530566-83122dd93e3f42c08099d0cb75c1d1e1.npy +02942699-90198c0aaf0156ce764e2db342c0e628.npy +03513137-608f7c4d52bbfeec9f00d9b3defbf21d.npy +04256520-58663919dae316f31ea2c93416c12215.npy +04379243-927bf59af25793ab76e29c9c43bc7aa.npy +03636649-526251a7530426a4b3c42e318f3affc.npy +03001627-dfe0e22865575c43cda85f6a3e19b0a1.npy +03761084-19362facbca806df178e7d331e641179.npy +04379243-5f8baa8b2f5c37f3124c962aae03701.npy +04530566-4af786ed4226705279863338881ed398.npy +03211117-4116b08cd0e4e19ff799a4672edb216b.npy +04530566-223d2316bb8b74a979170a5f8beda902.npy +03467517-5c7b3940e988e7e33af041adca0b9ca3.npy +03636649-435600f37bac6ed9a28fe47978e866bb.npy +03593526-7e4eb671672af422276206fae5d3c473.npy +04401088-c771a9b2dc439adac38a7eff5af707a2.npy +02691156-2c77ff96a9b46996b963df94d2f21069.npy +03001627-bee929929700e99fad8a0ee9b106700e.npy +02691156-52185f504ffa9b32ca8607f540cc62ba.npy +02958343-c7ce82b4b1e795b0cfd826dd468a5497.npy +02691156-b0fb094d1f0fc2a6766c6046535346e7.npy +03691459-cb3bc7b6610acb7d7f38a9bfed62447a.npy +04379243-2368a815da89faf940b559ef47048b86.npy +04379243-d58af24ca497ba8c4b3c42e318f3affc.npy +02924116-62e11d7b19c4c15aefe4e52d7a765fe5.npy +03001627-b091984264b4600f3ba7aee980c3a0ca.npy +04379243-9cdb0315eda9e8cf9f2c21e46768be21.npy +04379243-be00704e7366ec2ceb1488c2b7631b3e.npy +04256520-a5274620fb2ba9a23862dad076579451.npy +02880940-1b4d7803a3298f8477bdcb8816a3fac9.npy +03001627-893c689b192bbe33ebadcdfba7971b71.npy +02691156-ac06ebedebe86a7b4c3a35cee92bb95b.npy +03797390-ea95f7b57ff1573b9469314c979caef4.npy +02808440-67855525b642d59344221bef0fa3c36b.npy +02691156-6dccca8485094190be13ce34aa7c0c1c.npy +02691156-1c4b8662938adf41da2b0f839aba40f9.npy +04401088-98b929df60f9ffab49f9ea699d984c9f.npy +04530566-8f2eb4f44b95da78639e286420a03c3f.npy +04090263-a982e9bcf097e0e595ff232cd38210b4.npy +03467517-fca53c92b6e4b3a1107cf6d75b4a137d.npy +04256520-2f0f7c2f9e3b04a8f251828d7c328331.npy +03948459-592017db407391c68e7e947594effe19.npy +03001627-67713c9a313ece7226f51cb1aef0ea9c.npy +04379243-dba5223072bb092f76ff40a3c0e00e06.npy +03691459-b6f154678c06f537db24fbbf172c2159.npy +02924116-953520d61781e569d26ea7e8aaac5b9a.npy +02958343-9650fa63c6ec14fd80700cbc107b6f7d.npy +03001627-fb0c9739b5bd880ec15f2f972dbc5c17.npy +04379243-ccb8c52ff9e7a01819fb4103277a6b93.npy +04256520-fe3d9267a166c57fee7d178666aae23d.npy +02828884-b20fb19d75c00c9aad5067eac75a07f7.npy +03001627-6ddc64415a10f4b7debe318339eaf996.npy +04379243-195a2ed4931241d3c3bd24f986301745.npy +04379243-9cce8b636c333950eb98f4ac131ee005.npy +04530566-e86aed19f3272118e8340a4561cb4030.npy +03001627-3a0e392db610f1a1504d5af97121b5f.npy +02958343-fd50bc89fc1c1cfb7041f1c5e7744b16.npy +04379243-519ff6f082f8c41692f109aef7d7d6fa.npy +04379243-7c7c705c9f3b0ced3002761e7a3ba3bd.npy +03001627-74ae50b70108ca1118775c05a821f9ab.npy +02933112-8fd43ffcc981f6eb14038d588fd1342f.npy +03085013-3bd591ccdf575c261a6765dcfddfd63.npy +04379243-5431993203dfcf797ec12e029bc725db.npy +02828884-23ce36288382e8285710c881d369ccb3.npy +03642806-93fcc135217fdaf5c9614070d3269898.npy +04256520-36d43bd7a4f90e69e2ca61e91f2755b7.npy +04256520-d0dd5aeb1384125bd0cd98de57e6803.npy +02958343-5f32aca282eb9167ff1370452e3a0154.npy +03001627-512905c0211b947edc6f96c9bb9e3ae6.npy +04379243-e490518bf6d40e138288267d39a90f5.npy +02942699-cd5fd9a2bd6792ad318e2f26ee2da02c.npy +02933112-5523a90c230a1d0699bf8547ee35d38a.npy +04379243-58b58d56e5bb2faa16fafea97f025a07.npy +02933112-6ba512e07979da6ba3f4b1457e62c2b2.npy +03001627-30cd71fcd7616421177b96a1e00762c3.npy +03636649-e86bed66672425464492223278b0e937.npy +02808440-fca2b158f36e31559ce9562d3c10079.npy +03001627-89018ce4961c76cd5a8ae8f7c307d01c.npy +04530566-1b2e790b7c57fc5d2a08194fd3f4120d.npy +04256520-beb7e6c36552f509de008fce66fdc56a.npy +02958343-e4b1de221f2d66352638397725e10cf9.npy +02924116-48709357d52fb59bceeb72b524f3e0ca.npy +02958343-ae1c1141ce4bfde9d66a73de5847ea37.npy +02933112-9e6434ba1ad59fa611fc2b865c2a185b.npy +04554684-8ba3bb4e5f54bc15eb2160f94b208571.npy +04379243-a6c888f2d78e83075936c7265c890fef.npy +04379243-5f66c21e40105601958cd9a7e5831839.npy +02691156-7c6a2879e359f505467f6b8c6b1d352f.npy +04401088-7757585cdde7953d86ecff2582325794.npy +03593526-1168c9e9db2c1c5066639e628d6519b6.npy +02691156-84a167f743ec4f4de6f558e7f4a68d3.npy +03636649-80ced01703281d8e87de7314a5215f9d.npy +02958343-f48dcef252683ce552aa494042b7c9db.npy +02933112-8094a6efa5efa16776d812857a5be1ce.npy +04379243-187f32df6f393d18490ad276cd2af3a4.npy +03001627-6d27c80c3da530d69b11da89c22111dd.npy +02958343-a421aeec78440e40d3a3ff116860ca63.npy +02871439-ee23cf56cd1dfb7ab74a28862e11b00b.npy +04379243-5fbb7a5f01f646ca5830980abc1c717a.npy +02958343-5621ebf65ffd38468772afa45900d07f.npy +03001627-4fd20c1142b642221403e6cccbe91852.npy +04256520-79df431936df0a0719fb4103277a6b93.npy +02946921-9b1f0ddd23357e01a81ec39fd9664e9b.npy +03948459-621502aa0a01864d20ded1536778b0f.npy +02924116-aed84b7e25d3de71d7cd73ccf58d1f8.npy +03001627-40ab45735f526717e25492f5f62d416f.npy +02933112-818043d8e0cc040cc59350d819542ec7.npy +03691459-22fdef9bef225163d747b49524a1246e.npy +03001627-db86d16a95437f3898cfd47a860803c5.npy +03211117-99c0bf1f81b835129857176349e96f9a.npy +03928116-8a6429797237165e63920080bd2c2ed3.npy +02808440-13cd234acf0a6b4db362845c6edb57fc.npy +04256520-875c7185cce6b8b0813204830fbed813.npy +04090263-3fccb4301ce84fbc276c3d558130f8b4.npy +02691156-6c931227c1735c329df8dd4a2554378c.npy +03211117-4476577ff4776f5fa3ca88ef9e9610f4.npy +02924116-f44b45c031a02818464bb8192aeeef4d.npy +03001627-592cf5363737550cedee0bb2b729f22b.npy +03001627-3774a2b8c71e70b9f18a36d57b7cced0.npy +02691156-6dedeb5b87ee318b2154ead1f7ab03aa.npy +03636649-c1b939cc403a0662664b3b9b23ddfcbc.npy +04401088-b4c1d8191707ead52e10692b3b33e38.npy +04090263-94a58b162f17f908ecbf498fbf7a2384.npy +03001627-e7be08b34dacaafc405e3e2b789a211c.npy +03991062-cf184ee375cf827eeee0d5e82f0b9cab.npy +04379243-fb0459ca3947e2fecf5d00de99803a2b.npy +03928116-b0e9391ecbf7334c4383822c87ad59db.npy +03991062-141de0993dd1f2f24efc7e7114f1b9c5.npy +02691156-28add8a00a7bcb7318d508b491dafd46.npy +02946921-17ef524ca4e382dd9d2ad28276314523.npy +03325088-941633c3da8099dc76c18e71fd49c4dc.npy +02876657-8099b9d546231dd27b9c6deef486a7d8.npy +04379243-4d484d20a59a18d3fa6df2d54fa43ce.npy +04379243-29207ae4e01c415894fc399eb2c2f348.npy +04004475-f5aee7d7732eab9bd477567e8c8a6c59.npy +03325088-b7bbe0ef4893621414b35a7d7cea7130.npy +02958343-58773b5aebc3361793680c5a9a367b4a.npy +02992529-1b1aaa9a95ae964746becd46a4907f38.npy +03636649-70bf2aaedbf9499ec889c00efdaf9928.npy +03211117-f240248beae8d20661049a5d9182333f.npy +04379243-55aea0b2f76b3f7819592f8d1b2d193.npy +04401088-96700b47eb9bf33889a1b8cd5b44ae5e.npy +04468005-91bb88fbda95ab44e8784f880dac0f61.npy +03085013-8bbe84f243cad940f0ce652372f56eef.npy +04379243-8222dcc1680112635cc877f4f71ba410.npy +03001627-305589c1e37f32b821bdbc0445d9f748.npy +02691156-a50b4b0ac82a67d0bbb9a486df472172.npy +04090263-6536ba618390e1688e4cfca4542c1342.npy +04379243-6e0fed54fcae8a62edccc47bf0dcf5d3.npy +02946921-5c326273d61272ad4b6e06cda31f9bc6.npy +02933112-4cbb978cef36a5b9c60fe2650bbe2bf8.npy +04379243-8d0d7787f4babee7e66285d36ebb986.npy +03337140-2b2b84efa6e6b42ace5d6e9371bb5c33.npy +04530566-72f4c3c433492d585001cb19c4a0eee4.npy +04530566-476bc79bd6fec6b088f5c2d4f2395a95.npy +03691459-80109bf3b6904d577edd21390c628646.npy +03636649-1562318ff0c62163a488756a9c41f7e.npy +04379243-8383a9cf1380405dd9006da2b93c0a4.npy +03211117-df624231ef05b83d54c7ab6aa5674ccc.npy +03046257-f1ee996e8efb941ad8912880b776dcf.npy +03001627-88382b877be91b2a572f8e1c1caad99e.npy +04256520-a6ee2e98e8ae755f37af16b2893f1d4.npy +04379243-c45fe6d9f2c516997062f2d72cde5c95.npy +02876657-204c2b0a5e0a0ac3efd4121045846f28.npy +03691459-fe4ed2d72cc79c74b59e9758ae7f41a7.npy +03001627-5fa5f75741e94598e6fe3612af521500.npy +03593526-b0f75a497a309499816c17dd8398ee0f.npy +03691459-87e2d9c72eeb8c49f398d0c5832df00e.npy +03636649-1d2c2f3f398fe0ede6597d391ab6fcc1.npy +04379243-5275e0ee91ab4e755d009c98a5b96836.npy +02808440-10caa8d340fa0fddfcd4910413c446d9.npy +02924116-9986dd19b2c459152470de2774d6099.npy +03001627-3c3b33293af7459f2677042d71d00b91.npy +02876657-3ba7dd61736e7a96270c0e719fe4ed97.npy +02828884-90a8b80aa2fa209ca936e2693dce34b6.npy +04530566-98da594a65640370c8333f6c4d99e2c8.npy +04090263-efd09f6901b098e4eab5ee569c9de1b1.npy +03325088-bc30d9336c644592ff2c92c2a4f65876.npy +04256520-9e0feaee4da30fe7fa038765e58dd68.npy +02958343-e24f388736f4e6fd2cdd250493632937.npy +02808440-148ec8030e52671d44221bef0fa3c36b.npy +02924116-c5f11b1e82bf6b1d9aff919557ab16d.npy +02828884-78243d42e55bf254d47bd31d526e1987.npy +02958343-6eba2ec65e8e44ed5545896d1a9ff5d3.npy +02691156-b509fbbe99df854f0478431b5ad57db.npy +03797390-89bd0dff1b386ebed6b30d74fff98ffd.npy +02933112-34bc619e8ab3c0d2a93db6e4c0c75191.npy +03001627-59c89dc89cf0d34e597976c675750537.npy +03636649-b6f69dd63be9146d14f1e0019ad6a8a8.npy +02933112-c2ac91973d449b18738e43095496b061.npy +03001627-e0badcef3c110ec6c4963b39d8846214.npy +02958343-6c339c89246fe6a651db49e653372c20.npy +03001627-3020942d1547cf562056b4bd5d870b47.npy +03001627-4030ea84b560b857febad4f49b26ec52.npy +04090263-b69973526e91e3bd68407c8bfa49d3c7.npy +03001627-f215c608fe63e97d4aada2bcdc05aa43.npy +03948459-1e93ef2704131b52e111721a37269b0f.npy +02933112-3c6b1e5888e5fabd9463d0e381798ed8.npy +03790512-8b2e7ae8b0f0d451d97964d17de80d2c.npy +03046257-48ed307c035fe99e49c212147ab9c105.npy +02691156-94351a82955a6136c3f40f6a57084ffb.npy +03001627-3684490885c259e688235335f9e630b0.npy +02933112-3483076cc008fff0d9826d0ff198257e.npy +04379243-8ec96360a8674db5b000f20a5153622c.npy +04256520-3425e406f20e69efddfee72cbd7395cd.npy +03467517-3a520944e6265920aff103adc6dea0b0.npy +03691459-7628ba96cc90fb4df256a8c3e3396495.npy +04090263-74b95139078ce0dfacc2abd6f796df4d.npy +03001627-661fcd8f87d948f2fff16555386d173d.npy +02828884-9fd13f28f9260e65ad5067eac75a07f7.npy +03001627-209994649e7fdf052ff84f70e18e9c53.npy +03593526-c5beb87c12986f859f3323e6dbd51308.npy +03001627-5bd3e7c9695af73cc8687ff9b0b4e4ac.npy +04256520-5660a383172900a6593ebeeedbff73b.npy +04090263-73cfed37f9da046de2bb19fbad3e4596.npy +03001627-50e3f09b7dc9fcb63fde2470c949bc26.npy +03513137-adf9b0eaf3a1980187710597b0363fe6.npy +03001627-4f7523a3d276bfae4b3c42e318f3affc.npy +04530566-bc09ba292bd9e684610faa04834ad4e6.npy +02808440-b14791a6df68c09fde250725ad622108.npy +03001627-22bee1d9c6357b295493ccf8f26ab2c.npy +02992529-ce62e8c8a75a501535c433f6b651ec89.npy +04090263-64021a29f7245e0fefdff89bf9a96890.npy +04256520-50c1477484688492bbc7a6acbd8f058b.npy +04379243-575a8eca414c69f67bcb070cc655f13a.npy +02924116-b0780e992d557b7a3a142219f8bbebaa.npy +04090263-f172b2748cdd7027d234b3cff759c4bf.npy +02958343-35d8d94bdd379556a37f3fc191551700.npy +04256520-57f5a7660b1f186e14038d588fd1342f.npy +03001627-e19214cabca496a3f7b54e04c7238d7.npy +03325088-22d924ecfa024cc9c36fb70296e45483.npy +04090263-294c7c64f92d3b5537c107a0a05e0226.npy +03046257-15a5bb8c387dc7ac87ad02d88bbf4aae.npy +03001627-31dacef35c2d68cd7d5059679be663cd.npy +04090263-1196978aaae2ab55537a44a51980defe.npy +02691156-14d9c576d06622198f52dc705c3109b9.npy +03691459-9a859f2668f727abf6da3fc8db3c804.npy +03325088-5d7475a12087aba3176bf371ba7a6ff.npy +02691156-47a4ed133dd37264521546825315c695.npy +04468005-3c291cef4c82a608cea8d0e97d819254.npy +03001627-3c3f70971f203c4d6ba836372832f055.npy +03593526-ac3fa82107f01502cba92cca5bb025de.npy +03624134-3dc5a6d79ed591bda709dec9a148b2fe.npy +03001627-972355f42223e6199cd431573238602d.npy +02828884-26b3257b2e094083af9ff91a3a02b5aa.npy +02958343-ffbf897d9867fadff9a62a8acc9e8cfe.npy +03642806-1be64c0aded473d38ca8637757ac3f67.npy +04379243-812dd06fc99f174e9f2349486c570dd4.npy +03211117-9c8a2e3431b0b2dda2cc48a1579329e.npy +04256520-ace4472862ff3f6d917b96045c9b6dea.npy +03001627-c236deaff8c6fb0d29c9a7a92b0a566d.npy +04379243-affb5a80f11b383e1c25d54737ed5c8e.npy +02958343-a72134cd499fd1c4f79e091fa09130a.npy +03001627-1bf710535121b17cf453cc5da9731a22.npy +02808440-a9827a6ad29326ea14c8ee9aa2f8e72d.npy +03467517-1abe78447898821e93f0194265a9746c.npy +03991062-d8feb207fb33eadbfcd4910413c446d9.npy +02691156-e954dc13308e6756308fc4195afc19d3.npy +03691459-ea1b716cdf033bc4bb844bb01fa51c1f.npy +02828884-a001663b61ea6accf4fb4dee5181bee.npy +02691156-b7b8ffe2f07e4eff95dfd5eb5f06d19.npy +02958343-f882454f6fe1c5bcc0e3666c7d0ec7d0.npy +02828884-d5ef0f9bb990ffb3b2725423c902ba5d.npy +03691459-b2ae90026d7979d8267014f0fe84b7ec.npy +02954340-14df58bdedfbb41141edb96d309c9a23.npy +02828884-51d51b67faf16d3d2ea98d69e91ba870.npy +02828884-3feb79684658db043efeb398bf800e80.npy +03211117-46609dafc47fdf2b74b687cfa539ab78.npy +02871439-82b55e511522a942aed93548190eee8.npy +04530566-50c0bd9933f7259fe59358c5e6239c84.npy +02828884-e5af69132cc95133f155d75bbf62b80.npy +04379243-707b9fa6a564ba0e425fe98d8cc1c2c.npy +03797390-a0c78f254b037f88933dc172307a6bb9.npy +02876657-640835881dd33a2d30354e87bd14ec69.npy +04256520-954efb8e36610d1bab610b0c94236463.npy +04379243-28de11ca3a3bfc00acbc34d1ed23b6a.npy +03001627-faef9e4cff5fa61987be36ce60737655.npy +02808440-bf8e5bbe0e0938d98afd316e82119b42.npy +04401088-2caa10c91355efe6ae2545602370c249.npy +02808440-6328094d59f1221d7b57eb4fc830f67b.npy +04379243-482a76d14781e55e25374da32e705c.npy +02828884-ab1c843def8b843bed98cca8f0ccd5f7.npy +04256520-bade4726190d638498614b18e654375c.npy +04379243-c57e4f64b18e9b9aa320e34dad7c78bd.npy +03691459-7b8aedba3024ed389e87d2bdcb41f548.npy +04090263-8fc390879ead5efea0834a5219dec81f.npy +04256520-c6f1601208aa5e72cde6b082a301e49c.npy +03001627-ff14d078e2f0f8c65242f8291aafac22.npy +03636649-ba05811f301cdd791735ea0e092a805a.npy +02691156-bd066f14adf6c0a9f6639976815d96b.npy +02828884-fa4d4e697d21ec65512d71be7dbf2d60.npy +04401088-4b97582ec707108c6ace02f573c40387.npy +02828884-41120a43b6b7c93210399d5a44e67cb5.npy +02958343-66828747e0e7671021c7b87f47c77e12.npy +04379243-ece476ee957a099f5c5fd2c2f381b61.npy +02747177-90ad7e8c047b2dbe4c86b1fdc94892eb.npy +02958343-5b1c430ced749ac3897e805df74453bf.npy +03001627-97bbc8970b05c4a3fcde6bcb709edd9a.npy +03001627-908de4d82bfb422ec43a4855019be9b5.npy +04379243-faeebcbc4798714188b4ba3feb03ba8c.npy +02691156-dad83c903379cb9cfa585c96250561a9.npy +04256520-51f11001548cc8c0febad4f49b26ec52.npy +03211117-7f489cfe5174ea20c29a46091cf24cad.npy +02924116-886e97687dacbfef4fb1d9a9b8854179.npy +03513137-5f0fab98fec5f53bfac6099f3d4830fe.npy +02924116-9482cb79520f1f0dd75a864e79808b6d.npy +04225987-39c8a4798087be3e20d56eaf7c8da531.npy +04530566-edb4574369f95b50689cbb453f479f9f.npy +04090263-3efa6bed63249f928bd9de6b28931bb0.npy +03001627-68f1d9f63eae2b5123c1b1df1d480bd3.npy +03001627-107ed94869ed6f1be13496cd332ce78f.npy +02880940-ee3b4a98683feab4633d74df68189e22.npy +02958343-4e384de22a760ef72e877e82c90c24d.npy +02818832-66eff63edb4f5b4caf5b95a62b058b0.npy +02933112-1676f8b995b976e5824662341ce2b233.npy +04330267-de4301a3ac6e17e9843f813f752a5e35.npy +03467517-d4b021a085d836dd2b996d5d44e09408.npy +02691156-bb7c6c397143f72fe0cfe7507a46f0c.npy +04468005-d8a75faede3de91de75a0b04a57744.npy +03001627-55d147c5125f5043e1ddfae8bbce5fe6.npy +03001627-219c603c479be977d5e0096fb2d3266a.npy +04090263-cb5e01162787772ff7bd077790d66b82.npy +04554684-b0b77a2d6816230c99bb3947ecdf7d2b.npy +03001627-4a45de600363af6bd5cba62773b8025b.npy +04379243-375972fee9a2a6e28d2d730aebe7865d.npy +02933112-4205bc230382f663c59350d819542ec7.npy +02958343-26bc52b1307fca053e5ddfb0ef6345db.npy +02958343-d10226fc9aee707972a38ac2b8f5cd48.npy +02818832-fda18f335dde3c6898ee36f046181d28.npy +03325088-f6666b97498b17853321831d2245cf06.npy +02958343-a7f8cb46717528edace5721ccacba16.npy +03691459-fa6e17f7f928e8a44b2f94f4017fbbbb.npy +04379243-634fece55dc20d232a978d3a5b04bbfd.npy +04379243-2bac94c17bb341d84ab0e621f58e2d20.npy +03001627-a50b78207ec2256168d1b9a1d97e2846.npy +02958343-1b5b5a43e0281030b96212c8f6cd06e.npy +03001627-8f217a409c5407ade6fe3612af521500.npy +04379243-bd2949103a92dd56d3dad974dc098fa1.npy +02691156-9f9cc77c5e32664e6a8a5e39588ebf68.npy +03790512-89c948e75d1c5cde27e168bcc3c092cb.npy +04256520-43507f90235fd3214038d588fd1342f.npy +02924116-1bc9264f1c92b69752470de2774d6099.npy +03001627-b233a919f5d2f6ac2ad490d4d7fae486.npy +03467517-2ad699d80ae93ae793f0194265a9746c.npy +02808440-86880c061d80ebab3956bf2322987dd4.npy +03001627-fa041b0276dcaaaf98e0d1738edd4f19.npy +03691459-52ffd6fe29e51364b21928f7573b58cb.npy +03948459-ac88c6856c21ab422a79dd7a0c99f28d.npy +04530566-a6571d7e2c8f6113b05dfc874f00d5f3.npy +02828884-a857f9d4838b885f2056b4bd5d870b47.npy +02933112-a09130501c18c324404449202e2d8881.npy +04379243-504d908a55f3e0c764810cc21086da42.npy +03001627-2bd6800d64c01d677721fafb59ea099.npy +02828884-5b5d3f675f8d0bfdd2b12aa6a0f050b3.npy +04379243-3372c6b94fc719b9a75d03186a0409e2.npy +02958343-99cc91ea3f0b646be79303516c6edeef.npy +03001627-a89450b61d786e4d115013480320769f.npy +02958343-a495bebb2ebd72f3dd7cb6e3ad90d3ea.npy +03001627-78cf0ebb875de8dfba18ade30e563d37.npy +02691156-f5a667f5796b9a0b9a6e43b878d5b335.npy +03211117-f5b05e9eedcbaf9cf4d1910799b338b7.npy +03001627-8999368504d4374ce4e346ee2650d150.npy +04090263-5d2c6ca737f9accf683e3750b53385d5.npy +02691156-3fa5f65a92a5e521d87c63d8b3018b58.npy +03001627-13076ebf8b5cc457b8d6f69a14683de3.npy +02933112-9ffdd44e709142551b4e9ccf27cd840d.npy +03001627-5019265bd6215c9ed54fd46ccb781717.npy +04256520-1ee15a07c2845ab1b9f43426f477bd71.npy +03046257-223a78dd9e6999e67c0ca8d7a07be3be.npy +03001627-3895b96949fd81c5f07fee5fc5c45ee2.npy +04256520-57094371244c13fbe4ee93147efa8cb1.npy +03636649-b6953f683e8b3feb9571d807bcd25673.npy +03636649-9a244723bfef786294cdfc338037bd95.npy +03513137-ddc07c47962fe10f61f42fcc6613af2d.npy +02691156-cf0cdaa94220ee3f4c3a35cee92bb95b.npy +02871439-e3ae56f176b77359aa1bd50387389420.npy +03636649-eb311e6232cb7011bb5bd941c6665c21.npy +04530566-2d136ffca92d9c4e3639e751e7f78cf0.npy +02924116-60a6ad222bb446721bdb28bea09e3a92.npy +03001627-904ddb7762488b1b5dc3653f8341633a.npy +02691156-e110c699f2ed6511b53a02c8ab03ad65.npy +03001627-e9ccf4cc84c085f8c785f06f424b9d06.npy +03642806-a7f983f1d0642745135a402b573354e4.npy +03001627-c20a354161c28f6ed4da89766e80607a.npy +03046257-a14d909e62adb668661782af60b711.npy +04090263-5fde8eee79ab6885f0c705d37665dc32.npy +02958343-42ca4f6a7d7a39712a9eb0f146e94477.npy +04379243-2575d3108a55adfaba0351028b825931.npy +03948459-8fa02aab7237289667fdfbdf64f19325.npy +03636649-4cda1ff0899a6fd5f58da08b07a975ff.npy +03790512-a54e8fb64e5879161253ed5a61502f52.npy +04256520-93676b6ecba89ebb38449598167b268b.npy +03001627-ed108ed496777cf6490ad276cd2af3a4.npy +04256520-dc62af0b1d8af2c676e9713f57a5fcb6.npy +02933112-5893f6c94b15ba204f3443b22038d340.npy +04379243-83cf3765597a631e4ef113421a70a46.npy +03046257-44a961d1870b2279626620faac40b883.npy +03636649-aa765d04e997e36a1742918a871fc8cf.npy +04379243-b14270faa0beb387f36ea1eb6542fe7e.npy +04401088-cc6c216e25469966bf14f57b214697e5.npy +02871439-3bff6c7c4ab1e47e2a9a1691b6f98331.npy +03467517-e59ccf98ad868a758b1a3513f58ebc5c.npy +04379243-53b1f1781eb6339f5f4be3ad507aab92.npy +04401088-3035c3d7d7eef1fc952c851f81463faa.npy +02691156-7addd02b1c255edcc863ab010b80d9ed.npy +02871439-c3f572493adf0af810b7af17eb4b15c9.npy +04256520-511d9b4ffb8ad21485b479b317175b55.npy +03636649-627ed898c49543594c64af119029e57c.npy +04401088-1c87049d11292c5d21e2fbffea258ad5.npy +03261776-ca1c1c9aba8f4491a656de49935d2359.npy +03001627-92c068abecb15e1adcfd6ca2b952d624.npy +03691459-782655d93313d14726ee873dae10ece7.npy +04090263-164fc79c2ecf843bc8e292146f3d4d52.npy +02880940-45603bffc6a2866b5d1ac0d5489f7d84.npy +03467517-7946e354e342f560c5a468097fc791e4.npy +03211117-5bccf9711e1cfcc914e970d26b98a862.npy +02924116-57b3c60a91e930b42cc89196d0104054.npy +03001627-2ad02c9ed22b03727f141968548cdc00.npy +02958343-b16a147485ec40b25a70c4e5328e0b9f.npy +03593526-a18343c4b0a8026faca4186c3b7dd23d.npy +02876657-2cc108080535bc51e7a14f6d159dcd47.npy +03001627-a8756f91fe03b962492d9da2668ec34c.npy +04379243-345c1bb95b12ff8c013a7bed5288654.npy +04379243-3a69ef9c6512041768c981036afdae64.npy +04090263-50b8d57468b748c9f471ee8186a0fef3.npy +02843684-7a2642b37028b462d39f9e7f9f528702.npy +02958343-7db6c18d976e52e451553ea674d2701f.npy +04256520-27ff0317be31b5932c4e6cb98409dcac.npy +03001627-e50a97aa15d7cbc5972e15b580d9a5b3.npy +03001627-bb4f5cd713a817727d4f8900c5174db0.npy +02924116-3f20a5b51a68667941cefd10ce5d6cc0.npy +04379243-13f2a907f3ac7dfc9b8e42d3eb7abddb.npy +03636649-b6200d3340e31bf4da2dc0e73fb5c1f7.npy +04379243-ddb760d364ee3c5aa7257db74b7b377.npy +04004475-951ea8eeb141a54f9f4a2836426bf029.npy +03001627-e6f37dff25ec4ca4f815ebdb2df45512.npy +04004475-27c2d447b0597c177d9df21a696a9ee3.npy +02924116-2a594ade8abd8f816a7e70b9f461caeb.npy +03948459-fa12f9633aa3c6c9150e6b54e0dc098c.npy +03001627-1b05971a4373c7d2463600025db2266.npy +03624134-c19088b4c32c0f1d22b38218e60be05.npy +03991062-ecac13674a7d2d5be44bad6fc9badfe7.npy +04379243-9081c28e6a90fab1698da6fabf8a99e2.npy +03001627-de9e40c346ad2779f8c3d2002c77ddb.npy +04379243-a516711827a396085528d560ddea455.npy +02946921-f6316c6702c49126193d9e76bb15876.npy +02924116-dca406daf4b48e6760a4e5b4a0135038.npy +03691459-65b461241dd4a4698152e0baa78ddca4.npy +04530566-1e127a7ca9bfcba86df38a7dd1b448e6.npy +04256520-872e3d94c4a37f00d9b53420a5458c53.npy +04379243-f3a44bf9a27f1446ae23680cee12f145.npy +04379243-d7f9651b64c82c799e7c6a73ef46f40c.npy +03642806-a66e02f0effed39f4145b5f47fac09a5.npy +02958343-12d463649ed6c176ab98a7077c964a60.npy +02691156-6e7bc6995080fe6542ca265836030911.npy +03001627-b9e93c2036f24661ae890f02c6b951ff.npy +02958343-385f12fba67e43ada9fe1734a6086750.npy +04379243-95c2e462b2c3e5e529d8eecf3827c486.npy +03001627-b7316f361054c8501962281db2f162a0.npy +04256520-790e42476f871e29e0a954c49a0c328b.npy +04379243-594ca5d155b0bdc2c3bd24f986301745.npy +03001627-7049a1875e1b82d71f8d8332ee17945a.npy +03759954-db4ae89650e2d483d0c3082093ab9709.npy +04401088-113303df7880cd71226bc3b9ce9ff2a1.npy +04379243-b95b9f2d28ab42e49bdca9b7303475c3.npy +04256520-5a2da4b824000054d8390ec1728b1e3e.npy +04090263-9a8ce31de8d6f549a5aad165050e534c.npy +03001627-b117b01ab380362db8134b0fbf68257d.npy +03467517-c96d3c76605bb8ce552ddced979ec9be.npy +02958343-d9cfad911b26b2ae5690f18c88ad5b9e.npy +04090263-b4ad3d030491a7768aa7cb0651220ba4.npy +03325088-83c02a3da44759c73321831d2245cf06.npy +02924116-84b548a6c1b3d7e6c8af801085947b1c.npy +04401088-dd8b9ca9abc834feb5784fac792d6797.npy +02924116-b88c90b6cd62087bb1626da45836ca54.npy +04379243-317c099a20806d10b5c1550bc8448972.npy +02691156-42dcf7058ed936fd22362be7f5226e91.npy +03001627-71dfc2ea8bd6cfaca8e4e5c9426fb9cb.npy +03001627-6fa2db75b28cc1375c728bbce49718a0.npy +02933112-4bbac921678eb957614319d7d997614c.npy +02933112-37b9ca6c1be7e6e7cddef51ecbec6f95.npy +03325088-1f713f9a9ba4eca2b362845c6edb57fc.npy +03467517-7b93f4df48c5e3c4d22ed761db9f24fa.npy +03636649-1efd03d9264973c9f2098a9f7fc86999.npy +02828884-1be83cdaf803fa3b827358da75ee7655.npy +03325088-1f223cac61e3679ef235ab3c41aeb5b6.npy +02828884-f8137efb3a8bf9c3d2b12aa6a0f050b3.npy +03991062-fa392260102667eb612edac3a429aa9a.npy +04074963-e76784a475f7aeb57e1c85c5c15da7fb.npy +03691459-51bdaff7782cab384bde7bbe88086aa1.npy +02958343-f8c4bfc065e35555aa44bfa127abe4bb.npy +04256520-a76a2d34a1aca99611e76965808086c8.npy +03001627-7217176942b8fb42fa7b9a6c80e4e324.npy +04530566-75d41ee15fc8fa4cca581939cd410ca.npy +02880940-98d3408054ab409fd261c3d31246fed3.npy +02691156-dfa5d6ed898152d34210bb5f1b1324bb.npy +02828884-b788370bde4ecd578a333b44b8649ff.npy +04090263-e444044f8872e3b9e1f2a1daf140ac9f.npy +04090263-607b9d1474c640fb3d7c323cf1653143.npy +02691156-bfa8e832618454c0a179137acc8d4437.npy +04090263-27257aee4b0f91b1a16c70da5e24216f.npy +03636649-a4f6213e0b627da55637847f2942f876.npy +04379243-763fe8469c9d204931a818ce55e517b8.npy +04090263-ff5319e43471e9294b49cd65dfcc3a9a.npy +02992529-401d5604ebfb4b43a7d4c094203303b1.npy +04530566-7eefcf457d32b9b03146aa85e47ab8e1.npy +03001627-fc723b936f8d8443492d9da2668ec34c.npy +04530566-81c9e9d3f461c4da9917c7f0cf5ea813.npy +02691156-171f4e9ffda674f44f4fd7b0550f5bef.npy +04330267-826cea6d1387d794e793cc5433bece89.npy +03928116-d31d78811a2028e7d0683b3f1eb1a170.npy +02992529-ff1e484e02e001bdf8a0d9b8943b4050.npy +02958343-72d1eb25d911b6d8913eef1194316fef.npy +03593526-43816943fe7907124e806038192890dd.npy +03337140-d2fa80249a7d959091c352d02061b3f7.npy +04379243-729ff2cedd68a1ad489b0e2838fd952f.npy +02691156-33b8b6af08696fdea616caf97d73fa02.npy +02828884-36d1f0331d7f4ad2cf695c8970a97c29.npy +02691156-831171fab182f62eb115cf6cc3371017.npy +02992529-144d8038c1688e37ab3dd76bf33b0f5e.npy +04379243-96cd9d2f9dc5e102a8529d50958b092.npy +02691156-a5be00166e57ce5dd92de1e594e3dc28.npy +03636649-978df83c1cee012729a60d6ab40898d.npy +03001627-b8b5e172ee58899df2d9e72ba502035.npy +02958343-93357732c6306cb51673e1c313348a01.npy +02933112-2de782c81c89f704c2b64c0adffbe398.npy +04330267-108f01e1b4fbab56557991c690a01e0.npy +04401088-d98df8313cf5e0a7814fa32b2a1183d4.npy +02958343-3ca3c91dae8d2cbdf56f8ea3d9016e55.npy +03642806-7ebe5cc71bdeebd9dd70b866e1cfbf35.npy +03001627-c0b10448880dec62056b4bd5d870b47.npy +02958343-8ed0533fb22f972cd76439fb95cdd2ed.npy +02958343-20ece5093ff8da0bbda72093f9b5aa73.npy +03938244-98159cb7eb8bad07c45c0f305d0b6e87.npy +03636649-e94644a89151a426876b50fc31ccedf9.npy +03001627-297a74e1a658e231f51f77a6d7299806.npy +02958343-79d9cd9a0cc2184ffcc96966174e5650.npy +02992529-325ecc3acd232a5e981b9cd34407d026.npy +02691156-6c432109eee42aed3b053f623496d8f5.npy +03636649-86ae11f8d3079f0869e321f074c1ab85.npy +03991062-f4cae0649c1d4c6034c8ebd75c7d8f3.npy +03211117-c47998c0a317c60611ea7f12f22c0e84.npy +03001627-90dddd5e4aa586bf14513156cf2b8d0d.npy +04379243-710f2f56520b0bdd9b11da89c22111dd.npy +02958343-5f742b43bd5884c6a352068a7fd7afee.npy +02691156-e8c1e738997275799de8e648621673e1.npy +02691156-3a756cbf87c9a6c64d210d9468aedaf2.npy +04379243-35e1541babf368d83328d823e2d2a6d.npy +03593526-420254a2489912c13f8d8f0f2ad2ee2.npy +03001627-2c03bcb2a133ce28bb6caad47eee6580.npy +03790512-b3582e7abddb916c3722d6e4d79b71be.npy +04401088-53cd656555da181db6d41c42f7ade8c8.npy +04530566-6847480bd905f05b544654c1c7449887.npy +02828884-366db933a2c99444f4fb4dee5181bee.npy +03991062-41415d201e1e6b6c78caa162a41a851e.npy +04090263-c9e3dcd6cb94418bfbe54b5d01550.npy +02924116-b31ae15dca8bfe3028c832d54092e2c4.npy +04379243-e80016d5886fced69f8f9f2bcc40c84c.npy +03001627-5b2cfa084b8cfe389753496ba23f2183.npy +02933112-221c831217721399ac043ebb2140dae.npy +03001627-8914307dbc15a20387f0bafef1e13471.npy +03001627-bc61ea1b9348f456492d9da2668ec34c.npy +04256520-81180dfb3874d4c76dc992d5c5e6b2e0.npy +04379243-4d43e9b908d77ddd2d19175e7d19b7cb.npy +04530566-5c9d5cedcb75cd2bad7daee13cc76c38.npy +02958343-167df2c10c116eb5d61b6a34f3fd808c.npy +03325088-b6a6a851039907c433a676b484a36f68.npy +02958343-3b1ad5c98cd92726b60a292fcb118b54.npy +02828884-7b7b25e8ab725feae76bc197b3a3ffc0.npy +02876657-4ec31503deb053636c19a70b7478f722.npy +04379243-eef44075cd1781f1b0a6e87d5d5521b6.npy +04379243-2b1747c389f4d4f1ebadcdfba7971b71.npy +04090263-f2e592962a9df3de1d27f57617a4976d.npy +02828884-b2a585ba5f0b4a25e76bc197b3a3ffc0.npy +04379243-fa5d7f9c54f5bb2010b97bd228fca721.npy +03593526-9215bfacbcac3cb67697d9c3588bbfc5.npy +02691156-f73a8fa9c2859211f2b0736dd4d8afe0.npy +02828884-7df3c8885b22900ec88ad71674956292.npy +02958343-8decf42b145f98d148d2ba4615e03b21.npy +04468005-108baba96ac2f9be5f73a346378dad81.npy +02691156-22c11b2bab2cf93fc1ccec171a275967.npy +04379243-725fbbe72a41e6feafc1aae4dd82ec1f.npy +04379243-884f8604518cdc98c3bd24f986301745.npy +03001627-3896caf2057eed81589929e81650825e.npy +02958343-a39ed639d1da66876d57cf36a7addb49.npy +02828884-3b2f0fa67b29b6cd389a52d0b0203298.npy +03636649-266b5e8e78e4c0dfb82cf928f6ed5338.npy +03691459-12ddcbc94fa909502533128de72c17f.npy +03001627-ffd258571807e6425b1205fcf56bb774.npy +02876657-9dd18bbd88df283a6b36e3e6a5b248ba.npy +03001627-ff2333f528efd790fc93ece3545739c4.npy +02691156-d24f2a1da14a00ce16b34c3751bc447d.npy +03001627-79fb74d29b9b772c36b0f2a1430e993a.npy +03001627-a07f62023d3784839aab0d90d6455f4a.npy +02958343-fad616172dbd52649f06afd991af5139.npy +02691156-a20490d0ffcd3be6e0d6812cdcf8799b.npy +03001627-b192cda468f9390aa3f22b4b00de6dfb.npy +04256520-4ae401feb8499f5c9f2349486c570dd4.npy +03624134-612870fbbbbce57ffcace4d823343363.npy +02958343-40b272e537fae1418277d1ad96e14e9a.npy +04379243-516928532093f765bababe11fcea8796.npy +03001627-508450cc9ab2a5fa98cfd47a860803c5.npy +03325088-bcf485906e70fb0e50da8b99982a3057.npy +04530566-fad2e708e354b0315e585de41f56d4fd.npy +04256520-9eef66b5d0444f8398cfd47a860803c5.npy +04090263-36299a0fd2aebb5b1cb4c4614a9a037e.npy +02933112-83412e29d5978b101f6dfedaba98d5f9.npy +03001627-2a56e3e2a6505ec492d9da2668ec34c.npy +03636649-312d6dc78d666dc88a74e38e7d86eecb.npy +02691156-b9ba988dd9a6cf426e8b6dd39a855b69.npy +04256520-ffa7680b18ede5cfedeed2a7fa983956.npy +03759954-bfca931e3aa57d06ef026123226f5519.npy +02691156-421f45774389984bea6586b61968eac.npy +03642806-8489cb783d249651b674654e7bbe623d.npy +04379243-467e71e8e546721e1aa023603cb7e1bd.npy +04090263-5b7e127c67c72e72f6ebd7f0952711c3.npy +04379243-7b2af227264af938d42b9650f19dd425.npy +04256520-d510edfd51ee8a942dd4967de4160123.npy +03636649-5428e217da1af02822a33e080d0e71c.npy +02828884-8f25e1c5977cf1350f0339a8f91fdfe.npy +02924116-150004fead49c0b2193d7855ecfc1bd3.npy +03207941-a5084a48c41d1c454fa5742b9f971b9f.npy +02691156-757c47e20a37647431e38f024b7ad042.npy +03325088-74d1b8b026ed9dea3321831d2245cf06.npy +03325088-f5768e78c91ac91dd5fb864340bb146.npy +03991062-a002b46a27eedc46abd0967c9a744f48.npy +04256520-bf30f90b1c864bc2d5cb6d178687b980.npy +03001627-e039a013f1877fbf42bd71dd667c95ad.npy +02691156-8d148580eda6994c2a8810071030bd25.npy +03001627-40d4acc240c458a970aa4d5182ecf167.npy +04090263-d3a7c0fd2e4418861fe7d5784ec6d0eb.npy +02691156-b51c1bb30371852fa325f626d0051e24.npy +04401088-5ae839d512364bd4da0f54fde38627c3.npy +03046257-9b66a37c0e1a1da2d4096e81fa01e27.npy +02691156-77a70f61dc0c6260e70eaaf99089d5f7.npy +03636649-7be01530bf43f2ed8a83637b92bdc7.npy +04530566-5b86640d3bc2e43decac3f40526a2cc2.npy +02924116-c08377fec8061e8ab1626da45836ca54.npy +04530566-787e381b4a968a55af5574caf3b1433d.npy +02828884-371e22e18f8e2fccad5067eac75a07f7.npy +02691156-dd9a7dd5e2ea3389938204d34a891739.npy +04530566-8eeb2bec8499fc6ba60ce6f0a0028c13.npy +03948459-9b6c6048719e7e024cb47a45be6e6ae3.npy +03001627-c520bc9dde7c0a19d2afe8d5254a0d04.npy +02992529-c2884eed47300891697f9662a764c78.npy +04379243-757ad2516284e2728d3e4a6c55f660b8.npy +04256520-13b9cc6c187edb98afd316e82119b42.npy +02747177-16521a9446e3de14a6f567d4d1e09ecb.npy +03636649-31dee666120727b0be78c8b300d2a963.npy +04379243-ee5f0411fcff59951105a3fc18779f13.npy +04256520-8760843dbfc059d6c242632b2a8c3129.npy +04090263-6655be7932b8b984c04419d9f4e18d0d.npy +04090263-280cbd90ba9cfd24fc105e275e6ac8f1.npy +04468005-e5d292b873af06b24c7ef5f59a6ea23a.npy +03211117-15f23ffcc92b751af7502a3b84f78df0.npy +02691156-776c423005dbb55d354aed6327ff24db.npy +03001627-76ab50cc6491e518782f27684f3b650c.npy +04090263-22d742f999dd7823bd2cd7f810561bda.npy +04379243-49e5f7af3e3c0ceb87e54aa3a663dbe.npy +04379243-e3457599e244cb83ef9a8aedf51bb497.npy +02691156-ab8eadee08cba8d8303d346f4be7d4f.npy +03691459-acdf7e6e551eaad3423723bc261e3897.npy +04379243-1a43bd2e53364313f51f77a6d7299806.npy +02880940-ad8a50aa5894bc40c762eb31f1f0c676.npy +04379243-f4b83b7fde9a4f0cdc3d55ecee5c17b3.npy +02691156-947ac452f850e284082bf69673a94f.npy +02691156-80da27a121142718e15a23e1c3d8f46d.npy +04401088-4a48ce1a067f686dfb63369d5dd85d25.npy +04530566-9c92c9e16d1d214b81eadf50fbd8addb.npy +03001627-20e1bdd54d4082097962800be79c6e52.npy +04256520-c7f31b9900a1a7644785ad2feb797e.npy +03001627-59bd57fe0389e7831f7c97814eaf956d.npy +03636649-5d69edfdd6f7f62ff88ace17ca85e37c.npy +02933112-19a0a48b2b908dafc59350d819542ec7.npy +03991062-1c4257c50d27388525ebd1cd0b422e32.npy +03001627-589e717feb809e7c1c5a16cc04345597.npy +04379243-892127d87f684bd14b91ba28fa583347.npy +03991062-72bea517f9d243808b80480f1020d2fe.npy +03001627-d851b8a016cf114c742f75bc7df727ae.npy +02958343-56d5921f58898cbc56e8a11c9bc9a7f.npy +04090263-34eb31e5ac8802246f2614b47f532d63.npy +03211117-afcacbd7078a3b4b70bb6bcb670ecdf5.npy +03001627-4f136e2a90fc8ff63ac4c571779c5fb1.npy +03001627-50016cf5a426bd63f9d384ecdcc090b1.npy +03325088-c69047a5a9a995b1c36fb70296e45483.npy +04256520-139b1622071f1864f7d7105e737c7740.npy +03001627-813f84c21a081253c02e349cb722a77a.npy +02933112-548996207fe62d4a89ecd28750d46ac.npy +02958343-db91e70ebe09d5edf446f92b52bbd82a.npy +03691459-98b920157670bcdd716d882f857922cf.npy +02958343-af94283a61eafc7183a0f773f3852fbf.npy +02828884-f133d3165d54e5b227d635628fe95db0.npy +04090263-121ef8a289b232a73c5eae1befdca7aa.npy +03691459-b7c5eae318e4e796d4e62d99c536bbaf.npy +02958343-834c7e46dfe757b4d229396ef51d2d02.npy +03642806-59bf155f2c4d655894c7c2dce500aa02.npy +02871439-6dc2a415f75f0500cbf7082b5354e908.npy +03001627-1c173d970e21e9a8be95ff480950e9ef.npy +03790512-5a1e4b1b6dfe231a362d3a933f999b0.npy +03636649-4f16fffbe480b835276206fae5d3c473.npy +03636649-2d9224be8cc6fdaa1050b055aafa6fb8.npy +03991062-6957f3429308af2781faebbdea6bd9be.npy +02958343-bf506399c934c6b3c3eedd6d54e2a52.npy +04379243-3d4399c54a60ac26febad4f49b26ec52.npy +04379243-68142013a4f5e7c2febad4f49b26ec52.npy +02828884-15fd978b59889cdc30bbd4cddd04c77b.npy +03001627-8114bc9ee0a7a093a094848ea4d06501.npy +03691459-bcada2acf7cdd8c29a08db804545b684.npy +04379243-fc51355d4d03ff4ae6c5cd45aa112726.npy +04379243-a4e5a85d21a6b36ba60a29091f2ab01f.npy +02933112-6c45346990283b7fa2e244117f013369.npy +04256520-1a525427776b39259c89c86daa5af59d.npy +04379243-c85ba9a3e1896eb254adaad15f0d584e.npy +04256520-18a45593c2ac4ffb6deee1099ca09a28.npy +04401088-f760cdb0f8cbc6fa3c28e819722231b4.npy +03467517-ca9720d793355dd693f0194265a9746c.npy +03001627-6df1ecffaa0abdbf327289c00b6dc9ca.npy +04256520-4ea78c36488dd185f3598efd14e493d5.npy +03642806-e083105e9c2a28bb0c3a03d0a1f182f.npy +04090263-553b06cd4354c8ab1c15dec0da4e4dfa.npy +04468005-25d7d7fd82d761b5b80968527b758d3d.npy +03790512-54f016b47a5864cd5dde04c96fd8146.npy +04379243-62cb358e8c73add6b71af98eaf823ae8.npy +02808440-20fb36fea4f6ce91901fed29c825c894.npy +04379243-d828c9f6c3e9f67367d177b869ee03bf.npy +03001627-87a3ee7e68f360351db0d76a41d718a1.npy +03636649-ad01773f3f53bca3a8ffa3a6526018ac.npy +03001627-51d151853d8d05db639e286420a03c3f.npy +04554684-30468019d1d90687b361c88e264d57a6.npy +03761084-2a791816d868a81875782a1c52f768a9.npy +03467517-369fc7f8d880e1b793f0194265a9746c.npy +03325088-7f45c771a4cd5ca614b35a7d7cea7130.npy +02924116-2a5d0c039562dfe8481aa8b5531c68a9.npy +04401088-74e5759913a2ac208b0d3d4e51815944.npy +02958343-a9aea98c1e79a2e6e99225f2edcc7982.npy +03691459-789c800c7f6d9e00b5f0ecf6cb865832.npy +03211117-9b764d286359e0f9cb84789183638105.npy +03001627-3f23ed37910bbb589eb12cef6be5d578.npy +02828884-decfee8dff04ef84990a10a82d99ca57.npy +02801938-951c5192ed4b3759fb0f1b7266d79466.npy +03001627-9058e82b6cd496891e481c46590219a6.npy +02958343-6be5a91bdd709a42634d30cd3ecea7e5.npy +04090263-98375ee901fa6ae4e2e7039a6accd4c0.npy +04379243-f7f5cb907c50a8791f66341aa9abe5e0.npy +04379243-63c4c59906d69b0ffe15c1377dcce2f7.npy +03001627-187222bc1f81d57b781d9dcb8ecbccc.npy +04090263-87652d99be1b6e386d639befe132b2e1.npy +04090263-2385f3cc7fe8490bd3932d50c4a63aef.npy +03636649-8ce777fa2b40476cfcb8d8c6d4df8143.npy +03636649-cc3eb92ef1319ba38a3c32fbf0f86f95.npy +02946921-669033f9b748c292d18ceeb5427760e8.npy +04379243-675ac6cac5a81bd3811cdd52f3d07553.npy +04401088-6a073661711d8b9f1a5b805dbbf26206.npy +02958343-9171272d0e357c40435b5ce06ecf3e86.npy +03001627-8ddaa112e6ba36b5b1e23c7675c49239.npy +03636649-217bf5bf88842058b8a06a6203bc49a9.npy +04379243-5ca0a56bcc0d469535836c728d324152.npy +03593526-770df0065c50c19dd884646143528886.npy +03636649-f5c61ca4acfb7f5435836c728d324152.npy +02691156-7dfaa526d4b432e867c54439d6177032.npy +03325088-c72b179913088d6d76c18e71fd49c4dc.npy +04379243-23486b58246302de979ace30a051374c.npy +04379243-c20a339e2983a462406281a1e760ea19.npy +03001627-c5e3ef17d1fc834b3c84e7f4f4c3d556.npy +04379243-6c8bea32e31192a5f1dc60fdf1e64165.npy +03691459-79cbb3c5f6bad447abc635d6ed355bef.npy +04401088-67743ab1b28ab5cab3fcf86503541b68.npy +02828884-6eb04c416f0e40565a3c5e32936a202c.npy +04256520-49e39486a1df116be3923f7359326ebf.npy +03001627-c93113c742415c76cffd61677456447e.npy +03691459-36b29f93deaf22f66b1cc4d44837f930.npy +03938244-7b2bc135a01a7ff59be1712545749b62.npy +03001627-56fc424a89bb137bf2197da8dec8488d.npy +03636649-a37f1bd2732ce11981d841466b314f95.npy +03790512-fea42d4f08c271dcd5dde04c96fd8146.npy +04530566-77aacd8997c67145cf10e9e4657f415e.npy +03691459-87f10613128f3e6198e0c75f11f82c6.npy +04379243-ad38f4e8026d7858c3bd24f986301745.npy +03001627-9a28bffd582333ae2af4036e9c51cbc4.npy +02958343-c2283d62367d637249b991141ee51d9a.npy +03790512-33aa1eadcd21734148272812609617e2.npy +03001627-10709332176024ce9e47e7a22e24daa3.npy +02958343-5135ad38043cfe64eb766e5a46fceab.npy +02691156-d9a92927192e9755702736225b32125.npy +02691156-8fa9e2e8dbed43911f32208e53f871eb.npy +04256520-db8c451f7b01ae88f91663a74ccd2338.npy +02828884-9f0a6e7c525c3c53d4d8765e3910f617.npy +02691156-9873e280d91107fe9a55c6af6f4b2bb3.npy +03691459-d8ce373c4ad4e6913caae5373ff4181f.npy +03211117-f0582a84c9f7f353ba24f8032b14b71c.npy +04530566-d0d2753d2d3e6d3d2752699ac7aab1.npy +03467517-ab6843f87773c77e63e6b27c89da971e.npy +02691156-c777a5b86424892c644d8182e9bdf4a3.npy +03211117-f464a98b2d4f598be8581b38259c3721.npy +03001627-78d3258e4664daa9e8f8c11a24c52ebb.npy +03001627-a565a80b093f12005481bf9052f50100.npy +04530566-33f4d31a559bc07fc1ccec171a275967.npy +02946921-70172e6afe6aff7847f90c1ac631b97f.npy +02958343-5e87b04efd58cc8922412d2a728de1d5.npy +03001627-e2a7604ce1b5e6c4c3c6a889ee0bd115.npy +02691156-33c6568fd4de5aaf1e623da3c4e40c05.npy +02933112-429638b99d096c89c59350d819542ec7.npy +04256520-8180afee86f2075519fb4103277a6b93.npy +03624134-7be45dc5c51ad883c56c4418b190e03.npy +03001627-d0215a0b82661b82496d6322c763591.npy +04090263-5162b8d6add4dcd7f0fea2ee98610322.npy +02773838-e450a063965ce182372d50f0ef237781.npy +04530566-956c3b989bdd0603158a3417d0510bc.npy +04256520-ecf29f5698798a74104d78b9947ee8.npy +03948459-86886a49bb69dce3fb5c1b0f759e2bc1.npy +04090263-fa4cc6689173c57a25975e984b0e050b.npy +04379243-cf2351b8172fa011a6f925961cc8367b.npy +02958343-5876e90c8f0b15e112ed57dd1bc82aa3.npy +04379243-5b62582a39681d809699d7bc7fedec1c.npy +03001627-a9b75041c8ef8654f2b838d6025155d8.npy +03636649-b4aee889d5e2a826f6747912091f1965.npy +04379243-6aae2a0daba548f082ec48ff3a4fe07c.npy +04468005-3b52c5d66de4247952470de2774d6099.npy +02958343-38326e6ede45e5ab7b1fe308bc94d4e0.npy +04379243-32eceb8ea5b43926de4d0883c61d7e14.npy +04379243-76206b183e39910a1c6b880f91673ae8.npy +03790512-f160284c3ddbc5df573365aa54129c1b.npy +02958343-b2f412545dce6e8266ff862bad2bb0ba.npy +04379243-b24d5f0395eb987e185574a5e2255bb6.npy +03001627-e8c3582f0413179b47edf0d5b6459616.npy +03001627-570527a5388977c878ba201e6a414b21.npy +02958343-3fefe1e60f5683db247a5be450795511.npy +04468005-ff63d2ad2181fd002e730f8b5eb2a879.npy +03593526-5bbc259497af2fa15db77ed1f5c8b93.npy +04530566-fc71778c7daf92e49786591d9b03a096.npy +03991062-4cd5c535b26e905aa2c59a4d90e63212.npy +04379243-5fc81c6ef8ae997a6ba09c1bcc052706.npy +02876657-2c5fd15998b6f8b996716aabcb2fff20.npy +03797390-c7f8d39c406fee941050b055aafa6fb8.npy +04379243-50f1ace689c05bed30bbd4cddd04c77b.npy +02691156-3209a02075cb9f0168023bcf4ba60aff.npy +02992529-a0a41f9444733969c3d30d5f04be159e.npy +02828884-f9e7dcaf9b7a9eb3c9befbd10d7e29b.npy +03001627-b83c9e0fefbbd843e88e73357a673e34.npy +04256520-5149af0adc1f4a6aa45aa09d68b87656.npy +02828884-cedbe77bb857a16d3104206d774d39d1.npy +04379243-9b3433ca11cd09bae7c7920f6a65a54d.npy +02924116-386ba34d362af65e699f58a238068686.npy +02992529-8961485f45d94383af4ba3ad8461249b.npy +04379243-4a3fe6b653bd51d03d5f95f9058dd0d4.npy +03691459-fa98563736440326ce1db673cf70420f.npy +02958343-ad00611d36e535f266d77f2d6fcbca33.npy +02933112-297684bcd05347cd86d53ab0fe94e911.npy +02876657-4c5329ae5fc25ff5b7903bac4a497954.npy +03624134-2f74196bd5cb462727c767f081f1365a.npy +04379243-e241cba189154397718664fe76a3c7a0.npy +04256520-eac135eb1aa4665c4b3c42e318f3affc.npy +04379243-42c35105a94ae6e68ec80f11cb8c2f41.npy +03636649-2d3c98d5d85f22a127babbd370e736b.npy +03691459-3fc0513ac3bf11c873d25f4e2e3775f1.npy +04090263-3b4fcf1d294f11bc5db864c34fc9b1b3.npy +02933112-88a30428b822f8ad630e9aba042fe4f.npy +03691459-1bf06b16e59e482c238ad1274d829e68.npy +03691459-f187f9369aa0a93200d439345883b61.npy +03001627-fcfb7012968416679c0b027ae5b223d6.npy +04379243-7f284e0ae4c1430fc5beea20858a99d5.npy +02933112-696c0051a5d5db993bd5bed2701d5593.npy +04401088-ba21b515df2f8a8f19db431d2a67219.npy +03001627-a06c400e070343cfd8a56a98f4d239c3.npy +04460130-283c8fd32d9b9a95c2c6f10e262c6c44.npy +03001627-3d5053323021b1babbaf011bdbf27c0e.npy +03691459-bc11fa1bae19a90ad74a70b98d3225c0.npy +03001627-b41aaea5754adae0444b41d6d7f557fa.npy +02808440-77e9758d3d2256ddccd0340812259a39.npy +03211117-7ad85d1478f03d4f4532b058befb6326.npy +02876657-d2c9c369376827adf8f0533aaf004c87.npy +03642806-6d2681893925b93133817c25ef5f879b.npy +03948459-2d582f697e4522e6e1f2a1daf140ac9f.npy +04379243-5ca1a1574679afed68661782af60b711.npy +03001627-90a7820e2391509835836c728d324152.npy +04530566-b472526267976d94e145e5e8ca0d926.npy +02828884-1093ca7b44ac90cd902e30b4d3d9167d.npy +02933112-13bae5728bec802034ea40f5d8767c57.npy +03691459-2a38fb6acef92461ed2aedc3715ac201.npy +04530566-e5bb455414be46bbe62f291403035429.npy +02691156-e115f4f824e28246becc132ee053f2fa.npy +04468005-a9c20f1f97afab8485c84583a15d0973.npy +04256520-6043fcf2ea4aba3a8888e7425bc4b85.npy +02958343-66edab2d079680f876ad064d1c5fdd7c.npy +04256520-41aa5dba48b7a3f683257865d0a50551.npy +03948459-9b19164c5b17f3016da79efb34b8c0b4.npy +03636649-39439a41656f7d50d42b9650f19dd425.npy +04330267-52d465df8deb8d51908e9df84c8bf032.npy +03211117-78e7b27f68570f3c47dcca01880c200f.npy +02933112-d4c4d991f9fdf0b654affd783a718eb.npy +03467517-f1fb45c857f52083a24eeca91f583600.npy +03001627-11fa9b044482814ef91663a74ccd2338.npy +04379243-987b7b49a1435a4b1b17743c18fb63dc.npy +04530566-991dab2b2339600a27da61c271c9c6a1.npy +02958343-c6709eb00a557c9785af3668c1cb30b.npy +03593526-b99191dfcaa751ad50e02ef26f47fe02.npy +02691156-1a32f10b20170883663e90eaf6b4ca52.npy +04379243-bd39b7924b0f69359d0d74633db4834d.npy +04379243-6ec12aacb68a918a311268c007111527.npy +02691156-fe3aa0ec747c12c0ca8607f540cc62ba.npy +03636649-45a2e2773a905744d5c91bd67a7ae42a.npy +02876657-bd28b6cd2fdb691b8d8eca78e5e16d9d.npy +04379243-e563bbcb07d70dcc3321831d2245cf06.npy +03001627-64139338cf8835515d6c0eb60be969cc.npy +03211117-ecd1641932584115fcea08a6f6e1c30a.npy +03636649-c905941a8db6575fd5141de389ccb29.npy +02933112-3a910cc1f575b08339d3717288022c20.npy +02691156-8fe1c92c1c9ff33fbc0909d98a1ff2b4.npy +04256520-95d394154dc98f0ddbe9c90af547c85d.npy +02691156-4a7b3bb0f7e4e13af7f031a34b185310.npy +04256520-512434114e17c17d4a79bd7fa08bf04f.npy +03001627-9542f23e526bd7aa24adc0b4355a9827.npy +02828884-bb07fac582a687f0828583ad97f853c7.npy +02828884-b4ae95fbb879bed0ee38cd6552dcaadc.npy +04460130-37d62783bdefc54a1ffedce3943a1ba2.npy +03593526-f232cafa6b5d570ac5beea20858a99d5.npy +03642806-e9bb4175bc73a2eeb60886b233d6cbd8.npy +02958343-8cc9aaf75a2fb056dcff2899f073ea9d.npy +02691156-5b048655453b37467584cbfee85fb982.npy +02871439-4a380e2801664a015c3654528317cdb2.npy +03948459-7418810de4b13e8430b6ca3ac82edfa3.npy +04530566-a3f6f17c5febd688cb5e9b11b96f53b9.npy +04401088-3aa2fd5054465056e25336bb76be9963.npy +04379243-ec8efc59f0e8c0fa97b2fb14fbcb9c20.npy +02871439-1ab8202a944a6ff1de650492e45fb14f.npy +03636649-bb53a3c6ac9cbd386fa63795f94c4d8c.npy +02933112-5f55127e04171d6435836c728d324152.npy +02691156-3764de22af04fd32a993db466b6d73d3.npy +02691156-3af52163a2d0551d91637951367b1518.npy +02828884-38d0cc28d4ff1ad0b604d999bdb46442.npy +02691156-17bc7631cbdaaa0c932e2c9d273ab571.npy +02933112-875437f9f2bfdc3feadc9f074ecd1df1.npy +03691459-39554167163a7cc3f881bbcfcc456ec.npy +03797390-3143a4accdc23349cac584186c95ce9b.npy +02828884-578b801e35fd2defd4d8765e3910f617.npy +04379243-114a39da3b4bf118d42ec7e303174a87.npy +04401088-308cce8808b076bff49084215d845d01.npy +02958343-2dd174957a2053345fcb05674109534a.npy +04530566-74470719a1b44c9a45aff212946058fc.npy +04379243-fbcdfe3edfc9a679ad5067eac75a07f7.npy +04379243-3c6ced93a3103cf34b28edba8d17a601.npy +03467517-4976872c92b0c10ea070d261aeb7d2bc.npy +04379243-27805445a3c587c1db039d8689a74349.npy +03211117-3817ccc2d7a247cbd821b4c6abf4a2ac.npy +03467517-807435998a164b5ad57700c05b1862d8.npy +02808440-78c992bac95191673321831d2245cf06.npy +04379243-d9b82ebcd756397c371fff21f277e702.npy +03691459-e1bcea986fcbb7fab359198a2f47cf13.npy +04530566-ceaacadde93c2be6ee138bcc5a7d5853.npy +03001627-8fd87d4aac0153a26b28a4cbbb97a012.npy +04530566-cdb70178e2562e7a80ac63732535bbcc.npy +04090263-b012c9d123aa8064ace721126020c1a3.npy +04379243-33e4866b6db3f49e6fe3612af521500.npy +02691156-a657a0dec941d40772fe60ad306aa5.npy +04530566-cd65ea1bb0e091d5a1ea2dd0a4cf317e.npy +04379243-74444148ff8d13d0febad4f49b26ec52.npy +02828884-1c310698c57a3d378fd6b27be619556b.npy +02747177-86194a4645da1f19e14ca01ae177e9d.npy +04379243-2afbff3cd25cdd426392a5b643ed5e3.npy +04256520-d8a8701f3fb8855d4d0a79ea230a0577.npy +02933112-528ab24c6afd91c38aaae3d020f5ddf8.npy +04379243-c36d04d3a10fba869e87d2bdcb41f548.npy +03691459-6577288320db747cea37255d6341d07d.npy +02691156-f350f4836dcd13541b1cc145b0144991.npy +03001627-5ce845f80b1d407282dde982679cd879.npy +03001627-9012e4fff3cb71b57773c2e28f019f8a.npy +04401088-c43c9123ed893de5a0eb5a85db887292.npy +02958343-e7b9a6485b15921d51a95aaa6caba1d3.npy +03636649-8232dc35ac9ccfb016a2b5862518c93.npy +02808440-594c15031388ed1588cafac7d7e6b54.npy +03001627-97c343e28e2b9ea4bf4414e655b3a4c.npy +02828884-7ba9140b8e416d79601104cd2d998272.npy +02691156-3ae96a1e1bb488942296d88107d065f6.npy +02808440-88d183f319cddb7344221bef0fa3c36b.npy +04379243-e94dcd39a8e438851b17743c18fb63dc.npy +03001627-4841eb9b6b15d037dfd20491defa4a70.npy +02828884-14abcb14222adcd499b68520b875243.npy +02958343-dca1e82e7d39edcbc2c2c81e2232aa95.npy +04379243-db0c430a51ac45c19d2be74cfb51ade1.npy +03001627-426f02971983126daae8d1cc50964a7d.npy +03001627-47aca56ff3a7b8a71a782a4379556c7.npy +02933112-b7a9d8b469cb06037824b732b006daaa.npy +02773838-1342fc4f613687f92569b963af585e33.npy +03593526-26b9ede17422ff5b84cd259bd328e92a.npy +03001627-8e77d0965bd1ebc598e0d1738edd4f19.npy +03211117-dc4b21d338c4b4d1bef7854be4daf5ad.npy +02691156-25f08a106a0eb00eca8607f540cc62ba.npy +02691156-6bfee98d2078c3c4ca8607f540cc62ba.npy +02958343-f87f654f056b3679f4103381793c29f7.npy +02924116-583a67819f58209b2f3f67dd919744dd.npy +03593526-7a9c65728f8baa6da706b53616da968b.npy +04379243-7c24e4f8778e224799a5e8f6c5baa224.npy +02992529-7dc461c63f3aa4a3a2c7c5886f4bbc93.npy +02942699-51176ec8f251800165a1ced01089a2d6.npy +04379243-2e92e1ec1038ab0914513156cf2b8d0d.npy +02691156-7b9bb6e42aa2191b58a458f7911d7423.npy +04379243-2ab79a94145330a95ca21a5844017a0f.npy +03001627-11355c7f7ffa3c09737d107bffc3cd98.npy +03636649-64d0f2752aea0f40a99e0f0bf1de3bbf.npy +04256520-f1ce06c5259f771dc24182d0db4c6889.npy +04090263-76e10c1cb25e814fe7d6f3ee02d4059f.npy +03691459-831f70cfa81a12ba7b440c5df8efc309.npy +02828884-19f24754ceb9bc948598ced6ad25b3e2.npy +02691156-20865546e07ab8067c597cd12d99981b.npy +02958343-44c278891ddcab2dc0e3666c7d0ec7d0.npy +04379243-571c9ffa865fa70d2dff41777eb31a7.npy +04379243-366645cdaab60c793e5eb583c9d92b57.npy +03001627-c56dcaf6b862a6329158e0f216b27548.npy +04256520-74369d5fdfa2356a066c1f884f0378.npy +03001627-fc818d6fe03f098fd6f4cef762589739.npy +02691156-7b4b249f1d3400e488be2a30dd556a09.npy +02958343-1ae9732840a315afab2c2809513f396e.npy +02818832-8df7e58200ac5e6ab91b871e750ca615.npy +04379243-13782b95eeefcedacf004563556ddb36.npy +03046257-6efd372c631a9ea13b48a711df82173e.npy +03467517-8c3d3e69d03d3443e84e459fb01822f.npy +04379243-43daa5027409cbbd4b3c42e318f3affc.npy +02808440-89343976cb18545d4bce3147c41ec725.npy +02691156-a6cbada42d1a30d0f5c7319b71bdce6e.npy +03691459-62e30deaa5aeac183ef7ad0f5cedb0e3.npy +02691156-3aba99921e9e1c93ef40e4c1c2686cd3.npy +04379243-6a5c816eca38f130c6536c7253813c8f.npy +04256520-438c3671222b3e6c800d7b7d07715065.npy +03797390-5310945bb21d74a41fabf3cbd0fc77bc.npy +02691156-2d4c147d4d1cc40c582bf3113c3974ef.npy +02747177-f97df3db44133969fe42c1e9e335e7fc.npy +03948459-a4c228e14915863eb8efd193bc3eb26e.npy +03001627-8ad35dbc44f40be1492d9da2668ec34c.npy +02992529-893ed9fc527a8329d3fdfcd95fe3518a.npy +04530566-32dc0308ca44f256ae9e3df35a893c9.npy +04379243-2fa04d6a788be63f32db3066d0100ee4.npy +03991062-17a9ed841655bff02f4c86eeb341b7fa.npy +03001627-ce10e4e0d04c33e7322ed2ef5fc90e25.npy +04256520-8043ff469c9bed4d48c575435d16be7c.npy +02818832-75e308dc83c1c1f0bf20c89392e58bb0.npy +02992529-5fe99904fa4b22d4ff1911c2640f2e42.npy +04379243-e367cc737c304024297936c81e7f6629.npy +03467517-f37376f5089ad242561dce3fe08634b7.npy +02958343-fc620f7906f444f1ec403de85b47bd60.npy +02808440-32c2dbf3246c8b2366bf2fda6157c15b.npy +03001627-609746ebe63abc2c2f38c0d2792fb5e.npy +02924116-69038ea9a392fbb924254bfe0c86460.npy +04256520-d580b1bcffceaff39f2fd5a6f642de3d.npy +04379243-86b942f68417df36cbde89e0c48a01bf.npy +02828884-ce663a6430eb9523cb2a965e75be701c.npy +04256520-7cfccaf7557934911ee8243f54292d6.npy +02933112-1258a7bae01e349fa320e34dad7c78bd.npy +04090263-230851bc45f916297c9aa6759ab09b15.npy +02958343-dd0817b9757b74c75d3a87a5c4dd9ce4.npy +03467517-3b7928afa5667e9112a47018402419a2.npy +04379243-34ea33172f39665022d09160e03f114b.npy +03790512-8f032c42d53b5c79aca88bdc785b0d2f.npy +04256520-4756416d882c569b7acade7eda5e06dd.npy +03636649-871e950f1d453b32597976c675750537.npy +03636649-a29aa1d787d4d3252cd2160e449d45ae.npy +02691156-5bc41589eba11a4e15477d594f1fbd99.npy +02958343-9b0d7aac4500546911718baa6d4afc0b.npy +04256520-b0fdc43b0b4e990719abd93be2967664.npy +04379243-cae4f0f8b87db72dbbdc99ec57ef9c40.npy +02691156-92497dcdab4d0a8de1e82eac4119b0b3.npy +03001627-b510aa817f9aa6795906036a9b83f8d5.npy +04379243-185e4e4fe22d65842095a33119f8ea7.npy +03001627-5c427d9fe3c76b356c07fcbf2661d108.npy +04330267-1d089370d1329dbaa2d703b56896de1b.npy +04530566-9625f56fdbada3377220891f188bc420.npy +04379243-c6575b4c39a341c698d5fc0473d00a1c.npy +02808440-f6f4dc302b85c7f96fe347138aa3101c.npy +02828884-f6219339c25b42fe81faebbdea6bd9be.npy +02691156-d43b80dd95a2233a5ae839ffe09b9d31.npy +02992529-a1e51e185a9f24354b8478bdb97333d3.npy +04530566-724ca82e43f5e4816811fda0ba2e1809.npy +02828884-43d40b726c369eaaed98cca8f0ccd5f7.npy +03001627-480d483b508469d1a42913f1450ecdb8.npy +03710193-4816fcb4595a45e2781e7efd407c71fc.npy +03593526-330880146fd858e2cb6782d0f0acad78.npy +03691459-153c468a60e1116b2eafea928e361a58.npy +03467517-d3972d599036251369da8e7f9a803d12.npy +02747177-5a0590dae471241ad5067eac75a07f7.npy +04379243-c57c4616b4a9c14ca93412f1b60e6fba.npy +04379243-166ca6382eb80ee830bbd4cddd04c77b.npy +04379243-a0e7dc01e9bb5de1858699aaad4acee4.npy +03636649-45f11cb4099c9c87bbc7a6acbd8f058b.npy +02808440-77ec56a21b4ae4b8b84959963148f2a2.npy +04530566-58a768c309c01b2cd6dc46f6baef3245.npy +04379243-daf4f3295db84cd39420b255bb5956f0.npy +03636649-4febafd730ab294afcb8d8c6d4df8143.npy +04256520-afcb115706de531f909c248d0d9da9f5.npy +04379243-7ccb70ddb69bf162298a458038c49d73.npy +03467517-16916a50a064304bf6ed0b697979412e.npy +04379243-317a934556406ef84b3c42e318f3affc.npy +02992529-62314ec7373898059f7477e2986c440f.npy +02933112-1af4a1dfa4f94cd44da5feafe6f1c8fc.npy +04379243-b320afa9ad7573401bb64c55dcda87d4.npy +02747177-50978d3850fcf4e371a126804ae24042.npy +02747177-7c90fba6cd7f73871c1ef519b9196b63.npy +03211117-8826871281dc12951072594c80fb7e4e.npy +04256520-30cc7577792d4dfa4b3c42e318f3affc.npy +03691459-105d0802d1ee0430bba5c9b6de65a038.npy +03001627-4603969ca86e226affb3dd5191e9a4.npy +02958343-6615a61a799c144e84306f3bf0a1f2d7.npy +04379243-e35d752ecf4e205ab40f0ac0fb9a650d.npy +04256520-117f6ac4bcd75d8b4ad65adb06bbae49.npy +02691156-4e67529b0ca7bd4fb3f2b01de37c0b29.npy +04379243-7e154e1cd9f231dab8afe053c66e5d4a.npy +02958343-83c21f0f383524e9bdd7ac383509f04c.npy +03001627-df51cb83f0e55b81d85934de5898f0b.npy +04401088-800ef55c1401c26ef5d4e1af18c85258.npy +03211117-94001a0000497e8ae4b68d3b17c43658.npy +04379243-ec81c49ee12e8a70fd06de9ba37d44bd.npy +04256520-ff1bf2df4bc49e1f79add0ba9a2ff19e.npy +03636649-baddae470b28db0482e23b5f9fd46e1e.npy +04401088-e30f2d19e9f44f6ab0cb879d4613195c.npy +04468005-559a4e0316bb0fea6aab81f7f1d40525.npy +04530566-2114fe40b577ced9c7640fef6931a907.npy +03001627-52cfbd8c8650402ba72559fc4f86f700.npy +03948459-5f46578efd2c65e5d4ac2f5fcaa742ac.npy +03001627-6a3d2feff3783804387379bbd607d69e.npy +04554684-14bb2e591332db56b0be6ed024602be5.npy +03636649-53d1324d1e85fd37c35131da26f8061a.npy +02691156-9407c551466b346450e5128bacca96b5.npy +04530566-98a61aa6d78f6f49de91bdb310db8e7e.npy +04225987-a19d80304e26099e7394c987e5e211f0.npy +04256520-8a01d1d686c4b0d3593ebeeedbff73b.npy +02691156-6110cd7e771f0ab3a847e990b54bf80c.npy +04379243-c0ac5dea15f961c9e76bc197b3a3ffc0.npy +04401088-b7741503cf1fe40378bfad8b5ed8c4ef.npy +03325088-9c4876c03981833fb362845c6edb57fc.npy +02828884-3f2d311ddc3b6c19d4d8765e3910f617.npy +02691156-3b529633bdd49dc1e5dbe91fa3801c4c.npy +04256520-955d633562dff06f843e991acd39f432.npy +02924116-e92f10218f66fcd64931a7929d89a2d3.npy +02773838-e73d23dbd069877f4da5feafe6f1c8fc.npy +03691459-27dfcf48220c9ce1c3554591513b53b7.npy +03691459-14a21eb927d89df31ef58b31c4ba0d15.npy +02691156-6adda4af6b2b7bf9f315217de00e37bb.npy +02933112-4e62d6e735b8bf2b90071898148dca0e.npy +03001627-9303d374253d8e7f377b9297f3055210.npy +02871439-9b958222d9673b664b3b9b23ddfcbc.npy +02958343-17457b1f42019702618e9d35559b7aa.npy +04468005-1738b29e7344f8447c44435d252fe26d.npy +04379243-11c192ef34f5dea0a1bc88a716ad63b2.npy +02828884-797d99a5ca291a2085fcf80cfce883fd.npy +03991062-40115670f786ed1a6d93e521f7fd48fb.npy +03001627-47f0e1452ea20e4856c07129c79effea.npy +04090263-bf22abe4fbab4acd91d13947d0d17396.npy +04256520-29bfdc7d14677c6b3d6d3c2fb78160fd.npy +03710193-24807a8b5a4d1f942e9bce9ba08f12e1.npy +03325088-75d1c36ff0af66eb76c18e71fd49c4dc.npy +03642806-76d74a604c1ddacd6093b210438ee0f7.npy +02992529-b69603be92146a161ad8041551e9d3c2.npy +03636649-cef0caa638ab9be03b1e8527d043af60.npy +04379243-270430ab9efb9d85c0f947750540fb22.npy +03761084-c5d13a109a61060c178e7d331e641179.npy +04379243-3f058be47b5d4cf353c1d159a8a8422.npy +04379243-c0b4b99b37cfed365143f38859a6efa4.npy +03001627-dcc892f77239ace06b2befe83a0efe39.npy +03001627-1b8c83552010440d490ad276cd2af3a4.npy +02958343-1eb3cb637ccffd14597505fd7d99b613.npy +04379243-2c06e66c7a66878c3bd24f986301745.npy +02958343-3a3d23c4d325252aaaafd94b9f216ef6.npy +02992529-5bb9020da1d3bdc260a9d7568d474ade.npy +02828884-3880be8744dc0ebaadab4c26397edfab.npy +04330267-f195aba51aa86b934e88996f84b82fe1.npy +04099429-24d392e5178630079f3b7552aff14b6f.npy +04379243-de9b2870157cdba6f83df7938e45b43c.npy +02691156-54f0d46b866c1f714d4cb1c2a5e48b7a.npy +04379243-bc351c5cb264d29e278d386bfa54545.npy +03325088-384ac965e52b16c5b0957d845ac33749.npy +04401088-4a7c0d263fa0cc119553267f4c8c48a8.npy +04379243-fe2f2b120d84ed909b896cf832106977.npy +04090263-eeb8c212c7fbf6871fe7d5784ec6d0eb.npy +04256520-e51d445efd61b1e4e1296b473bec7902.npy +03325088-de4c1e3e21d5202da7c60f6678573a4.npy +04379243-2b00c0cd6353e2fc52ed0af58ae88731.npy +03211117-79f3ccc203ed18cc2b09e302847180f5.npy +04090263-76dd6c8a2cf09887bbb7f70943d3cb52.npy +02691156-9cda097e69ef82beace5721ccacba16.npy +03001627-d5b909ad5d7c793aa16baf954c1d99bc.npy +04090263-ac13748ced7f9fca86b2bcefc261a7ea.npy +03467517-5dd9e0c35898183bfbeef84a1ff2df7f.npy +03261776-6ab05701a8124ac25ff75fdb62ec3433.npy +02958343-2401f097228fdc1348b30181b0729b3.npy +03001627-837ba605a4ab4a4f19fb4103277a6b93.npy +04379243-3ada04a73dd3fe98c520ac3fa0a4f674.npy +03991062-aa7d667a7b5c67642b151d8b52c53b90.npy +02691156-2066f1830765183544bb6b89d63deb6f.npy +04256520-d9d465cf1be1142a86114f7b6efc777a.npy +03001627-58ebbe670d03fb65cf19858fd1963d10.npy +03991062-2558fb8bedc4edcb1b78de62f6c48608.npy +03001627-8a845bb67ee8486d6199d6fe090be061.npy +04379243-517a4c16b7c5960bac2b62da1791c2b6.npy +03337140-a44d92a6431afe516d907bf61e189d9d.npy +04330267-2cb7486cd0d713894c324889334fe6fb.npy +02691156-5b3e534b2d022a9528be5258a76a8dcf.npy +03211117-cbf33a6fa0f21270fc88f15aa2f9c9d3.npy +04256520-1230d31e3a6cbf309cd431573238602d.npy +03001627-a1a34c1d45d47c371519c64630268dcd.npy +03001627-458356b9c5a8d7bd7cc86734cb2f5062.npy +04256520-719eb32ac85c77ac4e7bb85618505650.npy +02691156-94c4ade39534d1902c13e5b9ca0fc656.npy +03636649-8be191f7e61673b13e3ed2a572e608c1.npy +03046257-751c6f35fc0194785445e46058840642.npy +03001627-b1b11a70a19492fa5242f8291aafac22.npy +02958343-7492ced6cb6289c556de8db8652eec4e.npy +04256520-e78b5c9191f3007cd36a803949e62cea.npy +03593526-7c8fcf46c9d543be3087f84b199fd297.npy +04379243-f27a46a8dce3b811707cdefe012d0353.npy +02691156-ec8ba88cdead53f336dafa9b6763ef3f.npy +02876657-bd5f6815e92e5fd72389a54fb53b0765.npy +04379243-20cba21d7122fec4784a45ea6efa1d77.npy +02933112-8317fd220232e3be11fc2b865c2a185b.npy +04379243-f5529ea819c6e97decdeb21614063c36.npy +03001627-c9b0828029f0405c473f10e6caaeca56.npy +04256520-3550a44cffb1fe001acfe75c509b3399.npy +04330267-dbba6cbf758062ba89f60a4ba2e4e417.npy +04379243-7093c8218c88118b3c5f24f851caaab7.npy +03467517-bb3417d78a84a9ac579eb377e469ec49.npy +04379243-4786e3a9fc33024dfeec1f13d2353f3.npy +03001627-da443e90e376b024b0f7e9a1c9f6c90f.npy +03691459-ff9590ccc2613d6c332d76467c18dfde.npy +02691156-dc6a2bdc4c3e630a43bc71474ad05fbf.npy +04090263-858975ab8258845f230a4d129580843a.npy +03001627-fb00ea443c74c00617c72672c86a49.npy +02933112-21185c06b8eafd1229426a0f57e4d15e.npy +03624134-3dbda789bc59a5f99246ea0301684d80.npy +03642806-490245e63baf78fb1bf5877a865437f7.npy +02691156-4c880eae29fd97c1f9575f483c69ee5.npy +04379243-a6f19d6f3a6b3cce35c6c07cec6934c5.npy +02958343-43e48813760ad55875c67b3b1e763fcf.npy +04401088-4e8cb66f915fb5ac5fdc2445fe061736.npy +02808440-e4f9cc6d4b3e4bcaa26ee71c5a5a672.npy +04379243-5441f511736c03f9738e43095496b061.npy +03001627-6c36a5b107e83d331191025061735ea3.npy +02828884-9c7527d5d1fe9047f155d75bbf62b80.npy +03691459-c2007f762f6c3d9f51dabd6f23097818.npy +03001627-7db1b46aa2a337adf51f77a6d7299806.npy +02691156-61330ac001ced49f64801ad2940cdd5.npy +04379243-439ea10da7a148bb2f210d96281fe860.npy +02880940-b69e25e7ab9b829215b14098c484b7c1.npy +03001627-6c72077d968519bc13e020d985215e3.npy +03001627-47a45ce9fb219083411e8b42940aba04.npy +03593526-7de119e0eb48a11e3c8d0fdfb1cc2535.npy +04090263-45030c1a84e0c23d7ec95138ef83ef2f.npy +02992529-43b59b01866f23e6f8d380ef6d10e2a7.npy +02958343-ead6f85d2eaafab32aa8b7caea8a1807.npy +02747177-c77e8499be0ce1e04f3443b22038d340.npy +04379243-2a5f29019fea4513dc0970d34db41136.npy +03001627-32a9329c11b5c35d4b3c42e318f3affc.npy +02691156-9de5723b085c9dd8f4fb6842b3610149.npy +03636649-fc03629860dfd3608ecdcdc5181b3655.npy +04530566-377497ba926616fbfd7a80a80a3ebd45.npy +02691156-c1b5fd196374203d772a4b403daac29b.npy +04379243-866a07295aa3a8ea5804b7e86be64166.npy +03046257-cf0208d1c19e8313cc63543a91bdd558.npy +02924116-1b572b3e4503dcc2a71edfed1705a549.npy +02691156-c1262e16d330f7a0231e16e03ac422a0.npy +02871439-333a32cad481ef84ce438ccfc4d79b5.npy +03001627-ea91d70feb603421f74aae127b28c047.npy +02933112-636c4d449f17b6a8b47cc2471d9dd7e6.npy +03001627-a1e414f0380b7b9e1fc1bfd241d8d6a.npy +02691156-19f211f1dec98bbb82ea21d84574e1ef.npy +04330267-601c1c3d98596cc34a60c1a189046dd1.npy +02958343-691bf14434c590f212a6200f1680863.npy +03001627-69261d58214053d1e6c5cd45aa112726.npy +04090263-cf51da336a5414031b8fee1b14934c0e.npy +03325088-c9716fcd783c1cc178d17489f52f679.npy +03211117-529cf5ad63bd49c8ccbd9a558eb91a2f.npy +04379243-faf951210266013cbe9d845bb7506ca4.npy +02691156-2e235eafe787ad029a6e43b878d5b335.npy +03467517-abf0a261cd0d01512c6fb4acc0f83de6.npy +02958343-232a1bf61d6d80ffab0e638d7c0cfd7b.npy +02828884-3c7a0029ec98c965601104cd2d998272.npy +04379243-60014b37baab2a2fdcc3461f14d611f.npy +03001627-40bfad5f86a730b29f2349486c570dd4.npy +03001627-9b4d530487df4aa94b3c42e318f3affc.npy +04090263-1af21b8dcda98fa6f3817c125fa377ee.npy +03001627-ffd9387a533fe59e251990397636975f.npy +04090263-14a07147c6b74e9d914c738e92faad58.npy +02691156-bc8c26902e912b851a53b454324fd345.npy +04530566-b9bf493040c8b434f3e39f2e17005efc.npy +02958343-b4ea44416a06834af200a72c9245aee7.npy +04379243-1b7dd5d16aa6fdc1f716cef24b13c00.npy +02747177-819795e285ea031625ebd1cd0b422e32.npy +02933112-1919dec93dff59e0ed3ffec8035a48e8.npy +02828884-916a6ff06a128851ed98cca8f0ccd5f7.npy +03211117-559bdf7d41b538f6290d1211e69c442c.npy +02933112-60d8c707c5f8278e3c8d0fdfb1cc2535.npy +02924116-eebb08eb1a4918b75d71b28e8a5230b9.npy +03991062-7335b7a1eb1bb091bf949868a8099949.npy +02958343-e4d396067b97f3676dd84bc138e22252.npy +03001627-8f4d7de6fef55f99232ca089ddf0305.npy +04256520-7e832bc481a3335614038d588fd1342f.npy +03001627-3427a6029f253860450621b513a975bb.npy +03636649-50dec764276863a77933e36129e75649.npy +04379243-419412b927d11c7d8312881285c04cb3.npy +04379243-e0be4621b0ea9893593ebeeedbff73b.npy +04379243-f2b641d16cd8a3ed33473d0d0e8c464e.npy +02933112-1e694a1848b810ebc59350d819542ec7.npy +03001627-45214e3010f8c3ddafa9c337f30be0ab.npy +02924116-75720a82a5ee59c7f72d0267172e294a.npy +04401088-e8db0c85b07ac581d409d3400adf2d96.npy +03046257-fcdc11d9d040e18ae65235d5580cc3e0.npy +04379243-96de9fda13fa986d9cd431573238602d.npy +04379243-c0a143c5fd0048bbcd01aef15a146d7a.npy +02958343-2c3a3033d248d05851a95aaa6caba1d3.npy +02958343-db392da8d05ec4d4f6d01abc93dc7d8d.npy +03046257-6970ca7ec4463ff4224ee0743294f79.npy +04379243-50d8dde1973aa467427adc6587850b2e.npy +02958343-7e3349b2d3e833b0364d334d86d85d.npy +04530566-be8efba4b5c1cbfb94daa4565dd30535.npy +04530566-66fc4d3e245a643c4f7b88e5a2748214.npy +03467517-216b9ada62f817d3e407add7ece1b405.npy +04090263-b7ebbb8db6add885e5fd7320f47a8553.npy +02691156-25805c9f5b2812b6b7bd17e458d0dcb.npy +03691459-2686bb573a9bae79d34aabb2f31dae9e.npy +03467517-9262812345d784f846ce38f148ceb1a.npy +04379243-5334d237bafced4c3719086e0b4ab8be.npy +04379243-31a85a1a9bb22c3bf1e23636310b7e7a.npy +03211117-2967a5504d5aef38bb3914fb474ebce4.npy +04256520-b16913335a26e380d1a4117555fc7e56.npy +03467517-2358df8a325993942b996d5d44e09408.npy +03001627-b92bfb13727f6659e45ef4135c266a12.npy +04090263-9e6d1d06ae82ac106f21883e4b04581e.npy +03691459-d087ad474122e24d887e8faf8f33b0c5.npy +04530566-3b60a8a4d71e3f192063cebb14246130.npy +02691156-985e020b26adf663acd7e882b88d2b.npy +04401088-c33bc3be82441ea66934b554e5b8d4a4.npy +03001627-b0b75045d06201f9329df33f4ef71f97.npy +02933112-962d112db5d7c687e82effbd6750a761.npy +02828884-9b37a6d7c9f1800952dac0add839bf80.npy +03797390-6c04c2eac973936523c841f9d5051936.npy +03001627-c1841ecc1302f45be798c4323a137f09.npy +02747177-4d6b6d392ec6b5b4c69692992c7aeb.npy +03624134-9571186710287c09fdc15a59a3f1c1.npy +04256520-d7aa6e5b0c686fdee039576a17a0737d.npy +02876657-fda8d8820e4d166bd7134844380eaeb0.npy +03691459-ef71576ad5262c4ef398d0c5832df00e.npy +03001627-3d800711f41284b519fb4103277a6b93.npy +02691156-72aedca98ea4429c8ed4db287040dac1.npy +04256520-8fb75426dae65b66a12caf23554642ba.npy +03761084-da44863f40e720ea8a94168388287ad5.npy +04379243-c7feff682976809482db9fca4b68095.npy +04379243-e6da3e780a427429791f2019e8710746.npy +02691156-3255eb4c8ad868b3b378822897b79a81.npy +03593526-fc17a3cffc86bdcae37f5a622d383617.npy +04090263-e5de6a3be440fd1866a9b092716ff368.npy +03593526-6519a8929afa98739de171e0db680498.npy +03046257-b263bde194a2a0be8cc14b65ef8ab235.npy +02828884-ced678ceab87f6b6f4fb4dee5181bee.npy +04379243-327fcae0643a70d916768ffb6be40591.npy +03636649-6de220e49cf87c6bb15194162f658e87.npy +03325088-9d5eb12ed318891d2ccf9daeb92717bc.npy +03001627-b6305089d351329681dff5c2e57ad46e.npy +03928116-ffa3b87986a640b11c30b93bc2bc2c6e.npy +02958343-dd06b4149a6f876341ca08f10af9385b.npy +04004475-128c57ad8f366a09f16da3ba7941918d.npy +03593526-48c94c6283fa5566a4136492f17b9a59.npy +03211117-4e49873292196f02574b5684eaec43e9.npy +03691459-ea4215e0c4455737dd3b7710c385b572.npy +02691156-c022461863cacb39a2872fda285c0d5f.npy +03991062-b82574f7d98d653444c183864792bc2b.npy +02958343-618e8b78bfa803dab1bb46d2556ba67d.npy +03636649-55de711b4c86b86188e7662971dc736f.npy +04379243-2d38fa0a1b4f94981faebbdea6bd9be.npy +03513137-2aaea503ebc42ddfdfc54a7d3e3d4e77.npy +04090263-1eb186e0fc2dd979901b177556cd6c33.npy +04379243-7d5e1184ee0db5cebda5f96847fc5070.npy +03001627-5627a479e2e7373b11800282ad2afb09.npy +04090263-e3a673dd3db3fd2c282dd3b430ec2654.npy +02924116-4427bfc7a4223b8552470de2774d6099.npy +04379243-3d83fa746851500cba85f67361bdb32.npy +02828884-a2a83603f38cffbbd2b12aa6a0f050b3.npy +02933112-ad86354fb5faf1c98a4820926b2a786.npy +04379243-1bba52fa91ad1f9d7ff6ace05b36a5.npy +03991062-da8a38e1d0b6f4aedd3adf3090c701f7.npy +03207941-7d19e1db73ebfee26f893b5bc716a3fa.npy +03691459-913eb13149ceb59a75a3010d3ada28ba.npy +03211117-48b8290cb0dc0a6cc785f06f424b9d06.npy +03337140-4d993b6fe254ce2d4c3aee8e9d3a6ffa.npy +03001627-b63fb0d22a44ff698cbb8bac2032149c.npy +03691459-95db5c34357e2a81bbb94390080b5b78.npy +02828884-9b5dfec7d45eeca94c8c340ea700916e.npy +02958343-8e8da02ac0168a47ec5e3fe5c33367cf.npy +02933112-c184edddd3530a8161e1dc6d433ab6c3.npy +04379243-7269b683b73eb9a1aee34134dce9c534.npy +04379243-159964114c1991b37618b16b281bdf56.npy +02871439-795f3f8a01db10a6b6aae9c441c6e291.npy +04530566-8b92073eb06f0365e18960ef54b079a3.npy +03691459-f5c62c89e8fbb245ce6c2bd14b4c7ba4.npy +03046257-d6659d1e40745561b0a18b9f4533c663.npy +03991062-98a107d314d1b149148a76a78b10eb5d.npy +04379243-7dc6c6f96b77b7d3febad4f49b26ec52.npy +04401088-74aab120cfb4d88257de0221db0b9d32.npy +02880940-429a622eac559887bbe43d356df0e955.npy +02691156-ede14aa589c68280216b327569dd806e.npy +02958343-9a0365ab56ae57ffdf6ad3edb04a4bc5.npy +03001627-b5254b56addb692eb516c05d046e8e45.npy +03001627-bcea72fa334f593bb41b7625e8c42dfa.npy +03593526-8a970ddede52c604eec3bf885b5e46e.npy +04256520-7bfad524f6a550f6a6fee8e2140acec9.npy +04530566-60a1ffde62956a96e4723800c586d63.npy +03593526-a886fcd1a2b625208d1dabf86742ec3c.npy +02946921-38dd2a8d2c984e2b6c1cd53dbc9f7b8e.npy +02924116-1e161833a2e30e114b53951575fe6979.npy +02691156-d75a4d4d25863f5062747c704d78d4f8.npy +03624134-261ce6a51cdfa35e1021cd55d164c0ed.npy +02958343-3dddc113e114b64a63b716db3275cef8.npy +04256520-db851fe630734a8aee7d178666aae23d.npy +04379243-335858ca88e800c34897c77cbc788880.npy +04379243-4fe7555a7457c763db352b8394e172c8.npy +03513137-aba5ab07cb21bf4454631ce860fd196c.npy +02808440-805bb0974d261c98e98372688b8dcb7e.npy +02933112-3763bd1d86776ac397022448220c7d6a.npy +03691459-8171c9bdb75a10d9abdb18c1e87978be.npy +03797390-8b780e521c906eaf95a4f7ae0be930ac.npy +03325088-476aa340d2ac9973c36fb70296e45483.npy +04379243-f90bf59515aa8368e42c56c78fb88524.npy +03642806-9cd223dd78199526628b49aa3b6c49c1.npy +04379243-50b8f401a5e2f2f431358207d42bcb21.npy +04090263-b76c7921d0fba930dcfd889babf6a0d4.npy +03001627-3a141cf2f22fed0ffebad4f49b26ec52.npy +03001627-a94eb852d2137621b38821f893bc10f9.npy +03211117-e817263a3acf985ff6c7cc6dd504006d.npy +04379243-4f5719eaa2e58c9cedb0cb3987e137d0.npy +02808440-7b0f2735068568ef3af30a3946d92feb.npy +03797390-5c48d471200d2bf16e8a121e6886e18d.npy +04256520-2a07656f030d682536c2acd70c777ff0.npy +04530566-425ff664205d2a7f5c0be177939e290.npy +03001627-c3fabb74405368a8c5f0b5eeb41fa897.npy +04460130-d24729b45b9192b8f1390d726a8b3e99.npy +03001627-6a0bd5d9ec4567d9d42216b5daf41a39.npy +03761084-33aeb6c217d9cf7e178e7d331e641179.npy +03001627-566df2b6ad0abb3198d5fc0473d00a1c.npy +02828884-1acf34aa0cb8f06a19fb4103277a6b93.npy +02933112-484aac3c3f3ee4aadfcedefd655bc18c.npy +04225987-1510427efa80c92b11c7049de48f3618.npy +03636649-8522fb13bfa443d33cabd62faf4bd0f0.npy +03710193-edc6601caff93c375cdc413cece6d555.npy +04074963-f677657b2cd55f930d48ff455dd1223.npy +02958343-cf9e82b3235f62c949956811ccd3041.npy +04090263-5a2ce6338b4e399f0fea2ee98610322.npy +02691156-3f6c0034bb278de4f446f92b52bbd82a.npy +02828884-8ff9b4b57eb5a60daed1fc72009b42ac.npy +03624134-bbfd2df3edce576e1e652fa812161367.npy +02958343-425db95a3377f4d6e62a01eefce42a80.npy +03636649-3c39bff6acbb6060899bad344dc01f2f.npy +04379243-e7f1a77130bceb8d8ec45320afaa5d0a.npy +02691156-dba3ab64bab4ed3ed13ef00338ba8c52.npy +04379243-2519505d0cee2edff08984f51debc075.npy +04090263-6c7dec6bbd8ede62f0e1c0df18936d05.npy +03691459-8453a71333241062f1b584cbe791b374.npy +04256520-427c7655012b6cc5593ebeeedbff73b.npy +03636649-7c0e5f39eeaa5d6cef9b6f306f98b0e9.npy +03046257-6c010bbc4ec34296291d2d0d560233f4.npy +04256520-39ba41744345959256a9d1ce1d40376c.npy +03001627-77f5b356fa515f1f396bfe08dd5ca134.npy +02933112-98a1211469f6c6a7c7ac935603e09651.npy +04090263-41da6bb82abdc626a5aad165050e534c.npy +02691156-4ee48907120e261c3df16180af9974ee.npy +03001627-8a67fd47001e52414c350d7ea5fe2a3a.npy +04379243-e03cdcb83404b3c3951c1fffab4f5807.npy +03691459-61a4c1b213e7eb2b2633ff66beb9cf31.npy +03001627-c46eb7460be602b6bf80985a99195eb8.npy +02828884-e929c571972b954981faebbdea6bd9be.npy +03928116-c167f20548e40314468f5d32b3766d7a.npy +03001627-d0c287f11c6cc95012d6d1e9f6b5e761.npy +03636649-e9f5e9f6f8d54caae455de02837313a6.npy +03001627-3a74e3d5172ee94fdef1c01cbd4ae0c.npy +03001627-655102add1989c1064fad3c7b88e6060.npy +02992529-831d6d9118e1a2fb71f2e8f64dc1f509.npy +04379243-41d18d4668939ced3a8e4d3441f2dd18.npy +04530566-ec3e0694850f1a923b7cda02ebfc1f62.npy +04401088-7772938405ac56c1b6d41c42f7ade8c8.npy +03593526-9c06b546a29ccb2f2c27670a86683659.npy +03001627-58b7e2dd5eb73b70dc742bd7c6fd1b27.npy +03001627-ecbb4e4665c7fbb45613f5c2df1029a.npy +04460130-f01c3ee2b1210cafdb3180683be7ca4f.npy +04379243-5e52ffe27434ff446875e2781cdd26.npy +03001627-3d3b7f63f5525b1ae37f5a622d383617.npy +04379243-c8520226f277a6af77cb37b8e3bb5ba2.npy +03001627-a0421aff56cad16790a9ce3e4b15521e.npy +02691156-dc8d9003cde43b66c8727b27ee96a4b7.npy +04256520-ac36eabbb3b405d3473f10e6caaeca56.npy +03001627-24c0fc01144790be305e886266e302e1.npy +04090263-af0bf9c4b6397877cb88c9db6e396994.npy +04379243-15c833aeea88fb19f428c5b66db689e3.npy +02992529-f66d8ca1f6b259de2a9eb0f146e94477.npy +04379243-201e927f4979bed6febad4f49b26ec52.npy +04401088-1bb65c38e6b563d919bade123d9b1a21.npy +02876657-81bf26a14c2dda38c19359cf6b65431e.npy +02933112-d6242003931d0a27824662341ce2b233.npy +03467517-265009e163bf5c6f69da8e7f9a803d12.npy +04379243-cf3270a5af169626efa153ac02df4ca3.npy +02933112-23637357c4e5efb653c80c0a3ef7382.npy +03948459-be4eb62282269fa3d65e0fc33127a486.npy +04090263-13dd392ca784cab79adbbc95db428a81.npy +02933112-474fb0ff79e036b0820018801b237b3d.npy +02691156-96291ea39a5c6eda203936772104a82d.npy +04379243-613c706879ee39c9132c018af3949fe.npy +04379243-f1858f78989891172027cee422df2aa3.npy +03467517-bccc58865720ad5082b2bb742a29db8.npy +04379243-2cec40de07b468661aa47689117a61e1.npy +03467517-e0a4691bb3d3cb47e33462de7b4c569b.npy +02876657-3c6d6ff143483efaebb19cf38af396e6.npy +04379243-c9cda6b019153ded8cbb8bac2032149c.npy +03636649-8935987356200f8d84f9e9db2fdf33bb.npy +04379243-ce2d3e0b58bb1244700ade95b2f08044.npy +04379243-8aac86cf8c72a375dcc7ddfa72357b1.npy +02691156-bb26678e5faaed16300ca77569ad3884.npy +03001627-300d6a7505f24959492d9da2668ec34c.npy +04530566-9a8c57edf56dff168a76a2dc0f9ed02b.npy +03710193-63556b1cf7309010c10acf2ba78060f3.npy +03001627-be745a383ceccfe453fa79783efbc3bf.npy +02958343-61348ed95aac6b3799cbdd78ced2546.npy +04379243-75b308ba45762ad499e8bf807e902261.npy +03337140-1b400773151aa9d64c3aee8e9d3a6ffa.npy +03991062-6e8d1c49e9d239651e70ffb3c83b7281.npy +03691459-cb25ea4938c1d31a1a5a6c4a1d8120d4.npy +02992529-69e45e401c1d05b767d8789d3a6519d0.npy +03642806-fc9dc2b33ac96e41e2dc67b821479cc4.npy +03467517-b234a7ad4a2fd1f2352e5d4d2615db5b.npy +02691156-18f5265d553d72fb6b7bd17e458d0dcb.npy +02958343-368c8d09c88404999be54f79e28fa49d.npy +03001627-63e184952df0f3698f5bccb3529a48d.npy +04256520-2814c27c1ac5370a30eeafee78afcff2.npy +02691156-f9fc7fc23e62986fef6c510e24348d3b.npy +03691459-a0f84cab1fa73358078e785d09667d5.npy +02958343-9472d19187081c62fce798408476568b.npy +03211117-b7315a68691210ebb25884c97d065d99.npy +04379243-6bdc37f729eef70d18706cd9c51d6358.npy +03948459-f249fdbb14d6c86087302680c759eef4.npy +03467517-1a680e3308f2aac544b2fa2cac0778f5.npy +04379243-d1950f4d38df72f59d297e74104d3ac3.npy +03325088-19e85eac24c2bac9c36fb70296e45483.npy +03691459-43f49627bbea5c39a052db10ff2f17aa.npy +02933112-2018d0713d4c22df480fa521a9c7198a.npy +04256520-f42ca56e450c3258b4602b4f31d3d1c0.npy +04256520-28cc5741095e9754cc9651014a82e2b9.npy +04090263-8ba99099a99012c77ec95138ef83ef2f.npy +04379243-62d18b3f3c520ddb37251258858a7a58.npy +03001627-63d92bf1f175a75a25ffbad401072b4d.npy +04074963-cc846e66cbfe697bffb5024c146ec04e.npy +04530566-73343fd92c286e80c570a3d482a3f588.npy +03001627-f3f31db17715ee0c327289c00b6dc9ca.npy +04379243-38310f3d796ac0b56bdcd672c2b17215.npy +04256520-abd8b30650ebda9c14038d588fd1342f.npy +02828884-6b894c1c57ba921c98d10ca8df5ecbe7.npy +02691156-209e9845a482333c77c06b43df2749d.npy +03001627-f645f79d47e2df0f7dca29e186afcbcf.npy +03325088-415b9606f972c2a876c18e71fd49c4dc.npy +03467517-6837886c1c4553ad93f0194265a9746c.npy +04256520-eb568f8bbfee977c6b4fe272da0db543.npy +04379243-a0aeb5a735e15171f15e29f2d0bc457.npy +03991062-6ebaa1c6357a05b33cc55b40df64ab9f.npy +04379243-3a466eacf622b3a13a5badb049bb270.npy +04379243-343b2351e2605a075445e46058840642.npy +02958343-f21188e5f1a6468050bb0437668bebb7.npy +04256520-2fb350e338cc61521b17743c18fb63dc.npy +03325088-4fbb6add41adf7eb843f813f752a5e35.npy +03001627-fb71fc8021c89cf342d8a8c5af8997e8.npy +03211117-bb2639fdd7ee85202f58405e4baaa2ed.npy +03001627-f4c6c927df8edb62c7623e33dc7256f2.npy +02691156-a1b95d2e1264f6bd66ccbd11a6ef0f68.npy +02942699-fe669947912103aede650492e45fb14f.npy +03624134-e98bc872371c852e15b040d25222e627.npy +02691156-d6db0815d8fbaad621967ef97204d18.npy +03001627-f0ca6f9383ee9aae517376ab44a447e5.npy +03636649-955143d7f0b5c70fef76898f881b76a.npy +03642806-9e901676eeb65f352b1c9d869bc37167.npy +02924116-a8dde04ca72c5bdd6ca2b6e5474aad11.npy +03001627-284463280e6a4d003719086e0b4ab8be.npy +04379243-b26f4075b45a3a473c75ff89cc8b70a1.npy +04379243-9a3194d78a592039a95110eea24f99c6.npy +04256520-f693bb3178c80d7f1783a44a88d6274.npy +04401088-c202335fd3dccf9d45e2a4e5729b970d.npy +03642806-6b4b8ff6b859b262169650f5be5e669b.npy +02747177-10839d0dc35c94fcf4fb4dee5181bee.npy +03001627-bfe64c93bf5c3858c4f202fffc87396.npy +03211117-ab8af4bf679eb599ffb8194c06b9bc3c.npy +04379243-8ed0ac779ec4bbc9beedb4c8fd29e2d1.npy +04530566-80c6a14accb189a9c2c2c81e2232aa95.npy +03001627-d9bf326d8ae7a430a5a7dec3df261ad1.npy +02933112-f3bc5eb543bd852bb7ea82317702e856.npy +03001627-8c91c7c19c20bc4cf130e9cdbbb1cf40.npy +04379243-b7c36f0afe9f16655b1ab0bf4891d200.npy +02992529-6ff995a8e9faa6e83e43be0b542efff8.npy +04530566-1d2aa0bcc9ade276a70cfb3232f40c6.npy +02876657-c46bfae78beaa4a7988abef1fd117e7.npy +04090263-605cfb5fcdef75539e6170029f747a35.npy +04090263-fbc88753c7697b825e4f1f524019c.npy +03636649-451fe793f6e8fc29276206fae5d3c473.npy +04379243-d7792a9c16aaf16d98e0d1738edd4f19.npy +03001627-27ef7dafe404bf424e83b37723b7fdca.npy +03001627-6cfc437d8ec6ce7413d48601aed73697.npy +03211117-2b2204a683efead6dfb0e2d6f3832f45.npy +04530566-1fb07d5bf3421a46e2b83b21c9537e1b.npy +03001627-ce159c7d983d74136ba14bfd91a75020.npy +03001627-eb32fa1ae8069d0998e0d1738edd4f19.npy +02691156-dbc521b1d4c2d308303d346f4be7d4f.npy +04379243-2bd915e46c4b08e3f2cd47be0243fcd2.npy +04004475-9504267500abe76c510a6e7bd9c355b3.npy +02958343-f1b928427f5a3a7fc6d5ebddbbbc39f.npy +04379243-c33f90746a3573878b39b912ed4a7b59.npy +04256520-3561da3d136b4deba023804ba421cf6b.npy +04256520-5b3b26c9ec974a1cdef028ff6a07adf4.npy +03691459-161de75c52763afade3a1fb6044fe536.npy +02933112-641e64902bb9f6a4aaca4b071fcc002c.npy +02691156-5a3344eee5b27e670da4e1131665650.npy +03001627-44f6f1cadf8e788f90a9ce3e4b15521e.npy +04256520-8b82330caa9b1a514038d588fd1342f.npy +02924116-b434422365ab5b9df54effbbed1a418b.npy +03624134-2b4aa9edf0e15a6b1e00d60b0f9cc70.npy +04379243-24d1d32aa33c38716a97150bb2a72733.npy +03001627-2e0beb3b6927a2b7e45ef4135c266a12.npy +03001627-3f194ed2680ac0f4f875094dbf5fec47.npy +02828884-2ae355c406b7204e8c5da39cd0403824.npy +02933112-7650fd61f3a162397ee0cb5488055ac.npy +03001627-6684ddb2b7acc11e975d41ba8f947ac.npy +04379243-4c49252bedda66402c2d6a2f47ceb5ce.npy +04530566-61053086346058bd2b477561b6a06f5c.npy +02828884-4aa87768e4e9c7639f7aad887e9e880f.npy +03001627-f0b50b64918ef41b990561fc34164364.npy +03991062-f61a766cd84d46a5e88c1d6fc3580355.npy +02924116-a10b42b69a8caa5b616d27151166e25f.npy +03991062-a1d2ddc8fdcc9f63adbcc9ee28cee4cb.npy +02933112-4f9b95af6720c7fc11fc2b865c2a185b.npy +04090263-3f9522f1af5597cbf0fea2ee98610322.npy +02691156-eefb4a1fcc2ca4d8894e22af7ae821f8.npy +03001627-11d9817e65d7ead6b87028a4b477349f.npy +04090263-fbda020053554eeceab5ee569c9de1b1.npy +04379243-c7778ca8dabfc6809856fa70a578baeb.npy +02992529-a3193340929f4bdd146def56c5fc9b3a.npy +04401088-fa3f5a6c21c56ef7e85fd905d1f6c116.npy +02958343-4471c286051d2bb94da8bffed051ff6a.npy +03467517-c7f501f73e11ee3352e5d4d2615db5b.npy +04090263-dbdf82759d3a0011df6f54267ea02d3c.npy +04530566-5295994daf6e427dbec3353c29751fdf.npy +03691459-6d75b6211f3bf8dca999ad3d6fc50304.npy +04401088-338c3f116cd39022a40276c99b77cde3.npy +03001627-308f0ebcbcdad58119fb4103277a6b93.npy +03001627-d5e9eb9dbf9d30073321831d2245cf06.npy +03001627-181b65afaeca2ee1a6536c847a708e24.npy +02808440-5a79d517ab366c52ccd0340812259a39.npy +03928116-b6272c4596bb32dd732e279d31bf9790.npy +04379243-9df064dd2a0f58a1d0176f9a144100cd.npy +02808440-b671a193d0397ad554d7082b34825ef0.npy +04379243-3c5048910fe8919ed810b14a81e12eca.npy +03325088-faec75b6043eb5ee4e09ebaf49b0cb2f.npy +03001627-f53cba4a288db2d58e1400f6db70a939.npy +02808440-b43b17f0378ed699ff1dc6e98c2e01fa.npy +02958343-94cfcfb74e246f938acb0ff76f4aec7d.npy +03636649-748983e71880720852ac619cbeedfc0.npy +03001627-10d174a00639990492d9da2668ec34c.npy +03001627-341e24df542e0676d42b9650f19dd425.npy +03001627-6190eb8be0f39ad782e3bf439621ac4d.npy +02808440-74de09e85976da12a13787f910fef0e3.npy +02828884-b9fb64100372235adbbc9440457e303e.npy +02828884-12b3daecfb0eb7d2056b4bd5d870b47.npy +03991062-fa894d811206c54dfc5eb16dbbadf7b0.npy +03790512-53d6f04450a85fe9ca547803ba354ce.npy +03467517-493df075787dc0f63ac61a2f8346a8f.npy +04256520-5f93127875373b8657f15fc9385a8a01.npy +03001627-c9dc5d85ea3bf4d8a1088e4f586b1246.npy +03001627-e6408c4be8e6502837a346dba83c013b.npy +02958343-3a46c9b9e8b18d6a61c6c61410fc904b.npy +03636649-77a5a12147a6624d786810c22b062a88.npy +03691459-5222c43f267d9f313129bd51bf061fac.npy +03593526-447730fef97d1f5a89035c25f0dfeb63.npy +04090263-8571fdae210bfd6612b38b1d99376c0b.npy +04379243-4e784e440912c48819fb4103277a6b93.npy +02958343-84394f62a86ddab875c67b3b1e763fcf.npy +04090263-951b61886488dd94d0b636a2d5e450e4.npy +02691156-bf124ddeb1189a3cb312af71146176c8.npy +03467517-6d546f8dd90259d62d4ead5a1be351b7.npy +03593526-ac95989d0e196b4a98d5fc0473d00a1c.npy +04530566-82ff35912d0a143a4e2501f4797d0851.npy +03636649-4610f7cdf3923b05cea97147b08cd8b.npy +03642806-d3606fa80e46f834562d7644f5df59b3.npy +04379243-b7621e8afb9e7b18890992ddacc04113.npy +04401088-b307961888415ab88ec5d235d7e81cc6.npy +02958343-26569f96aa6c4ed880af23b535873bb9.npy +02992529-3d1d0255e2163917f4ad1770263e7f39.npy +03001627-49c955a80749d2e1a5ffdf44ff86b795.npy +02691156-b27de883a83409a86bd2a0f0614d73d.npy +03001627-b5833d19f6fbd9a78c67f98c135b5710.npy +03325088-b3271d0ad091e15ec36fb70296e45483.npy +03636649-faa4b839db01b86fcb8d8c6d4df8143.npy +04256520-66d4f7c3c9018c9c4d3ac4ef5709159c.npy +04401088-bc27ec84fdfa912437ab6ee77f8c5e9e.npy +02933112-ba6599d00e879e11c59350d819542ec7.npy +04379243-795d4213e1dac276f9814818e8ac1c35.npy +03636649-d7760d5f9e1e6a622cd2160e449d45ae.npy +02924116-19242c27a28f09f141cefd10ce5d6cc0.npy +02958343-996354bbe7baa2b2f24437126510c3c7.npy +03046257-a67b32ac05ac3c965ef99326865249b8.npy +04379243-a886752590af36549e726e922f49b373.npy +03624134-5152ec5d2de585ec77b7d0d4764c121d.npy +03325088-a24f6e1d173f61885646c94351c07f35.npy +02691156-37b1f7f02c4b87dbca8607f540cc62ba.npy +04256520-e80bb04a59bd72691b17743c18fb63dc.npy +02691156-7805239ad1e40e07c69d7040c52664c5.npy +02691156-900771de03746670ca8607f540cc62ba.npy +02691156-f16381a160f20bc4a3b534252984039.npy +03001627-fdf0fd3b18066cd7e8b2b8dc0c816caf.npy +04379243-d77f7643e6e34ac91933ffef19678834.npy +02958343-472f62cb87c3f1606e04fb225ca92772.npy +03642806-9d48ab8c41174e60888cad7f6c0e6001.npy +04090263-70db17ecfddd51183554ccf8c30febe7.npy +03467517-15847850d132460f1fb05d58f51ec4fa.npy +03636649-a5b394e2c98f6233636c7e486232cac1.npy +03636649-c9eca1a946d5c74930259ca79b88bb0.npy +03211117-481a1dfe44babb3892b08e504d6ff5ca.npy +02828884-6c5b4a90068a6b511fcbd85b6ac8926a.npy +04330267-fd4201033847644d74c60db5b05c353c.npy +04379243-b5bc21c92dc997cb7209833c7512d6a2.npy +03001627-aa154024474ad7d138a720835dbeef20.npy +03948459-e017cf5dac1e39b013d74211a209ce.npy +03001627-a4b32d26e0962bf74a4ab00b9639232.npy +03001627-3190b19c1ae0aff9c5ff3a5f34406751.npy +04379243-ac440171fe3edf2a5284eac239212f2d.npy +02691156-81e6b629264dad5daf2c6c19cc41708a.npy +03046257-5aab22188aff5a9ecd124d563222b065.npy +02828884-b2fa26eb323ee7e3697079d6fa35f34.npy +02691156-54d49185bcda732a91e8833d3c500d73.npy +02876657-ca210c6696357f98e8ec08b84f068b50.npy +04256520-8892a081230c9e0557b8f616df7adf9a.npy +04468005-f46601730530a00e96cd7d9555234e5.npy +04090263-97e6439ba7e703dcd7d3985b6fde9645.npy +03001627-6aeaf646d526b41025a1c5ed6eeac95c.npy +03991062-3487ce3dc7f16ab15eeb207be0544bf9.npy +04401088-f928f74ed34e46c4b5ce02cb8ffbdc86.npy +02828884-a58e45ec5204f09559cbde03ded257fd.npy +02871439-750ba8feafceba921933ffef19678834.npy +02992529-3488722618d61cacd5b6fb666fe071d7.npy +03001627-597f2b2153af0c544aabcf2a7cb640f9.npy +04090263-da478adc6169bf2b34cef5923891e520.npy +02691156-dd5310819d4f16d7b9fc567905a4b292.npy +02958343-9de10b4469cdc435afe1d4530f4c6e24.npy +04401088-ca2e71c5e101797fa524f6bfc21eae12.npy +02958343-eface8341d001e9ceb01ae4a4788bd4f.npy +04256520-4f17918826b64fc8d5cba62773b8025b.npy +02958343-fd98badd65df71f5abfee5fef2dd81c8.npy +02691156-c18b1ed6e935b11bca8607f540cc62ba.npy +03790512-2610c94869f2456c3630e1f3568e4cec.npy +02691156-5c7729a3c482d77542c20743f866e1a6.npy +04256520-2780834da1be89d1f51f77a6d7299806.npy +02958343-1137cd58d6a45c6659a47b1880958de9.npy +02691156-92ffaa5ebef3c4025d85b5c95b248fc3.npy +04379243-82a1545cc0b3227ede650492e45fb14f.npy +03001627-36d314f3b118caa9bb557fc9202b7772.npy +03642806-9bfb4fcfe4fc903ca1fa797bebd1cbce.npy +03636649-baffbaa9a9338f331735ea0e092a805a.npy +04530566-6cf0d9cb4e2d607856f77b6bc6731cda.npy +02747177-94901779bc2359adcb2a965e75be701c.npy +03948459-9a90f323edc8c30f54e702cd89ce6f04.npy +03467517-23e9190aa371509820f1bd6cc69c7b.npy +03001627-276a4e184b9d71c4d838ae16242881dc.npy +04554684-bcf112d7f50c222685842deebe63f964.npy +04379243-21ca4d36a0f6fa69b937d98d58545fa.npy +04256520-4d5efa4209fc3c126c92f284160734ae.npy +03001627-20b8c6959784f2da83b763ebf4ad2b38.npy +02880940-879a5c740b25ef5c7a88a2ad67bfd073.npy +04401088-d659d98d384e2c37e405d2e0f546cab.npy +03636649-d00391a3bec2a9456a44fdd49dec8069.npy +04256520-5b702274926a8c433be1d0c32f5added.npy +03001627-5a94a4638e8d548cf7628281ecb18112.npy +04256520-221153f680f3ef015761a0b53ed37cec.npy +03636649-8a9ef07176e60ceffcb8d8c6d4df8143.npy +02828884-9c8aba47e37b1eff155d75bbf62b80.npy +02843684-cfa3e202c9b73e63a08977deec57f060.npy +03001627-469597794b28bb2bae5a95f4529b204a.npy +02691156-a18f4e4c291761fa7cebb3dd777c66be.npy +03001627-6f7a337878543c07c3bd24f986301745.npy +03636649-447a8ab0523dde411936a2870d820ad3.npy +04379243-3e4434c7714ebf307ac0fae7c37e01a7.npy +03991062-e7571eb148c46f16cb2a965e75be701c.npy +02691156-8f9fe8d7df1af4e057240bc6888ed016.npy +04090263-38fa7b145b3be7fdb4cdad9a5bf52dd5.npy +04090263-5e4bd1ed44830fb147e5d4c250a3c98.npy +03467517-58264c7b174a7cfdd57700c05b1862d8.npy +04256520-b7b15c6728478971bafac5c6f2fdd4fd.npy +03991062-6bf575f4fb9dabe278634ef2c5fdc560.npy +02691156-213004db08a787a466cf1b4a8fc3914e.npy +03636649-f4e1a4032b1686cec35131da26f8061a.npy +03636649-eb8da4f4245496c57f1cdfc0a8f38f2e.npy +03211117-dca7417eaa143de13ccf3d40fbcf475f.npy +02958343-2ecbacde09270d49cbf57aaa2ef6598c.npy +04379243-a814fbd363007fcfd93cf5f5bfd78ab4.npy +04530566-dbe05209a14fca8fdf72e713dd4f492a.npy +04090263-5eed8cd506081459ed6071560148e6eb.npy +02747177-28d07148048431d4ad5067eac75a07f7.npy +02828884-3b412429257bc1c34e437e844fb32a1e.npy +04379243-8c3e8ef43fdacf68230ea05136ea3925.npy +02691156-d70d648947c65b1eca8607f540cc62ba.npy +03001627-4179c276ee8dacfc8cbd400aa99bee96.npy +02747177-66d96d2428184442ba6cf6cbb9f4c2bb.npy +03001627-123b44b99e48eccb6960dc525de2f934.npy +02691156-f0fb27f3a597838feb1a0518c224975f.npy +03991062-b0bac7f86d4a184bffab4d6f10fa1d97.npy +03001627-35d2e2a050336b78dbca69f936e89647.npy +03001627-5bfee410a492af4f65ba78ad9601cf1b.npy +03710193-4b41dbd95a68067b71c1364ca3ac2195.npy +04256520-6ff38c09b9ab4dfd712f5f94eaf97217.npy +03636649-cb614975be6370dcb6b7592323488fab.npy +03001627-2bc587e0b4c0a0aa5a99858ad1805187.npy +02691156-fad346b02d91348bbbf3143b1cb6076a.npy +03467517-272d3447422afbc05389be63fb12cc36.npy +04379243-ee7e37046c26168dc2fd07f66cbad0f7.npy +04530566-d3043fff20dad5c41dc762869682f4f.npy +04256520-6afbcbdc7ab9357270db6230313d3ce.npy +02747177-e2276eb0322d1885cb2a965e75be701c.npy +03948459-345179cdbb6ac9da4dd752ddde80fb1.npy +03467517-671cdf7d555433fe94c23358bbce964a.npy +02828884-ea96a04c68b969c5c35f34f09f11667.npy +04379243-e7045bfa00de20a39a0d3e7e907e5b53.npy +03790512-5e43289edf360d01e937abf44800029d.npy +04256520-1ce97f222c9caeac14038d588fd1342f.npy +02992529-aabbfc7463d49368419fdfebc874eb8f.npy +02958343-a83c45069b2925efa7e7e5ea49ad8e45.npy +03211117-a03ff904fbcf341ce333e1b65ebab960.npy +04379243-53b815fbd98e6ed237be8761f2d10359.npy +04379243-2cef3d2d545f4a22b305a938e0ed1b48.npy +02924116-80cb1106b1f553669ccc82ba1c8f035f.npy +02958343-6a348343b90f8f06a78cb4f1b66f009e.npy +03001627-a8d357344e421ff21e12bb4aebfe8421.npy +04330267-4bad13c2b787299241965be83b7745a.npy +02992529-5fefcb474b6dca4b23b380c931ece1e8.npy +02691156-5fcc974627fb15fbd1491f61ed5cc034.npy +04530566-65c55828d88fd02da08632bc2f6881eb.npy +03991062-ed220bdfa852f00ba2c59a4d90e63212.npy +03001627-92b332233da033e71d022067655f6c16.npy +04379243-ad09eb0cb78bc62238279ad3a29524b2.npy +02747177-39733528663b8ffbad5067eac75a07f7.npy +02958343-911d8dad65dd79948e35db9103756ad5.npy +03691459-5dd29010575d36ea73e1b2d018c0512.npy +04530566-48a02e067f83c803473f10e6caaeca56.npy +04379243-62a0d0647476f5e5f8ece882ca124c40.npy +03001627-3de9797fbf88fc35d97fd0ea4791ae93.npy +02691156-c85e3f6c572581de7d3b11085e75c7ad.npy +03001627-cf1e9c2ae3309c65d7bb55f118ea0541.npy +04090263-dea853cf0b776f7dbc6e84bc30e573cd.npy +04379243-8e6254609ffacf233e5f17778b45d37e.npy +03001627-587d174c5f2b19c1d7e48afa5cc5db41.npy +04379243-1d8536c4e1b1b8eec5ae767f471fad27.npy +04530566-ee0e9bd4c375f1e76c07231ab3c62b82.npy +04090263-8fedf1a088427ea8ca3e540900266737.npy +04460130-3f95f49a3c400e9eebde864f704d194b.npy +04379243-d6064ca673a721ee44175b4dddf5be08.npy +02876657-726a6ce68bcb4b2d14513156cf2b8d0d.npy +03001627-f1a5a9aec0b63b91f487e71bd57b6e0c.npy +04379243-b20105f74c7a469647839bae1bc65257.npy +02933112-114b810af4a847ca99dd23ec22c4943b.npy +02828884-5e1ef1b63216952dd2b12aa6a0f050b3.npy +03001627-6b385a32489bab4abbc7a6acbd8f058b.npy +03636649-f9259d31df38bd5decd204cd7180226d.npy +02691156-95d0f4440a694e4a203936772104a82d.npy +04379243-bdf7606e8d493149664b3b9b23ddfcbc.npy +03691459-1ca17d2cadd47286c066b9622c005c53.npy +03001627-eeebe3fe14ee4d3aebefe6b1d594ad2e.npy +02958343-a2d50ee31621c3e059139efcde1fedcb.npy +03001627-8e4269ac16e13433d701c68e1045b606.npy +04530566-63c241d90e86ddb5a70cfb3232f40c6.npy +04379243-18d29165fc26330467903707764646db.npy +02933112-aa722d165b5ede74f8832716537767a4.npy +03948459-b3ea2d0331ec9ec650544cd7fa263944.npy +04256520-d58a2c86b9b71f6bef4e42d70375aed8.npy +04379243-f46f68598988b922eede8c01bbe6592b.npy +03467517-86bb8f9fbcf5fc20bc4ac3caf16ef65.npy +02691156-1c87b854cceb778615aa5b227c027ee0.npy +02828884-9683f5ef9e032a8aad5067eac75a07f7.npy +03636649-3cd21b83cf709f1829a42a0444436860.npy +03046257-5147d0b10721d430f51f77a6d7299806.npy +03691459-475853b0ac6bec73eb752889d5199f9f.npy +02691156-18666bda4244d22ca7aff2c3136e8e59.npy +03211117-2e5b9f616a0805dc3704a45f4027ebcb.npy +03593526-1a619680edc5c461a95e4741ba1b4acf.npy +02691156-77dfe229aa38e70b3fdf1b3b0fe86dff.npy +04379243-d2a3193796284084e8775b281dde57f.npy +04099429-863f387309a7c684bf88e92fc4e43a8d.npy +03636649-437482f4d187d43893202bf99dddc268.npy +02691156-ba37c8ef604b675be1873a3963e0d14.npy +04379243-c8cd7f01dd79bff03b92b6b9488ceadd.npy +03691459-e1b3bb54b9855f12d88a3e0e92891ad5.npy +04379243-1f24b9a75606239466e24bbfdb446f55.npy +02747177-2343794f942a698cb6c43a5634bf2724.npy +04090263-4a56ba0b85af56703bbe4035b770f62b.npy +04379243-7e1c4bdfbf19aa22d3cf0d40743efc0b.npy +03325088-a3999e8953b3274ab362845c6edb57fc.npy +02871439-27dd0e22a3151fbbd8d04e687db9eb6b.npy +02828884-4651f5b75533042283bc207d8a5912e3.npy +03001627-f1cb7ac166e7f23fd9d3572bbd9cf789.npy +02828884-ef1a728572967942ad5067eac75a07f7.npy +04256520-cf651c9562d9267032a526e2e9a7e9ae.npy +04256520-3b15020aeaf67cd5b085db76290ca220.npy +04379243-efbf0d75648b7c7d5792b99b8245d225.npy +02933112-b12c3a046c326ca1d9b228d02c3319a3.npy +04379243-f0a7dba4e3c7c1e4ffa178ce1c2c6b13.npy +03211117-115cf7354bf5926331067bcb59115bdc.npy +03001627-8d4efa9893f7e49b3a85b56ecd01e269.npy +03001627-b7af84a7e76dfb59b04cb542e2c50eb4.npy +03636649-58c49450594bef2afcb8d8c6d4df8143.npy +02691156-ba1358d41ef026fbb87697d3904b168b.npy +03046257-67e0ff4c52bea7ce61cfc645a8f27696.npy +02924116-3a46aeed35093d3d2ab2c6d327d62fed.npy +02691156-68537bfb054ee3802ffb52751fee2c0d.npy +04090263-c36992c1accaeba6803b54e9738b20a6.npy +03001627-4ae645f3b724a7dcb83ea6cf8ac00397.npy +04090263-a7de37ac9f6fd8c4d6e401b0db4905ed.npy +04256520-adfda3aefb86478319fb4103277a6b93.npy +03001627-3ef60b4e28c22b3bc7dd78af359f0fc6.npy +02992529-3d5487efc1d3442ce81f45a785365b0f.npy +04379243-5d3d902051858e56ed1397afd2317e5b.npy +02924116-b01aab6f2de05d1e52470de2774d6099.npy +04256520-5161e139d0a58822a773e2c829d72a13.npy +04379243-5826f35dcc58f9206025dd3b37729bd3.npy +04530566-28db3989d5ef36e9c3691cf0253958f4.npy +03001627-bd0cdf88217ac15af9e0f15cc1c070db.npy +03325088-a447d1bd3dea48ae54d7082b34825ef0.npy +03001627-a7d178cd0dc051f25fceaa39a8353bde.npy +04401088-8ede5d8c00e10a2ff35554ebed2bf2.npy +02828884-b53a4b74b0c898ab615925cde06141be.npy +02691156-754d9b0f12e6c6104af5b53e1d2ec5b6.npy +04530566-91c1e885c5cb2ace3c01fd24534f394d.npy +04256520-d8c748ced5e5f2cc7e3820d17093b7c2.npy +03001627-2972fd770304663cb3d180f4523082e1.npy +03211117-5282a5a7482b317ae81a51f0a8c4cae1.npy +02691156-8a674703723db7a390baeef8ba5b93e5.npy +03001627-3f0b0feb58008a663ec7ad443e0ae81e.npy +04379243-d9addbc9e91eb0efb1b6b0c5ddacb607.npy +03001627-62fb28b9a362fa0adf8d3197c3f0b3a6.npy +03790512-45009f5fa4cb295e52ee90e577613070.npy +03691459-4e3669ef40de1b3b465b32805167c435.npy +03467517-173e4f1824f7b9fa93f0194265a9746c.npy +02958343-a13fa4cf0dfdd5b58f7f0d2c9c57704b.npy +04379243-93d4c1821a6eccea462118aaf3f93639.npy +02871439-e6b90d7b634f03e0f65dfeec70ceaaec.npy +03636649-fdcee8d924f3a8404d01f72347a40cbf.npy +04379243-24b997004163af21851a116903680096.npy +03337140-e20a4db61eb83e2cac27179ae57fd682.npy +02958343-afa0436d9cb1b19ec8c241cb24f7e0ac.npy +03636649-ae5a1b5c8b93cdf4899bad344dc01f2f.npy +03797390-c2eacc521dd65bf7a1c742bb4ffef210.npy +02933112-5584ec27aa657c65ad329b1997e89fc7.npy +02958343-3163c8037d5782365688db6590f826c8.npy +04379243-4d85392c3233b2b8d3299846d5c00f08.npy +02691156-9196f5a53aa7756687bac2e90bbe10e8.npy +02828884-49704546a313b40781e404e60978a1dc.npy +03001627-1cad298ed14e60f866e6ad37fee011e.npy +03001627-2a1124c7deb11176af42602f1636bd9.npy +03624134-8fa93b48c0c8e9abca9a013036a28780.npy +04379243-cddbf3a55a623e423002761e7a3ba3bd.npy +02691156-8b594934c14ac5db66cf1b4a8fc3914e.npy +04256520-c5ded02dd51a5482e0c5923879d79f21.npy +03001627-7d3b7916dc5325a9c862eec8232fff1e.npy +03928116-d190952a74fdd232540cc0119178eda2.npy +03001627-2bfa0be90c15bfa0b82cf928f6ed5338.npy +02958343-14ab7a48f51bfe69597505fd7d99b613.npy +04379243-5c7dde9febf82c72e4d8d44a2bc9dd4d.npy +04530566-1b1cf4f2cc24a2a2a5895e3729304f68.npy +02828884-6d4fad5487a044249dc30bab479ad5d4.npy +02958343-b0fa729f031a97d2c3c561b608f78503.npy +02958343-8e1e365bb6202682f43c51e53897fea.npy +03211117-b9ef07b9ea14f4fb1dc17d595f9add09.npy +02958343-8e764c26b9d6fe15cc2825da82c7ac3b.npy +03467517-7b498b66d9426ca844629dda8178547d.npy +03001627-93001617daca67ebc8687ff9b0b4e4ac.npy +03636649-a1bdde7b604dd3a89b1c4543cc5963cc.npy +03211117-cd71c33773db5570be7e507ed67c0331.npy +02691156-6ad619600049376a4aa57d4816c68a3.npy +04401088-9878b77e157e4b0dffc2eedcd24a87fb.npy +04379243-2538c4fb2a271b06e74bf18c5b9ed60a.npy +02691156-422105cd23178ebf333c61abffc4e1c4.npy +02958343-69126951b42485ff88cf40718544e7cc.npy +02933112-1f0b5514d93f39ebd189eb81471216ad.npy +02958343-a37a9d8847ca3b90e6052439e5a76d12.npy +04379243-ffc75a8bdb88c751b7fbcb21c074906c.npy +02747177-5a2d3cfcbcd3779f44a292ef014253.npy +04530566-94e216dc57731577c14e2939682bc455.npy +04554684-add75c4fa0707efa226eabe1cca3e850.npy +03001627-3126c6e9277b775b245ac1812a4e4d0c.npy +03337140-6c07ed789e414305ac477d524b05932c.npy +03513137-bb3a039ef88a9fbc480514d7f2edc0a3.npy +04090263-dc4b75223b732847384cbf852f305630.npy +04379243-3959856509e65a18a36258eabc2b9c.npy +03325088-ac2cca058aadcea43321831d2245cf06.npy +03001627-ed5b718c4efc65f148ff063e62e02115.npy +03001627-dbf5ea40382c5efed30107faf024a18b.npy +04468005-d0465d61dc9f9df9db4b3acbf6e65df0.npy +04090263-7787bf25c9417c4c31f639996cb3d35d.npy +04225987-ac2b6924a60a7a87aa4f69d519551495.npy +04379243-34b36de23e2e64852e3db45253b87bcb.npy +02691156-5afdfdbb4161ce0a7456183f198fd1e9.npy +04379243-fb32e9a7a8c2dfad74eb542502c2205f.npy +04379243-2fa78f97515a4d5624760bcb862cdd1b.npy +03636649-1baf036acc927ae27b79156a61ad4c01.npy +02880940-1a0a2715462499fbf9029695a3277412.npy +02933112-97cfa011875acc33532e8683617554c4.npy +04379243-71581e6511d7782282e6c3a4e742651d.npy +02828884-1cbbb30e8e06e932ed98cca8f0ccd5f7.npy +02828884-9fd5b67a2b20b5d1b19874039c8f3e05.npy +02933112-721f7a03a70b1107c0b2397831029b54.npy +04379243-7f53246b6aa7fd551a44da2424b9c700.npy +04468005-dd17c94e4b9b250ce982c7c6a3539d1c.npy +04379243-c9f3ac109419150246ef4343e2399480.npy +03991062-8d0d51aca855152f8c5f8653702e8d09.npy +02801938-fe06ff4915b6665ae25f6fe802a8997.npy +04379243-eb6ded7c35e0a3f69856fa70a578baeb.npy +03928116-4c68319a9f02d3909807fae46dcfc049.npy +02691156-ad6e93a1db3e1da5977e4bb19a62128e.npy +02828884-6e166423582d68bfd5b24cafb84903c7.npy +04256520-aeff4f4375c08e8ab9c8adebb50c258c.npy +02933112-636ca387c40fa8adc59350d819542ec7.npy +04256520-4760c46c66461a79dd3adf3090c701f7.npy +03467517-c0e00a9f55c9562a1f41064618762936.npy +03624134-a98bff7180fa174742a9381145738f08.npy +03337140-b1d02b692be88b6e4c3aee8e9d3a6ffa.npy +03928116-48e315ed7ae006f7a0c70bf6db5526f4.npy +03001627-689f7ad63ed9a7baa75d03186a0409e2.npy +02691156-87cf8f265536d4369a6e43b878d5b335.npy +03001627-4c513ea0804fc008c8687ff9b0b4e4ac.npy +03691459-6ef86253eb81e4d418200338a176d705.npy +02992529-768648ae74e9d84e6d445fdc5fd8bfe7.npy +03636649-6595ee36783d261ed3281970e2c44dbe.npy +03691459-b78e6c1ed34b29e7fdd1073b17e9e51e.npy +03636649-ca65934efe289843df446319d65b9318.npy +03001627-68dc135cd4671aeaff74317afae0a323.npy +02924116-6bfa535418e49888ba23f12214cb6df3.npy +03001627-6ed95ed3e89e09ac191c3762b497eca9.npy +03467517-ea557b9733435d95e9317ebb79eeaf1a.npy +03636649-e7da3cd73ebd81146251354a8b1397eb.npy +03001627-7c467486ccea38ed9c3a7877712317b8.npy +04256520-d8de84e7c0f8cbb19473aab1da686220.npy +03001627-534b0e6e2c53a8e1a7cdfd3874ed3723.npy +03001627-43290694390ad1adfc735c9ceab0161a.npy +02933112-6a910ffe32ae2e575588a2543ef0b0b4.npy +02933112-7f6d01dfa00872a26cf87f8460db3ae0.npy +03938244-24dfe6ef933ae9692257a9702919f3a.npy +03211117-a98035c0230649c79b95c928a1983150.npy +02691156-c93d0663035962b01b1cc145b0144991.npy +02691156-4bca81eedcc3da52b8013668e30e23b0.npy +04090263-1ad3a8c8c369448c22274f18b3096ea6.npy +02691156-72d96bac651bc74c7af159eaf7625abf.npy +04379243-85fd80db82120aa719fb4103277a6b93.npy +04379243-e0f6e43ec7c44cf0f60d4dd27a88e505.npy +03691459-acdb8a7d906b126e20363e2561dd589a.npy +03636649-e13a855926f25ffc5285aeabe3f6e218.npy +02828884-3a1915451880215e9bfbe8b02639d1e9.npy +04379243-e7dd71eaab0f209dad5067eac75a07f7.npy +02828884-6b70f11a9baa59ade43f70c0a99fd544.npy +03001627-34117792b1a8c180796c584ff1fcf56d.npy +04379243-2777463657ece1a3299457639cc3cfe3.npy +03691459-57374f933930a1453f92eb5e681ffef9.npy +03636649-1bb465b8f22315d1116f219d90a571c2.npy +02958343-a2dbc7c6487ed68f1b448c2bdeb22379.npy +03467517-4a704919068627caeae5cab1248d1ec6.npy +02992529-5298e9c7eeca74f8ff2988f561e515f2.npy +04256520-2c86b652e14005a09c39abaf208a73e5.npy +04379243-5de212ea4d57b20b526934092c2c4777.npy +02818832-8a3240bc541767544b44261aa73cb2d9.npy +03337140-6f392c57518e225e7c54607407af3ab6.npy +04401088-180ef1cc23b96050bc8c03f74d3af56.npy +02828884-cb30a5a8df3007f6f4fb4dee5181bee.npy +04256520-1372c28325f2794046dd596893434005.npy +03001627-c3da3ae20c1f92650640e24a5497a2b.npy +02691156-c7fe2215d41c2db3a45193285587808f.npy +04379243-4f3e1e670753c96ac955e5ed03ef3a2f.npy +04379243-e566fd9bbc3d51d377b9297f3055210.npy +02828884-3363d17303f69d7fad5067eac75a07f7.npy +02933112-a21e3a21401f889defacb264ebf1ec75.npy +04379243-cc182c3aa204614540f68c5e459bb389.npy +03624134-68c2ea6a1c8c147e30f57e42c77d3894.npy +04379243-d819fc4d86af592f7394c9d8807c7bdd.npy +03642806-f0fb8d7162a100481492bb7d502a53a8.npy +03513137-b4c223db8b1a30016cf94eaa382e4d1.npy +04379243-5a61158cfba0bb6a80360680c1602c7d.npy +03325088-f5e2551d23370d93c36fb70296e45483.npy +03211117-f8a23c22e76666a3d4ab0eed66631cfe.npy +02876657-d8b6c270d29c58c55627157b31e16dc2.npy +03593526-6bc426e7226f6f22362d7fcfd32ff15d.npy +02691156-645cccbc057c79cdcc57882dfaef8a57.npy +02691156-d81042a53dd1cc5bd90bfc986bc4c94d.npy +04379243-e6684a7ab98d2809856053d38b62525e.npy +04379243-fda71e511d095837acbf0573260a18d4.npy +03636649-58484d1c37df459e32acbbe2387ce75b.npy +02958343-5bb0076c269d5cb1ad19b94b8069bb8b.npy +02828884-beae527c550f5ce8e4ed7bd95fe664b.npy +03001627-e052eaa1d5bbe795ded10515704c9720.npy +04530566-ae8ccc2a90c7d57ff107f18bfa25e296.npy +03948459-63e7e84894e95a8015595517be070250.npy +02691156-f6ea6663b48bf78261f1ef59130c405d.npy +04379243-d7cde91c536c6502d7a1dc9bb68fc381.npy +04379243-7588da8ef1e427d1177f2a3a0c71fbcd.npy +02958343-7483c242d7feb3a5b9da62c54efcb32b.npy +03001627-30f68a6304d6906c9bdca9b7303475c3.npy +03001627-395868f297f01d2d492d9da2668ec34c.npy +02808440-722a8934497d70d18fcae10bdcf407e9.npy +02808440-ffa8c8fe242f0df054d7082b34825ef0.npy +03624134-9d424831d05d363d870906b5178d97bd.npy +03467517-fc7231fd95d1e4687a57dd3c9d98d88.npy +02933112-14a093126f5764bcf2792e4b1535c6c3.npy +04379243-5f4c30f80956bbd25fc5e56a56e86bdf.npy +03001627-d36ecfec3f3c18a9a28fdea8831e592e.npy +04379243-8840824c8e5cfafff2b7361116ad2337.npy +04074963-33a7613166c65aa0c7c51d4ea74651a7.npy +04379243-f977ba3ec46bf1c064a940596f3d867b.npy +04379243-e19080d150b1932ab20aa91e9e90c311.npy +02958343-a1c337c71f246f0b1d1a964dea8a7aab.npy +02691156-f9c93ddc9b921d88a72ae0d8b7f98590.npy +04090263-ddca06d91af2db70d735fa1ab17311ec.npy +04379243-a2730a66ac07818cd3299846d5c00f08.npy +04379243-396a32fab409303c811237b87ea8b154.npy +04379243-43c9aa5ba91b803edcfcef693e7ec696.npy +04256520-dd572d69cfa263bfdb10cbf40397412f.npy +04379243-e8aed77e92a8c4daac3edc5d86dabc91.npy +04379243-30b3454ab0aedff9fc30525e763ef5eb.npy +03761084-3472585bf8e2cf3ddf3a1b0d597ce76e.npy +04530566-d830527d616f47c811b9a587ace886f7.npy +04379243-385e55a7d0e528d312fbf3eb7146682b.npy +04090263-55b86089f042d17f81d2fc3f6a98fa93.npy +04379243-81e223168807d7be74971c311d25a3b4.npy +04256520-a2bdc3a6cb13bf197a969536c4ba7f8.npy +02691156-3a3827f1a76c5230e24527abcb488f31.npy +02808440-ee70154fce37a50fb362845c6edb57fc.npy +02691156-17874281e56ff0fbfca1f1143bb6bc17.npy +04379243-ba2f81e15029a37baf7caa8fd318856.npy +04090263-67335d8a40daad7a7e60e1bca0143d66.npy +04530566-f6762e2b8bef4ffa476a01ad767951be.npy +02958343-eb1bd7389854311c14f284ebe538e531.npy +04379243-e4f6069dee09b0df237af722b64576c2.npy +04379243-274e9bcb57548a02dab956ed03b0f26c.npy +03790512-83d3483c6c9edc39949b12cf3977a48b.npy +04090263-a20f4c1ff94b9d35127e0873cfaa7b8.npy +03642806-33b9567a9f534747cdd9e16bfb7eee3d.npy +03001627-c487441af8ac37a733718c332b0d7bfd.npy +03001627-740cc6d4d1c6901eadb91c074e672e22.npy +02691156-d06035fb4ba89c91f119374ee5d5f944.npy +04090263-73ce9a5617acc6dbf1e0fcef68407ae5.npy +03467517-7eee3b79e053759143891ae68a82472e.npy +03797390-604fcae9d93201d9d7f470ee20dce9e0.npy +03001627-c93860b7f38bf628bda72093f9b5aa73.npy +02691156-c31f5303997022c842c20743f866e1a6.npy +02691156-bce1b10c92fb9fc81b7a4091d85f2e8d.npy +03001627-95792c6761663652aece045e8bdac80f.npy +03636649-9023acca19d27f3fd49b2e04785f8492.npy +02871439-2567c4d8f4da409e1362d127df6d94eb.npy +04090263-c51600abc4b5736ece58fb8fdf218569.npy +02691156-997539bb0a0d8cf852c3271e911ffe19.npy +02958343-a16ff37768fe676473d32960f279a9cb.npy +04225987-d9b0de3b3aecfffb1fabf3cbd0fc77bc.npy +03001627-873c017f35957717b56a13a4b2372aa4.npy +04379243-719d38e7ec228bc9ad329b1997e89fc7.npy +03001627-e102ff4df6f28b6cdb400c09abe26220.npy +03642806-b211cfb105e9f97e6436916a86a90ed7.npy +02958343-58569e7feac27d3e5da8146fec888d45.npy +03001627-ad023095f1868d3019fb4103277a6b93.npy +02691156-88883a7ad39baf47bd46d022fd7d80aa.npy +02933112-6de399f706f2972970365ad078f710ff.npy +03001627-311c07b96ce39f82c70d3fe6f2ca143f.npy +04530566-667c662b55519e4650cff0d5bea1684.npy +04379243-b78d5b0748c83f3f855931d119219022.npy +02691156-6da4668de7ccdd0d4d10a13d437fced6.npy +02958343-6b0238b41337365a3330c5ee7577e4de.npy +02933112-a2dc947048077f4bd0b36851d61b6fca.npy +04256520-84a119d032947cdf1da03d263d0d0387.npy +04379243-7bc93a4cc26fab5c8c12b667670a35f2.npy +03991062-312314e1dfd5173a9f71dc1b1525f6a1.npy +03001627-82ac145a471e406f35836c728d324152.npy +03001627-6844180c300bbf852edea1c2bfa3bc56.npy +02992529-864b69db6dfc4bd0d4b4ae2ff4c58b57.npy +04379243-3c1b4a85f3a287fe47d51fb55a1c2980.npy +04379243-63a2d10d7c77424ad214ef3f65f73d74.npy +04330267-32fef525b8b75d2bdd833638fb82f742.npy +03001627-8180afee86f2075519fb4103277a6b93.npy +02958343-99f49d11dad8ee25e517b5f5894c76d9.npy +04379243-7bebd474258ec29e3c594bb716fb0dca.npy +04379243-8673b121b420cc0ca23949c21eddef76.npy +03593526-f2599921c8e0a76ea4e7499e379fa4fc.npy +04379243-ec98b08c2093d435f51f77a6d7299806.npy +04379243-e8b3da6a6d938b475966c5a46a5a6ec8.npy +03001627-9d151e778dd4a3f7f91663a74ccd2338.npy +04379243-7da19b39d092fc8e33b12e4baae47737.npy +02691156-863742f8e07f52ba4c3a35cee92bb95b.npy +04379243-c0d8f876e068f17adebc282c830998c6.npy +02828884-b77813d8b4fb7c606919f8efc25fe2eb.npy +03467517-cb9bf7f11fc58db41afedc87fe387fe.npy +03928116-ef668f117f843e0a8be892244b73e9f4.npy +04379243-87ab01946ad4a2f6e56bc109beb9eb57.npy +03991062-3547134cc7eb68e2ffc6e457221b9271.npy +04530566-81d9e9f072f73e42c71a2f2273897a58.npy +03001627-c585ee093bfd52af6512b7b24f3d84.npy +04379243-4d959d3b7b3721d448ee6d5fb14cf83d.npy +04379243-29de23533f0a9c31b79de6fdd84b2221.npy +04256520-6c9beda59f24f107b001e9ae2ac46c17.npy +03001627-90b181de9005fbd04cd0eccf52b625bc.npy +03928116-a27dc2aecb6fa9f69cd438906b0d02a4.npy +02958343-57ad55aefd13445c94a5ecac47d28f09.npy +04379243-a93d61d10d489c8eb2c2cd006d206129.npy +03991062-e5fd89e60fb6f668228d0d8aa4a41f21.npy +02958343-2fcec17ab09a42782a9eb0f146e94477.npy +03691459-68393fdf9730d1c86e95461e6c2993ce.npy +03001627-4ad85a7d1ebf49e3490ad276cd2af3a4.npy +03928116-d1fe87277b6002405aa0446e42ad65.npy +02828884-6ba411c181323fecea2b566ddae9e6f6.npy +03001627-d2992fd5e6715bad3bbf93f83cbaf271.npy +02691156-320e542b0b2f8afa248b612e49a6e572.npy +04554684-4713da50446a7595df3a1b0d597ce76e.npy +03325088-bcf2c837460a391954d7082b34825ef0.npy +03207941-6e85f6897e07e0b1df3a1b0d597ce76e.npy +02958343-9fe68c848c1385a2a9733fa2ac6b95bc.npy +03001627-9c8d3c5779871705d22218517e73100.npy +04379243-45b6c77fd17726713002761e7a3ba3bd.npy +03325088-75f3d28ed37de79c3ca0c4be71e7b721.npy +02691156-d7454b0e80d3236ff268234accd8cf4e.npy +03046257-f6964ba8472cd2bc7adeea6eb984f491.npy +02958343-ac482136fc30fd5ad8f405c5ec4e8cb0.npy +03636649-ea5893e12134c6272f798bd8a3edd4de.npy +03467517-a576b89276b4afd4dfddf59b80ae0f2e.npy +04090263-92fe43536b3f6dc1593fee7ac9114e04.npy +04379243-d0c369ef812dc0cb1839c27e793b8c3c.npy +03467517-910e903e228fc0ca8c8de43217db4540.npy +03691459-afd431c30a98f782d52af5b75b4cbd2d.npy +03636649-68a94becfec1965e21d6b7a56ef55b4.npy +03691459-b2af20dc171d40e4d4e62d99c536bbaf.npy +04530566-4944328c0ea895c53f464857aba8c0eb.npy +04256520-487635f7daf9ff48b3bd1e430b6587.npy +02933112-b278c93f18480b362ea98d69e91ba870.npy +03325088-69fd9452cf1cbeabb362845c6edb57fc.npy +04379243-20b5a668a57dcdb3402fc9e845187711.npy +02958343-747c49bca6d4ae9d7c84d27684eb86f7.npy +02828884-9b1ed4bd84562d3f406f2f420f742d6.npy +03001627-92c176547858fd2cf91663a74ccd2338.npy +02691156-1e827425b289432e8b96ae1a0a8b84ec.npy +03691459-16bf19a982c7cd71dd6a08110bca7bd5.npy +03948459-378c3f18cf130bace1f2a1daf140ac9f.npy +02924116-4cc81551037031571d008b909e781f21.npy +02924116-9cc4191d5af880a131a492bf3af5da7d.npy +04330267-e3650521e9c1979ea3cde9bbf4c69d5a.npy +02958343-4ebf1a8cbbd4a05228044fe9244db50a.npy +03001627-a99285df8c6d4578b980c976a65c0d7f.npy +02691156-2a3d485b0214d6a182389daa2190d234.npy +03211117-3863575f24e6bbe3fe5c8ffd0f5eba47.npy +02924116-2d44416a2f00fff08fd1fd158db1677c.npy +04256520-d9ae4cecb8203838f652f706160dc96d.npy +03691459-b3009e2384620945a35bbc252ec176f3.npy +03001627-103a0a413d4c3353a723872ad91e4ed1.npy +04256520-32198f8e02253fc0d1fbf79741fcd6d6.npy +04379243-87ebd707ca90700d8b424343280aeccb.npy +04379243-7fdb1575e7f15c199d9fad88e2f4c8ff.npy +04004475-c7dc190e3b4d9875e6d38cae12e77b1f.npy +02933112-740eb7316c76854ace5d6e9371bb5c33.npy +02876657-c61edfb672986ee48a9393b5e735dbde.npy +03001627-a20df07368113438ac59dcddec3b075.npy +02933112-71d240b4e2e79be96a001de88d8cd8d9.npy +02958343-90f2e2d8f9b89074425b2c354eccabaf.npy +03759954-18ff360b39e5306272c797c96ca37495.npy +03211117-94525af6a244a33c21d7ca6ede0e9373.npy +03001627-86d77a9e22be4d5773fdbe4b39ff4036.npy +02691156-c85a76404b85d94e62b600da24e0965.npy +02958343-c30bf6d1ae428497c7f3070d3c7b9f30.npy +04379243-ca13d22c81c74698d97cb887517a1526.npy +03467517-b5fb2a19bcd09e0ef1a49eb32e519d69.npy +02933112-3fc6e2baf40f4377f5afb395b99ae069.npy +03691459-a25819c97470bcb09dd0351f01396cda.npy +03211117-2198dccbee4d38e11a23ce2d1a5d3925.npy +02691156-20150c9c3038d08419bf31399c6e39e0.npy +02691156-cbc73e8bc866ecacf7f795409cb230c2.npy +02691156-9b1fc3881a5335cb44012f72ba1e15a8.npy +02747177-8bdea15ae5d929d0a2eb129d649f68cf.npy +02958343-1e12573f2d8ffca667789dfcc3262f70.npy +04090263-83859013886286905dca6305fb9f97ca.npy +03790512-a2af2d47ac7bd232c3b8d605d6b133fb.npy +02942699-9533618250e35304514fae39ba03db5.npy +04379243-4da91eb1adb9e960ad5067eac75a07f7.npy +03513137-a6d6d755b17fdbbc3e8b63b9578c7894.npy +02924116-8b68f086176443b8128fe65339f3ddb2.npy +04379243-db8678030bede8ba88853ff6bbbb4a9d.npy +04379243-9ef38dea16d4d335a71c812e027f94d9.npy +03593526-6596b4cadc29d0448de42fc1392c2139.npy +04379243-6c50ffea3a4ec86655f46d55537192b6.npy +02828884-2d1e5eeb255e79dcab53bf7fa22f3636.npy +04379243-f02907c5c42e1e766f1e07a56c129dfc.npy +02691156-9c41b0040048581c32387cdb9b2a84d5.npy +04379243-80acb994a8dd6d636831079c2c481dd3.npy +04256520-2097fba74518dc6e4a949e376cab703f.npy +04090263-8933f22af2576e5b9f433921788191f3.npy +03001627-7f271ecbdeb7610d637adadafee6f182.npy +04554684-60f7d79d10e19134a3e7878f2bb5f0ca.npy +03991062-7773a6283bd25740ffc6e457221b9271.npy +04090263-d5ee8eeeed055401a3a714c763a6fafd.npy +03691459-ac951c58cd826af6a89585af9e32f3d7.npy +02876657-75bf30ec68b8477e7099d25c8e75cf58.npy +02992529-453c590f0a1b37c1e0c2427da07ca8c6.npy +04379243-5ea758a6391a2f814b7c5e48b51e5c7c.npy +04256520-b4c5addeacfce8242165c54dcecaacb4.npy +02691156-57f1dfb095bbe82cafc7bdb2f8d1ea84.npy +04379243-e57509d06a49646c490ad276cd2af3a4.npy +03001627-6ea2aabe267b519537b2bb75885cfc44.npy +02933112-c6abd725ec744274b8710a3469971b1.npy +03691459-7e359607ecf460f399372ee1e6dff278.npy +03593526-ace45c3e1de6058ee694be5819d751ba.npy +03001627-4e5e8af0880b0d98febad4f49b26ec52.npy +04379243-f69b664bb78a4c2f7537eb150af3dadf.npy +02691156-6d432caaa8eba4fb44b2fa2cac0778f5.npy +03691459-8df018bf733ff01cf00aae52edb0b7b.npy +02691156-2494cb5facfe7b1f85e0a2007a11e92f.npy +04256520-191c92adeef9964c14038d588fd1342f.npy +02876657-1071fa4cddb2da2fc8724d5673a063a6.npy +02691156-a4f5ce5926123e472e78e1154b9a2647.npy +03691459-6341662056860c3e225f3f0d46b4fca3.npy +03001627-aeb86d8354eaafa232acff7796d8c3b3.npy +03691459-38f418f2d64692df63ee8a34069b7c5.npy +04256520-2f458ca5f25954ea9f2349486c570dd4.npy +03001627-d4f5c3e3eab52d0a3334fb6668ccd834.npy +04379243-ff3f1004c4126b966d75aa5db61c1fe9.npy +03636649-b6efb78876150d45c94b622f1207af2.npy +03211117-dec6a8c1c01e148d20685b5a7e34b501.npy +04256520-8641e421ade0f7cae136ac3990ab77b2.npy +03938244-2b627f36c6777472f51f77a6d7299806.npy +04256520-1a389652d23b9cc06bfa0701d875ff10.npy +04330267-8ff18f81de484792f0b94599b4efe81.npy +04090263-65d6c3cd8c1edfea719b648239c8e160.npy +03001627-60c0c32187f4e2ddf51f77a6d7299806.npy +02828884-b218e59af74f0be4ee9005feeed08b86.npy +04256520-26b0765b08c86fed52db1d2b4104f173.npy +04379243-51205a57beb69476fa4763675e844f9c.npy +03948459-446e4145b475eb245751d640a4e334.npy +02691156-ba784e6de35a5c6b4f8a08a5e6b028e7.npy +03001627-19d7db03d81663394733824eae5cd9ae.npy +03211117-581df3d934bbb7d3206de7995cd4a74d.npy +04004475-73a7d3d05b9dd459ffe3432ba4f2e6d3.npy +04379243-f41198b81216f36ff155d75bbf62b80.npy +02933112-b5a6edf04474c327ded35d98d26f9668.npy +02691156-674115a86dd196c142c20743f866e1a6.npy +02691156-71ad36bd32ad44a0c503a3776fc280fe.npy +03691459-119fc0c18388a2a2e338ca8c90019f12.npy +02924116-f8977b22fa73c57910c9f5a2e580dd66.npy +04379243-929cefd882de6f9b5048ab7650c7a7c.npy +02958343-9375ded98380ccc77bbf13cb42ad9d73.npy +02992529-7ea27ed05044031a6fe19ebe291582.npy +03325088-d799034e7a417a97b362845c6edb57fc.npy +03636649-6f4f8f3788da22817217386867d08cc.npy +04401088-7d93b8dae79d5bbe7015d3b6f402d5a4.npy +02691156-829108f586f9d0ac7f5c403400264eea.npy +03001627-c6898b62e82e61a8930422448288ea.npy +04460130-de08da18d316f927a72fcffccc240663.npy +04379243-ccad4d1ffac1b5e978ebd8af2a314e49.npy +03991062-d6342010f3e2502fa4b84ca629203b44.npy +02691156-2228845a400dbad30fb60bd5470eb25.npy +02933112-c59d2a61caf94a97c59350d819542ec7.npy +02958343-f2b350b6c36eb73d1fac59b924f395d9.npy +02691156-2f4f38d774e0e941dcc75fd1795fa3a5.npy +04468005-84de1dc7422b00c627c514aa9d8cc75.npy +04401088-1b1969121f2d099b27192dc5dc6ab252.npy +02691156-d5a94c9f09d238c4c3a35cee92bb95b.npy +04379243-6a35640c7f10aa71850622797c13f562.npy +02954340-7cf439aa8382299047765668cf4023ed.npy +02691156-d3d788c1fb35227619ba010ddb4974fe.npy +04379243-e534dbb5eacd708c18885412f2b0a4f7.npy +03001627-f913501826c588e89753496ba23f2183.npy +04554684-434fc8832f3ade492d5c22cc9b713d25.npy +02828884-dc286270b2256b94d2b12aa6a0f050b3.npy +02924116-1b6f9f69c1bf86ef41556f795d265590.npy +02992529-1cd8004a1e0dd825c33f370fa5b41cf7.npy +02954340-dc3e5c0457defe87a52821bf1aa3b19a.npy +02958343-24d7494c6b92c6e7c1bbb501b1d87871.npy +04256520-c4af170f18f0d6edaaf0ad030fc37d94.npy +04379243-7bbdfac048aefc9a5634c21965ee6bab.npy +03207941-466e441dffbdf9fc14b35a7d7cea7130.npy +02691156-e4ac77fdf28116232fa725d7a62a02a.npy +02933112-832fa486c60335f66ca64288cf1b7ee0.npy +03001627-64a585a441f2ffa336c8b9bf2576aca2.npy +03001627-935093c683edbf2087946594df4e196c.npy +03046257-df5b2ba70ceaa05923500a5b036df62e.npy +04379243-5a9a9b14c1830de641cf86c757faf4f9.npy +03636649-8913c3dff1651a316a3d00506cb9ed19.npy +02801938-5eea24527c8b3124cb2a965e75be701c.npy +02933112-131992dab1550a7aec24cae3e129c189.npy +03001627-f2b2448978785cf5fb63369d5dd85d25.npy +03001627-341fcdd8a40a2612456cbf78e1e89022.npy +04401088-68ffa3cd161114cf55f5bce8dd67399d.npy +04379243-cc82b660e39ee47df287722009141c0e.npy +04090263-b4f358642d91251d26acd17789ec9c7b.npy +03211117-aa92ecd31491bca87a88a2ad67bfd073.npy +03001627-708fabd1e1a39a77aa6bb5920f533ce3.npy +04090263-2e0fd9303c251ccef02ee453ff283e26.npy +04379243-6ba6309d74f4a131272505863dd1b8dc.npy +03001627-b7073426bf9332187c564a6b9ce2156f.npy +02691156-2ef20ad4c579812571d03b466c72ce41.npy +04379243-d0346744d67b08b099e8bf807e902261.npy +03001627-20c6158bbeb2735ed1dcc55e36186e4e.npy +04090263-30fcbf2fed0eb241d8569d1a6c25406f.npy +03636649-eaca02e8f065925dbaf5b49ad7809302.npy +03593526-ce6f30234bb3797fa2ee63b46530621c.npy +02958343-58da19fef63348a56b6ef877dc525506.npy +02933112-6f113f2baf10463635836c728d324152.npy +03001627-81b27636162e148bb3fb065fa3089331.npy +02958343-8202d2165aaff4c05fb2da48d9c8120d.npy +04379243-4561b621e5b7c1ae8cb5d9909aeb1309.npy +03001627-ea1bfe81b88395fcaa29e9f0529e8ef7.npy +04460130-90143acb141fb1cb4292de5cdfae65e2.npy +03759954-1c2267e8b8a099a47457e76661a399e9.npy +02691156-e1324a093b45645c5a5672eede2b271f.npy +04379243-b12ccf1813b424864a62dd9e5e4067d1.npy +02691156-6db6f79bff14b883a0ff12a4a79c7c7b.npy +02992529-b73398902d1c267b5eed8c8b1cd54386.npy +02691156-7b485e11f80e0577bc0909d98a1ff2b4.npy +03691459-72c5cab12c0ddb22a0fd8d18f37cdbfc.npy +02691156-c9764fd84080da3f4fb6842b3610149.npy +04379243-a6e066da6311c2c7f4d017dd03935e6c.npy +04379243-366a7129cdbaa0b8fb94cf898f4fa24c.npy +04379243-54e85b248576c4eb57cd80d4b17e7e11.npy +04090263-5b5acb01373af13180c2e60c312b0f09.npy +02958343-c1186d49101dcd513a0daf3e5400b95c.npy +04379243-ce96139ae5a4dbfa55f46d55537192b6.npy +02924116-845599a0f9d7951acbdda2562495e10b.npy +04379243-90a2174624d8b62da53326e496617646.npy +04090263-76377dc3d6b1dad2c0aaedf10d776af7.npy +02958343-9f08e434ad95c4bbbc37558785e0529e.npy +04379243-9d2c5a0dbfc811b3f9ae74fa595a8a63.npy +03636649-d939b56b53aa7e7c42f80363988bcb92.npy +04090263-3e3ee43e001e800a8f06d4785681c4e.npy +04379243-f772e5b89475fd2e4719088c8e42c6ab.npy +04401088-36b3329dc0bbd86989704dab2d2a8ab9.npy +03467517-3527ff33cb9afa1aae4662a5bb3d78e9.npy +03636649-6918fb9f51d1dc3dba9ea396e14c59f2.npy +02691156-a702da03d770f5096e2738fc9da60e6f.npy +03624134-31b39f0851060f87913cad523820e930.npy +02828884-ac78c8b91417aa5bd2f4120f473fc3e4.npy +02958343-2cc413c3ea9800b3cf1e58caa15acb49.npy +03001627-d28423569bfd84708336a02debb9923b.npy +04379243-407276907088c8c9f51f77a6d7299806.npy +03211117-3aee103b0bde9cd7c16bf14ed6ef2f6.npy +02958343-9748063440a449ab3db642d8dff7fbe6.npy +03046257-37a995cd9a8a125743dbb6421d614c0d.npy +04401088-ab2cdd82bc69255f1fc489fbdec3fa1.npy +03261776-64c7ed011cb25eb5f9df692fb910a2fa.npy +02958343-63428e5fb6fb627aea5698f3cf7b2f4b.npy +04379243-e25fdb977fb867fdc3bd24f986301745.npy +03761084-c1851c910969d154df78375e5c76ea3d.npy +04379243-4f06f4d04d239448bfa17a32b3866b83.npy +04379243-aa96704dbd5e852cd9fad8aba2c312b7.npy +04379243-cd4e8748514e028642d23b95defe1ce5.npy +03691459-16ad8ba41b4caaf66a0a07a21e1bacf4.npy +03593526-852e1bca3ec5fdeb5dc9e54641a3f5bb.npy +04256520-78fa28a031f1042f3bd16075d47dda52.npy +04256520-507d740bec19238d18f52c8a4cfcbe33.npy +04379243-a4b2870ce7a54b8eec11c6b035aac769.npy +04401088-f420bf37baaeee5621844676433a0aca.npy +04530566-a3e0b522698e11a87e43a7221507fad.npy +04256520-f563b39b846922f22ea98d69e91ba870.npy +03636649-22ca1d5fbd8e6eac7b79156a61ad4c01.npy +03691459-54e61267b88174967bc8772c5c1a0c19.npy +04379243-651706776926937314b86d5282eb8301.npy +04256520-cd74a153b605c6a3cabc196a7f35f1aa.npy +04379243-397c56f15e547fad1bb088904f7cb154.npy +03211117-cadc40a7bb182a40cc229b563d900f4b.npy +04379243-f4d0e1be9884f45cd2fc64a9331b7788.npy +03691459-5948bd85a58330628de9f116e0231954.npy +02933112-2cd6ee7e592939a9824662341ce2b233.npy +02808440-36a554e2ef628266b0d51feef5761dce.npy +02992529-addf767a669d9732691c3af43bf5f97e.npy +04256520-fd4dd071f73ca07355eab99951962891.npy +02691156-b153004c293d4b151f32208e53f871eb.npy +03001627-6a227aa2e1fb8ecf51f77a6d7299806.npy +04090263-a0025e80ada9cf91ae9e1c81f7e5b0b6.npy +03001627-47bfa972100a782519fb4103277a6b93.npy +03325088-8c853348df36663321831d2245cf06.npy +03325088-4492ee234374c85914b35a7d7cea7130.npy +03691459-8a3edcc398f34fe534b2581df0f941a1.npy +03001627-90cae938e34b11a429823c412ca4576c.npy +03691459-453c959963a529322633ff66beb9cf31.npy +03001627-c2430d27be01948ab8e1b99345a5afd4.npy +02828884-52c13c1c0812699120f85be7e9edc22b.npy +03636649-4c3a0886647ae06a6ecf9e4734c75a01.npy +02958343-ed6bf649ad5b3d82b1bb46d2556ba67d.npy +04379243-79eb4b57cbd73e117e2e50070ddfd27c.npy +02933112-c6e91d50e1bb3351a8851b4eb6161973.npy +03001627-50a4aa069dcd171937b2bb75885cfc44.npy +03001627-87afe5137d675efb73418f9a8c25ad1a.npy +04401088-67c6c3db87a1d72b7b8e0bea6a77fb50.npy +04530566-c79c87dcf17a40f698501ff072a5cd78.npy +04090263-fe2e9f0363866aba8868d0641feb1888.npy +04379243-fafd354b0713882e4532856089dfcdf5.npy +03046257-883d4ed6c9441e8e707e09f70814b7ed.npy +02808440-3858ea48966b8e5654d7082b34825ef0.npy +04468005-b6d765b5c2e547d64878adf45135c9ff.npy +04090263-8b0710069d95b4563a411ca33a218449.npy +03797390-79e673336e836d1333becb3a9550cbb1.npy +03467517-1758c5cbffc7f6634236d3c4918b91c6.npy +04090263-c0a8c6eca464a1ab9f433921788191f3.npy +03001627-bb13760fd1e2dc182d19175e7d19b7cb.npy +03691459-ca545c7c3bf38891af3caf4aab91511c.npy +02958343-50840e502ec2a45aafe1d4530f4c6e24.npy +04256520-84ab3d4610acab1adb352b8394e172c8.npy +04256520-afb937bd74261f5110004612ff5e29b7.npy +04379243-eb54a7a886da95f69223fc014b68160f.npy +02747177-8acbba54310b76cb6c43a5634bf2724.npy +02924116-1e4909dbe765a9dc18db89a808b64af.npy +02924116-917de64538fb9f3afe1d4530f4c6e24.npy +03991062-9fa3f163821a388d96d49c3c538e4bfa.npy +02691156-48836d07312f930223e2b52fb0c019e0.npy +04379243-3712e31c61ea51a354b250a5bdfb0136.npy +02876657-eded10bf44a2571a911cff0cb398f845.npy +02958343-6165a435160e69bef997a8fb55b67177.npy +03636649-395701deeb1b2bfd48657c771cfae685.npy +04401088-3ef3e3008fd2696ca1033de17902ec9b.npy +04401088-cfc5fce3c76610e3634fff5505144a5.npy +04379243-2a5cd32bacd3ce601ba08c4ff5d0476f.npy +04090263-c8889a93245d305518c3adaf57b2e1d8.npy +04401088-35d370a1531826adbe5693b333a3dd92.npy +02958343-1548f5fb0684d08c63155b8ebc275bd1.npy +02924116-1c39805d5ae78d319797a4124a9f002f.npy +02958343-3980afb8f986988daf285e0d3f56d074.npy +04256520-927967e761c52c11eaf288f952624966.npy +04379243-c36b95723ccd6f6da99d925f789b1cf1.npy +02958343-999007a25b5f3db3d92073757fe1175e.npy +03001627-da49d0ed41204ff65c0da4cac04adaed.npy +02747177-eddce90cae7f1468f155d75bbf62b80.npy +03710193-62536cdfffbec7902e869c74025e32a8.npy +04379243-32f8195c437b5aef51f77a6d7299806.npy +04379243-36821105af341539d810b14a81e12eca.npy +03691459-3256546f0f70af9c39c80a095f51c7bd.npy +02924116-c2441f4ed9ee23984d44f5db04bf14b8.npy +02691156-be080a797406422843afdb9c81ff2967.npy +04530566-b1bc73627283a4076b861850ae66c9d1.npy +03046257-c0eaa0bcd85626c7847d4e46a1f9f05.npy +04256520-6b6509e3589bc296c10c5f14d140478c.npy +04379243-33e0b076b1dfd411654495ddff111d98.npy +02876657-95e6a3a1232f97e3d333084c1357713e.npy +03001627-490797c10b8cdfcdf4b6538438a0b930.npy +02958343-9f4bbcf9f51fe1e42957c02bdefc95c8.npy +04530566-e1a43edb6152a3726e23bf72aec61fd1.npy +02933112-a8a4fbca233fbadb7ef0119f8dd1f40b.npy +02691156-54c0f5b611d3c7e683651cbc8e49e4f.npy +02933112-868509e96bb859bbfd5b2dc3df6521d5.npy +02691156-655ea8d8c710cf98f3a69a6853df2d7b.npy +03046257-1e61fd6a1b436ce6153d4c0fe024d18d.npy +03593526-7b6d5a7a902ca441529e78b4656a338.npy +02876657-810e90684c0d4ce5636e3a589cf8c61c.npy +02958343-4b1227b5dbf1cad92e877e82c90c24d.npy +03001627-5c83457abb14f95768c2f5eb1dd4dfaa.npy +04090263-8b00e0ea294fdedf8af39b443dc477ce.npy +03593526-c1be3d580b4088bf4cc80585c0d3d970.npy +02958343-5b4243556369155858c383066ceeaaec.npy +04256520-75418c9587b8eb0edd7fb8bdab16e83.npy +03991062-4e1845df2a98ffb858c88d30f502a452.npy +03261776-53433f3e15014d831220240e825d0985.npy +03691459-5d11e7821ec86797b646fca2237eb6.npy +02828884-a8ea7dc227b632edb88a2574e8fbb52.npy +04256520-150c9d9b92f7559f593ebeeedbff73b.npy +04530566-a3459aeef2676d7653b838b6058a8d95.npy +02958343-e169584b7e66ef074051b6e037481c7.npy +03636649-c5d999b26cc9ba381735ea0e092a805a.npy +04256520-47bfa972100a782519fb4103277a6b93.npy +02958343-f9fb47305ee7156d59139efcde1fedcb.npy +03759954-78d91f0919fc1e9c799b5809965371e5.npy +04379243-10bb44a54a12a74e4719088c8e42c6ab.npy +03001627-348528e8d474a003cb481b0b11df1849.npy +02924116-1c9568bc37d53a61c98c13d6112727de.npy +03593526-97199437c2b3acb664cc17fe2c6413a.npy +03001627-268304221a5717124a05fa063da00291.npy +03001627-bfca24444b46e75e492d9da2668ec34c.npy +03948459-f80c465c9e401dab44608b3255ca1886.npy +02924116-c9dd192e42466ce852470de2774d6099.npy +04256520-979ca0cbd4bffe37c7b11e86284a2e.npy +02924116-2baa252ceda0b508cccea738142ac97b.npy +03001627-b65c3e0800f1c67cf70828d0af10edf3.npy +02691156-b71bd3c61315abf9ad8a06dbee1d115.npy +03001627-95039795fd8db944608244cbb9b86bf5.npy +02958343-ac813039f9a4468ccc777d23edf2f8d8.npy +04256520-e3610bdf0eb38f6b4b8710a3469971b1.npy +04379243-1bd801dd5da88655d989c9f989a09ff.npy +02808440-b03cb02cab23307b71f6c2d1271354cb.npy +04530566-5b0e4acffe94b6ebd283df6ee191ad24.npy +02747177-18be3d380d248fe081faebbdea6bd9be.npy +02691156-fd528602cbde6f11bbf3143b1cb6076a.npy +03211117-416674f64be11975bc4f8438441dcb1d.npy +02876657-defc45107217afb846564a8a219239b.npy +03001627-26d98eed64a7f76318a93a45bf780820.npy +04256520-139b38251b5bab5214038d588fd1342f.npy +02992529-7eb1bb8e7f83313b5bfaa3ead015ed29.npy +04379243-2ec33e8b457ac0fa278d386bfa54545.npy +02958343-12b5e4f52c22b348d8499d8846cb4c3b.npy +02933112-31c94abeda52273286d53ab0fe94e911.npy +04379243-75024d18227e53b565f968dab29b0192.npy +03001627-c5c4e6110fbbf5d3d83578ca09f86027.npy +04004475-8f827c87f5f7c053f105ef303e18c873.npy +04379243-f85a362c7607921a7aeca7115f6949c7.npy +03636649-c5946f7781bf5167aa6c5592e5d8022c.npy +04256520-ab1435d685c06277409421506a05b6e1.npy +04256520-3dee5f41a11a1fdbdc83753cd31caa42.npy +03001627-41ab50680dfef43aba5342d638d0c267.npy +02691156-48e477d5904bb7bb1ad94eee1d03defc.npy +02958343-fe9c6862f758ee056ce6bb1d0811960f.npy +04530566-7e7ec66ebdd4df7ed1745f739fc0fa03.npy +04530566-c993c40ab88b161e3cedf90fdd80720e.npy +04090263-e6fecb2700247e1dd87c63d8b3018b58.npy +04256520-d835768fc0cc3300ccda8d28b44378b7.npy +03001627-71dbb37c026cc338eff2e9bdfc79fa2.npy +02992529-8ce0fff87979560bed1f9cd2184d7b73.npy +04379243-c0546f05e8a4542f1cf1ba58f558540c.npy +03001627-b29f5c7c73908424685a4d2d2b5da82a.npy +02691156-7f4ceb12e48be00ea4642ec4b6f68a.npy +04379243-ce1bfb999b211d423825a5bc524f67c9.npy +04530566-f2d7625709d7bdaea6dae8586082d789.npy +03211117-31ea284fd46d2d6013d823b13369c182.npy +04379243-94d6518cf1e00eaac013a7bed5288654.npy +03691459-336ae67af51a13309e87d2bdcb41f548.npy +03001627-d58df0968070bf3b4b3c42e318f3affc.npy +04256520-d9acd27e2a9b12d3ae685ca100c909e8.npy +04379243-4ce90fe70faf4c3e255bc16374754e69.npy +02958343-613bf2e7f987553220d9307ef0bda318.npy +02828884-9ebca72c02d26886a6e82f4002a10be2.npy +04256520-6bfe4dac77d317de1181122615f0a10.npy +04090263-6d7b8924dd47dc6e7330912d1744819c.npy +03001627-13cdc9e018a811a3ad484915511ccff6.npy +03001627-f85f33b3f6cac48a512d71be7dbf2d60.npy +04379243-7988c8f23dc634678de5f815e8387cfc.npy +03211117-301148e373839ecc37ab55b97a5e9f9.npy +03001627-2e5e60f57621c1e7480c54eaada840a1.npy +03624134-efbe696985dcb81ae3912d46f2dbb69d.npy +03001627-a3e990cd563b7a57ea411f5a15742da6.npy +04379243-e9c3a3aa2278608bec15b38012222fa8.npy +04090263-9301e31bfb2f8f8d88be2a30dd556a09.npy +04256520-11f31367f34bfea04b3c42e318f3affc.npy +04225987-7a00dee660ee94f5dfa6594bd6ded322.npy +04530566-42a8428a3d909fd64de203ef6842ee61.npy +02808440-857adf3f4e2845b044221bef0fa3c36b.npy +03001627-7eedcb6d76b8c23a9cdb421f6af95e5f.npy +04090263-681e871906643ac4f9a24531fe7127c2.npy +03001627-c7ae4cc12a7bc2581fa16f9a5527bb27.npy +02691156-117861b9ebca4f17c69cb28fb4b4d257.npy +03001627-75d0664363f418efe461a9a9741d9415.npy +03636649-9af818e49ae8a9357bbff3af6bac359e.npy +02691156-649a8f44ccc86f4843513dd632697ccb.npy +04256520-859e3eab73311f38ce59ea70152320fa.npy +02876657-8a0320b2be22e234d0d131ea6d955bf0.npy +03001627-30074024ad3c581a19fb4103277a6b93.npy +02691156-97bc5fffde64178f43afdb9c81ff2967.npy +03636649-155c83f40406bd0c48d945252c13120a.npy +04090263-2ad41c44eab88406924d7b1c81f7a0b1.npy +02958343-985082c9239527ed728fa2df514c65d4.npy +03001627-6163793e4e973450a9b8d9d3b5cf54cc.npy +04090263-78c7c7037e2ac7a7e0490a4a721b5273.npy +04530566-c0eb62cb64ee1a31f29de30ec1bf6a3.npy +03001627-81ba38f4d3b7eac1f82a35e8b19afa86.npy +02691156-dae59259ed2a2951d13ef00338ba8c52.npy +03046257-d11f6cf17b7c9e7a741f8bafb2e2f5ae.npy +03001627-e5b6a3cf96b36a1613660685f1489e72.npy +02691156-898b4899114d9bb890baeef8ba5b93e5.npy +02933112-8dc8d2e0bdf870ec95d0ca3fdb30532a.npy +04379243-b1d643bee9cc33d9668ae11a7db5e82a.npy +03001627-c50976d44eac9f3cd7aac2535b43ae4e.npy +04090263-ae53ea0e6011cdbde2bb19fbad3e4596.npy +02958343-84f258f2969c02de6f94a44ce504367.npy +02992529-9fac50c7b7c72dc694f8f49303e93f14.npy +03001627-b10dd8cb211b26ba98d5fc0473d00a1c.npy +04379243-2766a883126503cac3bd24f986301745.npy +03001627-3ee094648665bc3fca15770f07fe3544.npy +04530566-8b2e1eabf620d76840633dde0a3c28c8.npy +04379243-c627f3639caaf614a6589c01f678d8ea.npy +02958343-341b474e01e039af59139efcde1fedcb.npy +03790512-e65c320aa245854e39e5b34b546caf02.npy +04256520-8673ce2da94bfe4ff42b5131862a2dd9.npy +04530566-786f18c5f99f7006b1d1509c24a9f631.npy +04530566-8b25d01f3fd3d5a373e9b20a29bc1d50.npy +04379243-b1bf0b775e6fc085391e4d6c585a697a.npy +04225987-48f26ddc704fec2f379c6a1d59ef7283.npy +03991062-4d637018815139ab97d540195229f372.npy +02958343-30456a19dc588d9461c6c61410fc904b.npy +02942699-550aea46c75351a387cfe978d99ba05d.npy +04379243-428279529d61b45260ddf36bc44130c3.npy +02691156-46d334b92644b9c8445d150719ce97db.npy +03325088-6f2fcfb9f844979f87dd60af81c93a3c.npy +04379243-15a95cddbc40994beefc4457af135dc1.npy +03636649-68abd2755ff4588b545bbb1b2e749fb8.npy +04256520-b3c7b4435c3d05164dc11e421397c795.npy +03211117-8b5a96b72767f7354fac5eaf08c4d9ce.npy +02691156-da6faddc7079ce8ab6befd5df74fffa2.npy +02691156-b2e86c7880a56b6f71c382fe82cf6e04.npy +03001627-fac321238dc8637eaa7cb30470f3273c.npy +02992529-3aa3d13575540a99167196b0ec8ce495.npy +02808440-474a0aefc64043da54d7082b34825ef0.npy +04530566-f36e77f80e2944ae73fb6350806be955.npy +04379243-5437d8fcd8dcb47a4733824eae5cd9ae.npy +04090263-efd891428cb699e78dd4952817969d63.npy +03691459-b754df4013a71f6873e1b2d018c0512.npy +02691156-201e40e86acd7d34f4c1adce71073351.npy +03207941-717ea298a9a70ae7e5bf1ab8e7d0b.npy +02958343-5a2d4ea15ef5c18abab6b34711b43bed.npy +02871439-6db2136ad0de3cded810b14a81e12eca.npy +04090263-97a7a1f3c53b3c5ff9489a342636086b.npy +02871439-336fa11d8fe3dd2815dd7d7985e749c1.npy +02691156-d0456644386d9149ce593c35f70d3f.npy +04379243-573e85e0e02dec63c5a208307819a3a1.npy +04379243-56e46d8bbb70b17491829b477862aff6.npy +03593526-72cd871f8335f911fe9e40361c13f085.npy +03636649-1112f253e122dc8273111597f45b8227.npy +02992529-393ae1877a5e20478139dd63d55edc44.npy +03636649-8f2e03f91a970464ef3a2c64cef919d0.npy +02871439-c40828710c91001546c4f23965b7dd40.npy +03211117-af2f3c9c8fe90380c75516c7217fb218.npy +04379243-676d6d79d32de9cec3bd24f986301745.npy +03636649-7932b195e0e8ab00726dbbf7bc5e4df3.npy +03001627-f351b1725b288d8847df6165146d5bbd.npy +03001627-f551bf7431e0fd7cf937a9747c26991f.npy +02691156-7bad9d15c0f0d3c03554ccf8c30febe7.npy +03991062-a36d457e57b67ab4a2c59a4d90e63212.npy +02876657-2a3e0c1cd0e9076cddf5870150a75bc.npy +04530566-b04e4650e547e0509803291b0f4bf532.npy +04256520-9fada8462006e138efc579970fcfc006.npy +03636649-a1d09074c83bbe418ca4aeb5e3b33af7.npy +04256520-d0e419a11fd8f4bce589b08489d157d.npy +03636649-ec2d7e5e968c3ace7ddffb7902a68a13.npy +03636649-a6413f422f4ef630fecfeea7038369e1.npy +03797390-639a1f7d09d23ea37d70172a29ade99a.npy +03991062-3d3c8f95006cc061a2c59a4d90e63212.npy +04379243-12b7462856335e3d2404817055fb55cc.npy +03001627-ce33bf3ec6438e5bef662d1962a11f02.npy +03001627-3cc6485ab499244360b0434449421de1.npy +02808440-47e7884cf9d5331c1a448a935e94526d.npy +04379243-2091efe147f9ba11e3069fe10dd75c3c.npy +04090263-6f86a5fd7d3a52dad735fa1ab17311ec.npy +04379243-17d3e93e5f3bf2044671d97b0fd17f51.npy +03991062-e0725fd7859fa238ff67c12005f72d2.npy +02871439-34128cd8b8ddbbedd92903da5c4b5ef6.npy +02691156-28d719b73b1fcd2f5de04aad18bd94c3.npy +02828884-6e27b6fc7769089f4fb4dee5181bee.npy +03642806-dd3642b10fdf3550615ca789e669df24.npy +03001627-2ed17abd0ff67d4f71a782a4379556c7.npy +03211117-eab36391bd7fb745585e5281d7025178.npy +03001627-bd500b346c427b31f7628281ecb18112.npy +02747177-81a04a676ff96a94b93fc2b66c6b86b6.npy +02808440-1ea8a2646a0e33afcd2957531fcac5d6.npy +04379243-e98f06e93bcc237afebad4f49b26ec52.npy +04256520-1896f141f12a0df135836c728d324152.npy +03001627-a910a4447648af1a35133ba9028a8318.npy +02871439-303a84aa514f566883679e873099585.npy +04379243-ac9fae8af57729945eee45c00c4de9d3.npy +02808440-663963fc3b16a4fcfc9a8c335b5abeeb.npy +02958343-3c103561d9a29ae7ddacb20b6a591772.npy +04379243-66b56ba61af420e654a2b6b20aeaf693.npy +04379243-2da6752496e0c37961c55d3f6d7eeb14.npy +03001627-7144c29cc7038186d67fae5fccab266.npy +04379243-f86ad1699aa2da6dc955e5ed03ef3a2f.npy +03593526-e0855a7115eda487186588b1d2fb9823.npy +03593526-7def3eec9ddc24d7a1c637e821f12a67.npy +02876657-89b12196a1db5a74bb8058680b6b9460.npy +04379243-e751c765bfb096da43f06ece0b2b5196.npy +02691156-2e961e38a039f1bc67711f7c205c5b63.npy +03001627-2c4e9d34472b4bccc16f7010a3b8fdee.npy +03001627-7004f4eb1a5b4a41a5e3e028709e0474.npy +04530566-47c35e001ddd44bf1f2cd7f4ede43a74.npy +04090263-ac6d4b9549853b509a2ee232a197081e.npy +03325088-cf29a33f72258731b7a867e9b35a1295.npy +04256520-44854046021846f219fb4103277a6b93.npy +04090263-39b95d373f0ca2de80c2e60c312b0f09.npy +03636649-6ba931adfa36c7965208aab875b932bc.npy +02773838-766fe076d4cdef8cf0117851f0671fde.npy +03642806-34715b469341fd4ce4b68d3b17c43658.npy +03624134-8facbe9d9f4da233d15a5887ec2183c9.npy +03001627-4521ce028e5009811866a0bc19f46a1d.npy +03325088-14269c9440e416d6b7a867e9b35a1295.npy +03001627-65c7a3d8fb95311c492d9da2668ec34c.npy +04090263-c383dcc4c30c70b41a3b39b07e4b3d0f.npy +04090263-c224535cfe42b795a39dc4a567ce225f.npy +04379243-13c51c08c3695a09eda47978b73f5994.npy +02691156-351e24a503c49840cc0472b5df09bf08.npy +02871439-c41a98460321abd5968731dfb1dc1f13.npy +03642806-6f6c8762f55f94e24145b5f47fac09a5.npy +04379243-83f1ff21744e71ad2690c0a5b39562ad.npy +04530566-ead18d83024fab8deb2c303a0e0d287b.npy +02747177-c27682e5292ce95b7eee615e75bc3b77.npy +04090263-2300f57a06457c092235a9282623d937.npy +03001627-c983108db7fcfa3619fb4103277a6b93.npy +02924116-a8d7f2228ca5e0d944bbf36763afdb18.npy +02691156-fdb87fe46a2dd5ae148cecac5cfe1090.npy +03001627-7297ec6faebb50aa1f285be552b78f9a.npy +04090263-5870c596f2359677d3360026d8a2282d.npy +02958343-9a58eccb0ab51d2fa790ab932daff416.npy +03991062-1a85e0a1a4991a92a2c59a4d90e63212.npy +04379243-9fc9605f6ed5762553cc33364504d5.npy +03001627-5f5a3d412807984a27f9863535eba56c.npy +04379243-4c977a08c3969494d5883ca9b41ac387.npy +02958343-26eb9c499fe0ff9edc10f9c1726304b1.npy +04379243-6965b32c6732f5c0668ae11a7db5e82a.npy +03207941-b132e38eab307f2649ad049dc6857ad1.npy +04379243-a06c61dbd3a5f3a5b903ba10d2ec446.npy +03467517-15222c5926c7058cc6df7dab8e567ef6.npy +02828884-af5bec1a8ce2348663b2acb037dfbcde.npy +03636649-cb4f1fc93f5047e1ecd8a55986a51a84.npy +02871439-b1b511bda428926c180cff5124af98b1.npy +02691156-98b163efbbdf20c898dc7d57268f30d4.npy +04379243-338c59dd95a2e93362e5325f0ce7656f.npy +04379243-394e24e46063786ef7632814cbc80bf2.npy +03001627-cfbd835002da52be8f8c11a24c52ebb.npy +04379243-ac343084fcd0677bf78817f740055424.npy +04530566-2362039302d80f99f2c9de96bdb467eb.npy +04225987-e38a4e6fb32b51a1bebb1fbb949ea955.npy +02958343-eb5e956c2dbd44248bb11dbc05ffaa74.npy +02828884-19d52509d16a9c2c81faebbdea6bd9be.npy +04379243-e75138a7ea380470191dd4460a0b4ef0.npy +02924116-c198f659a9e0694890e260bfe14d0e5.npy +03691459-40169512586f3b6f77964cc933a9a0ba.npy +02691156-47bb2e8a53331a2f3554ccf8c30febe7.npy +02933112-4eb789e7b91d1c7374fd54817454ba03.npy +02691156-4008286f2fe8b6a97c44cd1ce3d402d0.npy +04256520-455fad12d4170e398d36ea78699efab5.npy +04379243-747dd84010a0c34d78c3eead10f81a63.npy +03467517-a0561f911b532556aeafd07a67347f0e.npy +04530566-a28a7d34ad5f006f959df312c935a698.npy +03001627-878eee28ccc28b2e4c7384dbb75cab0d.npy +03928116-6fd1d36339cd6ecebd90a01d51d28fe1.npy +03001627-eacc4fa00a65e56e374f33ec97ba7ca2.npy +03636649-42e6823a1ad23819182816640e3b1915.npy +02808440-353c2a6611d4f72d3321831d2245cf06.npy +03001627-f4e355f3c1acc9f01ec783b810d76c4a.npy +04379243-c359be2db828da29cfcb2cdfd88e07cb.npy +02880940-a29f53390194166665c638ab0bc6bc66.npy +02801938-87d80e10b71ebc1f7846915cc11caff4.npy +02880940-5563324c9902f243a2c59a4d90e63212.npy +04379243-9e3f1901ea14aca753315facdf531a34.npy +03636649-3781aa0aaed95b8049244b68aadec703.npy +02691156-eb2ac022b65f827e5e0925f0d15a8f74.npy +03636649-5f1dec078cee0f78c580fdeb5460f6d6.npy +02691156-79f0a9d3d78764ec19ef6dae2862f036.npy +02828884-5bccce74947b32e38a92622cf31f5cb9.npy +02933112-5e61fc6946ed74c3532e8683617554c4.npy +03001627-6d63b89b904264a15fc64c97c5117aac.npy +02747177-95c5a762fc8624859d7f638b2b2e0564.npy +04379243-74c14e9a4ac91242388406859b1b0545.npy +04256520-a7b07dd40ee6af36747bd07ee1e3f697.npy +04256520-6f48fa0ce33292249ac506757b31ba4.npy +03085013-d0885b3f14be8fbe2070d983a046060.npy +02691156-ddd6c2a51c25036c8a43cd65b179a1ff.npy +04379243-ba212f7bfeb2faa75e05d85b12fbe60c.npy +03948459-9cf4051dae7a46ed77b7d0d4764c121d.npy +02808440-d4d61ab0356aa6d0b362845c6edb57fc.npy +02691156-a2c2ad021c80f08c973e06016b069172.npy +03467517-6cdeed314f07b7a8244cb06b21c0ad9a.npy +04256520-6bb62bdd954cfa07e30cb284f2e8e5bf.npy +04379243-91b12d3af7bc52c5550384fc1c3c3d02.npy +02691156-b34526d94a00ab55f5a25dd70eb863e0.npy +04379243-90494fe31b3db5f927eacc88b2b78746.npy +02924116-64998426e6d48ae358dbdf2b5c6acfca.npy +04530566-b8905c60432aadddb4a8f569bbe9f7c5.npy +02828884-e0ecbe3b106f94dbd2b12aa6a0f050b3.npy +02747177-663082bdb695ea9ccb2a965e75be701c.npy +04090263-56737c6d611f2a8465a6407cecfc902e.npy +03001627-4372b33dfc84c2f56a9ab6fc87e1604e.npy +04379243-6e81c795bb5f2fdaadb72b90b2eeacbb.npy +02958343-9e1e61f67c4a41e09783918b4b55c30a.npy +03636649-2768a3ebfde6410dcdfc3ede082b8a07.npy +02992529-db4c6fcc45cdee08d8dc338f42ea38e9.npy +03325088-d3c3cf0cb64bb51a208dc8b344513a31.npy +03991062-24eb0442669efd9b64558a1c6a2a9f11.npy +04468005-1c05fbffc0d5e60734813c288b6689c7.npy +03467517-919859cf5b204b917ccaebc549d343e1.npy +02958343-d894c407d7fcca0d36294458115cf41c.npy +02828884-894f41b8e4e3231601104cd2d998272.npy +03001627-2fa2acd39067ee788f6e9f07be105c48.npy +02924116-9193a78ba7f6d4108d4003a408ee4006.npy +03790512-2d50553277d64ebda513de4eb79b310d.npy +03467517-ac8b94c2d527dbc47f9cbe01d169e4c.npy +04379243-84f0b08cc2d6747b593ebeeedbff73b.npy +04379243-ed50f2409be0ad022b6168eeac2194de.npy +02946921-fac6341f9e5bfddaf5aaab5ed17143d6.npy +02933112-70ef5ad531624a24cb87a43f8f346ada.npy +02933112-6754e64c37f7318c824662341ce2b233.npy +03325088-f1599feb586c4998321d8e522c85e4ef.npy +04256520-d7bd0812487f786b19c5fea91449201.npy +02691156-f12b45a38f012a78ac4f72bf08dc79a6.npy +04379243-388ea3f8ba27da8b777b6246417c94ff.npy +04090263-f74ef838b3d8388b03509f6d3647539.npy +04256520-54cdb325265e343619fb4103277a6b93.npy +04379243-ea5e7b13d0eda809663191fd557d3a61.npy +02876657-5ad47181a9026fc728cc22dce7529b69.npy +02924116-8c71abeb4ecd7db5e78f6c4122b203e7.npy +02747177-755d669a95bc00c3ad5067eac75a07f7.npy +03001627-6169073a194742c5a7de7deb16b90a60.npy +04379243-e20c8cc35a498acc2ba308912365bc23.npy +02958343-18d2959d79af059e476502dcb0dc5465.npy +02828884-f1102a11687f3451f4fb4dee5181bee.npy +03337140-720fc26810e5755b2846fa729d90e125.npy +03636649-d217e8ab61670bbb433009863c91a425.npy +02691156-764894168678b36efc1619e612ccfb0b.npy +04090263-45e88d85974b540732624d0392494ea2.npy +02828884-5d463e4412600a3213afadfff198a630.npy +03046257-d545c16fd540a91127a97d6c875f5b81.npy +02828884-4a3feda042d94e85319eead4390b3fcf.npy +02808440-c6bdaf60ca0529cdf06b5a8163839b92.npy +04256520-f57c0d39936a324371a782a4379556c7.npy +03001627-20ead42180f1ba43ec7d59bee49bd15.npy +04379243-ba2ed19060724207508ab97c29985b12.npy +03001627-4b9ccf80a846432095bea7c29e873d16.npy +04256520-b6305089d351329681dff5c2e57ad46e.npy +03261776-4beb536ea2909f40713decb1a0563b12.npy +03636649-fe4ca0ab385784d8df6cfab91d65bb91.npy +02691156-17c2d3e052dfe73f9cc1fc25372199f.npy +04468005-f17a4c908714b29dd85b408a8edc983b.npy +02958343-e27019b4147f868dbda733a39f84326d.npy +04379243-2a796094f95904e9c6193dcce7cff00c.npy +02691156-b2235fbc13fc2ae0bbf3143b1cb6076a.npy +03624134-3abac859bebd4d8c63a4dab86bd84521.npy +03325088-140f3e225b12062f3321831d2245cf06.npy +03467517-39eaab6f38e942df5217e44802ac5173.npy +03001627-e57aa2d477a818ed2af6ec758865822.npy +02933112-d7e4b6d1d9ae4336ef4e42d70375aed8.npy +03001627-fff29a99be0df71455a52e01ade8eb6a.npy +02691156-98dd57d068c8de064c3a35cee92bb95b.npy +04090263-9f42f31d3b81ef232d07d103eb3a7540.npy +03325088-aee1330150624d22ef4cb84a0218bebe.npy +04379243-9fc50a184e6d86a9b3fdb1a7c9a60207.npy +04379243-fc472163ea149f8e19fb4103277a6b93.npy +02691156-d47207e14e61db3f1436d436f198567c.npy +04379243-16febbf5498604acfb666b203f8cdb86.npy +02691156-7274be512ba47d837678474be485ca.npy +04530566-7a4fb637dc511c19b1bb46d2556ba67d.npy +02933112-1222c37fc0c37124824662341ce2b233.npy +03642806-53bdcb3c0b28a51b580ee4476b0b0ff.npy +04379243-b40b97894f2c750bdbf8817a0e330a74.npy +02958343-1dbb24dedcb23beab1bb46d2556ba67d.npy +03211117-4d11b3c781f36fb3675041302508f0e1.npy +03636649-5128cdc2e7001b0fd8740cddcdf4464c.npy +03046257-c07b92d1d7930faab594bbf2c494ab81.npy +02828884-e0cefe05e1244097b51974a280a6461.npy +02691156-600f970e5d1032dda4642ec4b6f68a.npy +04379243-ed6dcbd0d670784537a0eda928b574d2.npy +04256520-d8a60e70bde76669e484a3178a372c3.npy +02992529-fa3f5a6c21c56ef7e85fd905d1f6c116.npy +03211117-db13ba7f1da5dace4ad2635b7d12d09e.npy +02933112-2c177b47d18940c735b355b56bb31701.npy +02933112-1d442f753e2d7d3cb90e13b20a8dfddb.npy +04379243-8a09f540491889f519fb4103277a6b93.npy +04468005-5f83375dc5b07b4852470de2774d6099.npy +02691156-443be81bfa6e5b5ef6babb7d9ead7011.npy +02808440-cb6e3dea697f87e55f0ba4cbc0133dcb.npy +03001627-9adb6a665f99addc8a4fd70ea4c8b4d9.npy +03001627-bbd6bde216a2c18479368d1198f406e7.npy +03001627-3b88922c44e2311519fb4103277a6b93.npy +04379243-519d1f0e03a9fbefaf794c3011d17461.npy +02818832-845942aee9bee62b9f2349486c570dd4.npy +02958343-82ede85c805bd5a85af609a73d2c2947.npy +04090263-ccf8ce0be2e03076a49c146495d6b4d5.npy +02924116-25387eb43f6f58774e08fc4ea39c13e7.npy +02924116-e2c4d25593f1173cfa13d53e5e4a7d2a.npy +02933112-18f41e91af76c77de25f00a04866d020.npy +02691156-cef4d41c07613b658168857903a9552b.npy +04379243-114d59f2e865eee630bbd4cddd04c77b.npy +03636649-1f115309bcbcbc5326010ae5c9a5e78f.npy +03691459-cf0da3cd69392999da2140846c49e200.npy +04379243-7dd881a26eea656d193afeeca14e3baa.npy +02808440-19da369ff1db9ecd670204dee97dc037.npy +02933112-2cd30f8ab084d274391fb969ff1ec5ce.npy +04379243-12df5c215f4364b7fe388cf6c4c3705d.npy +04379243-ae4507fa0f4c936a31055213877993a3.npy +03938244-fce7f95d023ac364402d272d6d981f21.npy +04401088-4f3c487c54ca29f2439292e4b8fd557e.npy +02958343-ffe0a5b165461eb66a2345809e2bb169.npy +03001627-baf3304f1352fae41c6aa36e5af1449.npy +02924116-896df439c9dd99914afbd069dad74ced.npy +02691156-d6bf9fb6149faabe36f3a2343a8221f2.npy +03593526-d56098d4d83f5976a2c59a4d90e63212.npy +02958343-a63ae43440751ef444221994b043fd86.npy +03636649-181d2b693d7ab89457a48b78ff77644d.npy +04379243-20bf71868949fba4b445ec1f6a39e0b8.npy +04530566-110acfe04edbd526969f70ba15f2ef4f.npy +04379243-95656a46c15d75592d1c552a8c88e58c.npy +04379243-b1dcc70ae478e417664b3b9b23ddfcbc.npy +03948459-e3f45b75b688bf33794921644e32aee6.npy +02747177-b1625cc91f9355fead5067eac75a07f7.npy +03636649-fb4043f7fb8257d8578d107c71db28ac.npy +02992529-c3c5fd4ce226ab0c4694b8455e89054.npy +04468005-f1497874764c9d964f57a4cae005e56a.npy +04379243-7683778558cc36163fb0920a55a7e805.npy +03325088-dfbd28a1b03b488950da8b99982a3057.npy +03691459-dd2a4c416625f29c4f57a7ededfb3bde.npy +03593526-3b5397782a5a1145fdbe2bf897d8a820.npy +02691156-7a3da3c75d98e44d7d64cad20089f027.npy +03001627-b5a741e11438fb83d155b73c25b81001.npy +03467517-51abcb617b2faf3a24eeca91f583600.npy +03797390-f1e439307b834015770a0ff1161fa15a.npy +04379243-a0745770bc3d12477b11ae648ea92233.npy +03001627-4217f2ce7ecc286689c81af3a850d0ca.npy +02933112-906d4fb94d86c4f0f0c255b2dfb0a92a.npy +02992529-6456bafbb5a656fc487f00a15f77c99.npy +02933112-2988d5b3d61d80c276555d27f71ae823.npy +04401088-7bd9b1b1297013ed65f78a217bb320fd.npy +02958343-65d6433043c40046b82c0841410a924f.npy +04379243-9bb646155fe7afd84e55f99914fbe961.npy +03928116-d26149f3d01ffb4d9ff9560d055ab12.npy +02828884-c32504d950d54881c3331c70c9cf7624.npy +04379243-44ee5a33ebe173c4d28a525d8260e58.npy +02958343-706083fa2a8c2b50bc97decb713a2619.npy +04256520-7d756e083f671c091b17743c18fb63dc.npy +03761084-16a1355b8749dcda33f93820d08ac745.npy +04379243-ab76021d53504f38f51f77a6d7299806.npy +03467517-6c3cabefe5c12e5a972e15b580d9a5b3.npy +02992529-ef2472e661320b03e324fbf60278e45a.npy +02958343-5da4c0cd066b7d0889d347432ecb438c.npy +04379243-7c42d9809322b3993002761e7a3ba3bd.npy +02958343-5d6160c6e87be84631d01cb0ca6cb2e2.npy +04379243-25b6b28e3b70be1c5a6be9e325f087ce.npy +03467517-5cfe03b0754039625afc17996a7c83c5.npy +02958343-43553b5efc2674cee4b68d3b17c43658.npy +04256520-c8caf9f60c19157414038d588fd1342f.npy +02691156-9d06f4ff9f1e7932941d71475449eb25.npy +04256520-7e9f11492f1db0e5e81fe3f8835bb5ff.npy +04379243-4d393b562df7cfad9a16b095d67f7209.npy +03001627-3b3a9f4e3aa9f2f4d39a194653571dfc.npy +02933112-973023bbf9c6a603c59350d819542ec7.npy +03211117-31f688edc350505191cb6690cc7eb18e.npy +04379243-93e81005c19a74b8664b3b9b23ddfcbc.npy +02808440-d970177e3a932dc344221bef0fa3c36b.npy +02818832-cea6fe3942aad10f529a225c2959bf7d.npy +02958343-c00e0066715c2226921cb81cb1632a5e.npy +04090263-fffbe09e4890f8f36314c3b6a3a65519.npy +04379243-e7e0942dddd1e709cc963bba1556032a.npy +02818832-9f7809b9eb2745895b142bfdf8ccf55d.npy +04379243-4fe648810cf1b4b5f4ae8c93f4db5e6.npy +02691156-69f1d9c3987d429e5e9e2656aff7dd5b.npy +02828884-8fe23a363bf80c48f155d75bbf62b80.npy +04379243-8b07d458499d63f36d96c6cb347d6a90.npy +03467517-7cf22bda34c2419de943333e8b45c296.npy +03001627-38141adb391a039ff3c330baa382ded9.npy +02828884-2b6ac3eb1232e99b3cf1509e0eed7683.npy +03001627-6cf3b41688dfc4b4707cdefe012d0353.npy +04379243-2c7817c16702e57188e7efbf7ff736b7.npy +02808440-b906bf01b0f9949044221bef0fa3c36b.npy +04379243-39f03b3ec91103af33367a1c9ac6c143.npy +02954340-e7e61ccc69e18440a52821bf1aa3b19a.npy +02992529-f4eda7905f55d1b382476058422e4a4d.npy +02992529-ab3ebae8a44e1ae8ca47cd18decbac61.npy +02828884-7d67ed4517c1d702ed98cca8f0ccd5f7.npy +03636649-aad04909cf72df68bd038489dd82490c.npy +03001627-963452f2fc2a74f62a3f8f484e6c5c4f.npy +04379243-3bbaad82416c897d82d19a07de9030f1.npy +04379243-da90bb35949fb45ac3bd24f986301745.npy +04090263-902ca61bd1f216f32511f68da65f4c4.npy +03211117-817aa43250590b38b3425db9d50d5dff.npy +03624134-895a4c3fd403f9c63edea20a1d0ddb66.npy +04256520-3abafff866f9319d19763227d95ac592.npy +03001627-a339a318c8a40fd4eebb133aa4be217e.npy +03001627-310c65506936cc5bbe5e5822eaa1366c.npy +03001627-64eb6d8212acb69fa094848ea4d06501.npy +02924116-e3d35f5a569095e182dd3c4188947bc.npy +04379243-bc1ff7fc750617d690f7bef12e52ac08.npy +04256520-fd2596a60338b08b318694f1cc6fb1f8.npy +03046257-9bd39bf4d0072abacda14cd39ae8c7f.npy +04256520-7d019d0342f8a70f3bec56bff764ba78.npy +02828884-84d8530355cafc8fd838ae16242881dc.npy +04379243-c43868d3e8ed646f4510596cb4be6a33.npy +03001627-dff768695c3013aaee3907b60a74e8f8.npy +02992529-638695025ca04d351d57a73214dd2a04.npy +02828884-218b98805019ba7df11e0e33e4b1b85c.npy +02773838-71ead7f072106c63ed13f430b2941481.npy +02691156-a99ffd1b1fd121bcf2b0736dd4d8afe0.npy +02828884-d8fe288f137ccddc1c57d18f89ad9dc3.npy +02958343-517dd2b0fc2aa4ea8f01fef4e6f571a0.npy +04256520-4a463efb8baf30e42d19175e7d19b7cb.npy +04256520-735122a1019fd6529dac46bde4c69ef2.npy +03948459-e1c06a263876db5528881fe8c24c5c4b.npy +04379243-f41ead4917ec05a149524cfd5973a145.npy +04460130-1f1f62c52fe4d27946fb3db517d0dfc0.npy +02808440-40b85440de55df08b05d6ed777b5533.npy +04379243-452d4d4dd64dbd32d12d3a3073d6ef09.npy +03691459-83dea2f2561fc2fbe9364d19fabb5f00.npy +02691156-18e6f319062ccb49ca8607f540cc62ba.npy +04379243-da745fe2b26f5d9b9ccce4c6d5bb195f.npy +03991062-6dbdd4270e16cb9425ebd1cd0b422e32.npy +02691156-89e0a038b52184e04f856435f28995af.npy +03001627-6cfe2f5ab1bb89022edea1c2bfa3bc56.npy +02691156-ca8c65b83038dddb17486544d154bb2.npy +03001627-ce387113cca9c0754d33a7fd9c37a7d2.npy +02828884-2eea9c22b37967006e40121acd58a004.npy +04256520-91cace4fc498690119f778c7a8b12264.npy +03593526-afce514f25812205c9f016d57db96408.npy +04256520-e42f4a13086f847be55735bbf02fe10b.npy +04379243-a53650752c2d73ce83eca490ad2084.npy +03001627-1007e20d5e811b308351982a6e40cf41.npy +02958343-732606e13ef11f465acf55f30acc008d.npy +03001627-88e514e71b48738bb022c94235bc8601.npy +04004475-2e42dc81abb41b06d483b3bba3d3c62.npy +02828884-f5e4f9657ecc18efc862eec8232fff1e.npy +02828884-784e9add253365c15a7771962bfe7829.npy +04530566-fcb10d77160ccc67dfaef96860d73193.npy +03001627-8f1e882bdc10f54955f46d55537192b6.npy +02691156-aad1733e7bc7152bcc14f1e6f4f4f49b.npy +03691459-b49306bfdc0d238076247c6336e7c242.npy +04379243-121ae3ce921a1e43ef40aa033482abea.npy +03642806-9785a579ea791039c639c533e8b5aec1.npy +03593526-54ae704d4eee561bd93768e7b9b1eabf.npy +03001627-ef1824754ae554af83b6e0255ae357be.npy +03948459-1171db047e43948b40aa5b072f9ee3d1.npy +04468005-6a26d2eaaf63d2a7b2faf16541f353f5.npy +02924116-58a477292dbfae96f2b46e2da97eabda.npy +04225987-e421c23a2c02cac61082f2ea630bf69e.npy +03211117-d89d1059b23e8c60edd8d267b4d8ab38.npy +02924116-8b44e35b773cd888bc7f39bf011e847f.npy +04468005-7f31a5c189a4c95d93cdde2be60b3ee4.npy +04530566-ba3eaddcf1a2e829fb64f9487ce62dd2.npy +04379243-8acbca7ddfd03dc85d009c98a5b96836.npy +03046257-e905eb10294464464b3c42e318f3affc.npy +02958343-37f9b2735bc9e80eeebdc06b146e1752.npy +02691156-83dd9dd45724d5fbbeb310a83b693887.npy +04090263-60c856b141ec1e75a5bed5eda256483c.npy +02828884-b7fd9faa8c78806da9bd18a6c1eb0c1f.npy +02747177-544bb6c9c8ff5ebd6c63a10c02702cfc.npy +03001627-30378faa6bf5b245fdef1c01cbd4ae0c.npy +03636649-b8c87ad9d4930983a8d82fc8a3e54728.npy +02828884-8f64075972a1f7f3dc18af6f6bfce3ef.npy +04530566-14b8bed0391dfe1dfa808b0b90ff6379.npy +03636649-f10af3d00a4c3e89f51f77a6d7299806.npy +02691156-723c87de224355b69878ac4a791083c5.npy +04530566-df63e149e706e3741556f795d265590.npy +02958343-ccdd144f89a78f5c554ecfc23d9fc570.npy +02828884-6bc471eb8f212c9317b431cae0dd70ed.npy +02818832-d2e248e53274bcd5ec223fd6ddc5969b.npy +02691156-3fe8243b660d5e8fbc0909d98a1ff2b4.npy +04379243-9140c6a8599f28fbf27a87e2aac4fd31.npy +04379243-9ae7f60bc9e20008533841f5cdbf3b2.npy +03948459-2987ca2166327746fcfb3ae2df2f7efd.npy +04379243-c65ab1fc77cfeb37f7c07d2e56f26a5a.npy +03642806-d122ecd3c34e87eaf76120a09d6a0db.npy +03467517-ef87e50f18f1407693f0194265a9746c.npy +03928116-6142342e876a0f6f4b695ac31691771f.npy +04460130-9e72b97a5af45ded7c272b953086dacf.npy +04090263-4f4cc3462f0e9dccf13eed41b64dddca.npy +04256520-7162718ec5f39640701dd519cbbba0c4.npy +04379243-53e06d7506fa12f93fc9a2b2d10317e7.npy +03001627-5822ae77b06bea3091da37ff8bdd2524.npy +03001627-41aa5dba48b7a3f683257865d0a50551.npy +04530566-a13e0728cbc8a41594ebaf95f022dfde.npy +04401088-f400eb5421283e8a102f4912aece242b.npy +02828884-10bb5f29a8654f22ad5067eac75a07f7.npy +02691156-43c5f85e9a10071cb1bb46d2556ba67d.npy +03636649-5859f1dcc6e47322e7c7920f6a65a54d.npy +02818832-f7d2cf0ebbf5453531cd8798c40e5949.npy +03001627-b631b78c2dcc748cba5342d638d0c267.npy +03001627-562b11f6f1fe56ce586a8827cb5b82bf.npy +03001627-29876b641047897f9bbef973cc1034f9.npy +02828884-e70d19625546502bed98cca8f0ccd5f7.npy +02828884-38e54a16698453baad5067eac75a07f7.npy +03001627-e8829b6a1601c109bebd676e3a69dcf6.npy +03001627-96bccddaf0034be04e5cf15b26e670ad.npy +03001627-eb29a065b495dffc85528d560ddea455.npy +04460130-de24d2498ff052c3fe10598e9bcc69e4.npy +04379243-dc0e4a9d3bb0397d5e994da5ba753c34.npy +04379243-bdf99b327d1079fb35836c728d324152.npy +04379243-204d9ecc196990ebe8479ad2eabcbab4.npy +03691459-d7233f2190432638d747b49524a1246e.npy +03211117-397644e58faef380e441f5bb6f88ca61.npy +03636649-eb37d11948d7b4ffe030fd2fa0608452.npy +04099429-2407c2684ee757e89c4176ab56cb612.npy +03467517-1f08ecadd3cb407dcf45555a18e7351a.npy +02691156-fd95b99d4699430a7395d58407f193ba.npy +02828884-7e029f73e9cd98d2f155d75bbf62b80.npy +02691156-caf92880cf63690188a7f6dddc29eab.npy +03691459-7b08e64e66cfe5d473c609379da5b9c2.npy +03046257-c34e4038969908b6daaccab222ac90bc.npy +02924116-e24cde6d0dd917c8a49d11719fd4710a.npy +03001627-d73e46e07bdb3fe75fe4ecea39e8bd40.npy +02871439-e6f306e6f391ace7b035d20a1a3ca345.npy +04379243-c0fb01629cdba5ade6c5cd45aa112726.npy +02958343-5410d4faab53ce49e9d8921ebe6d5b8e.npy +03991062-fa9e6aa9d67d5329e5c3c7284848bbfe.npy +04090263-d8e7f4c92af18cf2892fde398a8eab7b.npy +03001627-cc03a89a98cd2660c423490470c47d79.npy +04401088-d7c350e5d29074c9b4c216fa1de7d5a1.npy +03948459-d81bac8b449807bab7b81b671e901c39.npy +02691156-1d663e36e305fa8e2178120752ee7a07.npy +02958343-3ed25ebb78e48a84ca92a4cdad802b45.npy +02691156-16ef481509c64f845dcf422dd1ee66d9.npy +02691156-6cf339eb8c950ac5d556fc099c90ab45.npy +02691156-d581b2e10f8bc6aecc1d733a19631a1.npy +02992529-987662da7f345b272b1c9d869bc37167.npy +04379243-a0a17ed0d2367f433c40408002fc3026.npy +02924116-1984914daabaaa44afb5b09d8f4dd829.npy +04379243-25b9dbd6cab8f22c37a346dba83c013b.npy +04256520-7b5b2e699dbab90d1ead5d83d8c2f7da.npy +02933112-768564ef92377d886549bee1ee0ae3d0.npy +02958343-2180046932174984a10cf495b6dc4ef.npy +04379243-e731318d8d28bd585913832d290e62af.npy +02691156-995d06b3afb755eef446f92b52bbd82a.npy +04256520-6923a7384068b631d8e0f7676099972b.npy +02992529-7bf76e92b684d32671ab0d8014490a7d.npy +04256520-9156988a1a8645e727eb00c151c6f711.npy +03001627-8c2e0684a98bd4f82553cc33364504d5.npy +04379243-a5475eec7a98a02671a70be9f12ce8b0.npy +02933112-78d36740730c94a4490ad276cd2af3a4.npy +02958343-5822af4cda46d8c2f952aa5aa5267659.npy +03642806-129237ff9e4f5d5c95b5eddcdeed8f43.npy +04401088-eed72e5bc3dc4e85150c05906b260c9e.npy +04330267-5609319914f7d84a14ea9baefd0742a5.npy +04256520-30ed3ecec491408f7ea607586f414f8a.npy +03001627-58ad100d70e436bece93f2bb0b6d036.npy +03337140-94507a5e4ec17da4c3aee8e9d3a6ffa.npy +03001627-32e6139951627142a087337e55e3e2e.npy +02828884-79f02eae8c5b417d756b36dbe53a2798.npy +03211117-d58e51e184fcc1a2fc30525e763ef5eb.npy +03636649-eca8e4d9645271fa37b2bb75885cfc44.npy +04256520-3fdf33059301e1d248fda83c10428379.npy +03691459-9376e8048ae8b34ea35fdda2e8d5933f.npy +04090263-f5a9d847f69449626f07a69f0bbe0f4.npy +02828884-c2b18cadd355a5f18aaae3d020f5ddf8.npy +03636649-2b79c0ed9fc840e7e64208ea01814e71.npy +04379243-5b5fe86aa8e93f91c3bd24f986301745.npy +04530566-2e6a74a610868d5be1e91cfa8fea7dba.npy +02924116-437de36c15c08707294f9f1b885d961a.npy +02691156-1286826ff37699a1a0d713eb26379316.npy +02691156-2628b6cfcf1a53465569af4484881d20.npy +04379243-598e49637250f85d58df8eeaf3dad1c.npy +02691156-17e66cd463ff0de126360e1e29a956c7.npy +04379243-1d53223952ac93dc3bd24f986301745.npy +03325088-37f385f455809ae4b3ab5a380856c75c.npy +04256520-8a1a39223639f16e833c6c72c4b62a4d.npy +03691459-b56efe51e12dfcd72c730e00f4721fb5.npy +03211117-f4955005fc3fa1bb64b3cbf502645c74.npy +03001627-41ce60d5443c203eb31c248b8665b2e7.npy +03691459-28c30025290a56a689296e9c8a412e3b.npy +04379243-5ca423c2f3d176f94c5c5c89015f1980.npy +04530566-f72222b43e40e7e84cd259bd328e92a.npy +04379243-c5e37e895124731176e9713f57a5fcb6.npy +04379243-adfef21c37071016b4c161851ed2b4e4.npy +02992529-205b1494d7d3448e21844676433a0aca.npy +03467517-2eba922263fc1580cc010a80df5d3c87.npy +02808440-4e77f04af9f378fd6bae7522bd91c859.npy +02691156-8d5c3d38de9c3685f2e77d54f4da142.npy +03710193-242bb92902054a0142b99c0f2f4f9b4b.npy +04379243-245a4070c930aaae71e2498adb56e791.npy +03759954-c0aaca906293380f1242824b4827fe77.npy +02828884-87c34f2d5d53a51768679c90b064f491.npy +04379243-eba66ca2e46521ecb16ea05e48de73ee.npy +04379243-74a73d264fb01b188ad2a89943bab6f3.npy +02958343-f4532b1f55191eb7b9ad5039d820c924.npy +02691156-5fb64e3fc0abe449ca8607f540cc62ba.npy +04379243-5b349df34184e7fc2ad490d4d7fae486.npy +04530566-a5a16ec8ebc811f1aff407511d7dfc96.npy +02691156-f214cf57d5d5634960e1e93111ad3e76.npy +03001627-99848304f52de660a26aea0642029fc.npy +04554684-2e9e2ff2b757fcbc23a5a908e4c7c27c.npy +03337140-efee783f896e804791c352d02061b3f7.npy +04256520-c46a4ee98bad8264925bc492489de9c.npy +02958343-18da5e80080352be294d52e32dbd135b.npy +03001627-b83bebb013e4ddcabd1aeba6ff85928a.npy +03691459-fb2755146e61262fd50505ee01b106d8.npy +03001627-781677297ef4db1ab0b54dd2cf2a35d4.npy +03001627-a12d6ad9561fd39bca2bec46a3b47519.npy +04379243-3ec4be6e96bfc2512b5fb024f65f6da.npy +03001627-e1ca70ecc629eb46ca17c984d94453b4.npy +03991062-aa2c5cf4461fc4f8ee66deb6ff51e301.npy +03001627-71539c627eda703490ad276cd2af3a4.npy +03467517-ba597e1578fdd381bdb7b8a99c2de3d8.npy +04379243-f22cffb7f3ca2ea1d719cc16de395dac.npy +03001627-ffed7e95160f8edcdea0b1aceafe4876.npy +03001627-371ebb9ac02ecfd09710e093c764abec.npy +02876657-20c5dff3b09282035b76194468418a0e.npy +03001627-928678562a6a57db698a862d11861eaa.npy +02958343-835d8e35119c714bfdb3ae79bdfd4e2b.npy +02958343-4d39e6f28ce8970530515cb6d98a6c44.npy +02876657-3d8444d8717cc0b7c18cdaa4851a3c95.npy +04379243-46dababb078a797011ea7f12f22c0e84.npy +03642806-72fb4ce0b33310b4d852aca19c37edcb.npy +04090263-c391adc028f6a3df9a6e43b878d5b335.npy +04468005-409108700a3135159854ff9122ad4a0b.npy +04256520-81bb52e7a83d1b3e9c75eb4326997fae.npy +02843684-be167ea4f0718058b4501871f1444d0b.npy +04379243-198ff59a42a147eb8ac5948d70801389.npy +03991062-2392637006a99646d93e521f7fd48fb.npy +02876657-621e786d6343d3aa2c96718b14a4add9.npy +03691459-b638ef590025961f5adfd0d9df77c16d.npy +03691459-21e46ca2f8bbd4df71187cb9cc8e1a.npy +03001627-b467cd6baaaf5bf282db9fca4b68095.npy +02958343-301d1c48d321d29f5d2921c9c16f3c69.npy +04401088-df768d07fc99eb30142bee3d28727203.npy +02828884-b8407ab7eeda1d261be4769a83930a08.npy +02933112-50c7e5dace1d5dffc6256085755e32ef.npy +04379243-7df8028783ecc6ba6d5fdff4a5ada0ca.npy +03001627-f3a24b3131da1ce619fb4103277a6b93.npy +03001627-7824e41c86f9be776383f517a315e69e.npy +04468005-2349848a40065e9f47367565b9fdaec5.npy +03001627-934d183065b149d784e40fd1beec9c4.npy +02958343-8e9f7699e30cdd8c247a5be450795511.npy +03691459-f1d170b03b23a3139cdd3031da0f98f5.npy +04530566-f2db3a2fa09b459a91001ec6a6afb362.npy +03636649-475a3d88004052918a6353ea60f11b6.npy +04401088-3488722618d61cacd5b6fb666fe071d7.npy +04004475-c7a99991ddc26427c22cdcb8852569c6.npy +03001627-51c276e96ac4c04ebe67d9b32c3ddf8.npy +02691156-5c10e37453733ddb46d83d16be057f3e.npy +02876657-5470f2c11fd647a7c5af224a021be7c5.npy +04379243-105b9a03ddfaf5c5e7828dbf1991f6a4.npy +04379243-8e28f1259c6572b86cdcd27a8d5231b7.npy +04379243-e4b2faf6b123b90286603115d2739530.npy +03001627-d7c9ad0bb877b0796c9d2c8251e6074b.npy +03337140-879c6614916fb6907812c3baf25c5bb.npy +02808440-77e0932f0886aede3321831d2245cf06.npy +03467517-d0f1b3ecae66a027b45664be560bdedc.npy +04379243-6c0bc03812d3209fcffd61677456447e.npy +04379243-e1e7caa05e80e973308c1120d480c5b8.npy +02876657-f83c3b75f637241aebe67d9b32c3ddf8.npy +02958343-d6f754f7ccb42b194fc7cbcbd24e4ddd.npy +03636649-5c79a2bc3d2ca6b1df8d3317f6046bb8.npy +02876657-991d9df5bf2a33a1c9292f26f73f6538.npy +03642806-de9a39e8ef9c313bbba0ffaa383992dc.npy +02828884-f13e44c93bca57d092f4c88fd91c6b1b.npy +04379243-69c536d9e450cb79436e6787c76ef3f0.npy +04401088-8aa05d2bb435ab441ac3fdfdb76cf4dc.npy +03624134-4611d319dfdd29b52ee0f9a97b71d505.npy +03467517-5ed038fc12ed2fdc34003ec0e4a84348.npy +02691156-886942791e830bf1d32b1717fde97410.npy +04379243-f6ef4614e853eea9de712e1694f0a344.npy +02691156-89836a37ce10a26c8699933784576e73.npy +03636649-66111d2c7a23b0feb404555b84577afb.npy +04379243-f9ac7801460434b271140e10b6211a6a.npy +03001627-26f798f908ef2908c7660a81296c2300.npy +03001627-1093d35c2ac73bb74ca84d60642ec7e8.npy +03636649-896abd405c79547086485c798787f66b.npy +03001627-5c52a6b471eb82b64ccf4672ec1e7efc.npy +03001627-f9b462997cb333dc7fbc060fd555478.npy +02992529-9b608bcc7e62c3e2dbe1e810cdc7471d.npy +02992529-e4a8822c5faa386fa9976d676758bbee.npy +02880940-8bb057d18e2fcc4779368d1198f406e7.npy +03046257-10a200395145c61aea2f5d52559debc.npy +03085013-4ed5011d30d0bad8654d740782c268f3.npy +03001627-cf09618aedde38febda72093f9b5aa73.npy +04090263-20ba04acfb3a2df63fa974f1d1a1ac62.npy +04090263-5b466dcb5113a0704aef47a2c7bc343b.npy +02958343-ba89184f58f21ff63343f5fadc4a2136.npy +02871439-908c0b3c235a81c08998b3b64a143d42.npy +03991062-f8e09cb026b47fddd7f470ee20dce9e0.npy +03001627-8fbf9ce2c9cb77bd9cb48411c757aef6.npy +02691156-e5610bbacaf098508b96ae1a0a8b84ec.npy +02691156-7c67e8cce3f3eb3c89ba278a735b3c5a.npy +03642806-afa49e97861c45e5e738f481f8560d58.npy +02958343-86ab1c2ea989fda9ab15905beabd3f20.npy +02691156-b522108c4c08430a71d03b466c72ce41.npy +03636649-8d61e7c8fc9d989d1f30b807ae39b61d.npy +04379243-cd762ebd8c8ab61361a38c5058945a3a.npy +02958343-872e01a1c34494b737fd267fe4b3a5ee.npy +02958343-18c06b8c38623c0b4046e8fe9dfc34b5.npy +02691156-f0065f4f9e20d604521546825315c695.npy +03691459-548f94cd0c5fba501148996e35417db6.npy +04256520-7fd704652332a45b2ce025aebfea84a4.npy +03001627-383b4dbf090a73dd597eda2e51f31317.npy +04379243-d8f851bbc98dccc23fa92d98173c06f.npy +04379243-6aaa78b81528f4846674ff79eed6185a.npy +02691156-c156719444d78942db73445864b72015.npy +02808440-8fe4014c96a06f2a57ed847bfc43a483.npy +02924116-a67672775a7fb69a973f659238edf3c3.npy +04401088-9b74db2ebc90ae4789905122ac8b41f3.npy +04530566-9c3810b8bc98c59426fa791c6af15500.npy +04379243-5bcb0976657fe6df37b2bb75885cfc44.npy +04256520-2b5d99fd8dbdb44141cf86c757faf4f9.npy +04256520-4a910d2734c9cffb44949d7685cb63ea.npy +02958343-74f396cff021c1d2651e8da9cf70afea.npy +02933112-321eb85037156544799b0b9a0d4a12cf.npy +04090263-58c5409f614e42bbfd88a8f742d6b88f.npy +04401088-2acb9ffbc050ac2e48bb2194a2a904f7.npy +04460130-7c78b826f0f46ef3b6b5161efde62bf9.npy +04256520-5ca1ef55ff5f68501921e7a85cf9da35.npy +02958343-6cd6f11fe76058089ed785be4fd72d3.npy +03211117-ab729d209e3ebe2fb3cfe9e599b99e13.npy +02818832-7121c556308b16bf158482250c99c0b3.npy +03046257-3746592c1dfa698d49493d905c02fa86.npy +03001627-1f438263a82a1b8919fb4103277a6b93.npy +04379243-dc589e1223aaa5e65cf2470a6eb9a24d.npy +02958343-abc42e7c5ffaa41d1466737d5c4b4246.npy +04379243-dec59b04dd663d5965bc5e8933ad03bf.npy +03636649-16efeb266e249dd63a52a79d6f5aab84.npy +03001627-17d4c0f1b707e6dd19fb4103277a6b93.npy +03636649-608b5df0d5946c68400789f7122dfdab.npy +02691156-f26ea1a00455f44fb88e2a19106395c2.npy +04090263-d8478e58902d241ae1ca70d5205a82b.npy +02691156-172764bea108bbcceae5a783c313eb36.npy +03001627-263f629d385be2b1601104cd2d998272.npy +02958343-3dd52c850785a6ebbaf1745483a8b34a.npy +02828884-2355964634eba1da35eb9316401353ce.npy +03642806-a520b985d944cd3bb74e0ee1cfdd5ad0.npy +03624134-b93b611092db370248b901354fcecf30.npy +04379243-ac6f632b60ec643650fa82c2f036109a.npy +04256520-5eb193a332576b775e333fe3dd3959a5.npy +03691459-291b3dc6e6f0d5a7b249ecc7669d184f.npy +04401088-a19763322fe669cc7e51366b0cf7747.npy +04004475-c2951ff7d0b04515748e58db1ff83cee.npy +02933112-8914b82447db43a8c59350d819542ec7.npy +04256520-1f741437c1dcadc82d19175e7d19b7cb.npy +04379243-21b8b1e51237f4aee76bc197b3a3ffc0.npy +03001627-b7c8be9dbe5ff1d540332412c5d013fb.npy +04090263-50e559a32e81e8a9cc57882dfaef8a57.npy +02933112-2620701a50216dbed0b36851d61b6fca.npy +03948459-2bde85cb58bbee99f307c8df193268ee.npy +02691156-53c27d3031f6f97e402be9c8dff728f8.npy +04379243-e3f583837f5bb80a5526f91aecc0c37.npy +03001627-52c4af69336f4d6de9deec47d8412ee.npy +04379243-f7ff2f9bb62a9f5c96de5fa2ca080bfe.npy +04256520-aa26a6735be82e5da7de3fd12bcc8851.npy +02876657-831918158307c1eef4757ae525403621.npy +02828884-6afb907e76102e222056b4bd5d870b47.npy +03001627-75f32479a35f39e9f43d965e3ff9c5b6.npy +02958343-ad6572f7ac90b9bf2949d5274e5ab643.npy +02933112-5a60822959b28856920de219c00d1c3b.npy +03691459-5a66a86082033c79a3acdfe62acaaf8d.npy +02958343-4dca2e572dc278d563f2c3a55558a78f.npy +02828884-ab3260f85c28adc82056b4bd5d870b47.npy +02954340-be6604a272cf945bf691615c36cac509.npy +03991062-d0dfc32cbcfd0ce753f884bab27d0f61.npy +04090263-313b61a27e01ebff0fea2ee98610322.npy +04379243-70c02e8ff7d19554e6fe3612af521500.npy +04379243-d11363fff4e2dc6589cc5332e945f058.npy +04468005-7addc3adeb16b62052470de2774d6099.npy +02691156-4ae3b41081645ca3e70b97b9b33fd6d6.npy +02924116-ad3c65e1f488f5af37277701a400254a.npy +04090263-a99df9868677ced6ffe50f88045d4553.npy +04379243-6718e0bfb822e591738e43095496b061.npy +03797390-24651c3767aa5089e19f4cee87249aca.npy +03001627-c04660caf4670baed40fb6f8053555de.npy +04379243-f88dca28140a1685490ad276cd2af3a4.npy +02958343-c1ac2aee4851937c8e30bdcd3135786b.npy +02691156-1974f6955c36c2aece2cec85ea6ae00d.npy +04379243-6187d4be01231460a341228b21d337a9.npy +04256520-717e503b3846d60ee8f8c11a24c52ebb.npy +04401088-623bc1157836ddeff8a51dbffe0021e4.npy +02876657-81bbf3134d1ca27a58449bd132e3a3fe.npy +03636649-a18b996f56dbc5cf37b2bb75885cfc44.npy +02958343-2cbd461545e71ffcd3b83549e73dc79d.npy +04379243-5dca7ed62a72a5fe81a172d69c52a28a.npy +04090263-69237e82dd3f7d3f8a5e49d8f4867e8f.npy +02691156-60f99c0946c095e833b2a295000cb6fe.npy +03046257-b31efa25b43918d59fceff51518181d.npy +04530566-751aeec5f1d50668332d76467c18dfde.npy +03691459-b521957294cbb170c7c1bdfb41b9d2d.npy +04256520-e352b0882699b66a44db04bfb021976e.npy +02933112-6ec7c811025a30a2e3a031805ace4a99.npy +04379243-95112920a9ab9c24f8555ec936cd4b63.npy +04401088-ee7d2d986f2c989ac66dc18b3cf1700.npy +04099429-b5351d041405a64421669bcdba443569.npy +03001627-e39df7339552595febad4f49b26ec52.npy +02691156-3844797c89c5e2e821b85e5214b0d6a7.npy +02691156-20b91c5ceb005cc44947b319a9e09fd.npy +03691459-d6cd608c3c75afd01ad88f716ea80910.npy +04090263-f06f841de5e202e5a50ef3fc203c6ba0.npy +04379243-5ec6da31cbe72c7f492d9da2668ec34c.npy +02924116-f61fe8b152f5888a54f791e4a421252.npy +03691459-17c472a6899c92efcf39ad4726172e1d.npy +04468005-ca7432069416afb23f990b83d396f8f4.npy +04379243-497d75f6a5b0c25077cf3bb06f394ad.npy +03001627-8e21f7a88cecf4ab5ef2246d39b30aec.npy +02828884-8aabc6c97aeacae7ad5067eac75a07f7.npy +04530566-76dab7acad83682765aae3dfe86a49ae.npy +03636649-d3ca8a5d2e8c8ba4a320e34dad7c78bd.npy +03046257-9c3e6695a5f258a7f51f77a6d7299806.npy +04379243-4d6a3cb51ac2144dd47d15ec8813fdaa.npy +04468005-91ceb1625c27cb275ef7a7d3024ae8f8.npy +04090263-e91264640374a2716a0207b46ab78ca6.npy +02958343-f49155170c175dff176be984cf2a7f4e.npy +03624134-912ddeb6b325df6aad1d0cc319eac33d.npy +04379243-49ce1344c3c8a652f9883d2fd957d60f.npy +03001627-2db8006b905b54abf88a016bc446405e.npy +04256520-35e15a666990625a1aa34bfa6235956d.npy +03636649-f7093dd024fd09fc7219d6d5c4afbaff.npy +04530566-b2f200bd0861e1daeb78d3e0a9401d4b.npy +02808440-6989e5532cbdbbf344221bef0fa3c36b.npy +02992529-85841bf9d27c85a26062f54263899d21.npy +04530566-50f0d14029f7f7be450c3626dae37aec.npy +02871439-dfdc22f3fecbb57c5050d6a2f5d42f74.npy +02992529-a635a6b98eda6c1fa436566ba711d6a7.npy +02691156-3572e3fa25911295922e63c830b776de.npy +02691156-a7751857e571d6bd3c326782eb2d380e.npy +02958343-731efc7a52841a5a59139efcde1fedcb.npy +02747177-d756ab06172e422fa1228be00ccc1d69.npy +02933112-8316451b3959184963be0260dd648a5e.npy +03001627-663b17baebd39695398b2b77aa0c22b.npy +02691156-14cd2f1de7f68bf3ab550998f901c8e1.npy +03001627-20fbab2b8770a1cbf51f77a6d7299806.npy +03991062-bb5f7de6d079f8e2c054c46f3dc261f.npy +02992529-abcda75b9f826fce8dd7bd77b545a577.npy +02924116-1b9c827d2109f4b2c98c13d6112727de.npy +02876657-1d4480abe9aa45ce51a99c0e19a8a54.npy +04379243-6c8d4952f67d47f56bf829b05be0ce22.npy +02691156-50040de261741893fb5c1b0f759e2bc1.npy +04530566-c554a1d4895b67b457f5c96598c7eb45.npy +03001627-3c9747ff49d0da71f91663a74ccd2338.npy +03691459-88928666d9c3939dac55321e2e1cf09.npy +02946921-1beb16ca4f1fd6e42150a45ec52bcbd7.npy +03337140-d75c5f5cedcacf1a91c352d02061b3f7.npy +03636649-39583310660349282b6168eeac2194de.npy +03001627-bb660ca2ed9e0155f51763a096bdff1e.npy +04554684-22041d5c50a6a0fb91219aad82abc053.npy +02933112-dfb5415f3bb999a4c59350d819542ec7.npy +03001627-70bf905fc0d62ebcb1ab5f3e2ac4cb05.npy +03636649-646956f902b2a134450e3da30d6676cd.npy +02871439-14f0caee76872a89571be7eae57ba8b5.npy +04256520-d863bd46db86b9dc2906e6acfda251cd.npy +03001627-9dfaa9b599fced446f1e07a56c129dfc.npy +04090263-e502392ba0ba05ac683e3750b53385d5.npy +04090263-7a1e38f9d85548e256c58b78d29fd8a9.npy +04379243-eecec73da85e87ccf008d8a3590fb522.npy +04379243-6fb52c296531dc17beedb4c8fd29e2d1.npy +04090263-daaed98e5444c849a50b91ed3855d17b.npy +03691459-a3d5207350bdc01e87d57ccb715c57f5.npy +02924116-b030d739e1e077ac7d42408e08c78f83.npy +03691459-ad2e92448857e1cc6ad08aa387990063.npy +02691156-795e0051d9ce7dfe384d4ad42dbd0045.npy +02871439-34e73c7fb43d489cd810b14a81e12eca.npy +04401088-8b4d28e4df5ac6e8656557acf97c5e2a.npy +04090263-97291a29f435517db6a44e5c103915e3.npy +02958343-75b8fc64f98a71969d69712f9d08c005.npy +03325088-bc42f9907e3478553321831d2245cf06.npy +03001627-6e3435d56d8f8465daeb838d0771f3b5.npy +04379243-610f10d57a44e0d1ba18ade30e563d37.npy +04379243-a465210c23b0136d7afee304cce81d6f.npy +04256520-2b8d1c67d17d3911d9cff7df5347abca.npy +02691156-5cf29113582e718171d03b466c72ce41.npy +04090263-739971469c9903eeb6dc6c452bb50aac.npy +03691459-257e47c2c327ac0f86690e0779a3135e.npy +04379243-f9add10d9e9f13f413ee1dc69b2c2bdc.npy +03636649-3e21ab6c6d82ec4e1509d7278de350d1.npy +03790512-e036a72a92033782b9ba8289eb4d47d.npy +02958343-5e93dfb8e4d59a0630714334794526d4.npy +04379243-65dbf1f9230a2913855931d119219022.npy +02933112-ca6712dace1e32a548d8ff57878739ca.npy +03001627-808ba77745a0934586abe5555a3b447d.npy +03001627-595379651cc8199abf3c0fb77f1e5110.npy +03642806-3ba00d343b8ee1357b9c6deef486a7d8.npy +03624134-702d6f4583b41f911c81652b127a0ec9.npy +03001627-a7200578bd7bea065dc3653f8341633a.npy +04256520-61e1edb3150c71a1f2165a0df94fc0a0.npy +02958343-c850fc6ea372c568a7fd25564c2e888e.npy +04530566-44b4972b96604e08a2fe1981a00251e0.npy +02958343-b963de806d271377935310097e7751.npy +02828884-20ac7b1b285151789dce72832d2a77e5.npy +03691459-9d2f1644bbce8260ff26ed0bd5d4b63f.npy +03325088-e55b1f59cd50df54b362845c6edb57fc.npy +02828884-be9a174af2b3a463f4fb4dee5181bee.npy +02691156-5f7f0545eba4034965e692ae5160ef.npy +04379243-de551ddcab968586a90dd8e076a5a7f9.npy +02691156-e0aec5757f7a907d647cd52f13caf24b.npy +03467517-60a67f8aaac90a5543e09a26d3027978.npy +02828884-da39ee814b8e3c0387d7792ff13e9cd8.npy +04090263-b76f3783324a5f7b3018d2d3c13a7462.npy +02691156-a2041f74f316e7b9585e3fa372e910b7.npy +03001627-97da84d5d78d84cc2360e5e238139587.npy +02691156-8ac48eb3349098b535fc197bbabcd5bd.npy +02691156-8325baeca433510f4e8c959f70e2c0d8.npy +02958343-ed2e4dafc745bdd661fd7e090d4d0d45.npy +03211117-e912fab93eb63fef6b4897a481d7d16a.npy +02691156-f9db62e6a88f0d7129343faf3bbffb15.npy +03691459-6f1913cf723bdfbec5e5fd334d8e3b16.npy +04256520-683384e0e6eb5d4e81f667e2a25e0619.npy +04256520-72b7ad431f8c4aa2f5520a8b6a5d82e0.npy +03691459-918ae70cc8ff08c27f83e87789efc1c8.npy +02818832-ae34003be790938fa3f600c356573d21.npy +03642806-c3eac3a391b81bc8387188c556ebf654.npy +02876657-114509277e76e413c8724d5673a063a6.npy +02958343-a8d3020b33543bdce64131b695068ec5.npy +03001627-2aa122c56910bad8fb0eb7e753c06942.npy +03790512-5bb3597d49c58017b37378f3c85478b4.npy +04090263-8c0827d07d79165ad87c63d8b3018b58.npy +03325088-728e58be6bf87b89c36fb70296e45483.npy +04530566-b4d3624a4e2651ac6bfc202176cd1f2c.npy +04379243-c4a43d8473ddd9b4554be8f12e385710.npy +03001627-67e6503e7ab7e666e45ef4135c266a12.npy +04256520-20eee9b40b2f6f36e4947ad76f8ce42d.npy +03085013-d05abcd34629ca136d07c55cf995503e.npy +02691156-d30689ca6cdf2601f551b6c3f174499e.npy +04379243-5b6bba613d5dccdb21b55dcb76ec1538.npy +03211117-e6304d3bec856684d9c9f98900faca52.npy +02933112-ab9e20f3f9d2f1d1d77c088a902d8fa1.npy +04379243-e7b41a39388925c364f6d058992c3399.npy +04379243-10e5ffa28c252aceea46bea76c64cc3d.npy +02808440-b8cd34d7b1e0e9ae84e6e639680867d1.npy +02828884-5d9dd008caf920b8c29a08a3db9fbe1.npy +03636649-86a5fae37549690cfcb8d8c6d4df8143.npy +04530566-176c629c93b5a1f73cf0b8b75857cc24.npy +02958343-add26d8f4f91ba04c84b95bddf75b22d.npy +03636649-1c9283c95c8bddd5efacb264ebf1ec75.npy +04530566-1b89cb2463ccaf15e1e2fc42e32162ff.npy +02958343-49930a07ed003273fbeda5389ab05f5f.npy +03001627-283e59109ef763ba2168ec2d80dee966.npy +02808440-e41cc68c7809ec9a412deb0d2b0f3dcd.npy +03467517-1e019147e99ddf90d6e28d388c951ca4.npy +03001627-697fc3fa4c36fe9b128d966a6d72dfea.npy +02691156-adeb5d68e8d65cc419ba010ddb4974fe.npy +03001627-5b5d0af8426e604df1783a44a88d6274.npy +02958343-9676e8250cdd90307d5394224a6aa067.npy +03001627-6b95ac6189a395d3fa8cf35dd917fad6.npy +02808440-4119421c85d867c4fb5a74b09b9b3506.npy +03261776-a959980585058ee42764cfba57a5de73.npy +03001627-71656875081adda78b17d6d1965c2fb6.npy +02958343-cd8956854d515c47374462542bf2aa29.npy +02691156-bdf120e29b19f77b352526271bef32d2.npy +03991062-f892893037aaa2028cbd3996b1c0adf8.npy +04256520-244499318ac9251c3bec56bff764ba78.npy +04379243-287d78d72d12b03c3bd24f986301745.npy +03001627-ecad3bef91aa032b6c1d9538813ca7b2.npy +03001627-c2180f4b2d79f55cee30e9904f2fffb0.npy +03636649-f9b41c5ee5ce8b6fcb8d8c6d4df8143.npy +03001627-e6e65bbad248c82c4c59782c74cbf5c7.npy +02924116-6929f0a74db347dcc69634f1103db34e.npy +04530566-2a020ea3cd5e4fba37363131ac7e8139.npy +02933112-3d21c18153474a0acf004563556ddb36.npy +03991062-83ecec98acd12e53ab1be941467a2a97.npy +03938244-a3efd34601ea92facd6e752154c5afc0.npy +04468005-bc9469b0686383a0520ca1141749248.npy +04379243-da7daaa940ae6700286de2124bf64f07.npy +03636649-60500e6bc230e3f3bbe00b56d7315d73.npy +04090263-51b6fab73fc9ea886a34aa94ca8a3355.npy +04379243-8a3fe76dcc0c54cb502ac2eb9128f9a.npy +02942699-60923e8a6c785a8755a834a7aafb0236.npy +04530566-c29e6490308ad33320d713ce6286f99c.npy +03325088-13cdb5df9a944fcbb7a867e9b35a1295.npy +03325088-3bd7088a61b81842c129b46efdbc7885.npy +03046257-6a4547d6f396b3212871cc0b3cc1a485.npy +03001627-b53373122c7964c531a0ecc0d5a7b3d5.npy +02958343-7323fab0a83b9598f11a194d0ae1bf8.npy +03991062-b8bfd969eaa20d4c7c88564709ab8d9.npy +02958343-9a92ea1009f6b5127b5d9dbd93af5e1a.npy +04090263-a11fda24d699c02f75e83577a23faa92.npy +03636649-5580b95ab8e7806c6c5b8009db95f66f.npy +04401088-d565df5aa65604c86b69fa5331093439.npy +03001627-fe224defdf08a99a3002761e7a3ba3bd.npy +04401088-556b1ebe82977992c51777c7f8bdea09.npy +04401088-57004d88e4deebcabec15cbb63c9ab60.npy +02747177-1e1015a06e43c0a5a44b6af22454453b.npy +04256520-31b5cb5dfaa253b3df85db41e3677c28.npy +04090263-a4f94ba638d2bde76227cba038bf7c95.npy +04379243-e0eb9f5421ef2c4584904c716bc3b619.npy +03211117-65988a39887ffed8edba57559632880a.npy +02691156-e8b4bac72559c097e8f5e45871fbc77c.npy +03001627-925c06a5aea45ffbaf7c7ad2549a1b15.npy +03001627-c666bd15aaebd5b02de0bc4fc4d02dd6.npy +02871439-88d2609fe01abd4a6b8fdc9bc8edc250.npy +04090263-9a2d5bc2029c82cc1b7837f7a64e3031.npy +03325088-b039d06d4776f9f9fd24893a94b85cfe.npy +02828884-d63302230b1e358f24e2eef7547426c4.npy +04090263-bf2bf9b61e8eafab30d6a7e7f84a00b3.npy +04401088-1f93dbc9622d83de7a9f0bb7b1eb35a4.npy +03001627-3318f55fdfb9a132f83ac1589b0e94a6.npy +04379243-8862cddf90fddb3119fb4103277a6b93.npy +02958343-59e01fab310fa8c49c9f1f5abaab90a7.npy +02924116-5d55097e65e6495f8b0ca2812178f3fa.npy +03001627-b8c678c49e40ee5307776da88d1350f.npy +04256520-26891b80550301721a648655355dc699.npy +03790512-837330924dba611df6572e2c76e2d78e.npy +03636649-de063371e5ef119cfcb8d8c6d4df8143.npy +03001627-5f34521c634a4045c68e0b8b9ee8a0c6.npy +04379243-bea8659e45a1094f625ac64d4da8b7e4.npy +03467517-eaf405d9ecd6a9df747506aa863f10e4.npy +03001627-637606c1ca1ecd81b502160362bf1664.npy +02924116-d4ac8fcfe5b445d552470de2774d6099.npy +03642806-54dd364a4ea326ca21844676433a0aca.npy +04090263-beb75684ec2f965412b38b1d99376c0b.npy +03001627-11d3fc4092e616a7a6fee8e2140acec9.npy +03691459-39c15f4b2ccd699bf0a8b62260a2a216.npy +02691156-44ae568461e04dc2fb3831486f8b425d.npy +04401088-f3aac8f54f5f2a2f983ec12a2b33f18b.npy +04379243-bc4ba0bd86545f3fcc749dbc8c455b3f.npy +04379243-3f9c84917d92506f3bfb18d76f33685f.npy +03624134-ceeb38ab7929361e76ec14627bf6bbcb.npy +02828884-d3eea79405a0c784f155d75bbf62b80.npy +04379243-90446c710f3495f4e90047543e308ba1.npy +02691156-73bef2b9747edffb8b96ae1a0a8b84ec.npy +04401088-abcda75b9f826fce8dd7bd77b545a577.npy +04530566-2080308141b05e9e584c6557cf979aa5.npy +03624134-ff949d2335a226fde1c0dc67e69df88e.npy +02828884-f213ccec1e4c9dddcb2a965e75be701c.npy +03337140-f889fdcf54cd73d47be728bffb08bde.npy +04090263-4ba87457899d8385d735fa1ab17311ec.npy +03467517-1c9b41481f09f9d33aa393830f0be88c.npy +04090263-c7b9e0958bc8f2ae320f9466abaabfe2.npy +02958343-664473a5493912f4650bba674124a73b.npy +02933112-d9e69e6cd318d34380d6227ff9b21190.npy +04256520-8731945435676805aa29e9f0529e8ef7.npy +04379243-3fb5033b5ddaaf365f7afad12924b3b5.npy +03001627-cff9e23014880e20b2e8bfcc2dfe93cd.npy +04379243-3b8d176f94c0617867dc358060e3c47b.npy +03636649-922902d623e5e5dee527210494d6783c.npy +04379243-c5283929da8665cdcb9cf5f7d536cddb.npy +03790512-7b6d89ff70831e71594057aa2102e240.npy +03001627-23acbdfee13b407ce42d6c2ea750090e.npy +04554684-eca8612dc1cc153c4df5aaa9df719285.npy +02958343-d41c66c7b1ff1f57979ef391885ee5d2.npy +02691156-c814a53c1538cdca4f7e1991902e92f7.npy +02958343-3a5ce33bac316d8f6379c5e421c1d27.npy +04256520-ce378b91236095622155ef587b4a7084.npy +04379243-28f702b5c6ccffe7fcf9154182ccb5a4.npy +03991062-1cd99461021c535b3d2ad39bada7a0a.npy +04256520-fbb0d2c65c3a26a6490ad276cd2af3a4.npy +04379243-1c3310f4c05ce1f6a192483aa282f8e5.npy +04256520-b8909a5d6702f6f31680549bb1d1b739.npy +02958343-a3d0bbca6bf8a565dc90bfc1d450ece8.npy +02691156-e4b0599a9d06f7ae39cb1b92881e8e76.npy +03790512-455485399ab75f93429f1c522640e6f0.npy +04379243-8219a48422582b01c345108a8f6e3cb.npy +04379243-7772fe52eeb64fe8318694f1cc6fb1f8.npy +03991062-c5c04e396d6aecd344c183864792bc2b.npy +03636649-d54b55ff9b0923c12cd2160e449d45ae.npy +02691156-24bdf389877fb7f21b1f694e36340ebb.npy +04401088-4303a97b71a1bb894208dfa1c5fa1065.npy +03001627-6c16024ad8f16d6c83c7ca617c7f7461.npy +02992529-ff8ba237ee9164c8ff86292618094648.npy +04401088-715a2661c9be051bf4ede441a9f9be4a.npy +04379243-5463f71800fcf2e5e89951e6ee90b3d8.npy +04225987-11abd8b2227a9031e65449686a784d77.npy +02992529-b21610e986fa4c9c7cef36fa43392c52.npy +02958343-70d31e0100cab3fd77954285e7764e1b.npy +04530566-6a0da87e5858b4373e45dd2f173cbf9b.npy +02691156-f405858991b190173af8c56bd4352c9.npy +03085013-6445c051acf63ce01aea59cd55c902b0.npy +02933112-4669d272f690a18dc016d21df34cd8ce.npy +02933112-5fec62a43a64ecb6f51f77a6d7299806.npy +02880940-a1d26a16a0caa78243f1c519d66bb167.npy +03001627-efb0e98337c0554960257b24d454e22f.npy +03991062-8fff3a4ba8db098bd2b12aa6a0f050b3.npy +03001627-2cb0ac27f1cdb3f0b2db0181fdb9f615.npy +04090263-ba405d9633ec030ef27eb335b754fdaa.npy +02958343-e703fadeba32d912452ffe4552686849.npy +02933112-90dd9ad1a74e25d53fe047712e43e185.npy +04379243-5f8bb62eec8f6f49616fb9ab42452112.npy +04530566-393f1f8b2c656484a7ace102781bfe8b.npy +04379243-96ccbfacf833d023c3bd24f986301745.npy +03001627-fa6636dfa85cd625f63376552552931f.npy +04256520-d72e78905c4d975f4f650cd6cdc94858.npy +02828884-d3b644f9eb32ec9cbe1fb1bc0addfcca.npy +03001627-a1296954d5190272327289c00b6dc9ca.npy +03636649-94f1ca2ad33eac601ae26e820e4d9a45.npy +04090263-dbe471b64f9d8647e35dc3ced109600e.npy +02933112-3c855f2a52d5e3f63c8d0fdfb1cc2535.npy +04401088-3c0801c11fc7e4c5f31b75c4a94a8879.npy +04379243-ac9f82fd26fba6aac45e8c8bb42d23a.npy +04379243-b7a0dda52974fa642250bf58700b4d8f.npy +02958343-781b45d3eb625148248a78e10a40d8eb.npy +04379243-9b77e481163e91214038d588fd1342f.npy +02924116-17c0d859278b203df88b61e9125676b2.npy +03759954-35f36e337df50fcb92b3c4741299c1af.npy +04256520-6d41a09cc94d2505a82acb2f2fa57398.npy +03797390-f626192a5930d6c712f0124e8fa3930b.npy +04256520-9dcede4115b4379e2af4036e9c51cbc4.npy +04256520-bfc0c2ab5bcaa2df9442d81743a735a1.npy +03211117-d10085421b3cd3a27504aecf4baaa1e.npy +03001627-b773f81e938f95ed65ba78ad9601cf1b.npy +02933112-8057ca7c19a1457ee3f7a74e12a274ef.npy +04379243-28365bca55784894e99f3a1de720cdd.npy +02933112-8504af8851175efd253d6f91951c4f58.npy +02992529-29c5585362cf4aa5b4f6326696174df2.npy +03513137-802b08904ed6bb57b20f6e48f6a30cbf.npy +03001627-ed47d02d4518fb5d9cc2d4308810279e.npy +02828884-241f99f97083f685beedb4c8fd29e2d1.npy +02958343-bfa0a0a7862c2cf3c2179f10f381de6d.npy +02942699-4f2a9bf0d8eb00e0a570c6c691c987a8.npy +02691156-89a5679cb03f30caf5c7319b71bdce6e.npy +04401088-87f8a738b3f0ae0194feb18ebe41aa84.npy +02958343-508b9f9da70d70dc809a9c98ca4d300a.npy +03001627-6e1e605da1c3d680f9b9977a2406713a.npy +04401088-611afaaa1671ac8cc56f78d9daf213b.npy +02691156-813927b25c3a0c6dff227f13dbef5a8d.npy +02691156-7cabdedabd1d65bdfb86dddee1d6ac3.npy +02828884-d7731559d5f485bcd2b12aa6a0f050b3.npy +02958343-527d52b26bc5b397d8f9dd7647048a0c.npy +03001627-a64bc6079afa241f762ec387b772e9e1.npy +02933112-2036aaa68d164c373fe047712e43e185.npy +02691156-a00c0bdf007689619ebe905ef4009f84.npy +02958343-641a0da53609ee3028920f0e0293b366.npy +04379243-92016e48e44e8b8bbc16013e096d0c1f.npy +02691156-fcbdaf6100aad67d5abb92fce0f1ced2.npy +04256520-9df8e759e084a988fb1eb57de0e2e513.npy +03325088-e08ed186843c83bfb7a867e9b35a1295.npy +04379243-63b53646b3562677d395837145ded71.npy +02992529-a857d9e7cd90163e10bc2436075f6a52.npy +04379243-a8c7402b6bb693219786ace2aaa77b00.npy +04379243-92dcd20f1b208af9f51f77a6d7299806.npy +04256520-875aeeeda0a93481f51fa0238791f5dc.npy +02958343-18a9275b78be4b9ec6d3267fc5334296.npy +04256520-f55a514cc8f2d255f51f77a6d7299806.npy +03001627-bb3516732bcd45f2490ad276cd2af3a4.npy +02691156-f9e80ce23d9536623fddedb0bf24c68a.npy +04379243-88e6afb8c56788899470764d5e97d4ad.npy +04090263-360f8314b77730336edbaba04282b1e3.npy +02691156-b7b657d7db3c3b8cd13ef00338ba8c52.npy +02828884-c19a1aeba4d90b4aad5067eac75a07f7.npy +04090263-9548b43e0f416e3a4a4f87aa9a31cd70.npy +02691156-fb5e00c769fa06e7c277130bc8102991.npy +04379243-6eac64eb398b9d7145d4f35fd8d64cf3.npy +03001627-e8f20141696f143cdb77753d44aa25f6.npy +03001627-632a5ea290b0730c6ad8177a9d42d3c9.npy +03761084-401d1543b0617914de2a9aaff52ac7.npy +04256520-9e6ba78f80fbbfde5369e32fb818f337.npy +03642806-41e263d2af5c667f988abef1fd117e7.npy +04090263-b3a41cbb4ddaea6786225a62b2bc2d97.npy +03001627-6ac7b2ef38226e3d26c2e61baa2a8130.npy +03325088-5f46e75b9faf77c876c18e71fd49c4dc.npy +03513137-12a5eb233ecf486e3e01acc90dd935ff.npy +02958343-a2179820a01ca67f1a144f5cf9567bf5.npy +04379243-193aa6ce8777814b90e2ed261620fef5.npy +04256520-dce866778584da8219eb0cf70882af88.npy +03001627-49d4f5dc155b7b8a55f46d55537192b6.npy +03001627-bd0ee3dbadfa724f6ff454af1e8947f3.npy +03001627-668b9f6517f2bf501e54ac67f0143e13.npy +03636649-21ba9de4d311ff31cdb282e42e89414c.npy +03790512-61b17f12bec91d057395d58407f193ba.npy +02691156-999539f6290b7072ca2bd098b9203af.npy +02691156-9e524a14078824b5cfe15db7c5db913.npy +04256520-a37d0d0598d73b07165fd9581927b6ad.npy +03001627-a31b0ccff3aba978c3bd24f986301745.npy +02691156-8b61ba80d9e487deca8607f540cc62ba.npy +03636649-7fa4f80f92b8e779eef2192b7bb521a4.npy +03001627-52621a97e5036dabba18ade30e563d37.npy +04379243-6b62c85b16e300557005dacb6907e37d.npy +04379243-9c390832c0d1569b664b3b9b23ddfcbc.npy +02773838-c3426d26e0408be4285e5a1f74237618.npy +03001627-bd0918d75e22cbf9febad4f49b26ec52.npy +03991062-a2cee19f1c118a73fcf9154182ccb5a4.npy +02958343-c975716963b72b72236804c5ee26a2ab.npy +02691156-552d76fdb54e5d57cf7cf1e30e2f5267.npy +03337140-3d95c4ebb88f94b3d2f054448bd437d6.npy +03001627-3e28e0f5ca5e03df73227452e5016b6f.npy +04090263-9cf37ec1667dcd3b4d4925687e893b3a.npy +04530566-f2ad53e569f8ea255b9ed5fa79e9ec30.npy +03001627-8b016c4df0e139b660065f613e3a3cf.npy +04379243-dd197fdad7f339cbe8b31d97326b3fa0.npy +02691156-a94057f15ca19a33fd98271adcb6e31a.npy +03001627-62d87dab8cb3fd16c050719ed29b64cf.npy +02691156-e3f562bd552fbb14496e2f80fb255499.npy +04379243-400369fdca7608a531292d1fc01277d8.npy +02808440-198abf39ad554388b362845c6edb57fc.npy +02691156-93314e5d740a48049a6e43b878d5b335.npy +02691156-8adc6a0f45a1ef2e71d03b466c72ce41.npy +04090263-cc362ac31993fcb4fa0d7d9af888ead.npy +03001627-3c786ff99885e95c685d4893e4ba8951.npy +03797390-ef24c302911bcde6ea6ff2182dd34668.npy +03624134-17c4163247e9237d4b7644126b1d71e0.npy +02828884-a11db718438648a0ad5067eac75a07f7.npy +04090263-93bdf3bb2fe22dff7ec95138ef83ef2f.npy +04379243-369c19c0971221f3664b3b9b23ddfcbc.npy +02828884-b2acbc0822c163fb491436340b3b4d18.npy +03642806-2d5d4d79cd464298566636e42679cc7f.npy +03761084-3ba680a213e736bc23553854725256c2.npy +03991062-aab73b8b48bec09b36b0f2a1430e993a.npy +03691459-60765697073cc44cec7e019402cb7bad.npy +03928116-9abbf6edaf6148d25803dd89b71b9b2.npy +02958343-3044f0bf0ab7fd8d476502dcb0dc5465.npy +03325088-d20f44a49586d3d3e61ee99f7b43d0a0.npy +02691156-93a635370616538abc0909d98a1ff2b4.npy +03001627-ea87765cf9dbe2fe55f46d55537192b6.npy +02691156-2dcc844fe9c4d4d99b0fce6a4905cf2b.npy +03211117-ae8e106b972648d5bab4cb27e92377c4.npy +02958343-238c6d6da1c8ce2970097c1b40e1ea6.npy +02691156-5face359ff1d4b4f8e8131a047a07ce1.npy +02691156-65654b5c4e488e0c961fa14fc879444e.npy +03001627-28cace7066ffa9c2f4b6538438a0b930.npy +02691156-d0001af4b3c1fe3d6f675e9f2e677792.npy +04090263-a5b31577127d77d28653d927a24ffc75.npy +02933112-ab7b9934fa7d4768c0f947750540fb22.npy +02958343-1a7125aefa9af6b6597505fd7d99b613.npy +02691156-427030abcc0f11a8947bbeb9022263b8.npy +02933112-3735e7c2bdcdcd7eebf9241bfabf12f1.npy +03691459-cf45708ed1ed436970f2559ee6f59e37.npy +04256520-ddf7a59004522f04c366b8589aac6975.npy +03001627-ccabe6ab0816614dde03ab2a27ba7531.npy +03467517-3621933462e7962af4493a5b80949ad1.npy +03211117-bdb7abf15b1a3f437483e5069dd82374.npy +02958343-a111cef175177b3cd89cde5d5f759ea7.npy +02691156-e5abd988cb34ed9cdc82b8fee1057b30.npy +04256520-72421bcdcb3212f1bc2ef6ddd5c1612.npy +04379243-197f31b2a8fb2e1aba5342d638d0c267.npy +04090263-22fd2b354b1d26eb306b3e8b438992c.npy +03467517-b79e39da98c26625bb6216c38da5db0a.npy +03593526-770f2adb9756b792c9f016d57db96408.npy +04468005-faaf4bcd6d23ae08dc14ba0818ee5cec.npy +03928116-bfe3fe6dcf01eefeb9492d4f3d8bee7c.npy +03991062-462b8122f7439283610c2a68437007d6.npy +02958343-c7c3736ad5f3b252e56947f054952694.npy +02871439-55692507997f7884edd435e02f1ecb.npy +02933112-50492ac55ad27122e8990fccb12f2c29.npy +03001627-4bbd110ccfc81dd336b0f2a1430e993a.npy +04090263-1d4fbefad4abb85790acff7491720d9a.npy +02958343-8e2f0f7f5ca505b56227cba038bf7c95.npy +04379243-b1ba4d962206bad5dfda4f5adaef3a7f.npy +02992529-2278cc8b5a50421613fcb9cbc590fba.npy +03991062-5445f01471e4df5da2c59a4d90e63212.npy +04330267-23ea5db3e8c4eb2a99762eab905e5e24.npy +03001627-e9371c17042131d93506b420c6bcd44.npy +03001627-c6c7820d5e2f0011c2bf2dcc31ba1713.npy +02828884-a973a401412f5561cb2a965e75be701c.npy +03636649-b2bdd202470b4166f3a29b1591515940.npy +04379243-ce4e54dbb99b5bce98a96123d0d6b0d8.npy +03928116-f67a6db9393d99c85f3d43a486973313.npy +03467517-b1af1d78597d178ae7ef9fff09638f8e.npy +04379243-aadf84936183c2d7414701ac79f88733.npy +02691156-4937396b74bc16eaf781741e31f0df4.npy +02828884-f0c2b4f3e73873998cbb8bac2032149c.npy +04256520-a308db2269dbf79914038d588fd1342f.npy +03001627-9d0043b17b97ac694925bc492489de9c.npy +04379243-2e25c45a4456df3f36270e8efbeb40ec.npy +02691156-8d84a34d5aac3bffc6f6da58b133bae0.npy +04379243-ee077280e4f7c4a5ca554b08dbb3ef2.npy +02691156-556d2b99469e62e623a346a784afd6ba.npy +04256520-25c859754525fdf713dd6eafe1477be1.npy +02924116-bebd29ff5a8e475d20dd2f4d517f8804.npy +03001627-4428b7dc4b6696812905b6e26038a78.npy +03001627-2af09bd8df40506c9e646678ef50aa3d.npy +03991062-8e764233b0bf4cde4c5c5c89015f1980.npy +03636649-5de6d462706587e9f0f9e9e64b6b41ce.npy +02958343-8bd0d26352ea9de9becf71e2e014ff6f.npy +04379243-c3a9dc47c5bf10aac3bd24f986301745.npy +02958343-9e3a2cfb3c8a25909b2ccdf5f1fe9097.npy +02747177-112120e83ef41de3571c83071e95ca03.npy +02691156-6a8b9f82f1de022a9ea7c189c9a53081.npy +03691459-ac8fb298f7795ba47f1358f741bb7fa6.npy +02958343-e17065d11b36ab37f9d73bbb584eaa42.npy +02828884-7b21980987b63b953e329950ec40f6dd.npy +03759954-6d9ab595a7bd890128ee3839fe659fc8.npy +03636649-81894e0739e3fea9d49b2e04785f8492.npy +03001627-d3bf9df2360f0a56731dc97277e95217.npy +04530566-9bedc0d32c657b5a95003e7aecc71b93.npy +04379243-b8ec9bd6096a14488de42fc1392c2139.npy +03636649-a60c6cf7d4893f2ba26bf7a8fd4719ad.npy +04379243-7311255cee3e412771a782a4379556c7.npy +03001627-7b405c1d6d2dbea9f91663a74ccd2338.npy +03211117-7c5b291091dd0a166acb8fbfb472b3a6.npy +04090263-584cc870ac0550e87a268987b1e73ce0.npy +04090263-2eaed43aa5e4ec8cc24d00518a3dd6ec.npy +02924116-11aa2ebb5db8b9f36922bf4a94dea1c5.npy +03636649-5a4248187b0cce798aaae3d020f5ddf8.npy +03001627-2e0b6f6d19078424c3bd24f986301745.npy +03001627-32d9f69ef8ebb1778a514cac7cb18507.npy +03593526-7a971531ff72a48d5706d1c54190f27a.npy +03991062-263e56f24d3973216fe9ca24e0c157f.npy +04330267-5b0e09f6f3579f45efb11e763be8310.npy +02933112-f07668a627a039b87b79156a61ad4c01.npy +02958343-faeda504709a7af489d347432ecb438c.npy +02958343-35de0d0cc71179dc1a98dff5b6c5dec6.npy +03211117-e8428a7732155fc1134821a4f2837ea4.npy +02958343-81bb9f249771d31ac675ce607c2b4b5f.npy +04379243-6b5f3b7fab02f9e358220b7cab409d3e.npy +04090263-56b2a58cd5c679b35da6a29f026db97c.npy +02924116-da1c8417f95440739afb67dd284d342.npy +02958343-f2422eb6b55e8fb0ef3ecc8551d2c1fa.npy +03001627-ba45d6c491637dc5820018801b237b3d.npy +02691156-e9bae38bc2083d0bb4d73e4449062b04.npy +04379243-788af6bc08bbe51fd9a828fb989f49a0.npy +03325088-c63ab53b4ec1bfa83321831d2245cf06.npy +04554684-5fc3cef0cf926f5b9303a353ee6dfc42.npy +03761084-4f956e259344d4a3599fb6902c958d23.npy +04379243-b661b93b67d0ca908cc8e5a741a7e8bd.npy +04379243-5e4351c4525fae6d6fa63795f94c4d8c.npy +03001627-9db73a6184c82d33f28699debac30ad6.npy +04379243-459f1e82f058fbd0ca42ad68b92de4c8.npy +03001627-a6e3c2cecd4b6b6203c870f1209d6b9.npy +03642806-5430ba1b4995af02717dccfa4b0eec5a.npy +04256520-4b3f84ca13baf80be0c381fdfcdec36d.npy +04379243-3a7d5468084399cd11ddc5a6b5ad5cd3.npy +02933112-7fbd264b7031c399d37a1bae74ee50a2.npy +04090263-ed9b7dbc375d3543d0a6af9bfb470a20.npy +04090263-d82fecbd0fa3fe757e183a626c555090.npy +04379243-b61dec9a8ce09e4b80360680c1602c7d.npy +02992529-fd3c1ac6cd1f94bd3982f71b09380baa.npy +02747177-9307ad32b595cd82cb2a965e75be701c.npy +03001627-a147244346d84fe398e0d1738edd4f19.npy +02958343-87a7ebcb0dc2285d77471d13a466f5f7.npy +04256520-35bbb0da45fbb2d93eec26c23f5bc80b.npy +04379243-add1279c481f88a1955e0ab55bea4388.npy +02691156-68ff153952368948b4eba5f9f157d8c8.npy +03636649-dbe5479ef7f6c752eb1f13e2de7cd7d8.npy +04379243-9634e0b7d04586865fca6ef890703085.npy +04256520-212a8cab17af2454f8b0f8060696d1e7.npy +03001627-3d0b161ef3c026a28a514cac7cb18507.npy +02958343-a54ce961d973443a0daf3e5400b95c.npy +02992529-5deb3e8911dbef1adce6ba04fb42df.npy +03797390-5b0c679eb8a2156c4314179664d18101.npy +04379243-87504deae620d0dbf4b6538438a0b930.npy +02924116-9427168b4111ec2fc7a1e45e54191e0.npy +02691156-2e9c1c3d866c4b6ce2c6d8aa34a5d35b.npy +03001627-66654548053c709ac3bd24f986301745.npy +02691156-559f9a545b9b98a1d433b2698458193.npy +04379243-da1e75a8647bfd919778416969ddad32.npy +04379243-4805127beacfba4a7e7e510dabdd3cc0.npy +02828884-82b06455e41204e110df635c029b4e63.npy +03691459-9076b1b9e23c7446d747b49524a1246e.npy +04379243-b7821e69687d767aab610b0c94236463.npy +02924116-96d2cd5298733a7b54d963fd62c89fef.npy +03001627-8a455c7acaef577824f0493013a8318f.npy +03636649-a3a13218d61daab550903fb6fac1fa18.npy +03337140-4427e5eac495c14e40a7c7e360f68f9b.npy +03691459-1b24c1c65645c5f155b62c3398327a83.npy +02871439-3d554cb7c74d1fa0820018801b237b3d.npy +02992529-1101db09207b39c244f01fc4278d10c1.npy +02876657-194f4eb1707aaf674c8b72e8da0e65c5.npy +02992529-68376369681e50847e814a763437cd9.npy +04256520-e32a5fdbb75ed879568af879e5634175.npy +02933112-df0f03ac21921f02c868162258053ece.npy +03261776-4de2413a28db0137100e9bd5c4b0af54.npy +03624134-eef74fec4fd6537f89145655be527428.npy +03467517-a3c93f4327a923b3dbea3103e4ab595f.npy +04256520-1de06749f136ec8da066c1f884f0378.npy +02958343-d2ec7caaf8cc7a9fbda72093f9b5aa73.npy +03001627-bd6fcae754203396e34dfbaf829eddf7.npy +03761084-6216efeb4d5836d1efa585e146d1a8c9.npy +03001627-44fbc34ea7869e38e13a527279e951a2.npy +04090263-d8f1721d811dabbffe085ac6ce469d2a.npy +04530566-5bc8a432a5911a4c14621506c22882a0.npy +04256520-e389a5eaaa448a00d6bd2821a9079b28.npy +03710193-bfc242ae3d98762ece876412f61273f0.npy +03001627-b518d19f55a1e15f5d714c9d7df1c4ed.npy +03211117-77fee7e689d94e0f3637439a589fcdc5.npy +02958343-d45b86de9175d1c8becf71e2e014ff6f.npy +03636649-3f968096c74ee3a3b04a2e6a78ff6c49.npy +02876657-d44618b5aefe9ecd467ca2ad6571afff.npy +04256520-99ec7e5d04f32409d45611d32fd7733d.npy +02933112-94f4f2342f6335c5875c4d98e634f167.npy +03001627-551be68d484c8910f91663a74ccd2338.npy +03691459-6803540650949be89c4081063e213a15.npy +03636649-5d693f7115e5ae984e9836419f09cc52.npy +02933112-2a3023853ebfeff5eb0fe7d6b5545a1a.npy +03636649-f0414c5a1d22911555683d8c4a0488e1.npy +02992529-54de8ee661787c1d16d46ee44c40524.npy +04379243-decb34ff7d69d024e6c5cd45aa112726.npy +04530566-aafc192d33956391b82d6a0b1fbc7c80.npy +03001627-2b52cd0ffce12156ccbcb819724fb563.npy +03001627-7e7e130acfcdf64b1dec8546fd5980a9.npy +04379243-2df0d24befaef397549f05ce44760eca.npy +04530566-df307c1941ca4bbd8f6810e1a2b6aa04.npy +02876657-883ace957dbb32e7846564a8a219239b.npy +04256520-1fd45c57ab27cb6cea65c47b660136e7.npy +03948459-6dddfe264ab324a5e39bc2c6d1318094.npy +04379243-d29dedf88bac00a21c19e7863a1c200b.npy +04379243-1a6aca00bbc88c7d30bbd4cddd04c77b.npy +02876657-44dcea00fb1923051a4cb1c0c7bb0654.npy +04256520-23780fffcd205ae9f1ce854e012143bd.npy +02942699-a600991b042b2d5492348cc032adf089.npy +03467517-bcfac61cd0459d5437f945ae4b0d3b56.npy +03001627-fdef0425d385c1cadef295ef48e5307c.npy +03001627-a49fc9bab5834df95b1f17dc9a05edeb.npy +03636649-2e06c6e29aa90245532e8683617554c4.npy +03325088-1d5be60c3915be4b362845c6edb57fc.npy +03691459-9a989485d607844c786b126bff0b0351.npy +03467517-f0ea12f645a1c541ce1a36e7d9d3bee.npy +03001627-d04c2161f32a6499a6fee8e2140acec9.npy +03636649-d34a10201a5448a253cf897b7fc1d12.npy +04379243-5276058cfc1e139326392a5b643ed5e3.npy +03211117-e2787b2f0dd35fccf42a90fe4baf4591.npy +03948459-a7072394bb9d23f54b49cd65dfcc3a9a.npy +02808440-397908e45ef98af8aa8891d8ac9b291.npy +04090263-4d4fdcb113d7ed643a6842b1f893c19.npy +02818832-5ba5c9836e19ac7640b4c5428883e585.npy +04379243-8b7f2caf571342398b8e4fade0702996.npy +03001627-42abcded68db4356352fc7e973ba7787.npy +03790512-53062381d490e3d1e203ed9c6e5dca08.npy +04256520-cedd4ec33ee3b2de7252a102efb37f50.npy +04379243-8d1d04d72b7a240d4c61a7cce317bfb7.npy +04379243-472796909612bf1f1353dc45068d6f44.npy +03001627-50b4851d6e067f9bdfcd57c2094a665f.npy +02808440-5e83e7b924759c8ac2b1819e686b1fc9.npy +04379243-d70bd276cd9f66f0a909821b8b014ef2.npy +02876657-cf6eff1143f9826ab5c14191b5dd293b.npy +03513137-96366015f183b237f1ea818b22320c8b.npy +03001627-2268d24a64c2b20b16222ba719ed2541.npy +02691156-d9dd8dd2c422dadaad70e50d5d7d02a5.npy +04256520-bf335aa14157162b6f8304908c816659.npy +04379243-77986a9d5546899819fb4103277a6b93.npy +04379243-81a84fcb2b247a3348eaa510713cb074.npy +04256520-d4ea100ff8f94edadb1109c64edb2c4c.npy +04379243-52f2c6960d67445f896f73ae4af4fc8d.npy +02691156-c237b4636625f1b0af8d9a7eb0a2bedf.npy +04379243-d8ef132f3ae98f688231f48f0f8de6d4.npy +03001627-484a7d924c952e51af7c7ad2549a1b15.npy +03636649-680e5d7185a51e26a50ffe9b7408540a.npy +03325088-873b6c2543798e437d6fb76678b5a248.npy +03642806-b436271050d647052f8d6d501b18a4b5.npy +02808440-7ab27b5a8e1b0ed2fe52ffd0e748a1ab.npy +03001627-8979c1aaa6675009bf80985a99195eb8.npy +02958343-6ee7fc93288d678e3ab3dfa44f5fab01.npy +02691156-ce4b8076f8f9a5a05be07e24c1d3227d.npy +04401088-b1085da37756ddd1d3f1ccf368ff60f9.npy +02958343-e01a56af0788551e7aa225b44626f301.npy +04379243-eae2c096070f0a57beedb4c8fd29e2d1.npy +02691156-eff5216d782684aa3c7aa3e4b8926c27.npy +02958343-2205a3f2c102f180a134736201a79843.npy +03001627-23e80d93926a45f7f7628281ecb18112.npy +04256520-2056de97c97b2c85b759217db94d2883.npy +03001627-a8827a6013e06261e27790b0ec8671f7.npy +03636649-a06089b2d68c974c6273cbd9c7cef4c.npy +04530566-6556015faea5ba45e0f0f0669675011.npy +02691156-96ed9dcc355f3d34585be1dcf6e59170.npy +04530566-ebff6d8111c67fbdb52763715f7a6959.npy +04256520-8a66b03841197e23d93b543e2efc700b.npy +03001627-5c9b1a32f54b12cf81f667e2a25e0619.npy +04379243-2c118800181f296a855931d119219022.npy +03001627-a77b1abaa28588bb926350348c58b8b2.npy +03691459-b28c7b84869ba2aa87d72888c0a9277c.npy +03001627-cd5cc7a5e50478e82b520984c067934c.npy +02958343-bf7efe509caf42cb7481cee66aa2b2f4.npy +04256520-cacb9133bc0ef01f7628281ecb18112.npy +03642806-79ed190f0e35ccdf98ce68842a487b19.npy +03691459-58e73b03f3ecd4a45a31d91ec836a511.npy +03710193-c3b4b8b8e92f77428dd9cfff54e44f7.npy +04090263-10a2ef896a45a682ab379c9b5bf12bf8.npy +03211117-8c4cb4ea7cbd0ff5ad3833a4ccccd8ee.npy +03001627-a8641cd287bcaa2011fd5138fde4c9dd.npy +02933112-d998e75348902a511dff03f33a13aa77.npy +04530566-366c8a02305d2a0f4c9b81664e789bca.npy +04379243-c98eb7f9b2b99702f51f77a6d7299806.npy +04530566-ac2e609dec5745b9e00ca2cd74ddfc7a.npy +03636649-cdb065e1726769ca8cd36201f5f879e6.npy +03001627-4a9ac9e0b3a804bc8fb952c92850e1dc.npy +02958343-8269284992bbd0c886dad8a79e570561.npy +04379243-b59743992b870052255fc74f0e7640d5.npy +03261776-26e186ab10abad8ee6873d49607c1f87.npy +03001627-800dd8ed32104151a37f3fc191551700.npy +03046257-53b0f32afc6cac64f5d4e1af18c85258.npy +04379243-3dc68207126e2e3dd038992c6975ea76.npy +03761084-7cf2f3a1a3de48fda23949c21eddef76.npy +03001627-40cee2893781b47f50f9fc0e2c94dd76.npy +04401088-93556001d266860513ddb059403c66d.npy +03710193-a06df01467d298caac51268fdb437a9e.npy +04090263-ed5cba88deccbeb5a0431d1f46615221.npy +03624134-1640911b9dc0ef0da95c6095f89cd899.npy +04256520-5b5bd4ca75b788c6ece5b3f5f7505a42.npy +02958343-18d9ac72442260e0e97c6bb243ef67d.npy +03593526-789d336e4456d8854dff7c27c1f6df72.npy +04379243-e290e905c015ea0cc58b5b892c704fe5.npy +03001627-a1133464132d65fcfce0ccdae30f97db.npy +04468005-876fb32c52f3753d1cbdffbc1226f0b8.npy +04379243-4a0db050c8703a8d6e3c8a33c4ddf2ef.npy +04090263-d9a07758e979ecca44bebf183fb16c3.npy +04530566-fe09fbe9e43aa889a08db804545b684.npy +02773838-a1822be832091e036afa58a86636d6be.npy +04530566-3fd6e59f9c95a24d88b3e1662276b5b.npy +04379243-21aaa0dad37443f3720c3a14515ab23.npy +02691156-39d7e8e001e0234e8f721bc8b8155d7.npy +03001627-e77d7eb8a4e8f1816f1e07a56c129dfc.npy +02924116-ddd7c100f2c2829b129901f80d24b7b.npy +02691156-30c0995dcb7c10039a6e43b878d5b335.npy +03467517-34c8cf6bc747145c80a2d5cc9f4bea6.npy +03325088-5ba6bb8365b474f773ecd661ad15c4dd.npy +02958343-3645fce32715e0a4bda72093f9b5aa73.npy +04530566-c46b2f2069ce543c4bbcee86e282d431.npy +03001627-6b32d3a9198f8b03d1dcc55e36186e4e.npy +02828884-2cd4fb6323fa2462edccc47bf0dcf5d3.npy +02691156-875c4b43e35b6803a85b9ef94e886600.npy +04256520-45d3384ab8d5b6295637fc0f4b98e88b.npy +03001627-fe307b67739d9620d874a9fab241259d.npy +02808440-e7629f9e27ee058bea7b0e6d0dd8daa.npy +02691156-1bea1445065705eb37abdc1aa610476c.npy +02924116-80b1ea852c8ff6bbbd0a0ca33bfa9c26.npy +03636649-914a91528ef40e7bf7248d9dbed7a7b8.npy +04379243-27ee20b7a7e2467980dbca6e7b64a4bc.npy +04379243-97001433dad08b48e471c0726d35978f.npy +02747177-8ab06d642437f3a77d8663c09e4f524d.npy +04379243-5adf5a7173e588ad76e9713f57a5fcb6.npy +03001627-38bba5755f7d97ee70205dfbbf1e6bb6.npy +02808440-dd6db8928546fa02461827fe9825f696.npy +02924116-59e93330f9fa08344f95630cc18536e0.npy +02808440-3778a4349297e60b44221bef0fa3c36b.npy +03948459-3f5f657bec9a21814ce6ac98dc4781fe.npy +03001627-d32f32d76d7f53bf6996454765a52e50.npy +03636649-792c3698dc7d200144175b4dddf5be08.npy +03938244-b8e55509c5223c09f51f77a6d7299806.npy +02828884-99375af4e13f0b2f50f9fc0e2c94dd76.npy +04379243-eb363770ee36b0309a79b01b89f55c86.npy +03691459-2ae8239afdabc2baaf365ec12406f363.npy +03001627-1f576eefb36c3e189a6ba4499518ef95.npy +02924116-a1b73422396977a841cefd10ce5d6cc0.npy +03211117-6a1e4ab7debcb3f429426a0f57e4d15e.npy +04379243-8cb18fd9c7a54ceb715f13aeb6bde9cb.npy +02691156-85fd79b9fe5948ff62b600da24e0965.npy +03337140-661f24ca8ef19f864c3aee8e9d3a6ffa.npy +03001627-e922bbf8088552badd7092ed47061a36.npy +04379243-77e4ad83f78eb8c3fc8b5999cff24f2c.npy +04090263-6d66b80890d7e5c310a7d517f2e735d8.npy +02691156-9b5a1706223b150613f6b7168403d0e9.npy +03513137-3a12b9c4f7f08b8efac6099f3d4830fe.npy +04379243-f2b3a2f7c9a4ec19436e6787c76ef3f0.npy +04379243-390e0db80fe12ef65fa6da97b9eb4a2f.npy +04530566-325d6d879e306fec3547bc1786bc3b6.npy +03046257-7e2751a46aa8c454e0a659fb66c2add9.npy +03001627-3f4f1d18c61a07f134b707eb14b2a4a5.npy +03624134-7254ae071375f93ee7bd6ca49cbfa087.npy +03001627-878c70bddd336f6019fb4103277a6b93.npy +02958343-868a5166e31428b16d8aac72cf093e59.npy +04379243-435da96586eb1325cc719373d4fe991c.npy +03001627-d48dac046436a29ec3bd24f986301745.npy +03211117-f4d398256e6ec0b4f910da6a487551c.npy +03001627-6eebd118abb1b4146d60aef5fe7e2185.npy +02933112-df74daf1f96515bf9b849da658b46825.npy +02924116-3216f26ef6b3eb7bd01a0e62652f36f.npy +04379243-17c5c22c9ab97788db67d56f11b1bed6.npy +03001627-6f36520144753550f91663a74ccd2338.npy +02958343-d94f5345be1d81a751a95aaa6caba1d3.npy +02958343-1a48d03a977a6f0aeda0253452893d75.npy +04256520-b2ce2532f540cbde67b426838fce979f.npy +02958343-411d95c06a7e9456b3b0f00a15b90e0a.npy +03001627-d5200a27ca0d4a3ea4d56f1fc38d34cb.npy +04401088-5f4937b6e428e4ee122db064a7596ea.npy +04256520-ab1e7ae9a7e9a14a3ddab7e2e0338094.npy +04256520-c2aacd7edbf9b9f98f83f8853be14620.npy +03001627-4353aa4950c32e12f1783a44a88d6274.npy +03691459-3b01bd24d47245289159eab9ccaa73ce.npy +02691156-a93a20767d70220cd3b936925082270f.npy +04379243-8d4fe49d942ec85ff4b6538438a0b930.npy +02876657-59d7b4e7bc3c5d9d99fbba385cc0d41d.npy +04379243-20cdd491a443bc30d9651cd1d591d64d.npy +02924116-dc9c640221f58021c08550bf6ec9e732.npy +04379243-72f501d4168713b9445e85eb534460b0.npy +03636649-f38370fc4c112017a6e7138fdd58748.npy +03691459-b03efb93acd16a49699abba79f165934.npy +03691459-6309ba4b45aa1a648bf9fe7c1fcb7ccc.npy +02958343-ced4053b0616098b7c697c8c1c6e09e0.npy +03001627-209a904959643d0eba7afe602821e0d0.npy +03001627-372118e3595c328c713decb1a0563b12.npy +02958343-8b177994dc29a707e363d824c14767b2.npy +04379243-2a64bd38a4e42f33dc43fde5155b3946.npy +02924116-5aa136c67d0a2a2852470de2774d6099.npy +02828884-33a40eba7b3382f5653e42b6d3d77b73.npy +03211117-60bde4ebc37f9b31473f10e6caaeca56.npy +04379243-962bea9f435909bf3c6e55b962f380e9.npy +02828884-b29e0a7af1f8d51b5c50390adfa8881.npy +03467517-adcb312236c71cdb63e6b27c89da971e.npy +02958343-42e6ce03b361102ab86e0633bb69faea.npy +04379243-8befcc7798ae971bef5d2a19d1cee3f1.npy +04530566-77cf1b9003d904df96bb95f1b1976a40.npy +04379243-2927b65bc7b9561bf51f77a6d7299806.npy +02691156-d6c655a7c97cab8e9f5f802084bd1d73.npy +04256520-8c1eff1f448e33f4d56c79d3df7792df.npy +03467517-73f004a0f2c5e09b1f20024850a8a0.npy +04090263-6d5027e3411b23459a2ee232a197081e.npy +04379243-516c46ceaf6619d07ff6ace05b36a5.npy +04379243-cd2ad198854d47c6e5e7067ae780b222.npy +04379243-40dac9b7b00849366bd83cbbbf17afb6.npy +04379243-18634e783faca47d668ae11a7db5e82a.npy +02876657-32bb26b4d2cd5ee0b3b14ef623ad866a.npy +04379243-24929a5fbdc7682d7fbc060fd555478.npy +03759954-c38c1a3036e7135df50956e9de496e43.npy +02828884-208b5f58f4f45d63ad5067eac75a07f7.npy +03467517-dcb51f940894768f4fc7398f5eb0c5e1.npy +03691459-336fcd767dadec9fb611871e114769d9.npy +02933112-1ec5e12f2b5684a24da5feafe6f1c8fc.npy +04379243-d8a73e0d8fae54c23002761e7a3ba3bd.npy +02871439-4eda0d3b5aedcf8a200ad3f421b6c3d0.npy +03001627-19d3ba04e165e67dcb4387db711dc078.npy +03991062-93acaa40a2d53c726b7154919b02cbec.npy +04090263-1690354ea489c58e493055786e8f9359.npy +02691156-420efeb902ba9c9f47f9199352b2dddb.npy +04379243-cab027dd0162c5b7f1426260885dd0ef.npy +03691459-981abfda92e702e33b9f0ef1fda503b.npy +03467517-eec9877379771abef4493a5b80949ad1.npy +02828884-98d2e8dc90f050d52ef1844825af63f2.npy +02828884-36ac567cae9ab205d4cf0f8e55d6cb79.npy +03636649-c9a464649fb52e99d5cb6d178687b980.npy +04379243-7e5b7032a9faef913c5e1addd9922bf2.npy +04074963-2053bdd83749adcc1e5c09d9fe5c0c76.npy +02992529-267a2d6fbf29c04cbc17518d87dd1f7a.npy +02691156-d6c1cb09e27c3fbce8b8a0b16211ba77.npy +04090263-667772e778d69333e2365746e867db8b.npy +04090263-cbbeaec355a86ba9870906b5178d97bd.npy +04379243-cfb97383aaabd98ead67befd78c3a0db.npy +04379243-d3a55d20bb9c93985a7746683ad193f0.npy +03991062-50498cc86e5eb62acb2a965e75be701c.npy +04379243-6bb09b26c75b70b01c6ed23568095b6b.npy +03001627-b66ef4dd7cd2674f91663a74ccd2338.npy +02958343-9cea9b79ea255dde56ffccfd33efbc84.npy +04090263-72033b782c4f440ffb5c1b0f759e2bc1.npy +04225987-c171d90db4c4ba56cdb1768065dafd0c.npy +04256520-12a0c645e0bb6601ad75d368738e0b47.npy +03636649-f29758075925a871d706ecb3379aa341.npy +02933112-aa0280a7d959a18930bbd4cddd04c77b.npy +02773838-65680f336a50db976afa58a86636d6be.npy +03337140-bbc16b3bd570818be95cd0dc8c2f0e83.npy +03325088-f8ff61c5374aef8672101dcac4ed75d3.npy +04099429-94a4ecdcaf34f9ade07c6fee8d4d96ce.npy +04379243-545c6c30ead2d411e6c5cd45aa112726.npy +04256520-2658567ef94749293784599b9f219d55.npy +02958343-4e009085e3905f2159139efcde1fedcb.npy +04090263-6b06ff0184e3108a4bcc18d4b892312c.npy +03211117-fe314324a1e7e5c967a964feaf6ebeb.npy +04379243-e7c6731436bc2301bf94502f7765c22.npy +02958343-65c067fcae3292d0e7540f431cab4686.npy +02691156-38efd4e4060d8b4ec231d70e1e0cc567.npy +03046257-a29a303f3da335bea64e5c46abb30c70.npy +04256520-3ad0d0becf611ddec6fd9dc5af8f81a4.npy +04256520-711c7f25142a3e2a57253dccd1b3fd5.npy +03467517-95d08e17b620ecdc266e8ccca523895f.npy +03636649-8b6338fa5916b40e7a5d3427f09d950a.npy +02747177-dc7ce614dc719649b394cfa64dfabe8e.npy +03001627-fa172f7f09f785bb492d9da2668ec34c.npy +02958343-c48a804986a819b4bda733a39f84326d.npy +02958343-ec994111db1da0d6927e12317acf49e7.npy +03001627-45039c59b957063e742728b30848ed03.npy +03467517-d71c17b4d1ffa131f10a27cbb87f3a5.npy +03001627-be7ee770ad59ed0eb07bc9fe525caedf.npy +02828884-d74a990634bb4b98ad5067eac75a07f7.npy +03001627-56f9ae090d2fe856ad5067eac75a07f7.npy +02876657-331601288075868e342fe691e18bb5fd.npy +04468005-5120379d6ec5d7e1326fcaeb388e38ae.npy +02691156-b1f40266ad9da400d90bfc986bc4c94d.npy +02691156-85c9fba37bb685d7ca8607f540cc62ba.npy +04530566-cde9d2f6302fda60cd8d9984f3ad2fd7.npy +03636649-4c266f2b866c59e761fef32872c6fa53.npy +04099429-56c13d294f8afb1ffb88d148e845f82e.npy +04530566-283dc6c755398547657a96a9bceb8713.npy +03211117-efae87e53a1fbdf05dc3653f8341633a.npy +02828884-c3f3565f0754f1c910917cc30262fb08.npy +02958343-8bf8a7694267756e3ab3dfa44f5fab01.npy +02691156-b092d523bdd320e4ca8607f540cc62ba.npy +04379243-4fe5fa039fceaa1823eb3ad3d378722a.npy +02871439-f99da003d6daf8743806c49633f7853a.npy +04379243-2fced9721464b4d9c955e5ed03ef3a2f.npy +02933112-6d448fdac1dc71f9c59350d819542ec7.npy +04379243-8480f767da5d68ca9de7cc399bc9b2b3.npy +02924116-c33fa5a2611c9142a680e164a8237975.npy +02871439-722624d2cd4b72018ac5263758737a81.npy +03046257-1251971bcfcfad61624cf22ecb5162b7.npy +04256520-f7c79c7a8fb79212ddf7c7c2aa2325be.npy +04379243-251160ca48f91de7ad5067eac75a07f7.npy +04256520-9571cf49ac1752984ee1dfc331dd3e94.npy +03467517-9c399ebc617349dcd016bd20f13ab302.npy +02691156-d172705764e25e20884a857d19f7439f.npy +04379243-dba86ecb3a5a4d234b3c42e318f3affc.npy +03636649-2cdb96501ab2ccbf35836c728d324152.npy +04379243-4369d61d4409bac0413500ea4648b88.npy +04401088-8961485f45d94383af4ba3ad8461249b.npy +04090263-2acb7ad7112de6c2394e22ae6de2db18.npy +02808440-6751ed8cb63cc76e3321831d2245cf06.npy +03001627-308a3c347dd24ee4fa2713776d82bf59.npy +02691156-9c0431249dd5a50dfaf7f0ef9aa8fd9e.npy +03001627-421746966acf9b175ecd29875b6f0d44.npy +03691459-1788d15f49a57570a0402637f097180.npy +04530566-850d6a53ae03a9aab2640ff8dd6f4f82.npy +02933112-1aa76e87d7bcf5c0c59350d819542ec7.npy +03001627-67d86ed49b1bd1e7af802a9d0ab09410.npy +03001627-b42953e6e55ba5d4d2bc32977ed52527.npy +03691459-267dd5dea4dfa74bd4e62d99c536bbaf.npy +04379243-93fcd3809bc2b9e955f46d55537192b6.npy +04379243-d760cfad1855ef2d35f7fdc3c0cd22fe.npy +02958343-3cdb021c923034c68bb386c7dede359e.npy +04256520-8769b3281dd41c771b17743c18fb63dc.npy +02828884-c8a2ce0e65da4b817b11ae648ea92233.npy +03211117-5097aadb04ed3518f91a08212ded5334.npy +04530566-2e54c2bad5d117994daa4565dd30535.npy +03467517-c4d76ad65741ed1cdf16e78e07c53dc6.npy +02958343-5ebe8c53a7b1f554f445715e3bbcd7d0.npy +03001627-a91b2c89e543a4b3aa3d970c5602cd4a.npy +02958343-1ae184691a39e3d3e0e8bce75d28b114.npy +03001627-e6b2017501b20ce1eff1a662025674bf.npy +04379243-61d9def9b2df3e40dc6f96c9bb9e3ae6.npy +02871439-3fa60816f15b58c4607974568e26586f.npy +04256520-d562328792a3314519fb4103277a6b93.npy +03797390-c39fb75015184c2a0c7f097b1a1f7a5.npy +04468005-6d8ed6218777b1fcda43f9c7d6be09a5.npy +04379243-bac09b6764c6c6b9f4144767ba2e06d7.npy +02958343-ca44101f11f4346a34e8e5a47ae999.npy +02933112-cb6ca53673e681797292641f4348a707.npy +03001627-6214c8ab2dbae2517eaeab1f0c9120b7.npy +02933112-46304273699efb534b8710a3469971b1.npy +03593526-6bce9e16470b57d0c5beea20858a99d5.npy +02828884-5a0468d7c5ce7af6948dd2bc2d391e57.npy +02958343-8f715205d2e70c1ebda733a39f84326d.npy +04379243-3b874fc5f84eff21492d9da2668ec34c.npy +04379243-8024f88aa0136725804722305621f918.npy +04090263-99a3238af6d1b857178b53c3b6bafa41.npy +03001627-731a357bca179804951c1fffab4f5807.npy +02992529-e3c02395e83fefaa42dbe6bfe3cdb29d.npy +03211117-b90e7ec58327059e20327f464fa1f012.npy +03636649-551f8026ff0917c781a172d69c52a28a.npy +04256520-d4c6f2749bd85e9a6a9633583f89b17f.npy +04379243-bf0b9b88be76628440126a5bcf48fc87.npy +04468005-7fd1b974ea23815ba0338a523d3365ec.npy +02958343-3b2e74068fee2458dd1e15301c83686f.npy +02808440-dbbc5c9f97b42166c45c4181842feaed.npy +02933112-a4a939a0bd8f8cd9492d9da2668ec34c.npy +02876657-5c1253ae61a16e306871591246ec74dc.npy +03001627-694d9c2e9e769ffe83221ad0d21775.npy +03001627-708e7253604979d06d83c04495f2aa08.npy +03325088-ecc6eab80e50ea2014b35a7d7cea7130.npy +03001627-58a1e9909542abbae48dacf1789d97b.npy +03593526-7f355d9510fbe2b02af07f81a2ca6736.npy +03691459-16eec6c601ae44c06299da17267bf77.npy +04379243-2cd211982e3293a7492d9da2668ec34c.npy +03001627-9dc1371b6989479c9c0ca344f487323e.npy +04256520-388b70afc2bff624fe7ce990d81a91ec.npy +03636649-c695408a86062c4d242ea50288b3f64.npy +02924116-e868f6184d38be0be8784f880dac0f61.npy +02924116-1b137084c6f7facb41cefd10ce5d6cc0.npy +04379243-82b69c9b72a5159ce76bc197b3a3ffc0.npy +03467517-dceb9450f6d9f0bc171b7dfa253c9cf2.npy +04530566-6bbd0b0e09dd43017ddd35a83509257f.npy +02828884-7ef967a69c03c63dd3a0736b56eaf4aa.npy +04256520-640aadadf4fcba8355f9a00acc25f137.npy +02818832-bb1f8f4efd67582aa4aa57d4816c68a3.npy +04379243-212f9ea1cd96196992f4c88fd91c6b1b.npy +04330267-fdaa15a58a2a6e0d18b188ddf020af53.npy +03325088-21d413dde8e653fc14b35a7d7cea7130.npy +03467517-d50c76c0adf8b657f6ca74c754479291.npy +04256520-52687262fd77ba7e4de2cf65d389c763.npy +02828884-991803aca7fca258b40f0ac0fb9a650d.npy +04530566-e64611b8f590d12d2ae6c39a82bec2c9.npy +03691459-d922dd8309247d10ef94793a67b4c5c0.npy +04090263-f9ee6c612895cfeaf4b4b1b903442d1d.npy +04379243-4f4ea0588e9444be30bbd4cddd04c77b.npy +03211117-8fde0d7ae62ae2c802b4057d350ec8.npy +02691156-8504e370736b26604d210d9468aedaf2.npy +04379243-19708555411f795459a339f8ff4d3160.npy +02880940-c0f57c7f98d2581c744a455c7eef0ae5.npy +04379243-86ad91ef08c53dd77189b31b3e8c8ef3.npy +02871439-cd0563a71a03b69688dcbe86402c7c15.npy +03938244-ec4b9c23be44b35992cd8215a5562ce.npy +03211117-93b702bd7ae98bd16942161d780bcaa0.npy +02691156-13ea0a2ac279dbaa5e9e2656aff7dd5b.npy +03642806-7941f26b5f18d9554ab5d84c066f37.npy +03211117-2b0b8c07582c83d426bb7052f66b6d5b.npy +03211117-5e7034ba47012cf088c7562a134f5ac2.npy +02691156-1bdeb4aaa0aaea4b4f95630cc18536e0.npy +02933112-152a850e5016fdd6e0771d4c079a0ec2.npy +03211117-f0482a9b7084c6f8c83b51ded97d6038.npy +03636649-21f7bf15d2f6a765bcde6f92ef1f7ee7.npy +03001627-ff8efdd26382bb863769fe68c3ec842.npy +03636649-38c6b87674e80ee8515596bfc4f5c627.npy +04090263-e3a1e9f4699dd059d9fa04bac43c622e.npy +02958343-63dceacb54c3c170fc7fcf88dfdc47f1.npy +04256520-3ea28d2184d19410c823a47daff020c5.npy +03636649-f41b9c3cb9243780dce4754e673446ce.npy +02818832-5931f3a3ff29d1a36e07666ce67ff5a.npy +04090263-98ea642f1f50b9686b9603fc5970ab91.npy +02958343-ccc6b5ace9f5164d26068f53fe0ecf07.npy +02958343-7f6031f1738d52546436916a86a90ed7.npy +04530566-677fb8c312d9c5642712ffd807ced208.npy +03001627-4a19f4e47476ee654b3c42e318f3affc.npy +02933112-bd0388dc8384961ccf004563556ddb36.npy +04530566-fa656e5b70f12edcbe7ca2216dc1576a.npy +03325088-a7a2ddaa46155a723970a6f5d8822d49.npy +04468005-99c1749b8ffd4c9d52470de2774d6099.npy +02691156-1d1244abfefc781f35fc197bbabcd5bd.npy +04379243-61128b7cb47e0e6bd6e704b04fd0cd56.npy +04090263-e8931ae7d89ebf11d1c304326f7509b.npy +04379243-d60a5ae4802e7338951c1fffab4f5807.npy +04379243-7dea64a734cc77e6fc5030c2f25772b.npy +04379243-4079aaabaa6451a2765ca89770f206ec.npy +04090263-c3065c23eea6a998547046f04c724fd3.npy +02691156-9ff7d7d71bcf50ff4fb6842b3610149.npy +04530566-64bf2e0712889fb77c1c262c715c9a86.npy +04379243-d37b0328d4b5a9454d9e7559651bb818.npy +02691156-b7b743834a6d78c2225a23c790f08fdd.npy +04379243-9271bb0cab9365d44b3c42e318f3affc.npy +03624134-e6b32b3c927a7fbeae29387f6eb32067.npy +03948459-7681e8a8ba049dcec16b50401ee47ac.npy +03593526-12d643221a3edaa4ab361b6be63163da.npy +03001627-357275196334dc4feaf288f952624966.npy +04530566-91e0e1a6dbf302c3d55da98ad008849b.npy +03001627-42635d55c5905a682672e8af102e0b3c.npy +02691156-dbd589812bda0b1ebab624e35355496d.npy +03001627-1049953406c81b237eaeab1f0c9120b7.npy +04256520-3d95d6237ea6db97afa2904116693357.npy +02958343-f3760c5e8b97149163b803b494079757.npy +03001627-9245c7a6d33320da7b707c797539b200.npy +02691156-cff4a52406b84da7aaeb49542c2cc445.npy +04379243-fca884f9aaea06cc9c1e87e8cf2e52d8.npy +02871439-8e47f2e5ebdd38d8d810b14a81e12eca.npy +03636649-bfeda9055368d2dce76bc197b3a3ffc0.npy +04379243-74f985d5bde29b01dec11b4972c4b3e6.npy +03467517-37e72e4a18a4d0ede2e4961161b75547.npy +02958343-3844e637bc560e6298a55e96872d31f.npy +04256520-5105549b9de890319fb4103277a6b93.npy +02958343-ee0232b37ee6265bda72093f9b5aa73.npy +04401088-271421566061988a93d9d97ff82834ba.npy +02933112-4539b185db32eb4a533276a8c0b1c862.npy +04379243-a1480d2276574cfee6c5cd45aa112726.npy +02958343-d0cf2f187acda5736be7348aa770e4ca.npy +02808440-f9215f88025cf2474258477db4e0c1b.npy +02747177-e48d8446159614caad5067eac75a07f7.npy +03790512-82c8d89f0d15429a17bf584c2afe53e1.npy +03001627-e1623d4ae16bb17989e686021e3387cd.npy +03593526-83e749b6b8a6db9af67a276d485e951.npy +03636649-51b4f0fd600a7cdc580a266ffa083ba4.npy +02828884-b6ab037942cf91c0601104cd2d998272.npy +03001627-ce2acc9d7aea91a0988fec2229ccf13f.npy +02933112-932ae6a9eaca65a03f4b30b8df1dd26b.npy +02958343-151bebc457224c2733d7c9e122eec9b6.npy +04379243-55221b101eec29dc656a19d1d18fdbac.npy +04379243-d1b44c2dc663cca6b8baed360b6cc5ee.npy +03001627-6dc5a07a13fb7dc32ff27b24dc18a6e8.npy +03636649-69ae5e9ce88c9262dd0bffa2f83687b2.npy +02958343-b0a7789537663f7ba1ff2929b2f5cf19.npy +02691156-1e0a24e1135e75a831518807a840c4f4.npy +03991062-23448fc0b511d7b61e66636678929092.npy +04379243-c92ea3f511378ab1e21111e385a0661f.npy +03001627-3010d6ca1b1e8ce3bf54ca9b2f215141.npy +02958343-a74c1aa71334c6af20363e2561dd589a.npy +04401088-2725909a09e1a7961df58f4da76e254b.npy +03211117-cf7294db3c65ca5c945ef919ad31a7a6.npy +03513137-7e4e3a4a38a589232f20449572a3a77c.npy +02933112-9a0013f4e6a0521b5670497a6e548500.npy +03211117-d3bc26796e7fcc6b3956af37bf042355.npy +02691156-34c669182c8c9a2623fc69eefd95e6d3.npy +04256520-f2e7ed2b973570f1a54b9afa882a89ed.npy +02958343-b47d993a5e2dd15e3a3aa1d2d3319a4.npy +04379243-79eeee790ed5a5aac242632b2a8c3129.npy +02958343-63e0df089d6c1442f3aed64053e21b3c.npy +02933112-b1bb6113dcdc8a65ffa51bfffbc09ebb.npy +03691459-e97a846820b094b8f439510dd98d9326.npy +03046257-4f6b01b011b8b21354cd2a0ea6cb618b.npy +03001627-dfeb8d914d8b28ab5bb58f1e92d30bf7.npy +03337140-2a853c2492bc9615ce5d6e9371bb5c33.npy +03001627-f34fea2c05dc63d090984ccce1017e45.npy +02992529-b514d253eefdbfdbddfa02c62bdf0f8f.npy +04256520-b435dc75dfcee77c4b3c42e318f3affc.npy +04379243-d6daf5eca30ca0965722577712723fd1.npy +02818832-90d5d27ab2a94109a043a79379c5661d.npy +02933112-a9bfa9259f31ef9fde650492e45fb14f.npy +03642806-4348768ff9802fc5ce1decf313ece97f.npy +04530566-5702b12bfba4b9eb9223657c918f0a45.npy +04379243-7956ac7aba6295d1c2fd07f66cbad0f7.npy +04379243-3379b29c3a6221d79996b1334107828f.npy +03467517-fdb74c27462dfd837c481698bd5233b4.npy +03636649-3a0719c32c45c16f96791035e86a30f4.npy +03001627-74e14880b5aab8e3490ad276cd2af3a4.npy +02691156-b87185699318f4b635fc197bbabcd5bd.npy +04256520-aa2e8a77de22165ffe369f4f96683f52.npy +02958343-1ed012d3232de232473f10e6caaeca56.npy +04379243-414f3eb4c4de757cdc97baf002c8189d.npy +04256520-784b4379cc7e74e14fb315ce917a9ec2.npy +03624134-daf2098f026e292c152b5e07600b5ea7.npy +03001627-68af43642fa145115029039df67c2549.npy +04256520-9aa38ab7fabbd6becb6924eecbe974f.npy +03325088-7837cd8d1e5e69d4b362845c6edb57fc.npy +02747177-22f7580ee1819eb7fc435963bd99e667.npy +03991062-90dfa95b34f3a84b6777543134f0db6.npy +04256520-1442fc6ef6b82c8ae1da81584e31b667.npy +03001627-67ce9e1ac8e41027bd16d4490a10a752.npy +04379243-7aadbba28333e40a77e6105b101d7310.npy +03325088-13e1e13465fa1a67b362845c6edb57fc.npy +02933112-8b188db0cd8ecb909f076a53721d9427.npy +03636649-ca09dc8016291c171735ea0e092a805a.npy +02933112-1459b403c084a33e7694593a26340e.npy +03001627-355fa0f35b61fdd7aa74a6b5ee13e775.npy +03337140-1ba863365511363a91c352d02061b3f7.npy +04379243-a257171096faa6252ea98d69e91ba870.npy +04256520-147a9f656054d718e10a48f2bbb9bef4.npy +02691156-78c3a29d1153e68e5fa2a5df3ce5bc40.npy +04379243-cd5f235344ff4c10d5b24cafb84903c7.npy +03790512-de1f30fbebaa2cd675e2c647bf7937f3.npy +02828884-48c9e1679ada2949fd8f87bd7d4c2514.npy +03001627-3ac2da28e9a2f547ce4f274577283b16.npy +02808440-bebbe478c5c2d44e44221bef0fa3c36b.npy +03636649-9f8c2c2c3b9796654b3d6a0fb5682cc4.npy +02691156-43beab0c1cc46ae641b5a73cd6c05ccd.npy +02933112-d0af907a612856e964b62a9cc93b56f5.npy +04554684-622d6f378276a09b8fac6a8030e15671.npy +04379243-e27d9fece990d39a0f23466c3c25e2e.npy +03001627-438e57bab04de55e8544f4ec4dad7a5a.npy +04379243-810c87b90f7dc301da9bd441f1db1dfb.npy +03759954-91db799921bc0241c040d6dbf5370e2f.npy +02992529-f420bf37baaeee5621844676433a0aca.npy +02958343-92cc3ad1d3da26955fcb05674109534a.npy +04379243-ed9dc0937009dc031311158f08f2982a.npy +04379243-61b6b273190637e5788a7b7b4713dbc6.npy +02691156-80af162c0c01f27c4f8a08a5e6b028e7.npy +03325088-b68106b79d8b98b95268c5e200a25358.npy +04530566-7b00ce37add93f06ffbdd9e9972332a7.npy +03691459-7e105d770e297ee43dd0d6160c4dfd18.npy +03001627-7effccaa74122b5f2beec56b24479ed1.npy +04530566-5c6c725a75645a305de2c7f7608a946f.npy +04256520-3d498fd733de605a929a5204e472930b.npy +04379243-88e73c92d8d5195fb8b431083b6191e2.npy +02808440-93b1dc8aa040da641f6566a4d01370e6.npy +02958343-1cc85c2c1580088aad48f475ce080a1f.npy +02958343-728f6f29382b70053ce4e6f97016bd5a.npy +04256520-1b25f96d97a94b05125abe33bf4f0061.npy +03001627-5857dfefaa1b6d071d9fd76961a98198.npy +02924116-c7bf88ef123ed4221694f51f0d69b70d.npy +03001627-895099e136437cb799860e9353bb52a1.npy +04401088-21a7e90867b64433316979ee2b237f2b.npy +03001627-ce95fa90122dd67e5935ba184b9bc177.npy +04090263-61c0df4a0db0a32fe73c917c8db80e59.npy +02691156-48df2496242053da4ee0fb6a51564c3.npy +03593526-166c3012a4b35768f51f77a6d7299806.npy +03636649-c211f82e84eb62bb776f01d35517da23.npy +04090263-e3230062ee3def46aca1893e093d31f3.npy +02958343-18cd6293d7b17a698ce68842a487b19.npy +03001627-8a85b0675605ed8219fb4103277a6b93.npy +04090263-e0b23c80cbe3a2d8fd8c7a1bf5db0aeb.npy +03211117-51fcf8537a132b789058e0e56fa89a94.npy +02828884-7f418f4737d4a7339702fe80e90cab1c.npy +02808440-33d2b4361e3fcecfb340943d9bddb446.npy +04256520-36f4fa1689803b442d19175e7d19b7cb.npy +03001627-4a783b2ae8fba8b29dcf2183c858e6e5.npy +04379243-1307c27c3f1d1f7a895e947287fb0c95.npy +04530566-c991fc4636615e64ed01ae0c90548352.npy +04379243-794dc333392caee153041c49040be3d5.npy +02871439-b26b03578ceefc20f9c0f9cbb10e38a2.npy +03001627-1b83311557e48d6328145ddc1e2c18e1.npy +02992529-1bff7e425c06b65af431996b7f8b435b.npy +03211117-edfc3a8ecc5b07e9feb0fb1dff94c98a.npy +04090263-ffba44e241dfb481efb47d8e2c9f3b57.npy +02691156-22831bc32bd744d3f06dea205edf9704.npy +04090263-2bdd7783684aeff0f3ece95ce0e0247d.npy +04256520-50766e42adb211675e0d6e917505f52f.npy +04379243-aa8f7d94b5aa9cc1f9ef5ec0bb70f1c.npy +03337140-a0cdb98dabb459f7b8183a4a81361b94.npy +03211117-41f428dfe76c1788957b752c832ca929.npy +02818832-f10984c7255bc5b25519d54a714fac86.npy +04090263-6d026044f6c68821de698295f9180ced.npy +03001627-b8f2712e8330ba6b3c9fe3a963c6d73b.npy +03691459-de41e90d949a21d6a41c66e27a37f014.npy +02958343-1cd50bde9a3e711637b0898eccd7168.npy +04256520-da77fefef637adc26eb9b08c8a74d159.npy +03001627-dfae4f9155877a1ef57b53e86a4ec824.npy +04256520-854ded41212e767c12132bd78ab15cd5.npy +02992529-c864337d009c823290a9c3b0b32f8569.npy +03467517-a39dcefa599a76dd93f0194265a9746c.npy +04379243-4442b044230ac5c043dbb6421d614c0d.npy +04379243-edb69ee3e3e66e9bc242632b2a8c3129.npy +03211117-f1a3e41b45de104a810988cb5fefedde.npy +03001627-7ebbce44a6001e71268677b0fbb8a262.npy +02871439-e9b41b47c97866b7e76bc197b3a3ffc0.npy +03001627-a232eec747955695609e2d916fa0da27.npy +04379243-9b365e622638616d58df8eeaf3dad1c.npy +04090263-9e43b09d2c4115276f21883e4b04581e.npy +02871439-e3738af2b535ea36ecf5e8796652a83c.npy +03467517-a60209a0df7a3c87282aa382fb875f4c.npy +03691459-f663176a43096b35a43ada367b02a4fb.npy +04401088-235cca962513b7a7629cefcc54d102ca.npy +04401088-2ef0e93ce68dfa74bd1f358005ee8ea2.npy +03001627-9d81bc691486a3c725bc9a8086ca05b8.npy +02818832-74d5ab41106d27a8bf6d866879baaa7f.npy +02924116-43c425087cf9d73352470de2774d6099.npy +02691156-6296558889cbcba8faa7ec7d870d2e09.npy +03046257-f82e90f8a6d49827e8784f880dac0f61.npy +04090263-9b19164c5b17f3016da79efb34b8c0b4.npy +04379243-ef9f3af9b8453613febad4f49b26ec52.npy +02808440-fffe3ce4db102b3254d7082b34825ef0.npy +04090263-1e62da4891f2021d950daf47e5ba3cf.npy +03001627-6bb6b27aa687d422d612b1f62c413c3.npy +02958343-42147d774e08199564c7d8ebbbb68f5.npy +04379243-a2cf3d4375a5c6a65dea31ce253437e6.npy +02843684-524610c549c74ff64197bf8bf6f07b46.npy +04379243-3f5497bf65ff9b91c48d90eef8384210.npy +04401088-83f766eff3c5c12c781fb7da315db2c1.npy +02933112-851274c7a38bedb5f55057dede601621.npy +02958343-d05aa55f9e5b4d10afe1d4530f4c6e24.npy +02924116-e299444f1a4c7457fa9ee9b3a7eba069.npy +03001627-eb9851403aca75937d395837145ded71.npy +04379243-a4cd409ceb0aa148d93cf5f5bfd78ab4.npy +02958343-294331fc6c86a51ec805dfe4ca9f2fdb.npy +04379243-7cfa4ac4e24cd680c3bd24f986301745.npy +03636649-199273d17414e77ca553fc23769e6051.npy +03001627-52c32b187590e8f3bba5aaac798c64af.npy +03636649-6f6a74a5528a7b5d88e7662971dc736f.npy +04379243-afa90f39238804b35778775dfd5ca46a.npy +03593526-82806d655bf46d8793b839ea777587eb.npy +03046257-3a5351666689a7b2b788559e93c74a0f.npy +03001627-4fad9d9b2c73cccccf0517eac2f2d331.npy +03001627-c8166f63964058199947cf98084faa8.npy +03211117-d911b390503a11f96436916a86a90ed7.npy +03691459-34fec404bf5a83dc8fe1b374a74b9d43.npy +04379243-9c162d575505f102ad16260d4d73b56.npy +03928116-47aa44d818a406d822d6b12a61cbb9ae.npy +03211117-2be8c8104d0025ba74dedaf762719321.npy +03636649-1845801e19ac5c22683869a26110a529.npy +03001627-b960544cfd0ff09f26b2c6e6d8c1e1ab.npy +02691156-deb9d02cd1eda25270c4138179d9ed97.npy +04530566-d6cf4f71059b98a13d9a3c3392922df1.npy +04401088-987662da7f345b272b1c9d869bc37167.npy +02958343-c299ad24d291a4b6756936223b42a971.npy +02958343-7e65e7db2b227946631a8860374e7eed.npy +04379243-fcc0737ae08a9cfb63eca8f941f00cca.npy +02691156-d84bb293898861ed9b2acbfd8323f804.npy +04379243-80f8961877a467b23002761e7a3ba3bd.npy +04004475-361e69779293348c7cc896d3ea5ca772.npy +02876657-f853ac62bc288e48e56a63d21fb60ae9.npy +04090263-27326efa9e84ca6aaf365ec12406f363.npy +03691459-c1cc6f59c8c6406df64115eb33ec13b.npy +02958343-e899ede8bbc146278746a6bea8ba48d.npy +02808440-d171a949c9583599ca972daa503b3095.npy +03001627-840b73e5066afa12941584a3d730ae7c.npy +03001627-2c351621045e25351385913bc50a0210.npy +04256520-3535ee6f6b070f07a1989a802607e7f3.npy +03001627-f1563f3906ae14dd32b8e0971fc6a65a.npy +03046257-64f72d2cc5449a28e2334ed17f235e6c.npy +02828884-e2e528622ff47c32cb2a965e75be701c.npy +03337140-6633b658534938ded02b906026bee536.npy +02958343-5ec3322293a39816ad7e7cea4034d226.npy +03642806-76ce3dd6212251d34145b5f47fac09a5.npy +03636649-ecf9ea749680ae432d9c07d3b9171829.npy +03046257-53aff981d28b365ec5996c1602569cba.npy +03001627-e6328c1bb6b194f262e682c9809bff14.npy +03046257-412bf74d9811f27dd06c8fdd4cec77fd.npy +04256520-dfda3c467eb6066fe6fe3612af521500.npy +02958343-ba494b33be3a3e0dc1bbb501b1d87871.npy +03001627-61d29e8133da0b58d1fd43e2bf80195.npy +03991062-5af2910a3b96af5cd2b12aa6a0f050b3.npy +04530566-7a3ad44b854faf361f377e6c4dfe0096.npy +03001627-bd3941eb3bcca6ad9055f83d11955109.npy +04256520-592e8295672e1419e82c020151d41155.npy +03001627-7f6858bd9d4af9df97316612e1a4343a.npy +04090263-411de9a0a7a8e3e9a0d6b294e290074d.npy +04225987-619b49bae27807fb1082f2ea630bf69e.npy +03001627-ca2294ffc664a55afab1bffbdecd7709.npy +02992529-2f468e01f4fdcb54d81a607e3ac2f927.npy +02691156-b2dd8a3e977d8e5f23c640e813cbc041.npy +02691156-f97a48680d63a78a9751e413d5325f7d.npy +03085013-80512f14251fb8c94f0dfda6a4916221.npy +04379243-bad7911965fdf1786487ede8a6f074c3.npy +04379243-24732a80e4b1a44282db9fca4b68095.npy +04090263-26bf4f71d7c24af87ec95138ef83ef2f.npy +04379243-3a069fc75bde2735aaa6ab0dcef7c556.npy +02691156-926749549b15941e6455d739a5cbd8d7.npy +04090263-3151db7f965943ef9bba8f87a19ff3bd.npy +03001627-e9a8c9067bc733ed95bea7c29e873d16.npy +03001627-e5ea39e2b4c28ea2a8df8437731d97b4.npy +04256520-fe154cb3a5dfdffc5ae252905262c0ed.npy +03001627-c571ff6f3231fe861e1a7bd9d68b88a6.npy +03001627-27923c3fde05f14b5ea23a116671b38c.npy +04379243-ea6b9474514df497febad4f49b26ec52.npy +04256520-4ed802a4aa4b8a86b161f36d4e309050.npy +04379243-a5815741cc777e643002761e7a3ba3bd.npy +02828884-be125cab2902e0e163b2acb037dfbcde.npy +04468005-87b7d76dfdc7433552470de2774d6099.npy +04379243-3d791e306d7ae620b3b8d66c43b5b940.npy +02924116-f9cf9ccaf5491830ca857150e7faab.npy +03790512-56f5e30ad65f01561c6c61410fc904b.npy +02933112-33ec57af7f648994da5feafe6f1c8fc.npy +03928116-88f854b66978d1c45caaf941a8fac2d7.npy +02958343-84ffded0ab4b499588ed7b6315c3b4a.npy +03991062-3dec5904337999561710801cae5dc529.npy +02691156-5cd19fcc882cc769e8b0cab853748d53.npy +04379243-743d8382aa44117e593ebeeedbff73b.npy +04468005-f26e122bb890e6ee810c01b1498aa2b.npy +02828884-2974b7f87eb2297ffebad4f49b26ec52.npy +04379243-fbf9ef8784c0cb8485c1a9fb01e08349.npy +04256520-fa71486d68dbe48bf27b78f69ac93684.npy +04379243-8cebe5dcfa2b907f47c638c0eee4a2b3.npy +04468005-2c1478b556f8cca752470de2774d6099.npy +02933112-12de47490769694e490ad276cd2af3a4.npy +03211117-6e3fafd33a4683d1fb0a4dd466ef3d66.npy +03001627-b8666dca76b418e04c9bf8fa5a14f3be.npy +04379243-738e5983a229c432db984b8f0550fcd4.npy +03211117-2c4f9415edb358adb71a0e5ffd778fe.npy +03691459-2750caf7565977341ef58b31c4ba0d15.npy +03325088-9f4ab72b17226d3d843f813f752a5e35.npy +04530566-54da496566d05afb568b456e2715b08f.npy +04530566-fd488ccadbc89bc7ece8bb633fd3452d.npy +02828884-d6580bbf1220d39ede270fc3c23d78b.npy +03636649-ed54691cf655a8a3b3a8888e78d004b3.npy +02871439-3c5225f973732610664b3b9b23ddfcbc.npy +03991062-54fdf8d25110bb95993afecc2c675915.npy +03761084-fa70f7c905cd59294d895026cd5c31a3.npy +03691459-ee6445b3657504053839b8b68c69081c.npy +03790512-86a247b7f3be38957395d58407f193ba.npy +02808440-5f2cd0c8c02d7557bff8b2d517ae4561.npy +04379243-6e23179a3559775a65eacc25f128a1c5.npy +03948459-5b2c7491683bc482fdd247fb557dd75a.npy +02828884-a5a9a0be36997bd82f549c6b85154162.npy +02828884-1b80cd42474a990ccd8655d05e2f9e02.npy +04256520-41f47dbde823f29640d304b02c5868ea.npy +02924116-d5a6bbe13a5781761afedc87fe387fe.npy +02958343-63069a0c741a4d228b7c308bd543da59.npy +03001627-13fdf00cde077f562f6f52615fb75fca.npy +02808440-e9c2323050d30491b362845c6edb57fc.npy +04256520-cfa5feb7486f88ee1b8fe07f15de05f7.npy +04090263-69240d39dfbc47a0d15a5887ec2183c9.npy +03001627-43849351a4da550b33d93f57729688db.npy +04379243-656aefa835e5f6624b3c42e318f3affc.npy +04379243-6ae5a011c8724eb5c3bd24f986301745.npy +02992529-95e61ab6f817d7ffdf3f86c9fe70c0ad.npy +04379243-33857c2548cc653ba53276bbe109327a.npy +04468005-840a2e6a291049ad85b408a8edc983b.npy +04256520-126ed5982cdd56243b02598625ec1bf7.npy +04379243-f12210d97248ee00e3db80a3cacc6e3.npy +02828884-c57b336bd865c0907b20cb946bceb58f.npy +03001627-9f9c83f3014f19c79e4965f0106e00d9.npy +02691156-10cfc2090a2ade124c3a35cee92bb95b.npy +04090263-3a3c0edd93ed40d35a39b667673bce58.npy +04379243-a253b171a28f3ecdb781d9dcb8ecbccc.npy +02818832-24abc08487b7d111259864675d182396.npy +03001627-e9c344a392e311195b903ba10d2ec446.npy +04401088-9dcc24af7e0df254525b3f0594400a46.npy +04379243-e8afe4f07f221087620018391309f97.npy +02924116-29c4c3d205d4d1dad4ea1a05271e100f.npy +04379243-27008d8569ba4426f577ff4de1ac394c.npy +03001627-688af6f43377f16bc3bd24f986301745.npy +02691156-23f911351a5801aa46555ee25941a22e.npy +02801938-814bba8e48083abfdce1af5c27e3da18.npy +03001627-436ed3a8e05baa0d492d9da2668ec34c.npy +02958343-b3f1ad55fa401c35e8c505ac322336cc.npy +04379243-2517066dc728ebb955dbece39a4b7905.npy +03467517-6f52e760ce1d8b95fe2455ba3d942ef3.npy +02933112-63397b0df482d51ad7838dc22b16368e.npy +02828884-ecd56b7b86c4d94ad1f278e1513f3b7.npy +02747177-ae3257e7e0dca9a4fc8569054682bff9.npy +03636649-be02ef97e47b86c34e3474b03483338.npy +02828884-bc1261eb081cce07467f6a563eb9f7b2.npy +04074963-1941c37c6db30e481ef53acb6e05e27a.npy +02958343-50f4fff3a26ea3518b3ab49d2e0e41ab.npy +02958343-477ffb061f40e10e148f8c864a546424.npy +02933112-8f55954a0b07a4b2bf64ff63662d244b.npy +03948459-f4cf735786b69d7a5d0dded52efeb4fd.npy +04379243-a24af284041888bd5f05ba8053abf6cf.npy +03691459-c280153b72c8e8ff571d223b2b8e4a24.npy +03467517-9e6221cb3421a1a1082f2ea630bf69e.npy +04379243-8483abf40b0b4a65d009c98a5b96836.npy +04379243-807c73aa0a556bd496a3517f50eeb9f4.npy +03001627-7c7b4bdc2fc34ffdb398ef956214258e.npy +04090263-30c4a2e9a403c9d9d7cad6f9e585deac.npy +02828884-c930760585e923cbdeee898eeed8aea9.npy +03636649-9c3646d9db630e1d6bab719bf4ec73ef.npy +04530566-8497e02fa1662113776d8bc79b9caa2c.npy +03001627-54b7d484dbad29cdffc6e457221b9271.npy +04379243-c5480855c540290ecb922bcc33df0268.npy +02958343-89026c748b9cf721bda72093f9b5aa73.npy +02876657-fa44223c6f785c60e71da2487cb2ee5b.npy +03046257-75b2120c563d66edbdfa5e0753fa3240.npy +04379243-4a11c4ed20638d74c3bd24f986301745.npy +02808440-401637cb32f0eebb2b8489ea79093b09.npy +04530566-ddd02c6fb780d4f6c683d3e7114aaa37.npy +02933112-2b376f6dfed75d53684b7bc3f8a9aa55.npy +03001627-46d7e85d80411f50a094848ea4d06501.npy +04256520-e5f51c7ccf8ec35d2f134420f7b0d7e6.npy +02691156-934dd5529c22cd05bc0909d98a1ff2b4.npy +04530566-cab7f319f0b3cf8e57e59e0ad2d11e74.npy +04379243-68680849282fb0be21ec2f83d790ab97.npy +03790512-fbe400bd5e06d541617798af67b81f2f.npy +04256520-e17c6810519ba81a559916e9a5177b0e.npy +02942699-6c14c6f6cca53a6710d0920f7087353b.npy +03001627-c42b305fdffad7c9cdc9f3b79a373ad4.npy +03636649-9c11cbb88d574584c4f1f36666bc4b4a.npy +02958343-6f3887b3b8253284de541e973ae662b5.npy +02958343-7da7ba42dbd0a0f9be40bb45ea25a041.npy +02691156-2636cc55f0bee49671d03b466c72ce41.npy +04379243-fed49ae8578b251d9e5f3db95fcbc5c7.npy +03636649-98f1dd4a250a906fb5fd9907631a04b7.npy +03467517-b2861185931876e1e1f2a1daf140ac9f.npy +02691156-5c4095795aad447f7301f2b895d332ac.npy +03790512-973d75ed9c12836f3d033e6cf82ec72c.npy +04530566-da73f51f17f0a8bfb0d00cfc385a039b.npy +04379243-59027dc9bd7a066ec031b2e122ae5028.npy +04379243-687c7be604090bf89cd431573238602d.npy +03001627-588dc044970bc56f3a4a5c95fa1b0032.npy +04379243-9a71b92445cd3f023a9bc242c86fb7a0.npy +04379243-bd27680b9f09262bbdb2cbbdf53d8900.npy +03001627-74e6ecf3201874777954eb05bbab463f.npy +02876657-bf73707d87715aa8ad5067eac75a07f7.npy +03001627-7e5dada1bee3e6dfca76c527f185435c.npy +03948459-d1ba405fef56efa0fa29682ba98e856d.npy +03001627-77e84b5e6526be75490ad276cd2af3a4.npy +02933112-aee149ff795d5a7ac59350d819542ec7.npy +03001627-436be9df788b706fb40f0ac0fb9a650d.npy +04379243-142060f848466cad97ef9a13efb5e3f7.npy +03001627-b07c1560f5c3bf20525319ccc5eeb31d.npy +03624134-a782251f2c38b909bb4cc32522c2ea6c.npy +02691156-67979ab8dc522028788e57551eae0744.npy +04379243-3604b060233bfd79bd08524bcb66a009.npy +02691156-34da5dbfb4bead034c3a35cee92bb95b.npy +02933112-aa28deb4dd304d12f51f77a6d7299806.npy +04530566-f9cb8429f822b8469ae563bb6367e47c.npy +03001627-6b7a74a6a77b0699c3bd24f986301745.npy +03624134-3cbec0d04a115d9c239ffdb3f2fb535d.npy +02691156-a51d836a9349b2a1f42bc0eea174f82b.npy +03211117-c62af9a75f8779b82b8499d50978754f.npy +03001627-36ee2823173fecc8d22730b0728b2fc9.npy +02992529-61424998613d67b75ef3453134070b3.npy +02818832-7c078d8ceed96b2a115a312301bdd286.npy +04379243-27f9965a337bf46d85924458b86f34.npy +03001627-7715c9c229d80afaf487e71bd57b6e0c.npy +02691156-97066012fbca5983c74417871493eae8.npy +02933112-216096d5038c86a74c62bee40dcdc539.npy +04090263-b6b6d7cbe981d57276c3d558130f8b4.npy +03593526-76ffe67d67948975464e3094da7d844a.npy +04090263-705d24724cf1b7fe4fb30f5124687748.npy +04379243-69a96a236eb59dbb4594f83fd12bcf18.npy +02958343-61b40cc1d7e054cfaeea7738551d104.npy +03337140-2d418ca5fe05f2534c3aee8e9d3a6ffa.npy +04530566-4ecbd1471e916cd6c1ae34bcb12af75b.npy +04379243-58160ac529c37aef1f0f01a76c5ff040.npy +04379243-2ae89daf7433f4d14b3c42e318f3affc.npy +03261776-f5d210ff14ca9d29b6d9c2cee7f2f72b.npy +04530566-f2192f3c34a877f1d01eaac447e2e9b.npy +03001627-e60f50cdb48c2626d61bb0c6c287d278.npy +02828884-1ffcb829779ad5942056b4bd5d870b47.npy +02828884-dd4d12077d16512d8ab9e8dd82b356fd.npy +02992529-a6b2c1427dec317525bf2427892579c7.npy +03001627-c00d5c9b043b600019fb4103277a6b93.npy +03636649-3fef4c8dca9dd0e0dd4763fce8a9da20.npy +03636649-48cde19fa1d6af1653b336293441aa49.npy +04090263-12b346d7a60328ba9be47ac7c7e37815.npy +04468005-17407a1c24d6a2a58d95cdb16ecced85.npy +02691156-752a0bb6676c05bbe55e3ad998a1ecb4.npy +03046257-978541d6924dd42d7b0f449c7fb27872.npy +02942699-8b4f63046ee3bf99373b92b376321e13.npy +02691156-99656ff9d5a8a0fcbc0909d98a1ff2b4.npy +03636649-72ba0dc1fd49c2b5eef5d83b671bb264.npy +02933112-4d3df5ede83cd26e661673811de66400.npy +03636649-db447b84e1a8d8d6ba5342d638d0c267.npy +03211117-7fac92e1ac6e11945f6762b47fc0ecae.npy +03797390-187859d3c3a2fd23f54e1b6f41fdd78a.npy +03928116-8d84337557ed610533cada922154549a.npy +02992529-6b9cd9c72e69fb81d8630b8390e34e0d.npy +03991062-6e7a46fa4a22f5cbf2b931201029bc76.npy +04379243-da0def87fd8cd658da094b3bbad5f5e4.npy +04256520-c69ce34e38f6218b2f809039658ca52.npy +03642806-7312c9dc3c2802e926db2cd5ecb2df2b.npy +03991062-630aea241cb0ec8f24cedf205b903c2a.npy +04379243-f9c98f76522d375d20bac10b01e55c85.npy +04379243-2d52675c865f669047bc3701b998a7d5.npy +04379243-5b100f548ae5b162f51fa0238791f5dc.npy +02828884-43e72408630a790181faebbdea6bd9be.npy +02828884-8b9d37a08dc542f86f4e61e20a3631d1.npy +02691156-641af2da275049936cc53f9d72e7fec3.npy +03001627-6272c21e439e0205c8687ff9b0b4e4ac.npy +03636649-be61621254d82a6ebb40b038e5e0b7f0.npy +03636649-9a9aa982c0667012ce11183544874734.npy +04090263-61403e9bbd37636385076c97ccb96169.npy +03046257-47aacfbeb77a977b6463df620b7b4cbc.npy +02691156-723921d0060203a344d33ea02fa0f619.npy +03001627-b67232c18d00fca7593ebeeedbff73b.npy +04090263-727b9b62c52fd7d6bf36cf6ce284411c.npy +03001627-8d3817ad88a809524b9112ce9ce98204.npy +03001627-a004ad56474501f67eaeab1f0c9120b7.npy +04379243-f27a1f3db59556cba0ab1d82ef09f78f.npy +04256520-d906d689ec1edccffebad4f49b26ec52.npy +04468005-e55bf524949fe29052470de2774d6099.npy +03636649-e37796d40348fa5fd8013bb984303089.npy +02691156-b94b4edc5e4701093ba0eea71939b1f2.npy +04468005-d7ac71c003622f4d9954eae9164faecb.npy +03797390-9c930a8a3411f069e7f67f334aa9295c.npy +04379243-ab1d67b6f09b35424ea2d70ab68cd1d2.npy +04379243-a3e030b5fd13158d7a2166c62eb7eb3.npy +03636649-9534d5751fd1ed574cc30865d6337b9c.npy +02691156-d16405b7a4300014ef5bed0139d3780c.npy +02691156-3badd7765618bd66a532a2f6f060af39.npy +04256520-b3d686456bd951d42ea98d69e91ba870.npy +03636649-65f11c0c8a86a8ea9813dd6c977cb17e.npy +04379243-cda92b4188af3a17c03a563a9407c5ea.npy +03001627-b93d170448493717c2b64c0adffbe398.npy +04256520-c05c058169a31a19b149830119040db5.npy +04090263-dd9586cd8cc762dbe43969badba53c7b.npy +03691459-799a7910c5084f1a799c6c3b2fff049.npy +02747177-942887c8d668501681faebbdea6bd9be.npy +02808440-2b535c15e1baec23ee2de8169f41c6e9.npy +02828884-fc7785be580a926a3409d1e6da3f019.npy +03211117-d3193b07bd166c0611e348ae03a757ef.npy +03642806-6da67be7e83afd3be3b927dfeefbac4e.npy +03790512-2ff252507b18ce60cd4bec905df51d1d.npy +03691459-b7acad8df6aef539a35fdda2e8d5933f.npy +04379243-bc23348d2f16d4237155483601ac0c56.npy +02958343-d83fd4f79f16a1313c9d2d3d4dc0edb0.npy +04401088-c864337d009c823290a9c3b0b32f8569.npy +04256520-9805e011defa15f37fbc060fd555478.npy +02691156-8eda6d2dcf9302d2d041917556492646.npy +03001627-3f5f14f6156261473b194e6e71487571.npy +02691156-5cfdb557f5fedd51adb50624aa91e8c9.npy +02747177-e3f87ceed5c45b39eb0ce5843fe6b264.npy +02747177-3b4bc00820afb447ad5067eac75a07f7.npy +04074963-3039044a24972ae37bdb91f66fe1a363.npy +04379243-4822e02112a450f593ebeeedbff73b.npy +02876657-9cec36de93bb49d3f07ead639233915e.npy +02828884-7769891a8af54054bfde7937440ef438.npy +03467517-3824a2336972d144a24eeca91f583600.npy +02958343-a5c969e3401228d2c92e66330b5ca173.npy +04090263-dcc4bb465d403801e1f2a1daf140ac9f.npy +04256520-55bae67315330e0f131878391e12e811.npy +04225987-ccc91585d5d614a3ad3e04762b7c31c.npy +03691459-622a9789d1eaf6e3cf56355417e88d12.npy +03001627-74615c2f7098738ca9764f2d2db668a.npy +04090263-8cd9afeb654c89b8fb5c1b0f759e2bc1.npy +04401088-db058088ec098d9bdfbc59eb47b047b3.npy +03636649-5270f973e56a05f12cd2160e449d45ae.npy +04379243-1cc337d9f3f6d8f47f45370489ca3156.npy +03691459-993d30ee5f04eb7bc41d2caaa616b8ad.npy +04379243-953ffe955229423213d2510999d0f1d2.npy +04379243-2c9756c06606c05bfa85bd040b2a2468.npy +03001627-473a9ac8376e5a15ae0b06ef692d1ec7.npy +03636649-a5a31ea56d8fbe0a72ad95ccf7316565.npy +04379243-48a944dc8751ca7531370540942e6ad.npy +04256520-fbcaa3c4d17b8b7c9b0790357cd0493.npy +03001627-55e1cde05a99f6c7d1d34366ca81fb3b.npy +02691156-8f40518bd30467151e5ae32cb9e3711f.npy +03001627-e0a473eb557c424320768660cf080d12.npy +02808440-d0c3bf270f9e04eb362845c6edb57fc.npy +04379243-1d9b72020d680630bbd4cddd04c77b.npy +02933112-9304e9ad9853d1caf760390d600fe7fa.npy +02924116-4253a9aac998848f664839bbd828e448.npy +04379243-4e46ec6d0826e4525228d12f1858463.npy +03001627-cb87604cf146b4eee897810eac8c21be.npy +04256520-cd1086902b5eb749f51f77a6d7299806.npy +04379243-43b3d26626b7ac54b35c92fbf601983.npy +03325088-981c79da1f3dfc3bc36fb70296e45483.npy +03691459-1a1ff0c5f28f10d642e265df80f79372.npy +02828884-e27ffabfdcd52e7dfa11d00fb25084c8.npy +04379243-9d873d1e7403e2c825971c9167623d21.npy +03211117-cc3adfb500c1d443b441e189e5a85c02.npy +03636649-94af43cc530f8c4649244b68aadec703.npy +04379243-acf4b272c86a011fa0ab1d82ef09f78f.npy +02933112-44d195279a116e347eee615e75bc3b77.npy +03001627-7fe64a3a70f8f6b28cd4e3ad2fcaf039.npy +04401088-c6f62eb51d1750497dbf89b54afcec5d.npy +04090263-874cc0d822e74148b88eabc621107e4c.npy +03467517-8d35e1d412f3715469da8e7f9a803d12.npy +02691156-6a868213168421c6f0985368fed75674.npy +03325088-aeb9d0a78ee06f6e2b3e9b6eb52d35df.npy +04379243-c5fc6c1e0d446d37acce1c6e70b58979.npy +02871439-af326bfd00ac8edda9d79518470babf0.npy +03636649-3766b272cd3836cf28699debac30ad6.npy +03624134-5d3549571f699f8dcbac9c2913bca39.npy +02933112-5f7b88ac9256976cc59350d819542ec7.npy +02871439-a98efeb82eabc760defc4117d86acef0.npy +02924116-56767c32a4f01e2c83b8b9c448a35518.npy +02933112-3649b02bd61a337321730ef9c9d28bd1.npy +04379243-cafca523ae3653502454f22008de5a3e.npy +02958343-dbe713c83afe559316abce8cb03e7794.npy +03467517-9142906d08f5608e8f5758ba0b9a4200.npy +03624134-ca5e9779bed60ea8c6c26a6a38f12bff.npy +04379243-86a955d448e4dc0c3ba9e53316119012.npy +03001627-f859a1ed07d088be920de219c00d1c3b.npy +02958343-596bbe4864580ded5833b7f8c91b5b48.npy +03624134-7238d0009faeacb5fd770de1635caa0.npy +03991062-c313946af426bcc7368b14e48c164a6e.npy +04256520-611f5a21a6f9ad3d7635d2483a62c61e.npy +03001627-1ab4c6ef68073113cf004563556ddb36.npy +03001627-c747e6ceb1a6faaa3074f48b99186254.npy +02924116-9db400a7d654016f52470de2774d6099.npy +02958343-af814b4b43fd826a3a0daf3e5400b95c.npy +02958343-f9e91a22776f3d8be9415adaaf77fdbf.npy +03337140-97149625367ac1444c3aee8e9d3a6ffa.npy +04468005-ac3d0b9db6e5c9c29954eae9164faecb.npy +03001627-22ae801d650a1e3d492d9da2668ec34c.npy +03001627-b56829d48d66fd0bf368f5bd754a08c3.npy +03001627-f23ecf3348299cf743e99e0cae970928.npy +03001627-efafddc93951b8fdc975d461b3f97726.npy +04256520-a9bfb70669bd7f37757a6361b10ec08.npy +04379243-e97156fd53e88e27be2d01aee0780473.npy +02808440-782e16fb84e867632a3ca6620448176.npy +03467517-efa4ceed4d7b25fbce1c7d24654787eb.npy +02958343-47638c9573ee7ba3d8a1849b0098a5e7.npy +02828884-838c48b41d513a2dd0992406ba4944f5.npy +02691156-545cadae487b55bbc46ba5100bcdc520.npy +03001627-7a2d21eddb89c8242058afcc28d23393.npy +04379243-e679dae35e8ccd9acd2220e987e57553.npy +02958343-7c44aa72f314ee8e634b31c394824611.npy +04090263-7edd1e50920e559e0befc0b4697d414.npy +04090263-72e4958882980380e1f2a1daf140ac9f.npy +04379243-9ad91992184e2b3e283b00891f680579.npy +02691156-6bc51a88f3c58469b00421d9df4746fa.npy +04379243-f8c0c4f713f0c136e9048ab4301b0c63.npy +03636649-23eaba9bdd51a5b0dfe9cab879fd37e8.npy +02933112-50f0ea68b77810121fbac718728a36d.npy +03085013-44ed926c35d42e38b20f6e48f6a30cbf.npy +03001627-be1ac2a0b4c75bb9940806ade53ef2f.npy +03001627-bb296502226ae23475becd8a4c3f1866.npy +02828884-a28d0dbb90413692d42b9650f19dd425.npy +03691459-4cd3259a06b904a36a6d1e86c6266511.npy +03761084-f26c8ade290b82c7843e991acd39f432.npy +02958343-17c32e15723ed6e0cd0bf4a0e76b8df5.npy +03691459-16e3c79113685e52203eacdbee49fa8e.npy +03001627-37ba94e29b7d21ee41fbc1e2da054acb.npy +02958343-4dbf4e0654d0c234e811106a82796d20.npy +02958343-11b09de6631b3b3ad997cda1a938a10d.npy +02691156-3f69370401d4dc9a275386e1d3ac388e.npy +02958343-1c6591c3fc686bf24132f89b3e69f40f.npy +03691459-4d698b1e935897905e97b1b6281b6b04.npy +02808440-1f026dc37ca7c7b26b448b8aaebb705c.npy +02691156-bff6cee515cdefa8a5effc03faf54012.npy +02958343-e3d7957c7a9b95382e877e82c90c24d.npy +02691156-50e793fe39e527b245f31985fc702c6e.npy +03691459-f14ddd757b128a96b2b304a0ae97620c.npy +04379243-7c59421abd239c358b069fa6e7378ac2.npy +03691459-c75c5ae81c1fd498c066b9622c005c53.npy +04379243-1a153612bcdab3e23cc149415a408229.npy +03691459-88eefee684586cd3fd56d9106430c3fe.npy +04379243-306f10749606ec9355f46d55537192b6.npy +03001627-397a5fd0a95a17e4dd2be59fe725394a.npy +04256520-1af8bfa4eda36bd697c597ba4db02ec7.npy +02958343-8f8bd59f17f122a163739f01ec1d22b0.npy +03325088-11cae04ea5d825693321831d2245cf06.npy +03691459-ab478f6a1f38a5d18a0181490cb73cbc.npy +03593526-c7e207bcb48a699fd0a0c43e4971be14.npy +02958343-2076be423fa5bb9f9e908ecb03b3d6fb.npy +04090263-2f4d62df133d15ca5874d5106201fb13.npy +04379243-f39401db6cc45a3ae3e15116d1de599a.npy +04256520-e708bde6a2ffa4cd1ed1d681aa8388f6.npy +04379243-b8261a2db6b6525f490ad276cd2af3a4.npy +03001627-2bf69f0fa5be4c3f6ecea8cff53afe1a.npy +03211117-800ca9956f66a22a23d94393165a64e3.npy +02691156-7488f87b1e08bbabd00d52e62bf14ee9.npy +03636649-d460bf2dd59883f44e1a714ee619465a.npy +03636649-2a762ba822eef5fe5c7e2f94d3f5eaa7.npy +04379243-f220f4b4c7b79d7ab54f2a7bd7b06a98.npy +04379243-1b739cf713702b2146f41dc2aaef556b.npy +04379243-3cad8d726389e5dca5e91f4d594e20e6.npy +04256520-36cf45005b263014917b96045c9b6dea.npy +04379243-1652817da2b9193bc3bd24f986301745.npy +02958343-9dee0ea5da388102e6d91d458fe44a15.npy +03001627-ecd46956b35523fd492d9da2668ec34c.npy +02992529-98eb601db13d2a99611f4167fca99b42.npy +04530566-3176313945e3739e10508e1f7e97aa01.npy +02828884-be7408f8b03d491145004a22a9d35958.npy +04379243-e157aa6411d02cb16f1e631ee7d027b9.npy +03001627-3d5c94f748861bcf6038f78d0f44e587.npy +04530566-c00cee4431f3c2db89d39b85991ba25a.npy +02818832-19de1e83fbe292f55a2aa419fded589d.npy +02992529-f2db6829e0c0298140d50eb4da376b1d.npy +02933112-69932a9f53ce20bbe4e346ee2650d150.npy +04530566-f531f4b2ca36d626e18dd06c1afbc426.npy +04090263-27fc4679ae16edc887ecee1779f8c08.npy +04401088-df23ff3151aa1f0a3cb2f20e21cb06ff.npy +03593526-763474ce228585bf687ad2cd85bde80a.npy +03636649-e926dd7cf6831f9afcb8d8c6d4df8143.npy +03207941-a377f5af14ac6710a168e247bb97e471.npy +02691156-c3bd5ab4d3ac6a5a5c351e299b24e355.npy +03001627-caa330f85a6d6db7a17ae19fa77775ff.npy +04530566-5fd55e301007884c742bc8027e4951ae.npy +03001627-b6985891e45b998e7181375a1be1d1c9.npy +03001627-6d7a7f4660e49fd130cbbda41991e4d0.npy +03001627-c6e46dc0afd8b9fdd722b8781cb9911.npy +03001627-404bfa75a054791920e791c9b6d759b2.npy +02691156-bd698089021a4a58e23abb9b807b4cb1.npy +03636649-9627da26edc003e7d49b2e04785f8492.npy +02933112-576170f154143ff2de421c2ab5cfb52.npy +04379243-10ed64b4c7eb6d9311ee7ca4f000feba.npy +02933112-10b54fe832a00c3ec59350d819542ec7.npy +03636649-947c6753d77d8082290e2f84c414e6be.npy +03325088-1501500852a5295db229726a165222c0.npy +04090263-b9b9eb89bea6ce2fbeef84a1ff2df7f.npy +03636649-fe200902555dd8c89f2349486c570dd4.npy +03467517-4064b0ee5430ec6baef45fef9b6cadb4.npy +03467517-ea201ccc779eb93843a90475d48649b3.npy +04379243-ab5dbe7338e842e36f7826c82fdc3f35.npy +03691459-8e25a8e0de9ff545bf1411bc6f3b308.npy +03691459-2e0fc1bc430c5c1bdfdc04b8b8434e84.npy +02958343-c16bafa65123cddfce29c905218d4398.npy +04379243-ba44082e55ea58f431475fd256bf1b7a.npy +03948459-c16e5ae5e9f4af295c288fb30cd9ee47.npy +02933112-b8880afd2b1038c8ea7cdfccad65e7e9.npy +04379243-ea60054e04139d95b90b5e5b769a3ec0.npy +04379243-67b9c88c4f75cd1e886a7d82f0a2cb9.npy +04530566-722b68d90bc3955d2e5eb68672f87e15.npy +02828884-9bb6f0077f91c613f155d75bbf62b80.npy +04090263-e53f8481983564828ef0c1f0d9cc8b8.npy +02808440-81aab72890c8cc3a64c8c924c4738650.npy +04379243-9792d6d50c07e27627992812a922e94a.npy +02828884-27267209ed320cd271cf429728b349ba.npy +02691156-a85dbb5bb889881419bf80b167cee3a3.npy +03797390-48e260a614c0fd4434a8988fdcee4fde.npy +02958343-385d82108ff7ee1be2720e351c87b6fe.npy +04330267-3aa97b75ff79a0594d1cd794fadc7ced.npy +03790512-766002ed9dc8556d390c1a9993716e73.npy +04379243-1e57738f60665b1a908caac6d5f8ca97.npy +04379243-9dd80e356880c9deaf268f6180933aa3.npy +03211117-62ac1e4559205e24f9702e673573a443.npy +02924116-393575fc4533b0e8fd116a83fba6ae75.npy +04379243-575beb82bd20f61fad5067eac75a07f7.npy +02958343-beedf39c8f5709bea9fe1734a6086750.npy +03001627-c2076591d588586719fb4103277a6b93.npy +02691156-be5d2c935a36894c92cea77f96988ae6.npy +04090263-4a0f1b426cea6f13fb41747dcf822261.npy +04256520-83410e32b49b4f9957aa81cfc66d7b2f.npy +02691156-130d3f27fb083eebc0909d98a1ff2b4.npy +02691156-d4aec2680be68c813a116bc3efac4e3b.npy +04379243-b1117a83ebf5a4c9c337a931444a5063.npy +03636649-7a892d6b3951124cf004563556ddb36.npy +02691156-46dcd7b89d67cc41a1398b9e7da33687.npy +02933112-ac8cdb6289d3d446c59350d819542ec7.npy +04090263-be70ada7701ea798a8d379aabc8e63ca.npy +04379243-3bf8b96b10519a984afda4ff857119a2.npy +04401088-cd74be6a1d8a6cc721844676433a0aca.npy +03001627-eafec1b145972dcd815b2b467e8e2eac.npy +02876657-47ede0c10e36fe309029fc9335eeb05c.npy +02828884-f8aa82e7e4c58ce29d31c5ce17cce95d.npy +03001627-d221f07c0921e4d2b9576c1fc1b047de.npy +04401088-58ece48e59781da1fd0a2086d631b6a0.npy +04090263-e8bce069e560a97f310bbd45bf9024da.npy +04090263-f5472d552004345b51cfdb4c9f126c12.npy +02958343-20a967d68b6d291512da0dbf3c68e847.npy +04401088-922380f231a342cf388f6c7a9d3e1552.npy +04379243-718679874bec63183c9bc0d98cd0376e.npy +04379243-a91ee72daa437343d1f4e3beb8257c5a.npy +04379243-1248597ca22fa1e71332a40d0134407.npy +04379243-3ca6199c8adacd4d30bbd4cddd04c77b.npy +03593526-37b06eeb82c1a486835e59296200e86.npy +02958343-99dd952f49606ba01669695e4df59de.npy +04256520-5f50ec09722ee31fbcd054bcf140e51.npy +03001627-e39308cd84103a47f4b6538438a0b930.npy +04379243-b598794290077d8cfbbc7c456d85ce59.npy +02747177-7d47e79aaef3b1482056b4bd5d870b47.npy +02808440-8e1de9c946615fbc6f893b5bc716a3fa.npy +03636649-6e43d4b4829b66d06fa63795f94c4d8c.npy +03593526-281530bc7fbb122f30612f5c0ef21eb8.npy +02871439-e9c50ead4efa013bd42b9650f19dd425.npy +02958343-637a26dc6b1a3f47e7540f431cab4686.npy +02958343-eaeabed4e984364868ebd0cfefbb61e9.npy +03467517-78a978e7e34a751c69b43b9b42712589.npy +03001627-2ac24756c1adbd62c1a25f36f85c3fd6.npy +03513137-956fc471237a3e55613792009f64ab4d.npy +02933112-61d42e7c7c16b2d53334fb6668ccd834.npy +03636649-7bc1b202ebf000625949e084b65603cf.npy +03691459-ddfa1daa59d5bf2676c2a9de5c96f76.npy +03001627-a007a3cd5b8ca7fb19fb4103277a6b93.npy +02876657-bf7ecd80f7c419feca972daa503b3095.npy +03624134-dac1fc01fb44b2b9cb7078d644842b01.npy +02828884-dd9d0cfda54dfc30eda82e072f128485.npy +04379243-4f2eab1aa639ecdc6b17bdafaf39f370.npy +03001627-8eceb15a3c79b1b8719d8721fec72f0c.npy +03636649-26f0f37f0f2623c4a3fa46ae73c48b4.npy +04256520-ab350e81ff71034434895070e6a9b93.npy +04401088-98eb601db13d2a99611f4167fca99b42.npy +03759954-da951dbb3c6ffb3a6c22bf2209f4782.npy +03691459-fd4b2e3a6caf4706a817854e3b5b5439.npy +03001627-7ab99231f6a6cc282ca32e2623a35d99.npy +03691459-32cf86c686fe9b1974828baacbf242e3.npy +04256520-aa21824de23b516995c7d6b48c371712.npy +03337140-2e2704de75c84d3d6f1e07a56c129dfc.npy +04090263-b095a80476a8e002bb9224760a70fece.npy +04530566-9ea44b515bef76f3faeafe37c2ce4f6.npy +02818832-47f5f16fe3f346aa67a76d084b67db2.npy +02958343-6aef84dbaa69dfd8becf71e2e014ff6f.npy +04256520-4353b992d238cff0cda85f6a3e19b0a1.npy +03624134-d04de9ffdb1f36c1deef0cfd16bc41f6.npy +02958343-a52f704da0d3c947ca92a4cdad802b45.npy +04256520-874bfe0bc817ac827571d17c374fac42.npy +03001627-3a40eb7b9122bbfe2f066782346a992.npy +03001627-a86c5179fc3f7ae114038d588fd1342f.npy +04554684-36594769b62b24d63b1e413ac12356ae.npy +02958343-93f298a78be6883916abce8cb03e7794.npy +02691156-a224182f76e4a44fe1a65cde8802138c.npy +03001627-cc30a723aeba69a139e0f39f5249b0ba.npy +02958343-4dca3760ae9748b6b0aa56928723eca5.npy +03001627-d581539aa6d5c2ec7709fbdff3d15bf9.npy +03636649-6f422c48a60cda58472cd9d4266add0f.npy +04379243-a275f4b42b430eaf320f10afdfbaa18.npy +04379243-e699d5904e00a6ab748c0b14b00bc019.npy +02691156-85cf5445f44a49f5cf35fd096a07bc43.npy +04225987-2085eac3fc071dd47292d1029e5a9853.npy +03636649-3101d2b22e21297ccff8db9efabb6c62.npy +03001627-7e8b24aab1f2681e595557081060d0b.npy +04090263-36d3338314e3db7cf6099a039722df68.npy +04379243-4c20048e9066d768b7490c34ba5d2779.npy +02933112-2af2279b9331aa9916c6f599d5622764.npy +04090263-c7b8d834209413393110fbb3943dde1e.npy +03046257-425e82131e7a8db3bde2b05b8fa4f117.npy +04379243-1797eec0a23dcb1dff29be004a6f7c0a.npy +03001627-c15a1da769c1ffc5be1649add3e36e21.npy +02876657-776502db6e2e680e5e4f0d37557f3953.npy +03636649-270ec239221938991735ea0e092a805a.npy +03001627-3a16d7535d87d441d772e458a8f80cd2.npy +03790512-8032295bd3851d75468bac13e007a6e9.npy +04090263-e325afe389a39f49e641d7676ac20451.npy +03636649-f111f0e0c6c3434f30f6e0ede20c4525.npy +03948459-5e7afb318ff701583018d2d3c13a7462.npy +02958343-2999f005f1eba724bda733a39f84326d.npy +04379243-7cd4844def36a9f5bc7589eefbdbc3c5.npy +02828884-54f33a7cb3621d5ced98cca8f0ccd5f7.npy +03001627-ece1a921c1bfd44947f5e245ee376525.npy +03001627-594d1220c2c6df41b04bab4867aadedc.npy +02946921-b1980d6743b7a98c12a47018402419a2.npy +03001627-1ff1912cc74a76c3b2152dcc3ff6a477.npy +03636649-802c287eacfbcba9564b8e0b814c602e.npy +04256520-c136abd9c245ed8819c798cfc4624378.npy +02958343-f9eaaf5abb238c22851f021b9ed69c58.npy +03636649-57b95c1122beac7c3fef86d7b5969363.npy +03046257-c65500930362e3b925bae8352085782c.npy +04090263-8894650164a2222b1a857c47fd0ecdc3.npy +03691459-53d6d8e3e4731b3bc0b5947ffe18a468.npy +04256520-d4704c12862c808b593ebeeedbff73b.npy +03001627-b1d9c55bd4e8ded1c76575d5e6d323f2.npy +03513137-a1357ff99c759de448d4a59eba9f268c.npy +04379243-fb097cffc3cdd8512027cee422df2aa3.npy +04225987-d7045c95ab319b711082f2ea630bf69e.npy +04090263-179764bc36fa4246fbf44f447f38c175.npy +03636649-a0e1732661667683664b3b9b23ddfcbc.npy +03636649-c7aadb7ac29ac778aaae3d020f5ddf8.npy +02992529-44ce10ddb982c8ff72152988eac576ab.npy +02691156-2f379576475cfba24c3a35cee92bb95b.npy +02924116-7cbd178243b93689be4604cdb22fb3e0.npy +02933112-975426b49f98bc1b4c62bee40dcdc539.npy +02946921-4a6ba57aa2b47dfade1831cbcbd278d4.npy +03467517-3cc9bf3137c4776957e2b466f0c765d7.npy +02691156-8b59ed9a391c86cdb4910ab5b756f3ae.npy +04379243-aaf3aeda0f848344b87028a4b477349f.npy +03467517-ebf7994fd17b6331c64d0082475b0472.npy +02691156-eb110db9bdd0463e5b7003ff580606fa.npy +03001627-909244db9219fb7c5bb4f4519002140.npy +02958343-30045ee0751d6ee88b3ab49d2e0e41ab.npy +04379243-2fc468b98c0cd227c8830fa1ef6e3e71.npy +02992529-8270c952b147d263b9746cb9e2b9d08.npy +02828884-873ce9c208428fd5ed98cca8f0ccd5f7.npy +02958343-b098f1db2f190a71d61b6a34f3fd808c.npy +03636649-1e9b2d5d65a8b7c29fe8663d47f73813.npy +04330267-f73ae0a40649c7b950c862b58109065.npy +03761084-c3bb5f3c842a6c2d178e7d331e641179.npy +03691459-3aa8876d86cf481d3fd2d4d929afab9.npy +04256520-6ed6b121918d8f3531ae8c8ff1eb3d45.npy +04379243-b905d2f688f56afff4b6538438a0b930.npy +04530566-8687ac78ffaa38584de203ef6842ee61.npy +02828884-59b1ca3d780ed0381560641bf48464ff.npy +02933112-b4da5084ae0237fca4ab444e58fa9bdc.npy +03991062-1c12e50abd02d26d25ebd1cd0b422e32.npy +02958343-840f98dcf50b48f9a7fd25564c2e888e.npy +02808440-c075ed9936aefd1151f7fdc9a9600159.npy +02691156-452c18f8997c53741adbb4c4e06ad649.npy +03636649-6cb3a2872d2c2646fcb8d8c6d4df8143.npy +02828884-92f20bc7a09dfc1d19420b7669e7265.npy +03001627-379f2db4f028cd7925e847faed0661b.npy +02992529-c70daedaade33fd0fb24e6a63c26ad2d.npy +03001627-665511c6bccac090492d9da2668ec34c.npy +04379243-cb214fef007a2a46bed1bd9593e318c.npy +03001627-6bd633162adccd29c3bd24f986301745.npy +03001627-ea77c800bba6566aaf7c7ad2549a1b15.npy +02992529-22fc328d136756361e5d846d206adf3d.npy +02958343-16ba461c0d7c8435dd141480e2c154d3.npy +03691459-199ce49a7db017107a964f742d0e5820.npy +02691156-2b20176a59621b35497add46ccd9d60.npy +04379243-176e3b32d749ac94d79f2fc0b8d8ffad.npy +03211117-95d82c761a54684db3690a118770a184.npy +04530566-f678356e3e61872a28730ed49126392b.npy +04379243-5668d49d776c954c5963245f0923337f.npy +02958343-79b99595059c53108540dd23f35aa602.npy +03001627-1f571e244384bca736b0f2a1430e993a.npy +04256520-fe63ff3ee440cbe2cbc66df5fc1969c2.npy +02992529-1d390d2560fc259336eb9fe355d50fdf.npy +02958343-4eb5ec5502561124875fb780d36841f.npy +02933112-9b2759851023fad7dedad3eee47fd556.npy +04530566-67e41dd24b6902da49f471d054f6b528.npy +04379243-ab529bd91a158a53851911ab8e53bed.npy +02828884-84aa911799cd87b4ad5067eac75a07f7.npy +04256520-5af36cc3a98642019fb4103277a6b93.npy +04379243-889f48aa85accd2ee73947fdf756a329.npy +04379243-51f0461221d5a86370d2e38b8c410c62.npy +03337140-b6e067ad1812af03492d9da2668ec34c.npy +02843684-bf698ee440b6de7ca7667c99d0d11d68.npy +04256520-a89e0f5b5a8157afb0aea9d5db2857a9.npy +02828884-8b682ef98315c3be21349c674433e602.npy +03467517-ecb17b6917ba033bc39f53b4a75f9475.npy +03991062-7a70cb897ca6c3e1436455e65b78c0e3.npy +04530566-5e1c4ca986d216866554a94f24190b8a.npy +02828884-2a9ad7f4e7ab564a5be2d177e843be47.npy +02876657-8cd9b10f611ac28e866a1445c8fba9da.npy +02691156-105f7f51e4140ee4b6b87e72ead132ed.npy +02924116-920a7d45cf2455f0616d27151166e25f.npy +03593526-9195960e68825d41156d1d06c447a736.npy +02992529-9cedde0b189fc03824ec4b72ec33390e.npy +04379243-cd91028b64fbfac2733464f54a85f798.npy +04379243-39a71631941673b1c287a33ab134ac42.npy +04379243-47cb4740e2e0cb8d11bf24e88933ed8f.npy +03001627-fd726084724adeea492d9da2668ec34c.npy +03691459-3a4950ac89429ff5b396c6d231dec74d.npy +02691156-1b626fd06226b600adcbeb54f3d014e9.npy +03325088-427cdfd5eba597ba14b35a7d7cea7130.npy +04090263-a5b6e717194781776559a92f80e3672e.npy +03642806-decbfc069b08016d6ac2773342338507.npy +04330267-3139001aa8148559bc3e724ff85e2d1b.npy +02691156-646b93aecb7b7011a9b2becd26dc2fc1.npy +03513137-a8e04b323931f2b9f2c6c460ab16f409.npy +02808440-b0cf9853f86d85c062c5411db2c28360.npy +03001627-9ee1b4fd18b040bb5445e46058840642.npy +02691156-53c7a6b56afb63807222da102ac36d2b.npy +03001627-965f9b75de94d03aff74317afae0a323.npy +02691156-8d5ecf095e56cf8cca8607f540cc62ba.npy +03636649-f392dbd90200bd7dc77f357adbe5c980.npy +04256520-125ace480d9f2fd5369e32fb818f337.npy +02924116-1821df0ce1bf2cea52470de2774d6099.npy +04379243-f116ba8983e6728eb1f243bab39fb29.npy +04090263-a7cf230b5a2967125f5038a2cf78b1e4.npy +02933112-743366dfb72897be1ba9fd11dc8bf457.npy +02933112-7d95374a9110157c7d8c689e1315827b.npy +02871439-1170df5b9512c1d92f6bce2b7e6c12b7.npy +03046257-58945eca103891f4887f087750df94d2.npy +03624134-d23341ca5eb721abefafd451049df010.npy +02691156-5bdef9dfed852e26195688f8ce8acdb7.npy +04379243-a9d890e4b6b426dd358ffaf8d4d252a.npy +02691156-e805624480f632ebcc14f1e6f4f4f49b.npy +02992529-b140bdd32b0287a64a21fc95f845c2fa.npy +02992529-27b4f430b881e16ad6339cac3214b6bf.npy +02691156-99e1961a72bb8ac46177b6d1ecbf989.npy +03001627-7720c68121497e555a28000e191ea2c9.npy +02992529-36760a27d679f058c4a0b6f738c144f4.npy +03624134-77c55aef23f91604a4a0a1e78d057db4.npy +04379243-d22e15286d0d99ec52d2de7b04447df3.npy +03624134-c116fc1447fa496ac1cc4ae0ecf50bf4.npy +04379243-9d73e1a51a56683bb65b71636c46ae49.npy +04256520-5a8adf52078b5008490ad276cd2af3a4.npy +02691156-bd298d2907400418df8fc3a07f996293.npy +03761084-6dad0112ef18439cb7add4de9f6e92e1.npy +04468005-f646c4c40c7f16ae4afcfe0b72eeffb5.npy +02958343-7fb5dcec8e6745554ddfff13f461e46e.npy +04256520-7461a53eae4126a79fcf47c4eee9d700.npy +03001627-5b51df75df88c639f51f77a6d7299806.npy +04379243-90343e416528b576f41d9ea5f63b1b05.npy +04530566-498773c5047c01b35fa1a6e8897313f4.npy +02958343-f10e32c6daaf237f13ded1857c15b5b6.npy +03001627-d868b5e696c362b9ae23680cee12f145.npy +02876657-81b2ce7d719326c8fd54367fe37b16.npy +03001627-bfe54fe90c7d99637fffc92abe94e907.npy +02876657-1d4093ad2dfad9df24be2e4f911ee4af.npy +04379243-33ef80eb8ebf4207fe7e23d061690240.npy +03046257-772008d5e703c4564b3c42e318f3affc.npy +02808440-7b440b188067638a44221bef0fa3c36b.npy +04468005-4682b77b2f9de0b942a772abcd2e8eed.npy +04379243-38ec61e847b8ec152864bfffd12f80b5.npy +04379243-63de5ec054b2d310dddd8ce1cda8c6d9.npy +03001627-a93853bdb9b378dd50c2ec40da48fd9d.npy +03593526-9b93492086316fdc61c8cbc38c089792.npy +02828884-7c49749ab1fa402a2056b4bd5d870b47.npy +04379243-e8288b5f567569f19fb4103277a6b93.npy +02691156-337658edebb67c301ce9f50324082ee4.npy +02691156-fbc7afa847c30a4c183bb3a05fac486f.npy +03624134-2743e37a65e198d51592d7a04a86fa53.npy +04379243-a4af8f822fa8d95456c08464b83f209e.npy +03001627-9841030f427150567dbe6b236c44c533.npy +02691156-77f5111d348bf051368d7e7849f8df62.npy +04530566-6cea89128bc0b5e83b9f2b6367bac7ce.npy +03636649-dac278ab197b5efefaa6996ece0d86f4.npy +03001627-268e15d6c73f3495f2c6f9bb81f9e3f6.npy +03001627-f23d3a85baabd7ae32d9baba75737e72.npy +02691156-f277fd1032f615ec2268dda5c324173f.npy +03001627-4afe3d1ef68515bdd6a6b5838ef6b356.npy +03636649-292ba732e002629e68c2f5eb1dd4dfaa.npy +03325088-6e1051dae8109411b362845c6edb57fc.npy +03001627-c6811f115d89758f46fb9c38320df24e.npy +02933112-819a1fd8c7bea7f3984cd513e00e13ae.npy +04379243-2f58b1ca8634a6b48b9b51ae4415d5aa.npy +02691156-ed57671fc0252e15b95e9a91dc6bad16.npy +02828884-459f90aa2162b1f1d46c340938e2ff1c.npy +03325088-b58fbcabbdf942515e861292bc046f7f.npy +03691459-cefb560ac4ca8b38a046bbac53886364.npy +04256520-189e64b308b4345d291d421ca3746ae2.npy +03790512-a3dfeae5bced3533b37378f3c85478b4.npy +03467517-c084022f2ddbf95493f0194265a9746c.npy +04004475-bad6374187a626722d24866ea0018e08.npy +02958343-34b507c24d9eab7f7eaeab1f0c9120b7.npy +02958343-c907a6cb1b178999c805dfe4ca9f2fdb.npy +04379243-5771840ae9ab5a334a3ececf7e04ebcc.npy +03624134-a73a2d9584b2cbc81395331ebe4786cd.npy +03001627-c6bdf057e1a5e900548360e92af6377.npy +04460130-70ea9d97de7de827221d54273fff89cf.npy +03001627-e54417646ad16604738a251b334366e.npy +03467517-c980271f356c3e9b605c81d3188a5b83.npy +03001627-c89a9a38e300cb502c10b2c975aee2eb.npy +03636649-3638d46a41870173713decb1a0563b12.npy +03001627-77f1880f07fc9805ce5f623508bcaa7e.npy +02933112-1e95c521f70972a2f5758e5628273c4e.npy +04256520-21addfde981f0e3445c6cb69e0968783.npy +04379243-52037005fbff92d08fa35606145b47dc.npy +02828884-5f21d3b66aa9b62d63b2acb037dfbcde.npy +03991062-5d2e2e8f2cd99c4b2d7a27ffaafaaddb.npy +04379243-e9871fd4c45b34148737eef0436997.npy +03691459-b44a0f8900edef4c957a55139a8e936e.npy +02691156-4561def0c651631122309ea5a3ab0f04.npy +02828884-2f34980683df2b47ad5067eac75a07f7.npy +04379243-c2c4846106b3597ce76bc197b3a3ffc0.npy +02933112-d4a7b45abac7a39c59350d819542ec7.npy +02691156-728d58b27cd53a16c93b40751084c22.npy +03759954-51f167b8049ae3362735b4cb5e9f26a4.npy +04256520-5a94cc0c277f391df9aec59741c69cf7.npy +04379243-6e16dc2baf237aeb5b87cb2d9a815c73.npy +02876657-d655a217ad7d8974ce60bdf271ddc452.npy +04530566-8fe646e75e9b99bbb58435942a1b4dac.npy +02691156-b2ae4acd6774f410833bb0b457d51a52.npy +03001627-a543f7e8114b19cd5397d07b571cbcb.npy +02958343-3ff887eaebf0bc7e9d2b99af43da16b3.npy +04256520-fbf0c4f6a483bc15ab7a3d3a1341aba.npy +04379243-5b719bcb32b8f291f16681d085170878.npy +04225987-c0280aaad5473e8398c63cb68f11df34.npy +04379243-c0401853da58a1b7beedb4c8fd29e2d1.npy +04379243-42fad469afab19939724db0ba5853d76.npy +04379243-760b1ea228d6c2f6e785b88cc9024b2a.npy +03001627-8c8efbe62a1547942b90a0fb76278f6f.npy +02691156-1df217928b39b927a8cba409c4409ba9.npy +04256520-40956fd98a04f34914038d588fd1342f.npy +04401088-64b6ddb847da082d761eb63018291094.npy +03467517-763905ae00b39589c445f4f26253ff9b.npy +02808440-dd60bfd98b869d96b5e423033398ff30.npy +03001627-a6420c4ed13cf628945a77b945b7b70f.npy +03325088-45fd2fd02e27bbb53321831d2245cf06.npy +04379243-6afec996cdd847031638d1ffbbaa0c53.npy +03593526-58c9d6575d62fbaf12bc68f36f3bdd45.npy +02808440-2f6da348147cad9c3321831d2245cf06.npy +02958343-60458c0d233ccf9daa69dfdc5532bb13.npy +02691156-9e75560008080a8529348d14ca881f7d.npy +03691459-5394ceacb131b5e79d7aee0f8e107545.npy +04379243-199881390e6ac3a89ccce4c6d5bb195f.npy +04379243-855c6cc99578afda6a5ef4b501708f3.npy +02828884-213e68b2abe5cf24bffe63c069324d61.npy +02801938-35bc440973661b91259e0fe12d9ec13d.npy +04460130-7635df079a9d126ff9c0f9cbb10e38a2.npy +03991062-12b90995b3054ea3a2c59a4d90e63212.npy +04256520-80d13b57aa31f79cef188758bf2e3a30.npy +04401088-8a62ea56cad1ea25430f38f25519fb5.npy +03001627-52e2b4be107a9d6495bea7c29e873d16.npy +04379243-e96bc1b7f02caf77eaf288f952624966.npy +03211117-a56c13025ec97af31ac04cb85e251041.npy +03325088-e08f50bf9a0b4776b362845c6edb57fc.npy +02958343-d79f66a4566ff981424db5a60837de26.npy +03001627-d987dc40c90907276bc601efa799c927.npy +03636649-409ff705d837b30ec3c3e425b20b4636.npy +04379243-3db6ff15d7ee52482db431502a680805.npy +02958343-d652c35de82c3f3141fd6622cb2ed89d.npy +02828884-9aafd6c69c331aef535e3a87e2212e35.npy +02828884-cdb6ceae0102632fffc6e457221b9271.npy +04401088-54bb14aad2406a124ce28f0f1b509eda.npy +03001627-f3249612d067e120384f43a3132c17b6.npy +04379243-9ffd670b6eb68ae8840e9c8d11bc8e80.npy +04379243-9b86da62c360aa0d824080f516909671.npy +04379243-2583fa4932ddfe741ec48bc3c478566d.npy +04379243-f4e0c7b0e402ac86e5a953fde71681c.npy +02747177-22fe449cf2cfd7981faebbdea6bd9be.npy +04256520-5e9a36c61649952f555740dfce3e4a45.npy +02691156-a7d29332d98b7b8340a4a448803b06f7.npy +04379243-c02d673e9b7658d52b70eac6546e93fd.npy +04090263-65b8974ca9c4d73e34c4a8f12da88608.npy +03001627-406561a447d3f7787f4096327f1fb3a7.npy +04379243-7a0b6685a30298fb8ae8d7de284e7d2.npy +04090263-add8dbf5ef758141e63959b7baa1103e.npy +02933112-71c2c44dd20ae153353a90f87b8ecab5.npy +02691156-27317e8e93190374780ee0648cf79a36.npy +03337140-aafd560ec2d1d4814c3aee8e9d3a6ffa.npy +04379243-ed8dd7ac0d865ac686f1a0f58f951001.npy +02876657-f49d6c4b75f695c44d34bdc365023cf4.npy +03991062-d7e77f60893f20c4a2c59a4d90e63212.npy +02933112-370608d5fd4f39745e7493df1bf8fac5.npy +03211117-31ef46873b20e53274e7ea1d002bf071.npy +04256520-cb311c253401e27165eff2c7075317a4.npy +02933112-5ec805e8599196746be771595eade0e3.npy +03642806-7b944e090c10969666aa414faa9189f1.npy +02828884-3a4ab482c4d344eb2fed5f7b90bc9e3c.npy +03211117-4812245f2f9fa2c953ed9ce120377769.npy +03211117-bafe343788f824bd372d432893cb48f8.npy +04256520-8fce754ab94cf3c0e07a1c4b84dfd325.npy +03261776-b5c4585baef4a036dae5edc5d34da94f.npy +02958343-7e7e5752ce2aebd46034a921cc85e098.npy +02691156-7b553eabcfe3709f3d2b6eee5a74cb08.npy +04090263-2a1f207a0273683c9f433921788191f3.npy +02808440-ab3e7307f7e3a435863bb5f5739560b1.npy +04379243-722bd78d5f625018d27b31bdeb5f5c79.npy +04379243-e8ac113e9db33ac8cfdf2d08e1ba2a48.npy +02880940-34875f8448f98813a2c59a4d90e63212.npy +04401088-db059495c20c0e2e514ce6dee24d82db.npy +04401088-1b41282fb44f9bb28f6823689e03ea4.npy +03001627-a14880ecec87a82bf9b9977a2406713a.npy +04090263-9104e081cb7d92f0fb41747dcf822261.npy +04379243-e702f89ce87a0b6579368d1198f406e7.npy +04090263-b3bc8adb8349c958de423072102e0bc5.npy +04379243-5b0ca203bc4021a2cf9ca735ff10053c.npy +02691156-afa83b431ffe73a454eefcdc602d4520.npy +04530566-11766a7b1f86adf36bfc202176cd1f2c.npy +04256520-2c1c9fb6e940c636b1467c71658cc329.npy +04401088-eb1fa4d2a399d4c38334e57fff4eb77b.npy +03001627-665fc6411855306530221b1717636e3c.npy +04379243-7eabef19cb02a9e6aa29e9f0529e8ef7.npy +02691156-d83300deab42c100eb9db4e832a6dd82.npy +04379243-ed289e72b00480521fac473c90dd4a.npy +04530566-cc97fdf906ef08afc5646791c1cc7f13.npy +02958343-55785c5e30e293e03146b856dc99bd62.npy +03001627-81276e5b6c8871634af957103f4767ac.npy +03001627-89d62702b266b20a58a2d0ecf7ace1c2.npy +04256520-2f426679ff0345326e467bd7dd946c3c.npy +02808440-c37f254715a78571ae8be095e1557726.npy +04468005-f04e5f2911de028219508c299c767a7b.npy +03691459-607096f600b6b75620363e2561dd589a.npy +03691459-5533322e8dfb7d69efb0fe88d2924d2d.npy +02992529-c5188dbebddbad3597cfb99c9c9efbb5.npy +02992529-39359aaddcc4b761b0a79e28606cb167.npy +03001627-bb878313da4b02e3dbbc9440457e303e.npy +04256520-277231dcb7261ae4a9fe1734a6086750.npy +04379243-1c8d1cb23d037f2a9e4965f0106e00d9.npy +03001627-b58909919d9feea6976cd10355a74f40.npy +02828884-ddaa540f004e7889d2b12aa6a0f050b3.npy +02828884-abddca275435a7b987b6d520ce557b3f.npy +03001627-75716acbe4ace649854cb2d2b60c3da8.npy +04530566-5da69ec4bee76b21f3e39f2e17005efc.npy +04530566-9c92fb3f3a4fbe8cac932f3ba44b77b.npy +03325088-289c4f1b23b09836b362845c6edb57fc.npy +02933112-2f0fd2a5e181b82a4267f85fb94fa2e7.npy +04379243-efc01209cfa158eadbbc9440457e303e.npy +03593526-5b8b46006f36e9a741711e9e73e5d4ca.npy +03691459-d23b86065834982bdc99793862c889e0.npy +04256520-d71b806ed0d2108dc149927e19d9b07.npy +04379243-f49c7d43808b1033f91663a74ccd2338.npy +04256520-98e474a6bbaef456febad4f49b26ec52.npy +03624134-c1a44efab8a2616c44a16a1c9776e2ce.npy +02808440-20192aa7850b2ba35821ec2db55477c7.npy +02933112-23aeb8fdc0d1ed4c4da5feafe6f1c8fc.npy +03593526-9cf099a555d04ea1417700afcf470f3.npy +04379243-f7d17f8d80fd2eaaa62ee5d388bdaf2f.npy +04379243-777365e9179ef98cea4f74d1efed63c3.npy +04379243-58a0638f8bf4f0fb79414e04132a8bef.npy +03948459-d83cb380b72c7724d6794b7eeefabea.npy +02933112-87c85956b41a7fc541d86c17c15247b0.npy +03001627-48f0c9b02587b5a8ea0588dd0d874b1e.npy +03636649-bc5f2f93922aeb65fcb8d8c6d4df8143.npy +02808440-5132921c7ed221103af30a3946d92feb.npy +03001627-400a5dbd31db947b35836c728d324152.npy +03991062-186cd7542e540fc82b2a077db1b64e23.npy +04379243-74b8222078ba776c661673811de66400.npy +02691156-f337580024e8c36da5cec7cc83604181.npy +03991062-5f3a050002015f5bc323742ccd065ef4.npy +02958343-831a3689b2f48664473f10e6caaeca56.npy +02876657-57b186ba25a680584289430f919c490c.npy +04099429-b967f61b749b3d0578268642d8df40d1.npy +04379243-6b5f5a51340e371ea753e2e06c37201.npy +03001627-a54ac4580f151f89278d386bfa54545.npy +04401088-5a28460645d4a28c7fa29a3ea424473.npy +02958343-ca0f99974520bde12776450c3e3bf20a.npy +04530566-9b91a683da8c4781f990230c33049243.npy +02876657-43ad6585f6b9a64675e1008a71b1c5e9.npy +03636649-ea71ba1d8d8c8e5888a1de3dc61bfeef.npy +04379243-2d7c48df632589a7ad5067eac75a07f7.npy +03593526-b7f03dab9501bad647be29e6263b8b5e.npy +03001627-59ca6d57ddd091c26eda1c7568601317.npy +04530566-c15004cb38217b33af018ffb2ed4ff85.npy +02691156-911e9f0246b26b309f789b924eaffb62.npy +02924116-c099c763ee6e485052470de2774d6099.npy +04090263-f06a233c12b64a0ffa9286f039319ff7.npy +03513137-f2513143d0467e357af69fbb2f9a628a.npy +02958343-20b03fde0d55a99fbecf71e2e014ff6f.npy +02871439-d36a9b7716b47b90492d9da2668ec34c.npy +03636649-d36d4552fe1290ee90c2e24416edfe5b.npy +03001627-bb8fbbbb9925a376d1dcc55e36186e4e.npy +03001627-7fb75b03d3ccd58c4710269d4bc18736.npy +03001627-1e53d84e48bb7d25febad4f49b26ec52.npy +03467517-131f827521abed2548627a76b6268107.npy +04401088-d0b5b899929975558ee99126b119afe5.npy +04256520-f27962a9ea7a87a87140e995552e7616.npy +04379243-6913ad01e9b00c4ca6c03a53cf0a14c9.npy +02691156-77a1744ee3c37f9b6aa3bf023a2b42a5.npy +02691156-7ee2912263fa4bb36f14b7a660f4c864.npy +04379243-564474f25a4400c5dc20930e6fc85682.npy +03593526-f9346339a3b24bfc500158c23c4c5a8e.npy +04379243-fa89bec3cccc137b10eb3ebb0bbddbb0.npy +04379243-bd28567361a3541d97fb366fa4051f4b.npy +02691156-d6d84d05892a4f492e7c68eb5d1b9123.npy +02691156-f98964dc88c44a2c863ab010b80d9ed.npy +04401088-34d8c06ade78bee87e273378b31b6ba6.npy +04379243-6110ca3d6213d128c96f5ad2252495c6.npy +03001627-8763bc46c26ab19957b7bfa2b0e9620b.npy +02958343-f6906412622f5853413113c385698bb2.npy +03691459-9471b1f88cca01134c40f34de8f3bdb8.npy +04379243-6acba1cf4d21321a9ac279f421086f50.npy +04379243-25695002a51a61c38596fa5b590d746a.npy +02933112-5c306efe5d4409c31190e285a2cbc9c.npy +02691156-7790715d4bc226f8b569b36137d81c9b.npy +04090263-9a1bd54ed9acf1ae73ede6cad0df9fb6.npy +02933112-1175801334a9e410df3a1b0d597ce76e.npy +02691156-5cd14216765393f18b96ae1a0a8b84ec.npy +02958343-3e36e7b04fbd55a0f691b4bfa2a7ff4e.npy +04379243-622d66d9e598b7788e0faa4ef4033cfd.npy +04379243-a19e6780182c72cf9bf8bea04806ba15.npy +02933112-8c1cd3c09ffef7efc59350d819542ec7.npy +02958343-641e43fc49e754edbcfa8eb5a2d224d7.npy +02954340-373d717709b3e181bbda4bd2b976d8f7.npy +03211117-b68da827b6c8852ecd0f781bc45707bd.npy +04256520-21e930917f2cab28dd711af5650bdcf.npy +03001627-aa3e5b5828912c0b5d11e7d6920a72ce.npy +02871439-7f40e1a4fd8344228ab882e168bd8706.npy +03467517-1817e920fd92124fcc1908493f380315.npy +02924116-1aae0b0836cd03ab90b756c60eaa9646.npy +03001627-858e512945d4544644175b4dddf5be08.npy +02958343-4026bb045c2cfc669f4536d76626fb35.npy +04256520-469a61462432d5521625c754b61476d2.npy +03691459-65e35b8378bb62a3801d0b1c6eb274a4.npy +03710193-551fcbbeb0e75c3dc2c30a1e5c9027fe.npy +03636649-cd7bda99f9797d8b1878e92fa20d38a6.npy +04530566-4c8fa5d0d4b2c54644dbf20ba8545fd.npy +04468005-6ef9b372b0a3ddb7cb01c89ef4a63ff6.npy +04256520-b76e0d43ac0800366a035d0ca8a43948.npy +02958343-a08b151ac5254df184bf231ea6363fab.npy +02691156-f613ace665da5e3e8b96ae1a0a8b84ec.npy +03001627-a3ce9ba74ab50352e6fe3612af521500.npy +04379243-3e08106901d3c9157145387788e4fc89.npy +04256520-b95f97ba63ab989cacbf0573260a18d4.npy +04379243-234a106ec36821d8c9f016d57db96408.npy +03636649-48f878a6176591190c2e24416edfe5b.npy +03001627-e199b1f6a70c9f56df44d20a516c07b3.npy +03001627-c55077d0b8fd893fdc4d371eb87a65ca.npy +04379243-1ba43964b343f6b6ddad726b9e01fa69.npy +02992529-6cc44d39e099bb6b9ef9eb3ddb0818a.npy +03001627-511e6440fad9bfa81fc8b86678ea0c8b.npy +04401088-e55c20e95bf299b5fc4d1dd4278b31a5.npy +04330267-15e020e34e3d2bba60ddc468fe733ed1.npy +02958343-bbf01f037b55306f8c2fb4d10f176f65.npy +03636649-8edb515a3e77afc4a8737fcf23389014.npy +04256520-fadd7d8c94893136e4b1c2efb094888b.npy +04530566-4c6e4bc79308e23e480060a68009533d.npy +03001627-975ea4be01c7488611bc8e8361bc5303.npy +03001627-ub5d972a1-de16-4d0a-aa40-85cd3a69aa8a.npy +04530566-72f3510fb835c3557c0ab7347b9e831a.npy +03761084-31548a2ffbdeb4037b6fd5468f603b31.npy +03001627-2191f89e65241e7be04d00482f14a156.npy +03001627-561d50862a2cb4aabc19762eaa7ba40f.npy +04090263-9ebdd77ce251d68626243ac6fb5d9ad9.npy +03513137-20ef9affd966bb53727b087f26084eb.npy +02691156-48706d323b9041d5438a95791ca4064d.npy +02958343-13d0f68f32a86bdfe3857ce739e6606f.npy +04468005-59b884e12684b48b1b2cfb60d91b4238.npy +03001627-1da29597f89c2b004b3c42e318f3affc.npy +03691459-1b31f250deb7e124fae32a4a57dfb78.npy +03001627-7df2443e976658b7cdfc3ede082b8a07.npy +02958343-cdfe4dc408f4ca84aaafd94b9f216ef6.npy +03001627-17ab0917e215e4fcfd300048280f015a.npy +02828884-ae1adc589a37317b2056b4bd5d870b47.npy +02924116-131a94e966b7dd5dfb89738614af8f1a.npy +03928116-8c2565c3adfa691985d624cfcd9a37a7.npy +02808440-2a5d4962869b1c34c62bee40dcdc539.npy +04256520-916abea85193002adae12f3947d07dec.npy +04401088-75dce3b2e5152c01ead1b13838d77bb3.npy +02958343-e09c2528f56f04d03e241901f2025878.npy +03046257-64bb924549024c7cac26591069295f15.npy +03467517-1821a6d30c529af493b667ec2f48a310.npy +02958343-39cb477c0a03aa1c3ab1417a5ca1ff4.npy +04379243-6b43398bac2b6979438d8caa9ae106fa.npy +03790512-d3e1ee410274fe4036abd307db1ff816.npy +03001627-68c7f82dd1e1634d9338458f802f5ad7.npy +03001627-b1adda06d8846afcb96f0049223adf04.npy +04256520-a8f10f404b317af4946789884353d9f6.npy +03046257-8627319b3c0a9f4c90ce699a92b3fef9.npy +04379243-88c833a60e220f2320ccbe1c34ca182d.npy +03467517-22129fab1497437cc3f912172873d52f.npy +03636649-cc643d2e5b7a46f5809222e4341a7d65.npy +04256520-b2061e554db928f233442b36ae29e50f.npy +02958343-f15ba529063317d241b8aedea2034739.npy +03001627-bbe566c26d28ccfb504721639e19f609.npy +04256520-7f0d93163b0db7a71ebf17f9e9667427.npy +04256520-85293b59b0f9cc1e593ebeeedbff73b.npy +04379243-6949e65a18ca505298d5fc0473d00a1c.npy +04256520-fcdc852692f43041fdac1e69603928f.npy +03593526-a0569f8e769d087467964ba700cd97f5.npy +03691459-abbca9c2aa1ab018ad65e8e6cc8ad9b8.npy +02691156-6481eb70eb9a58cfb2bb87688c5d2f58.npy +03691459-2454758b9629441cf322c3e7acea58f1.npy +04379243-d5e003575739a8ce1bb088904f7cb154.npy +04401088-11f7613cae7d973fd7e59c29eb25f02f.npy +04379243-24c854eb3f4bdba21b17743c18fb63dc.npy +04379243-b16567c16d0aca41532e8683617554c4.npy +02808440-c9dfb7c152684e3f3321831d2245cf06.npy +02691156-253a1aead30731904c3a35cee92bb95b.npy +03001627-86e2424968b01e241b94efa300287e71.npy +02924116-dcfe09e01660f263dd49dbd3b1c588a7.npy +04090263-457cbd3f2a9a710c11f7dcbb4a32aee5.npy +04379243-f17e630571a76d4f4b8710a3469971b1.npy +04256520-1739665585ec210fb04cb542e2c50eb4.npy +04379243-8fd9d529453e8d56c09af5354c5cbf4e.npy +04090263-b151820ba72ad964fa9286f039319ff7.npy +04379243-6f03a6f024145fc9febad4f49b26ec52.npy +03636649-f449dd0eb25773925077539b37310c29.npy +03001627-e0efbc4e240b9cc235836c728d324152.npy +04401088-856d33d16a97605bc9164fb9f03dc1ac.npy +03337140-eb0913a3e196f517ce5d6e9371bb5c33.npy +02691156-7a1954799b5fbb438fc2d09ac4aa4e78.npy +02691156-edd9583988b62c90328f15e6c60d0e90.npy +02992529-1ecbb2ddeca087b5fd71b7a0b881ae82.npy +04554684-abaca4a16b203ccadf3a1b0d597ce76e.npy +03636649-9dd9e38efea22f529a60d6ab40898d.npy +02808440-a4b457c41180e0b9fe52ffd0e748a1ab.npy +03211117-8440ff1637f2c6d7ebe17c8dfb911d2c.npy +03325088-59f6a76767eb5fc72f8c68dc62edc38.npy +02691156-e033b6ad34586a86cc1c9e8218bfe7fc.npy +02691156-d221f607d5b5c553faac198e88c3dbb7.npy +02691156-265f5348ab2320b2148672750a1a335.npy +04379243-cde67434193a2a6f19fb4103277a6b93.npy +03991062-9f4e8476917af3a12271466eed05a4d3.npy +02958343-30f4617775480bcce27281f3b76d1f5.npy +04090263-b6feb20b14f9519ef933a612bb11b1b8.npy +02691156-a56143efe74ee89ebbf3143b1cb6076a.npy +02876657-3a6fae97b5fa5cbb3db8babb13da5441.npy +02933112-46e31ba5963a89fac59350d819542ec7.npy +02933112-dc4affd586bafbc8d45f502ecff9e44f.npy +03001627-94ef9a352eefe9455ac8254dd793f590.npy +02691156-4d50ff789e84e70e54eefcdc602d4520.npy +02924116-ab0921f71fda6e1bf446f92b52bbd82a.npy +04004475-d9a7f7d8d6358ab268e3172ee2027144.npy +03759954-f482692b2086e54e7ec3f7c14c03a92c.npy +02933112-4caef9af7bd31f195588a2543ef0b0b4.npy +03001627-64f03da6f61e5b99d858721c5f89c1b8.npy +02808440-90b6e958b359c1592ad490d4d7fae486.npy +03001627-c18fd0dd722d164f41bb00bd5475793.npy +04530566-ba05637e557909b19527abfa7ff95c0f.npy +03624134-acd9570aab1c4fd47e25b10df54e79de.npy +04379243-45d5801abb4affea5b411468d0e36e1e.npy +03593526-d68da52ed2de0e7bc5beea20858a99d5.npy +02958343-4493638824352150940e51eee9dd2409.npy +03759954-d823eac75f84b3bbf76111a8c1b3eccd.npy +03636649-89f8c456a55c3386157d629c9921fc15.npy +03001627-fdac1f9c0b030841c8687ff9b0b4e4ac.npy +03636649-9c6084d24011c791c8107db508bde472.npy +02828884-e14c754dab919df2ed647189c2f43b5f.npy +03636649-3ab9e4300cee0259f72e8839e840c146.npy +02808440-2f3d0058b843186180a744f96587254b.npy +02691156-3d5354863690ac7eca27bba175814d1.npy +04379243-d1fba8006e7f72bd7228984b9aa31321.npy +02933112-a07f3b931238a5c3fe618e12c7f65698.npy +02958343-600ab6a1f116a5ac994a3466f8481f8a.npy +03001627-19666f52289092a3394a3bbfc81460.npy +02871439-b276b63c40e9ef46534d1a2a7289d9a8.npy +02958343-94b52d2fb55004d5ab2c2809513f396e.npy +02773838-abba6df6294f20c569ea850160c0b35.npy +04530566-c55868566d2cd547d8d2db57c9e192a.npy +03001627-902a46f5caf6b1f7e38c7f0de498b8e5.npy +04530566-40752c807c2be827c924fc2f78f9cea0.npy +02958343-202fbaeffaf49f4b61c6c61410fc904b.npy +02691156-e00b89bc338348caa42c49797afd1f5c.npy +02691156-47d958a8a781144b132a08135eefe76d.npy +02924116-eebc54c82c116bdca8b9756f00ab956c.npy +03001627-38436cce91dfe9a340b2974a4bd47901.npy +04379243-3f2e9c14ab1d26a0ebead06af665220.npy +03593526-a95db9f4cb692657a09c6a60c6dc420.npy +02691156-ef6db5bcb6bb96ddd2f0cc036969ee4f.npy +04256520-b6049bcbc56eb65e2553cc33364504d5.npy +02958343-9e4380de95fea34a11718baa6d4afc0b.npy +02828884-a3e6d02075732ca850f9fc0e2c94dd76.npy +03001627-3c4a33481f45cebb81f5ac91b0c9e99b.npy +02933112-192caea21a57389265dbe89d2f371f01.npy +04256520-ea06841d7501d07436b31862e09495f2.npy +02958343-a17bdad065a0e008a2e48b029cec5d4b.npy +04090263-d601235af9b5e93e49f0e3dd7767881.npy +02691156-fd0262e95283727d7b02bf6205401969.npy +02958343-25de320e58cb3898f43db49cede9f847.npy +02958343-1bace29924c0ae42226fc3902f16303f.npy +03691459-ef793b2369c5dcd9bb63f7ad325b6424.npy +03636649-23c41f1c519c82202dccb0b1a2845fc.npy +03001627-3e8ad99691e8ea4c504721639e19f609.npy +04256520-d0b33818a29689a8ab5d9b3550c46460.npy +04379243-2db1f557e247ded7e907b6d9dc1d71b7.npy +04330267-df6e6a6405d121abf39d7554d3e63ae4.npy +03001627-e779cf261cf04a77acd8c40fddcf9ca.npy +02828884-6466c201a664851de7b89654b68b9e5b.npy +04379243-ad9adf7c2c45842ae7354dcb6082ee59.npy +04530566-5c116a0ca9477e44318f6eb5e296bb88.npy +02828884-52867aee1e2e137912a905e721b748f5.npy +04530566-3807ccfaad3716ec59d8a2cd36b3278.npy +02958343-570a9903fc7fa557d0a4f72b67c7f064.npy +04530566-6e1781a84b5dbda6fb3e64e796c0391a.npy +02958343-6482e3afc2664e32d30f2d8d219e111c.npy +04530566-5168b7d5df698bb2852d4401c7cd1fee.npy +03001627-3ec25d235438258d815b20ced9d3b22a.npy +03001627-320b6f3ae2893d3c9f5d3fd8c90b27d2.npy +03046257-569f15f5c49a880c5c9c63683b16d1e1.npy +04379243-965abcd187b93da3f1783a44a88d6274.npy +03001627-3fc6ab5d3c52c128d810b14a81e12eca.npy +02691156-1203825bf97bc3524722e1824a086fad.npy +03636649-8a6944062cbf8b25ef0a7c6e0ed55209.npy +04379243-408c3db9b4ee6be2e9f3e9c758fef992.npy +02828884-a219234ac9ffe2e012f133bc7efb2111.npy +02958343-d4abda76f4db60086d07c55cf995503e.npy +04379243-319e08128a169440c3bd24f986301745.npy +02958343-b6755cab505f437375cad724c63e222e.npy +04256520-8d87711b1fc30783f06800d5696e457f.npy +04379243-d1c6ed48a115eed0659dda512294c744.npy +03636649-b8c6a482bc4d5da6fcb8d8c6d4df8143.npy +02958343-e69a5ad60aad3da2292296f0c84d7087.npy +02818832-f7edc3cc11e8bc43869a5f86d182e67f.npy +02828884-593251f67107e6b4db03e4f5c01cf109.npy +03001627-b1da0d9aab6d2308608505d960f2a393.npy +04379243-38fb3322efc35807486150a9b7f2cf18.npy +02876657-3861b002979703fbed4f86beca49f32.npy +02924116-2136de514b7c5e994764eeaa5c6e1a63.npy +04379243-124cc3b92266c2767156f312cf4e035e.npy +03636649-8b2b8b1048a707203c752b66cc923fdb.npy +03001627-9fd0c95e0112f6f8dcbca12e02e87571.npy +02992529-add38cbd2fd27d62cc98c9802550400.npy +02828884-2b90bed7e9960ba11e672888e1de63dc.npy +04379243-a5029c18a50d0e4be7c7920f6a65a54d.npy +03325088-d8f173b9cf9b84c728486e67fcce75da.npy +04256520-602e0f167c5edf327289c00b6dc9ca.npy +03001627-ec78623a598fb6d67fa68300c57bff0a.npy +02818832-9995e8f977861716e3ebe8b18779c486.npy +03001627-c4912ddaf24ee0fe7ea88ba060407992.npy +02992529-db89fa13b1c3c53afff0e9d5e9e3da5b.npy +04379243-60052d2cbcb9f8e725c578fb351f3549.npy +02958343-7f701224ca471b2ab8013668e30e23b0.npy +04379243-3365fa395d93bfd8f181ff4e3cb0a33c.npy +04379243-415e3d53c7a93ef88b90ca5a8d93018c.npy +03001627-e9821fb7af7db92b26f6c8b5b75f0ee9.npy +03513137-c54fc7db01647d02823590ed8a67d74b.npy +02828884-3fbbb64cce9b5fb681faebbdea6bd9be.npy +03001627-b8db5d63c7042d447cbf7cf495477037.npy +04379243-726c677962874743002761e7a3ba3bd.npy +02933112-2ce5e1eb83f4510319f778c7a8b12264.npy +04256520-87bdac1e34f3e6146db2ac45db35c175.npy +03636649-88d29e1350eda810c066b9622c005c53.npy +02691156-43d8125d940bb2ae850f318836ee7512.npy +02691156-a312cb2c9bb4665bd44389c0c0e68465.npy +03001627-5008eca8deba6555ee229bc98ff4457e.npy +02958343-420519a0f7390564f500cc506a763c18.npy +04530566-372ff5cab89350d23217bd20648fc12d.npy +03001627-640aadadf4fcba8355f9a00acc25f137.npy +02691156-49611834b200ece04c3a35cee92bb95b.npy +03691459-c198d2df79e4a40fde3a1fb6044fe536.npy +04379243-4b35aeb6ad7a0370f51945de050323d3.npy +02828884-248e0773a2a8d90879ba0a8466ed4e3b.npy +03001627-e5a8500223786886995e7ab497adca70.npy +03642806-6ae14173f5bface824a85bcf396c330.npy +03691459-eb9de225b5d502c1278fe505f40d50be.npy +03691459-fa6fab7bc0823f6e54feda409512bbb5.npy +04379243-eb9b9b8d186a974a7afee304cce81d6f.npy +02691156-2c5bdd9a08122f9e2023ec956848b741.npy +04379243-7e2c280b5839d502eee2d67fbfa67a7f.npy +02808440-556213319f5a21dbccd0340812259a39.npy +03001627-2dbe453ba389adf5f91663a74ccd2338.npy +04379243-9ffffefc4b5a04ec49ed2275c90a1298.npy +03691459-99f296d0bbae5585414ff38ecabd5968.npy +03001627-5ae7ef4cfaa6bd85b04cb542e2c50eb4.npy +04379243-24f753c88ee4376f19fb4103277a6b93.npy +03001627-4f58ebeb561bb94bb9e8bdc9c4a49aa2.npy +03928116-5a3017574c3ab9d61d4127b3f0e05b90.npy +03001627-a95b5ea73cf0c9bc8e72c17826417b99.npy +03691459-ef509cfed1b359a7dc1ad15ea0771770.npy +03001627-fe31beab802cfc56c2bcda262700befe.npy +02958343-fee1c13922c07e8711b978ff9450f61b.npy +04330267-d07660fd1f3ca85f4d1cd794fadc7ced.npy +02828884-adaf1ba4acf51baa601104cd2d998272.npy +04379243-cc445d016f3a487d84cc5b3c1e5e75d5.npy +02691156-17ac3afd54143b797172a40a4ca640fe.npy +04379243-5dbdb35766fd2d4c9f4b4145f6688869.npy +02958343-11e5b7d67058e1d75f67208653687b70.npy +04468005-f5cfce14d01f0c08157566c5ec7088ba.npy +04530566-3c5d0c6c971d39aa70cfb3232f40c6.npy +03691459-3655d8078087f1c62d563c85edb49108.npy +04256520-7140d5cf3fb0c528b43753a53e4593db.npy +03001627-8d5866194748bb3492d9da2668ec34c.npy +04379243-6dffe86c24e3870cbeedb4c8fd29e2d1.npy +04379243-bc5fdc598162f85076c7054c38bb1311.npy +02958343-fa9897315ee8b6ba67789dfcc3262f70.npy +02958343-f18093ac0242d439f500cc506a763c18.npy +04004475-d825fea4d6efcf11c4c8b2717842f75e.npy +03593526-c17615e76d2988802f841233486fac2b.npy +02808440-ea7913efbe22abed412deb0d2b0f3dcd.npy +04256520-ab38a559643b01908b424343280aeccb.npy +02876657-c3bc0cd2648e76b9187964c89b3399f1.npy +04379243-59366e331014e2248738e7290b6f3237.npy +04256520-785505b155a724cb6e92e37d6e2c659.npy +03691459-e5deab6728f237a6fc7703ebafc3f082.npy +02958343-f6e0b8a0746d36d74eb766e5a46fceab.npy +04530566-ce15225b24bb4ed2742fb0ba5ae222f2.npy +04379243-53fe29e7363eaa70ce898a7d76534f1f.npy +03636649-e02e79e028662e9ffcb8d8c6d4df8143.npy +02958343-911029433b8ff0f1afe1d4530f4c6e24.npy +04256520-695b90883d398e5b15cdaecfa8164583.npy +02958343-c896260b935971fc65d21723f535417.npy +04379243-55589c71a2abfe97f09df371fae9d63d.npy +02808440-18100df055914701d79a5415e88748c0.npy +03001627-b8e5ce05c382b9a3f51f77a6d7299806.npy +03001627-7f79aba01e8c572b68d1b9a1d97e2846.npy +03325088-b9816227a0b977c9b362845c6edb57fc.npy +04330267-a6912050e1bb1c13c7fb1a0a584939a5.npy +03325088-2d47bde73180097d76d20e73c57c9a03.npy +03325088-346a94616fa138bb85d4c34ee84c24a9.npy +03001627-6fde09bdd613f6e6492d9da2668ec34c.npy +03001627-fc4d15c15c56aa7baab4888e25356418.npy +03001627-2fa970b5c40fbfb95117ae083a7e54ea.npy +03325088-7d98283d7e6fa67a76c18e71fd49c4dc.npy +02691156-f57caba2eed21f2998459325335edae9.npy +02808440-1302d8860c7bd1e17f53f1372963d362.npy +04090263-82c04946433c4a8f63413b0440eeb6fc.npy +04379243-6a2c94b2c34c6134490ad276cd2af3a4.npy +02992529-cd1739ec8797049072f1ebe52d9b9daa.npy +03001627-e078876957aa6efbb0b0d46323bc2ae0.npy +03325088-eceb070402c34d37f38c4a12750d961b.npy +03046257-d8bb7dc20a30afe1f0aeabfdcb4e1dd9.npy +03211117-2e6204b4aa7ba83fbd28395acf9af65e.npy +04379243-f9beeefdebf70350f4b6538438a0b930.npy +02876657-64ad00b1757205a3f388b3201b32e1d0.npy +03325088-736123b57129c3bc14de2a9aaff52ac7.npy +02818832-c496214ce548416f4af8975fbcc96231.npy +02691156-1e6a71e0cb436a88a3a1394d6e3d2c63.npy +02880940-aad3cd6a40a15cb8664b3b9b23ddfcbc.npy +04256520-f9f7fe005455dbec215b8895763d1ff.npy +04256520-35b4c449b5ae845013aebd62ca4dcb58.npy +03001627-bda113bd71ea0352654ea6737b0d3597.npy +03001627-682bbcd00c5287a39d365481aaba80e.npy +04379243-268116c288b215c43dbb6421d614c0d.npy +03001627-1878633a36518ffc19fb4103277a6b93.npy +02942699-3d18881b51009a7a8ff43d2d38ae15e1.npy +02773838-758dd5af7f18ed9acd99ccc7ff441abf.npy +03991062-9b56496d8e6be657ff67c12005f72d2.npy +03001627-a7d75c84027af5e7321f25048c6142.npy +03642806-8a0edfd20cdfc27d8ca8637757ac3f67.npy +04256520-cceaeed0d8cf5bdbca68d7e2f215cb19.npy +03636649-4f62263f7bb10280a5f600ed2cf472ac.npy +04090263-2fe46eacc06b51bfeb8dcf90fc26e10c.npy +04379243-acc0b552910e603955f46d55537192b6.npy +04090263-cb52cb876bb3ec76aca1893e093d31f3.npy +04379243-bee1f4fa0730c6c5735aedaf68f44c57.npy +03636649-9bbe778f05a04009fcb8d8c6d4df8143.npy +02958343-8109ca22dd6b5772bb54d0b0194b4764.npy +02691156-78551e5fc01df70f77fd7318510b8627.npy +02958343-2830f11dbd7172222214ff09b39580e9.npy +04256520-2e5d49e60a1f3abae9deec47d8412ee.npy +04256520-4a264b02e0d8fc214b3c42e318f3affc.npy +04256520-dcfdd81e4410dab49f2349486c570dd4.npy +04379243-4b6d73d06b7359f26cca17c12e67a536.npy +03467517-b68c1576d19b5f1b93b667ec2f48a310.npy +04460130-c85bd50e2ac803aedfca80608ef618ad.npy +03001627-d657236c764dabdf5de9b4b5ce85d50a.npy +02933112-a32e351352e1053ad124fd2a448c2915.npy +02828884-2b25e49c58ae0e292056b4bd5d870b47.npy +04256520-2b7e704b07fd21febe65001d50394fd9.npy +02933112-623c347d2d5cd6b4a66c900acb409285.npy +02876657-957f897018c8c387b79156a61ad4c01.npy +04530566-d9e044a3cdd4359110f59460c26e963e.npy +03001627-a2441f03fed7c13def31f91fe6afc8fa.npy +03001627-75d3fc4649a63ac13efeda73d60343e4.npy +02747177-acfe521c412fcd04564c0afd61663476.npy +03691459-f0b4735b45d1a6b51aadbcf355bd688f.npy +04401088-22fc328d136756361e5d846d206adf3d.npy +02958343-69aaf42f0b8d0e2da37127a27e431e39.npy +02924116-e4cbd9d5a9c5b7d241cefd10ce5d6cc0.npy +02992529-76a4a3e8370bdc24bd2d4107e8dc02b8.npy +04090263-9f4c4c60efdb3076d02276f7769397e6.npy +04379243-8ee19157170f16dec12312ed5983ff64.npy +03001627-122a480cfcdd742650c626aa72455dae.npy +02958343-b1ad30609c2fa8a2d63b3823877bfa70.npy +04256520-3a27e270712fe178ce59ea70152320fa.npy +03928116-413f8963de404dd6c3c1160502619061.npy +03001627-f2af2483f9fb980cb237f85c0ae7ac77.npy +04379243-ee16bda18e585ce3445e85eb534460b0.npy +03790512-3156fd3e3101da329b0e27507dc1a100.npy +02843684-514e3ac98b1d18565ae27b5e83f8a47a.npy +03325088-fef67b0b5fee52a1843f813f752a5e35.npy +04530566-b1991078d16797eb221fc8bb1161b418.npy +02933112-88a1a68c64ef85394da5feafe6f1c8fc.npy +03001627-341c9b0583d31770492d9da2668ec34c.npy +03691459-bd1ffe5dcd7239d8299f55a072267eac.npy +02958343-f66180e68fb1c98469f2880702ff1c7d.npy +04090263-630818ee20900d67fe0b9f6d3db7b59f.npy +02958343-ffb4d9920493f1e5c29076ad43b687b5.npy +02828884-f3ec1b92140e1d80cb2a965e75be701c.npy +03001627-11e55ca087c74082feec1f13d2353f3.npy +02924116-84d8f737e423d441bb81ac54404de04d.npy +03001627-61b984febe54b752d61420a53a0cb96d.npy +03642806-11448f34681c545439f3410d5f76299b.npy +03691459-6b13ee07cfc1eaf7967b9b287e3372bd.npy +04379243-62eff79cf2e75bc2765ee729adbdf968.npy +03001627-b274fcf203b9ba7612c19a9a8d2be7d4.npy +02691156-d38922599bc74f6da30fd8ce49679098.npy +04090263-1037acddbd363ef5782611375da5ea9a.npy +03001627-b5ae5354fe7c166319cb07ecb5b4102.npy +03001627-7d7b3b8a1734154b3b8d5c0ebdd194c8.npy +03691459-e6b83a9d10349930b611871e114769d9.npy +04090263-bc8ffdeb04d8526e1f2a1daf140ac9f.npy +02958343-1c490bf1c6b32ef6ff213501a803f212.npy +03624134-76d4739797f4cec15d3426ee101e9f8e.npy +03001627-8fbe7ef85a9c57db784a45ea6efa1d77.npy +04379243-e42f2707bec24e028bfc6c6704f4dffd.npy +03001627-768acb4029f2d682bfad749b583f6a07.npy +03001627-892529626a1710cf17ef8b7bd64bd7f2.npy +03636649-c9c2e5fc4d00db3acd99cc18cb18bf34.npy +02691156-ec4f0bfd77978a1cca8607f540cc62ba.npy +02828884-fa1ab735efa7255c81553c4a57179bef.npy +04379243-f0b827eed9f044bdcdcd8e1ae308f03a.npy +03593526-d214b7c1d3b40f935e7cfd06717825f5.npy +02828884-7d1e56ea7f32d634cb2a965e75be701c.npy +04468005-2c25a659d3f1b5d5543c83125736ede7.npy +03636649-42129d6b04cb9038b2f7093e7efce142.npy +03001627-91dbbc203e8562e6238f27554ec73a59.npy +02958343-5ad4cc3f8e191c61d31d4c555d4c5a0.npy +02871439-a82d418331301d2c664b3b9b23ddfcbc.npy +04090263-439fd95bcbf861f572cad024c77ecfb1.npy +02691156-77c9fd0f0c6b0e9fca8607f540cc62ba.npy +03001627-f230308627e5edaa9d796919a8d71368.npy +02871439-3ff6c9fb0941dab184df0a86512fde14.npy +03467517-b6f78c76441e30fbb60d315a520dce5d.npy +04379243-54f33905a3c8973a4b3c42e318f3affc.npy +03001627-27e757d4ed3c929b75c39dc45570367.npy +02924116-7f2de63b2c90a0633b1a772db543a132.npy +04379243-889a50c35328c8ddfd91359c9f546b9a.npy +04256520-18a6381f8a0dffc876828214888cb11e.npy +02828884-5f355af51670666cfbf62ed378434fd1.npy +03991062-e0ba02e9ab9e9ecfdae1b60026a5409.npy +04379243-ca22c129ee2ad8a1f0ca692121a428c5.npy +04256520-251fc26346ac1897febad4f49b26ec52.npy +04379243-6d4fad5487a044249dc30bab479ad5d4.npy +04379243-de1d044910991a072d184f71ff3205f5.npy +03001627-b7fd3cf7f37e22e6713decb1a0563b12.npy +04379243-faa5d5ba2a002922511e5b9dc733c75c.npy +04090263-f4775027ca39270897ddede15c51e64e.npy +04379243-c9f85a671d551086d61f9b2773e1d72a.npy +02876657-ea200708a0779090eab2bd7322386ffd.npy +02958343-99efa2111f3be22d5fcb05674109534a.npy +02992529-5ccde0c95cc0538ef39072555215f568.npy +03467517-8accc9161ad74bd4d13ea145d0a10775.npy +04379243-31ecf1e704642491ce372179a495fcb.npy +03636649-ddeb5d944c128f78b0957d845ac33749.npy +03636649-50a3d09ac90370ec9c48f338871146f5.npy +04256520-be2d759412b18995946789884353d9f6.npy +03467517-ad63f2323dae4b154b938e339e865d2d.npy +03211117-f3d6470b3f4f5ad71c7075c2bc313334.npy +03636649-76eb7436c40e083384d184bdc625781a.npy +02828884-7ac9bc04a2f8e59c7a19c607757a04b2.npy +04530566-d0652ef190720c84f4e9dade6d46323d.npy +04530566-68925483ebc30618698ab31ac670e62f.npy +02691156-f8fb835bdc55ffffdc82b8fee1057b30.npy +03001627-6ec02d7a508434f1b0957d845ac33749.npy +02958343-9f703e578b4b36295b74572d48ff6382.npy +03001627-ef10235a28cdf7cda16af3198c99de08.npy +04401088-8b4c89b8f756cc6e78fe949fc1419876.npy +03046257-8fba28ff0d6dd6bb80d26506b9358671.npy +04090263-db97f4931d2da6e53e1271d7bd927006.npy +02958343-dd184b3f41891cd317c40808ff7018fc.npy +04379243-dbf2123ee206a81b8b00eeaf68a1358.npy +03001627-3c8864b07a5c0718861df5a407858f2.npy +02880940-4bf56e6a081c2a85a11f6bacf5c7662d.npy +02691156-c2d5bd1215248f9c8b6c29bda2bc905a.npy +02691156-a00f6bbbba234739b92527b70e93ee2c.npy +04379243-c15aaf668a80aad9ee5912a5f7e89744.npy +02773838-2022610a5d1a8455abc49cae1a831a9e.npy +04004475-2f0086118aef1549f616f642bcfb80d3.npy +02933112-ac499f75479d2e372ad490d4d7fae486.npy +03211117-6272280e5ee3637d4f8f787d72a46973.npy +02958343-350be6825c19fb14e0675251723e1e08.npy +04090263-b90a8fd2c92f5d26ac0fcae21e22e3fc.npy +03325088-7063aee9b0cac797b362845c6edb57fc.npy +02924116-a701862b4a209173c98c13d6112727de.npy +02992529-436d7a114f72dc03d4713685ae50fa13.npy +03211117-54ec97f055d68a78ea0068b966c5177.npy +03636649-2af78c0b040634e5881cd5e2fd8f0f3b.npy +03261776-c81c908ddf6c48744310636931b68fdb.npy +03593526-cb451e92ce5a422c9095fe1213108032.npy +02691156-c5d0dd7a7b44b079a76ffc04f04676cb.npy +02933112-6c01e409fb522789b664d1885442ba70.npy +02946921-d052c17866cf5cf8387e8ce4aad01a52.npy +03325088-4477714b35747609f34d244dc02df229.npy +03691459-b8417869805cc9913ef7ad0f5cedb0e3.npy +02992529-d5561b05a6b84a5489905122ac8b41f3.npy +03001627-22f030ce09693f4c65c99f3aded15b93.npy +03636649-fcd263dc05862ad1bec3353c29751fdf.npy +02880940-9a52843cc89cd208362be90aaa182ec6.npy +03211117-ab64dabcbaf1086f14d199c00aad9da1.npy +04090263-e479b8f33a323147f0eab8a2ebef8e89.npy +02828884-794573d3e6a2c4ddd845dc43591f551.npy +03001627-30526709beea1350c862eec8232fff1e.npy +04401088-a0a41f9444733969c3d30d5f04be159e.npy +03467517-f440f59916c2ed897b076baeaedfec9b.npy +04256520-cd06c0f38b4db9b4c397356311cbeea4.npy +02958343-7ed6fdece737f0118bb11dbc05ffaa74.npy +04256520-ce3055223e53a46e67d4ef1ee6cc8170.npy +03636649-e0e365a2927a7a73bafad60030e6ab60.npy +02691156-865f434c71d41326c9d5795160525060.npy +03636649-3879234efb8e60219f6b6d8f19761cb8.npy +04090263-5dbe96b00f0d7b201b8fee1b14934c0e.npy +04468005-e40a2d72efd3e67ed85b408a8edc983b.npy +04379243-33bf7aa0aa429a98bbfa993b02d27a30.npy +02808440-40f0604892e7b4268a7ab8a2c534e9e7.npy +02933112-43ed2ac5e1836f5ef51f77a6d7299806.npy +03642806-6b4698eadedd956cd2079b28d473791b.npy +04468005-cefa8b1b55922f419e5c987c836cf01f.npy +04330267-563f955f46e4368d8ae69567bc5a3efb.npy +03636649-121286f843ab37f71735ea0e092a805a.npy +04379243-572abcadc95a8ed14b3c42e318f3affc.npy +03001627-28d27f1204c1b3de6512b7b24f3d84.npy +04379243-ab7405d5b3ae15565e7087f2d9a278a9.npy +03001627-1f1b07bf637b3a1582db9fca4b68095.npy +02691156-3ecea45bfa541b8e4a4dd08ffc16eb81.npy +03046257-4b1283cead37c519e49675db0062ac74.npy +02691156-a82400edb160c18fc8727b27ee96a4b7.npy +02958343-1c14ef4c48b7d95d61c6c61410fc904b.npy +04379243-1613e86311fd7601c103f0a69924253f.npy +03636649-68491d576b5d35aade8e7376ce4e111f.npy +04090263-5ce2da67625a1415ae42d8f433c1cdc1.npy +02818832-3a3a4982fd12d3d7fcc95bb239c4c353.npy +04379243-3e0b229e646595261a719e2a845bdada.npy +03467517-c9b60abdc17708fb78ad94b294a9faa6.npy +03001627-87baf0c4bd11ebe7f771b7c5ceefa9be.npy +03636649-4da9ae6448c860243dfad56d2a4eefcd.npy +03001627-4bc5a889b3ef967b9de7cc399bc9b2b3.npy +03636649-d8a5c77da4c92921f7258dec1a592c96.npy +02958343-ba1b8956b1d84856369912a1ddf80ef7.npy +02924116-7fea6a3b4f76cf6d1b78de62f6c48608.npy +04379243-356e173817daabb0f44dc88afcdcd380.npy +02933112-56f7c9a029b6b40d12de5317fe5b354f.npy +03337140-992b47933eb0f924c3aee8e9d3a6ffa.npy +03211117-5a66f2589c7df206e1f2a1daf140ac9f.npy +03593526-c6ffb2891c1ea743ad8827e8f4f151e6.npy +04256520-9b08d6288f208362dac562275d66ec29.npy +04379243-c4998912c5b40b8de1590f407a430d33.npy +04090263-e85f80f7fe4c8f3266597c7d470782b4.npy +04256520-45e5b5efe95ae98ff2be27e9cc5f92fd.npy +02876657-f6ffca90c543edf9d6438d5cb8c578c6.npy +04379243-6ea2512df0b4f49244175b4dddf5be08.npy +04379243-f247cb60019ea321dffe3352803d6df5.npy +03636649-7972fd0fe5755b4ad42b9650f19dd425.npy +04090263-2509d876e7521634ad26d867b17d1a48.npy +03790512-170cfc531a4fd09fe6905ba5363784c3.npy +02876657-a95db9f4cb692657a09c6a60c6dc420.npy +04256520-918ae8afec3dc70af7628281ecb18112.npy +04256520-c9fb9cb259692ec0f7248d9dbed7a7b8.npy +02691156-2c3ba3f35c5d2b0ce77e43d0a92bdc06.npy +04530566-8b3cf3842a88136c67c16c85d5f8c7d7.npy +04530566-16f53391dba14c9829ebc23acefb248a.npy +02958343-6291f064e64c6eb9d18a5bd35f0d115b.npy +02828884-9596592f31910b9684a9223b0abc0b3.npy +03001627-dcbb15dad2001a0b8a4c763d71484708.npy +02924116-1134df3dbee4c3dc221d7b13f13a827e.npy +02880940-960c5c5bff2d3a4bbced73c51e99f8b2.npy +04379243-ddbbe3651f274503c7f9b652b66aa35c.npy +02747177-60b743e913182e9ad5067eac75a07f7.npy +04379243-6e1dc5da243fc523c5f48f9175316bec.npy +04530566-bfa34aeefb04b4c2356c09782a9de7a4.npy +04256520-bed924f1f1208f37f0bb193323cf7c6b.npy +03797390-6500ccc65e210b14d829190312080ea3.npy +02828884-d5bd619acad1bed3d2b12aa6a0f050b3.npy +02958343-97831a753d80d66dfd24692312e9de8c.npy +04379243-8f8954e310eb265bd42b9650f19dd425.npy +04379243-49374090de654a54fcd4910413c446d9.npy +04379243-283844acddc9df141191025061735ea3.npy +03593526-6a13375f8fce3142e6597d391ab6fcc1.npy +04379243-21009983c23be33dde39a695c03bae3a.npy +03325088-df3f006c8a8a59547bae653f822044a6.npy +02691156-5413e0eca808b2601f17e8416b3322a8.npy +04379243-549bfb6738e5c5a019fb4103277a6b93.npy +02828884-a64965f10047f31db3ee3d0077feb1bd.npy +02691156-44c0cb6571f6f000ca8607f540cc62ba.npy +04090263-b06d8b805dcfd1ebe212dc904164c2e0.npy +03642806-74eeef3fb670363550d5454e56d54b19.npy +03001627-68dc37f167347d73ea46bea76c64cc3d.npy +04090263-736af7558693f029774a2bc3e125b7e.npy +03001627-d4c3dd37d27afa8e7c5910dd17778965.npy +04256520-6931000a5a1932b6a494798fa117187b.npy +04256520-26fe44345859362569e2e0d2caa039.npy +03325088-2031479400b516043792c04fd8184496.npy +04256520-d0fcb2993379cf9ed72ff9ec64cb596d.npy +02958343-d8c7f76320624fef02d716c401defb1.npy +02958343-5881807902ace2dc7d26edf2a8ffb68.npy +03325088-8a1de547037ee5a4b362845c6edb57fc.npy +04379243-f7ce798a5ea0850c4b3c42e318f3affc.npy +03636649-30fd90087f12d6ddb3a010e5a9dcf3a8.npy +03691459-c3fbe6332f413bd2bddb05cb83a4378c.npy +03211117-b0c1b6c373c4ef3a83f09c7d0a6695f0.npy +04401088-13dfb842c1944c64de3b109acc7ed8a.npy +03636649-6b9f509d91eeef913efeda73d60343e4.npy +02933112-36bfa6f0a5897be786d53ab0fe94e911.npy +02992529-dd996020281c929f73caa5ba625b1f4.npy +02808440-30247fa574c0f87b35e6699e9332d49d.npy +04530566-3cbb8096ac9bef3533ffceb8a4acbfe1.npy +04256520-9adffacedef7ae4219fb4103277a6b93.npy +04379243-39b851143b4f68ba21d25a6a55757584.npy +02828884-77fac848d4c863b2cb2a965e75be701c.npy +04090263-13bfc7f0f9fd39f73a6842b1f893c19.npy +03001627-25b55c1686d6114de0f3ac5d28aef4d9.npy +04256520-60fc7123d6360e6d620ef1b4a95dca08.npy +03001627-3187a69dae9fd8dced403132b02528bd.npy +04379243-8215382c95d5dc0a5c6a44a505804654.npy +02691156-b9f486be9d0160349a6e43b878d5b335.npy +02691156-7006c5afe5175d76e69ef11112d71da4.npy +03691459-982f52d3117411a37ec3f7c14c03a92c.npy +04401088-479e2ed536698d478f257ecba9a6ef8.npy +02691156-fbe788465e564e46bc0909d98a1ff2b4.npy +04401088-a82fbd031a79f88eb6d41c42f7ade8c8.npy +02958343-c08d4483e70f02e5322b377b3e7c8ad8.npy +03325088-a76a5fef802be0b5b362845c6edb57fc.npy +04090263-2288e5e13ae8aa7192cea77f96988ae6.npy +03001627-78fbcca91324c141ad2e2a7cbbc076b8.npy +03337140-381cf26b050bf515820018801b237b3d.npy +03001627-44b317a5dc651210e76bc197b3a3ffc0.npy +03211117-ae33f2b2031069e0dc67390c888f2eca.npy +04530566-39c41184f49edccbc381729395a38d7b.npy +02933112-8f8a2633debaeb96c2b64c0adffbe398.npy +02992529-be66886215eafadd56b70d2dbf032aa1.npy +03001627-d274fc14092387c1e17e1cb731e2fa4f.npy +04090263-ce8a04e433d06b03a0ba30bb56da40fe.npy +02691156-f8d7d8331fe29f247209009cfb89d4bd.npy +04379243-cda2b04eb27a6b429ccce4c6d5bb195f.npy +04379243-7ad475266c37d4d3588d78fa7ad8e5a3.npy +04256520-b28f66155cb67bbbf182e66e17d08d5a.npy +03636649-6baa8b21a080da186fa63795f94c4d8c.npy +04256520-b4043ab6723a39f1406316a80ad8bed9.npy +04090263-fd0e1e7c62efab3cbde9b246866ffe11.npy +03001627-41896e1532fe1e63bda72093f9b5aa73.npy +02871439-a9c2bcc286b68ee217a3b9ca1765e2a4.npy +04379243-552692f06e4fb0c9ec5b06c6d7d7648.npy +04379243-fc42d63af681a927e14dcb97ba059872.npy +03001627-71372a09d0dec4f2e3837ef7356e7613.npy +03636649-ba397aa90c4af6ec98d5fc0473d00a1c.npy +03691459-c0add53ae9928d73b184474322bd24ab.npy +03991062-c85033738a03ae6a3b77ef2474e90dcf.npy +04379243-64630e265ab5e1604b3c42e318f3affc.npy +03691459-e6e7c3e1b887d2a1751b29c8fc6f20c.npy +03001627-bed17aaa6ce899bed810b14a81e12eca.npy +02828884-9795c0ce0679cacdd201085e80edb26a.npy +02958343-b6345c309ba64f97e97c6bb243ef67d.npy +04379243-47e24c3995150688d810b14a81e12eca.npy +03001627-80544a1e0e443c7d5438b83aba42ca46.npy +02828884-af264c02f69566cdf4fb4dee5181bee.npy +04090263-78e2a75ff1d93138e8914057d776d90b.npy +03761084-18234c941d0421729e8ab085b6e4d874.npy +03636649-e4d3e153ce7f9904e76bc197b3a3ffc0.npy +04379243-2b4cee8331e825806bd0aad3d992cb54.npy +03691459-63f13073406d8a2b4092d3b515916436.npy +04530566-5adf37321156a7bcbfe1cbc47170312.npy +03636649-dbfa4bf005acf00d351d9ca36f76b95.npy +02691156-9c9d6469ecdfc54fc2a9d7232db0ed61.npy +03001627-4499729e53c858ae71a782a4379556c7.npy +03938244-51f5522d1b9088e2d7465eca206fda6f.npy +04379243-f1fa3fac81269971820018801b237b3d.npy +02871439-48d58a4f43125e7f34282af0231ccf9c.npy +02808440-ef9318f2fb898812610c2a68437007d6.npy +03790512-fd53bf3eb05d8ef4312a95c7d4d74309.npy +03325088-3f99e84747ae5e0216f1e46eb2815c0b.npy +02958343-65332c9a15126b924b3ff698267962d8.npy +03046257-242d1fdad67de9d6f2543b208c9ee8e2.npy +04090263-595fcd065407f54ca97e1deede586e49.npy +03001627-3503fedf43c99f0afb63ac4eaa5569d8.npy +02828884-55619caff40ba259601104cd2d998272.npy +02958343-d43dc96daed9ba0f91bfeeca48a08b93.npy +04090263-8a071ea65e9057a1c7c8ce3bef5c2aa9.npy +04099429-d15f389919446c40d4a6ba4a33475f32.npy +04379243-de4fb391ab81be927ff6ace05b36a5.npy +04379243-57ee5654191b4265890992ddacc04113.npy +04090263-7f5f905397b76cd2304a8d13750ddfa.npy +04379243-95af60aa8cb9be066a76e23e6f966dea.npy +04530566-736e45984ce6645cda5505f71d8f8d5b.npy +04468005-f49f6eac711e7e97413710d5de208fe8.npy +03001627-61dfc04e60e3df4b4c350d7ea5fe2a3a.npy +04379243-fc7a8af42911dc77b4169e4cad9bb63a.npy +03337140-ad6624317d8af2d44c3aee8e9d3a6ffa.npy +02933112-68f25e77ac6bdea7de650492e45fb14f.npy +04256520-d4aabbe3527c84f670793cd603073927.npy +03001627-94bac9505cc503567085b4353236aad.npy +02942699-1ab3abb5c090d9b68e940c4e64a94e1e.npy +03001627-bc6499abd6192f128c605f8788f64de4.npy +02933112-2537e62a6495a46bc47fc2b7741fa.npy +04379243-8345588ba41cd2a87e4bbc5bb7fd2afa.npy +02933112-14c527e2b76f8942c59350d819542ec7.npy +03046257-b086cfa7419c820df69d21260b05e361.npy +02828884-219c0e465d55e89cad5067eac75a07f7.npy +04379243-459304c1c27aa82aa14bb1d7e401bf06.npy +04530566-5b1ef304e7a8cebde255aabfeb1b2b82.npy +03325088-240b8336c85be71750da8b99982a3057.npy +02924116-f0fb07c3592f55b2c2ae5d9462fe97f3.npy +02691156-9a0f4dd21a4ca19bf1cb19f636b1c2bd.npy +03691459-d76360da1411848ace1db673cf70420f.npy +02958343-355e7ad1d5664421898b91227342b00c.npy +04256520-569c7293b52b633814038d588fd1342f.npy +04256520-56df8103181fd18b27787a85c3bfabc6.npy +04256520-f9429d6bef2df25e4dbf8d635749f669.npy +02691156-92b7d0035cefb816d13ef00338ba8c52.npy +02843684-9ea188aa06a7a240290d6bb85a775cf0.npy +04401088-864e5512dd35164b2d477e233bc97afe.npy +02992529-e513675ffb2da709a060e584e7409aab.npy +04090263-d91e08ed981156717a362e61d329c7ed.npy +04256520-ef185107fb8d70ced06d60299de4d22.npy +02933112-19a0d9e5e036290bfe9e4fbec1f7cb98.npy +02828884-e6063d88a2b192ab56f6fc4b4ce1db04.npy +04379243-8a37a87d367ec0fa276b6f6d90ee3a83.npy +03691459-591613a69c2e212f78c0a4707b40a908.npy +04379243-71752a166bbbb06592bf3ce6b900c3ae.npy +03467517-8c9cf16672bdc795f94083089dddc4d3.npy +03691459-e08b3ac3bbae3dfe5580bd812eb6e71.npy +03593526-a88577a2ecffa8e858323e30458acc42.npy +04379243-994f6d12ab22d187c03d8b4214ec06e9.npy +04379243-3e0b8992e00a327bcb2a965e75be701c.npy +02958343-9d82d5874349f623d834dead2eb68d68.npy +02828884-9b15c79ea9ddff8d5065e2a2857d7fb3.npy +02818832-1ef20a206e940a4bd79d7db7b8ed51c8.npy +03001627-30363681727c804095937f6e581cbd41.npy +03337140-ccbe4636d7a55cbd7a50afc9c93f8a50.npy +04401088-e8e9617b4f7247fa3578fcb734a22822.npy +02933112-2862558059dd584c59350d819542ec7.npy +04225987-303555f1c5f4cb0a1082f2ea630bf69e.npy +02924116-d92a10c4db3974e14e88eef43f41dc4.npy +03790512-d6bef9011ee021c677b7d0d4764c121d.npy +02933112-283fed24177526de7eee615e75bc3b77.npy +03001627-91f867d862e6c96c3ea242d1c18c3489.npy +04090263-f5ab909cc5813c7ebe8eb764bcb3c31e.npy +04401088-e6838870d0138aa43b995d74ae757c1f.npy +04379243-9f732b16a7faf3fbf4052eb4c07f564.npy +02924116-b6451e8ac7d3af0ce7132c57a8d37e4.npy +04379243-50fdd5311091e5d742d09291b1705b96.npy +03046257-f1e9b69dbcaa8ca84b3c42e318f3affc.npy +03001627-63b84cdf260ab81b14b86d5282eb8301.npy +03593526-4ed93b27b2b1ae4a17d01689ded74b74.npy +03211117-d0959256c79f60872a9c9a7e9520eea.npy +02992529-8ec44fb44e4a3224795284068bb430b2.npy +04256520-669568cff92228b4e6fe3612af521500.npy +02691156-92e2aee5e86c0fc870d98a97e17b4da3.npy +02691156-d78a16856adad344670aaa01f77ae41a.npy +03991062-dbd112b601a9d91ce651568bc8a2644d.npy +04379243-e8d505c5e89f313dd42ec7e303174a87.npy +02828884-567779d7087c75eead5067eac75a07f7.npy +02992529-d9ce2d0be1f3952aa36bec4fa7cd58c9.npy +04379243-77a683709892e56fc535a1d76df92ef3.npy +02924116-7c2a4413154a1725c95c7a8a79dc0c72.npy +02946921-4961c651fdb6b45fa57e04ecfc2d7abd.npy +04530566-5b00c251f971aaa437a692cc86ebcb7c.npy +02933112-77ead277434621b5343087e1efdee691.npy +04379243-a9fcd41e05a12a0d7e1dc03b595bd36c.npy +03001627-5ab321d70991c94d780bc2708a85ba9a.npy +04225987-58ae991bd0350810b9ac379f661f5c75.npy +04090263-f53a4093fb00a490683e3750b53385d5.npy +03001627-2e291f35746e94fa62762c7262e78952.npy +02818832-b765b2c997c459fa83fb3a64ac774b17.npy +02828884-72dfdf42a06d55f61985df8e5a34361.npy +04379243-3b72f2c31c5aac6ab3421b3649fb16c1.npy +04090263-282f9e161a0bbf58fe00453e7ccbcad3.npy +04379243-70995336d06fc07ae9f3e9c758fef992.npy +02818832-fd1f49ec5a690d53c3bd24f986301745.npy +04379243-3d08a0ed3ba94fca6652506d959dc71d.npy +03211117-f1b1a1badc8ed7e739d3eeb007af69a3.npy +03001627-4a0f1aa6a24c889dc2f927df125f5ce4.npy +04090263-255b002258e74085d735fa1ab17311ec.npy +02828884-e03e7aab2967929d3fdfe80ff0b57538.npy +02958343-5fe3753b18cb01ae1b581e1887fa67b.npy +04379243-8374ea1c4c032ec8488ef35e8e3ee601.npy +03001627-40168f46019eb867be7e1d42d63ca9f0.npy +04379243-ec565aa9b442ac36ae6afb0c7fa710a4.npy +03211117-b13c22f9eda41f328c504ffda4ce2aaa.npy +03046257-955b66d63d6a92f5132fd0b3f17b0d6c.npy +03001627-98d20227789f5c9a5af29473330f42b1.npy +03001627-7bebd3cd1be32a0646f7430ae2c8ca51.npy +04379243-481e479cb50f251a7cc7de242a4585fd.npy +04090263-faa1fb485ddd6c9c8bfbe54b5d01550.npy +04530566-e3fe6f0e74fa641c2247d987054751d2.npy +04379243-9477f34f16c650f7cac9ba4482ce0612.npy +03691459-88bafe4a96ff3348dd1080d43103149.npy +02691156-e87902d01d40c71521b1ceea9c93aa79.npy +04401088-5c8d554075a904bfa7ca3fec59d82214.npy +02958343-2d8b8d98d4e3c76e3000d241e527f650.npy +02958343-5c542cd5371a631d6436916a86a90ed7.npy +02933112-55d1668a7d33f8ebc0b2397831029b54.npy +03636649-d466b21fb042a2ac605afa80919f9592.npy +02958343-4c60f32b6efdc7217dfb1ee6a4b12bf8.npy +04379243-411811d0fac7dea18705931e60ead6a0.npy +03001627-32b7f9324c56d6131b02cde7e81f0fc3.npy +04379243-e5eb64f97f6161ebf51f77a6d7299806.npy +03325088-b405f1da8275fd1214b35a7d7cea7130.npy +04379243-14d0926471af661e3087f84b199fd297.npy +03001627-7252a2c022a1a3b21f285be552b78f9a.npy +04530566-fbc2e96b16209642fc86577bf738024a.npy +03691459-eadad629c581c28c6b424c689f1d711a.npy +03211117-85395b5f99177f864311b8458795b94b.npy +02958343-3e37a76f38d057cd3f823401cb5b3c88.npy +02691156-de65da5cdc92b4aebc0909d98a1ff2b4.npy +02828884-42ffe8d78c2e8da9d40c07d3c15cc681.npy +02958343-30feb9f00597aa2a3781057335c8a2e8.npy +02924116-41fa4235493cf5d9acef723912f2fb61.npy +02992529-ac8d3abc6a6f7a939260029564d4cf0.npy +03046257-788ec08ac9682254f504bfef7c734006.npy +02924116-a18fd5cb2a9d01c4158fe40320a23c2.npy +02691156-eae845d4a7945ecaf2e466e56cb8c63f.npy +02924116-a4617051ca47db2cc29b99b0b80dbb7f.npy +02828884-3e0694b77418eb25d2b12aa6a0f050b3.npy +03001627-2b55385a63cf62f6bababe11fcea8796.npy +04090263-aca833639091b256922309b37ed10e7a.npy +04379243-34208e6a1f53551366d6af16d45fa132.npy +03001627-485831d92925bf03f3d7c13662c10792.npy +04379243-7a7188e439a39ffd9a2cc6d7b7b4954e.npy +04090263-c45c9f4ede3246e6a54581b3915c3bcf.npy +03001627-b88d8b5e5fbee4fa8336a02debb9923b.npy +03001627-ae6770f159b2f7c868c51305d76b1f8.npy +03001627-c58f6a35f86a1802e8f8c11a24c52ebb.npy +02924116-398bbd8bfc14e9d8df98386e2670b45a.npy +04256520-70ed97376be1d0a84301558fdb0b2522.npy +03211117-90d97637c01fd05e59122da3e1ccb92c.npy +04090263-72b28bc54158f0d512b38b1d99376c0b.npy +02933112-a2dcea3f88c397f487d0ef3f1f8b9c07.npy +03325088-bafb5f206f100bffabd7f138f3335c2b.npy +02933112-57041ab17b34eba1f49237e570f62c8f.npy +02691156-acd8f367c36a3d84fc7a6d75b3d807ff.npy +04530566-1356fcf0ea4a95bcbe7ca2216dc1576a.npy +02933112-56625ccb6e7dc3fdc59350d819542ec7.npy +02958343-f24129eb2169197c203f35d9b3b48203.npy +04379243-f2c4fbc0c7c9b87d961b3f02493c4f73.npy +03759954-506f9ea22fc92da4161e123a102b12b.npy +02828884-7139a01aa4fd148b7435838026088e5f.npy +02808440-b16eae893bd12a87b8724a732b3d4cc1.npy +02808440-5e07cb24ec93904bcc6434361376a7a4.npy +03691459-d3e279ab7bb0dcbb85d9d97241397921.npy +04379243-d704a2ea75d8a2b3507969980fe06783.npy +04256520-1210afeba868a87bf91f8f6988914003.npy +04379243-eb6f0eab4203ca0e1c19e7863a1c200b.npy +03467517-7e6d283b6c6728ab343b0b12983b9982.npy +04530566-e19c3bb778bc8e9ed372f295778d1591.npy +02808440-3b222c644a783ebbfcd4910413c446d9.npy +03001627-713d651528ade2516bbe7b731c00d0e5.npy +03991062-28938abdb2114e53bbc7a6acbd8f058b.npy +04379243-f1a6dd0d5d9bccf3825a5bc524f67c9.npy +02992529-ed004bce9e457ab037c7c775913296f5.npy +02958343-b3be6c7fdc27043ad63a36acd73ebb29.npy +02691156-483207a72a39129771d03b466c72ce41.npy +02691156-3547cdf24eeabdc925194e2abdb4c403.npy +03691459-324c0e25576498485373b650bcccdac6.npy +04530566-f90a485c72b6047b102edba1bfa321c4.npy +04090263-c0b2ff6229e1175aae9e1c81f7e5b0b6.npy +02691156-1354e0acd354a3ddb6670e1d7042072b.npy +03790512-532e6f88a9975a27b37378f3c85478b4.npy +03001627-e8c8534a16d600ba20685b5a7e34b501.npy +03636649-9896b288bc97e6556bcc48b8d936ddf4.npy +02691156-e521828113e1e0c45e28caa3b26a73fd.npy +03001627-u1e22cc04-7c4d-4ed5-bda3-8ff8067f22ee.npy +04379243-4c51b04b1b32ddcc4ef96d1bb8be503c.npy +03467517-4275faf3b0234007f03058f020a47ca5.npy +02958343-ee63549013035c385e28caa3b26a73fd.npy +04090263-d400c42c4c4b3ec1589c07868201b17e.npy +04090263-175ac778b726ef5d48cb5e52f6edec2b.npy +02933112-8b23fc57517a57d0523cc82298d77b36.npy +02958343-7e3237619d96b6e551a95aaa6caba1d3.npy +04256520-867d1e4a9f7cc110b8df7b9b18a5c81f.npy +04379243-2568994ff8112b6d65daa37b7e13aee8.npy +03948459-79c0cac016998c7cf7ba4a82f8032357.npy +02828884-1f4ab55de315d6aa7d77abe0f9632d4.npy +04530566-fa63720ea3f8bd379a6e43b878d5b335.npy +03790512-59c019516149fe33d5dde04c96fd8146.npy +03001627-80ca57536dfe8de971a782a4379556c7.npy +03001627-758b4dd493ebb4b34ec0aa53d814a8cb.npy +03001627-96b2bf512fcb51b2af7a8f97983e7906.npy +04090263-bc187370b495d54b4c82ce83dca284f9.npy +02818832-ba690c29eb60a5601112a9ee83a73f73.npy +02933112-a992c3b41cc3027a9e1c34656195f3c2.npy +03001627-cea21726757b5253c3648f83bb1262ce.npy +02871439-aefad6690d1382d675f9535c96844dc6.npy +04379243-66dfbdb8c35a6db779bd5cf8fc22cc7d.npy +03691459-5aad6776bda34de6831627e12e4fbb8.npy +03691459-a423a97b5758a266d747b49524a1246e.npy +04379243-389aab2eb6debceea5a5170d48a648c.npy +03001627-5afc95ed2a26ce548644074928ab3f32.npy +02992529-74aab120cfb4d88257de0221db0b9d32.npy +03001627-a18156a0e60e50391f4c17ff3c45b28e.npy +03624134-bcc178786ae893835f7f383d5cbb672d.npy +03325088-b9aa61770fa227bc6d0157e3e7a8917c.npy +04379243-1bd555bd6f08c5f4f90f8519e58d5382.npy +03001627-90c6d1df1f83329fe1181b0e584cdf9b.npy +02691156-5dbe5dd200fc214951971f8370d9050.npy +02946921-990a058fbb51c655d773a8448a79e14c.npy +04090263-938be7a1544953152c3271e911ffe19.npy +03001627-b490ed3bdc9debe6cad73d9df5957ce.npy +04379243-f11b09dd3782f084f78bdf37d618e97e.npy +03001627-9b52e73f96d181969cd431573238602d.npy +02691156-efc9cda06afcd8c2354ab1decf4fe605.npy +04401088-3dd3ed204c56943389e13811ad04f53f.npy +03928116-4d626fb144471575dd54cb5398e1f0b5.npy +03046257-c50629ffd5def0793b407f4857c15d98.npy +04379243-625c161306cf958eb000f20a5153622c.npy +02958343-7dbf6379da9fc6c3a4ee0fb6a51564c3.npy +02958343-7a228c811e7e18ad18e1879dc4ad8784.npy +04379243-3fbeeb56c557e9d6aca1a38908852eab.npy +03001627-280553e975d6b79fd2b12aa6a0f050b3.npy +02691156-bea43bda17ea2ec792e07599d5caede.npy +04256520-bb529f670d4cb04160d8f573d6badb2c.npy +04530566-99b9eb5e1a7dd3b9e4614310319ea50.npy +03797390-35ce7ede92198be2b759f7fb0032e59.npy +02958343-82c224e707f63304acb3c21764457201.npy +03467517-bac2a7eae4f7d1a8dac47853b7da5949.npy +02691156-a1848a4a69b14704ca8607f540cc62ba.npy +04379243-c35990badac37b256c09970ea0def16f.npy +04530566-cb497aa6439c5a058c8c82196ef75032.npy +02691156-914c308ac4a9156842c20743f866e1a6.npy +02958343-49e4cffd7736c34362b21e1bf23b9ba8.npy +03593526-198a821d967679684b3c42e318f3affc.npy +04530566-50848665c2b2d6f491347c63d1dae43c.npy +03513137-dde4e367492ca88bce01c07526cf2aa4.npy +04379243-61a898c20ddb028dfebad4f49b26ec52.npy +02828884-46bae1672b4d146993a6b3a551dcb739.npy +03001627-482afdc2ddc5546f764d42eddc669b23.npy +03691459-c4733a08e1fc82373f48f08f97da0e7c.npy +04256520-46c6d2fb8c92cba419fb4103277a6b93.npy +02691156-ed4aaf81dc577bedac4f72bf08dc79a6.npy +04379243-db969c98e24511cc98cfd47a860803c5.npy +03761084-aeaa5b0ad8e5c786a805114916841d69.npy +03691459-da23f8427db17c3c627a66821130f814.npy +02992529-1b41282fb44f9bb28f6823689e03ea4.npy +02958343-71a1122469df0bb8cc8ad0deed05da5c.npy +03467517-862247de086eae853f0e01549eab8c2c.npy +03642806-9eb06745445806576e14170ade57410.npy +03001627-e66ee381e20dec3a44f23566597ec464.npy +04090263-a45b989db049e503a04e41b7ea7de8d.npy +04379243-98578539ae351bc3876b50fc31ccedf9.npy +04379243-fe5f543fd0c6b34edbbc9440457e303e.npy +02933112-9623560560cb59a3d37a1bae74ee50a2.npy +02801938-a642201d64f3a2adf345c3e267c3bfb3.npy +03001627-ba673ea75085e46cbfd72d7396bc040a.npy +04379243-bc3c03577d04c17a8dc9009357301fae.npy +03636649-70c523d337585b9743dbb6421d614c0d.npy +02691156-c4ed630f9c0f728090b1d6deb98feec6.npy +02828884-94a2f3859ed66873d2b12aa6a0f050b3.npy +04379243-afd9337f23ea759b54cd2a0ea6cb618b.npy +02958343-8d6de65bee9c269bf222d93492cfe0b9.npy +04379243-df7b982169a2d36fa8d8da6771a88b8f.npy +02958343-793a8675d7a5fecd653effc8a32f84f1.npy +02843684-8fdcf46df1b30e1179f82e70cc0e3b57.npy +04379243-c572c44eb47c2a15c43d2b61614d0d0.npy +04379243-a3a4cda9949c347ddb039d8689a74349.npy +02818832-8ef4ac16aaf7daa9a95095163012e0b6.npy +04530566-d188656d279f4d8b94daa4565dd30535.npy +04256520-6900b73a93136591bbc7a6acbd8f058b.npy +03001627-4d6f35e7eebab44e2c8a86aeeb3b996e.npy +02992529-71899992cbb987ed5baadcb81f14fd84.npy +02958343-372ceb40210589f8f500cc506a763c18.npy +03207941-b904af827973a59977e1c4f3e3547f0c.npy +03691459-5944386805308443cdb1aa1514be92ab.npy +03001627-49e8ef75b5ca2a7c699012d4a63c792f.npy +04256520-c446a77a01eb3e59a6380f3fc7269ff.npy +04090263-d5734bfe7c57d3bda1bdbe5c0cfcf6e8.npy +04468005-c4fa99df3452e4321de75a0b04a57744.npy +04401088-5814df537b8f1bcde95cd0dc8c2f0e83.npy +04379243-5ac1ba406888f05e855931d119219022.npy +04379243-664dd0e93a0f941a47fe752318e646fc.npy +03624134-7f1cf4175b9e3b0dcc34b900bb2492e.npy +04379243-2afcecd6a801171dbe25fbd47cafc694.npy +03991062-c623808300139bc3beedb4c8fd29e2d1.npy +03001627-54b6c08ddcd0762adbbc9440457e303e.npy +04379243-2fae93478f8bb6c423a62335a5f0e6d2.npy +02691156-2117484d4ad547ae719b5362fe06bbb.npy +02876657-74d0244fed5504cdb1d85e3f9755b881.npy +03636649-c2aa9948afc6d4ed39b3360f500ac52a.npy +04530566-2458e4e41633c95642f9e27aaf0c47a.npy +02691156-6c2c84db10ba167e48464d2edba1bcf0.npy +02958343-690609438d922525ff1370452e3a0154.npy +04468005-71df29935222b917aba3295c9fb9b32f.npy +02958343-7219c2a7e7e04850374462542bf2aa29.npy +02828884-4bc92bee14e81db06c262ba0bee45d20.npy +03001627-2343e2c4fa69f33a2ff834514c92e8fd.npy +02933112-5b04efb9a9e392f7f51f77a6d7299806.npy +04379243-de077e0bd6932baef12d7184a2ad3430.npy +04379243-fd958ba5f3116085492d9da2668ec34c.npy +03001627-2ef1e7da7f2a124215d65204573ec4.npy +04379243-4c5bc4f3d5a37c6dca9d5f70cc5f6d22.npy +04256520-dfcc3ebaa7e5ff1720768660cf080d12.npy +04379243-3185d26189034bfa48db03d58a820cad.npy +03467517-dc65ca08817cd673d0b89b8c97d1428.npy +03001627-da292ce4ccdcfb2c842c47c8032438a1.npy +03593526-9eb7d0643394a33df633d7643fec578c.npy +03467517-cc9e9ef3e1326c5363e148e250c0340d.npy +02958343-ee1f5ba95a6bed7bbda733a39f84326d.npy +04256520-1824d5cfb7472fcf9d5cfc3a8d7af21d.npy +02691156-7af320cedd724bc89437816457a69b.npy +04090263-582ff2c7307daccbfae4699de9cb91a.npy +03046257-71bc557e3b154c037a24ef313a983026.npy +04379243-ff60e4b29c5cc38fceda3ac62a593e9c.npy +04468005-b2a72df72812b0edc50a037462bade42.npy +04530566-395471e88200756d88d5590328ce0ddf.npy +03001627-90e67facc9af413abc19762eaa7ba40f.npy +04256520-1a04dcce7027357ab540cc4083acfa57.npy +02958343-cf88ac755b07beb2becf71e2e014ff6f.npy +04460130-9151fdcecbac4d2fbfde35fcbc037c53.npy +03790512-8a9586b8eff9f3a6932abeb6e2fd4072.npy +03636649-e5fa327c14553b11e589b08489d157d.npy +04330267-e7bf4ad72b1ad9b69c436f89fdc07cfa.npy +03001627-521f0ff0b1d7828337b2bb75885cfc44.npy +03046257-d0ca6059273922d25daff59553183e5a.npy +04530566-d152611e5b14420460e26fdb6baad14d.npy +04379243-9f1fcee83cacf964f4b6538438a0b930.npy +02691156-464a8718f0e81ffd9a6e43b878d5b335.npy +02924116-884764173de226d8bbfc16c72fd24829.npy +04256520-791f224b44cc67b084a05e54516915de.npy +02958343-492a339ce5da3fe8e4b68d3b17c43658.npy +03593526-e7c29b8c7709187d42526f5fcee84e09.npy +02691156-9a04c7aa6e1655fc90baeef8ba5b93e5.npy +03636649-d21f149ace9ed2ffa3714990138052c2.npy +03991062-e2a90a8a9c24e8fb6f30d3298af6449b.npy +02828884-44facd26b66e6ec8cf0c8ab22c613984.npy +03624134-d179811d0522500f881796c365ec5f7e.npy +02924116-97db0ea84d0fe5fbe14cb463f23a6803.npy +03761084-479af1fbc8399fe47608168119193cbf.npy +03938244-a136a79481238e046d3e11439c6c22c8.npy +04256520-4da74e02ba23a7e98ec703e791db2af5.npy +04379243-12dfe5b5c7acf776beedb4c8fd29e2d1.npy +04256520-d7280c7d6dbb6f20ff12919fb1541da6.npy +04379243-4cac98acfd5c43e1f51f77a6d7299806.npy +03001627-9e6b834449ed2db86199d6fe090be061.npy +04379243-d485cc87ba99e2caffc6e457221b9271.npy +03001627-3928ff39e32dbddbf91663a74ccd2338.npy +03636649-edd398530cff676282bfcd34215ccfc7.npy +02933112-5abaee58835d67975f9f6f4c95ed18d0.npy +02933112-4c44e4124118a2521e4b67452ae5160.npy +03001627-e491dc151c8e801186abe5555a3b447d.npy +04379243-63c93cb827f004c9c738b9c67433b6a8.npy +03001627-993dfc1874d17acd08b731e9ce099e7.npy +03691459-b1fa05d508d9ed81753a010738a20397.npy +04256520-c0d3ed00259b4d9da326264e704c832e.npy +03636649-352d68b2a816640099e8bf807e902261.npy +03790512-8cc21006e2d9f38fb4f2746c8140d6d6.npy +04379243-980ef88f896e4ebbe6cbbd79676d8c68.npy +02958343-8976e05f72b43a742a9eb0f146e94477.npy +02691156-d9d39f688eb9ba58b3f2b01de37c0b29.npy +03513137-f04ce9786ba0364b6e686498ed562f91.npy +03046257-7dc182e052ddc140bd332b3f93481432.npy +02958343-20649c88556a7e7a113ef105f1affa3f.npy +02691156-3265b621ca222d29d00d52e62bf14ee9.npy +04379243-cc3f1a06508f2ebd1aed2875db0a8711.npy +04379243-9551ceb9c3d5013284c687cefb7c213a.npy +03261776-4f9e3eac5026bdfc50b69fcb22e78050.npy +04379243-98fe480bea8f8f0486abe5555a3b447d.npy +03991062-8111c4fa78c69d7925ebd1cd0b422e32.npy +02958343-12941cb870df79b9815337ac44abb964.npy +04090263-68333b503766aeab6171d14862875338.npy +04530566-7c4b6e4ef996f109a2b4e6eee41ad14a.npy +03691459-b47ec1326b29546bce6c3ccb8279bd8e.npy +02880940-e3095ecacc36080cb398a1cfd1079875.npy +04379243-1eb459fa4f1039ef8245b0d36e16cba8.npy +03001627-71a0fe77f0bc1cf94187eeeb0dea4986.npy +02691156-783f3f72d5639597ba0d990ae229b477.npy +04379243-79c5df613523a462d42b9650f19dd425.npy +02876657-f1c0e107dc158727a8360f05ea0a1d2d.npy +02808440-beeae670a6ed2a4cae5f116398936abf.npy +04379243-f9a9c8e70b6a2b31b20aa91e9e90c311.npy +03636649-c5a69f02323e087181d0740b20dd8fd0.npy +04090263-2d81e10114fa77742c242e8cf15917cd.npy +04530566-1baadd62642d9f03a134736201a79843.npy +04379243-4175d6f2d66c2e1353c1d159a8a8422.npy +04401088-c70daedaade33fd0fb24e6a63c26ad2d.npy +04090263-9586fcb3437ab068e1abf5082bc04e75.npy +04256520-eafc1a44c43b48b24b3c42e318f3affc.npy +04256520-234ba0e3cdec0c306512b7b24f3d84.npy +03207941-e700df968d805f9722c3257bdf875d06.npy +02880940-ae5c7d8a453d3ef736b0f2a1430e993a.npy +02958343-86736cf3dc841eafde5db5d0d11befd1.npy +03624134-aba3ccc2f015ab2cb824d0a927927209.npy +03211117-96c87c372083e06e9ce9562d3c10079.npy +02691156-3fba2f3ea21abb4f8c1b0ccac3d04f1.npy +03467517-482b8b9a225b6ca1d57700c05b1862d8.npy +03001627-88c39cf1485b497bfbb8cbddab1c2002.npy +04256520-423d4e5cadc6dbdaeaf288f952624966.npy +04256520-a6054a189eb45e30672e57a20276f6e9.npy +03325088-591f34168e565c1f1f195495a075a72c.npy +02691156-7a794db8180858fe90916c8815b5c43.npy +03624134-e2a838d9c35af903e332fb3cb6ebe50.npy +02946921-60f4012b5336902b30612f5c0ef21eb8.npy +02773838-30bf69aa24dbb3fc9de193e488fc4dce.npy +03337140-fe998d14e236584ec123147a914238ea.npy +04530566-9119eaa9b5996cd3b1bb46d2556ba67d.npy +02992529-f8d97bebf67cad12a0eb5a85db887292.npy +04379243-69c655d9411692a319fb4103277a6b93.npy +03467517-87650e8ff3d85672381b7fbf79296afb.npy +03636649-ca5d8536386d31d0dd90cd03407bb536.npy +03001627-eae58f128191381de9efec56e07965d4.npy +02933112-5ab3129036e7b69e278d386bfa54545.npy +04379243-1a9ea91307d15d91f51f77a6d7299806.npy +03710193-39728a7708d1b4bef7c06f0b26f28b7e.npy +02876657-d30623112e58b893eee7d6dab02eb061.npy +03691459-2325005b09d12b2585d624cfcd9a37a7.npy +03710193-e2e38e29cc30fd208ae1c1abea367249.npy +02871439-3b2fa4cd0b774d13d3b55643c9c176f2.npy +04379243-b5a2a53b9b7e16e6b85cd7b6d43e8edd.npy +04379243-6b58fd8948d4d34851581925776a606b.npy +03001627-799de8b0527ea329c725388bb41d64e3.npy +02958343-ecf4e8f49102db90a27a0cbcc84ba703.npy +04256520-cba1446e98640f603ffc853fc4b95a17.npy +02691156-b9794f4722f565e319ba010ddb4974fe.npy +02992529-6aa3eee6391336c821844676433a0aca.npy +04256520-38fed916a35dd43d7c8c503b4b873379.npy +03001627-3358536e8e7c416ea9ef8e11754eeede.npy +03325088-94cf19d3af4620d176c18e71fd49c4dc.npy +03691459-5efa892adca22d37cd8f3fe9ca2145e1.npy +03691459-d14285fb64811217e50f6aaad9a07bc.npy +04379243-f3d5911a52b16bf78bf1cb9ea68ce0cb.npy +02958343-f48659c519f422132d54e7222448a731.npy +03001627-351705e42490c3506764a784715fb668.npy +04379243-7580dc6788ab60123fe64ec32ae84891.npy +04090263-be0024e025b5d75024c5c134cb8fdbe1.npy +04256520-978ab0578d8691ceeaf7fa9cda77a592.npy +03636649-e8927203fbdbe320c02170c33e00ea64.npy +04468005-52dacb5f2a7118d2aa28dc6884266713.npy +02871439-364a2a1172dc0a827c6de7e52b00ebab.npy +04379243-f94b4fa5703a0d96983ba8b03ccecdb9.npy +04379243-34303ee69f402e0f2b931201029bc76.npy +03001627-71b3089481026a9e677db18592980bcc.npy +04256520-fa279ffe1c3d480e4b48bc115078129b.npy +03642806-58c9c43b8f4c39b25a9aadea699fb864.npy +03636649-dadeb9844d9f0c00f6da603e92626bf9.npy +04379243-5e409a2627f7cd7d63ecd64ef0e6814c.npy +03001627-72ba6d6bdc6aeb7d330a170e9ceed373.npy +03325088-45418a76d770945552bf76ac5fcbf05a.npy +03001627-9da67fff6ae787b2eb0f0bdaf192ff28.npy +03710193-95a442b63317a572148741ff87dd06fd.npy +02691156-639d85cb4487bb0e3c326782eb2d380e.npy +03691459-58457267e0a8e3eccd4a817c9d7b9f3.npy +03001627-69aeeebc9a686862cbacd8aaf9fd8072.npy +03046257-670df65cc7db261f1f6dfedaba98d5f9.npy +04379243-642fa34b5b7c5e5414c0d1332b864458.npy +03691459-d05deb21bcfffb07fac7130d270bddce.npy +04379243-651560f344dd987fda6f0c2ce3101382.npy +03636649-3ccfbe8b56a3b181276206fae5d3c473.npy +02691156-e60b86c7a4015490e5a760ec65004efd.npy +03001627-29f890e465741b7ef8cb9d3fa2bcdc0.npy +02747177-7e1b27b8df1f9ae8ae868ec20dc7b43.npy +03467517-538a397c8bb811f776d05024fabfa1e5.npy +02958343-6df1aadb0dbc696cf568f785e33a81d8.npy +02958343-6d3d67957e1ca228ca92a4cdad802b45.npy +04379243-58611e7338c17f2bde909714df3390c0.npy +03001627-650d540bac31f56ffebad4f49b26ec52.npy +02876657-cbe88d4a56535ba64e23e9314af9ae57.npy +03001627-20a128166fc9ac939240a35c2a5f105d.npy +04379243-c503356361873b89730cb37c9a5f63b.npy +04379243-215dd9e926305bb7f8e7f2c38fe37243.npy +04379243-e3cf80e575ddbc03d706ecb3379aa341.npy +04379243-74239bc42f23639f3ea6912ae089646c.npy +04379243-82a9838fc655d7f62e6da3d97725a350.npy +03467517-a132eccaddb5decab7a841fa7c24140c.npy +04379243-67ac830369ffe09b664b3b9b23ddfcbc.npy +02828884-323ff904411c3d427c64e9314d548016.npy +03001627-1efb3d9f1cd2499c5339eb67f6086a2b.npy +04554684-ed34c7ded72ba0a346cde67a6a1ea328.npy +02828884-d0c64a8b3fed1ba113736977841a6b9b.npy +02828884-ea577ade393dcaaacb2a965e75be701c.npy +04530566-8faf5fbe39f67f3dfa2eb3102eea4e72.npy +02691156-5aec07305ba4bd3d66cf1b4a8fc3914e.npy +03636649-5c9595253f292e154ce3bd4e27d8e100.npy +04330267-47c68395a5775e10d9deb3f829cc2475.npy +04256520-79fba03fadd8c00ef10b04ee8b1c6914.npy +04090263-79008976055024fa93cea328065cbce9.npy +04256520-294dbaa0e9afde3a35836c728d324152.npy +03948459-75363128f211014a42426cd19697880d.npy +04530566-7aba61c9096ce60b7002bddf0942f8e.npy +02924116-101fe6e34502a89952470de2774d6099.npy +04090263-197f8aac538b6f7327b14e46288c9d26.npy +03691459-96778a7607802a72ce1db673cf70420f.npy +02808440-d7d404ced8414f01a64e5c46abb30c70.npy +02933112-9c802e8971c1b25f480fa521a9c7198a.npy +02924116-3d6c2c05de399202cb2ecbd32dc2119e.npy +04379243-2ad18975be0934bfa93e942a054d60b5.npy +02933112-75c4595a4d1c3bf9fd2b139960f72a73.npy +04379243-e2869255db01d51df577ff4de1ac394c.npy +04090263-fcbfd6863b56c882dda5b2729f8f3c68.npy +04379243-ed963e8e0589eaa5490ad276cd2af3a4.npy +03991062-5e914dd726313181b1b4b514128408b0.npy +03001627-4f1e026bc520de13d66f9962327b4367.npy +04090263-b40a96b48a27dbed8f38658d7fd17ab4.npy +02992529-5828a8259ba570bbd24e3068806a8c67.npy +04099429-b7e7c5a838c33f19be4274edc10c1c8e.npy +04256520-ae9d32ee01af191a32dc1e76c3474bc.npy +02924116-c3c8e100b3c10f80ceeb72b524f3e0ca.npy +03337140-dbf34becc9a4e4c34c3aee8e9d3a6ffa.npy +04554684-2d856dae6ae9373add5cf959690bb73f.npy +04379243-4ef54a72580df356d5617443b3fe2227.npy +03325088-516eed82a6a512d6b362845c6edb57fc.npy +03636649-e001d10c9aed09d9947a4fb398a91722.npy +03691459-e82622f52b46e31df4e3932877a139f0.npy +02691156-1f3fd9b2ce99e4ed164ee3a88aef3755.npy +04256520-605fd6f6541ca57de56133f0e7d362b6.npy +04256520-b765b2c997c459fa83fb3a64ac774b17.npy +02958343-2b18b149cfccacec1d4fdb0e0fa715b.npy +04090263-7fe56b2c6ee7d118994714b2bc8b41cf.npy +03938244-a0903daa3dfa996837b2bb75885cfc44.npy +02958343-20a3df3de67f309d8e35db9103756ad5.npy +03001627-a27b9f94d052176af27383fc5a5a711c.npy +02933112-6a49166d5852d23044221bef0fa3c36b.npy +02818832-d776c6eacad7ab019c57c7eb44b963e.npy +03761084-49670b80947d34aca7f79a2a8b5d6e7f.npy +03948459-10f7179292b04787cf335697521a6511.npy +02808440-98f774d812a2ff0022f427296d72cac2.npy +04256520-fe79eb9d45cfa9c5ca7ed590d69b9804.npy +03691459-f452418d7be7e78eeb752889d5199f9f.npy +03001627-36bfb3be47fd957e543087eec55f714.npy +03211117-691ed09923a0feb95adfd0d9df77c16d.npy +03642806-6123321e3af0b6328204b359ccd3949e.npy +04530566-efdfd88f3fcbc162b4c316c21a905ad4.npy +02876657-f9f67fe61dcf46d7e19818797f240d91.npy +02871439-ad6ba923084a6eccbd3049064a592667.npy +04530566-9d737c1e2872b322d2ff3af4b7716b6.npy +04379243-862cf2d35bd106c55230ba3c88b645e3.npy +03624134-cb95eb6a8a62cb46127075892a2f27e9.npy +03636649-864ecd5e816326dc2da4b3ec05850371.npy +04090263-5de0665cd8e490f47de08b76f60612dd.npy +04530566-d7b1c89328c8f0099c42421cfc900873.npy +02691156-de5807cb73bcbbf18587e940b916a22f.npy +04090263-82267e9766dabdd653fd2f31e6ee4fc0.npy +03325088-4a77b3d8bca397c5f6c00faf69d13ed1.npy +02958343-ce8dae15de55bc57ec96068985a57399.npy +04379243-357d9c5b669d6aa37ec818a4524845f.npy +04379243-72da00b4d8ab22bda571da3abf5b1931.npy +02958343-876d92ce6a0e4bf399588eee976baae.npy +03337140-a71d07ab8246c80391c352d02061b3f7.npy +04379243-65cceb90a30f7b15bf6d866879baaa7f.npy +03991062-9c06b546a29ccb2f2c27670a86683659.npy +03991062-844323768c81e72794b3ff00a3f2269a.npy +04090263-a4d1ad2fe0d98814e6cbbd79676d8c68.npy +04004475-af7b8202bf769382ce4ad3e55837155a.npy +04379243-d416139067bf7db337b2bb75885cfc44.npy +04090263-7eeeec55dc10e1bcfa9286f039319ff7.npy +02691156-e27229a5f83b0ac96ece6611a5309fa2.npy +03261776-ea885955cb82b3cee074faa875b76f82.npy +02691156-6a59f581ea7f33a5700feb5468ed9746.npy +04379243-4707256a1f8fb862a8bcbe9721909844.npy +03001627-40e2ccbc74d0aae3b398a1cfd1079875.npy +03636649-bea6350707d0813c85f486468112b4ec.npy +03642806-949388e7bddc1b02c60ea5009df4047d.npy +03636649-dbd8677c25a60799a10831b4711b98b9.npy +02992529-975de17c0b5d96cda38e5bd2fdb10d11.npy +04379243-fd1573fb1fc4a99b4c161851ed2b4e4.npy +04379243-ecf9321f6fd98688f88f925b568f2dfa.npy +03991062-b8f273f071041f694c6c80caaf15808d.npy +04090263-f02cf5cf3a6c61c7d735fa1ab17311ec.npy +03593526-baa918c56da0512da2c59a4d90e63212.npy +04468005-903584d52613647290df764ad314c67f.npy +03759954-47c434d0a4a571f64fdb7f619836e43d.npy +03642806-40935d32976b7dd3c8ed5bb8c3ee3317.npy +04004475-775d7562a64bf1c58b466382c9d6d096.npy +03001627-545e984b290a7398e8b2b8dc0c816caf.npy +02691156-df9d8ab5ab6f50ed4d4cb1c2a5e48b7a.npy +02828884-2b529b43c73da6e92056b4bd5d870b47.npy +03593526-56f7b662be65b7824725f67267e31c89.npy +02933112-a80ad4eafdb304edb6b975d10a10702.npy +02691156-804821516ddb3203c6747f7c9ffe9e32.npy +02876657-f6fa8cc6b08aaabb2aafb83519a0c8dc.npy +04379243-2e096785b8d98d4430bbd4cddd04c77b.npy +03691459-7f382d870d2816c78ff420534f79208a.npy +04530566-eb891509436863da874f0e42f84eb4f5.npy +04379243-70a2420bdd77d414820ad1ca4d3c95d5.npy +04379243-ea7dcf537a18150cd3dad974dc098fa1.npy +04256520-7598b1e15de58e67b18627bb8f2c00d9.npy +03691459-b747b1fe2a8e76bfefc97c4bab792c9b.npy +02691156-3391b6520218cacbf27ebdfa602af873.npy +02958343-38f323fd119d14ed2a9eb0f146e94477.npy +03759954-a15b163ce08749f84fdb7f619836e43d.npy +03325088-c01e1d2a113e9f65d93da2c1c55e2c1a.npy +02992529-d740b0679a9996ae56acd5d5597a72c4.npy +02691156-6b69e4c1cceb6e0681fa1ee3c368532e.npy +03691459-2afbdce92417c3bdd9349058f7c3888e.npy +02876657-7280a6655ec867d67b79156a61ad4c01.npy +03991062-62890e8b684d82c936b0f2a1430e993a.npy +03593526-a99b8679b072b0cf9b6e5e087210d348.npy +04401088-be66886215eafadd56b70d2dbf032aa1.npy +04090263-5c64271eb8c09c3a6af1f39296f6a397.npy +02933112-e2716932c4739645e0958c0e3fc3eaab.npy +04379243-7d95cbca44393d12ca39a5500b69b164.npy +03001627-77a56bf8ea88336019fb4103277a6b93.npy +02958343-2228a428bfa91e4f771592b49641a847.npy +04530566-6911bfee295138ccae6afdd0fd1549e.npy +04530566-2e447f96f152a33a7428866500a95dd8.npy +03636649-12d44fd814bc9b40ec2a7a1f5fe7365d.npy +03991062-7962092866f8088ea2c59a4d90e63212.npy +03001627-2b454a3d18d5efba615debb484b4c30.npy +04379243-d939c9aff66ee720c47a35332c17cce2.npy +02876657-328ba04ff5119c74763cd81c1b401a16.npy +04530566-6dd917d73699da0d255465ee23ab5b12.npy +02924116-a3e4fc3d00a38746f9c0f9cbb10e38a2.npy +03001627-26ab589f6838edc99ae676623bdd3284.npy +02801938-33927052606fc67a70048d788a6ab3c0.npy +03797390-1f035aa5fc6da0983ecac81e09b15ea9.npy +04379243-16bb609914396bd0fa7b9a6c80e4e324.npy +04379243-8f7ffcbcc7e8e5a4263a16a1017ab2fb.npy +03642806-6ba2cdd89db562a08329485eab7078c4.npy +03636649-74799fccd1636ce4df6cfab91d65bb91.npy +03636649-39262f1d1eb0678f71428d548481a9cc.npy +03001627-886c8d7538d9d7bde2d5f8333c552e26.npy +04379243-b68a370aadfe0b4d4f3443b22038d340.npy +02958343-f478cd5a04d2220a25af19d380ae3a.npy +02958343-bc36588d4095dc0975c67b3b1e763fcf.npy +03001627-9515e377c1ec86529b9f2eb77f5e247e.npy +03001627-a88cdbcd4fe502c743f32dd9b833c1da.npy +04090263-45a794d26abda59e49c13db2bb1e6735.npy +03691459-58db9d793ce3c2ceb0109464688ee1f9.npy +02828884-c1b8d982d97e337f19fb4103277a6b93.npy +03467517-fc76f63343050ee1d57700c05b1862d8.npy +04379243-78c577ff52f4d79ae0a0b410fb7d15f4.npy +03467517-5cbccb74c904efe49d99f2f186e46f1c.npy +03001627-e94befd51c02533b17b431cae0dd70ed.npy +04401088-7a4619d2240ac470620d74c38ad3f68f.npy +03001627-2aacbdaf7dfbc5adb1a98fe8994d06b6.npy +02691156-e74b8862468d887c6d9b5a419d9131.npy +04256520-7577bddda1f3b6de73a5c8eabcf6c479.npy +04530566-c9b7da24378152d082e68e57491bae0e.npy +04379243-7a3326ec918a44846e3c8a33c4ddf2ef.npy +04379243-86b48365b2bd587e61830bc1b4d6c5ea.npy +04379243-31b4349e405e9157f927eef536ae57f1.npy +04379243-cd224ca2a8aa04b11362d127df6d94eb.npy +04256520-58d87762038f551bf2977dcfb5a9b56a.npy +04256520-fb2bad5e3ba66eaccbc66df5fc1969c2.npy +03325088-500a24738427fcb0b362845c6edb57fc.npy +02992529-7d5180e005f1601ca36bec4fa7cd58c9.npy +04379243-4264ba880cb763d37342f7d672371a5e.npy +02691156-2af24e1c7067533d50a05a17b2f9bc.npy +04256520-2bc74fa3617de19fd5bfda5cabec2102.npy +02691156-9595693b6c0f5157651e8da9cf70afea.npy +04401088-d8071a38bb3dd8f097c8d78b9aede742.npy +02828884-7cc7a6e8e2aad387a6a7b6e78d8d5bcb.npy +04379243-58479ad882dcbbfd9d297e74104d3ac3.npy +03001627-5bb8457da2bbc722d810b14a81e12eca.npy +04379243-51c7851a252ed0ff8211891ea560a7f0.npy +02876657-91235f7d65aec958ca972daa503b3095.npy +02871439-8f0baf74e4d91b0d7b39f9a454e866f6.npy +02691156-9bf3c126d5918c41f5c7319b71bdce6e.npy +03325088-34d310b4964578f876c18e71fd49c4dc.npy +04256520-66df0b92b5712c0c917b96045c9b6dea.npy +04256520-69f6a6087f0da861af8fee88d245152b.npy +02958343-9f69ac0aaab969682a9eb0f146e94477.npy +02691156-bcaf04bfae3afc1f4d48ad32fb72c8ce.npy +03636649-d9adf06b7288f3cbac520a24f902dbdd.npy +03001627-f4e24cf8c5d0c5c31dbb0393636b3531.npy +02871439-9181c8bc52315206d810b14a81e12eca.npy +03593526-d090b33ac316a4b8bc7f58784fda27b5.npy +04090263-2eedf3a4c4eeee20af56497f051566ab.npy +02871439-a5f5552f1691e13ba5b8ca7c7b46f1d4.npy +02924116-63f691c1b2bfe5846ca2b6e5474aad11.npy +04256520-f13ce2c21e2ebba4b40f0ac0fb9a650d.npy +04090263-d33c5c2a6d3c4c64d730d5e13144e77a.npy +04379243-73bfba756e6e8511c3bd24f986301745.npy +02747177-ea90a3c6378d6f6d56f6fc4b4ce1db04.npy +03001627-b6689fb8b784c570cc514b26ccc20774.npy +04379243-8fbcd8920abcdcc519fb4103277a6b93.npy +02691156-58fcba9ef405277cfc8d2548f6ad75e.npy +04401088-bdcef95e8efb2665408f0e810863705a.npy +04530566-c521d7e4482fc7f7a716de2121565fe.npy +02992529-ae7b93f3ea4238712f20ec3aefa0fb91.npy +02691156-62aecdd1266b27935fc197bbabcd5bd.npy +02691156-3ad6bdeed351f5a84e61a0c2eaaabe87.npy +03790512-a0a40a9d5aabd6a7d5dde04c96fd8146.npy +04379243-3da823da4b6acf395b903ba10d2ec446.npy +04379243-9437fea69f0b44e8f97ef3b999ddb957.npy +04330267-139478e7e85aabf27274021d5552b63f.npy +03691459-276363a6e7991caa85dbc6e74635dd32.npy +04530566-a35aea08a3cb9391fc1bbbe626c79a7d.npy +03211117-b9b01abf4d7c9458ed756341424d6b8e.npy +03636649-a1d2f39cb17540e8988abef1fd117e7.npy +02828884-cb1ce3240eec3fffd417c7a2ac331601.npy +03691459-1e52b6d474a08635c10555abb2efb430.npy +02876657-11fc9827d6b467467d3aa3bae1f7b494.npy +04401088-c7fef6ae7f7f91814a0be3d856af9ad.npy +02958343-24c0a08cf0f7421d979ef391885ee5d2.npy +04530566-cb9ff07ef4769dba1d055b8893d6182.npy +04256520-2fb74a2f2b2b23a8a8cba409c4409ba9.npy +02933112-49485d1e98629d0c1c76f329bc4666d1.npy +02828884-84caee0c9f3b03571c56cd199c0bfbf8.npy +04379243-5bfbd0f0fb965cca9df2c4ae01002f5c.npy +04379243-f0305c34a57664ba32388c13cc4a0ba3.npy +03085013-dd369d106a5180ddcc47da24d018e46.npy +02958343-45673b0840de7daefe5083d20d7b5c42.npy +03636649-e37de82cff38f88d1735ea0e092a805a.npy +04379243-a40281aa13c75ca2ec4a754398bdb370.npy +02924116-f4d2b141c7956794378953424bcbb407.npy +03001627-88a7740602eb0d59cd431573238602d.npy +02942699-d9bb9c5a48c3afbfb84553e864d84802.npy +02958343-5d851496c2acbd8cd03e665be0237104.npy +04379243-5f226992dc83d5ead42b9650f19dd425.npy +03691459-5b22a13742fc7224079257326eb1699.npy +02691156-b04ec55f4960b3b984b7ea000aa0a2b.npy +02942699-97690c4db20227d248e23e2c398d8046.npy +03001627-39fee081ec01fbae4b3c42e318f3affc.npy +03001627-6fd5a9839c5caa52e8f8c11a24c52ebb.npy +04401088-9efabcf2ff8a4be9a59562d67b11f3d.npy +03001627-386b2caac16694edbab0cb5a4ccf2fb2.npy +04379243-8a07b5fc233b5ad2f51f77a6d7299806.npy +04379243-23ce23d83f097dfe30e9c0571435b6e3.npy +03001627-24d3d4259b35fb93490ad276cd2af3a4.npy +03636649-82c10d98a1aa65e89730cb37c9a5f63b.npy +03001627-3427d2276fb713e5864c004309dc898d.npy +02933112-e0c8d4f4c31b26f6d295b24579cf55b8.npy +03636649-83c0ad378b5802b73d39d8012919dd25.npy +03001627-a3e985835e89c8b1498f847f9f26fae3.npy +04379243-4be9eedfb4071f919f9a4711823598a.npy +02924116-9fb19dac527431c77d5938f6fe09fcd7.npy +04530566-2e4aeae716401155bf9913347b9df76.npy +03001627-96e83c79e8d76d4519fb4103277a6b93.npy +04379243-26642892c5579f25998886098b83a99e.npy +04256520-cade7495591007c2ec53fa9e4378e66.npy +03001627-6a02133392afc96b40ef1c8b63a628f9.npy +03001627-f2d03c1b46ff3c387bb504f750cf6e27.npy +02808440-adf9df7ae15500f88e30f00c0774a63b.npy +04379243-d94795f08cc91051a7bc6296cc70fa9f.npy +04379243-25c0559c051e57cc7fe20aad99c84084.npy +02818832-2f44a88e17474295e66f707221b74f43.npy +04256520-194ca5fd43b1c04be9ada1586a8c9364.npy +03467517-3ca24964106a34e2f8b3e7c2833060bc.npy +02828884-be0b1cfa18356b5bcb8b82ec2ef44379.npy +03001627-197ae965385b8187ae663e348bd216d3.npy +04256520-7dfdfe28e3d25a0d19fb4103277a6b93.npy +03691459-5edee1135040e2a9aa2b654345545ea.npy +04090263-82c56ec37b153eaf97ad4936ef9fbcdc.npy +04074963-404b2de4bc8bef211eba86b475bafe7.npy +04256520-3a99bf8e2a3e5e294b3c42e318f3affc.npy +03797390-7374ea7fee07f94c86032c4825f3450.npy +02958343-52ee842db08cd881979ef391885ee5d2.npy +03636649-2a9cc4404bf738302a278ff7f085c260.npy +03325088-86c6af80c470a805eb69804478f9c547.npy +04379243-918e7e6a01c7645bcb8248441df6c2f5.npy +02828884-7a910c3d6878068ba653610be84c6d81.npy +03001627-328df096e089c4eafebad4f49b26ec52.npy +04401088-7dd788cca7df768495b1245be456cdf5.npy +04460130-35824a59a19511c538cd8eb23853c009.npy +04379243-f52b167d756420c83e5f17778b45d37e.npy +04090263-556f1e3652f8c8984a2ac5bbe9a7c771.npy +02818832-a8cfed0a1b9451c9d213467246722099.npy +04090263-385439035e040c1e9a2ee232a197081e.npy +03001627-8cedc8e684d60ff42a06d8c81262ef96.npy +02933112-5135a234fe18481235836c728d324152.npy +04379243-c7f673b7b956508cf51f77a6d7299806.npy +03636649-fc5aa16de2be4b2b93411b5b3583c4d6.npy +02747177-4a14e1ffc27ba762ad5067eac75a07f7.npy +03991062-e070cedac4d9d52ff9aec59741c69cf7.npy +02958343-b18899d2b002ce0f80360680c1602c7d.npy +04530566-dded8a613927539cd72535fe84d882f0.npy +02808440-d422fa89aec6c1bb50d0c6a0c254040.npy +03691459-d06487d7634bdfddc1b62a5dd6fee95.npy +02691156-23d5975dd63000eb4e901b3386f76d65.npy +02691156-934d7c130fd419cdacffbc7889712a99.npy +03001627-a92a13b4968d7780472349060cd3c236.npy +03636649-b69c3a0a46b932e3d3c1fbbc2200e255.npy +03211117-f480ab303b2b595eb9f9e1b0ade9a295.npy +03948459-7af9e52ccd99125c67b9bb226efd81df.npy +02933112-64f02390a1487f791e4b67452ae5160.npy +03636649-4524946bc53f31a92d5c7a0e60b0c525.npy +02958343-a838af854310e283e8d78fb938bac492.npy +04379243-c450bd1ef8e17865557ab4b593540354.npy +03001627-59907bb6aaa7afeec283ca2c9df7372d.npy +02808440-9f55d5b55085bd9a5e7c3700a257e43e.npy +02871439-95a56e0b1817ba0991857224647f3835.npy +04004475-da1ab3860b75dbe837f7fabf76ffe0b0.npy +04256520-5a71471acef6f8153d4d11ac89066d36.npy +04379243-d0a4d46fd42a0c3df6cfab91d65bb91.npy +03636649-79041f47579a9e3f3c8d0fdfb1cc2535.npy +04379243-564c9bc401397abc7d9b8c8596b4309a.npy +03207941-7c03487eaa8d9cd9a26e3d8de97aed3f.npy +04379243-56eeebd64c7821dd641aac62064f7645.npy +04256520-995a4ed2a96d7c60140c975cafb9782e.npy +04379243-a8130d38d538b6306f3d2b1b15fba494.npy +03928116-8cd2b891b455539433ae329611c23135.npy +04530566-3b726a3562a1bc6e9d2b0f4ee2fe01a0.npy +02691156-cd6a3584c3da1db4abcfca680e6d54ff.npy +04379243-26fa34f25c673a7f4f41773fb12c1cbd.npy +03790512-a1553e0bb7897a7ace0bf41e5f45753d.npy +03710193-9d0ab19d54bb1f90ac51268fdb437a9e.npy +04379243-fb59360b5cfb54ac6f74453f2a3da519.npy +02933112-dd6ebb99b2346757da8c66dd9a203cf0.npy +04225987-ff04077cb675226a1082f2ea630bf69e.npy +03001627-d71d9d23d786cc8dfebad4f49b26ec52.npy +02818832-5ab88816fbf1cf9ba0ee062ac3106390.npy +03001627-21bc90d659dbe28a71aa44dea7a6d383.npy +03001627-2207db2fa2e4cc4579b3e1be3524f72f.npy +04379243-e21f715035a4471ae7fda7f082299746.npy +03691459-99c7341e243c7a2ddffb6acd1a5cf214.npy +04530566-72a68c898941cb3541556f795d265590.npy +03001627-9dac39c51680daa2f71e06115e9c3b3e.npy +02933112-ca89804bd77f770c4c62bee40dcdc539.npy +04530566-20d1090d07a49fe927ac692756be9e24.npy +04090263-f42647b43072abc9c48ca2220df3a9b9.npy +03636649-a415a0bc88904b24ed56e40d2df47c3.npy +03046257-648801b3c9b7d66b9ba80f08c401fbed.npy +02691156-19b6112991fb8e33f3f2af1b43965204.npy +04379243-162e665f12c4340f963aff3ec12fdcb.npy +04004475-263aa26d579b6def14c06184923f6962.npy +03636649-1cf44cb081b1a2b2fcb8d8c6d4df8143.npy +04379243-1eb732041cb7f2d649dd82184c01c565.npy +03001627-f199965dc6746de38b01ef724ff374fa.npy +03636649-ec0979097f7c811922a520e8315099fb.npy +04379243-9ada332060a35a9ea8a8d4103b2a0b3f.npy +04256520-90ccc3b3b344b3ea2250bf58700b4d8f.npy +04379243-8c9782f2dcd99d5255f46d55537192b6.npy +03001627-533af4a6fa955f2e78cc773ba5d9e52.npy +02958343-1a4ef4a2a639f172f13d1237e1429e9e.npy +02691156-a60cd34f71c3c0549288437ebbe47284.npy +04256520-82b6391291239d90febad4f49b26ec52.npy +04379243-fff7f07d1c4042f8a946c24c4f9fb58e.npy +02843684-26334c57fc4b83b543e68d98c50c8932.npy +02691156-5d925e4748bb4ad155050237670e0ad2.npy +03001627-e118a2870622acaf65ba78ad9601cf1b.npy +04379243-2e20f537a7b64de177981b941eb4f5d1.npy +02958343-15e52e44cdcc80ed13ded1857c15b5b6.npy +03593526-12ec19e85b31e274725f67267e31c89.npy +02958343-f6bbb767b1b75ab0c9d22fcb1abe82ed.npy +03337140-9ce1c0b588ad6ef84c3aee8e9d3a6ffa.npy +04256520-7961d0f612add0cee08bb071746122b9.npy +02828884-9705540347025dec9c2dcf27153363c7.npy +02828884-27c3e5b2656c50f7cb2a965e75be701c.npy +02958343-e9573675928b6f1c2a9eb0f146e94477.npy +04379243-855b1a33bfaf996ea1fdf150cebcb587.npy +03001627-bfbb19b74bb5973e14de2a9aaff52ac7.npy +02958343-d691906c87bb2850a9733fa2ac6b95bc.npy +02958343-6c08a180a3437f316dea32b07f945478.npy +04090263-3cd7545839d7c7affc4536f2bcb40d3.npy +02876657-ff13595434879bba557ef92e2fa0ccb2.npy +03211117-dbff3b6424b743f6ec7770a2628afd7b.npy +03467517-5ed99a0b793e1f5ee52744498b9b3051.npy +04530566-1b19bc5a09198bc85fa2a5df3ce5bc40.npy +02808440-550fd88ceb559b49ccd0340812259a39.npy +02924116-e945160734280e1927a32abbd63df691.npy +03467517-797bb7bbc5af3c6567a66e84fcbfe789.npy +03001627-feab80af7f3e459120523e15ec10a342.npy +04256520-8078da16e565846181ae47ffdeb90d54.npy +03636649-ccd12ea2362ef81d8bb3deb7fab7c9b7.npy +04401088-d299bcdfee69c57d419fdfebc874eb8f.npy +03948459-fffbe09e4890f8f36314c3b6a3a65519.npy +04379243-d2578e2ab0be1ea3332e588d1e0957a7.npy +03761084-835ca5f3809182e86d1ffe1a45470ad7.npy +03337140-a6e10b71fbb9feb74c3aee8e9d3a6ffa.npy +03001627-f6d1ecef43ed4eeb907f4a296134a0cc.npy +03467517-ebb111e59d33f36f792f3038a6b53389.npy +04090263-ac25513a060b0ca3cc20f30a7355a75c.npy +02958343-7f4dbefeaeda54628ccbb4eb8965b05.npy +04256520-361b60c0143d91c3593ebeeedbff73b.npy +04468005-7261bd067778a9a2299a59bfd8e7d284.npy +02691156-50342e9cb1a7e00e59c11002fedd14ce.npy +03467517-9bee64cbbb1061678aeceec6397860fa.npy +04379243-6dc6bb97c387b2f3af4e8812cf1b9e1.npy +02958343-60963ce07aa742382a9eb0f146e94477.npy +04256520-8728e0df5b94173c9b709c9b379c59d9.npy +03211117-813b3e438a8fcb189d9f3b4d1ec94c69.npy +02958343-7c35cd27ae8d673bb1bb46d2556ba67d.npy +04379243-1ce2de1e1077d66c1d5fca03776c86.npy +02691156-304c2daaf96c79138cdbee8c4dbbdd7c.npy +03467517-5f24e8a1b07665a7e546539ff7b98351.npy +04256520-4a1b7de779cde76487311f65d7a3e3e6.npy +02691156-10aa040f470500c6a66ef8df4909ded9.npy +03691459-eb0c85cc627406b5d33b16aac56dbe59.npy +02691156-3aa2ba8ca2aede556d96f75c7a1666e5.npy +04256520-6e7f0557400601322112c05ea370d321.npy +04554684-81ecf0670ab97ff5fb23f72ec839c310.npy +04379243-d43664b8f4df83341ee9d48493ad639.npy +02933112-b1bdcc7bcb3148aaa23949c21eddef76.npy +04379243-dca260c356a236053f2fc07aab1b396c.npy +03001627-f2ef238e2e4615e92cf8e80367b40c9a.npy +03001627-7530bff8f0c2b45719fb4103277a6b93.npy +02992529-3ff176780a009cd93b61739f3c4d4342.npy +03642806-3e9af28eb2d6e216a4e3429ccb8eaf16.npy +03001627-8bd75ffee48bb4b845fa198471a5a8a5.npy +03046257-9a3e3e241da6de9d93f86a8fb60496b7.npy +02958343-a4548c56bea7f927ad02214e86fd5091.npy +02691156-37700819bf2af266f64801ad2940cdd5.npy +02958343-c38cba0ec9d1a74f38f3979791e64082.npy +02992529-8ea128f9035474394cb30fc798a4d976.npy +04379243-29ae41cd05f7bb1e377940ad91815d8c.npy +03636649-b78bef16d4f44844931e98da3a93e73e.npy +03467517-663dc9c3e5f11e44d57700c05b1862d8.npy +02933112-9e1fb93dc979f8fb5f9734700aefae4e.npy +03325088-6f3d84d580aa77f0c36fb70296e45483.npy +02691156-730edec9009f8cea615ba7bf3620290d.npy +03790512-365c1f92a54c8cb52a45a87054fa7272.npy +02871439-3edc5b95b8d629931a75b4e96d345a5a.npy +03001627-de351bfde19253af54a7a6750196c608.npy +03513137-68106146958b708540b769487f41c4b.npy +02933112-84a374fd72bab291ccff75c3d7aff973.npy +03790512-cfb2cd4ed1ee0de56dacd34e70282fc3.npy +04379243-f7477e845dad9568b0aa15078ea6f391.npy +03325088-850f04c8e1d8039676c18e71fd49c4dc.npy +04090263-35af9072a2ac0c485ab5fe67efb19452.npy +02691156-91f8e08144218e2d23fc69eefd95e6d3.npy +02924116-36d710fdcc160180452b9ebce7999790.npy +04530566-55cf3c1207e421a29e3e34eaf1f39535.npy +03001627-98f2d21c4dcac477f7628281ecb18112.npy +03001627-939d97b226f11272217ffa735084910f.npy +02958343-a5476137d0f2f930425b2c354eccabaf.npy +04256520-1575354ba1faad67490ad276cd2af3a4.npy +02691156-cc40acee83422fe892b90699bc4724f9.npy +04090263-23a5887211380b2f663e90eaf6b4ca52.npy +02691156-60232dad38a6ec709a6e43b878d5b335.npy +04379243-4f06092100d0164013d2510999d0f1d2.npy +04379243-9976f7053b1b7bf2318694f1cc6fb1f8.npy +04554684-5aa97c0e9c11bcd1677ce0c660f811e0.npy +02691156-791af615e17374d38eeaefe98ae26867.npy +04379243-5348f1ce4dac7dbd5dcc7ddfa72357b1.npy +02808440-1a74ca07a11f507554d7082b34825ef0.npy +02992529-427d255534038d47e5eda863cef11226.npy +02808440-da59b45d5f06d4a844221bef0fa3c36b.npy +03001627-4adde89dd6db1c4845e13b6ba9ac0cd3.npy +04379243-5c593d79b5f9c918b398a1cfd1079875.npy +03046257-550ecca35381f8cb75b642c872f5c552.npy +02933112-da57e1d30424771a14c06184923f6962.npy +03593526-9fe7e6a7bf8ca964efad53eb3f0b36fa.npy +03337140-d98bff9e813a9fc64c3aee8e9d3a6ffa.npy +03211117-ddd82fb23a12e2eb2c8bd51dc6fc05b.npy +03001627-23b52ffd037c95223704253c4a874401.npy +02818832-958f2d4bb17eb247c9dd845c88786daa.npy +03001627-f1b1c92f91d0e52bc68ff00665267e32.npy +04379243-92d64294a4c9af5cf8609c6280e52413.npy +04379243-5533c35223061f231ff2429be93a82ac.npy +04256520-48228cf2207c7af5892eaa162d1e35d.npy +03513137-22ff6fc2c81a3674823590ed8a67d74b.npy +02818832-8154ea19d8f7f02e6a041dc074c34106.npy +03624134-877875fdfa0bd32c8272e0c587033b7.npy +03001627-69709cb300ae3784ee72e5c46412e9a7.npy +02946921-5505ddb926a77c0f171374ea58140325.npy +04090263-72aaf4a05a6d988412b52a369561019.npy +03001627-64d07a909361ccdd1a8a283df3396be6.npy +03636649-c802fa4c82498450af6016f34c89d087.npy +03001627-e352bba8524fdbd98f62bdf4e9082924.npy +04090263-a573925ea3002ef5878dfef973fade71.npy +03636649-1d3259fe9377ca5f899bad344dc01f2f.npy +02958343-81af904b941c47abccf0883afcbd4b76.npy +02828884-ba8ca7cb2d3c265bdf535ea8b5cca766.npy +02691156-460cf3a75d8467d1bb579d1d8d989550.npy +02958343-44559a87bc7a0bb3121f82ae456ac81.npy +03636649-d2ad6adbad3ac49752d7b587347d0cf4.npy +04379243-8ae2ae3b341fe20bf80985a99195eb8.npy +04379243-88ebe411acb90592e8952e902d0fccc8.npy +04401088-6aa3eee6391336c821844676433a0aca.npy +03467517-58a5d088e1b9aa0263e6b27c89da971e.npy +03761084-7bce489081dd3a03379f47575c295bee.npy +03001627-1196ffab55e431e11b17743c18fb63dc.npy +02871439-bae1a98fac9dda6a7dc4aa29087c6236.npy +03001627-b96452f41194937691a3aa674c7ec1a3.npy +02773838-c3a5009c4867f7293c8d0fdfb1cc2535.npy +02818832-2cc7c1f0c903278bc3bd24f986301745.npy +04468005-9e9b16fb7f239b2183d23296e7ba4847.npy +03624134-f19fe19693937db1cb03b57fca000b1f.npy +03761084-8d94838d6ad21411df3a1b0d597ce76e.npy +03001627-184007a6dee70847c2a9692bf3ba76d3.npy +03046257-2b326c82b14dcdcfaf0affed7cfb91de.npy +04256520-c144f9c06cae44492fdae21c212bf119.npy +02691156-89b42bde2332e5c067c5e3041553656b.npy +04379243-a4d907884de88227febad4f49b26ec52.npy +03001627-33990ef5ffde80fa83bc207d8a5912e3.npy +03001627-e127ed243617eaf04904d89e9169817b.npy +04379243-57213d6dd723e767cbde89e0c48a01bf.npy +03337140-4ef6afcc8c732bdb91c352d02061b3f7.npy +04379243-f073fc78c930ca06f777b6b1bae343f6.npy +04256520-a409f5a41d2acd344b3c42e318f3affc.npy +02933112-44e48c541b5466342f38c0d2792fb5e.npy +04379243-21a807616afa7c6030bbd4cddd04c77b.npy +03467517-2cdbb215d7816019f22d46d16026da2b.npy +03467517-b0f553ef37dc1248a97512d711172fa6.npy +03467517-bddbb876fb62fe7fa2633106d043f491.npy +04379243-2d3cb79ce06eba3c7550d396f1a3a8e1.npy +03001627-4efde5d7dfad17354f13c1c9631f2b03.npy +02958343-7f09e6522f212f94512af8eced68fa8.npy +03001627-6233ebe950c7d44df51f77a6d7299806.npy +02958343-b216e194c572e9ff99ef493efb31e54.npy +02958343-c6eebcd03aaa9060e7a6de039856f1eb.npy +04090263-a90a070a0603a4fc663e90eaf6b4ca52.npy +03928116-eb99228ff23aa9f9c6543c981120ca48.npy +02808440-f1c38a8f87ca506f1884c7a487bba311.npy +04530566-af964792bea4edac541ae04c251c7da.npy +04401088-39cd15c429c6007e2826f529d0b74d3a.npy +04379243-f910c50ed20073928be66dc0939fd23.npy +02876657-3f91158956ad7db0322747720d7d37e8.npy +02958343-7b00e029725c0c96473f10e6caaeca56.npy +04379243-b6e4f287aad69f285aefe1fcbc7169cd.npy +04090263-1ae9c8f100db37692d356a2793fb4d69.npy +02924116-81b9a5cbd961da85bc868bcd254a4e45.npy +02691156-d20e3ed9b3430672bbf3143b1cb6076a.npy +04379243-768e965bfe1f6141473f10e6caaeca56.npy +04099429-53009165a8a4d43995698f277be16510.npy +02958343-965e73db41af495941aeea95b863b1b3.npy +02818832-644f11d3687ab3ba2ade7345ab5b0cf6.npy +04379243-edba7eb533ae3578ece232edf44331c7.npy +02691156-110f6dbf0e6216e9f9a63e9a8c332e52.npy +04379243-7c278d5d7fec83ba7d0628daab3fd779.npy +03691459-1e83ac6d9ce1541329965f7e898eb4fb.npy +03337140-6d63f6894c2a8cfe4c3aee8e9d3a6ffa.npy +02958343-5523a6798194043146810e868f84ab51.npy +02992529-1d9169471bf9223423e378ba27e11ea6.npy +03001627-5330a65bc54912ce35836c728d324152.npy +03261776-703dced3f9479f348a731b44a5fe7a8e.npy +03636649-8e025c4aa0b0201a81a172d69c52a28a.npy +04379243-fa1dc9a58da9ddb6235820b1d1961ea7.npy +04379243-6862bebc1f59a5caac7bed72580dc30f.npy +02933112-95ca7e79cf9b51cbb9a0f5d18f1ce54c.npy +04530566-b03e831a78f2f16a5b04bf7f324b7e5e.npy +03211117-b3ed6cea7ecd3f56e481cbc0aafd242a.npy +04090263-2254c238167dd6a5672ed1a3426b68fa.npy +04530566-97dd02cb0afa088d485fd5204f716152.npy +03325088-81b5af68af1b0a4ce25194f3c5a4f307.npy +04090263-366db4aa9243cbee4d0af51460733e47.npy +04379243-459a13812561557e26217a9a857cd404.npy +02828884-1d9fd401e86ab773d2b12aa6a0f050b3.npy +04379243-56597cf3ace4916743ac09133d4c1d60.npy +02992529-6a0c0c55f355cc23a0eb5a85db887292.npy +02924116-ca27d87d42a074f0df98386e2670b45a.npy +02801938-bf4e9a91ced79f63d2ad39bada7a0a.npy +03001627-4f4d7ae825908e303a8be023e0f2e100.npy +04379243-a90014ce65aef22135836c728d324152.npy +02871439-a58e567af32c9f58eca22c501ad0a77a.npy +03001627-4b9278e9f2f4056d1f47fd90378714ec.npy +03325088-702319c82154da5850da8b99982a3057.npy +03001627-429319c0c5bddfccd26c2593d1870bdb.npy +02691156-d2e99eeecebf0c77bd46d022fd7d80aa.npy +04460130-607a0e44587e043a3e974a0808687b8c.npy +04379243-38c395f4655e0e70fabe21cb4fa2fa68.npy +02818832-f52493e81565c11a15dfb09c4607d131.npy +02828884-2c81dd5038d43eb7b11ae648ea92233.npy +03001627-685f2f19452cb973e98f4318c324e998.npy +03001627-b37f1363aa93688619fb4103277a6b93.npy +03001627-8661c4d0ab5e3636490ad276cd2af3a4.npy +03211117-e5dd90d78168e53741e88434245c899.npy +04379243-bd7c71ca15b0d4e56c252f74b6220e29.npy +03001627-1e15f238da6b4bc546b9f3b6ee20ff4b.npy +03624134-c9a3eab86e5e134f6402b8f491cd92c7.npy +04379243-d37560b9ea27af4efe354164024016d6.npy +02933112-fc3bb2eda6e061e9b50d0c6a0c254040.npy +04468005-9c6fc1db4373c6ec37b0cf2f5378601c.npy +03001627-63e2d9ab50536799b2b9c1746713a87e.npy +03593526-7a5aeda354f43cd5baf4ef477c70e0df.npy +02942699-4cd861035c740db5a33f3afcb8763f26.npy +03636649-8064580d3a225366ecbab50f1720e223.npy +03691459-1733111366ac40b76eb0973c46aae0d4.npy +02828884-fd2d7b385db7d186f9e8cd846ef13776.npy +04530566-ff404dc428ac3cb7102f71c17954fcf0.npy +02691156-720d70482d13696277fd7318510b8627.npy +04379243-d45cb36eb4c38786b9a7614f2da8d7ae.npy +03001627-57263b7b778ac3a87c076cdc1de5871a.npy +04379243-eb8a34ab2eb9a26fe93eff560d16430.npy +04256520-9ea47bf98413280bfebad4f49b26ec52.npy +04379243-55d5fce641343449d42b9650f19dd425.npy +04379243-72a4fae0f304519dd8e0cfcf62e3e594.npy +03211117-233a7970efc2594b26735a5c7bb362c0.npy +04256520-4385e447533cac72d1c72b9dec4baa1.npy +04256520-7dedfb51ff65c27f67bb14b25f99796e.npy +02992529-c95b7121b6408df49fda13f2ab6d2b41.npy +03691459-7fb191e5d0d7464b538cf6df9faa9b65.npy +04401088-7bd964021c9c26e0e4b68d3b17c43658.npy +04379243-e7b9c7a47208cb067b14a4ce87ce734f.npy +04401088-9a94067c6ae50d59227a8035cf3430d9.npy +04256520-440e3ad55b603cb1b071d266df0a3bf5.npy +02933112-9ebf23f2bcb8f334246300e1c662ce6d.npy +02933112-108295ef2f00c9aa9d886ab2fa5ee681.npy +02828884-dfb1e5e85b5892adf155d75bbf62b80.npy +04379243-57399be7d3352241b8812f80908a0273.npy +02773838-f297885d4918000ec8724d5673a063a6.npy +03467517-e709e622fb4f54546d9376f644442e99.npy +02828884-ade8119d5a30ba4bf1547b1668422ce3.npy +04090263-ff042c9b61e609a78e4ed0a212e54db7.npy +02691156-4d0994838c31434cef5f09964a6a1f97.npy +04330267-86a46629a011d6adac7bed72580dc30f.npy +04401088-f8d97bebf67cad12a0eb5a85db887292.npy +03001627-215e557db4c4bb5d837b757304479228.npy +03001627-b203918276818529febad4f49b26ec52.npy +02843684-a25a621347c07e49d89388918d47c02.npy +04530566-1b86008df6322c5d438d829603922fbc.npy +03636649-b3530cffd4a04deab641e19ecbf0e871.npy +03691459-711b146200447f4183247f812f2eaa97.npy +04379243-4dfa73e922842c02a7e7cb173e141227.npy +03513137-d76f5069b5f42903b20f6e48f6a30cbf.npy +03001627-8d9061d863268349db224de2961e777c.npy +04530566-f8cf09473d99d5ebfb7214357e073eb7.npy +04379243-33ceeac71f2031577cc56a6af4771185.npy +03513137-32396b24a2106049a8963fe61f2bc75f.npy +04379243-4b2119939de4f6e892cc1f9d231c0f76.npy +04379243-bce46214d9982829f51f77a6d7299806.npy +02691156-91bd6e91455f85fddcf9f917545742df.npy +03001627-fd2fbaa023b5e3a81718a174f9ac28ba.npy +04225987-fff0431e712a1887ac7a821ba28adc14.npy +02958343-31389308f2b032ddf09fb258eb4b1e60.npy +03636649-b1edea6e2974e1b35c935b78db2f5ec3.npy +04468005-b98188592c6cbd55990561fc34164364.npy +03001627-8ac35c25faa261ef4f3443b22038d340.npy +03636649-5dbb2120f2f828d28aaae3d020f5ddf8.npy +02691156-da3ed25d281fc4c065fc5f76098aceb0.npy +02958343-f06af3b73004c92ec7193c87bbfa9088.npy +03636649-7dcbac101ada832568d026fbc8fe70cb.npy +03636649-4865be9773c699bd2fadb0a8dd9104b7.npy +02992529-c33bc3be82441ea66934b554e5b8d4a4.npy +04379243-4d3a4749310a3d242bf2627b2d231d97.npy +03325088-465ec9636301436b7a867e9b35a1295.npy +03001627-367dc1e6752cabbcc34bba142e6e15e6.npy +03636649-78a11c0b8e964c9b41657e31b569b105.npy +02958343-1213742aa7815fd0e23d60a1b706b44f.npy +04090263-c6d573383e36ec052e38f6d9568202c7.npy +04379243-464a6067af815ccd843ead12644a79bb.npy +04401088-c87bd717c3640f0f741e88434245c899.npy +04379243-ccc1fcdb8b104c97700e86b51ee00536.npy +03001627-9c1ee97e493fa79ce83221ad0d21775.npy +04256520-ba8afc95c19a3d369753496ba23f2183.npy +03467517-407b7a6118e1cdd240c20797381ee39f.npy +03593526-2293b6aa5ed35db3b1a98fe8994d06b6.npy +02992529-7617e95211fc3ba0e02ee35b95994e2a.npy +03710193-1f62225a411c998d983ec12a2b33f18b.npy +03001627-946f16a9bcc3c2be75aa7f24a9b6003a.npy +02818832-e480a15c22ee438753388b7ae6bc11aa.npy +03001627-a1a173788669c84befb94709f30ce0d2.npy +04379243-8d10d8d72f135011febad4f49b26ec52.npy +03337140-c5a97a3868a2c9054c3aee8e9d3a6ffa.npy +02828884-7f4f6fc801f4f957263e68b45fad1e64.npy +02958343-ddc63b22552ef13b734650590bacf709.npy +02691156-52b2c8f99319167c71d03b466c72ce41.npy +04256520-241a341105cf3dfe593ebeeedbff73b.npy +04530566-c23960425c8cb654c6cb0dfa2f14f9d4.npy +03467517-5f3726ea13c5bf7f8f4da12eef05ed4.npy +03001627-d4e0707b680e61e0593ebeeedbff73b.npy +02828884-c71738e3b314a72411afa9f5eb84a7ae.npy +03636649-5be8cdad3b218e373d39d8012919dd25.npy +03001627-eab859ac65d47f4e6412cccabcef91eb.npy +03691459-4468a5e60a6fedc086bb0379a61a0978.npy +04090263-92ed31e84e85000beeb5508ef773ccb1.npy +04379243-ba6909f6263ff92f72b785f16db8dbf3.npy +04379243-4368d1fa80c34433f88bdcce05b1a623.npy +02747177-69773dc176d1fa3fe88c1d6fc3580355.npy +02958343-5d353140bc7569a48772afa45900d07f.npy +02992529-f6b4f01d4c9c09e6af1fe3c052ed3a8c.npy +03636649-112058b3f8c94177d2dba55bc7acf0bc.npy +04379243-2abe61af67cbd99aaa1d46a2befc5e09.npy +04379243-78420814bee5ad17f2cf6a9bef44d625.npy +03211117-849b58834fec864c34794e47f2eafa39.npy +03001627-23951f57f090116141bac0aa0782f561.npy +02691156-32b6448c0864812729348d14ca881f7d.npy +03211117-4302bce2d7e6594cab610b0c94236463.npy +04468005-79e1589916d42685dc14ba0818ee5cec.npy +03337140-c68fef3fd87998974eb412130b6b0cb0.npy +02933112-7c12c2a7a1957abc8bf788ad2aab0947.npy +03691459-6503d74fb534ca43d4e62d99c536bbaf.npy +03325088-4bc18e1398c1b56173ec0850b5880d3f.npy +04379243-f10936939b1c9277d6134c153bee8ea0.npy +02691156-31fd02481a07471e4e8b48a4c01e36f8.npy +04379243-edb5fe83efeaf086fb0eb7e753c06942.npy +02691156-130934b3dd2fddfaaf4f36f817f09501.npy +02924116-c975efbd8c9b23ef94a1965cc6affaa3.npy +02958343-72122bdcd4ddcb96a0c0a4b1a1c1a4ad.npy +03001627-b559688f7af76ff5466127bf535bd761.npy +02924116-730fb62cfb278e0c2ac826a3c82da491.npy +03046257-5c851029d69c6252c834958aed613724.npy +04256520-6bdcfd4b681a6254c45c0f305d0b6e87.npy +02958343-3dab4ef100f906c2bda733a39f84326d.npy +03001627-5a96894b5cde0551c8687ff9b0b4e4ac.npy +02958343-d13d0612c64c1c872457c273ba02ebf.npy +04090263-c9ee75f15d7f6bd13623b64770edb4be.npy +04379243-c82910190bf76ef216efc8582f9e6d60.npy +02958343-34412b56217de1112b12ea83455b0f44.npy +04090263-92109df597fb12692511f68da65f4c4.npy +03790512-42857ece33bd9119617798af67b81f2f.npy +04379243-30655ef8f2511b4ad8f2ca82d6e1c314.npy +03991062-44aea02b6852ce98910e50f05b8001.npy +04256520-3247d4bf8bbcbeb6840bf649c20f40cb.npy +03211117-3d4079a37c8fb40e808951ff5fb582ac.npy +02828884-4e43690694133a65e5ef38e098c46afd.npy +02691156-3d23703a618ce7df1e569ed4e4cfe84.npy +03991062-1af2b0b5ca59c8d8a4136492f17b9a59.npy +02691156-6e65a6f2b81fdea2282e76ed8cc73a69.npy +03948459-2a8f236c10ec9b98ba9409808fba922a.npy +03624134-fca703c2489237d51b44a9962207f944.npy +04256520-5f67ee55d76bf582c41aee3d4c9d0c9d.npy +04379243-20bb1a34891588c1cce90f0d61ed7a70.npy +02933112-26a2132b719d226a86d53ab0fe94e911.npy +04256520-949054060a3db173d9d07e89322d9cab.npy +02691156-ca4ec545363b3b8e8c2814a4ead9cb90.npy +02992529-97e214d6b93e012f6337fbfda5096043.npy +03001627-54263fcf9d6380d343638dabe1eb5336.npy +03636649-dc8b9cc431acdda473f5a6f6800a3e79.npy +02958343-fc2b81391e185db9f1335b4fef92b83f.npy +04256520-2082b15a24a55e52cc9651014a82e2b9.npy +03211117-a87214036fbca69e84a172a28c2dc.npy +04379243-52c379f93a8ae9de276f41435671c8b8.npy +02958343-5357fd81d212951a1c64dffb0265c4d6.npy +03001627-1d2745e280ea2d513c8d0fdfb1cc2535.npy +03636649-ead77648c9c7dbf8d42b9650f19dd425.npy +04401088-ac6f6437f9e63981b6d41c42f7ade8c8.npy +02691156-fd3a9743e16d35e51fc210a07910eb2.npy +03636649-1e83293107d6c3a92cd2160e449d45ae.npy +02691156-47d677bf1dec3dca82cea33798fcd6b6.npy +04256520-4b7f63ec83da1c25c59508b4e3a82241.npy +04379243-e92bd321064e981e5208aab875b932bc.npy +03691459-f37f4ef72fd0204d839a84b4ae4862d3.npy +04256520-20222a2bd14ea9609e489c1cf724666f.npy +04379243-88ba062b171b4797e30dbde92844e593.npy +03325088-4a44ef4b181f1101b362845c6edb57fc.npy +02691156-bed589371c324e896aa3bf023a2b42a5.npy +02992529-db96e9b2c96c273de7d92dda5756fcfd.npy +04074963-4fae99783aa8706c548eb4d45dc63633.npy +03001627-6870fbd4a7b733b0674f1c30a8cad95a.npy +02992529-320d0f9256ab9cc3a046bbac53886364.npy +02958343-eb56379e243b0e2090da6b3e2ed8b49d.npy +02691156-4ee6a3030995dcd4bc0909d98a1ff2b4.npy +02691156-1e8adc1e176bc68571d03b466c72ce41.npy +02808440-5125de61a2cf9dd2b362845c6edb57fc.npy +03001627-89f5cda510eea57a9917ad57402f53f1.npy +04460130-614ba760fb825f93ad5067eac75a07f7.npy +03001627-27c00ec2b6ec279958e80128fd34c2b1.npy +03211117-111f2a331b626935d82b15a1af434a9f.npy +03001627-ef1152b1660592d413f0924ccc9628e5.npy +04554684-60b8c29d75c28ce214b35a7d7cea7130.npy +04379243-c2e2206394f6de78a78a19ca5a5a5ca3.npy +02871439-98c20af27765a11e3178ebc750d175.npy +02933112-587315cfb22617a1d37a1bae74ee50a2.npy +02924116-e5eef3183d03c4ab4fb90f1c75bb6c3.npy +03624134-f639cff54b955a9b39c78a1e40e247f3.npy +04090263-fbff23bb1043116a92cea77f96988ae6.npy +04256520-6dc235ab4a2c7c6810edd100dffd8d85.npy +02876657-af3dda1cfe61d0fc9403b0d0536a04af.npy +04090263-b642c89b7359f0cb66ab132932374f46.npy +03001627-c69d5899d85eab9c173b9f28a2caa84d.npy +02958343-abda34ccba30a7dd80360680c1602c7d.npy +04379243-63790a73bd92ec04a55e6ad8c321a190.npy +03001627-768ea32d8303095bfe6f9308e75765b1.npy +03636649-eecf97919cea666e67903707764646db.npy +04379243-1539b9a05dd82a3b23adfb9fc6ab1f7a.npy +02942699-45b01c604426a0a9c5c10e0ebb47766c.npy +03001627-659a60740eb6bfa930bbd4cddd04c77b.npy +04090263-6a9fac86136c7ba0f3dbacbbb2e7e80c.npy +02924116-419cb0a5742d8f1ce68a7b2541c35558.npy +02828884-9a87c9d904851205bfcc4c7214610fe3.npy +02958343-39b307361b650db073a425eed3ac7a0b.npy +03001627-8dee8193a06525f51de495b75c95e5ad.npy +02691156-5a5e4590c54a70c6322c168d7a7c32f4.npy +03001627-59cc459b0e75c2ec1142c13b71507bca.npy +04090263-d326ce10d768da152c3271e911ffe19.npy +04468005-1ac8292d6ce89f7452470de2774d6099.npy +02876657-21dbbd17ae4c3fce6a90f735365ac29e.npy +03001627-ba2f3a0d2e90025bb3234e0da44b11e4.npy +04530566-b7d831d7b1dcad77a8596b6b008107ab.npy +04256520-d3c677deb7e829f05728afe1a12978b.npy +02808440-5ab70805cc7ca4be73fd10002dacf954.npy +03001627-923447d348ddd1ff3002761e7a3ba3bd.npy +04554684-5e411987081d3f3af44ef865a534c948.npy +02691156-94dffe91af2c8834fca1f1143bb6bc17.npy +03636649-3c3286722b31c8e2f678c9833bd643c0.npy +03001627-80bad2242183a77df69c1bc654d8fbbd.npy +03691459-4eceec9a386a21ef77818a0572bf1777.npy +02958343-66d89101c69cd1fc1e4f5422b970bb55.npy +02808440-4f14ed9498cd69c6392f36bc2fbdcf8c.npy +04379243-497175f56357e331b4b7c06325f7a2a5.npy +04379243-c6cc25ee47d08674842c47c8032438a1.npy +04530566-ad62a23a7de3965f94daa4565dd30535.npy +04530566-d74ea3567f8861dc182929c56117755a.npy +04256520-ca2204f36a01e3515b943c35c765be0.npy +02992529-e5b629f4a5e7467066ccbd11a6ef0f68.npy +03001627-751d61e1d2cbbeaebdcc459b19e43a6.npy +04256520-218233bd68f5261dff318cdb0cb45ca.npy +03790512-f04281f2440a6821aa213948f4ab1d15.npy +03001627-eeafc14e4e0db2ca3b481215325f1515.npy +02828884-891b8a01ad71af2db7e843606969432b.npy +02691156-3a6f0d1cff0aa524567ab83a85d8a5a0.npy +02992529-e156db6fe3b9286c87cb3c64e47598b4.npy +04530566-f5a0bce67dca5ccbe3de75b155d3b403.npy +04379243-ddb20a7778038d87f51f77a6d7299806.npy +02691156-e899c19c87245ac94c3a35cee92bb95b.npy +04256520-d5a2b159a5fbbc4c510e2ce46c1af6e.npy +02828884-cc7ab68e97b381eead5067eac75a07f7.npy +03211117-cde799eeb40e6e8524d1772907b17f1.npy +03001627-c46ed3a68dcef72039b07b3056a2842b.npy +03467517-849c080c585387e61082f2ea630bf69e.npy +03046257-90fe7c32c11b9a371bdc62787da74594.npy +03467517-364f85832427992343820c03f9f59458.npy +04090263-1a68ec72239a781627f279690428499f.npy +02691156-1a54a2319e87bd4071d03b466c72ce41.npy +03001627-fcc996c2c8ff394194887ea54f3cfb87.npy +04090263-10639ade9179e38d624a9463cbe27c6a.npy +04256520-4e8087f3851d85cdeedfca8b846d3b01.npy +03001627-c5203dae464c264f4e41620d80d9e89c.npy +04379243-3092a18a275497f54b3c42e318f3affc.npy +02992529-c3a90bcecce7f4817b6fd5468f603b31.npy +03001627-fa33e83563fc2765e238f87ef5154562.npy +04379243-a87c9d907feba5e944187aa25305d7b7.npy +02933112-557cf522ec6be06ffc5195fbc9cb6806.npy +02933112-7177dc5922252f1311fc2b865c2a185b.npy +02691156-3cb63efff711cfc035fc197bbabcd5bd.npy +04090263-7e0e797780f6945fc75e2dd4efaea578.npy +02958343-4f31142fb24b4814ff1370452e3a0154.npy +02958343-df5a4ebff89f02cc25508ed649b952cb.npy +02992529-35d370a1531826adbe5693b333a3dd92.npy +03928116-3e2a452e802b178eb72f1eb118b6fbc3.npy +04090263-313b30e96bdbc29cb1d04c72ba966611.npy +04379243-5fc39e0ecc8e50f0902a571380e15334.npy +03691459-7488e7b4b7174ca73b2680579dc5dcf5.npy +04379243-a06fa6a604ddc974ccd77b10347fd7d3.npy +02691156-8eab40ab482a46f04369ac253fd9f7b2.npy +04379243-3b384a4919d180a666ef9dd2f3ef27d3.npy +02933112-d7ec3740a0c67d89f8c3d2002c77ddb.npy +03467517-aabe3066d17c90c163e148e250c0340d.npy +02691156-b1f056090f81f992301e72365eacb45b.npy +03636649-8c4539bca010eae1cd74bafe512884c.npy +03207941-e4d1d33b9aaf1407be92f74d81ff60bf.npy +03001627-ce35ada9c4a8de2fffc6e457221b9271.npy +04090263-4a20928c1570034d77c52b6e87288e66.npy +04379243-87d5a94d81a299401877c7666e1dab40.npy +04379243-9f6388c27485b03adfd21203bf8b4b46.npy +04379243-d41ba8cd6a5b1071c1237601d86c1b5b.npy +02933112-9702a1fa518b960784db07849359372d.npy +02691156-6feb039c710277aabd10f71f04d299c.npy +04379243-90908595d267ed89d970a88713e6172a.npy +04379243-a5abb8bcc70e8099ff39d54f280fc5d8.npy +04330267-4a82d3e205075abdc5f3208c32f3ec87.npy +04379243-9f62189d260cbad33c11c3dc5dc42217.npy +03001627-a896856650a288c0c05575120a46cd3b.npy +04379243-b57f0907adb6a60b391e4d6c585a697a.npy +03467517-7aa29002be26087ebc2f9fd0bfca25cb.npy +03790512-c43742bc6e7dd467e8e23c8de25a6ff4.npy +03636649-12aa829de18f4e6ad5cb6d178687b980.npy +02691156-45801aa10db0636d4694b8455e89054.npy +02933112-1819a4e03dd67e6c59350d819542ec7.npy +03001627-d020eee9e094050ad776c08b6a3d0a38.npy +04256520-dfc8656b5e7e6104feec1f13d2353f3.npy +03001627-c149718d89776eb5f71db1fd522c9a79.npy +02691156-4d84619c0da53326e90916c8815b5c43.npy +02691156-eaccb2ca303223afc503a3776fc280fe.npy +04379243-df1b280b7763abde3002761e7a3ba3bd.npy +02958343-6d79f2cde0340b5fbecf71e2e014ff6f.npy +04379243-3b112cbb833b57ce7774eacf69d476db.npy +02933112-83bb0c92d3ede1e8c59350d819542ec7.npy +02828884-34a1d09b3ec2f05b2056b4bd5d870b47.npy +02924116-3e2a8aab3ad459e5f446f92b52bbd82a.npy +02691156-393cfa7e090b972dce2cec85ea6ae00d.npy +03001627-c8860d4563be0f34f2b7580a739cd4d5.npy +04256520-776c31753fadd5593a1c86745128d0e2.npy +04468005-e92e28a1ec1c9b2dd85b408a8edc983b.npy +03636649-a4b3971680744f7f1742918a871fc8cf.npy +03636649-e6d62a37e187bde599284d844aba7576.npy +03325088-d1a20d867c2b8f459cd6e2005048d293.npy +03636649-60fe504827e96df11fcc6cd2b8a40871.npy +02933112-6e6801ca4a03a1adc672720c52b0e374.npy +02691156-9ac292686a2fcebbe719b5362fe06bbb.npy +03761084-35cdd3a824ada16042725722166b0554.npy +02843684-92f6d4d1dc94f4db973037aa80f5ba45.npy +02808440-a1d69eef3e42da23321831d2245cf06.npy +02691156-8d62d327fb15c9b42ff26728ed9d7bc3.npy +02942699-eb86c8c2a20066d0fb1468f5fc754e02.npy +02747177-f7470d69ce11121a95f577622f465c85.npy +02992529-500fbdefb58e261af2cdad303f49c9f9.npy +04379243-114a55b4647938cee3dff0d5ebb43915.npy +04256520-44a17a70369e803cc7623e33dc7256f2.npy +04379243-fb5d7176752898cc5fceaa39a8353bde.npy +03759954-62854e501570e57f1781e1106734ef2a.npy +04530566-24ab70fe2e704df45b76db9a8a523dba.npy +03467517-2c491c5718322fc4849457db85ec22c6.npy +03691459-1ab52761b829fcb375a3010d3ada28ba.npy +03467517-ca6740aebb04e18bcf414637ee646214.npy +03001627-bccedf688d8e5536eaf288f952624966.npy +03001627-51d67f7174881679f256a8c3e3396495.npy +03691459-47072a1458f35a8e1574d21c0c95092f.npy +02808440-e5f025768acc620dccd0340812259a39.npy +02808440-44094937bf0f806c49cad307d3d06994.npy +02691156-dd48aa92170bdde04c3a35cee92bb95b.npy +02747177-c6ef918f335bb21c5896bab37ddebe7.npy +03001627-d9aa42439dc6f1b1c63608961819b578.npy +02691156-e127b1f5ead603f9a5a118bd15e6e34f.npy +03991062-34875f8448f98813a2c59a4d90e63212.npy +04530566-1f20ff37655c5dd61aa01ae491663d9.npy +03325088-db54ca4101f454a055ced94b11ca829d.npy +04401088-b77f57d319fd864fda5309001d158b32.npy +04379243-bedbd91db5d280ccfebad4f49b26ec52.npy +04256520-cb680d8c4891670d559916e9a5177b0e.npy +04256520-a207c52399b289be9657063f91d78d19.npy +02808440-453faae27faa3cb454d7082b34825ef0.npy +03001627-802c46001be93276283b00891f680579.npy +04530566-c28ec663f25bc97de8bdcdb326f0e57b.npy +04530566-daf5575e801967cdcefe7473eb81422f.npy +04090263-e0e0041f541a646689ea614fce832f5.npy +02828884-a3e3c1bd2a644e2df4fb4dee5181bee.npy +04530566-4bb41171f7e6505bc32f927674bfca67.npy +02828884-8b4314a159d964fdcb2a965e75be701c.npy +02691156-58fadbeceb7e239724f575085333a65b.npy +03948459-9ab3478772766eec803b54e9738b20a6.npy +03636649-bfdfe22081bd54f7581fd19c35a5c8c.npy +04004475-bd6207b442ca86eb5c4cedf67999f333.npy +04090263-394a97c4ca0132132bf26da672b84220.npy +03642806-e6329b09d7920f006f729e50d852de2e.npy +03085013-fa61675a0f92a2ed3aeab48ed64c0fa4.npy +03691459-6ca4143e8b989ddf8dfd947f5413afaa.npy +04530566-486e953ff691d414d8190076748f5b20.npy +04401088-1edc7aa574624ca0200a0406803801e9.npy +03001627-f0cbf508a2f27a16504721639e19f609.npy +04379243-4d7035ed932406819223fc014b68160f.npy +04256520-dbf6c49376ac9591c8e7e2daa5cdb0c4.npy +04379243-fbd83a2ac7a5dc52e915f7ff1872d16a.npy +04554684-d49400b5298fb56adf3a1b0d597ce76e.npy +02691156-a839663396fe378a896facc4c7b99761.npy +03790512-3339fcde0648dadd11d830afc8c91af.npy +04379243-bcb349231b83952a3da27ece6ae88fff.npy +03001627-1a8bbf2994788e2743e99e0cae970928.npy +02924116-ed4554f4c9ad4f1a3bd565c86a477bf0.npy +02924116-494c24cc1ec8256944f9d2f9464b48c8.npy +03001627-9fd6bb18dc21c70766ef9dd2f3ef27d3.npy +04379243-2145e510632056161afe34ec6aa383f.npy +02958343-12cd99c20b1a5a932e877e82c90c24d.npy +04256520-398fb143825e597b960f73850432c28a.npy +03001627-75ea5a697313a8c214c2f69de20984ee.npy +02691156-ce6aef9846db6aa5c1a897657d9a1924.npy +04401088-53ce93c96d480cc4da0f54fde38627c3.npy +04379243-94f9034f0a3e85d3ee881d4feac7f213.npy +02958343-85e54cec1c6808009bc0c5b67eaafbc.npy +02871439-863be573b1c9420cd810b14a81e12eca.npy +02933112-bae2eb7c426570752c91206be77753e3.npy +03211117-ff7333934e9ecd5f681c36c9abb1a31b.npy +02958343-1424d894bfd59cdc65e9f24f8c34a52.npy +02691156-cf4c2d7d836c781e5a59e179e114b9a7.npy +04379243-3997cdee934a9b238eb3bc6c6d15f9bf.npy +04379243-ed36c49874dc325698fc83ea562f5c95.npy +03001627-2e37697d32d085415634c21965ee6bab.npy +03001627-e65d2f0ed75a786a37b2bb75885cfc44.npy +02828884-90d6cf58f5e9ba30c175dd3be8577953.npy +04090263-fae9667f8fb1217d124c90ae3e698e4f.npy +03636649-1edec15a9740c25edf85db41e3677c28.npy +03337140-cfacfc7c4c6a49d5195ae0b4bee7180e.npy +02828884-9e4e83e67a901168febad4f49b26ec52.npy +03001627-ba56f02dee485974c242632b2a8c3129.npy +02992529-c556efeb2bb3df4621844676433a0aca.npy +02958343-ddd5e2bb26c82862b41ac95a0a9b3aa0.npy +04530566-147fd27a40793d7e9bbe4f1047e9e5fd.npy +04256520-ee3d0be16a4499b7d8ce2b7ddb5bbcea.npy +04256520-5d3a1feb79ab7987bcedcb5f4c7257b9.npy +03001627-d661b52c3763eec020768660cf080d12.npy +03001627-e476879972230ca719d8721fec72f0c.npy +03691459-435ab5f43b24f739bc0c56c4d4a1fd3b.npy +02691156-3adbafd59a34d393eccd82bb51193a7f.npy +04379243-3fedf94dd96ccf8db595eebc49c98d3.npy +03636649-796d944631745f69275286bf1f79c201.npy +04379243-190ac74c619a233470412e9b69c8933.npy +04256520-a4ce7b3e633a6c802c5d34a902e568f9.npy +03325088-cef466a7a055ea8a15aea01a869de65.npy +04379243-8f380fecd7c5b0e4cb95bbaeca3ed4f1.npy +02691156-f1b9ff223b5a13719a6e43b878d5b335.npy +04379243-d443a71b6cd1b4b0d0e90ab6c6492cb4.npy +02958343-1c66dbe15a6be89a7bfe055aeab68431.npy +04256520-2fc2409aa962c5553ca57f5648ff1b0d.npy +04401088-3621cec4df1ddf421844676433a0aca.npy +03261776-8f000f5a05ebffc5275a90d0cd7aaf64.npy +02958343-272791fdabf46b2d5921daf0138cfe67.npy +04090263-36392e6edec3c8b59aa300fabdebe6be.npy +03001627-4ab439279e665e08410fc47639efb60.npy +02924116-45223e07115146db5b81bbc42b23c7b6.npy +03642806-69ca190b89d622d6def5bf46a0f0ff11.npy +04530566-e5a3728a3b5a7ecd1d2d2f3b717d35d5.npy +04256520-461772d07ff458d7470846ec41d04ed8.npy +03948459-12b346d7a60328ba9be47ac7c7e37815.npy +04379243-19eef9f0da098279c8bd09537246ca3a.npy +03636649-41e0a38cafd737a87088591b1a3e2750.npy +03001627-52cc5e280c23ea9d490ad276cd2af3a4.npy +04379243-c40a88d13709eba91f30b807ae39b61d.npy +03211117-3324b4a3f1440d7b4161e123a102b12b.npy +03001627-6b4622c4e15b5cc9f91663a74ccd2338.npy +02828884-d55207728b14e543ad5067eac75a07f7.npy +03001627-1bdf0a0bb9db1db68998b3b64a143d42.npy +03636649-c93f10431b324061581fd19c35a5c8c.npy +02691156-6311138687290f8a505ae8d422ba349d.npy +04379243-8669bdebc11a4646618b7927ac6e11ea.npy +03001627-49e265cf00ecff0f59d9b12c05c8f809.npy +02933112-282f296a666fb63dc59350d819542ec7.npy +02871439-7c1982d2d4a240de3848bf8bbe386d81.npy +04090263-425f45023b30fa6ecb88c9db6e396994.npy +03001627-1f5a2c231265aa9380b3cfbeccfb24d2.npy +04379243-a25f904dfbc0fb0331b9e762848db625.npy +04090263-b3ea2d0331ec9ec650544cd7fa263944.npy +02876657-63d98b2654d8d2a2f9411c52486c6e63.npy +02808440-ead316f148fa1b699fd7df127276ed69.npy +03046257-752bc71803170b3514038d588fd1342f.npy +03624134-c0ddcd295d84beb696196068f29f233.npy +04379243-521e51c43fe3def573ae93d3b4dd6712.npy +03001627-a65534c7545a4b3a19fb4103277a6b93.npy +02691156-1ac29674746a0fc6b87697d3904b168b.npy +04090263-9773bf30a8dea97145f791e063652f65.npy +03797390-b811555ccf5ef6c4948fa2daa427fe1f.npy +04379243-c8fff605d821d607ff28aa687ec5e78a.npy +02958343-3efdb762f2663a014c9dc258dd1682ab.npy +02933112-2ba392a70c40dac7c59350d819542ec7.npy +02691156-1d4fbbf681ba892ddeddb5c33cb2f8f3.npy +02958343-e5da1a1fa675c704a2edbcbb0bd69bcb.npy +03337140-ae4c4273468905586ae3841175e518b2.npy +04379243-8ce538a671c6e684d93768e7b9b1eabf.npy +03001627-65f065a51800eaa5cd476b195edd95d6.npy +03642806-ee31f8d77002d8869b07343517e0f88e.npy +04379243-451e66939d40c5be61bfbba8a5defb02.npy +04401088-73d6b5dfb0f2bd8f5c351e299b24e355.npy +04090263-22bf66e440bdb80c3d7c323cf1653143.npy +04256520-a9698105867e9818f91663a74ccd2338.npy +04468005-22de7219d157d442af02dc8e9b049407.npy +03325088-790d92e4614f2f13321831d2245cf06.npy +04379243-fd1cb59eda441efc3a6294a7f35b35be.npy +02773838-2970e5486815e72ccd99ccc7ff441abf.npy +02828884-6ba417deb22dec19ff8d96709474c16b.npy +03593526-f0612de90c1fe7d430612f5c0ef21eb8.npy +04379243-84611112c9300d6b19fb4103277a6b93.npy +02828884-45d52d8c9b100eb54ebf9d56b42b3033.npy +02992529-8aa05d2bb435ab441ac3fdfdb76cf4dc.npy +02958343-f578a26ffc6771b21767453ad70570c6.npy +02924116-8780fcb7aeb4dbe1e2f5e842488b65f7.npy +02992529-78b4f3aa956b52139531a714ad5bf7d5.npy +02691156-8a050edf3d971a617b17a3f88bbfbb61.npy +02808440-763aa4a2281d5a2cb1e4f0ffdb30250.npy +02958343-67c229c70e64a25e69c2e0a91b39f742.npy +03001627-b90720eca9bff16c45c481d507018ba.npy +03636649-c778a6ac6cf0c81d4904d89e9169817b.npy +04379243-cc8217e65e253ffcf51f77a6d7299806.npy +02801938-27f58201df188ce0c76e1e2d1feb4ae.npy +02808440-81a7ebba1f545a4b57b6140a0b345e1d.npy +04256520-3a69f7f6729d8d48f51f77a6d7299806.npy +03001627-9ea7facf01e448f328a1548e344f0e2e.npy +03001627-48d2769e59e4c2b9febad4f49b26ec52.npy +03211117-70c43793136021289261ff87472ba275.npy +03001627-43d38ad2f5d103adf9b9977a2406713a.npy +04090263-8532101879b57af2fa9286f039319ff7.npy +02871439-e382838534662ffaac6f189ba32d2a38.npy +04379243-1b48826b38c2dc0630d4c74109f9e072.npy +02691156-d63bd140efa537dcf73e5bc170b7e2be.npy +03691459-20ac1211f88a8a1878396b03f57f644c.npy +04379243-46e88f122a869874d989c9f989a09ff.npy +04530566-a646c8780e79d091cd079e2d482994e.npy +02691156-b943b632fd36f75ac1ccec171a275967.npy +02691156-6abe0099d2a6efc882401bb74114a99.npy +03001627-ccc4b5366a6dc7c4cffab2c8f8bf5951.npy +02958343-70cf106dd369bf3ac427f8508e3d634b.npy +02828884-7262d96c5817ab55ad5067eac75a07f7.npy +04090263-1fe9e8fbcee0dcc8683e3750b53385d5.npy +03337140-56dc186e01c7056e91c352d02061b3f7.npy +03467517-b004331ee5cc39caa24eeca91f583600.npy +04379243-65b353144d52d75e98d5fc0473d00a1c.npy +02691156-35c8abfbabb0d8ea66b0983c7366318e.npy +02933112-bde4addb689c2ba55841240ed5c62c36.npy +04256520-c8962afab63de682a9ed6dce8b2a37bc.npy +03001627-df8c98028d8ff2435dc3653f8341633a.npy +02828884-39d8fdb56b0e160dbcceec49967c0de7.npy +02747177-9d579fa393e18a0570442b4b3eac5c43.npy +03211117-3c4c7ec7ffdfec50f39105e1e4d2e270.npy +04090263-22e4139b7fd37bda2538e024d06c30fd.npy +02876657-ab3795042c759b6798646029ad91cbbd.npy +04530566-eb1d9a98d4024b2e89d2f742ca991829.npy +04256520-d0ce2d65a1f3f7f0942fb082e747f0bc.npy +04401088-7392ea79052281e6bfbac23a8087e8f4.npy +03761084-337b1db9d85de33b4a73e364671ba824.npy +02691156-7054f98cc8af397f9a6e43b878d5b335.npy +04468005-af418bcf5fa6b22642ca7cc070f21ed3.npy +04379243-bda00a13a1dcbbee908afb10f96957b6.npy +03467517-e25b244880bb40b9cc34b900bb2492e.npy +03938244-f06843cc11cfe791cbcb2c721c3564d4.npy +04530566-ac8a42622eed9830ae433bf4d273c8e2.npy +04090263-b5f4600ef0e9a5a8dd0a2071dde26395.npy +03790512-66fb059b0102f4275a03ed6c9088ec08.npy +02876657-2a9817a43c5b3983bb13793251b29587.npy +02958343-afc23aacd3e166d9f513bf8e198d377a.npy +04090263-4223e38ce99c160724270d533c13dba3.npy +04256520-61177f1b2f1dc0b394fadb3555028734.npy +03991062-43e335f8f080f6df56ffb3d9eeba35bd.npy +03691459-bae089bd1855bcdcfa9922db9b6aab31.npy +03790512-e5747516a94cc4c9e8d78fb938bac492.npy +04530566-133c9fa2562498d28ae10bd53dffee76.npy +04256520-28a77ea1fc6b43f936460820a7040825.npy +02924116-662fc1d9049603e61759ca9eefe0e251.npy +03642806-466ea85bb4653ba3a715ae636b111d77.npy +02958343-54b10fd57a55e249ad07230f53fe98be.npy +04090263-f9564e57bef8a7446c16036d807ca393.npy +04401088-be254a4f3097143fe0e25464307430b.npy +02992529-8b4c89b8f756cc6e78fe949fc1419876.npy +04379243-d309951e04fd344c7b56d76bb19dcf39.npy +03001627-fdd7090f3ca12395a7ae19ac44244eae.npy +04379243-f3cbca2c7a6b2821f4b6538438a0b930.npy +03085013-9acaa3cd9bf7ab64e1b43120579d856a.npy +04379243-3838913e27df8fe5287005440c82669a.npy +03636649-f021d7374cb40f0da2ee802ea6ed091.npy +04256520-9e35945e9d768135d028c2e338a88f09.npy +02691156-bdfbf1c555dacd9d325212819caa597d.npy +02747177-27ed54b7f9c371b72056b4bd5d870b47.npy +03593526-701cb938a050ced01071d664364e92d8.npy +03211117-d83dcf0d435bbb87b6d41c42f7ade8c8.npy +03001627-6dc02b1884fb578492d9da2668ec34c.npy +02691156-87b4476ce2df563972459a40bb821ba6.npy +04379243-3c475d9f0433a7eaad2650d014e970a5.npy +04530566-e3f81331fa00c5f893375feb9c1d5577.npy +02871439-bb6b74ceb3fae8b5de98e4da245e0b83.npy +04379243-2e4715cfffeb76f6e074517a246f1e65.npy +02958343-8b2f030e604925c92a9eb0f146e94477.npy +02958343-a115d534edec6f89afe1d4530f4c6e24.npy +02924116-d23dfcd55f78a48041cefd10ce5d6cc0.npy +02691156-f390b1b28b6dda03dc57b3e43c28d486.npy +04090263-8a669ef9b92912112b38b1d99376c0b.npy +02992529-44cb63b74117f9a77877a964f5722626.npy +04256520-fa0218bd49f8cc6d593ebeeedbff73b.npy +04099429-9dd060ee900f4e81928f48325a5eb64.npy +03211117-e2cc0d50d6953e760a25ec0f32e89e3.npy +02691156-4fe076aa34c706b83d7edb3bb2d24b58.npy +03001627-a97a00bee5585e49f05defab1869a09.npy +04225987-58ab8327f188e0a063381d3d7e871939.npy +03001627-ee20e46c542e2268f51f77a6d7299806.npy +03636649-13b365ef4887f5d388a942de43574033.npy +03001627-f1167a0c4bfc1f3fcf004563556ddb36.npy +03001627-7b86f52727b40120e3f7a74e12a274ef.npy +02828884-8d074f177479ac42628516f95b4691f.npy +04379243-cbb90091d43fabcbd5cb6d178687b980.npy +03001627-70f1f85d47c970bb78dd615a59de5f05.npy +02808440-8a55c7f9d5fc9dac33da1d126caef9c6.npy +03636649-5ec6c52d6d5dbbddded4c23d05709216.npy +02691156-9be01448f3b2b932828204947d78b9af.npy +03001627-40747ff0ea92f134c409eaceb0331214.npy +04401088-8f3dfdb531d1b5dcb4ca066f17bc06cf.npy +04401088-70fe91a7bc072c39cf81faac56233ce6.npy +04401088-f48acd0450cf96cde6b9b562e2cde99e.npy +04379243-d1cf31acd02985bb50efffb055ed6bd1.npy +04379243-1ee0509358dc8bcae19134c8fbb91f2.npy +03001627-5a52b62f564eb7e117b431cae0dd70ed.npy +02992529-3ed359e502a24e5a79510444cc61f839.npy +03001627-1825f6f71e68da9da36af77e45b32071.npy +04530566-f1d39ce0d8c25403b4caa017b521f7.npy +04256520-978c47d21e5c66c6f519adc9991b5f11.npy +04379243-8010b1ce4e4b1a472a82acb89c31cb53.npy +02828884-ab1614b56ea09479d4d8765e3910f617.npy +04530566-77e304ed79aded1e454ff46d89fe2a0a.npy +04401088-6e30906a4d0854e9f31b75c4a94a8879.npy +03636649-9e49915157b79d911735ea0e092a805a.npy +03001627-a4684772b9356ba28fa2f6eb9fb1de7c.npy +04379243-399680cabe38c8e27b3d8399a9d05045.npy +03991062-2e1b664ff0cf2589577bb053711067f.npy +04379243-92d806ba93c283f73379bf463ad73282.npy +02828884-716fa6d69c22db83bc6fbe160acb5d0e.npy +03001627-dd0eecbd7ad89b2563e7eea06f1f07c8.npy +02958343-4510559f5587f601147d1b898220921a.npy +03467517-6c9f5cce840dd728d74aae0eb2ddb027.npy +03636649-89ec7ebc49a312184205db2677c7526e.npy +04090263-760165682193d0d235d753857de68a9a.npy +04530566-bbf1507f7126733665224ccd01ad35d4.npy +02828884-b2dc3053a4643c876ae68b11b0aa337e.npy +02958343-e2349120e4c089ef2fb4628a7a8b337f.npy +02691156-602a71a251857294959a8a7d5a8a5077.npy +02933112-5f7e3d694d47fe6cde650492e45fb14f.npy +02933112-7470935c77e340f31781dae1261f1d28.npy +04379243-afea61dd761b70a3fc0035da39bd5e1.npy +02924116-eecc5e70c70de25f41d068e6df669f0d.npy +03211117-b3f23358467f8c75dc974f7ff5ddbdee.npy +04090263-98fe43e81b9e1b5ed8569d1a6c25406f.npy +03636649-99688a2668fe1fa3cf004563556ddb36.npy +03046257-58507d92c9c0a4f07b79156a61ad4c01.npy +04379243-d01a6b35a54c8f77dd986a55e273fa14.npy +03001627-99fcb202acf5d60950cf3715818ccfe8.npy +03467517-4f401d78068a9d348ee96618ee16ca27.npy +04256520-a8abbef69d380399429c5e5ac1d52cde.npy +02691156-144649df5a5f9c8b5e4cd38353d7ef05.npy +04530566-abee560e2dd721eeb129901f80d24b7b.npy +04090263-d2aef97be32d8118433d7c8e9cebd7c2.npy +02828884-ec4317837dd247dcd2b12aa6a0f050b3.npy +04530566-3970dff155f0a8731aa129fffe673b3e.npy +04379243-d30873e4da202806d42b9650f19dd425.npy +03261776-54bbfb95b752b658c0aaedf10d776af7.npy +04379243-b87594dec9d851c035836c728d324152.npy +02992529-ffd186dcf855e13e26479a182158bae5.npy +03046257-50ad0cdc651ab6fbc6cb0dfa2f14f9d4.npy +02691156-71dcfd1e5d1e261179febb7e11d3625.npy +02691156-bfcc89117315f3da90b1d6deb98feec6.npy +03636649-64eaa45bd2e01db8991ff09eca5b27a8.npy +03046257-ee017bf2df50cf7d5ae4454b5be72736.npy +03001627-2b01a7501dd9780075e0fac069101b51.npy +04401088-2c8699277b2717be66289707fcc0ca1d.npy +03001627-eb7c48d1729fc4ceb04cb542e2c50eb4.npy +03636649-a4c06cd5032733af543df75232f6ff2b.npy +03001627-c6856ffc6e9afdaf680876614ed35a7f.npy +03325088-c4d3c1f18cd11fbb7fed642e5f1ac4c8.npy +03642806-454a88f4b2fe4472f9cacf0b2853f40.npy +04256520-1aafe6bb91e66b1a22e6294dfcaabbc8.npy +04379243-28411ec68714ab87b9ea118461aa8a00.npy +03001627-7fe08cd7a9b76c1dcbde89e0c48a01bf.npy +03325088-5c93abb4d8158919c36fb70296e45483.npy +04379243-a1d7eacfc3e946cbed4671e7b5b34212.npy +02958343-2a844013c66dd19d32e3a970ba4fb82b.npy +04379243-ddcaa720a7b878a4beedb4c8fd29e2d1.npy +03001627-99f02614707ce072e8f8c11a24c52ebb.npy +04530566-d7c58ed725b2449dc570a3d482a3f588.npy +04379243-3249c3ad90085a9e98d5fc0473d00a1c.npy +03001627-106c7f10c5bf5bd5f51f77a6d7299806.npy +04379243-7473f09709d14a2a8d1dabf86742ec3c.npy +03001627-cbb3ece285d9c48ee7e684d25d4dcaf0.npy +02933112-2b3f95e3a1ae1e3f824662341ce2b233.npy +04379243-5aadc1a9220fdbb8349f14616fb49d0a.npy +02808440-a3701a7cf32da91c52b20f433bf30081.npy +03691459-5c4964d7c42cf84bdd9ef3991bf7600e.npy +04401088-fa14355e4b5455d870f7cd075189ddd8.npy +04530566-fc252e6ab475cfd6882046e7e9998f89.npy +02933112-a874dcff3bcf8a802aca02f099166182.npy +02924116-d1f70630a6dd39ab5c3e3ca6678c6811.npy +04468005-91abdd972aa6223484e6ee03d2dfc5f7.npy +04379243-764c1145134d658275e36e88b6617f01.npy +04468005-76a0286bd59daf33ce5aed93ba1467da.npy +03001627-c67a255a26e30abb6b9f3980da0b1dff.npy +02992529-2bb42eb0676116d41580700c4211a379.npy +02871439-f265bb0c3d006754c397356311cbeea4.npy +03467517-58bb21c325f021088f01c8e793a6e062.npy +04090263-5c960809f4f0424d217fc13ba9e6b2fc.npy +03467517-23d3e315f1364475be98a7e88127164e.npy +03001627-53653524f2ec502e8b2b8dc0c816caf.npy +04256520-7402b0be6d04b45da5f9d52c12457194.npy +04379243-244955211c2f3b94b821b834431f4e0e.npy +04090263-67c285f5c701d6cd8ea092ebe8f64ae8.npy +04379243-4f3b404cc30d2306b96ac7572d4197cf.npy +04530566-3583b3e2b8dab3f29d8ea13dd61813ef.npy +04379243-741b91f2187d54792d4fd2b0f2040d45.npy +04225987-e7a5dd6f6ac650977cbfdb97d3d9f05.npy +02828884-3c90d2eda6fdae1fbe1638d01f5577d9.npy +03001627-994dccd2cb784510a6fee8e2140acec9.npy +02876657-3999ca6a50ae47c876b38b4cbe0c74b7.npy +04379243-a63f58a27c22886a721de3dd14942a.npy +04090263-88b978e04c343d25c11d80527540607.npy +03938244-81f8252de176a440f37af16b2893f1d4.npy +04379243-3d5f5cf765767b0fe8e2c411e1e93d03.npy +04379243-b360448cc4b230c672745a2d9975c702.npy +04379243-9e2318099f77d3df3527ecfeb345775f.npy +04090263-30195a2d2fe56a1f6887cd98a5557c7b.npy +02691156-12f3fb99c95c6a7357891d676f728bc0.npy +03001627-7729a6ad96985f4ed1ccbd5d84e5bc86.npy +02992529-8b17963baf2e54f87a0b781a26650bed.npy +02691156-4f2830d3d566220be5dd38f670a033a8.npy +04379243-5cbd726c3ffd8fc49b458816be7a3962.npy +03593526-cec74e921815d1323785c1af944402a3.npy +03636649-5cca570916f420e64b3c42e318f3affc.npy +03001627-fef17c8f92673dd477b7d69aa83ab6dc.npy +02691156-73bcbc2d147291451e7b1f533ce75.npy +04090263-7f41235f55f396118aa27cedfe9e8bf6.npy +04379243-e897ac13dcc0adfe456cbf78e1e89022.npy +04468005-96aac69e5f77277fa0e49cc1ab2aa478.npy +02992529-3a8b1287aed892ba5661e3450b04a6b4.npy +02691156-9e998a06601e9f944b2bd73664dd1844.npy +04090263-3ff0d95df1076951385d661539b5c1fc.npy +02924116-969b8fb8646a799d9a6127d91a931eb1.npy +04379243-8d45802ef679d08a1a3b40747093a35e.npy +02958343-ad4b1cd62d72089e200c039929e0446f.npy +04004475-6bbb7abe06ab037784d5f12fa5114b4e.npy +02691156-464879f87b67827af268234accd8cf4e.npy +02958343-bb7ca919b59a3a2e6b418c7d9fedcaa9.npy +03691459-2c44213112c85413f0c1015881a0926c.npy +04460130-28685f1adb96fb1eb6eefc259009d337.npy +02924116-339007af4ac0e349b1bb46d2556ba67d.npy +04379243-541087bc5ff0e0bb349c13532142fc61.npy +02691156-95240a3e33d607bd88803e631d9fa455.npy +02691156-1678946724380812de689e373096b0e3.npy +03991062-2dcd625ed44bbf1625ebd1cd0b422e32.npy +02828884-44d2f4786d18667a86d0ad6addf83b07.npy +04379243-b9a0e6854bfab1682db9fca4b68095.npy +04530566-9e3c0b7fb69ec3997cd1f8dd6fbce8fb.npy +02691156-aca6b424287392cf3438e17bc657daf1.npy +02691156-c1e6d2235406d250e9ca68dea406967d.npy +03691459-4cee7bc85dae3a58d6a78c624f639b3a.npy +04379243-cf97b60fbf85b0656f236f75bfa0f434.npy +04256520-c7e3aa97aa279582febad4f49b26ec52.npy +04379243-e53057e1a9f6f135b97ad864945165a1.npy +03001627-1dc63eb0c6b1102f5369e32fb818f337.npy +04256520-24deb13c2dd93649d329896bbf26eda9.npy +03001627-1bbe463ba96415aff1783a44a88d6274.npy +04379243-adb934d3f4ed9dce22cec5ca16c50ce.npy +03001627-11740d372308f12185047f9f654ddc2e.npy +03624134-57a636a6a66cd955f16c469ffeb982e.npy +02958343-eda96319f9f01f998496c87dd2a4075e.npy +02828884-473655a56670e13dcb2a965e75be701c.npy +03001627-f23c1bb951fa8909bc01640b1b5116e7.npy +04090263-aad0d20fb05f8fb0cdbadd1af48b5cd6.npy +03337140-7176a2f2662a410558df8eeaf3dad1c.npy +02691156-53789eb9419da78c19bf80b167cee3a3.npy +04090263-83dafc89711bbdd68cb93ad688d1ab8.npy +04379243-20b8c6959784f2da83b763ebf4ad2b38.npy +04256520-89622aab3cd599787088864e604378e7.npy +02958343-5c3fe4057ef12b6886ac29addefc0f11.npy +02958343-9e4a79d30930cc2fcefa74f1d0bc6e6.npy +04530566-8d7af39621a060ef6483ed11b9134e43.npy +02924116-80437e427d0e38d6ffa4d8d9b47d3a6.npy +04379243-813599653f44dcbf245495d3641f83a4.npy +03001627-81e60b07ea1090bf58e4244f8066a2ba.npy +04256520-bf16681e4b86db58ea07fbd08eb87bf2.npy +03636649-3784e4624e880e3d1735ea0e092a805a.npy +02691156-aeb10a6725afb1abc79f92df566f8c6b.npy +02691156-f998bb1b62da4d06d3a1a47fb9b678.npy +04225987-c7482cb7a8db514921cafafd7e7949c7.npy +03636649-80436dff2a30721849655ac7c771b113.npy +02933112-bc7973150ac25b1ce08dea88cca8641e.npy +02958343-45d94dee6634efd516abce8cb03e7794.npy +02808440-90abc75db76e80e244221bef0fa3c36b.npy +03001627-323fc7b1d2b44cb7ff2b8acf844d34d2.npy +04090263-268b57eb7dfa94a55eec6d8d24f1fde1.npy +03691459-aa293b3c1b4f1509e3bf55e5ac6083ca.npy +03642806-66d47a84a3d522dc9311bf79d4774e73.npy +02691156-5b985bc192961c595de04aad18bd94c3.npy +02871439-3c8722f2c0cba2f1788f926f4d51e733.npy +04379243-d58ea40d8a5c8c0c362f4098f2ea31b0.npy +02924116-c279df97ad444bf8cb2ecbd32dc2119e.npy +02691156-870dc1667e957672c66e7238ddb322f4.npy +02828884-807f68d665cf7b0cf4fb4dee5181bee.npy +03001627-250ffcc789426a255f46d55537192b6.npy +03001627-8c76176c82e3e42d283b00891f680579.npy +04379243-f96aeb7884a318bee76bc197b3a3ffc0.npy +03636649-63ca3763b86aaa4daa29ca6a13991ec5.npy +03211117-901170b0a4cf30e746407779dbd69b2d.npy +04379243-654d6b82543a863c3bd24f986301745.npy +03636649-7bc039fffc79dec9e680aea9bdb841f9.npy +04090263-7ca6a11f827014b4643ae903098a314.npy +03001627-b54ae988f5bb6c6b3efeda73d60343e4.npy +03467517-1508f193f91760f4ff04617a8348dcb6.npy +02691156-55cdb0891d7a05fb2217d56276f279c.npy +03325088-70b9b63ce547031276d20e73c57c9a03.npy +02691156-769efbce0af867807456183f198fd1e9.npy +04225987-fb1ad690d8befb5a74bfd4c8606b795.npy +04379243-d08ea9c1e5b9c2687bcae7a654cc37.npy +02691156-8f4c92227704fdf11c568754310e5f73.npy +03790512-af2648ef08812a0aa747c19778aa6cc0.npy +04379243-40343df799bfbc12c506ad4a52a913c4.npy +03211117-34808bb66b2bfa07ab7f9d2da6fc61cf.npy +02691156-48a0d4cb43c961165de04aad18bd94c3.npy +04256520-7c31c4d88c67d094b3c42e318f3affc.npy +02992529-e70ce62b41a598dba48aee3bc134fbf8.npy +02691156-ca11efc8928c10908b96ae1a0a8b84ec.npy +04379243-c302d8053ed38c06b589fc18f8d1e43a.npy +03636649-7124fa42397a447c34db027e489e649e.npy +04379243-a7197c1bd1bd1e47f9715dc5d7dc0802.npy +03759954-b5f84612f4afab9127454bdf69cf23f.npy +03001627-e9651bd689ba5c14713decb1a0563b12.npy +03001627-e64630913e8b723c23ff850238a15b07.npy +02808440-712d9397ec53765f9e25afd4f06934a3.npy +03624134-d63521a0dfac9c1f342494fa6f09f376.npy +03636649-cce6476ac521a1d130f6e0ede20c4525.npy +04090263-144551f27b55f6d69127cdd763fc899a.npy +02958343-ea6d538fb5cf3c0bacdcbcbaae0ea58b.npy +04379243-ac6b9f1d494c9a007ff6ace05b36a5.npy +02691156-c1e081e8b97b3fc7ca8607f540cc62ba.npy +02924116-d5c8e754e1575799e787217f33881228.npy +02747177-de2d9b57b6bd695c6ef50a3361f29610.npy +04401088-f63a0d0c33f7a0c69a83e6b4ae8b154f.npy +04530566-13b7b299d346020a4de203ef6842ee61.npy +03001627-453a678dec4e9d40f36ea1eb6542fe7e.npy +03691459-2c32c107198ac36d37bf4b78d36088c4.npy +04225987-af4343c5b78b70b11082f2ea630bf69e.npy +04530566-f39ff9453d6247fd5ad805579cc24068.npy +02871439-f7e50a524e4c0120f5e4af71271bcb89.npy +03593526-9bbc7da5313433c4af93a86670701266.npy +02801938-2294583b27469851da06470a491566ee.npy +03211117-95832db2feb0cc7ce441f5bb6f88ca61.npy +03211117-862ac718bed40aef2715de3ea7b582d7.npy +03636649-771d4def2e44bc169eb34048e600e1ea.npy +04401088-3d5487efc1d3442ce81f45a785365b0f.npy +02933112-53b396d2ff7af087d01673c7c57450c9.npy +04379243-9afa121e3aec8bd7c387f328a37d8ece.npy +04379243-cc53e7b618721da04b0c98bb5e7fbdd9.npy +04379243-f29863d2fe8863d4195b8ea6a366e14d.npy +04530566-c06ec9a0e32cfd11abdc408c54a4b577.npy +02808440-a807c9e7d931552198e5dcc53f48a2f5.npy +03337140-f2a535d237557ec26795ef8bd10c984d.npy +04379243-c245772cbf233578164e1349afbd1b70.npy +04090263-38cbe2bd51cfb1e47751f287348e54d3.npy +02924116-5376e60ac978731b3e0663c649d74521.npy +04090263-4696d7e82c49aa2a7b6175b1be6bcf01.npy +04256520-47c991f72eaa53c6a8737fcf23389014.npy +02958343-44bd1920adb5fdbb473f10e6caaeca56.npy +03790512-c2f26a9646369c6d373c34785838ee4.npy +02958343-29793366c4b45bf6f43c51e53897fea.npy +03001627-8ec16015c0956f847acc6457762e6ee6.npy +03001627-d46e16509b1c91b3933dc172307a6bb9.npy +02871439-51afa4e0aa973f8e8798cb61bc1bf943.npy +02924116-6198a0042a1fbd8e096abd9da1e14da.npy +03467517-9019d3332cc8fa89a40020a6eb12ffd2.npy +02691156-aff5f5ac9dbabebee5d07633dda45110.npy +03001627-e34658debcd1644dc8687ff9b0b4e4ac.npy +04379243-dc68436ab1a576f6573d2c9ac4b23fdf.npy +02691156-96ee3ab4413dca5a48d2ba4615e03b21.npy +02691156-2b8bcb6e208a69b16a3383b58c4a9330.npy +03467517-a24d5a44843f54ee26587cb13c78fb9b.npy +04330267-74b1c02e8862abdf1d1f7b2cee80fcdc.npy +03642806-4b4dee079f46cb516b99fe64076e852d.npy +04379243-bce971ee4e980b77e3f7a74e12a274ef.npy +03928116-81412f3a04fb62c39a595400278b1b6d.npy +03761084-c57ce5ac1f4f5e127bae653f822044a6.npy +03624134-cae0a0c69888bde2daf44b37a13dc4d9.npy +02691156-bf78d2e27a671fce4d4cb1c2a5e48b7a.npy +03636649-69222648c3e3ed986c348bc129690193.npy +02933112-737fc2d91572a9032ea98d69e91ba870.npy +03593526-70367e4fd1ad753427eb00c151c6f711.npy +03001627-2ce61518f138b7f75d009c98a5b96836.npy +04256520-4975537eb678cd54ee8a0a0ef14611b2.npy +03636649-fb2de79ee3a257eaf8f5708c6c7585cb.npy +03636649-a3b93f34b7e36cc52460e48c67c108d4.npy +02691156-df1c68e94259c6cf5c7319b71bdce6e.npy +03211117-78f69254fdbe4cb4ded49d32c1b10de3.npy +03001627-adc76ddfb1d619a25dc3653f8341633a.npy +02828884-e5b1626359c609a59d297e74104d3ac3.npy +02691156-1482d7a9e529dde7340461a254c1a95.npy +04379243-6281381ce38aa988de98d10ab5975b59.npy +04379243-45363f30a1e16c215963245f0923337f.npy +03001627-5952c6c49ace76c5beea20858a99d5.npy +04468005-fc3f81e5a2bfc2a08be7c8c5fdb9bd6d.npy +03001627-20eebdb573142c4eb0a9829865a5e240.npy +03593526-ee490d76aac9cf342f2318fdd66be40a.npy +02924116-ed107e8a27dbb9e1e7aa75a25fcc93d2.npy +02691156-e41c5719ad09055f1b880c747ee1f83.npy +03001627-5482bda23163df4f30e916fac260c672.npy +03691459-9f242e37099ac424c3bf2ffa047e96ea.npy +02818832-5b584c8178fff5bb77fe1aa9b41a89c5.npy +03211117-1dd8b03b590dc0ff9470c43f253f33ee.npy +03691459-40b492e1a0fb0860e2f05bd11e1d1c68.npy +02958343-41b4832983f44aa3a7fd25564c2e888e.npy +03001627-df6ca774d390755cbd18e74cb7446915.npy +04530566-bdd8d8f6e6536c0d4d16452ef1302b59.npy +04530566-6a7da232456b16e852f03e17d84c12b.npy +04379243-677f0b4f9c5398caa3e1d5a29d2bb5b9.npy +02691156-3a3403fb14bdb46823e79e99b949a341.npy +04225987-c8aed131dd905c6e1082f2ea630bf69e.npy +02924116-6312773514521960f5770725611ee0cb.npy +04379243-1e90d86b5649720047f453c4a13e89b9.npy +02691156-e4e1b542f8732ae1c6768d9a3f27965.npy +04379243-61aea77ab9adadfb3eeddbccbf885e99.npy +03001627-d481cc9e7d6d7d64baf5b49ad7809302.npy +03211117-6c49b516b04e89a15817e30de1dabac4.npy +04379243-feda1b3bf39743d8f16ec553491baad7.npy +03261776-51245ad5a0571188992fd3dac901d508.npy +03636649-6d15af6141ea7c918bb3deb7fab7c9b7.npy +02691156-3576bf753aea3dcf661f0ad700067cc.npy +02828884-dd97603ce7538c15be5bbc844e6db7e.npy +02924116-8042307e75e578ec80b4025fb2dd9473.npy +03593526-aea1a8fee02c011db8183a4a81361b94.npy +04256520-c365bb7af1fd9fd490ad276cd2af3a4.npy +04379243-a01e8ade2a92a0eb35836c728d324152.npy +03001627-72cd991e81a34504d838ae16242881dc.npy +02958343-72ba2195087f80d8b7e8c57d131d2ca7.npy +02691156-d59cd5f2012a1ca1aae46a5cc955c766.npy +04004475-e5b8c6300b1338c95cc4187bd88e76e1.npy +03001627-9849c890f3bc80723a4642fe4c259750.npy +03001627-d311e10015f19bb7482d5f087974fa09.npy +04090263-4bf3fd740498b489a7d276ed256acd94.npy +02871439-c758f0524891b18110b7af17eb4b15c9.npy +02958343-ec9f938ad52f98abbda72093f9b5aa73.npy +04379243-37e1a5d6689a83d3b03169de4ffd172b.npy +02958343-5a9cb2d24a3591aa27fda8a7465c0e0b.npy +03001627-1c3f1a9cea91359c4c3e19c2c67c262f.npy +04530566-ea940968d0ba131e7b66b8fe985fb060.npy +03211117-5e64913f2c74cb4825680a002b1d7d67.npy +04379243-7b92f6facc2a27bc84cc0348a73b80c3.npy +04379243-618469f067751604b0b9d11504ae34f.npy +02828884-5a86b8c93baf8ad0a9030dd33d75b731.npy +02828884-49908190a4206224f28732697aa0af57.npy +04256520-e8d6ed94c67d6f43708fed31e484f9c0.npy +04379243-5d38978fa7591a3465a50d0cd9008f5.npy +03001627-8c0a0360a7353ec26dd3cca80cedd415.npy +04379243-308a43b7ad3f8c2bdf8a6816927a07f4.npy +04256520-2bd1439924492a3fcea6c8d9a419e8e0.npy +02958343-d20990638711f55967bf54a1f364120.npy +03759954-2b717a6fb2aadcf9a22dab393015702f.npy +02924116-bc1c76c847e4dd6a28c978a3d9ad6d7.npy +02691156-e0a8ae255ed47518a847e990b54bf80c.npy +03691459-368d30ee72c63a9512da48a027621f2b.npy +02933112-d8cd6611c5f407cdbe81a9109a782712.npy +03001627-7eaf212097293229fd3456bfc7553c94.npy +04379243-32761afb4b1eaf31810493eb9cc85e00.npy +04379243-6c026a5f412f0b93002761e7a3ba3bd.npy +02828884-812665596d6c13b1adeb1694faeea26.npy +02828884-29fafe9d3b95e324535e3a87e2212e35.npy +04401088-ab4ddf9e4130d6b560cc5a290ea3b31.npy +03001627-790d554d7f9b040299513f98ce033426.npy +02691156-48b99ae8fbe0762a8ed04761eced33c6.npy +02958343-89eb1c5370b80567473f10e6caaeca56.npy +04379243-6d4128ab108730f1ab610b0c94236463.npy +04530566-aa0e4a79926c68f9bba1d36dfe35a060.npy +03001627-752102fb466042576a63d6c64bf6b56.npy +03085013-980ea79e2dab7a595f4027209dc8065d.npy +03761084-b546876ab51eb402203eb08a0c3b4355.npy +04379243-8eb9536af97f1aa05608802d2be44a9.npy +03001627-a643edc1849558eba81634d14a6ca786.npy +02691156-7f1eaf37fb4e24de82cea33798fcd6b6.npy +03636649-17b083510f14982b7eaeab1f0c9120b7.npy +02924116-303ae4f0f8aa96472889da66a4dd79e2.npy +04379243-c399ed276ed35cb9a6ce08f0d82ba063.npy +03001627-6d866b3d22082b89191c3762b497eca9.npy +04256520-f3e10fe9995b4f864b3c42e318f3affc.npy +04379243-ab5faf4dc8b23517ded06cbcf08b2fff.npy +04256520-14b9fdab8d264fc214038d588fd1342f.npy +03513137-190364ca5d1009a324a420043b69c13e.npy +03325088-e45586f848a038243321831d2245cf06.npy +03691459-17c5950c89528703225f3f0d46b4fca3.npy +02828884-667305123da07968d2b12aa6a0f050b3.npy +03001627-ec454747a071b83291a302a171d24a87.npy +03001627-431ca0621cab1313b0204d9cc6bc8619.npy +02992529-180ef1cc23b96050bc8c03f74d3af56.npy +03337140-d1155a28ca74dac83c4f66791e25960f.npy +04379243-7b89037bf1695628eb03e749ccd7a541.npy +02933112-da3a71168ea830dcc82d9accadcc9c9e.npy +03691459-ee2d8d72b555df84ad5d27efc990ebb2.npy +04379243-b2cee79b97104212aab142a21aede3bf.npy +04379243-9bd1c242bd66d2fbb63c01786992bd2f.npy +03467517-d157227240617cac755f5f999c69a058.npy +03337140-d0b6fb93a69beffc4c3aee8e9d3a6ffa.npy +02828884-49d0d178976c81f52056b4bd5d870b47.npy +03636649-75ae2c70aaf3c818d9c283deb7cdce0f.npy +04401088-2a48a703451da580555dee99eadeb47b.npy +03797390-85d5e7be548357baee0fa456543b8166.npy +02828884-9e5a16d68611c57cb2a965e75be701c.npy +02958343-7b2c86b542f822b1b8cf782e8c539948.npy +02818832-af2e51ff34f1084564dabb9b8161e0a7.npy +02691156-79a62c385180cc51da67790f4274f014.npy +03001627-8fed5abf598c5d113379c738ca193530.npy +04256520-8e4999f0e6bbb791f51f77a6d7299806.npy +03636649-5f901ee60f9c0d2c6297030373bd4c3f.npy +03636649-64c393bec510aa63c83f06951aa9795.npy +03207941-a4576a087360458a5194936fd57ca90f.npy +04379243-94aef6e5634907b16ed6e9e08c602c83.npy +03001627-499c4b519c708ae84cd08aa7c510fb85.npy +02958343-53125271f866288dc8b3f3d7aa7cc0c7.npy +04256520-6cbcf4636ee5593f75a82b88fe6e733f.npy +02880940-fa61e604661d4aa66658ecd96794a1cd.npy +03636649-d7ceec3ad0cad8093164c8a6f66d85d8.npy +02691156-73934196c92ce472f4a5531fe6556d72.npy +02933112-3724c3633a0db0c260a7085510f65cd6.npy +03001627-ec91b1b29b6bccd37eaeab1f0c9120b7.npy +04090263-e0b38e1386eec67624c5b9ac3d3770de.npy +02958343-4145debb6cf68ec0afe1d4530f4c6e24.npy +04379243-75e24952ed996c1072dc9d42e683347.npy +03001627-432ec0e5f2a07ab8795bf1abcc63e867.npy +04256520-75850c6e67073a2a593ebeeedbff73b.npy +03001627-d9943f96dfbdf331b17743c18fb63dc.npy +04379243-8af24cacd38e9c0aba5342d638d0c267.npy +03636649-eeffd79536a7ab3e597ff152ef65c9c3.npy +03001627-2ca371de1093a3867c9386abeb61de4d.npy +02958343-98d4f1e36d400acf5fd7e9b026930cd3.npy +04090263-b72ed7c7239e7bfd8e62f59b444d701a.npy +02958343-f9c2bc7b4ef896e7146ff63b4c7525d9.npy +02871439-72b84b9b53fee78c664b3b9b23ddfcbc.npy +02958343-9fbcae2f132db088b09b4c3b88665c4c.npy +04074963-98f33f33eaf6ccd3b09914703fdadd6.npy +04256520-53c1b173913bbc2b63d467b618e97922.npy +04379243-2bb137095c73ef6fe45ef4135c266a12.npy +02828884-28353d39cde416d0ed49e2c2d58fcee1.npy +02691156-a074750e28ed3818203936772104a82d.npy +02691156-d1a8e79eebf4a0b1579c3d4943e463ef.npy +04468005-95cba66f344cca89bf3ccb21f1908cc.npy +04379243-983cd9caf65adf1ddf6cfab91d65bb91.npy +04401088-8f049b65309d8390f5304dc8cfbb76e1.npy +02958343-7bf95b4dad8c1244d928f30a3aa85f67.npy +03642806-61972112749c9beeb95c80bb1ee18b0e.npy +04401088-5286f018c374d3ec3f7fe3cbfc3d51a7.npy +02828884-f60378083ea9b7fa5e14e00a99d44acb.npy +04379243-7fc3bc8542f4c17ce4511d9a59e40339.npy +03467517-9358f81d204434db1cd605219498ddaf.npy +02958343-39d161909e94d99e61b9ff60b1be412.npy +03991062-1ab5af367e30508d9ec500769fff320.npy +02691156-7855e8ac604ae162bbf3143b1cb6076a.npy +03790512-a70eb1b6321022e260e00ef7af003fee.npy +03991062-16e6fbacfbbc4bcf9aec59741c69cf7.npy +03001627-4447ee47cd2333f6349bb1cbbf9a4206.npy +04379243-9ae98c4b9fc07bc1beedb4c8fd29e2d1.npy +04099429-eff3a27a085e02e5146be45f8a3c1ff8.npy +04379243-6d00c1008f41a099eaf288f952624966.npy +02924116-eea7be530ab0f33e41cefd10ce5d6cc0.npy +04379243-114377fc17eceaae3e12d7ebda60f8f.npy +03325088-dd4f5eff165c85d8200a3881cd915629.npy +04379243-692e96270191113358df8eeaf3dad1c.npy +03211117-65582f49b9191ea805062aaa3bb7665.npy +03467517-6d89c3abfbc99a29ca3b1d47ae5d14fd.npy +04379243-27ef271434e2ab43f07fee5fc5c45ee2.npy +03642806-75936cfb6c3ee142205444155ae5c84d.npy +04379243-61527f3ea1741800c3bd24f986301745.npy +04256520-bd199c38c0fd7602c9f722bbac7c6194.npy +03642806-5d544ee4b094c6606436916a86a90ed7.npy +03928116-4f3300cd29c8b45eb1a6bf6b45cbdcde.npy +04530566-a0372d1c35e531e7130b54be1fe602e.npy +03337140-9c36412009d5311e64d8b0368afacc65.npy +03001627-a56e201584ad5afb61ad1cb92b23bf5.npy +02828884-486535f610428612cf078dc7b29022e6.npy +02933112-b5a0f4e52687b87ea5cbb6810d19a105.npy +02691156-64cb683afd5e9e559db1d21b460eacef.npy +02691156-da12fdb456d5fb588b96ae1a0a8b84ec.npy +03761084-495543ebd719a29ceeb8d422649e5f2b.npy +03001627-37c5d67f97a2231cf51f77a6d7299806.npy +03001627-4e1dae6ca4f220048ee0cd746086d989.npy +04379243-d477a17223129fec53227dcd0d547ba6.npy +02808440-2aadee812a70aa79fb3819b3d3d9c448.npy +04090263-190ce4466c6f4c04fa9286f039319ff7.npy +02958343-b87ae16029527cf3fa87597d91a3e9a2.npy +02691156-a6a27c5acbf70ebd3df325aac2f73830.npy +04090263-cac1edcba53ae3d16b2c8bb96250e4a0.npy +02828884-d27d44b023a8ac1a54457eecf7344025.npy +04379243-bf293b370275cac173eb02f1d995d891.npy +04379243-80ad1f839582d183fbf6f493308acc40.npy +02924116-3ad9c664f9173bd33746b762571ee4e8.npy +04090263-57972c646e88289b7f9e2c1c83736d47.npy +04530566-3ff7e02233affcc350eb615eb69452b.npy +04401088-fe9d97823a25e56d95e43220ee0eb824.npy +02773838-22b7d6fa819d62aefc69b7db9c6d5ad9.npy +02828884-fb2627957d4cda1bda31ead4cf13511a.npy +02958343-f1eb3f6c5a5313564c7d8ebbbb68f5.npy +04090263-c4f95f531b5ab758b91a90edeb58ed0b.npy +03001627-6ac89c723fcd7a55467971b4d8320221.npy +04379243-89a7bd3d0af7be05104a4ca1203542b6.npy +02828884-c33adaafb71b0080582f9c2e887b930c.npy +04090263-c518e4b872a0841e0652a919e7ad7e6.npy +04379243-954ae626fe09e5ccd5cb6d178687b980.npy +03001627-4011b7d293cbeae11890f3b4ec900fa.npy +02992529-d932fb5d06d5e4f8da8c8a88ff86c5a7.npy +02808440-b46801f946f4dd403af30a3946d92feb.npy +03001627-b8fe0dd70bae3a9dba7a8c9ac8add14.npy +03001627-1e6cfd4bfc6270f822b5697e1c26fdf8.npy +04379243-59f4f7f1f7cfd0f3831ae64559c8e0b3.npy +04256520-9faefdf6814aaa975510d59f3ab1ed64.npy +04379243-11a559d19457ea3950cf3715818ccfe8.npy +04530566-183054ec6b2665a38b2b48d71cfe16ab.npy +03636649-40c778a9ff366c2bf36ea1eb6542fe7e.npy +02933112-b34ed11766d80175f40dbe27bdacff57.npy +03001627-f55a514cc8f2d255f51f77a6d7299806.npy +04256520-85644a68a1d5f4cbab610b0c94236463.npy +03337140-3c68117a5d4e9d5814d271edcaaee8b3.npy +03636649-4f1199474ab8c9b240cd51e913c7ba8a.npy +02924116-8beee0018157032415b08060dfa6a939.npy +02828884-86059f6fa56a8c5e44175b4dddf5be08.npy +02958343-2c8e9ae34ce33a40ab2c2809513f396e.npy +03001627-2c149e5ab744616f60ac8f16dfbc3b59.npy +03001627-e76457b55a3c041cfe49db72b6ffb2c9.npy +03001627-953a46766108d4e01f60a203be892cf2.npy +04090263-4539958ad62e662ed197ecac88773a00.npy +04401088-fa98d507d82d325c80202e5aaf48e957.npy +02801938-2bcc1b8bf5ac9ddc97e30bfe57d923fb.npy +04379243-84a354fd068a410d40719bb3f7e29ad5.npy +03991062-a09c1936162854e6f66cfd1e680c17b6.npy +04330267-acef3518b152a08e5645f04397aca2cd.npy +04379243-e56196f67d724cb892f4c88fd91c6b1b.npy +02691156-f533dc37778c6f004c949161e83c47b5.npy +03001627-691b10e17ba828e2b161f36d4e309050.npy +03991062-bde637cdefab785d51fe629e42afb50.npy +04401088-54de8ee661787c1d16d46ee44c40524.npy +03001627-8d14cc01f39f2679a857215a199c2ecb.npy +03001627-8e9247a97fea8e0caab901f164e48538.npy +02876657-e7714b3280fa7f925b2cc658332a8e03.npy +04379243-5c0810caed3ca0f83bec56bff764ba78.npy +03001627-6a6f0168ce551ebf40d341bbe0ce6dc3.npy +03593526-4fbe0133d0df10ef5636a727f8e7b7a.npy +03211117-30fc571d408b84cd6315023d0bef39b6.npy +04379243-55104b3d3c3f853992bd9b46d18a6c1b.npy +04379243-d03256544371f1eafa6e1fd63f4a1c35.npy +02691156-c049dcd36058a87e75b7e61db54ffec7.npy +03001627-389db7fba32b71182165c54dcecaacb4.npy +04379243-d8be4b45afb21cf1616fb9ab42452112.npy +03001627-ce23daa630833de7d9fad8aba2c312b7.npy +02828884-c005e1da092925e5aa3e4791e7582e61.npy +02958343-1da433472693082a3b03cab05e253d9.npy +03624134-f4dc11f89dd2d21eccd82bb51193a7f.npy +02924116-c5d30dc6bcabbb56ceeb72b524f3e0ca.npy +02958343-709d6b2cf528e10296d1882ee61d6c58.npy +04530566-a8f5ce05ab3aac91cbd32f07d6724eb4.npy +03211117-be2f04d1204c86d4db70fa8937c64733.npy +04090263-e57dab2d63693b0280c2e60c312b0f09.npy +04379243-19354bd08463173480f6183c41836dab.npy +04379243-2e13d82c2dd5d0714251f7ff551cfb5e.npy +03001627-5c027016e14cac15ffff2fb60b0d6e6.npy +02924116-92d0fa7147696cf5ba531e418cb6cd7d.npy +03691459-9a9e5e5e3e034e74fedde756c9eb0eaf.npy +04379243-426fbc6c365147fb6430c2c15987e4cd.npy +02933112-a82276d1ca28e11a4d87481e09b681b3.npy +03211117-80976fe087ec183f3de42699b619b796.npy +04379243-da8ec638b64227066d767b6d0313d349.npy +02992529-58c6118bd15ca3b48dd025faf4cea27d.npy +02958343-a2b3346bf52d4d5acee5b7ceecf56d71.npy +02924116-54ca4c3ae9913db82e255cf9f3f0b410.npy +02818832-560854f624e60b6cadab4c26397edfab.npy +04379243-e9383126d043156fc1302d82d108316.npy +03593526-4784aeb9d867aa83f685327911e7e258.npy +03467517-e5c64af35ff60ce069da8e7f9a803d12.npy +03636649-600b2f00113ad714e2367b9e27f16a71.npy +03636649-9e7ae4e322a056b954cd2a0ea6cb618b.npy +02880940-a1393437aac09108d627bfab5d10d45d.npy +03211117-cd9d0c82b16aed01e4db95aedeacfd37.npy +02691156-74ebf601d9c872a7828204947d78b9af.npy +04090263-a7072394bb9d23f54b49cd65dfcc3a9a.npy +02992529-7114283643761bb4a5545c1d5c84020a.npy +03001627-89a13017c0d517319fb4103277a6b93.npy +03691459-b04281aa2c134623cb3c1170309e6b12.npy +04554684-1b77c0248add1d5540b559ef47048b86.npy +04379243-ed73c41dcfe9170119cc3eaf35cd388f.npy +03636649-17349d6d35aac0685ed28d6c8a1bdfe5.npy +04256520-8b8152865839a79719fb4103277a6b93.npy +02691156-92cf58c641a4e5af56a793e48de27b07.npy +03467517-821316d050fb993b1dcb4e3497cb68d4.npy +03691459-8877b9b8e68fcda696d7d56afa10bb68.npy +04256520-a5bec86d283a19aef296d2773652c8e4.npy +02691156-ec9bfc810a015c3a446cb1ee5d43f75f.npy +03001627-6abacfbb354818b1adda578d985c7034.npy +02933112-61f79a63ee5315693fb45d07cfab7906.npy +02946921-fe6be0860c63aa1d8b2bf9f4ef8234.npy +03001627-7af9eb2ebacde5422a373b90044f1dbe.npy +04090263-b7e25fa0ff4920f28f5b599a9e7928c1.npy +04379243-9c4dfafdbd7f9b76c955e5ed03ef3a2f.npy +02808440-1b6bbfbba694e33476c18e71fd49c4dc.npy +02933112-225905a8841620d7f6fe1e625c287cfa.npy +03710193-e939b756e10ceb73f83d66144c2cbfe6.npy +04379243-c2fe8c88c2b42564415434d4384bb66e.npy +04530566-cfd92436ff0d0779b011f864ecc25526.npy +03001627-c8daa8e9496580667b9c6deef486a7d8.npy +04530566-eb214ca65059e8d8fb8de648691848ea.npy +03001627-7667d0da445e324bba600d75deaf8d3a.npy +04379243-b789ef3e2e28aa0c3b08200028f31a6a.npy +02691156-32da9294ff0c3d8c7a40e1005054fac1.npy +02808440-aa1200913fdb9f1679d57ee14f8ee702.npy +02958343-dd1bc8c4063a6521456a647a9e7d914e.npy +03337140-86fbcd62054c7dbf4c3aee8e9d3a6ffa.npy +03991062-fa8538255c27636753c42d8148a60bba.npy +03636649-aa0c8d5c38e8c87f805e3a6c310c990.npy +02828884-b3974f214dd4af93601104cd2d998272.npy +03624134-7422adf7859315961000fcf84b12c2d3.npy +02691156-a12179d6f8b753a934a446df7eff04e9.npy +03001627-4f188d1f92b859fc283b00891f680579.npy +04379243-40eb3b0b1b43f8cdd0a96520c31993ad.npy +04379243-a1efc57eedf9a2e93c8311d2f6bcff87.npy +04004475-5971d36336f3cea81baa19f2d6f07ecb.npy +02747177-fbf7021503a2a11fce41b639931f9ca1.npy +04379243-6ef4f1f0b3f8aad48cbb8bac2032149c.npy +04256520-40da067ec8d56e2242a61f5042a573f9.npy +04530566-ad0879d8dc9312b5c6cb0dfa2f14f9d4.npy +04530566-772835e02fec3a93629f9e3e495fed76.npy +04379243-d9daa0e33f695897136d9cfd13835101.npy +04379243-adc763e089e2535fdd155b45c76af694.npy +03001627-f2129c67cb55c6868779f85a8bc31fb.npy +03001627-779e4f9f044c71612f95e2a1e9997b85.npy +03001627-1762c260d358a1751b17743c18fb63dc.npy +03636649-f18a519effa019d819cb07ecb5b4102.npy +03001627-c7f0d32287191563bf22a5ca4fa4678e.npy +02958343-c6441f127d51e478f0fb72d24c42a39.npy +03001627-d0d18af5959e613ed3040d716596ad68.npy +02828884-5dda4ef4ab9add9411ee8243f54292d6.npy +02880940-a08af31cb43f1f662d88c45db31bc366.npy +04530566-118d43609d6de540fdd92f489e57a4cc.npy +02958343-bb39689b3e6568e85ea174ca141ad66c.npy +03325088-8b5fb07c0ca26bf4b362845c6edb57fc.npy +02924116-2c922ea4c2fdd84b270b857a2cb41e7c.npy +03001627-46c6dec63dd7c45854ca97f654da3901.npy +04379243-8f8f98df7a9caa18febad4f49b26ec52.npy +04379243-8f02a9ff58479e59ac51268fdb437a9e.npy +02958343-148ba646cf954b9249352dd33f95cb9e.npy +04379243-73e9e162c2d4f90a6c4acae4ea0d5870.npy +02691156-604392af2cbb7d1fe30ec10233e7931a.npy +02992529-496270f12655bb84e38ab39b0490e043.npy +02933112-63f3ea0c41eedd19f51f77a6d7299806.npy +02801938-9969392f6425a85750da8b99982a3057.npy +04090263-7823da328516db23394e22ae6de2db18.npy +04379243-383fed2f8f81108c6fa63795f94c4d8c.npy +03001627-5c233981556ff20fcaf36640a0c92faf.npy +02933112-1f674f735abb7b1d75869f989849123f.npy +02958343-e9233510c6e0f2672a9eb0f146e94477.npy +04379243-8657197d00d103ad4ac2955bec7764a6.npy +04256520-fe29b89c392e1bb39a2d92ec05f8de08.npy +04530566-2bf9436a79954087bc585c195913193c.npy +03001627-dfc85456795d943bbadc820495ddb59.npy +04256520-ef05b57542cbf151e7e684d25d4dcaf0.npy +02924116-6d3f6953945f4f38193d7855ecfc1bd3.npy +02871439-d8b0928ddac7b02d664b3b9b23ddfcbc.npy +02828884-38e367e4421ec3cbba70cedf91706353.npy +04379243-45122ce45ad6bbc0668ae11a7db5e82a.npy +04379243-cd106955d3bdf8e751c4deb11af7079e.npy +03991062-cb2dfb2ab016e50a2c59a4d90e63212.npy +04379243-253b7cf1ca03674bf4b6538438a0b930.npy +04379243-a7e343ab31f1e113beedb4c8fd29e2d1.npy +04379243-6726c2d72f835554781ba0fdb47276df.npy +02691156-db758090dd739ee9ca68a659ecae961c.npy +04379243-74246960cafebda4ded4c23d05709216.npy +03001627-2842701d388dcd3d534fa06200d07790.npy +04090263-3728ea8fca746a8d52499cf3d29e4e95.npy +02828884-eb9938d81ec9005882db9fca4b68095.npy +03001627-7212bdfab35f72b23002761e7a3ba3bd.npy +03691459-fd11b075bb1df4b01f1c09aefb59ebea.npy +04530566-6ba7c592495e203f49006426f75e891e.npy +02691156-8a6ab7486ecbecdb203936772104a82d.npy +02691156-84b84d39581a6766925c10fa44a32fd7.npy +03001627-8f3c91049838cdf2b04cb542e2c50eb4.npy +02933112-74104e62e8fbcbeed0b36851d61b6fca.npy +04090263-e5beb08af46a6b8f6fa28a58edcb926.npy +02924116-efdec3c35b0e36128449e0b8dd14796b.npy +03211117-a52e505fb03e2d8568292529fb38e524.npy +02691156-8def338aaf898d6c26479a182158bae5.npy +02691156-9a84164528544d5690baeef8ba5b93e5.npy +02958343-c9d53c90471eeb06ed3696d854eee1ec.npy +03046257-4ea7645a8421c2cb9c2b8a7ac19b29f5.npy +04256520-dd4a6a955c925d7762fd9a1e220aec64.npy +03710193-2912f56d135e2f97b20cb946bceb58f.npy +04256520-bcd6db8d23cbb9a9cf19858fd1963d10.npy +04256520-c2d26d8c8d5917d443ba2b548bab2839.npy +03636649-1d198eb08540837be9bd6b804c8484dd.npy +03046257-b4ba086ae065fbe3664fd9ccc8bafb2.npy +03001627-76389d102e3fb729f51f77a6d7299806.npy +03691459-8a8f13245888b8a1411171a7db2d5342.npy +02933112-4aedc26af43f08d08f7d9678498f2295.npy +04379243-cdc9ea006d761feb8c56c26d10173bf7.npy +02801938-d224635923b9ec4637dc91749a7c4915.npy +04401088-62a6de09ff956e997b239f1b8ec0d46d.npy +04090263-36d4635979ae79256314c3b6a3a65519.npy +02958343-35d473527fa9bd8cbdb24a67dc08c308.npy +04401088-38881e9944ea86dca374e5b9b6427c16.npy +02958343-b10794a03c59e42d32a4e3dd3a89488f.npy +04401088-d4a038b20b1250d7241d076ab53023c1.npy +03001627-4a1510e398260ba36b31862e09495f2.npy +03001627-be4c88a130e622a21961e650f3cfa396.npy +02958343-dee6c7e696048330ccd4ba9035439a85.npy +03991062-63787d5ff22ef52a2eb33053525e23a0.npy +04225987-d4c492d7076b1e6160eeb9e113ae7397.npy +04401088-609321c1351a955c1e1f8455cdf1c0bb.npy +04256520-32859e7af79f494a14038d588fd1342f.npy +04225987-a1d36f02d20d18db6a2979228046d9f9.npy +02958343-432efbe7784cba3ba65b1575070b0b4a.npy +03325088-4ed3d9c8a8ff37ebb7a867e9b35a1295.npy +03636649-94fdbb748526dae4ea2d70ab68cd1d2.npy +04256520-8a484fb8faf9dea01495d00ce1193982.npy +03325088-c956fdc19b02782bb7a867e9b35a1295.npy +04256520-a66befdc2b049fa3eec26c23f5bc80b.npy +02933112-860929843ad9e7e16ff961d84ac7046a.npy +04379243-df2244d33847f7cc4802d94e40825ea.npy +03691459-23efeac8bd7132ffb06d0ef27244d1aa.npy +04401088-1b43d9193794748e31811399a4ff3aa0.npy +04256520-145bd097a4b1cb8a44db04bfb021976e.npy +02691156-7af2dfbf11201feac3ab86afd1c689.npy +02958343-4ef6af15bcc78650bedced414fad522f.npy +03691459-f1175bec19adeadde188dff443a0c2ac.npy +03001627-37044d4f5fbcbe9bae536f42ef59cec5.npy +03691459-e8ffa936875c7b3a7ffffd2e0fcbbf0a.npy +02880940-faa200741fa93abb47ec7417da5d353d.npy +03001627-fd1a87a399c1c82d492d9da2668ec34c.npy +04379243-3b64bf8731a6a2a63c5e1addd9922bf2.npy +03001627-bfa435c63b1e96d3492d9da2668ec34c.npy +02871439-ff62d6b0cde34b7f6f1e631ee7d027b9.npy +04256520-c839f879381df0f0f42a90fe4baf4591.npy +03948459-afa2048d3da423ed3f5d17ee01b81759.npy +03948459-445a386fa38254aa6aae23d08e2851e9.npy +04225987-ffea27596947c29cc983a1dbe02fac40.npy +02747177-1eb3abf47be2022381faebbdea6bd9be.npy +04530566-d3ba52601a902f407f436bc8bb8973a3.npy +02958343-4a1b48e1b53cb6547a3295b198e908bf.npy +04530566-33a9a04e7d8ab8ce861ba49603151327.npy +04379243-602526e4a9de3f2c822a33e080d0e71c.npy +02691156-f6f2905883c49d179e0d0faf84afc607.npy +03046257-395c82f7a56b5cb0ef6c510e24348d3b.npy +02958343-6976cc9f5982474e9aae70753d127b0b.npy +04379243-aa6b5cad531b9ef982db9fca4b68095.npy +04379243-40cb833fe986db191ce7600faa926b91.npy +03467517-a2a57079224183faffb3fd15b3de82ca.npy +04530566-e00d3546401b6759710b5d09f274df.npy +02876657-8be0066e544e11da664b3b9b23ddfcbc.npy +02808440-1866a0bcda2564053321831d2245cf06.npy +04401088-e1fb2b5e5a306e6621ecd2b49af349a.npy +03001627-3515073c473f4ec94b3c42e318f3affc.npy +03467517-3ebceeb3562ed5c751b42caefc789eac.npy +02691156-52cd5876945106d154eefcdc602d4520.npy +04460130-1683c5bc839969f438cd8eb23853c009.npy +03001627-e9e8f839c77a03498307335ef66226a6.npy +04379243-c91c78e14fccbab316a2b5862518c93.npy +04379243-b82c6769c98e877d24d29f1dedd03a57.npy +04530566-dae38d7110c4bf252f84cb7932f866fd.npy +02828884-1bb14f4633ad52e3ae944a46a2846086.npy +03211117-f35e818eba233a7734bb689093b9bebf.npy +04256520-d4dddfd40635a72f1cda25fa42fa5ece.npy +04379243-75f9ad7ded87bffe1bb088904f7cb154.npy +04379243-9482c5f0a38a73c0fa16d3c3138134ae.npy +04090263-4c9c33529e9a555458e51bbf75d8cac6.npy +03691459-88bddaa41de4fc386f936ccdbda50e38.npy +04379243-1810b6accc77d7893918f23e2305ede2.npy +03001627-804cc836409c921ea666d560e4dc80d2.npy +02691156-bfa52c24ed71614f48a7b7802dc31138.npy +04379243-67bee18dec77f305e4af5827e8177766.npy +03790512-89aa8433ae3b9a197395d58407f193ba.npy +04090263-1655608678a4f9ffbc7bb5239e53ea6f.npy +04099429-add291bbd2c208f249d91b0fd3240957.npy +03046257-7bb10722ce68c6d2afbeec40033bd27b.npy +02958343-d1bf2bf3302c0ec0e21186de41a0101.npy +04379243-3842243b1f246b3dc4e62ff7caeb0b29.npy +04379243-11cd9cbf28d3918f1b17743c18fb63dc.npy +02958343-1b1a7af332f8f154487edd538b3d83f6.npy +02808440-3290b970bbb388fa3c8d0fdfb1cc2535.npy +04379243-8768002c872788b8e513931a191fd77c.npy +04379243-90cd1d5e2f33888ebe9fa30bb5c5d8b5.npy +02933112-513cc5132f0543d0b47cc2471d9dd7e6.npy +02808440-52da987951645a4b3c8d0fdfb1cc2535.npy +03636649-6b9e4403230a162b54fb5025c749b481.npy +04530566-60cc5839008caf13cea6e9826e81ed40.npy +02828884-1541e36e8dc2d84caed2201239784a35.npy +03211117-742705ebaa879604f2e5d34c7b677bc4.npy +03928116-17c154783360a7126f2cdf5afa9a3cb0.npy +03790512-4878886fb154d54366c6576de41cd6b9.npy +04379243-32b63d54261678e266a713431ac35e37.npy +03636649-dda91a2215130be16035905876bb696.npy +04379243-c1a04d0c233263aaaa199671f55e5379.npy +02828884-9c9aed95c76b4ecd80360680c1602c7d.npy +04530566-a980a2cc1ece321968165c64a4129512.npy +02691156-1597cbeb8266af206aa3bf023a2b42a5.npy +02933112-20d00eeac9377d1212de5317fe5b354f.npy +02933112-9d7338e6d5da1acd353a90f87b8ecab5.npy +04256520-580e58ca5b0f8dcf490ad276cd2af3a4.npy +03790512-67bff6cc82b6565dfaa866ab8ff6f59.npy +02691156-4f5fc434ebc03254fc7b1255b2e02e3f.npy +02691156-2c932237239e4d22181acc12f598af7.npy +02958343-36d0591781587d9fb1bb46d2556ba67d.npy +04379243-31f1b54fb7c9e5a3cfb87ab5efe3dc31.npy +03513137-6429cf540f58c246226eabe1cca3e850.npy +03593526-e08d96216c6360155e7fae0bb48967f7.npy +02808440-19605cf5174935043321831d2245cf06.npy +04379243-2c5d6e88359ccffc3396b0dbcf4d4bc7.npy +03636649-5360bb53166e73958b424343280aeccb.npy +04401088-b8a2c7c7df404ab8e7ef9fff09638f8e.npy +02933112-4edcf59d45bfff5a5b903ba10d2ec446.npy +02933112-580a7733e55e08be3c8d0fdfb1cc2535.npy +02691156-f88be1c8e93fbfecba0d990ae229b477.npy +04379243-a8a68d6e43cc0e094fde46457697d80.npy +03001627-8a948db5f12d02af492d9da2668ec34c.npy +03636649-1f80e265e6a038ad9c5c74ff620f967b.npy +04256520-48b67f0f05994da092a31ec18c4e190a.npy +04401088-af3c1e4367942543264e721f309fb873.npy +04379243-2b1f1929a6a5a6517b431cae0dd70ed.npy +04379243-31451828a0b452174705d3a68027b503.npy +02818832-b4fe88b1c71ec07817c98cc13ef6018d.npy +03691459-92e409aa16d2d673b5203226c26c59ad.npy +02992529-9d021614c39c53dabee972a203aaf80.npy +02808440-68421e740dd77fa7c664c3d4e2d59341.npy +04225987-8b93703a2046ddf5519438329ccc67e5.npy +03636649-d8b33b356591441f23d2ff62625c9fe7.npy +04530566-340bed24d1dbd33ba9142e7277ee08f1.npy +04530566-176d386905bf227da56b564158d089de.npy +03642806-5085268208bb23ba7b037ded105df073.npy +02958343-c951be855f20a1bfb2a29f45da811562.npy +04554684-aba19f953a07b5d3f589dfa369e10caa.npy +02691156-34a89777594d3a61b2440702f5566974.npy +04256520-946ab73b9f05a85ad5b24cafb84903c7.npy +04379243-e2dac2205ed98fad5067eac75a07f7.npy +02958343-9e0eb55ae7af7f8a61fbb658aa965606.npy +02933112-cc843a4c31c60dec64cb4ed80bd76aed.npy +04379243-ea45801f26b84935d0ebb3b81115ac90.npy +04401088-4a60039ed657d838fe5c7c47101442e0.npy +03337140-4be2322747a8c2604c3aee8e9d3a6ffa.npy +03467517-a276d9eee2bb79f2691c0d594e383a87.npy +02924116-337bab6b54d858ad15a9da89784be865.npy +02933112-7261f3eee6d5cac0e7ae87d20a4fdaa5.npy +03001627-91283b7062407b7381806e3880250dff.npy +04379243-890940359fdfa036569c11df1aea8ca4.npy +03636649-37b0f61c553e0499be27e423fd45ffe7.npy +02691156-e52f08852429e6117dc01d89d8a05b74.npy +03636649-aa9e96ac6c121cc54cccbece4754c7cf.npy +04468005-8d56ae45f65330beff6d47091cf62142.npy +04468005-c8645284ecefc0caa5e12deb37e3ef08.npy +02933112-1411cbedcc428f73b76e29c9c43bc7aa.npy +04379243-6ed74f11887c521f25f6f84717a88f8f.npy +03001627-4360c9c8a22facffaac6edb721277502.npy +02992529-a8d72bc949bbf361d8dc338f42ea38e9.npy +03001627-21e5fb7e2de735f490ad276cd2af3a4.npy +02992529-52d1db0a460723949582767760266e88.npy +02828884-230a85ab57a15b90e074517a246f1e65.npy +03991062-3862f8610e0329e2d4e6b2984840098.npy +03001627-6a5be179ac61ab24b07017f7091028ed.npy +03710193-3ea1339c113555f231c93b4eed4b11.npy +03001627-1bb81d54471d7c1df51f77a6d7299806.npy +03001627-c1b8c2f0c4f3cc43aff7c08b060f5ed6.npy +03467517-8ad0bde65846fd724133bbb00b8e2c6e.npy +02958343-a57e65f0c8f21ebc31780fdd33037c9d.npy +04256520-f611f7d72fccaa4c8bfdb54347dbe48d.npy +02828884-97d009dc14e25080d83393768c99f441.npy +04379243-401cd99ace3b92fadf6cfab91d65bb91.npy +02691156-b42620c214ca7cfc44deee06752bbfaa.npy +04225987-8ae2871e13786052f42b80606c2f3752.npy +02747177-ec95231a746d67a0775917454d940127.npy +04090263-d7d7d990d385ee8a67eb21515c2e5ee3.npy +02924116-f59d8d1976ec3256f07d0074fbd4a555.npy +04256520-8331de0bbd3b0e19db8fa1712f9ee93.npy +02876657-a86d587f38569fdf394a7890920ef7fd.npy +04256520-3600642b1b3a91422d83e0e365c4ccb4.npy +02691156-560b4af718f67902ac4f72bf08dc79a6.npy +02828884-6a9fb118c1501215f6459198cd03dd78.npy +02958343-dd240a8334032434bda733a39f84326d.npy +02691156-77c52530ef9983c94c3a35cee92bb95b.npy +04401088-43d96f5a6a619c06bc663b874223ed74.npy +04090263-64abde6390fa65fe26ffa6f51f050119.npy +03046257-6e5262c1b52858c5191c3762b497eca9.npy +04379243-6f53e944fcac6e49795407f097f1ca4.npy +04090263-2e9dad6c61b3269b1ea15a3c13db250a.npy +02992529-3aa2fd5054465056e25336bb76be9963.npy +03001627-27559a7e2b0b839d75bd952b0c911144.npy +03636649-252152593d97aabfd5f1d0bcb81c89ec.npy +02871439-d3497a61bdbac9bce407066405497871.npy +03691459-5e9cb0d76e74b0a9339c90d74e7a6543.npy +03790512-8da04b6c03068e6ae21ad659cc6e09ee.npy +04379243-9e5c21e11110fc9ec60dad40a0c0e85b.npy +02818832-a3baf2c091f1d89276a8f34f63bf4ef6.npy +03211117-eedbd3126dad6abe5de04aad18bd94c3.npy +02933112-a7e9a54cfae053aa20768660cf080d12.npy +03001627-46cb1e740cf6e9ec7ea88ba060407992.npy +04401088-a4c32dbcb71076d5825732a29ddd146e.npy +03642806-c912c50b812268e8fc9e3f0d993c8121.npy +02924116-80babfe320be84aa5cc49a2de2817ad2.npy +04090263-3594567f8d54fc9475e036b82df78473.npy +04379243-992899a16779bdc99f8c3d2002c77ddb.npy +04256520-8190efdd2054a0d9f51945de050323d3.npy +04379243-2ab14a50afa530d5253e170a96a633c1.npy +03691459-716d1d38cc0bcdc8c9d5b08933b9e0c1.npy +04379243-63aa4cdf9276e6bc19cdd91652400369.npy +03001627-bafa7e4e50e0b2bec8687ff9b0b4e4ac.npy +03593526-63447253a06727004725f67267e31c89.npy +02691156-d9f90f110ce30fbbadecb6fc00604132.npy +03467517-6b1648834de5c0c910a26d9d3646f933.npy +04468005-1a83e2d92fddd64452470de2774d6099.npy +02828884-cca18c7f8636606f51f77a6d7299806.npy +04256520-63b0904e68e5d1c6f51f77a6d7299806.npy +04379243-4de9fa90bcbd6beec3bd24f986301745.npy +03710193-ab94303f7fad5b453b02598625ec1bf7.npy +02933112-33c47c4c9afeea5a4c62bee40dcdc539.npy +03593526-6bb307429e516e2f129f1cb6c6fa9dd5.npy +02828884-c3da9fd354b31502d6eefa796d2f261c.npy +02933112-59d2e972374292c19dadd90fffe49008.npy +03001627-ffd616229a97642c7ea8c9f2db0a45da.npy +04530566-dffd4f1a6a4d3647568f91064f82e7ec.npy +04090263-8f81c50e0b90f961b40a1b2ef5e0c995.npy +02828884-e3fddd1e0ce63b65ad5067eac75a07f7.npy +02933112-23108a41e40a49f6389b013bdebd5e94.npy +04256520-82dffa2751f8e77643c18769338212d9.npy +03691459-36526654949a904b2bf4f773fe0e622.npy +03636649-72d5a2931dc1c913edb30e9b97600303.npy +04379243-41b0491fdb14d41bd25ca1a27cf9bdec.npy +03001627-709a5038988a70f58e6803fc947043b9.npy +03636649-52e15c498d33748d53227dcd0d547ba6.npy +02691156-c798fdb5baef6b8be36e92960e9f090a.npy +02691156-881e02b2d5a2c306f7fe0727acb55c39.npy +03636649-5f22096b25995531fcb8d8c6d4df8143.npy +03211117-f3bfeab806cc976072052f2ed83934f0.npy +02933112-adece72df027acd6658fc1ad354006c7.npy +02691156-7e1646c0a04dc68f6ea66e6959004764.npy +02992529-78855e0d8d27f00b42e82e1724e35ca.npy +02691156-deb196087108dfbdbe4df22b15a36e0b.npy +04256520-413e31ca041f65ee5b40246fea20c2e7.npy +03001627-9aa80e9e5adc8084792de12ccdce67a.npy +02924116-280046943bd65148669bde2c0a4bfb2.npy +04256520-23c65f2ca9165072490ad276cd2af3a4.npy +04530566-767cd95abc076d3af9d742d7f0246fb0.npy +03636649-b5a223ea93f39c2c961b70a6f96df2a4.npy +04530566-873b7ab23a5c85e365a308491a8f2afe.npy +04256520-8a207daaf453777de79c8740b4fafe4.npy +04379243-98d93b260a69366c490ad276cd2af3a4.npy +04090263-b75dc97eb33f6f5f98469ce4eac5b4d0.npy +04379243-5370b493b077fdd39ccda3ab71692a66.npy +02828884-dacfcd3de6bb08e4d2b12aa6a0f050b3.npy +02828884-5ce636f716f8f11e601104cd2d998272.npy +03593526-60abc8a27bb77020535deb3b0c692a2a.npy +04379243-6e029f7d5901aa2e2e4e89f168578552.npy +03636649-2c806132ebd0fa0eccc87962551b3d9d.npy +03211117-f3f21d06ff78f426aa444c25b73bbf6.npy +03001627-30488c6d05b4848388df69d6c56c6047.npy +04379243-db665d85f1d9b1ea5c6a44a505804654.npy +04256520-53c81bd4b93b14491e6d59363e6e833.npy +03085013-57a57e95d06b60458ee125fbff9e483f.npy +02958343-dc2c49d8617d400daa44bfa127abe4bb.npy +04401088-99fcfdd6edb3898a1117cb504804bf09.npy +03001627-233cf8ec4019005ceaf288f952624966.npy +02828884-978e21e3ac24a83c17b431cae0dd70ed.npy +03001627-212ad23c8afe1f9a9d297e74104d3ac3.npy +04379243-1fdc88f78be6ba4e14b86d5282eb8301.npy +04090263-d79182f4d76d63e9f13eed41b64dddca.npy +04379243-38ea17d177c4e872fd07832c54eb7e78.npy +02933112-20d92bdc128be29c59350d819542ec7.npy +02958343-d84c7484b751357faa70852df8af7bdb.npy +03001627-c9cc8df04240b27890907a4c1a185a7.npy +02871439-9bebf2913d515b5c66bc0e25cf103e1a.npy +03636649-9841e6ef0d244f3d42b9650f19dd425.npy +03624134-61c24b66ee29c936813a3b78020f767c.npy +04379243-b24092dde9ca927758aaf363794b1631.npy +04468005-b21af8271ab47f79c82ee199db6586b1.npy +02876657-bd50af3416f45348679a03fdc41e0266.npy +04256520-20ff83acfd590101be65001d50394fd9.npy +02691156-ce5310bbab4bc178d7a85b8b6dea0a54.npy +03001627-7a5e63ee142a424c5f6d0af6de791c3.npy +04379243-c679e4eab49f91fcb4392c1299b1bbaf.npy +02958343-32f458e413dfce699cf7b84b43bdd8f.npy +02958343-eb144af0fef08314f00cd8c386c592fe.npy +03948459-5f540dfb9dd0f21c9f433921788191f3.npy +03636649-1ce6fb24e634d5962a510b8f97c658e.npy +02828884-779907753183ea36601bea3dca268229.npy +02958343-90a59a473e9d110ae13bf7a39e9b5432.npy +02691156-d583d6f23c590f3ec672ad25c77a396.npy +02801938-eb0ad0de58fbfd32ca972daa503b3095.npy +02924116-adfac6d3b3f4f41c91a491e8257bd6fe.npy +03001627-553c6c2a186db82597976c675750537.npy +02747177-df3772b1bac3003c464e1d2ff524a75b.npy +04256520-61f828a545649e98f1d7342136779c0.npy +04379243-63df9bf9884c5b485e7087f2d9a278a9.npy +02691156-cf13bbe558f37bab4c3a35cee92bb95b.npy +02958343-932363431a35b189898b91227342b00c.npy +04256520-2fa5cce72c52f5ea95696f73b672b1e8.npy +04379243-32160b2dd0d1c8ab507243968c1db8f3.npy +03467517-97d91c9c16a2c6b5df7372ed5754c18c.npy +04379243-19b849328f1a8e522ee60509601408f5.npy +04090263-56026588e19ac1ce5109391625c31397.npy +04530566-9951a6732eb8438a79662f01dd94fba1.npy +04256520-3b7c1e67ee312cfe1bb088904f7cb154.npy +02808440-8ba04a13e0b5a33f774f018e2c69edb0.npy +04379243-68247c737f565de8615b3e12f53b391d.npy +03211117-3b188ac95d09cc149d74e2a2b8c0c58b.npy +03691459-323f51a8d5029453d603e2778861154f.npy +02946921-b36902ae19ac77f2a89caedb1243a99.npy +04468005-5588d3f63481259673ad6d3c817cbe81.npy +04379243-53433c9845f6b53955034479f8a160c7.npy +04554684-91e432daef378b24553e9c84d5d40de4.npy +03636649-c83f19fefc2c06593e22d791db24e31c.npy +04460130-b8a35075f420cc7066ea44c6d828197f.npy +03928116-9578f81207bacd5ddd7dc0810367760d.npy +02924116-29e7da770fc347b87ea4a7d096d4ae73.npy +02691156-5f9b4ffc555c9915a3451bc89763f63c.npy +04468005-bea62459ad724a7a3b371d842587b0d2.npy +02808440-fefaeb0bbd82f411412deb0d2b0f3dcd.npy +03046257-caab4218b7855fc5de9107ce13dea90f.npy +02828884-de305de253b7040aa4e9452025f4f1c1.npy +04401088-2009fed0ea8d1fc3e2dbe704eec7e8d9.npy +02958343-368583768dbe789980360680c1602c7d.npy +03046257-e3a00627dcef6b854b3c42e318f3affc.npy +04379243-ce1c3321de30433b16ec4c6284dcbcbe.npy +04401088-44d7b5d87c26896944608b3255ca1886.npy +04256520-9f4447e8dd345d33d68f196c7607adb9.npy +03001627-ue639c33f-d415-458c-8ff8-2ef68135af15.npy +04090263-891731397db0b6d36669f41869e0668.npy +02958343-2dbbd2bec94e4a7440eaf79934ff53b6.npy +04379243-9d5941cd2ae236db2a63bbf40292a37e.npy +04379243-10b246b375c15ab59fa24672a35ae8bb.npy +04379243-6e6f8f0ea7008fee620851befcf2047a.npy +04090263-2c10978bbf84a263b2b9ca36f6b76586.npy +03001627-8e87911087743bdb2314deb821327685.npy +02958343-3ab98667cabf774e3343f5fadc4a2136.npy +02691156-a1bb5d1a075bf7fc37d1c8fcb5a639e2.npy +04379243-15ba6dd7a9ad8b12efe5f291bc2f5fd0.npy +03001627-eb1d92be1e6bd84c4d9a43d557cf49de.npy +03513137-9cbcaecc65c3a511eeb5508ef773ccb1.npy +03593526-cc432b9eeeb02485a6a06826583046ba.npy +03001627-d8892d8a902616b1669e5c8c05e138e9.npy +02958343-53328de5c7e18b752350d856e276adb8.npy +02992529-e870d160aab8a55f1a696e9ae9fac3ba.npy +04379243-fe3351c94fbab8ce3002761e7a3ba3bd.npy +04401088-e96198cfb23a8b9d1d7ccb77d69f693e.npy +03001627-93e183f827d9361cd7c558b0724ffc9e.npy +03001627-374e87fdee7711491e046801e2748f1a.npy +03790512-fede9c1de88d225c7395d58407f193ba.npy +03691459-f2bec55383f72f04f6eb098afb876d6d.npy +02828884-74d4dfa4709ef0b056f6fc4b4ce1db04.npy +03797390-a637500654ca8d16c97cfc3e8a6b1d16.npy +03001627-96929c12a4a6b15a492d9da2668ec34c.npy +04401088-40dbb04ab8f780d6cc571cd3cf8f17a1.npy +04256520-75fa63a7576e2f509ae676623bdd3284.npy +03046257-64a32db4416941acaa2b654345545ea.npy +02691156-b501466a5a77f1173d2cc3e9d55f7579.npy +04090263-e5221bee9996da87d6964d5ad6a822d.npy +02818832-19ecbf9af52ad3fdc3bd24f986301745.npy +04379243-3b0c62bde7b24de85ce578b5b4bfae3c.npy +02691156-b3bfc198214215397b5fa2b5a4fdb00c.npy +03593526-146f6702601f9c5d8bb41b82b15c6ac.npy +03001627-637b36b2e5db7f513f7e27638e63d848.npy +04090263-698623ed6f1fb3076b2c8bb96250e4a0.npy +04090263-96013016f3e33bf3e1f2a1daf140ac9f.npy +03001627-f8bf45e20bec7cbc9cf3f05539f5c4e3.npy +02871439-8f94fb5a0fd17a0b68d1b9a1d97e2846.npy +04256520-2e474051a376ecace543d6ca26cbd98.npy +03001627-e431c68fbfdf826d561dbc0c83a98a32.npy +03001627-2ede0b0117e75a4315d50c1c4b796b2b.npy +02924116-df6917b20b0e16f8fd12abdf466ae8f.npy +04468005-3528e0d7239a47e41f3b9c5c62b1e7.npy +03001627-37cea3ba8e5a146da6fee8e2140acec9.npy +02958343-1ae530f49a914595b491214a0cc2380.npy +03001627-4460e0885d82b7b5d9987a7cd00eb98d.npy +03001627-59fd3d1409c0ee2e47bc3701b998a7d5.npy +04090263-e6887514f6d28e446314c3b6a3a65519.npy +04379243-cf5e67d5e6d7cf03f26f8ea67fbd8269.npy +02880940-a593e8863200fdb0664b3b9b23ddfcbc.npy +03691459-776b1ceb53c8ca881ef58b31c4ba0d15.npy +04530566-23c31b1c25689d2a7ba04de7d6d93ce8.npy +03790512-41cc9674e700c3fdb37378f3c85478b4.npy +04256520-a47681de164dccc6ad04591c9486ec0.npy +03636649-65c87436f6d6c695cf004563556ddb36.npy +03636649-9c5a4f568399539b47afb7a57d27bf15.npy +03001627-2df489b6a14404b3febad4f49b26ec52.npy +02808440-b3e22df8581158c66f893b5bc716a3fa.npy +02691156-1c26ecb4cd01759dc1006ed55bc1a3fc.npy +03337140-1880ed173d662f92c78621ab7e0ef193.npy +02808440-326e05c24641bf43b362845c6edb57fc.npy +03691459-f9250e29e640eff9a5f99ba0b2469cd9.npy +02958343-cc0c058e2eca523051fb05589f6b0d0e.npy +03991062-5cc4660eebade12d25ebd1cd0b422e32.npy +02954340-f40b47fcbf83b962f0d11ae402ef940e.npy +02828884-205b404cdee5d81cc624b11e153a6d87.npy +02880940-d78860e8318fb75a12a72bbc636a1f9d.npy +04379243-49bf25ff4401946524c10ba1eb690638.npy +04256520-3f79bfdf49c2b654c397356311cbeea4.npy +04379243-50d253ed67d73392140251e5a7586890.npy +03761084-391c1645b46367067621f3e966f56f52.npy +04379243-3a1f1de9d4693576938da3ea2c9e0e4f.npy +03636649-37be7d2937f7fd88fcb8d8c6d4df8143.npy +03593526-e8a0fca9bfb4422cff3ef8f363b2cc43.npy +04256520-75d76c87ee1066ae7ca0c2077c3e38e0.npy +03991062-8281f586fc85d6a377b9297f3055210.npy +02843684-1025dd84537d737febed407fccfaf6d8.npy +04379243-3564c6480a95a60323fe3501bb9e7193.npy +02958343-555303045808ca7530e7b962d97a840e.npy +04379243-6086c6195df8e051cce17d79b4472d62.npy +03636649-63538ead3a81058f1c1ef519b9196b63.npy +02828884-94420ab399ce8a1561e51a63d5bc6e46.npy +03636649-370623095c9773e42ce7d46577f8a9bd.npy +03636649-3e2d51c40b37c9c086052e834fbd2c4a.npy +04379243-72659c0df8a3d5f77ee217c21e683487.npy +04379243-603e2237e14611f9d4091fbf7990ddf0.npy +02992529-e0b1cb72aba261731fa8e666182e8619.npy +04379243-505dca88c2a9f7bba75d03186a0409e2.npy +03928116-8cb0a98e336a767421eda8d3e50ed928.npy +03691459-1eac013c89689e58d421ffb972735edc.npy +04225987-90210ee9fd29275dcadc0bfc31415370.npy +03636649-fa3b05deceeddc26fcb8d8c6d4df8143.npy +04379243-7ad02b2b54c9456335ce7cf30c872281.npy +02958343-10555502fa7b3027283ffcfc40c29975.npy +04379243-679f9dd2f3d8c52e2de61958ac6aebbc.npy +02691156-dd9c0622e873de43c752b66cc923fdb.npy +04379243-1f34ff8c2ecab3b0a4ee05a5737b7178.npy +04379243-c26913f8e139a80baa2b654345545ea.npy +02808440-2ad3ff96fe7f5d46a9420f0961aa2e8f.npy +02933112-aae9df5536cce166d5532c7891a349ad.npy +04379243-b6d644abd3a2a54c904f770b8a17d30a.npy +03691459-b8a5307c51164dac78128d32fc0f2897.npy +02691156-5c9e30bf0691c04d4c3a35cee92bb95b.npy +03593526-777bbb60f4596a5155f46d55537192b6.npy +03211117-e9466e872848075d3aeab48ed64c0fa4.npy +02691156-bbc645e0c0449532b3c7301213dfb7.npy +03001627-bf9f2ecb581640bdf91663a74ccd2338.npy +02958343-1198255e3d20d2f323f3ca54768fe2ee.npy +03001627-892d8090f05c136dd93768e7b9b1eabf.npy +04256520-f990194a8401d8de68c2f5eb1dd4dfaa.npy +03467517-d790ac3aecbdfdfdd4f4a255f121abfb.npy +02691156-25668f59015af0de56a7f2952cdf4b81.npy +02876657-a1c63c463ad7fc1fb549927fbd0d12d.npy +04256520-c3e86ca4f6ca077459d0a47cd36512.npy +02933112-504949a3b05dd13e3f7a74e12a274ef.npy +04379243-bba7bc453203fbc6e39344961f657bcc.npy +03001627-210115ebbbd9eefe5fdc736bcab9da58.npy +04256520-6f202d8517db172a5b2e09b1c446ae22.npy +04401088-9cedde0b189fc03824ec4b72ec33390e.npy +02958343-82c6851526bf7350b5554d042286b030.npy +04256520-13f398918a8ae11b17743c18fb63dc.npy +02933112-467b66a6ed7b3cd24da5feafe6f1c8fc.npy +04379243-e5437217b4f28c976c45c685905d0ecb.npy +02828884-75ba60267a6c36af4b0780126e986ee.npy +02958343-3d681ed2a7eef0df28f46021c78a3723.npy +04090263-6c95a697b85c6a52683e3750b53385d5.npy +04256520-ecb362a469c76e76febad4f49b26ec52.npy +03337140-976af9491aa692b94c3aee8e9d3a6ffa.npy +03001627-17dee0cfe9a370b134bce1184e175df4.npy +03636649-caeabb766b3b9c67d3c1dc91e223304c.npy +03211117-2190a888d3f7ba6bd3ffd38a8449bde8.npy +02828884-8256252192c60158c5449cfd4c0f0a4a.npy +02691156-5e7952b2d1a495f24c3a35cee92bb95b.npy +04379243-57e3a5f82b410e24febad4f49b26ec52.npy +03691459-9cb881bfcd65686176d485609557b1d2.npy +03691459-e8885d12901ed5aaa7d0cc9b15400f65.npy +04379243-b893c20bfb5d718371a782a4379556c7.npy +04401088-e1b7a28e8f8ddf15a4ecfe858e518c15.npy +02691156-2d3ecfb6d7ef2c45e08b03c50fd87acb.npy +02958343-68e733f38f957332afe1d4530f4c6e24.npy +04379243-2ab09f4db5f5e842bf595b60a303303.npy +04379243-36f53cf8a68d1ea73ca57f5648ff1b0d.npy +03624134-27f3ffbdbddf545d179125d1d357cdf5.npy +02828884-2cdf972377f30d9485718c281d7fdf61.npy +02691156-62ea17b5f0d46e2288a89a28f04ce622.npy +04401088-efed528241cd773fa2c7c5886f4bbc93.npy +03624134-3464db7fada86430c0e19881d8a9def3.npy +03046257-f9bd4d79a34592ce6695909af0a27770.npy +04530566-b10850ed8a61d4dd148bc340784a8c1.npy +02691156-19b219dbd2e4467828d4f2ffc8f17f3a.npy +04379243-696beb1883be838cc955e5ed03ef3a2f.npy +03761084-406dad41dfaeb674477dbb9bdedfcc.npy +03046257-57723d2d30d532c7adc5f5aafedb1c38.npy +04401088-fef0bba982a4ad5296913ea8ca1ac015.npy +04090263-debc38fe094476bf2dbf1aa086ad30ea.npy +03001627-a3e4639ff201f69b22a3043dcd383f68.npy +04379243-3dd0f8b4dd8a688aba893aa9f42bc953.npy +04256520-2c16efe54c1368b297f437b37a859ff5.npy +03691459-2a7c52141a3a32dfdd14180aafd9db4.npy +04256520-accb504861a4091b894b04fea82e6039.npy +04530566-a3be3018a002bbecacd548a9de859b7d.npy +04379243-3e32e9de344b723435c5f7d532a05db4.npy +03593526-6dfb59f33c88a4e0263c42ff6d6b9672.npy +02808440-733dd5a046be8d4029a0731d6489a64f.npy +02691156-d1e78f6226a9ac76fb2fba771d8219ff.npy +03636649-be00be72836114159568832390d67ef.npy +04379243-91c380f2d26f1a9ff128012535a24244.npy +04379243-eef0387bc4e72a1efebad4f49b26ec52.npy +04379243-5a720d961df190d459a6208793b9dfca.npy +03642806-f53ea19f871a80d420685b5a7e34b501.npy +04379243-c5195b46ac75dc8c20c6f761e8cbbf.npy +04530566-aee93c0ff8dcf746ece2f98c4b805551.npy +04330267-7bddc990442a3c6ea8ab8175d04e5764.npy +04530566-e0fc9177fe0aab2fb50d0c6a0c254040.npy +02992529-428ac05b36bb576d2a9eb0f146e94477.npy +03797390-962883677a586bd84a60c1a189046dd1.npy +03691459-1a511622eba730c79ee3c69ee7ee1fad.npy +04379243-82e1c0b874b0a9e035cd53a06b1d2317.npy +03797390-91f90c3a50410c0dc27effd6fd6b7eb0.npy +04468005-4f7dcdaa6bb963354aa78dbead0d8a01.npy +04379243-b4855f52572ce2b0febad4f49b26ec52.npy +04256520-33ab106bfcc881b14b2bf798c0452b7e.npy +03001627-77727bbfb22c57de492d9da2668ec34c.npy +03991062-e828ac0a8a9a1e96ba14bfd91a75020.npy +02828884-b1ac6f2ba106e8ec2250bf58700b4d8f.npy +03636649-5d94d971dd819985713decb1a0563b12.npy +02958343-c43b1ebad0ba016a7fd25564c2e888e.npy +04379243-e22b23cbdaa1e259e8a94a8468340ce7.npy +02876657-13544f09512952bbc9273c10871e1c3d.npy +04401088-f2158f4f4141e07825a703f74bf22d93.npy +04379243-2fe8de498d0f00f51f77a6d7299806.npy +04379243-49c3ad60b7d5234dfbe06dd91adeaedb.npy +04090263-b754214217c4405dda6cae4e030ce341.npy +03046257-f453f21d54c766d94edcf3b74eb57b13.npy +04090263-b589b1af4eec862beae3ab415b6ca18.npy +04090263-cb9b99a239fa07bb139336f03eb955d2.npy +04379243-65acf2f512016cdf553c860eacad5e53.npy +04379243-ea6571f7ef98f562fca88347d0eb86ef.npy +03642806-6146d9fd9460370c578b3fc82443ab96.npy +03001627-a439465d2bd623a14cb9f394cda169eb.npy +02808440-7d41c1e628b1312977da90a8fc1a6429.npy +02992529-e9352850a60bbee4975308da62ab2e39.npy +04379243-d3b7021f03ecd58d2585ba435c7d1fcc.npy +02691156-46c52edc6107d1a3505ae8d422ba349d.npy +03636649-87107afb7ad115414b3c42e318f3affc.npy +02691156-e559a626d0ef8b4f982014dd9aabdeeb.npy +02747177-e05add2e5e4574997c6269fe8093902c.npy +04379243-7f9c12456dea1c2531c7871fa99a9d36.npy +04379243-2d5b8274376a7095955824885d6e7dc0.npy +04379243-e53f5f3d4b20df8176331cff7db8f268.npy +02933112-9c245f01f94ae038413b3ddc4f2d9a06.npy +02958343-c487e9850891e1ec2d15396b7bcc6366.npy +04530566-67da87349baf66e3c1ccec171a275967.npy +03797390-4d9764afa3fbeb1b6c69dceb67157a66.npy +03001627-d86158642391ea7a150a331b054ed006.npy +03337140-68446c00eeed26264c3aee8e9d3a6ffa.npy +03948459-b3a66094d5ee833bf4de29b99f103946.npy +02691156-94056866a14b015a50c626aa72455dae.npy +04256520-b48603e4595bb61ab6f5fb02f36f9480.npy +03636649-979867c99d8e0b7a4601feca428b2996.npy +04379243-102f0532f9f8bbcdcb503f63ed915ed2.npy +03001627-9cabf21d12d271c5d295b24579cf55b8.npy +04256520-f1c533e2cba193631b02cde7e81f0fc3.npy +02876657-f68e99b57596b33d197a35146ee825cd.npy +03928116-f1e27303883d1c444e09ebaf49b0cb2f.npy +04379243-1faef163785bbc427b11ae648ea92233.npy +02871439-9ca929d28c1838d5e41994ffd448fd07.npy +03001627-d11ee4294daf6ebe492d9da2668ec34c.npy +03337140-137369963be020cece5d6e9371bb5c33.npy +04256520-4521ce028e5009811866a0bc19f46a1d.npy +04530566-c2d6eb0899e5d10dff531859cd52e4b5.npy +03991062-2bc8254cb4d6ed7b5c27243205718de9.npy +02808440-72b2ecba8ab54af8b362845c6edb57fc.npy +02691156-5b5c4dc4bd29dc8166cf1b4a8fc3914e.npy +03325088-4baadfa07397fff83321831d2245cf06.npy +04468005-2d05eeac352398006bd10bf92325d933.npy +02828884-18926a71dd7f17eaac40ad047084c6e6.npy +02958343-c3d23ea4f3d1e18180360680c1602c7d.npy +02828884-ce2112fa16725a7aad5067eac75a07f7.npy +04530566-79284d5d39e4738394749f185cc702f2.npy +03593526-2d69fad249c53ca0c6e02b40b50fb3e7.npy +03636649-4003077668e23d6c9998b4eb812699dd.npy +04460130-6d839fc8ad123620f20d6153247513c5.npy +02880940-aeec00d8dd6e196451a2ad3de1977657.npy +02933112-11798e50090b6dcd0b36851d61b6fca.npy +02828884-94df387a0b97302ad201085e80edb26a.npy +02691156-c359e067e75cfa8693d4024985440d4c.npy +03467517-4ae5a491c3ffb473462c6cdd250c26bb.npy +04379243-7b356141695f75e271a782a4379556c7.npy +03046257-4f62af2d14df6cb6eddb8fb8ef75e718.npy +04379243-22e1bbacd4ae7812a23d33d54fbb4b2b.npy +04379243-801616c42a468c298fb2b3b07693a96e.npy +02828884-7a7c5ca50411d85f4fb4dee5181bee.npy +04379243-1be0ad8c6375f5d47edd45e036b3c8b1.npy +04379243-ae0ed75bbd4c5a74b7c9606efbb8bb3d.npy +02808440-8b1b57f4b4f2477b362845c6edb57fc.npy +02958343-ebbbc8673928ad37308fb27494afe372.npy +03337140-47278fe8f8be0e3c4c3aee8e9d3a6ffa.npy +04530566-a3905dbb972cbb3db57379b548da98a0.npy +03691459-75c408e3ce113c84d084cd4069686980.npy +04256520-8ea11732a1198be1dae12f3947d07dec.npy +02871439-ac9f6f5ed922f0a5ca3d3aba150597ee.npy +02958343-52f592a68c828a1e190cf42afcf85660.npy +04379243-15cb1696b45ef647dcad484e89744ca.npy +02942699-a230560372fd55a410ec06105f027b7d.npy +04256520-f2a96143ed0936265d2b890291504877.npy +02992529-8f049b65309d8390f5304dc8cfbb76e1.npy +03636649-f5a121812ce16ed2578f5640449b6f5.npy +03001627-c9fa3d209a43e7fd38b39a90ee80e328.npy +03001627-6dd44ada2f481c776dddf6f75fbd4a4c.npy +04379243-2e8a4184f4067657f2cf6a9bef44d625.npy +04379243-8bdb57e97f726a8133a39277b6bd460a.npy +02691156-e1e5cfcabcbe26a03087f84b199fd297.npy +02924116-571b77397f1b958fc98c13d6112727de.npy +02958343-3ea68e00dff2847f1f0fdc8ac183f8b.npy +04530566-ac479ce45b04972891bdbed880f31c72.npy +02924116-165b1865ba7eb0efffef2f04639c404e.npy +04256520-f444000ead89fbf2558ba0061239252f.npy +02958343-651497ec47e9d1182e877e82c90c24d.npy +03001627-568050037ad958625ea33df4b8846880.npy +02843684-ece71b326dcb50bdfcfdb70b6c560685.npy +04401088-fbe18b762a1328916b7f36a4c89ad37.npy +03467517-2f1ef453d18cc88d74f1a026675e6353.npy +03624134-ea2a14aa25e34566ed60d0c28bcebc7c.npy +02691156-4a6961377146f08cb45fd154bd3b6957.npy +02691156-875d75a0aef86850b6b87e72ead132ed.npy +03691459-70ee226bddd4005836f19668fecae7e8.npy +04090263-7b1b02b8f71226e4bb9224760a70fece.npy +04379243-8821c22c61ed87e3a585c7706fdbbe10.npy +03636649-908bfd876def9e43714531f0291497fd.npy +04379243-72458d4233742f29fa24672a35ae8bb.npy +02958343-6c5a34971e2bd518d571d7357468d0a2.npy +04090263-37aaff9b0f567ca378d7c0e1adfe122c.npy +02828884-eb245de64157afe8ad5067eac75a07f7.npy +04379243-364b9c00797efba693ab1bc955ac34ff.npy +02828884-1b8e304a9c23fd4563b2acb037dfbcde.npy +03636649-6a977967aedbb60048b9747b6b395fc5.npy +03593526-915ca876e784d965c5b724995774ac86.npy +02958343-3759a08d740859cdafe1d4530f4c6e24.npy +03636649-aa78d1c91a8949313c8d0fdfb1cc2535.npy +03001627-36ced137933c36a3ff085529822a7226.npy +04530566-e6a9f9135e36b6c17c0ab7347b9e831a.npy +03948459-418cb9c89655274822d79ac75435d5fd.npy +04379243-119a538325398df617b2b37d6988a89b.npy +03001627-7035d480f6bda22938b39a90ee80e328.npy +02808440-367f0d3a99b5f9f834f7f29b38d9290a.npy +02747177-8fff3a4ba8db098bd2b12aa6a0f050b3.npy +02958343-90573f5d0156d6e23ffe0e5069bf1eb5.npy +03001627-4c1777173111f2e380a88936375f2ef4.npy +02958343-f1c277f7fc421492fbe59dad8284dc0.npy +04379243-eff1bc2f644be748490ad276cd2af3a4.npy +02958343-6333b9c777384ad14362be10a3fc8255.npy +04379243-1be435a3027d58824461bb4901a4cb6a.npy +04379243-2d5f99d5c2f3463d477551ed4bff707c.npy +04379243-2dcbd662fa03dc88956c2c3ee7a48cc0.npy +02691156-16715d886ecf0a97ce2cec85ea6ae00d.npy +02924116-6d619fcbceaa0327104b57ee967e352c.npy +03001627-cbfa51dd6b795262774ba10f0bcc178a.npy +04468005-a2a67baf798eaa72dd8e272fd230200.npy +04530566-2005e1613f1a46b5c083d5272d526845.npy +04379243-686a09b1584249ecac3c355a33b4399.npy +03593526-5eab5b7ed4d29ce5664b3b9b23ddfcbc.npy +02828884-52d8b9703dfcf31f2056b4bd5d870b47.npy +03001627-3fc616c2b603b333f3369bb203286e75.npy +03938244-1332172ba896e1c2a40f4c396e0c7dce.npy +03691459-4e957072c3c876e02fc6b53066be64d1.npy +02818832-ade1791b73a3b528bf78ecfda71e346a.npy +03691459-5260d7e4d379219df2e5d34c7b677bc4.npy +02958343-4415ef6ca1d9a6a3ed734d5df4ac741.npy +02871439-693836c29e5fa6179a2988e955b5ae43.npy +04554684-aaf971855cff72731a1a2dbbd3d54d53.npy +03928116-bba9c90254fb970b8dfaa3491bc0f718.npy +04379243-c348d279fd22730a9741b7ee128375de.npy +02924116-a645fad8ed4a2ecec13ce7c1406181da.npy +02958343-1ec1c4aa9190e767da5421a736792418.npy +02691156-34ffc5e29472358cae81a3776126c079.npy +03001627-74346aabf555ee0295122b1ef21ee4c7.npy +02828884-9c8a96bb95a62a6ae6e54a934c4318f1.npy +03938244-3ee02ff403e6e5bc2c6c98851414a9d8.npy +02924116-7e5dbe69598c6439ab80ed476c7fb6b1.npy +04379243-635005efb9077ca282c22b790c082c19.npy +02691156-50755e616df58fe566cf1b4a8fc3914e.npy +04401088-bf0f0ba650108d03cf144715a1bb5595.npy +03691459-388ae2b6420bfae26cde9ab9486e09f0.npy +04401088-71121add7e94b024fb88c3d40924fb73.npy +03211117-aba93b2b9b45a30dab0b172d4dea80cd.npy +02933112-b0f329dc43af0fbd4da5feafe6f1c8fc.npy +04379243-b658e507c84d6202610c2a68437007d6.npy +02808440-e456b80ce2d41953ccd0340812259a39.npy +04379243-e935cf0b43767dc9c3bec646284d5a6a.npy +04379243-20cd5280f106b36fff90854b4e00880b.npy +02691156-1580c09f49bb438a7209009cfb89d4bd.npy +03046257-260be91d90d4aff1f51f77a6d7299806.npy +02691156-e161df613fc808b0d7ec54df5db5828c.npy +04090263-80915054aeb243259747e122424ea8b7.npy +04530566-263eeac4bcfca21285f7a3de54751f1b.npy +04530566-447a43ec44a3e672e7cbc4e41c1d1020.npy +02801938-dafcdefea7e1445edce1af5c27e3da18.npy +03636649-9c2699c78add2e5847ecd534f9237f9.npy +02691156-9b687f9cff46d43d89c2da356f872ebc.npy +03325088-34764b40046d5c9f72101dcac4ed75d3.npy +02828884-6f0723826537010c870f22c94729669b.npy +02876657-9dff3d09b297cdd930612f5c0ef21eb8.npy +02871439-824246a3f4b7075182750018fd60ef30.npy +03636649-670525c759c07ac71560641bf48464ff.npy +02691156-2d41a07991b546751702b97fc9845e5e.npy +04401088-61e83782d92bf80b7548281e465c9303.npy +03001627-bd98d493766949a8c05575120a46cd3b.npy +03001627-f9da1bdadc982c7f78ee935ba846606a.npy +04379243-a3a701905091355e96aaf875e27b02c9.npy +04379243-3e09b5c70cc4117d9969f8371ba19c2a.npy +03624134-4389fa45cc843df7e430a24be6d784db.npy +03001627-4a54684f8ab00cf5a4e0cb207f311458.npy +03001627-d80133e363b9d2c2b5d06744a21b81d8.npy +04530566-8bc922537410e1ce847c4e55bb965ab0.npy +04090263-5a148f5250c5d987918977c639d98325.npy +04256520-369dc8240dd358bbfebad4f49b26ec52.npy +02958343-28b5cb11ead4c878fd988235de2147e.npy +04379243-4020a2b829f148a18d8c7827464490b9.npy +04256520-ae7af4ea5c63938878585c45c8af09b2.npy +04256520-e8f21fec8246fd5a8bbe798b99a6a988.npy +03001627-2828b98d980480cec3bd24f986301745.npy +02958343-ae6827651ce624f6f5a0534aa77bf2.npy +02933112-475907f4b97bc1da25ae8e5e777da782.npy +03001627-2d808b6451253b7e7c7920f6a65a54d.npy +04379243-92e742c940c11e60812e3ecbeaae3980.npy +04090263-686be742e65eab7816cf8b1cd2155e02.npy +03636649-70b3279caee3ed985c6e7b50a2f671d3.npy +02691156-52ca6970fb09b561f9f7510373841dd9.npy +04256520-96aa85a45fed687dbbc7a6acbd8f058b.npy +04379243-d753e5da9b064152ef2438b4b778b7f8.npy +04379243-c1d808c75cc5e7ab4da5bb83ec125010.npy +04090263-92431d034edd34c760c81723f0d4ce20.npy +04379243-a98d6ce7eca8cf272d7d7823aa90da0f.npy +02992529-e33124aa016bd1f19c1db271ad9472a7.npy +02691156-d8a8e238987fed8dbc0909d98a1ff2b4.npy +02808440-589c1f69b5a29cb7b362845c6edb57fc.npy +02924116-ebf386fc1ba825d180288501d9901d7b.npy +02747177-2f06f66740e65248ba6cf6cbb9f4c2bb.npy +02958343-372b1a139379f5198e42313717d27982.npy +02828884-f56c78ba29d9f73e9bc72297235ac73c.npy +03325088-30597a40e0756ea650da8b99982a3057.npy +02958343-2d730665526ee755a134736201a79843.npy +04379243-4e5fc1f56057d5f439b1b7041443703a.npy +03636649-20c9d1713fbc0925c35131da26f8061a.npy +03593526-4bc38481b09e397689035c25f0dfeb63.npy +02808440-cd42ce92bf94eaf35e690296776c7bfe.npy +03790512-ba0f7f4b5756e8795ae200efe59d16d0.npy +04090263-c54be9902d947a1ef6fb0164eb28c4c2.npy +03636649-398c948f08b778a1fcb8d8c6d4df8143.npy +02828884-1bace34d2c1dc49b3b5ee89f1f802f5a.npy +02933112-267aa08f20a000a3b15194162f658e87.npy +03001627-e0a0d5c2ba6fdca215b55266697a17be.npy +02828884-8e260916773769032b7072d8dd8cf43d.npy +03467517-7175e8671bc22afea937a742b4b0dc33.npy +03948459-49429e1d1e90c1ca202be79d8b285c1e.npy +04256520-577625945f1b83d16296847c9d695b0b.npy +04379243-e2a940682bf386d166e77edacd2d5e3a.npy +03636649-c05273997fd65e7b88e7662971dc736f.npy +04379243-b515a107aa3a3fd0e3dff0d5ebb43915.npy +04379243-9e229ffbaf9b7395efb9eda839fc42fc.npy +02958343-7d343bbf3265164fb2d2900ee0ae7e0.npy +04379243-48c61eb9c9453db75828f54ccfceb8a8.npy +04090263-e63cd617410ceddfc9ae1c09f478779.npy +03325088-cc79822a10e3cc9eb362845c6edb57fc.npy +02691156-9a58779da170911a7a571401e6605fc2.npy +03636649-545ce32e4a72ac04352681850fbc4af9.npy +04256520-d66ab7a970a3344e34e89adf02e34b7a.npy +04379243-cbf56579ffce57d84cbbac005f3700ba.npy +02828884-8bf63e9b3df32ff1e1aaa7ea27fc24bf.npy +02808440-88ba375e0d96eea94989fccd91bef01.npy +04379243-b2582dd22be909767ff6ace05b36a5.npy +02828884-f95f1121136052bcd4d8765e3910f617.npy +03001627-2ed972dad69431ab89f8949830ad07fd.npy +04379243-9f78ea7856f21a4ac8e00bb0b2c9ef1f.npy +04379243-3c4e1361b066ea3b8ca998f0f87d0c84.npy +04090263-21b7114455da0bf033e73845251cbf4e.npy +03001627-a27a04ccbe8d5c90b91fe758ff985f40.npy +04256520-621dab02dc0ac842e7891ff53b0e70d.npy +03691459-d027e01fdb3830687ffb47acd56f396b.npy +02828884-607414f33022aff2d2b12aa6a0f050b3.npy +03046257-d220a3a4e31ea77a1550babf1ec984b8.npy +04379243-22daa2fdacd34e086c701087a194026.npy +03991062-dec779d32766f97adbb1480d02e6cccd.npy +04379243-3c34a433ab1dd3e2f657e3152307ea2a.npy +04090263-146529b22d3c510ddf14c6e3e40331e9.npy +03001627-2e8748c612c5d3519fb4103277a6b93.npy +04379243-4cab7b493f8f404694ed13cc64e8d835.npy +02691156-2c83e01a7a4423c74d4cb1c2a5e48b7a.npy +02958343-24c0c6d558d4d01d8772618b7452025.npy +02958343-f8857237df1717e3aa562f24645e326.npy +04468005-e7223dd1d94ebc5d52470de2774d6099.npy +02691156-69a46dafabb616191f9b3085a256a338.npy +03001627-2b9fa5950d81d925cf004563556ddb36.npy +03636649-9fbe081afc5868ca5c9ed170ce1aefed.npy +04256520-5b70eb12242d4a03fb6ca00006f2c76c.npy +02924116-60229aae7778899d248376edfe1878a.npy +04401088-7af2a3d126ac5e44fdda95e9849ffbd2.npy +03593526-1ae4ba2e963a82777cba7aa754e5342.npy +03761084-cfd21967d9621f664e09ebaf49b0cb2f.npy +04379243-19d5525d3d65063bb664d1885442ba70.npy +04379243-4309b8cf22f0382917271868b642acd3.npy +04379243-889f05b7771f6b9fe76bc197b3a3ffc0.npy +03001627-c69069021b390de513232b7b9d3f985.npy +04530566-3c835bfc9201041a34f2450730697f14.npy +02958343-6c6254a92c485787f1ca7626ddabf47.npy +04379243-c5a4cea5107d72f54b3c42e318f3affc.npy +02958343-3b3a3b0d9082236cba77eb053523da42.npy +04379243-a387e9c10bce09c85828f54ccfceb8a8.npy +04401088-612466085d24ce50b260ba4e94db1a27.npy +03211117-ed00d5a47a7ddbd5e464ff83d36486e8.npy +02958343-5b74aff38b82c58f453226473c9b5a05.npy +02876657-10f709cecfbb8d59c2536abb1e8e5eab.npy +04530566-3e874274afe2d37c70640aa5d7fd3004.npy +03001627-b5699ce2511433f3b28ede0f9f5a31e9.npy +03001627-7ed9395ec6fa732248db5ebe0dbfb1d5.npy +04256520-5eae999a81861da03bec56bff764ba78.npy +03636649-36d90198790ed82386052e834fbd2c4a.npy +02691156-617993bd3425d570ca2bd098b9203af.npy +02691156-76e66ae36d942c494c3a35cee92bb95b.npy +02958343-88fc7d197310ea4b961b666ad9ed1438.npy +04379243-42fc350dd15b5ee07bcb070cc655f13a.npy +04468005-abf12741cb25bd593ae1361afc45ac52.npy +02924116-15e2d1fe9a4b28e68fb8c03013603b0c.npy +02933112-d4f4b5bf712a96b13679ccb6aaef8b00.npy +03642806-7d2ed394b410e9646f6e459e863eaab.npy +02933112-f0ebc33311b55d6b4e7d60def15dcb8b.npy +04256520-ad023095f1868d3019fb4103277a6b93.npy +02871439-8198c793defb5c1d55f9913e822d5318.npy +03691459-b53eaf891eccce82a4df8e9a50b4aeaf.npy +04379243-7f9d2da43d6aba67afb6676a5cd782b6.npy +02924116-d72902a7e8401366f31ad0ce8af976ac.npy +02828884-1ef8c3cabd16f7cbf155d75bbf62b80.npy +02958343-beec9297d087a1677e19c609c6e24294.npy +04379243-89251f322490e7047e38640a31d0bc3.npy +03001627-b625936e3db6af6318df1fa50d2b64c.npy +02958343-1e987cad6ca8a97a7a24dbc42a104ca8.npy +03948459-e3619c5b8d8ad37cf4de29b99f103946.npy +04379243-64c8873572f3eae175c80d0dd670fabd.npy +04379243-1c97870c90ff3a4f23fe3501bb9e7193.npy +02933112-721c788bb55b083ae8a9bc001231a118.npy +02876657-29cad22b0fc6c9985f16c469ffeb982e.npy +03928116-598de9e74adfaaae2db285a7fcff0623.npy +02691156-d199612c22fe9313f4fb6842b3610149.npy +03211117-76e8b00a0f6f78de1f82a1eb98f84dee.npy +04256520-89f4bb22cb53fecaa0fded058fdc8ec2.npy +03991062-3fd59dd13de9ccfd703ecb6aac9c5d3c.npy +03691459-60858213ecdb37dcb7a0c56c5d82c3cd.npy +02958343-e297de736f8f0b3f67738c2420579616.npy +03325088-74239af5ddd1f9676c18e71fd49c4dc.npy +03085013-4daa8d27a660895142ce30c291f8ca44.npy +03636649-370a49ad568a764febb6b411cf15c31.npy +04256520-330caf403f42c12ace8417aef1b7a422.npy +02880940-7ed1eb89d5463580a2c59a4d90e63212.npy +02691156-17c86b46990b54b65578b8865797aa0.npy +02691156-2aec6e6096e640add00d52e62bf14ee9.npy +04530566-74093f3d2583f3be7b0299baad14624c.npy +03001627-3f4f6f64f5ae57a14038d588fd1342f.npy +03001627-457aed734b0a8619ff6d40d828e0167c.npy +03636649-94ca5c31d2ba70f42cd2160e449d45ae.npy +02992529-427e06d425b901be5c0be177939e290.npy +03001627-594d5b7f3e705a1ab3234e0da44b11e4.npy +04379243-c3e43144fd61c56f19fb4103277a6b93.npy +03636649-edcadf508090e17bfcb8d8c6d4df8143.npy +03001627-9905ba0488b0471dbfb0f09ba9f2d99.npy +03001627-2b9ca6deb278a10cffc21cb5f21201cc.npy +03624134-262a62f3e36262e313195356ebccbadc.npy +03001627-17e916fc863540ee3def89b32cef8e45.npy +02958343-12498dd65e8d65ac3b6f5204eb590354.npy +04379243-190028e65867076ee12186cc8c5022c7.npy +03467517-61f90a151236d28640c20797381ee39f.npy +04256520-398bc907b92b0260285dd489701ccbff.npy +03001627-44854046021846f219fb4103277a6b93.npy +04379243-d36f8b6fbc03cb3630aec64313e58bdc.npy +03691459-29a7fe8fab62a9e134cf66ffc496802b.npy +02691156-e3bdca8304aa6593c503a3776fc280fe.npy +02691156-4843a702815e8ab442ffb0c016ee58f9.npy +02958343-e8a8d47957d15bbf8079d5a13e411210.npy +02958343-9757fd5be93ee0fc82b157e7120744ea.npy +02691156-fc9f6bc1ba1cb7c1c3fe7930fce05ded.npy +03636649-d5815f747626cadef912acc8c54e7fc1.npy +02691156-b644db95fe32d115d8d90babf3c5509a.npy +04530566-88b27dd110461b38b193f1c482b98a75.npy +02992529-f9ecc6749a251c0249852b2ef384d236.npy +03948459-1a640c8dffc5d01b8fd30d65663cfd42.npy +03001627-36c4421ff44218775510d59f3ab1ed64.npy +03211117-1405ccaff7fa9dbd51b711a0825fda5b.npy +03001627-27ea798c55699b6d2c528d33bca1ac2.npy +03001627-5a460cb21fb55f639f73340130af944.npy +03636649-eeefddb3f2ee93dd49b2e04785f8492.npy +03636649-f092117adb1e9254d1cbf3e52b9b6237.npy +03636649-8338a18d589c26d21c648623457982d0.npy +02691156-343a607d1604335fb4f192eea1889928.npy +03636649-a186c58be79925634cc30865d6337b9c.npy +04379243-b62908961c47a373b097f065a7be019c.npy +03001627-60cbc688b57f8b5446407779dbd69b2d.npy +03046257-22d22a2578f0a3574b3c42e318f3affc.npy +04379243-1674e0a5bde2dd67f12d7184a2ad3430.npy +02691156-19e531e6d0bd5ddd67c54439d6177032.npy +02747177-3ce42bc74819f5dd56f6fc4b4ce1db04.npy +03085013-4cade5a7ad1f473870d89967fcf73679.npy +03624134-75e32ddfd15d3ef1fd92188644609a39.npy +04530566-23be001cceb4c31af6f70779d83413f3.npy +04379243-506e4e67efe1794c1dacbc3d67b5a11a.npy +03691459-5b931476c24abb5535b5e203791a802f.npy +04090263-7f9e93c855aec4995e22590d7220b895.npy +04530566-72c942c6ed4dbf4e8e5cf2440102d1ce.npy +03001627-a873a489386dc825ed843e67f2e2e9d.npy +02933112-d08027b0f50619ef5c2f6ec7d4720d0b.npy +04401088-1101db09207b39c244f01fc4278d10c1.npy +04090263-e9ee67ab2cccdba5771dea817d9f8136.npy +04090263-e07fbeeec2a12fe313b315bf7aba3803.npy +03636649-36c6a6f0e206c79890fd203f931c9af5.npy +02933112-b6392ba0cc9448b353a5b360543fbe7.npy +04090263-911535f04299f4a53f732a8d4ec0bf11.npy +02958343-83db7e16a49191e5ed3696d854eee1ec.npy +04379243-63669ae28cf69b767f51cfad32a5bc58.npy +04530566-c189e1768a4f291d4de203ef6842ee61.npy +02876657-72d49a11c34a3b6880dd154b5d9c087.npy +03948459-fbda020053554eeceab5ee569c9de1b1.npy +02933112-9b885f40e2d36819e4e346ee2650d150.npy +02691156-dac25e0fbef7dabaf1692146d36a4a3d.npy +02871439-be99f079debaeed9a0fa21f3ff15b515.npy +03624134-e03a2ab2b6506ca0ef1f81f15fbe736c.npy +02808440-23288026c3ce8e5dc197f3661a4ec752.npy +04379243-a211f3080f4659131622a21d32ed9c9.npy +03001627-7ab86358957e386d76de5cade2fd5247.npy +02924116-d8226fb72a137597be2e23e91e24717d.npy +04379243-c2ad4e19213d839873baa2510487646b.npy +03593526-d9a35f5bcc527fb3a982675e6ec522a0.npy +03001627-efd0411eaf2396c4de7ed732f5aeea4.npy +03001627-e74035d3001deb876fb1d532bc5b4021.npy +04401088-7176e9baddd8a2ea33ac431572f43a21.npy +04401088-5148da752bcd11884ce243cdbc967ce2.npy +02924116-f90bafa70be9bf1bd4713685ae50fa13.npy +03001627-7ef4b16e0c38fe09b04cb542e2c50eb4.npy +02992529-3ca1d72d2416bee6f4e9c7b80248eec1.npy +02933112-15d7f54338bcca35e82e35fa57516a45.npy +04379243-17b444c072a6a3ec76e9713f57a5fcb6.npy +03211117-85240d0fdd8bc669ccf3727bc3da6c48.npy +02691156-3b3eb57af5f995c268aa0dbe2db661e2.npy +04379243-7bf29d83522f630190ff2a7142510fc1.npy +02691156-fc7fda7232bedd84bbf3143b1cb6076a.npy +04530566-2467cd9f4ae70875e26aef76db45b56.npy +04256520-a105701680f658b8f92f3e7bff4c4ab0.npy +03593526-d74e6a54e500b5744f9bdb71bf603cdc.npy +04401088-1105c21040f11b4aec5c418afd946fad.npy +03691459-b6ac65861f2b7a726bd362b3eb022b32.npy +03691459-a8277672da45a94e9d151674c6eace6c.npy +03001627-3f4e88498f4e54993f7e27638e63d848.npy +03211117-c61bc4cd473fe3326bd865f153842b49.npy +02828884-961d59d3ba6c7e1bf174129a51bed83.npy +04256520-a2b93b7632e98eb944949d7685cb63ea.npy +03046257-806f319a7465817814038d588fd1342f.npy +03691459-1334b56706bddaf4451f278fffaaebae.npy +02958343-8df83b28d786ccfc10f2ef3071342a2e.npy +04379243-462afff41381a622ffcc22765a7dddc5.npy +02871439-b0c1a8d1988b72e92987a7b722c00b7d.npy +04379243-b896a4afaa13fec7e90f16feb54700fa.npy +03790512-179998dd1743facfd5dde04c96fd8146.npy +04256520-bdbb64bc1fac0cded0176f9a144100cd.npy +03325088-9d2aaf99df5b83524ef883cf529ce415.npy +02691156-1856da25a85402ce63e266a803d9270.npy +03691459-aff81ceb0788c2c2d77f9c6ccbaf6fcc.npy +04530566-efc2b7a0ab3828761194cbd9c0740031.npy +02924116-c31a4569c45b13c9d1c83bc8b134e4d8.npy +02691156-8b851217c2ef15b8eeb11afd6f15c99e.npy +03001627-ff793ca32407b2022a54a8462d1ffe9d.npy +02691156-d3f2dcf27000283799d9d900afe054b8.npy +02871439-fb25e1f798321c354a134d5eddec03d4.npy +04090263-aded0c6beed6938ba39dc4a567ce225f.npy +02954340-d18c3ce1f186c16976bb31db0358e9c6.npy +02992529-b159743a482e73baa56eeaf8467b96e.npy +02924116-a89483619f413f91e9bc5a3190ed0a27.npy +04379243-7e871b4bbc5e3d175cfc8af3b7d60a4b.npy +03691459-b4e7253cb9ef78852b75817a0faaa5a0.npy +04090263-a4888af5b6c4c631cb239ba7670e0fec.npy +04379243-30ef2e867e365b735445e46058840642.npy +04090263-a0e251b5b4305d49893bac51482eaead.npy +03624134-df7a65224f295122ed9c5b25fef60d04.npy +03001627-79850e4ff6e43e6b3dfa4373373135f6.npy +03624134-2c23a56cbc058d5356c5c8316540f708.npy +03624134-66955a3156556f0d1395331ebe4786cd.npy +03636649-387429f609793f9dba5342d638d0c267.npy +04090263-ddb85b40a6e44c387a9af63cfe0c0758.npy +04256520-bfd15618fcd88e104017642dab433250.npy +03593526-aaa87a2a3a5b8ab4a156590b19c3013b.npy +03636649-fad0ae547e1facc09f97ca916781e800.npy +02992529-d2bce5fd1fd04beeb3db4664acec42ef.npy +03636649-ada0e305757901e589daba250d5b5a5c.npy +02924116-3221d0114c010afd613873e456db29aa.npy +02880940-e4c871d1d5e3c49844b2fa2cac0778f5.npy +04379243-ffb7b155cea1159a3a8e4d3441f2dd18.npy +03938244-590fca6c280bb31c943b92d8dfab705a.npy +02924116-567d3b42ab9b89195135b59750002c2a.npy +03790512-cdd1e5890e5a766a65397d05162306e.npy +04379243-839334dd754c09e5b7ea82317702e856.npy +03001627-879ffa2150c4537d6afcce3b00733da.npy +02933112-ccf5eb1023d22445762406157deca112.npy +02992529-4534e6754bcc38f78bc584bb94b0b13b.npy +02958343-10f158d2f43926ac80360680c1602c7d.npy +04090263-4fd2d1fd9aa1f2e4d3756a4e297a88d0.npy +03691459-60575cff5db034c621e6f308016fab7.npy +04256520-5cf46a99a9dfdc07411e8b42940aba04.npy +04379243-468955eaf3b3a4c6df8b5f0b7511efe5.npy +02808440-85c3bd8f53a7329ed83a3378d32b3048.npy +02808440-beafc45419f70db3252e0775cff1c394.npy +02691156-350d12f5290908c7f446f92b52bbd82a.npy +02691156-884adbb15fcb934051279f7b42f4d889.npy +04379243-995e0edbe7bbfbe0659dda512294c744.npy +04256520-b2cfba8ee63abd118fac6a8030e15671.npy +03928116-c5b7d166231c04328413778731d6cd28.npy +03636649-5a9e0dd068e2436bd7ebac63aa51083.npy +03761084-5a98c841d578715e4a44340bf227e40.npy +04090263-5f8a81e3c0711e087d81debe03396504.npy +02958343-227ab69792241382acfaf62fe6ca656.npy +03797390-128ecbc10df5b05d96eaf1340564a4de.npy +03211117-9ea0bddee8c8654d6b56d21c51d762b9.npy +02933112-68582049d02c7c979ebcda765f4eafa1.npy +02958343-36c2770d00fdd0bdf1ee968c9039cc3.npy +04379243-ff212e47775ea7fe6a3056c8cad72d81.npy +03636649-cd80cc92cf732e8d8a17805dbfb751e2.npy +02992529-cd7e6ab98a2d090099b101e0ce243aa5.npy +04379243-dea755ad1156374f55f46d55537192b6.npy +03593526-bcacdde81063a5df30612f5c0ef21eb8.npy +02691156-e160529ef50ae4dbb819cac660ba383c.npy +04379243-dec1d2cf8a4563d36cb02543e4df83bf.npy +04530566-b942192d17d2e267b7cc248da6c5c5b6.npy +04554684-e994852d9f4502674a16879fb3ac81f.npy +02933112-29faa40d5c0a65a576e9713f57a5fcb6.npy +02876657-b033d2a7efef6d881bd37ceeddc6ee3.npy +04530566-30e536833dee7cd8a9d21767a2141a63.npy +03991062-9ea66797afeb86196ea1c514a0de6d2d.npy +04379243-975b724129620c9af4b6538438a0b930.npy +02808440-75ab1d00c330fbb36f893b5bc716a3fa.npy +02958343-dd768e1b90b4537cd9eb65becee97781.npy +03001627-a5dc036f882fcbaaeb655fc642cef479.npy +02828884-88fa7d07abfcf9f03cbbdb20d4d80207.npy +03761084-6d8a8628eeb8ae92de6fb7d70c413eb.npy +03046257-d7942f024d24b8ac731e5d7a1aea3c4f.npy +02958343-3f702ea027037a5c4d18baf048fb19eb.npy +03325088-ee9f4810517891d6c36fb70296e45483.npy +02828884-ea518b89b8511916ac51268fdb437a9e.npy +04379243-621ae6c715e1af8087694c57464ff1e3.npy +02808440-8ebeac47d29d649acb6267f1b348aaaa.npy +04090263-44f2f626a4c73b216314c3b6a3a65519.npy +03001627-a5eea0cf3865da9749fb53621b8edde7.npy +04530566-d939109a33e6e2d175517226b23c384c.npy +04379243-32ea6609eb659a2cec3367bccf60e518.npy +02747177-33e36da1afca5e57f155d75bbf62b80.npy +03001627-5a61caff5d5b3e22424f8f8e828c9ab9.npy +03325088-21c4d5612e5b0437b362845c6edb57fc.npy +03636649-31a15957bd4f32f87eedf2c7d21f7cfa.npy +02958343-7bd15f738bf2a402d4fdf31cc2d78fd0.npy +03046257-60bc27587a400433b885fc9e74ed3e30.npy +02992529-71fb433e386a5547f63375fea17cbfe4.npy +02691156-79c10c1d217b4e96ee2723567c7709e6.npy +04379243-24b208dd138d8af36210db75a4cd581b.npy +02691156-55ed35a03b08a8f44f95630cc18536e0.npy +03467517-b427af4fcda02cf61a2c693bb85517c2.npy +04379243-1f5ee5ebb9ba55f454d30af857cfae06.npy +04530566-7fa94092d77b9f7877c1e07fcf5968a5.npy +04379243-5e0ef66271f36ba862feaf6b02ccee1c.npy +04379243-3a17eae5843c2c7660a62758a708c922.npy +03636649-2d4c4ceacdd41cf1f8c0f5916f81d758.npy +02828884-ad3c4c72cda4dcbd620ea05889322bef.npy +04379243-4a944441380ba0a45990f2c81f286aec.npy +04256520-824953234ed5ce864d52ab02d0953f29.npy +02924116-b4360cf115a6678ca71edfed1705a549.npy +03001627-92450ce64f51c778f235ab3c41aeb5b6.npy +03001627-621c62aa667c4d3cfe2fba8e5d6db330.npy +02828884-b628ddfe4d99a46021c74c368d3910fb.npy +02958343-fa563c2b77839dafc0e3666c7d0ec7d0.npy +03636649-3c3e36d1faa6c53c1f886eb96ca2682f.npy +03211117-b38d6f1025399725815b2b467e8e2eac.npy +04090263-bad9e6cf69ec4553db181f2efd806577.npy +02933112-66c38b5e6d9ad852307776da88d1350f.npy +03710193-c6d910f8cd92a59fdc83753cd31caa42.npy +02958343-64ee682c9dd2ee467cfc46ae22f84c92.npy +02958343-d922b4f3ba23cf43780575af49bfeda6.npy +04090263-da5d74a592c747e9ef7cbef6334698fc.npy +03211117-3c7ff78e8036b217d3923426933f698d.npy +04379243-47b6fc814d22a030db6175ef18ad3f80.npy +02933112-3e080e2b2556add4eabad247a05ad956.npy +02808440-c9e4c04d662d401afe52ffd0e748a1ab.npy +02828884-7a2ad24394c5d139d46c340938e2ff1c.npy +02924116-8b976988a516590c4096404077ea89f9.npy +04379243-667b59df5e098355c82f50464edece2d.npy +04379243-6afba6bbc7ca32bd339797c21e8801b1.npy +04379243-7556cf66da8b4498e12186cc8c5022c7.npy +03001627-f2a4d96e77d1c92a3d6cc735e3493c99.npy +03636649-caa8985efa72ea528d6a77b750ad3e43.npy +03001627-33ce7f85e65320ba9a404da609e2789f.npy +02933112-3931068c10d0a606ef37b256c10c21e4.npy +03001627-aba6ab10f7ccd59f9f8c3d2002c77ddb.npy +04379243-1a614377adee252e0445fc6d980dd5c.npy +02691156-65f77283a392890aa8cba409c4409ba9.npy +04379243-cd82d526e58e3e7f4fb85ea6fd426098.npy +04379243-7c15998c0d653821ab610b0c94236463.npy +02828884-91c949736e4887002ea98d69e91ba870.npy +04090263-1690a5959e2659d165b14b263bdb456e.npy +03691459-fad354295b4c0fdb55266ce6303fe1e0.npy +04379243-f94bd6bbed8fd60614038d588fd1342f.npy +02871439-2b9bb02f657a0e582ade7345ab5b0cf6.npy +04379243-dcf1095b329396b3a193550461f84122.npy +04256520-308a144f77a7aa2dda625e752fc62bb7.npy +03001627-6bcba04c2e45150779368d1198f406e7.npy +02924116-9e3197f8c8e3d6effa3f6d7e682927b4.npy +03001627-95db11e86efa7c3e8c6222d771a6c85a.npy +03001627-9a91fe80c2cd2f37f51fa0238791f5dc.npy +04554684-81c849960bdf3f1e91219aad82abc053.npy +04256520-9ab89ecff5672c38aff5bf458c586262.npy +02691156-da58b3e055132c9f6afab9f956f15ea.npy +02691156-c9aeb20d7cd1b3b45e9e2656aff7dd5b.npy +03001627-5f2d4c625595dc2499b025797420aa58.npy +04379243-7980d0e22c197dfa5e7e52a559b573fd.npy +02958343-1bef8891f35535ac2e877e82c90c24d.npy +03001627-2f249cbcbb122b85845e78b431e4d529.npy +03593526-7ac1b3847038de0e4b3c42e318f3affc.npy +04379243-e3287950481e9811cf48ae153052b71a.npy +03636649-c25cc72cd06852e75bbea6ee257e41cc.npy +04090263-b79cabe03c878d2980c2e60c312b0f09.npy +04379243-ee5f85db427865e63e5399147a5b4763.npy +02691156-3dc5331ce579b2d0d8ff6111270336a9.npy +04468005-c4053005ec79262c9954eae9164faecb.npy +02691156-5ad5fbe84d7d8ef790b1d6deb98feec6.npy +04401088-6167bf752533508dfd6e968ab91bff17.npy +02828884-632fbec93961015ccb2a965e75be701c.npy +02691156-653665e9c401e7ce6b310cbbfd03b8ce.npy +02691156-15898fef6fec88c53ada73811bb576de.npy +02691156-e17a696c47d4292393db03f6b4e68f17.npy +03636649-e89a02d4a6cc95f3fcb8d8c6d4df8143.npy +03001627-e158f7ba6828db5c654ea6737b0d3597.npy +02691156-2421f54274a5c237e8cef78f8179925b.npy +02933112-139aeafbfbdd6bb64da5feafe6f1c8fc.npy +04256520-9a7f267890144d4a7afe2ae8eef63a8c.npy +04379243-5aef22f5441b495d19fb4103277a6b93.npy +03593526-489317571832ea4c15d3518b43b3bc22.npy +02876657-1f1e747bfce16fe0589ac2c115a083f1.npy +03636649-cfebf5d2a0382ee3fcb8d8c6d4df8143.npy +04379243-71d50d287357e7e719fb4103277a6b93.npy +03001627-8e678a54f2ee4e5e492d9da2668ec34c.npy +02876657-e119bf2041459392601bea3dca268229.npy +02691156-64211a5d22e8ffad7209009cfb89d4bd.npy +04379243-6712647c8e0c6af29b6e5e087210d348.npy +03691459-292353a763d0870432af7736a533c197.npy +03001627-ab4fd3bdd8c1dede578d107c71db28ac.npy +03001627-8ea007bffdc9a27831aee04639d1b4e0.npy +04379243-cdf9659a23c89e80a23949c21eddef76.npy +02808440-1cc2487bfbc0209e3321831d2245cf06.npy +02880940-baeaa576ba746179e8d7df9e0b95a9b2.npy +03001627-eb2fabae15f77882139d2c86c9e03ddb.npy +02691156-c3733e626c07b9ff26360e1e29a956c7.npy +02942699-9cdaf68ed1e1daba9c21adf7cd249be9.npy +04401088-ac0a78736d78a5a5dd8524baa80cc603.npy +04379243-fa72e9cf7308066b1c072ac0b83fe07a.npy +04379243-92ee07567c94fd6d9a53d72e083de39.npy +04379243-4e15b52579903323f51f77a6d7299806.npy +03325088-ce9fb0a7128d11de76d20e73c57c9a03.npy +02808440-547a161a58187d52d4ba28a7ac06cf0d.npy +04090263-f6f468a51ccb62669729231d295371f.npy +03642806-25bc168b214b54799e28e9cf32e5157.npy +04090263-642e457eeebe04758480c9cd0a5e2175.npy +02958343-647faf34f7fdb50c16abce8cb03e7794.npy +04379243-6d9d5501c0a3d8f1615fc479d27ea86c.npy +03001627-336e92c7c570250251c4deb11af7079e.npy +02958343-468780ef4ace9a422e877e82c90c24d.npy +02691156-22dd4b6a60e20112185b376619557c95.npy +04256520-a7f45bd27efe50af4dbf8d635749f669.npy +03636649-b4e7c74a6e6685d2339c933a8cb966c.npy +03001627-f7e1a17728ea76dbc6bcadaedba80eee.npy +03001627-7fc8b858cad8f5849df6f10c48eb6cee.npy +02691156-97d662e5e6345b46bd46d022fd7d80aa.npy +02828884-1e039c5d86b061a593ebeeedbff73b.npy +04090263-48d29b4a2d749776e2e5bc9806debc17.npy +02691156-d06105ee2a2ae27c51008e496c6cfd2e.npy +02958343-7611c8605cb47d74b11647ffa4306609.npy +04401088-2a6d70bc7ac6db391d4136675e1527dd.npy +02876657-3b26c9021d9e31a7ad8912880b776dcf.npy +04090263-5707b3eb79f78b5fb9dd291f5235c28e.npy +03001627-2d44744a7ea0bf724b3c42e318f3affc.npy +04530566-9114091d7dce55242e5cac9166d7a1f5.npy +02992529-7dd788cca7df768495b1245be456cdf5.npy +04379243-c966a18da154da2c467289cae69b100f.npy +04256520-645aa5c32b9fe34014038d588fd1342f.npy +02924116-3caed8944366a746c8f372fe11149a91.npy +04090263-9397ae7d40c327044da9f09deacee7d4.npy +02933112-98003a902555e73adc6a693174c70feb.npy +03938244-950f71d6c271cbf47676dfce60793e46.npy +02691156-cd9f07bc1e5087b7f33a09c02bab9cc.npy +02933112-a6abf531780014f890a1391b3fdfda26.npy +04379243-beebc267ea0c16a5c7f6a57f6f73d8a6.npy +04256520-c722e02b37ec324463d444e16188727b.npy +03207941-3ca503ae899826e88bb4434d620302e3.npy +03001627-3ab2563609476e089868adf0764f7fd9.npy +03001627-4f5639e943b60edc600515ec9ccc96a4.npy +03001627-d1b03eeb33fd441d8189e5e3786f2290.npy +04225987-4473c1e89500747b5cc36f190f62c41.npy +04379243-67ec09f7e7cd6f059f2349486c570dd4.npy +03001627-17b558e72a4d76ef8517036a5ca6b1c7.npy +04256520-fd2449fd2aa8b142febad4f49b26ec52.npy +04530566-e0ddb444604f573d48260190ec06324e.npy +03337140-640b94d5aa88d61e4c3aee8e9d3a6ffa.npy +04530566-dace99ad1144747eaec7ac3c7340a2f9.npy +03636649-1499133658ea746d713f2e93cbeac35d.npy +02773838-4a1f62dbe8b091eabc49cae1a831a9e.npy +03001627-3024deb09ba519c517089ab023f65eee.npy +04379243-12a73c63681d65587a0f32fa630f6a0e.npy +04256520-105849baff12c6fc2bf2dcc31ba1713.npy +02828884-7def648b4fd4d1e419eeae21e79bb898.npy +02958343-c6762641f741acc2a19bced881c9e641.npy +03046257-217b47212a5a521ec6870dc41f78676b.npy +04379243-61fafe333f8c79c78716341f2dff4249.npy +02691156-4bf0b3df529d5093551df482db927edc.npy +02691156-29192f8c96264e3435fc197bbabcd5bd.npy +04256520-16cc2e83a7ed73b7789a00cfce0c4a8b.npy +03797390-336122c3105440d193e42e2720468bf0.npy +02691156-551635d89144da64299a59bfd8e7d284.npy +02828884-f200a8b5882be096d104df3d337858a6.npy +02691156-296d0aa10bd7ddd87965b154b2af39d4.npy +02876657-518f6867e5d38301fd3bf7a5792372cb.npy +03642806-6f1d1ad1d8238e84957b6a4f3924d982.npy +02933112-97c6b3099a406960d3dad974dc098fa1.npy +04379243-c5ded58bf0e362eaef9f898cda0ff409.npy +04379243-a251543112f3a452fc5718d28351c534.npy +03593526-a722038146f27d9550e02ef26f47fe02.npy +02691156-ba7d272a0ef0f06cd165fddf32a925f6.npy +03001627-ff167d9f25fb6ede2419ec0765e66c90.npy +04379243-d20562f6f18add5c7dcd20e7ddd78bc8.npy +04256520-9ba5f57133b048f771e087d4163df51e.npy +04090263-487330fd2ba7d55f97020a1f4453e3a4.npy +03325088-14dfa201e54c7aa0b362845c6edb57fc.npy +04379243-ad0082e4bc0b5ecd2058afcc28d23393.npy +04379243-6739b7952f7e53a7ee462e7a3aa014c7.npy +03211117-cfdd661f4521ae0e331bde3212dc4d8.npy +03636649-6a044fab6905fb1a145fa6babc33219e.npy +02691156-efbb9337b9bd3cab56ed1d365b05390d.npy +03001627-ed3e73a2609bf304377b9297f3055210.npy +04379243-b87c155d6c95c768668ae11a7db5e82a.npy +03636649-bd234f132e160fad8f045e3f1e9c8518.npy +04090263-c7e84421af16e48eadfdd35441a4b4ea.npy +03001627-ae9e1ff1ae0b0a8f6ee473575a9f31bd.npy +03948459-5a2bb05af1dedd91e641b9ab504917bf.npy +04379243-2f9c9357bfb89ac1d38913e96bbf2a5d.npy +03046257-56303474bcea6fea3b48a711df82173e.npy +04401088-a857d9e7cd90163e10bc2436075f6a52.npy +04379243-d3030c8698bc2f874c4c693a60456ebf.npy +02691156-62a72a5afc84ed54faa7ec7d870d2e09.npy +02828884-6150a9e7c5534dec50cdeffe12411e9e.npy +03636649-78b7adf1f72ad31a841a2fa612410176.npy +04401088-dc2c4f42a5715d0a6d1ffe1a45470ad7.npy +02924116-4e4402d72896357d1cd228cf70713a1.npy +04256520-953707e41b518f631125768e50c51e2a.npy +03593526-de948c52437de4d2a57b3bec78e5d1b3.npy +03001627-1e92f53f3a191323d42b9650f19dd425.npy +03636649-da4fe1c3d5b1eb6ab2b4f8bf5db83688.npy +02933112-12b0773858754105c59350d819542ec7.npy +04379243-16802a946bd714e819fb4103277a6b93.npy +03001627-d9346fab44b6308f40ef1c8b63a628f9.npy +03001627-79f86911bc86222a4e5aa1f8c960ae63.npy +03001627-aa6f5bed94640d81c20bf61cb7d8cc34.npy +02747177-11d2b7d8c377632bd4d8765e3910f617.npy +03085013-f24f90cb00b51c2ec8c3ac9bcbcd9687.npy +03337140-53a2e3a87300241c195ae0b4bee7180e.npy +02992529-693fba444859fb7d54c65e829609f393.npy +04401088-9f56c8a7cb64f4c36c87ee6c360661c8.npy +04379243-589599503c7b88129a87002a4eeaf610.npy +03691459-a6cd2be54bb9297d53c8f7a04cc7057b.npy +03636649-13ba3fbe8fbc53f3ef3a2c64cef919d0.npy +03928116-e92073bfdd7d3004f8ce064c0d1d8055.npy +04256520-e921afccfbc7137c5a95bb8b37106cdd.npy +03001627-8d40dbf5ada2f6f662e4024c69de065d.npy +04379243-c4202200cd2ff878489ea1c28ddd58f0.npy +03325088-1bec5441a4a0fc3d6af014d294c0e7c5.npy +04256520-ee5631d8abed7e69b06dae6f40c44a8.npy +04379243-304ff1fce32b5bdfadccd0ac21fd007a.npy +04256520-9f47842c7fbca0be593ebeeedbff73b.npy +02828884-81d5dd006f418712f4fb4dee5181bee.npy +04379243-ce88f6aa0e43bf8811099baf02792d0b.npy +03624134-a496cafc5238575291687e259c21528d.npy +03467517-c8acdfaec5008118343b0b12983b9982.npy +04090263-fb686ac45c8e545c8d1265a14954deda.npy +04090263-b2f4f17f6d59c6a53e1cebf83f3f1bdb.npy +04379243-b14cec4ece246fb75b937c87a8810c08.npy +03928116-59da3017ec277bb92cf5a6ed6299d488.npy +04379243-127d935d17cb36c8b0a3f25f5d8cb0f8.npy +02933112-3bb80aa0267a12bed00bff798ed59ff5.npy +02747177-b729214e49af571bf155d75bbf62b80.npy +03001627-ea281c9e968757dc351f7b956f3bf26a.npy +02958343-3d0308da43d52e3ef56f8ea3d9016e55.npy +02828884-6a2c354ed5212c77d2b12aa6a0f050b3.npy +02958343-a8f2c3adc0671c15c64e95fc6a597455.npy +03636649-ab8afd0f2f10be4f3443b22038d340.npy +04256520-b1b9c6c7b55d5bf845ed290334fca9ad.npy +02828884-18a3d4fa8abccfa7ff8d4c5a7727a428.npy +03001627-584ce0f244158b37de2b9bba503c21f.npy +03691459-a47b1e6d492bb68e8dcbd53cc631ab.npy +03467517-eadc5e7826fa778939257bd6adf678.npy +03001627-cf0d80feb2f6f71d9df508b37e4a3518.npy +02828884-4504e203b67dd8e473f10e6caaeca56.npy +04460130-17e229dbb42786e6b164f257e05e5435.npy +02933112-d6a58b80b6f1a4f9a14bb1d7e401bf06.npy +03001627-55192bc667582ebb83d21872be197422.npy +04379243-fc3d26aebbd75ed01e112f5fb42394ff.npy +04379243-cde57c6c75d1453a372bb05ca908b13.npy +04379243-a075004f2659de5a797e3338b16ee6ad.npy +03948459-115aa37af1a07d24a5a88312547ed863.npy +02958343-247de29743ed24c5e61b9ff60b1be412.npy +03046257-fb0dbe220131e28f6402b8f491cd92c7.npy +03001627-645022ea9ce898648b442b160bcfb7fd.npy +03593526-807620fed80ead9672160feea2b67fe8.npy +02691156-396312e9bec88c2590b1d6deb98feec6.npy +02958343-d4d7d596cf08754e2dfac2620a0cf07b.npy +03325088-6975759bc0f32b912f9e27b3b2a34f3b.npy +03001627-9e39c4ea1d69b2f19b1e9677d6cddea0.npy +04379243-ab8644ffc94a2f2dc746cacb18b4d81a.npy +03642806-8e13c7ff206a424fd52bc338a86e79b1.npy +03211117-d7ab9503d7f6dac6b4382097c3e8bcf7.npy +02992529-9f56c8a7cb64f4c36c87ee6c360661c8.npy +02808440-a4c022ea469ffc054416e513daf6e560.npy +03928116-7d4429c2b65ab0dcc05cc8f408623292.npy +03636649-9fdaafde365beafc37f7ce56c66316ea.npy +03691459-60a7df9bf00844735e7cf7bd2b19c869.npy +02933112-8fcaa6e3a07bcf5038169f16cecf9bd.npy +04530566-55da76d97620d111e3ecd2d9271dad4c.npy +04379243-9a066882ba79738fe3767a60a4ba1ba5.npy +03001627-1eed5ebb2af372cb5438b83aba42ca46.npy +04379243-924ea50a921ac1e032fe69ab8bb2a7c3.npy +02691156-228478022f30a2bef1f87579d4dedbb4.npy +04530566-eba55caf770565989c063286c702ba92.npy +03691459-4a124e8015bc6122778ed5a91adef178.npy +04256520-836d2a7bc26d1b75ec195f2cc52f3287.npy +04379243-25bc205f6de491f4ccde40b1205ec7ff.npy +02958343-e39215e03ab8e65e68428aabd2c41ee8.npy +04379243-bc6aee7279114dff428a5246ba7de3fc.npy +04004475-43ce5d7525f1e7cabd349f2c5e600fd6.npy +03636649-7eadde33d9f9d8b272e526c4f21dfca4.npy +04379243-4e9a4060a7fb0dd230bbd4cddd04c77b.npy +03001627-be7897b96b04a5d12aca5d156344f8d3.npy +03467517-a3aa87664655c03b276c3d558130f8b4.npy +02933112-ab870b99f869186fd523772c66ed5bc5.npy +03001627-a5d21835219c8fed19fb4103277a6b93.npy +02958343-75221b7668e145b549415f1fb7067088.npy +02691156-973df01cea43c7f690b1d6deb98feec6.npy +02828884-4d24a0d4ed77db9f4b3c42e318f3affc.npy +04090263-d88c106c00384130fb5c1b0f759e2bc1.npy +03001627-1b7ba5484399d36bc5e50b867ca2d0b9.npy +02691156-8ce12b6b3b451b8ad0671652a4c42f7b.npy +02958343-a5b7cc1a5ab2828b28b0b7b876595fb8.npy +04530566-fc15175b34b5e47ec57b4b6e80796be3.npy +02691156-e4d902abdf9481558caa71b1fbf7fb98.npy +04090263-39ad36394c9b7267e2043871148f79a.npy +03593526-abf5f73c5440f78c20d37e3fe8c3f09.npy +02992529-9911b2ee8470d6dab2098fa3046754f.npy +03325088-59d8bc2a9d837719b362845c6edb57fc.npy +04401088-1bff7e425c06b65af431996b7f8b435b.npy +03001627-50c446295496eca73542594e05cedc89.npy +03636649-78b95abd1d1158ffef3a2c64cef919d0.npy +04379243-2181ecc9b382a7a873fdbe4b39ff4036.npy +02933112-76fa5df01e82242c684b7bc3f8a9aa55.npy +03001627-df84087fe057385019e48122ff512ea5.npy +04530566-90e6c6083fcd47833e45dd2f173cbf9b.npy +02992529-d7ed913a3888696d289b03e5721252f3.npy +04379243-6606f65226a75c2e34fe19fa8681ba9e.npy +02691156-fc5ca618ae253663d13ef00338ba8c52.npy +02958343-642b4f6a2ce0e388284432ce2f42f498.npy +03790512-45b69ab448b01056267aabe46d1527a0.npy +04379243-636fb360173b08e788dcbe86402c7c15.npy +03001627-3270016f24001d9f3149bb9ed65c73b1.npy +02691156-6aa1ef13aebb1935ebdda919ac927e5e.npy +04379243-8a12ba383cbda72b91829b477862aff6.npy +02933112-850bd3a9b96e3ac67d3aa3bae1f7b494.npy +04379243-6daed91ae491c9cbe22ea6d770699e4b.npy +02924116-8d52b124e1c9ca6720d6874a38819f38.npy +02958343-c683e8e57b20ceeab927782fc69a1fbb.npy +02691156-a777672f17d3641f1aa9d8d95b6740cc.npy +04256520-157ed8452a7edab161412053ff521f64.npy +04401088-8ec3b148b8c608a0562c671ec5000f23.npy +03790512-8cf5bd117e04da6d6a3456c0ab5674a9.npy +04090263-f6d74e48206fca39a6e43b878d5b335.npy +03790512-97bb8c467f0efadaf2b5d20b1742ee75.npy +03790512-6ce7a58297a6fa5c8249f134aca4c817.npy +04090263-98ed5fe737e80b11eab5ee569c9de1b1.npy +04530566-6abd7ebbc9020871bfbc6e788697e036.npy +03948459-8a071ea65e9057a1c7c8ce3bef5c2aa9.npy +03636649-55b002ebe262df5cba0a7d54f5c0d947.npy +02958343-365af82203c96fbca92a4cdad802b45.npy +03991062-d246fc3587cda5787c6842d93e448798.npy +03325088-994f4a915885dcadc36fb70296e45483.npy +02958343-d6f8cfdb1659142814fccfc8a25361e.npy +02808440-9177eb193eac94dbbdcdba9491bb75f8.npy +03642806-9cb17f33ba3c057255d5baa5be4ca05.npy +04379243-7a0280b9d2fbc2244cbbac005f3700ba.npy +04074963-c99bbef1b2c514a81b22d29e47ec3f2.npy +03001627-108238b535eb293cd79b19c7c4f0e293.npy +04379243-2ef899e67eecef65190a91fd9a6f7d55.npy +03325088-4d8b953c08a287c26eb5b970490a0d07.npy +04530566-a8f225774d1bc8d0b7002bddf0942f8e.npy +02747177-a2e813b6032aa494a1b95b258b5f7139.npy +03001627-815f436a40c28da51f56aa11cd5e0c3e.npy +04379243-ec0d4fc8d4c29e7a7ff6ace05b36a5.npy +03797390-387b695db51190d3be276203d0b1a33f.npy +02876657-5e896bc124bc0af9fd590443d27a974e.npy +03691459-16a8c851009d6786887e8faf8f33b0c5.npy +03636649-3397952c22be7309796c584ff1fcf56d.npy +04256520-ee63182f95899a7419fb4103277a6b93.npy +02958343-dce6f59b6ab987d4bc863bdef4e7bdac.npy +02933112-5b112266c93a711b824662341ce2b233.npy +03001627-61f71cc002f6da561c81652b127a0ec9.npy +03001627-9c700bfbe8730e6db8f4af915220b65b.npy +04256520-34fe095ab6fbf3a09c0b027ae5b223d6.npy +03001627-79ef569979791f136f10b4c199f4a16d.npy +04379243-82b5a7823990ff0f48964aae007fabd0.npy +03325088-f6b1ca2df0be11bdb362845c6edb57fc.npy +03593526-b362273df5596c7e7f095f36ba0999f4.npy +04256520-32b6c232154f2f35550644042dd119da.npy +03790512-a9399a50fcb25209429f1c522640e6f0.npy +03001627-41fd861b4f4b8baf3adc3470b30138f3.npy +03001627-9a35f15e924e19db637adadafee6f182.npy +02933112-18d94e539b0ed30d105e720ebc569399.npy +04530566-1d8b27e78b2f326480d90033321f5c09.npy +02691156-6db040a8d5c1d5c14d210d9468aedaf2.npy +04256520-fd4285c2c5050ff7e8bb25231731c25d.npy +03761084-4b896032652578d8b5d95a89c22ce403.npy +04379243-8db7935008158509b55b46d261fe0021.npy +04090263-a8eae38e77cabdbd873aebd175ac6f11.npy +03001627-326a0c5116e410cfe6c1a071a4e8216c.npy +02958343-188621bbfc7d9477ce27281f3b76d1f5.npy +04379243-81271aca364735e4e6c5cd45aa112726.npy +03636649-b11c3bda15930ee7bba5aaac798c64af.npy +03467517-93519f396ef3cb23a00521ba9447845b.npy +04090263-eb6e7e6241c20448a3fb48700889ab3a.npy +04379243-6e8d22c6e069b71965b77a565916c7f.npy +04379243-86745eb914ded54c4ddda47ee90d6a21.npy +04530566-c2d6e8710215b74c82689dfa8a7d7e7f.npy +03001627-8cfc69d79fca89223a4a5c95fa1b0032.npy +03636649-893d9bdf1d7efe71bb5bd941c6665c21.npy +04530566-698f399e6c578386b64d3e1832079349.npy +04379243-aca97b802b08e220ee36f204dec02883.npy +04379243-575ac593154b95b6dae7645f889ddcf0.npy +03797390-a3cd44bbd3ba5b019a4cbf5d3b79df06.npy +04530566-29bff2fc529f82d676051c4eae3f0a9.npy +03001627-b2c838917b9f0fb68a40e1421d6a3cbf.npy +03001627-af28dbdce6ed8cea19fb4103277a6b93.npy +04379243-608af07bd357d605f155d75bbf62b80.npy +03513137-13f607a462bd1ea83b13741399690655.npy +04379243-e8689b8b1610bf2841bb8a7ba579a58.npy +04379243-a5d6b025b4c7239df1c7a32d97b27a4f.npy +04256520-aec403bcd87487b5b3aef1eb2166205f.npy +04379243-62d51d3d505aec1e5ca3dca3292dd1f.npy +02924116-35b752db6bccf0be5f0b5ee0fb357b4c.npy +03797390-fd1f9e8add1fcbd123c841f9d5051936.npy +03261776-a5a29c03bca0ff22908c261630fec33.npy +04379243-96b17bfa556f57e29d2be74cfb51ade1.npy +03001627-d487d3b9579762cb5dd170fd3a296ebf.npy +04379243-8dd8370dcaa8d770ea5682a3b818969a.npy +04379243-44bc2b9ceba25f8555f46d55537192b6.npy +04225987-97a1800db9a625bc28044fe9244db50a.npy +02933112-283bf988df376b9786ac7f2dceaa530.npy +03001627-4527cc19d2f09853a718067b9ac932e1.npy +04256520-9b73921863beef532d1fcd5297483645.npy +04256520-7d6453e00288991c61bf0ba277ea473b.npy +03001627-a564c8a43f6a7ba5199f2eca998ded6d.npy +04379243-3e6e16cc5a4f26da30bbd4cddd04c77b.npy +02946921-baaa4b9538caa7f06e20028ed3cb196e.npy +02924116-e0b2e30ffdabf5d4473f10e6caaeca56.npy +03001627-5c2b9c31cf63b0b93724abdc4106b950.npy +03046257-4e5b4341af6bd97368baccb6cef7077.npy +03467517-a42d7ee49607640176d05024fabfa1e5.npy +02691156-320e639572e8b9ceca504cdc40c452de.npy +03636649-a9d554c5d9d09405fcb8d8c6d4df8143.npy +03001627-81628a0b5f7f9ad7ba94feecf6f7a200.npy +03001627-efa83c67ce47bfca304edcf7c4314468.npy +04256520-224ccf9ba2b786d953353c404519f02f.npy +04379243-283e6da77ada4d65d42225b7548c8765.npy +04530566-89f52a2a136ce55728ba119bc0e1c878.npy +03636649-611f9690f6eb4da79a6a8a8f3fa61f11.npy +03636649-3ab3e07e432b0afb6b1c0c9b30aea3d.npy +02924116-ee8d5ded331cfb76c0100ca2e1097f90.npy +02828884-7ecd49fc95f8eafaf4fb4dee5181bee.npy +02691156-ad546b049b2246bd609e2d916fa0da27.npy +03001627-58620941b03e46b6e718b2093cc8d7b1.npy +03211117-8ce9fa1075039c8c63f4b01b3d592bed.npy +04379243-eed2fa156d662c79b26e384cea2f274e.npy +04530566-a8976b06101853deb4d272023dce0149.npy +02958343-e624da8cd22f6d289bc0c5b67eaafbc.npy +04530566-ec779915957e5361ce000b0a5d25ebdd.npy +03636649-53af1ea051d78e799904d527fb5485ad.npy +02924116-152d5e60eb9c72abbab671af2c92e476.npy +03325088-77c6367c2d0b0c9e29d75ea275a1cb4e.npy +04530566-65f78142a6c33a89ea7dce1646d86149.npy +04379243-9e42bbdbfe36680391e4d6c585a697a.npy +04530566-5aaec5938224841f36cf5f476d32636f.npy +03001627-8b0174afa05ed3c2dcadbd99efe6967.npy +04379243-5237a2e80c68f90abf7421909bb3502.npy +03636649-3b64d5033c580d2ef76898f881b76a.npy +02828884-ca04a1b1ff6701f8ad5067eac75a07f7.npy +04090263-e27f87039008855a341b8a806253912c.npy +02691156-af73d05ac86369bf4ce863ea27e2b897.npy +02691156-68c61d42222863682296d88107d065f6.npy +02958343-7015c7c8ee74f69313ded1857c15b5b6.npy +02691156-e0385af10bddc6a0ca8607f540cc62ba.npy +03636649-d52bcf6a2c75ced5fcb8d8c6d4df8143.npy +02808440-5c06133aac3e8fab3321831d2245cf06.npy +03085013-72d5aad0fbca8996ef04aec0d9ffcd31.npy +03624134-b5090018439903e0202be79d8b285c1e.npy +03691459-ea7d44b28bd22258f5ec01c1dd7b80e.npy +02933112-4dc45b86bdce7d96d37a1bae74ee50a2.npy +03001627-78bb9f39d4251624a502e035aafd3af8.npy +03261776-5acf58974a81ba7ea7b482715d4b6103.npy +04401088-996fd7ccc0567c3c6b2ba76eab0d2b1c.npy +03001627-7d1a9d6a3297ab853e02e5116c35dcd3.npy +03467517-853a5832f15461c9e8f705eb96ba3376.npy +03001627-c47bcffe3e74391af3c9c1464e55d580.npy +02808440-200c5297948bf57f6b448b8aaebb705c.npy +04379243-b8425a23b0525ccf004563556ddb36.npy +02871439-84fcc00a222163cd2f353d2ea8863d32.npy +02691156-bd8c9f9442124cab5e64c90e34fc13b8.npy +03001627-7f73cc6c1c9121a9b9f2eb77f5e247e.npy +02818832-970fff8bef63e40bb138abea28057850.npy +04530566-3a4c31888d291859f8e1db0ba8b72d09.npy +03001627-2c4719f6aa7b2c8a5a9f35e635b7e48b.npy +02954340-a0fc32a763b57b85f0d11ae402ef940e.npy +03991062-f2aa612d6ab76bc1a2c59a4d90e63212.npy +03636649-5f9edd0b9cdc77ded49b2e04785f8492.npy +04256520-4180d98246089cf014038d588fd1342f.npy +03938244-4c617e5be0596ee2685998681d42efb8.npy +02691156-1659db64bbf46bcdc1955ee4b5680e91.npy +04379243-aa41c42a9a79070de4a490bdf2c3ee62.npy +03691459-f4290921bda21901caf9cf929ed6f71c.npy +03001627-d0c6af0d44cc068523c1b1df1d480bd3.npy +03001627-7309610420ae20c930ddb6ead95f49cc.npy +02691156-cabce3320f119855a5131d38588a62b.npy +04530566-daa1781b81a74852bddd6eea3463dff0.npy +03790512-2c6e2d1e743b93b67f44d6925c8a069.npy +02691156-9c7268dd8ec3a3bb590874dcd9dc8481.npy +04379243-66378f0a068a111e57211f5bbbd90b35.npy +02958343-3134927c492c39e241d7734b73edc062.npy +04379243-e1d7b48449559549303c85804d402599.npy +03046257-3699e4ac78eb732866a92e3fe9fdc71d.npy +02924116-ea80f7a2a3b97d2e8f3f2979f302c57.npy +03001627-8eb33e21e03b8f84db039d8689a74349.npy +03046257-15cccdfb473dae1799f30106e678cab1.npy +04379243-6c2e919b70c335f240ef1c8b63a628f9.npy +03636649-c961e64a930680bb900a91cbf836390b.npy +03593526-244399287185e74d8ca4aeb5e3b33af7.npy +03337140-94453745e0faafe2fd938442e7c3fbc3.npy +03636649-748e643d7982fab3fbdebca9f6788597.npy +04530566-522614512d74a2f8c5f391634c2a5ade.npy +03325088-990ca49fe2a40eee5c19b45944d27e3b.npy +04530566-64ceb6b8d122c2b3c9b5311300e82c12.npy +02691156-e0df54a0990000035dde10d3d9d6a06.npy +04225987-563569e15313d7eb89e13811ad04f53f.npy +03691459-f57c5e8f460e659f395ea88528a634f.npy +02691156-2d01483c696c0a1688be2a30dd556a09.npy +04090263-37cc0262192286c2e4235a2d12e58a2.npy +03211117-87b093f1fa5495968cb623bbd4140197.npy +03636649-b36bfbbc98cb45431735ea0e092a805a.npy +04379243-f1323a66816293be29ae2bc03882456f.npy +02958343-109567d7d55b8fe515a520abec2f04dd.npy +02691156-d1119217281b8475fe755e3418b63110.npy +02818832-a224f207c639eeaf8d704b7b9cbe87.npy +04090263-58613784e5ff705aa74a2c673ce55a44.npy +02958343-d2776550e240c0d642fb51f57882f419.npy +04379243-af71e4dcd477656f9cd431573238602d.npy +04379243-aa615f385b320782eb57f2e4f0583f2c.npy +04379243-8abb8d75987c92144417a5312cf9d851.npy +02958343-90917495a9603208c368040825ed335.npy +03593526-c7bb8b9685f0378307f509cdf07ef62.npy +03207941-6e5bf008a9259e95fa80fb391ee7ccee.npy +04090263-734c46fe71b6021416b34c3751bc447d.npy +03636649-72bc0272ab1ce5a3f8d6a4359d6a181b.npy +04379243-706dbdfc48b19b0f423f1f7d60608f89.npy +04256520-8d69121ec9f174cb4db79ead79f57b22.npy +03001627-2db6c88145049555e6c5cd45aa112726.npy +04530566-da4003977c998e81f74f6fb7142d37cb.npy +04379243-2e5ac0552fa296c43bbab77a66bc3671.npy +03211117-f1d77e0f4a2adc2bb305a938e0ed1b48.npy +02691156-800ce26e517769dcb87697d3904b168b.npy +04379243-9ee005b0d0cf88a0e7e684d25d4dcaf0.npy +03636649-379b2a19deff9954f51f77a6d7299806.npy +04379243-fd09a960ef86fecfc515407725a6e525.npy +02958343-a89dd60aadccd84be04e0c24d5a9d818.npy +02818832-ba1eaf2862426015b345c23c11c95b7a.npy +04460130-149f13db5c358ecfde1c31612629d3dc.npy +04256520-2e1563209d3318b2d544b90b3a170602.npy +02958343-841d9f6bbe50ec6f122568beab222093.npy +02958343-9752827fb7788c2d5c893a899536502e.npy +03636649-f3a9cc3060fd6b0e6e4f8fc909e0d34e.npy +04379243-2486659a274a6400ff07dc9cc50c993b.npy +02933112-5f2f90d83db6bcafe7e684d25d4dcaf0.npy +02933112-3d2870c83ad35dfe86d53ab0fe94e911.npy +02691156-3029b9f2174da4b0bbf3143b1cb6076a.npy +03624134-e2cd287563f26e3eef1f81f15fbe736c.npy +03797390-f99e19b8c4a729353deb88581ea8417a.npy +04530566-6b2fb8cbc5365f5c8cfe472915a175bb.npy +02992529-3dd3ed204c56943389e13811ad04f53f.npy +03467517-22760e2b45e67d724d88968940783b69.npy +04090263-47d871d9a3b5553cff790997f2048517.npy +02924116-800d1ff96ae2af8059a2046f98794106.npy +03046257-3b19d7b7f975a08abffc4b354a59e33a.npy +03001627-ff034050f7ca727ea64c9c407ff9dbfa.npy +03593526-e15fc6c148793ebca6508ea9c3850f4c.npy +02691156-fe82a9934a38997866cf1b4a8fc3914e.npy +02691156-d8a037897d5d5b108130971b27e95927.npy +02958343-77d884ef56bc97a8b7ddd670a53fb311.npy +03636649-405e760fb406d96c2cd3f16bd931920d.npy +03467517-7701180906a0aa156a7ae841f1f88f87.npy +03001627-4e3cc3f6d2c25b904addf6a5f8726274.npy +02958343-e9bdc6c0a9e4675bbecf71e2e014ff6f.npy +03467517-9943ae38cd844c91082f2ea630bf69e.npy +03001627-bace9433ae54fcb3290d57214c8512a4.npy +04379243-fad834ac9ebf8d5595b7b91db37ae400.npy +04256520-bd98ff55306cdd592c509b30860f3d1f.npy +03593526-7037b6266188af53197a35146ee825cd.npy +04379243-55547d2fae0e3dc21705bfd3afcd10e.npy +03211117-252640ae350a1e53f119712971a6882c.npy +04379243-ed6e26db873ded9573e85324169605dc.npy +03211117-25a09a149d018bdcaa95bf474e195f02.npy +04379243-1011e1c9812b84d2a9ed7bb5b55809f8.npy +02691156-688930b9d0e06ead9a6e43b878d5b335.npy +04379243-29b57f226644c696e921ee447a9e7b42.npy +02958343-6fcd4ab4d968a975715e04edb8af9c53.npy +02808440-cf9814ecd52f9dcafe52ffd0e748a1ab.npy +03636649-a0858fbc08ec5e34e7e684d25d4dcaf0.npy +02691156-c6d39a3c52f8beaf7f6c3adc89eef8e6.npy +03642806-10f18b49ae496b0109eaabd919821b8.npy +03636649-b2f18bebf6566bcc97554b6bd947feea.npy +02691156-a8773829298f492cbcb9a99298d16322.npy +03467517-a7ddf2e5b9dc278293f0194265a9746c.npy +04401088-9d021614c39c53dabee972a203aaf80.npy +04090263-14fa15f31d713b7153b838b6058a8d95.npy +02808440-28f7f68307ad843944221bef0fa3c36b.npy +02828884-107eb4f1731b2466780bc2708a85ba9a.npy +04379243-a83bee7cfe190a1dc26fa198e521610a.npy +03001627-7710ecf956701938b40f0ac0fb9a650d.npy +04530566-812c1a3dacdce93ab4b5d7d0cd89b504.npy +04379243-9c1b0058dfe027cbf519adc9991b5f11.npy +02808440-fbbe1f77590ae6771a3b39b07e4b3d0f.npy +03001627-a1dbdff3da83425f3eec26c23f5bc80b.npy +03001627-72bc27a22e5f516e8aee1b6cfa0c3234.npy +04090263-a3c96f18e2aaf2efcdd76170a7089b09.npy +03046257-9f51f591d698445a5fa2d7ce8c99e4e6.npy +04004475-f8bc97b503ea024c4fb4be49c5910c7.npy +03642806-bb33d26f324d19d94845e0946708405d.npy +04256520-26caab5f69ebc9693eec26c23f5bc80b.npy +02954340-3dec0d851cba045fbf444790f25ea3db.npy +03636649-86d556273aa5075aaa660c42e675c161.npy +02808440-a3fb3caf38b63d06ccd0340812259a39.npy +02691156-1f672d2fd5e3f4e78026abe712c1ab05.npy +04379243-fc7d921df59e86e6beedb4c8fd29e2d1.npy +03513137-30c9fc79edc88adf438fdee28ab485d3.npy +03710193-580f93299ad002c2949ea1574c63d947.npy +04090263-52102b24df4b0e09fe75cc28d6fccb4e.npy +02691156-d7f3d0503ee4ee1cc34b900bb2492e.npy +04379243-8d5dafee7c2e89aa4cbf9a02e3342127.npy +02958343-2cc4573bb9441493d12568d09c2fba02.npy +03001627-e0154380de563d2cd81aa8b56a36ec8.npy +02933112-1b6e680e76d452a097144612c70a9099.npy +03001627-f5fdaff0ac02f106e8f8c11a24c52ebb.npy +02880940-e16e27d3670853b12d4e6b2984840098.npy +02691156-f71028dac9b396fe80288501d9901d7b.npy +03467517-4110ce992cd45b83d3270fc46b08e35e.npy +04256520-c9276f00529396bb35836c728d324152.npy +04225987-7a8b7d5d288742546fee3d712d650ac2.npy +02808440-e5a1ff704398c55ede9471c962dd6ba.npy +03691459-4e06e2b59a83bb6229cd1f0bcc30f82c.npy +04401088-6a0c0c55f355cc23a0eb5a85db887292.npy +02880940-1fbb9f70d081630e638b4be15b07b442.npy +04379243-a86969194537bd5a3a602af85160c9b5.npy +03211117-c356866299f4451cd3563af8dc07cd64.npy +03691459-192fd6e662d89b62dbf53b03c847b004.npy +03928116-bd586b69c27f05c8fcb3c6c0ffedec6.npy +03001627-9b8c50f5b9e67dec35836c728d324152.npy +04401088-81ad8af206d6b21b89b367279b017ccc.npy +04379243-1482036d8ce3b51ffc0035da39bd5e1.npy +02691156-14161a05a21cbd6f62b600da24e0965.npy +02871439-777785bf709e10ccffba1ef7a9b50ff2.npy +04379243-db2d4f781756e687d8864caa856253b.npy +04090263-ed9e0161c72f98d5def607f4d4140edc.npy +02992529-cfc5fce3c76610e3634fff5505144a5.npy +02691156-2a06adfb446c85c9f9d3f977c7090b2a.npy +03691459-e66e2202b11cb7122d563c85edb49108.npy +02958343-d28d00d6488ad1a78079d5a13e411210.npy +04530566-2fe634902b6ba945b4e4ece897f04daa.npy +03593526-41391118c374e765ff3ef8f363b2cc43.npy +03001627-5510d5af1ab5714b3c42e318f3affc.npy +02958343-dda0d7e01642f399d4118745f38eac76.npy +03691459-d8f6aaa777f0cd4f5a31d91ec836a511.npy +03001627-88cb38c612cf60dfab50b8ae6c38666.npy +04090263-d254cbd6f2e319ced348fc2382f06377.npy +03211117-64f6ac23636c5c2c8a17805dbfb751e2.npy +03636649-6c4c45af95f811e479414e04132a8bef.npy +02958343-b790d70257a8191a29984c4afd2e98a4.npy +03642806-5eefc8f2d755c843614c1d5b48350fb.npy +04256520-1476ee6116538beb1d0e6f3a33226a84.npy +04530566-80439bf303734b76ff37346ffc41ec74.npy +03636649-7f5bc32085dfbbb88e7662971dc736f.npy +03337140-16345185248d057d2b352e2703063a3.npy +04379243-8497e2cce58a0ab46827eb366939da8b.npy +04090263-f5a561a38af6b829b3066d9a2ba0c7c3.npy +02876657-8cf1cc180de4ecd0a826d25a0acb0476.npy +02958343-da92c8d35fabe4093a67185d75524e9c.npy +04379243-a1c04a11d0e20691fa3982b18d6e7664.npy +04379243-f58e58ad9952e174d058858de40fec33.npy +04379243-7f2d4ff98dec893094210977e5394f26.npy +02933112-a6565be9e3fb8e1095bea7c29e873d16.npy +04256520-4106b3d95b6dc95caacb7aee27fab780.npy +02691156-65278860c7d0f3704f59c2a67aa8473b.npy +03001627-1e276a016b664e424d678187b8261d95.npy +02942699-15e72ce7a8a328d1fd9cfa6c7f5305bc.npy +03325088-f403e37ca7831479b362845c6edb57fc.npy +04379243-1c38f1631efaf9fbaccd05bb6a369505.npy +02818832-1619aa637cbb6e131ba2f806cba87b47.npy +04256520-9500ae0f745fc9efe5b815c86e529aab.npy +04530566-ecbfa1faba336185bc33bb3e21836dd7.npy +03001627-e425c1db44d1ec8ac73ddf48fc777dc.npy +04468005-bd06d7b322a2c65147367565b9fdaec5.npy +04256520-38fd2710b8fd5eceeffcc073d8ec38f6.npy +04379243-a65dd1088e44917b93edb2fe34609efb.npy +03636649-c99eaaeb9b941af62ebeb1e6a8111f53.npy +04379243-2889aae96f0b236e27790b0ec8671f7.npy +03211117-decec5d8e1f9f54e1a5295d0078b5d60.npy +02992529-953a952a18e389e4eb386a4e845c05f5.npy +03001627-a5a5d118118eb760fee31d33418a3c16.npy +03001627-c1e03281b9f179c7620365f6656fe3.npy +02876657-542223f09a872e973858be97087c26ec.npy +02808440-b3af478264146f6ad9b53420a5458c53.npy +02691156-cc6041868bf2913312b981fe5abe4a07.npy +04379243-11ff78cc42de92ca597976c675750537.npy +03593526-3a6e1c3f0755d58d774ba10f0bcc178a.npy +02958343-f2b28cd6e6eaa9679393793f9cf3dbea.npy +02933112-7aac04fa0361f0da2f8bc0d6e7c6775.npy +02958343-5057c9dbf72e0352728fa2df514c65d4.npy +02691156-43ddfbedbd6721fa828204947d78b9af.npy +03636649-bfd36d77ecdb0c9de76bc197b3a3ffc0.npy +03691459-88842eadd96e5cab570b6bda9783c8ba.npy +04256520-81018f492277b7649f13e3294f6a3574.npy +03001627-b3e4c494a862986b9226550f5173ae53.npy +03467517-f3500593f65d37e5817f6c88302b2a8d.npy +04225987-98222a1e5f59f2098745e78dbc45802e.npy +02958343-8aa9a549372e44143765ee7ffdfef49f.npy +02958343-687253f72301b508c9c0a46cc4ca6589.npy +03001627-46c6d2fb8c92cba419fb4103277a6b93.npy +04379243-be06e77602ee4d089c0ca344f487323e.npy +02958343-4e9a489d830e285b59139efcde1fedcb.npy +03928116-7ab2295c441170a967aad4e7f685c416.npy +03790512-88950eedce83a11ad4fea43a014cf734.npy +04090263-65aab903355c7abeb4cdad9a5bf52dd5.npy +04090263-54b68b9a4c40e86b3da3f9c40ebeed54.npy +04256520-899a328f7c0292c5998b2b87439f61bf.npy +02933112-1b212b67e5eb90f4da5feafe6f1c8fc.npy +04530566-7a9ad733a68b93bbb1bb46d2556ba67d.npy +03001627-44c25bfcff4a4a4e4dea158f05aae320.npy +03593526-569b55cfce8c4d15b136b011ae1ece0c.npy +04090263-191f8debadb867fbc24d00518a3dd6ec.npy +04401088-e11ff7bea65e8545c3f912172873d52f.npy +03001627-a7aafe44f64dd04dfc6afbc561d74a4e.npy +04401088-c5188dbebddbad3597cfb99c9c9efbb5.npy +02691156-5e124107cb94b90218ad244e2cb2c6cb.npy +04379243-c7d36b8a4b79f89dc963b248f3fa9d25.npy +04530566-bffc229892a3d301c8bb4876165f947c.npy +03928116-479f9b6c9cbdea649a957a60b2bcc479.npy +02828884-b9eb4b3d3ed564142427332fd13e1534.npy +03642806-d8ef2a8a3ccff3fa5cad2ceae48f2da5.npy +03948459-800cf19b2f7ce07e1ee14c0944aebb52.npy +03001627-cd9812c163ddfb3e83bcab979449e28e.npy +04401088-4dfc1e4efd7fbf083cdba96133f0c38f.npy +03001627-f4a36a5ae5a596942d19175e7d19b7cb.npy +04379243-89142ab0273740f221bdbc0445d9f748.npy +03467517-ee7d5c8cd074b18992eedbdd14b936d.npy +03691459-c2024c0fa0906fc724abfaa350249967.npy +02691156-ade0163327c8c7f5847335355bf4459e.npy +04256520-7e550e32d80421aa19fb4103277a6b93.npy +04256520-1e678fabd0622a1119fb4103277a6b93.npy +03001627-d7ba3ad07551c886a2c9d2062eb4aba4.npy +02992529-759c984fa6831ad7bf0defeaa770e93b.npy +02880940-f44387d8cb8d2e4ebaedc225f2279ecf.npy +02958343-5130947e5f18e73a8321b7d65a99d2a.npy +02801938-7b407dedd933e3812f59b845f0db2ab3.npy +02958343-f374adc8c35b9a0b3eb5f91920765edb.npy +02992529-9dc1088c4f5de29ac78df40cf2e9097a.npy +02808440-40d7753fce9bec3c3321831d2245cf06.npy +04004475-83b080e6ea2a46242974cfd5336a9b09.npy +02876657-8707d78855e8cce1ed51290fb4dc2857.npy +03624134-5aaec976445f88662b994aa4e028ede1.npy +03642806-24721e62300a3c4f98be7382d7a678c3.npy +02808440-3e2b33cffce8fc632dda19453ee07c6b.npy +04256520-8258954eb7929aa13542091189dc62b5.npy +03211117-c0c1c344c3bcea10c0a5099af057718f.npy +02924116-2f77c7fc777f8b11665c5daec82c51b2.npy +04090263-60efcea872fa7e52341b8a806253912c.npy +04379243-5aa1db3eb76c53aeb660da28fa2f03da.npy +04530566-3e5147f0fcca2ed7c2920de4c5efc2ee.npy +04256520-de91f9457052646eb658faecaae06eb0.npy +04379243-307bdd2a06137694a10ff7fd5e43a633.npy +02691156-d2815b419e61dbb0b87697d3904b168b.npy +04256520-526b961864b9cb0ca81116f5456ee312.npy +02691156-5cd68dfe309e1f8317e5bbee411fa5d0.npy +02924116-7031bbf89b4c551b66cdb417aa9cef4a.npy +02958343-67a3dfa9fb2d1f2bbda733a39f84326d.npy +02691156-ab399dca637174fb9a4a28ef635593ce.npy +03636649-18ed152bad2c123b4b3c42e318f3affc.npy +02958343-1399eab8ad7262eb7f3efc94c2d31dc5.npy +03636649-65f23d07991128e3fbb8cbddab1c2002.npy +04468005-f12ab466f3c74189b1112c737944f1b6.npy +03467517-e45f323ce7ecab8393f0194265a9746c.npy +04379243-3fa4ca95ea2c3d4649a734174fea032e.npy +03001627-75b1bcb68c8344261a648655355dc699.npy +03593526-d5ffa68a7be137ab157d60b585b8fb6e.npy +03211117-52387a90d9aa2fb019945cdf27c7de1b.npy +04256520-4fbadccbdd689b18b8708912bd92e115.npy +04379243-e8632c8830944cfe422be95e44ce930.npy +02691156-3a7e89dc355faac111f5789deac2dcac.npy +04379243-8e66fc32d49732c4eff311703ed2e9b.npy +03636649-2cba43cc26f174a8f9a65dcd8ee605f.npy +02808440-42d7c051c1e771ba3956bf2322987dd4.npy +04099429-beec19e75ba3999a46f4fa69a8f7f711.npy +03001627-c31a206ddb92909e84f0c4075db76b7c.npy +02992529-504c453471faee3ee304974abc9afad9.npy +02958343-45186c083231f2207b5338996083748c.npy +03636649-27910c314eadb1109998b4eb812699dd.npy +02992529-937b3450c8976f3393078ad6013586e7.npy +04379243-1e3871159daf135370bc652a18e29c3d.npy +02808440-8634d5d3fbd559c8c49077a31b9f504a.npy +03636649-4242398ccded25abd3ba76930e17ffc8.npy +02691156-82a472004d00b288b4d569aa61960548.npy +02924116-5b04b836924fe955dab8f5f5224d1d8a.npy +03636649-1e0bf9701623f02014038d588fd1342f.npy +04401088-b87251d1d4f4b7ab2c216c5e0f221195.npy +02954340-6c607b6b3d6fc1cdf0d11ae402ef940e.npy +03325088-270123ec327ec824c36fb70296e45483.npy +02958343-7f2b01a53684e72154b49557f8ea8b42.npy +04256520-9c0c2110a58e15febc48810968735439.npy +04530566-fcb92e30085a580d9c6645849b3b7d65.npy +02828884-7c335945340c674cefacb264ebf1ec75.npy +03636649-f46d1e234c05fa4e62635f8519c19a80.npy +03593526-e51ccd45d54c9f4225e65d4b5f3b6456.npy +04530566-397f37249263000990960087ed86644.npy +02691156-c14ffb40a37074ed26360e1e29a956c7.npy +02958343-e2d98e5fa33b5b0daf8a2e210ebd5168.npy +02808440-686dd1bdc574ebd152b20f433bf30081.npy +02691156-7feab568d879270dd8d90babf3c5509a.npy +02808440-ceba3a37ceb3f3cf798df87163b1956c.npy +04401088-b8555009f82af5da8c3645155d02fccc.npy +03001627-6015aaa9ef170d9bfdef1c01cbd4ae0c.npy +03797390-daee5cf285b8d210eeb8d422649e5f2b.npy +02691156-e08574959d2cb7c8f6cabb305f7d6d18.npy +03001627-c0c823f094d972c94b3c42e318f3affc.npy +03948459-d76b953813ea5024dd3adf3090c701f7.npy +03636649-24927157e3a53c1f91cb6b6c47a03f13.npy +03001627-1e7bc7fd20c61944f51f77a6d7299806.npy +02933112-70eddd0ddf5c9ba21c1b3b2ed8d13bf8.npy +03001627-a81795209ce65006ee0f4a6e5ea1d8c.npy +04379243-901eb5d8bab4bbe48fe31aea3727611.npy +02958343-572edac8bce600c56f2b832ee4c8c232.npy +04256520-b5b77de7a8a05ab4f09df371fae9d63d.npy +04379243-28fb3bc8ab9f518035836c728d324152.npy +04379243-51d196f6b12a84ddac594abb03ff6297.npy +02958343-abbd90920a240df2ed3696d854eee1ec.npy +03790512-acd49452b452cf2f3ab3dfa44f5fab01.npy +03593526-595e22f425839eac2d4b0854f7611ed6.npy +04379243-e9a38d17361a5f20af268f6180933aa3.npy +04090263-e42d10c193cce254719aed4531d5366b.npy +03467517-b6d2d35747549a5b93f0194265a9746c.npy +03001627-475cf49d3764f04ecc8bd7a04c9659f1.npy +04256520-b1db7a545796dfedce59ea70152320fa.npy +04256520-2358a67773472af0826fc8d57346a2e4.npy +03691459-3187862d922b0ce96583871b5c274818.npy +04256520-c40adbdd817cdb7a14038d588fd1342f.npy +02691156-e5c98b67c146cd61e816c75152573ee0.npy +03691459-945805d18c0de73ae3e30e20ce3a5bf5.npy +02691156-a80a6ec94928f7dfe87d0cb113e517d2.npy +02828884-6b47fc9f533618719c8ccc4e539799af.npy +02958343-2696ef55dc264b8cbba9b483d5f3874e.npy +03991062-1b10d9cfe0211e8dd31520fd3c5602c7.npy +02691156-645b2bf682e865ab9a6e43b878d5b335.npy +03211117-ff2664a07ecb6edceacb155f400b9076.npy +02828884-46b3e857b7faab0117f92404d4be5d8.npy +02958343-21205bdb7ca9be1d977e464a4b82757d.npy +04379243-ee43ed656acaf774f4b6538438a0b930.npy +04379243-7ef03c6cfa3621f8ae46e333ff78e5b2.npy +02933112-21ffe8bb21951feb5c8adc541f88498.npy +04530566-a49537b465965537fe3128d27fad4d2.npy +04530566-3750fdd9ef7f941d2173755309fd0db7.npy +02691156-2b0a2bb1556c96b94f762cd8ae1b1c4b.npy +04379243-121a3040c28295829e4b5aa807bb4e7.npy +02933112-25d7aeb2970030371733347bc72de5f9.npy +02933112-4d690cd9d3b41f46ce5d6e9371bb5c33.npy +03001627-26908ca3183b5a4223500a5b036df62e.npy +03211117-31512a50c12258726ca2b6e5474aad11.npy +02933112-169d64acd930adb12871cc0b3cc1a485.npy +02958343-ae9b244f9bee122ba35db63c2ad6fc71.npy +04379243-3a85ef469535f0542cc8fcd230a7f687.npy +03001627-2d8f0977b9c6592ffebad4f49b26ec52.npy +02871439-4b9c35238db89e93464280042b597d.npy +02691156-45a4ec99ed13ed773c2498c4c2f13ca.npy +04256520-f8ccc92a6a5d20875eea3e3d89293379.npy +04530566-31a41e6a73c5d019efffdb45d12d0585.npy +02818832-642a38b553a520c03f7f3ed2c3c690fe.npy +03001627-2b70fe0b5669985c100bd20b85b3554.npy +04530566-65b75158bb049f5af647317afa6ffdd4.npy +04090263-fd2435673c53179dd1a62290a53cce98.npy +02933112-5edc6766196953a28f62bdf4e9082924.npy +04530566-f91e712b124915514b6c44ccda750d2e.npy +02691156-a39880327ac8815e62b600da24e0965.npy +04090263-465746159129abc7c0d38eeb2893c7a.npy +02924116-317907b3d4830c6db7e4d3ed6e9e6394.npy +02828884-84e0619bd80f5455880e561fa6db53d8.npy +03001627-46743849f0b01b1ca72559fc4f86f700.npy +02992529-128bb46234d7250721844676433a0aca.npy +03001627-c04c5b7d68b4e6481a68dda91fe5259.npy +04379243-bbdc08f4f00c484f310af74324aae27f.npy +03001627-95d082c78ea0b1befe52ffd0e748a1ab.npy +03325088-7832af11012adbe7b229726a165222c0.npy +02992529-313e9b124e421a4efa9922db9b6aab31.npy +04090263-7bb85cdfb1794a5712b38b1d99376c0b.npy +02828884-1f239e55de52bb63eefaf3e79e3e3454.npy +03991062-67bc9bec05f78850f9e08161aea27d2f.npy +02691156-e1be99a614c85c3e2016648502c798bf.npy +03001627-e9c99b6af129c22cf91663a74ccd2338.npy +02808440-f8d0cc0680f502e98eb3bc6c6d15f9bf.npy +04379243-b878329d1c965d195f9efc5cadcb44d7.npy +04530566-7ee49cd8ad72bfd2c620cf302459a7d3.npy +04256520-eaff5688bb49f845ba41eea807f5d3c.npy +04379243-c3135e3b21b42e132449009b96f8a6ed.npy +04256520-e5b0d8cabce54f524b3c42e318f3affc.npy +02942699-6d036fd1c70e5a5849493d905c02fa86.npy +02958343-3bd66fc2782bd2019766e05e7d6c9088.npy +02958343-e128a506f2e29a6796cceb824e3c56b0.npy +02958343-ef77d2e622786026d32bfc7a837f790.npy +03001627-8becb5888c900f3a610c2a68437007d6.npy +04256520-a3604a6631bdd53b593ebeeedbff73b.npy +03991062-3de068a04b96e3a3bc5996932c1238cd.npy +04379243-6d31e827bea8e970f198b94f669bca91.npy +02808440-7e8cc52fa74c26b4eb1f243bab39fb29.npy +04379243-6a613281bac861a49dbf2f762a644724.npy +03325088-1bc3c767ecc9323c3321831d2245cf06.npy +03001627-fc99c80f588bc88d5a6be9e325f087ce.npy +04379243-c76d9d9756b8bbf2a86b2405ab6de30d.npy +03001627-5a80c5a35dc1634db87028a4b477349f.npy +02808440-d51e086b0af8815d412deb0d2b0f3dcd.npy +04379243-4c7faca525777be32f7524c98ee0fc42.npy +03691459-23907d5a2bec2ba6ce029fab54b6cfbd.npy +04379243-9c4afb731e910d3723500a5b036df62e.npy +03636649-e7287ee25156053773ab7b7128d466a2.npy +04379243-28ce06aa6f25b39f2d19175e7d19b7cb.npy +04530566-1d6bcf04874000a9ea96bfd37cd8bdfb.npy +03001627-9225e57e34334ee019cb07ecb5b4102.npy +04256520-f20e7a860fca9179d57c8a5f8e280cfb.npy +03001627-e325f573905ff945b8183a4a81361b94.npy +02942699-e85debbd554525d198494085d68ad6a0.npy +03948459-d84c25bf4f0cb029537e3f6cd50ed63c.npy +04379243-accdf18e9eea0dc31191025061735ea3.npy +02958343-8c346443d2feeaf916abce8cb03e7794.npy +03636649-ddb951343304bf1f351d9ca36f76b95.npy +03001627-c8f5189b54fb3fcc6c518c577d808035.npy +04379243-7543553927036b0352b7768d51b257d9.npy +03001627-7d0e6a5c10d2f97c62e682c9809bff14.npy +04004475-a8c41f725d1dcb8ec8bb35fae3b41809.npy +03001627-4a9d3ce54c09a2da696b74614952b2d0.npy +04379243-d5402158d5fb9fa8c283ca2c9df7372d.npy +04379243-ef62dad7755794a47558b47f7ba0b0c.npy +03211117-f3004c5b38bbc0e445804144dab4dd66.npy +04530566-5a2bdc97e9d6683077f1d7a36adeef7b.npy +03325088-5068487242356027b362845c6edb57fc.npy +04379243-89975eeeb0a1313e4b3c42e318f3affc.npy +03001627-90d35ca55b35d56dd5883ca9b41ac387.npy +02992529-b1d1d6a5f46a30894884e1105772427c.npy +03001627-1c9d7e56ae8c90c87ac6ce513ae497d3.npy +03636649-e1c49baf0a79732a7eeca6709b6a824e.npy +03691459-11c1c970e9cae04183ef95920b2c145d.npy +04379243-978a4869d7fafca74b3c42e318f3affc.npy +03207941-687c09af50c2e5f5db2f7e7d8b44c8fa.npy +04379243-8af35280574ac141bf7ea2059cd7e422.npy +04379243-8f7d16c0303d8cf4593ebeeedbff73b.npy +02828884-5bb40ee2f4893358d4d8765e3910f617.npy +03636649-527212b174a5313fdd5616230e7f3c5c.npy +03642806-6b61ef17b4f45050b598e8984f11eb0c.npy +04379243-fe22668b577f0cbe88e99eda7bb1ee8e.npy +02958343-f2e433cab0ddc755ca3ba83abff10be.npy +03001627-d66fe5dc263064a2bc38fb3cb9934c71.npy +04379243-e3b585b15506fa7113f96345312df593.npy +02933112-36853ef4167300c86e5b9257c4084ca2.npy +02992529-4157af4a11fda8ebdd3d821abaa89276.npy +04379243-4e8d9f4bebd6a97670553da2430bcd98.npy +03642806-1ce688d90a2010a69718283200011d2a.npy +04379243-12c8ea55000707be8ea4cedb988ff461.npy +03691459-f88ff1c46ccace6d5392678120123c42.npy +02954340-dd2d95b294a7a8b4fa5b6212657ae4a4.npy +02828884-c97683ce5dcea25ad1d789f3b2120d0.npy +02933112-31de44d559904485f51f77a6d7299806.npy +04379243-f5d6579b3a1f5a879d2be74cfb51ade1.npy +04379243-79d5aff74dbfa0c2307557ffe40d48d7.npy +04090263-9c8e406a5e198529282dd3b430ec2654.npy +02691156-86c8e75179f00b725b7d3d0361fc611b.npy +02871439-bf961e64ff78bc7e664b3b9b23ddfcbc.npy +03928116-e963ffa0699ae9e45e244aa0433fda37.npy +04379243-92dccb2a3e6445d5c790d7efcdfb5239.npy +02992529-bd7b84ae3b88bd5cd2dd279a9538db3c.npy +04379243-586edb4eba5c3c7557ab4b593540354.npy +04379243-c827c0d4ef212f2b30cb1fe6fdc7d605.npy +02958343-355e2c8d8d10e8227541c0a826e78e18.npy +02924116-bb292224e499052641cefd10ce5d6cc0.npy +02691156-10af5de930178a161596c26b5af806fe.npy +04090263-5bb02bd49d2ce6e590b94f57d8818348.npy +03593526-1dde51480f0c5474a38859fd71bee28c.npy +04256520-48acfed2c1f2d42cbd16d4490a10a752.npy +02924116-a2859adca84473da892e7ae844e0da5.npy +03001627-19319101e064eb1019fb4103277a6b93.npy +03691459-c1ad8720fcc7246a1fb294203c64a4b3.npy +02691156-a726f95306ce6e1071616ead796bdece.npy +02942699-b22e56fdf18e2eb8968b65a7871de463.npy +03001627-ba9ce924d452795f519259b5fe9bdf5d.npy +03211117-7b0327ed7286487623ab4519e0263310.npy +04379243-87af702a9a5370aceea6a5a0ebf81e97.npy +02691156-75fd28838e0fc8cf5b1edf5d4f643136.npy +02828884-85ab526dead09ffd398e68bb81784a80.npy +03001627-8757370fa33bc4e9419786e9c37fabbe.npy +04379243-50c9d436169103249cd431573238602d.npy +04379243-74c3d551e32a1cca664b3b9b23ddfcbc.npy +02691156-5aca1a2ca9143638b129901f80d24b7b.npy +02691156-d353b227b279804190b1d6deb98feec6.npy +02691156-af6cf1d2b6c00b1233de69c9cd670995.npy +04256520-1bb6224360321002b8bd10c3418cc648.npy +04530566-5f7c0e4368784e795dbfbfcedb83d61.npy +02691156-521eab9363fdc2a07209009cfb89d4bd.npy +02958343-e5aae7748aac94086228d448ae07dd2b.npy +04090263-206b4a7aff5ae78ecf61781659594ce4.npy +02924116-dabf9de698fe00716464444786faa32c.npy +04379243-dc3a90ee32e36cad43dbb6421d614c0d.npy +02933112-4cede87a6ca6bb876a485daf2a997e28.npy +02924116-193572f57626a97c65e6a15e0a997e5c.npy +03001627-ef45086ec881cb657288e3849fb636ff.npy +04379243-45c5ee611c73b90a509330ce00eb0b20.npy +03938244-c13de90da6f6744736902d83e4cc385.npy +04256520-19b9fb3d3763cd1e4c4a4dca0a101f1c.npy +02691156-7fedb48b457ee9f31629b98cc1b1b992.npy +04090263-70871551850d47c2823acdd521e722d.npy +03001627-e9effe5159dc66673b93a3cd851adcaa.npy +04256520-2715a63f41552d6c19fb4103277a6b93.npy +03001627-ff8921eb06e95b9cfebad4f49b26ec52.npy +02958343-346917af7c9659e3814085552234c955.npy +02876657-f47cbefc9aa5b6a918431871c8e05789.npy +03001627-4c3f655507cc6aecdbe9c90af547c85d.npy +02828884-1b0463c11f3cc1b3601104cd2d998272.npy +02691156-8e2846178e2976fab96212c8f6cd06e.npy +03467517-81bd0c7a35a147988cc3ae4061da3bb0.npy +04379243-9d9d1a2c33b32c2078aeec4d01b034df.npy +02747177-64393896dc4403c0e88c1d6fc3580355.npy +02958343-64f940ade3f61f976a106c3e1a10b659.npy +02691156-e9ddadf335adac52e025e00c738da634.npy +03001627-c9dd1e508be23628d0176f9a144100cd.npy +02801938-6d21c75bbe308322513c73fd461b230a.npy +04379243-5fc0812f8673249aa6a7b6e78d8d5bcb.npy +03467517-73368b2f443e51661082f2ea630bf69e.npy +04401088-ec39e26f8c0829b3413ef77469a0f9cf.npy +03710193-2008a48636a98f0d4f25f5ffbc4463cd.npy +02808440-519390da89f5cdc83321831d2245cf06.npy +03761084-d5739ed3034fd2551d5c138748955e00.npy +04256520-c4a70ab37043efeb14038d588fd1342f.npy +04379243-47164255adb1efd5fc54b7f07479f415.npy +04379243-12a2733fc5f6b31ef8574543281e850f.npy +04401088-54539e30a59cce413864ee650d9e9c5c.npy +03691459-5787e7156ddf7a2adfa0db1c1e10ab1a.npy +03761084-bf6914cf309077cc575f4e5007488531.npy +02958343-c8ab7f11ecdbf873921cb81cb1632a5e.npy +03593526-7b97f7b6ba604173fec8ec00010848b3.npy +04530566-927c8ab9d2603aec2d4fe9f5177af0.npy +03691459-4c43241d7b30eee379e6d136097a1329.npy +04090263-2ec617c22f8a1c7d96f12bf103d650c8.npy +02933112-6723be3b8435e27bb6146c7a77e1b943.npy +03001627-5e94fe6e318670d310da6117f2797a4c.npy +04256520-716eba8ec4825ecb19fb4103277a6b93.npy +02828884-9ddf92e8ab113b77a98ec10fab84d714.npy +04468005-5ceb4a6a1e9c2378fef210d199fabae3.npy +03001627-39ba09c13d784741dcfbbf65ff959eb1.npy +03636649-cf280bbec8017c26655715f3c8480da5.npy +02808440-5d403d56f762fab7b362845c6edb57fc.npy +02691156-7ce6c64ab3a45504dcc75fd1795fa3a5.npy +02992529-3a3fb2919b1bd92658c2dcb60645f75c.npy +03624134-de69d6441bbf8d39230a4d129580843a.npy +02958343-ba817f535c2668081f757787330d376f.npy +02871439-bbddf00c2dda43a2f21cf17406f1f25.npy +03001627-b58b8a4646d14b7c202339ec5396045d.npy +03467517-a591dc6d2760a4654177e158c403ccd5.npy +04379243-5f32ce6996fadc96b3f49378110b01ba.npy +03001627-4bc064672eb85023d84a8130bee3aae8.npy +03636649-19171a11ad8bd9d5411a00390d1cd315.npy +03624134-8592840d350b7cd4b9282c90175ec706.npy +03636649-13c127aad3fc8e6af51fa0238791f5dc.npy +03001627-2463439444134401815b2b467e8e2eac.npy +04379243-8381dcc6adaa7752b7d9d23574a480ae.npy +02954340-3957332e2d23ff61ce2704286124606b.npy +03001627-e2c16ac7606317b3e85a21e38833ddcd.npy +03046257-8c274f1ac64c21afd820bb9763a8af96.npy +02958343-3ef0d561be7aeb3080275d4a88484513.npy +04090263-383bd13aeb390df0f8edafa0d47e47db.npy +04379243-cf24f0128755080569080f7eaa8f3e1d.npy +04379243-ca56e6241a3c762a391c070c9832629.npy +02828884-76958ab9aa25d309c9eed7651b77d0f.npy +02924116-d2be14011f8c99231e06124bec25a766.npy +03513137-59c1f0cc533e57a7d44412b02a9868.npy +02942699-147183af1ba4e97b8a94168388287ad5.npy +04530566-a492984be2c03294213a43a25cd73264.npy +04379243-f444ea9df9132a3616a2b5862518c93.npy +02828884-b272113ac712ca012055e892b9798352.npy +04256520-c22b660349b21edb246c4171f2c393b.npy +02924116-d6779395045f32b5822461519ed909c.npy +03001627-9d961de6d462a7619fb4103277a6b93.npy +02924116-5862a13f9639f1ba44f19502064e0a74.npy +04379243-fa0ee25a0c8109639f5f9b9f432d1ba0.npy +04468005-42e786d44eae54dd52470de2774d6099.npy +04401088-b575152bd96a4dc4adf82b2748b1cb62.npy +02691156-e06d3e6c1fb4b208cb7c15fd62c3982e.npy +04256520-9dc28627bd03a2201e606a18cee01990.npy +03948459-cc84594ad18e16bf154ac598883c344a.npy +02691156-9d65814e1b252fb01636caafca838500.npy +04379243-94f83fc24106e39f782f27684f3b650c.npy +02691156-bf57639c6735626282b3aeca5b3e7150.npy +02691156-b5130ad12f6db8d0c83b9fdce4d2e0e7.npy +03001627-f4427ee23d4d51fabbf98dcec5f11066.npy +03636649-2a52bd01472ec7e1589ec67c01f5c1a7.npy +02828884-8ec231441abe44a05e276f6574cfbdbd.npy +03691459-67b63929a6fc3804dc7d80effd6f43c0.npy +02992529-e13a5d5b3f7581cbecf207e73a787c06.npy +04530566-e3e2bf1879ec9298c711893477336d39.npy +04379243-5d819ba4e21208ac2b5fb024f65f6da.npy +04379243-fe130356df1977499c2a886f3b75f1ff.npy +04379243-f5ad10e6a938aa80e85c7a030ebdf69a.npy +04379243-c71fa66202239b58d6de1645a30c4052.npy +02880940-4967063fc3673caa47fe6b02985fbd0.npy +02828884-41e1774c1ad94df4ad5067eac75a07f7.npy +04256520-337f25da3cdae83bc7660a81296c2300.npy +03691459-81a096b49d138bca1125e131b6efeea1.npy +02871439-a79a38419ae817fb3d2900ab7b1f5d81.npy +04256520-a15be5686c875d703201317d7803c43e.npy +04379243-26ab5349a902d570d42b9650f19dd425.npy +04379243-e49636394d4b0189523e5ffab409f73.npy +02958343-8c1b20c4c37dc679301fa882a9655049.npy +03325088-a695ea6dcd5e85b03321831d2245cf06.npy +04225987-99aef9f6486d3d90b267718342f3f316.npy +04379243-d20dbb223dc5e26e6e4d44229ea605db.npy +03211117-f84f6c14852ddad1d06e6be4f8954ac.npy +04256520-6a5f98654b75a18c593ebeeedbff73b.npy +02691156-6420a3ff5e526d59e16519c843f95ce0.npy +02843684-76ea6ce7dd6c1298805346b85ff6b7a.npy +04090263-cbe8debb3fa41f716e96d446ae30c673.npy +02933112-3b307c9b473270a1c59350d819542ec7.npy +02691156-5f9707e5f6b820275823df672991ed66.npy +04256520-8ead2b6ac2726710707cdefe012d0353.npy +04256520-fd181390f71ec72478ae896933c670d1.npy +04401088-722acb5e8ccd39391e5d846d206adf3d.npy +03691459-dfc0bd9721814628a4eccbbe9e05e638.npy +04379243-3b0625a3d623a7decfbec6fc6446a041.npy +04401088-4b96f974453ef59ea2c7c5886f4bbc93.npy +02933112-f6d2550b82c208b012de5317fe5b354f.npy +03325088-1a5586fc147de3214b35a7d7cea7130.npy +03001627-3dc252fd90d82b18c9be65dfbd21428b.npy +03691459-c3233311a94b7b968a0181490cb73cbc.npy +03001627-bdd57499bf64fab6bf80985a99195eb8.npy +04379243-6a436b27484166629f9a7ffc9bd1e3fe.npy +03928116-23cb522f8c3dc4b15375aed1ce49c448.npy +04379243-12e2dcbdc199f0ef8fbd401ebc04b5b4.npy +02924116-741f329be4ac607c63c2b7a67ee8957c.npy +03001627-6beb16fbb2337f65936c7265c890fef.npy +03790512-5de5e9abd5f49ad7468bac13e007a6e9.npy +02958343-7203130a35ab20a4b1bb46d2556ba67d.npy +04379243-f2743fb608c502abfffc97a61124b1a9.npy +02958343-4cce557de0c31a0e70a43c2d978e502e.npy +04379243-b31a613e7f289c8bf5f6997e99549136.npy +04090263-2229f60c2819cccda50ef3fc203c6ba0.npy +02958343-471673f3f062abd473f10e6caaeca56.npy +04379243-5d93e285b2006520ab610b0c94236463.npy +04256520-40a6ac0c94ae686e8dd711af5650bdcf.npy +02946921-e532d6bd597d4e91e3e4737f6033f0f8.npy +04379243-4cfe758f926fbdf2f51fa0238791f5dc.npy +03001627-2f20894566c681e5922309b37ed10e7a.npy +04379243-60c931dcc6d0982944bda2555d37e46.npy +04379243-85d5a731ea4865c1e258f9dd9d42f6c9.npy +03211117-bdf3dbf43ef2637f578d107c71db28ac.npy +04379243-8b612b06a3d668eb67dc575d3328bcb2.npy +04530566-1e3400a7a099823371feee345701e9eb.npy +02871439-e48a1bc3ed228765664b3b9b23ddfcbc.npy +02691156-c581942f40cbb60819ba010ddb4974fe.npy +04530566-65e21949247e36a541db137505613210.npy +02691156-e94ad5f8e53a255a8fc2d09ac4aa4e78.npy +02958343-1ad321f067ffbe7e51a95aaa6caba1d3.npy +04256520-3946ab8df54210ef1789afaa92d90146.npy +02958343-7b2dcc7c4c879e9116f7ad0d1093bd39.npy +03211117-3fcd048b1daedbdeac22ae9309c09ec.npy +02933112-9f88eb11fd20541b4f759a9b042055cc.npy +03991062-aee91e867dd2be3ea2c59a4d90e63212.npy +04379243-3ebb9bfa2afb2f8c9db5a91069a42c6a.npy +03001627-19c8189116dd7cd3e95c611687989498.npy +03691459-d46c71be46696b1d41ba258440d3e234.npy +03991062-1163604f205da98d7df9613e629232fc.npy +02958343-5721c147ce05684d613dc416ee51531e.npy +04379243-c05033de978da9dd5de04aad18bd94c3.npy +04256520-a8db9db73bb5a4dbf51f77a6d7299806.npy +03467517-cb5b2e3f499e4fdecc571cd3cf8f17a1.npy +04530566-2b58ca08b8f93769c5408f4f799fe72.npy +02828884-59cb1f3c7476a5712056b4bd5d870b47.npy +02958343-de1564379b1315a3efadfa67efa023c.npy +02992529-d406eebe0342fa8373acc74b15c67e07.npy +04379243-eece94f60e91c3d819fb4103277a6b93.npy +02808440-89eec42ca751ce883321831d2245cf06.npy +02691156-6a9b8fd1f4ddd87f152be1f5910e33df.npy +04379243-84a3c87bba5a472af51f77a6d7299806.npy +04401088-52494d36a6d136f6b34ae4286be3d813.npy +04256520-7ab84ec80e11d03fe8daab4fe9011efe.npy +03790512-e9c34796e3c9e46939e8ef80333dae6.npy +03691459-f6d6ab4f49238452b45df535caecae62.npy +03001627-e6b77b99ea085896c862eec8232fff1e.npy +04530566-bca8b526924310bae8d6be23f236225a.npy +03624134-db7be6ac02bf5e48e2bb19fbad3e4596.npy +02946921-10c9a321485711a88051229d056d81db.npy +02808440-7d4c5f150ed81e3054d7082b34825ef0.npy +02933112-c00edc704ff4b133da27ece6ae88fff.npy +02958343-5efb2b4cda03da10e047028ded406033.npy +03691459-11f5f6311449da7ebb01628f533af3ce.npy +04530566-358bac5415f0773941d6cd38228b9631.npy +03001627-92d87019793c97c636c8b9bf2576aca2.npy +02808440-b08eb2a2c20e681af51a9050d9136192.npy +04379243-227308a94bc7b231e5490ac94fb8e485.npy +03991062-ad58ba1e4c6dec3b5d8d4d8a3cf8b294.npy +04090263-62fea07f4f7a6bfc673a614c45f3afe4.npy +03001627-24b5d56b254cb1958b424343280aeccb.npy +03691459-d17192339d28af3234140f5d5f70bb2c.npy +02933112-74126116f42f09e2e6e130a30b5ed875.npy +02992529-c6ad139da5e0799c712cb59213324f9d.npy +03001627-fd9c60e969f83e6086debb0a33c851f8.npy +04379243-1a442af63ca5159d86478bfcc70b1bc5.npy +04530566-83d2a7a4cd616008e19ccaf2c9aa161d.npy +02691156-e005d8b297850d483a99ba0078ef7bd1.npy +03001627-ea8ace071a8ffc2a50a1e454933067.npy +03624134-4a0ef45e02210e47914c738e92faad58.npy +03928116-b7b54152e58fdee6bb4d99f9abe880cc.npy +02992529-237b8445c70b1749ce2eca356a0e3474.npy +04379243-375652536313a1c2278f90ef85162deb.npy +02958343-9aec898631a69b6b5da1f915cad9a74.npy +04379243-aeba3a81cac0687abf3f8e8aa5b07c2a.npy +02958343-fe61764c0552c837d76439fb95cdd2ed.npy +02876657-e56e77c6eb21d9bdf577ff4de1ac394c.npy +03001627-a631fb1b054697dcfd8aaf214a1df4be.npy +03211117-79f26b0be635b891631d57ce83092826.npy +03001627-eaa4ea82bc814005e6fe3612af521500.npy +02691156-dea43c46fdbe84511adbb4c4e06ad649.npy +02691156-ce1d767436d9b289e8ac6b4e1f12f978.npy +04468005-734a3e7a655fe3afeb34db531a289b8e.npy +02828884-71ab9fd8db7ee09a59cbde03ded257fd.npy +03691459-4a1ffed169f04f5fd084cd4069686980.npy +04379243-9e068a0ec94cb7dbf51f77a6d7299806.npy +02933112-11f59587596e3bf1a9958063063ce065.npy +04379243-9f3d4541c2754cc2a516ad65be981ae.npy +02958343-b3047118a9b0d7b7e858db1dc3499392.npy +03001627-78386cc102c6dbb03430d3d86b335afc.npy +03636649-b401155fbc54313330f6e0ede20c4525.npy +03001627-711d131beebd279cf0102d4d10f82457.npy +03001627-86b6e539e72be6d46fa0ab61d9f9d96d.npy +02933112-90c2b07e831f5e7fc75178c2e93f5b68.npy +04379243-a4eb161a000b159e2ddaf02885ddf74b.npy +04530566-ba1b46458170afa57ae1c9ca63d5fd92.npy +03624134-7b492f2baa1dc710cc34b900bb2492e.npy +03001627-37cbc18323826bfb19fb4103277a6b93.npy +02691156-b19927db257219bb26360e1e29a956c7.npy +03790512-543ccc442390ac8ad3e27012e0feb9f.npy +03001627-bf3c02f71de0260a8dfc31d0ab372d9c.npy +02924116-6f92698b7e495df56b61c956066f9ade.npy +03636649-2df234af39ae991afbd43c84cd4013f4.npy +03991062-cf1dabebeaf02912a2c59a4d90e63212.npy +03467517-c40f68a092baacd133d89feae811d3a1.npy +02828884-84d3224312b9630465826cf0dd1f6a6c.npy +02992529-6bd7f7a17a7bbd2d68acf22a03600648.npy +03001627-b197d9b353a923cfdbbc9440457e303e.npy +03991062-dc39b65c9ed54544debefefb2e8c0245.npy +02691156-3e8fc3155bbc4225c1ccec171a275967.npy +04379243-cd4357aae286fb57c5f48f9175316bec.npy +04379243-9e58589d9f3dc4f24b3c42e318f3affc.npy +02958343-efd9059d23b9c01f46f8ee02bd8f9824.npy +03467517-464c2b11e7c9ae87241535bd4c40391e.npy +03691459-508e66670fb3830c2cd6a352b52d97b9.npy +02958343-d80658a2f50c753cf1335b4fef92b83f.npy +04090263-7da59289cc7eddf7c92cdb7e63a33179.npy +02958343-8402d2237afac94a1cf6f8e565096a1e.npy +03001627-1028b32dc1873c2afe26a3ac360dbd4.npy +03790512-6e1397773a4d15db429f1c522640e6f0.npy +04554684-8103431c1feeedcd42163310d48ef535.npy +04379243-7421abad75caa60a299938728adfdc7a.npy +02773838-10a885f5971d9d4ce858db1dc3499392.npy +04401088-e55ef720305bfcac284432ce2f42f498.npy +04401088-79912d77eb2866af4e964633a1b1c39c.npy +02818832-73d8ed364821a2701a6208c41cfe5c77.npy +04530566-4cff5eb82cac0f56b7b1411b0ad3bd0d.npy +04401088-b73398902d1c267b5eed8c8b1cd54386.npy +02808440-5015f03078bd60f8e219859c1bc1bea1.npy +03636649-8c8ab9d274bf85bd7054f829b1ba8eb5.npy +03001627-956063d67b939431f56aa11cd5e0c3e.npy +03001627-6bcabd23a81dd790e386ecf78eadd61c.npy +04379243-63e37e8a29ee34bab277610811e28cd.npy +03001627-3a1b54325b3565e72ca4b544d68c52.npy +04401088-41f5caf37dafdecc5dcb6feb4bf8ce13.npy +03642806-d91a3191d427bf0467710679e532af1.npy +03325088-67525c6f3d27609f4091462be8a295b5.npy +02818832-dc5a7937cf3d5ce2d6547ce8d3c3ea11.npy +04379243-6f835f3532151c25c2a21be00e77ae82.npy +03001627-408631c881e3b33cefb90719a33cc920.npy +02808440-882ea3f99bb9e7703321831d2245cf06.npy +04379243-f8e3ed6b09b50d1d7f890f73fae19325.npy +04379243-b606da9c4be6e6106cbce046ef0f1d8f.npy +02933112-1700d057c9e0c88cc59350d819542ec7.npy +04379243-299ff1bf2618a4b584b039efed4b32d7.npy +03337140-7969fbbc3d46b46e4c3aee8e9d3a6ffa.npy +03636649-374ee0d01fb25ecc9bad7d7f6ef7bb21.npy +04256520-bf01483d8b58f0819767624530e7fce3.npy +03624134-8bd5c4f395695ebdf40d02cc9d84a93a.npy +04379243-9a6ab25d91c92a5a35acfdef2ece21c0.npy +03001627-3f36e261cc87648ac3bd24f986301745.npy +04530566-ab52de94b627af794c0b957b7129452a.npy +04225987-36aaae334d636ec28043db94fbc8c982.npy +04379243-575b467b6ebb2f234eaa3180e8182d9e.npy +02933112-cc9194f94951cd934da5feafe6f1c8fc.npy +03991062-f15c66948002dec0d7f470ee20dce9e0.npy +03001627-6601d179e754149e2f710dc8afceb40e.npy +03001627-a07b5b7014264e0330e06a011e63236a.npy +02992529-c7fef6ae7f7f91814a0be3d856af9ad.npy +03691459-6a864ca4b19aca77645b6a2a45925e6.npy +04379243-5555cf0638339605f0fb3e3d2a0d34c9.npy +03001627-1ef99f4e735ceabad97996b11dc03f35.npy +02747177-c18e807ff9858a51fb016d9401ff3e29.npy +04530566-294283d06ca9a9abfe755e3418b63110.npy +03001627-3c02356c918f7365b82b2bbc752d3ebb.npy +03790512-48bd19f7d6a20c5c52ee90e577613070.npy +04379243-7f531dece49aceeb4d1bf4af7e44abf.npy +03211117-350da53c8b5dddcde2313f5ca29127ab.npy +03001627-732ee6a49bd6db06aed393947b9cb125.npy +04530566-3e03e3d547d6fd9e4ca65624f18b38a2.npy +03691459-b6d83532d5479753bdcc14b36549ecc3.npy +04468005-2733ac1f2b34bf4b0b2e6e63122009.npy +03636649-6c96c1bcd2579c259b12350e98805eb9.npy +04379243-1e4a2ed85bc9608d99138ce6d9b8fa3a.npy +03001627-4a636d555b4f9492e27790b0ec8671f7.npy +02958343-d4512a374073ae95199f3841b86452c3.npy +04256520-b2c62e5b20b34fad5844a4d0ab925627.npy +03211117-74a99b32b562fcea7fa29a3ea424473.npy +03636649-e94273de8e52f9f896a3517f50eeb9f4.npy +03211117-2f1975216fc24c5e572bfae97b5793b0.npy +03636649-72099a83e9a058ace715cd506e17332.npy +04256520-2abe8d5b5d29ff52f7628281ecb18112.npy +03325088-3beb681d384c32a076d20e73c57c9a03.npy +04530566-8e4fbd72746ed71c20d966555ebf57d2.npy +03001627-79fd9633635ab7f6490ad276cd2af3a4.npy +03001627-efe76021aa616a41f51fa0238791f5dc.npy +03467517-798c7b38b096e7cbeccd82bb51193a7f.npy +03325088-f48e5d5d88b9ece98a1a0260fe4e4cb9.npy +03001627-baa8760ca5fbbc4840b559ef47048b86.npy +02808440-b0d95b98cc9ced8bf82d285b0703fe12.npy +04530566-5a8c1f3f0ff3e5a87bb222726cf5a84c.npy +02958343-719487aa97fd9af513345bcbe0ee623d.npy +04379243-3b334febd0aa9ba7b20aa91e9e90c311.npy +03001627-fee248777c9c4807f8bc1f8036e08e44.npy +03710193-f8ebd72bdd49a43b8ad4a36593b38a9e.npy +03001627-8cca53295cb61e878d3e8783b997c75.npy +04379243-3ee0a3bc5e7af23d1bb088904f7cb154.npy +02958343-f55e967e8617484fe565b03326f48ebc.npy +03467517-38eb9bf1f02d192259b584008b480e22.npy +03001627-f14a2e78a93c559b253b862f13dd465.npy +03001627-4e0beb356493c9cbc862eec8232fff1e.npy +02958343-ebe05fb264a56628d7ef29ade0716b6c.npy +02992529-2eafc16c78c43b35d9f7ce5b19e46227.npy +03624134-1a1a5facf2b73e534e23e9314af9ae57.npy +03001627-64d5bd4a6af3da16327289c00b6dc9ca.npy +04379243-e8ba9621aef9395a3019620286259e2c.npy +03790512-b179e7e416edc37086b7427eea4d0f22.npy +02691156-7826147390af0f9d1fbc781ac25c5c7a.npy +03325088-a515d60008ac9cd5175c399a4380a866.npy +03513137-a452a0857cb46b5226eabe1cca3e850.npy +03636649-91c55497aeec1fc55e29ce2c9d37b952.npy +02958343-13d090612aec3d80ca92a4cdad802b45.npy +03624134-79505790e5d8365f4948b6ede15604a1.npy +02933112-663cf5c8c88a187b6fa3ef67a69ab460.npy +02691156-a1c3287d5e847f866b7bd17e458d0dcb.npy +02958343-5bb7b111a3835592531e940de4b7770d.npy +02924116-f490a8ccde2449b4e0361fcb3204da3b.npy +04379243-8a1f9d4a36baf4fdc563fcc2752ece39.npy +03211117-a4dd6c69ac130db6795284068bb430b2.npy +03991062-10de406de3078873a2c59a4d90e63212.npy +02691156-1f9b49f320eeb2f5d0226d12d397045.npy +04379243-4ffb8579bf17a5a7df253edc1fde0322.npy +02773838-d3bd250ca3cb8e29976855a35549333.npy +03691459-3a0747975c07896f1ad88f716ea80910.npy +04379243-1e202e618d6375052945e400e1430726.npy +03001627-1b5ae67e2ffb387341fbc1e2da054acb.npy +02933112-4b6c7f81adcc5f7e4b8710a3469971b1.npy +02958343-344eb3613a1100634591011e8f7af9ba.npy +02828884-3ecf8f8f3b24350bbd17a7d75b77705d.npy +03046257-d76b2c36bcbf8fd7ef76898f881b76a.npy +02691156-d281db2c631c0170991ade27bbcf967d.npy +03790512-d8ee11cff3188479e7299bc85dbe3a65.npy +04379243-fe82d64b0268ba75febad4f49b26ec52.npy +04379243-4292e4bc1f783b399c409b26b1e9e946.npy +04379243-7dee34ea0b8cefe8668ae11a7db5e82a.npy +04379243-4eb3c0cffaf389fac3bd24f986301745.npy +04256520-c6956d32c9748c746c7c6307622a722f.npy +03001627-200324d0bafb1c2e19fb4103277a6b93.npy +04379243-f77643cf323921d7c6542d86974f9497.npy +04379243-dd8693cd2fbb5a0c7d0efae8dc996b9e.npy +04379243-212476fd8bf012b1e3ecbdfbb6709c74.npy +04090263-908d00034bfb9a8d5d30f6c8adea5674.npy +04256520-a627a11941892ada3707a503164f0d91.npy +03691459-ec9938becbd706dc8dcc38f589890f0.npy +04401088-5fea05a3cdcc05756dba92a4e2177102.npy +02933112-147e9d3591cb190829a50a2b3c5e5b6.npy +03325088-4befbb7f5548a835fe1bdd3c0c9e9c3c.npy +03325088-f988ec7ece669319b362845c6edb57fc.npy +03636649-5f0c4dd6cfa0def2e59f529cd1b6faa8.npy +04379243-9d4b8c8d26c3be06d269116c7276660.npy +03636649-f40c7b19234b07c2c8687ff9b0b4e4ac.npy +04256520-7b5e46d1cbe7c2de7d92b0739e572d9.npy +02958343-ade5514c578e4bc27dc9e02a5c320eb.npy +04379243-39f30c279e085ae41683a1f2bb7ab319.npy +02808440-304346a133b9153379d57ee14f8ee702.npy +04256520-7eeb7a4c2f3f1a0505babec7f39a63c.npy +02924116-646785d05ef7921d75dadc997718614d.npy +03001627-b971b6c16dded4fd44db5bc086b2ea47.npy +03001627-b021f7d705c4113ac7bed72580dc30f.npy +03211117-c9a56fbe2d5d735f9daa2bf0c68f794f.npy +02958343-1a1de15e572e039df085b75b20c2db33.npy +04256520-4aba95b774b2cc2233ea3991d83e660a.npy +02958343-363ddd7ab72bd485be40bb45ea25a041.npy +03624134-3837fb44d414845630dd2b88f7efae34.npy +04256520-f653f39d443ac6af15c0ed29be4328d5.npy +02691156-971ef250f2d0cb389a6e43b878d5b335.npy +02691156-d8452d4fe51f2bab3554ccf8c30febe7.npy +02924116-f1d9503cdec875fa876becae6fda7069.npy +02818832-8dc13611a04e2be9deeb06780e8a81ea.npy +02691156-c6c525a71215dd5a459f73e379ceb540.npy +04379243-bf77a1c8a520eb6deb0fe7d6b5545a1a.npy +04379243-bf886e6f28740776f1783a44a88d6274.npy +03001627-98a1d709dc51ba87870894bef54d428.npy +04379243-19c8ff25264b77666716685cf333d2c1.npy +03001627-41b90d1977ef7672b9b8f177284f45fc.npy +03211117-dd6c708c87d7160fac6198958b06e897.npy +04256520-1579af0fd3cb306154b2f0044ac86c5f.npy +03001627-18005751014e6ee9747c474f2e537e26.npy +03001627-d5e1c6d3e6ce16ca8f5bf896c08c419f.npy +02691156-2e468cc6afe2da70bc0909d98a1ff2b4.npy +03636649-5830c288acd8dbc5f71f6713526f9507.npy +02691156-f8647af0b1ad01445de04aad18bd94c3.npy +03001627-5ab7fb2f11d26c1c291743ae4bc47673.npy +04379243-74ca743e2ba959f56623a58a6d7bc060.npy +04256520-33db94c3b6edf1efc3bd24f986301745.npy +02992529-68ffa3cd161114cf55f5bce8dd67399d.npy +04256520-fc3350236b25f198f2b841e334abcf20.npy +02958343-fb97ee1707f495bbdcff2899f073ea9d.npy +02933112-2950d1baed4dbd78c59350d819542ec7.npy +03001627-79397634d362eaded96cac5d008c9fc3.npy +04379243-6661ae18418d7cb28965f16c5573871b.npy +03211117-87d4b97120598dc54e6185a07ec22996.npy +03001627-4a2766bf63caa24a4abd5da3f5ea2512.npy +02958343-27d42437168ccd7ddd75f724c0ccbe00.npy +03001627-45828c176099f3c3d2f92ecc75b4cb66.npy +03211117-8a4cbeb489904fe3083b551ec2a5aa3.npy +02801938-547b9fbe28ffae9d5f9a06467b1259de.npy +04468005-51ea5a8f915a9dab8050d454347bac2a.npy +04554684-9b50ed5a7b980dea4572fbc715b752ca.npy +04379243-8256e81768151f74d931803ebb8c8c44.npy +04401088-d7ed512f7a7daf63772afc88105fa679.npy +03001627-8c1c53ff86f59a97d2f33aaf794b5932.npy +02958343-dadcc1200b43a12be8b7f81712644c1e.npy +03790512-b91b7ff8ff1b59c6a88e8cb97b773125.npy +03636649-17fb3b85fb6bf1d74888a07f79e95b66.npy +03001627-ecb53ab8eeeb43d31246538126da07a8.npy +03691459-5e9e7b6cd01eb0edbdeac9f0a8ab72fc.npy +04090263-206d81abdbdbbb5c63d83c622f45f33.npy +04379243-3b7fcc7c030ecd496062e86c1d0c60f8.npy +02828884-89e2eaeb437cd42f85e40cb3507a0145.npy +03691459-e5a6dfbc6e89ba42bbdf3c5f28fe5d98.npy +04379243-812665596d6c13b1adeb1694faeea26.npy +02924116-bf187619d212dd102d42c1e28ea24b6e.npy +02691156-444a58c4c6bfcd6c7a571401e6605fc2.npy +03624134-427139e42c842b4fe931b9a85fdc07c.npy +03207941-36b0dc42fe805430991a1c802df98c78.npy +04530566-a74f3cc7adbdaad2a072c5ad67cebc91.npy +02828884-c03e7f08edefc17a5b28ac1273e4dac5.npy +03211117-717d3ef4c7000c5917a27c3fa1d3566d.npy +02933112-b4e35d962847fb8e86d53ab0fe94e911.npy +04379243-bf9674274a0581bb11632b225817c709.npy +04379243-2633f011b236a8979070b65ce7b4b532.npy +04379243-fb3816ce98c668157e22078abbbc121d.npy +02933112-9a24860d7ea8d54f109097154427f779.npy +04090263-2a70089aa6561ce216cf8b1cd2155e02.npy +03636649-7324c25be8ff5cd74725f67267e31c89.npy +03636649-44bcb1ec762af23b8880edc6251fa529.npy +04379243-40a7ed7ce8ba70fa4ddda47ee90d6a21.npy +03001627-2fa4a8a5848f9223a10fbdfc2fa57509.npy +02958343-dd5eceae670f164ca134736201a79843.npy +04256520-68ae06512cfbf4f95fc186cfb5f359d1.npy +04530566-5a6439bde2204588fc3f5f3afbd6c5df.npy +04530566-aa05992294efaa26a47eca0fafc43370.npy +03001627-f4e5698718f3d4494311a07b696e63e3.npy +04379243-e41da371550711697062f2d72cde5c95.npy +03636649-2967944ae64112c11952fef39dab6347.npy +03001627-39de90c34ab1dd3f327289c00b6dc9ca.npy +03001627-75ceda9606ede8d2ea98d69e91ba870.npy +03467517-4bd2492d56d6b8c537b5646da91e9ed0.npy +03636649-a3c6ef6078045515ea9f23f235ccc6.npy +03001627-a8b5f5b6bf0cb2d6876b399a99a15c0f.npy +03467517-6d60470e9e402861f18228781f85571d.npy +04379243-e758e1b760f185e2593ebeeedbff73b.npy +04530566-7fb484e04409f7323f3cc56bc9bfcde3.npy +03325088-b7c6df3b5836ea6a76d20e73c57c9a03.npy +03691459-6751b5616193e6908219b633b364ca6a.npy +03001627-374bec02e71fe06528b4c5ec471dc963.npy +04379243-e87136a7996cc5c82d6b4fb79c7b302b.npy +04379243-56a57ef7c3385c9f2f38c0d2792fb5e.npy +03948459-e318098b6a42cba14968c6db52a4c95d.npy +02933112-544fbd4d4c1d445498a4820926b2a786.npy +04256520-cf571875efbd60fd3d2617f9171b5ccb.npy +02958343-e4cd5b3cbe9082f536699018d15f07da.npy +02992529-fd1dd7c841cd9cf51f05b3da5aad55f7.npy +03636649-92c8a795e0dbe340145fa6babc33219e.npy +04090263-8f5da7a2501f1018ae1a1b4c30d8ff9b.npy +04530566-f8ec76f3861f7c68b76982957f05710f.npy +03001627-2dd729a07206d1f5746cec00e236149d.npy +04530566-2722150ea003017d7fa575e221973fef.npy +04090263-8d1cddda904b6f363a842af7a220e7d.npy +04379243-2edf007c0f4542554fa8d6439169bda4.npy +02933112-8b63c8e0d3959c961e1dc6d433ab6c3.npy +04379243-b34afa23c47c80db7422d2e1b1d40882.npy +02801938-29880fedb8770d6ce51e3cd2b72fbf02.npy +04090263-f7cf0e4395996803ed901abec3fdcc06.npy +04256520-160887408a65f88f67903707764646db.npy +03636649-86d7a728dc35d634f800b597bc1c1eb5.npy +02691156-5763ed16cc79ce63dc0a4f5bab755bb6.npy +04379243-34c0ef1a944d5443e2f1733877da1c63.npy +04554684-3f60bb32239ffa303bf7bae2651d2cf.npy +02747177-2ee841537921cf87ad5067eac75a07f7.npy +03001627-51ee5a84b4afc40be45ef4135c266a12.npy +04256520-dd9a138fd557c44f4a6b6d001599a1e5.npy +04379243-4960515bed0e76c403c7d0cd70738a3.npy +03691459-5a115cf7e21d34d249d7025d277c28a1.npy +03046257-a939cbfae7bb05effeb1e532f4bae7f6.npy +03636649-d47f0a026f66e2f24b3c42e318f3affc.npy +03001627-d1852e622204dbb0f4b6538438a0b930.npy +02958343-7478c015f1814c0728ccbb4eb8965b05.npy +03991062-f04a8c4946e7941ad0d7efee165f0a98.npy +02691156-fb402a36e91ab1b44e7761521d3c6953.npy +02958343-8b74a58c28cac774753d1d86ac1bdfce.npy +02958343-721dfe60b48849ec7ac8cd969c3298ce.npy +02691156-a73be4c48272735df64801ad2940cdd5.npy +04379243-10cd74fb0af8021fbf7cf6012a0af9fc.npy +02691156-751b1e75fcd7f1deffb814dfce3ab22e.npy +04379243-e62c51fc96e9394a647d4fd8d921152a.npy +04379243-e17121f04e884edde480eba094ece03b.npy +04090263-c5874d1a3b616a641703868bb196594b.npy +03636649-da64c56e36024add5b903ba10d2ec446.npy +02691156-4ba7b11cd496e3be69176f0174b7620c.npy +02880940-6118da3aa071921b664b3b9b23ddfcbc.npy +04530566-e93a47089f5c03fb7220891f188bc420.npy +02828884-60287e7894707cf9fd074351be80913b.npy +03636649-e333f7f89b74575e9a5046bc3786ad19.npy +03761084-67e4d0cf70b87600ddf024f7de40d58f.npy +02828884-7dd37767a253f98d56f6fc4b4ce1db04.npy +02958343-5ec7fa8170eee943713e820becfd99b.npy +02691156-b8ce3803485b620b2c674305897e1782.npy +03337140-5dd48360dcb573d291c352d02061b3f7.npy +02958343-d8f813278a49463db203f960004c7382.npy +04530566-64ccd647293ba2a75e73d168e741c7c8.npy +03001627-4b01dfb6fa24eb4c4b3c42e318f3affc.npy +03938244-c898517ee2fab5ace3f7a74e12a274ef.npy +02691156-23cb6abc0705de4ba5a118bd15e6e34f.npy +03797390-71ca4fc9c8c29fa8d5abaf84513415a2.npy +02747177-91d6f4726d1a169d924bf081da6f024c.npy +03001627-411291d56a967d9fe8b2b8dc0c816caf.npy +03001627-56e194146b9e584b3321831d2245cf06.npy +03691459-8f920f26ead4d592cf66d96a8426fc6.npy +03001627-4ad06cdc2f8929f44733824eae5cd9ae.npy +02871439-b7474ed0e4ac46cc3599bb3238bd1beb.npy +04256520-8d15fdb921ba675af592707fed2e148d.npy +03001627-a50cf70c56091637e6fe3612af521500.npy +02691156-a0bca89b37e69d349f66d5781c13189.npy +02691156-519f1ddcbf942a76a71b0c9b506dc672.npy +04256520-785ba264dfcf722bf284a86ef67b13e6.npy +02828884-1bdfb8796887adf92056b4bd5d870b47.npy +03691459-8080831f18e0cbe1b22b2ae1c9a24291.npy +03467517-c951a1ad8a90e3c344cbf4f97fe3744b.npy +03001627-fc7e2126419f5a4cb84959963148f2a2.npy +04530566-9c4ae8501ef74e82cffae3eeba6126e6.npy +02691156-76b492b77a03882d431e5b4ad135fb8.npy +04379243-1bba8d173012111f5fceaa39a8353bde.npy +02880940-9dcfab1fab6232003bec56bff764ba78.npy +02992529-7ab7f36fa3523a1a33c7b6ed91d531bc.npy +04256520-9e4cbc2bb68878b57984fb9ec7e40829.npy +03593526-5d636123af31f735e76bc197b3a3ffc0.npy +02933112-aac3c6db20d3248579cea75b38cb7ce.npy +04379243-d5a7ae84e93368c28b015826dff11d35.npy +02958343-b2e36774150b580e21f6e2b0f75cf9c4.npy +03001627-91b8fe4616208bd4cf752e9bed38184f.npy +04468005-4a5c80895fecf3b3c51d8e07a45cfa0e.npy +03636649-a2f760540b18eac2dbde8847d3101230.npy +03636649-9f07035e2ff0e5946ef2faffa907bc32.npy +02691156-cb744ec78dd320efd2c2bfa672ed621f.npy +02933112-9029a5f19440d04e6b19a27bc4c01b1d.npy +02691156-7db10020f24a3232abf03860b8d62488.npy +03001627-30e8b5402898334ef4b6538438a0b930.npy +02691156-676e568ab8e286ad67c54439d6177032.npy +02808440-575c40e0d9d3f2d75ac2d26bd5b040e2.npy +02828884-92e7ed09c8d265e5cb2a965e75be701c.npy +03001627-632a722f9edbaf607b11ae648ea92233.npy +03624134-2071c9e5fe60e5886ba5f56f5d8b6131.npy +02691156-62ebe2dd7bceccd097f28f82dd9c77a2.npy +04379243-9826f7752703d7bd58cf2448c6d2934c.npy +03790512-d94a099c6a1ca8def4cddc55888e6926.npy +04099429-b333cc1b0f35943228eba1f0b7744e9.npy +02691156-1ea8a685cdc71effb8494b55ada518dc.npy +03046257-160f24d660e3183235836c728d324152.npy +03211117-d1ff5895420a205dba1a3bdff265e174.npy +03991062-3d377597d4ae8f38a3b06ba374e12b77.npy +04256520-2b1f1929a6a5a6517b431cae0dd70ed.npy +03001627-a16b8de490656d03713decb1a0563b12.npy +02691156-a1ca5014ee1048081e06124bec25a766.npy +04256520-e1e2ab3bc1d604752b4aa1e18549d620.npy +03636649-b5b728ebd7c0833530f6e0ede20c4525.npy +04256520-f0e243acfc5605bdcadbe66b40c67b2a.npy +04256520-cbd547bfb6b7d8e54b50faf1a96496ef.npy +04379243-4b548d4f399066e1c2f0a1a44c64aad4.npy +03001627-91be45a6b74f2fa283b00891f680579.npy +03991062-f012c87f43047ac015d2b72e86737c92.npy +04379243-696482ce58cced1044b0115560181a7a.npy +04379243-dd468c350fc655eafebad4f49b26ec52.npy +04379243-a8d59c4b6577b9eb37a0eda928b574d2.npy +04379243-a25141a07c77c25467de2aaf749e5256.npy +04379243-6c27a2a85e8d512ce6c5cd45aa112726.npy +04530566-3283111173c12947622984b5941cfb8.npy +02946921-eac30c41aad2ff27c0ca8d7a07be3be.npy +02691156-d2f8a99bbdc387c8c5552bebbfa48bd7.npy +04256520-b251364a878eb5fca192483aa282f8e5.npy +03001627-5faa205b9355a66579ae41e1ea899b06.npy +02691156-47821cd2309d5a3990b1d6deb98feec6.npy +04379243-14d8555f9a21f341edf3b24dfcb75e6c.npy +04379243-6a4bbd1a2d533741849f98fb0b88a16a.npy +02691156-7279a912e89a6f00adcbeb54f3d014e9.npy +04530566-f7b13135feabfbbd91347c63d1dae43c.npy +03325088-458b641a644595ecb362845c6edb57fc.npy +03001627-e4b0814cb9a34107efb405803527fdbb.npy +04256520-a930d381392ff51140b559ef47048b86.npy +03001627-98ec1c46805977c33b48a711df82173e.npy +03790512-f4da1640ad370ce2468bac13e007a6e9.npy +04256520-45fb33cc152121a97b8f528a5a7a471d.npy +02933112-6c6e14968b5e951de7e684d25d4dcaf0.npy +02691156-7eff60e0d72800b8ca8607f540cc62ba.npy +03636649-31d93627f2fbf86dfcb8d8c6d4df8143.npy +04379243-b34982af1d6e18736b4393ff6e4e0f88.npy +04401088-198557f515ecfe73f3c5246a46375579.npy +04256520-70be13428e2a6eb1a789fd2e20dfbbd.npy +04090263-8a0a85f55ffa4a13269c192b79bdefe.npy +02992529-bcbf0ce42d2b0f91abae9246594d3f7d.npy +02958343-90c4864afa329be1fac5c51be36c9fa6.npy +02958343-75c4085b3315688aca92a4cdad802b45.npy +02808440-202920053729ecd1ccd0340812259a39.npy +02933112-cae4ad6aa7d0e49df160c00ab31497df.npy +04256520-a2bd385c411aa690c795085b4d203932.npy +04256520-222ee8debd39d5fedebd258f4352e626.npy +03001627-67c866143e633daaa6fee8e2140acec9.npy +02992529-8ef2182a6f91e71e7877a964f5722626.npy +04379243-3c079f540fafa7e13b3db95ce254f64d.npy +02691156-61159c0458d41ac8e341b5704aa568bd.npy +03001627-861251082f0935c6990561fc34164364.npy +02828884-82071d0daa90cc15ed98cca8f0ccd5f7.npy +02691156-57937c7ab42260ebf119374ee5d5f944.npy +02871439-d4d6afa83861d9c9201432a6a5e88038.npy +03001627-a8f21e581e687c0fa329355bc8cbc0b5.npy +04379243-b7bb5f021d40ae59f7b4b759a0c02e4a.npy +03467517-653405d4777d063351c29c30f86deb78.npy +03001627-2a8554af80cfa5e719fb4103277a6b93.npy +03691459-8d5064233fdf0624b6d9c2cee7f2f72b.npy +02691156-26210ec84a9c1c6eb1bb46d2556ba67d.npy +03001627-72d0cbe861a7de2de4f382dec07f365b.npy +04554684-5e04ab0e24e0882272a5adfd0bef5d10.npy +02808440-e3da3660529c4986ccd0340812259a39.npy +04379243-b9cdd373211c1d406349f6b5431fb3d1.npy +03001627-86c4bc3f46e1bf7bad179769eda42205.npy +04379243-3bfc7947fb8abec5d925b06c8689bfe2.npy +02876657-ac79fd7f10f274aba2c59a4d90e63212.npy +04090263-209b87f6aa188df0bce41980429512ac.npy +02747177-84ade133b55dbde550da8b99982a3057.npy +04379243-dfe0eb3f446059d0500cffceffd2bd2b.npy +03046257-896f36a9b765fabb504721639e19f609.npy +02691156-a60569e3e80d24939bff604afc480b65.npy +03467517-f182545f81b6273f92d73a7cb82eabc7.npy +04090263-9b2cead73808a61a508db6f63303da32.npy +02958343-c6dbb4874805a2c6c2998c73c3c35adb.npy +04468005-b1ab911647c2e39d510791503ab90b79.npy +03467517-d63a56ed4f0bb9aedb43638841a7895e.npy +02691156-c8a7eab796be432d5de04aad18bd94c3.npy +04530566-51b25c88fd90ae2b57c58fd0f9b1d74.npy +02828884-c65b1fe1cb4ec230262cc3347c0f3889.npy +04460130-8ceb7f6e170f793f38cd8eb23853c009.npy +04530566-de010f7468ceefc6fcfb3ae2df2f7efd.npy +04379243-f9f9d2fda27c310b266b42a2f1bdd7cf.npy +03001627-9a5b54e835c762e4f51f77a6d7299806.npy +02958343-605be4facdcdfb194dcb1867559ba976.npy +02933112-a65df9374a1492d7fff2ea4466fc1c5e.npy +02818832-5e930124cbecf7091da03d263d0d0387.npy +04090263-afab3cfa9a8ad5f55dec35fda9dd6781.npy +03991062-ae33867e3c5e1703f155d75bbf62b80.npy +02691156-5d1594f792f3641583a1f09b027e5462.npy +03001627-fc7d038dc7fe2911a75d03186a0409e2.npy +02818832-b8d3510487f019a76bdcd672c2b17215.npy +02958343-f66a6fe34a80b0fbe7540f431cab4686.npy +03211117-97870c19256a95acf5f79806bd65844f.npy +04256520-c1b8d982d97e337f19fb4103277a6b93.npy +04256520-7c92e64a328f1b968f6cc6fefa15515a.npy +03001627-8ecb9191ec41785b351d9ca36f76b95.npy +02828884-7836a7015159442980360680c1602c7d.npy +02958343-3bf15c48eb9110d16abce8cb03e7794.npy +02828884-5cbffd78e4cefc3038330212e10bdbc0.npy +03636649-3deedc86a83bbf23f647dc544bb0ab61.npy +04379243-438f44f223f116e3c2a9901441a2941b.npy +04090263-7da8e9ece43c210e44b4519fba3aa36.npy +02924116-41a74616fe8dab5f88b61e9125676b2.npy +04530566-1994120ab63fd4fa3df8f4ac45647158.npy +03593526-2fc5fff977ac930050b92125e5fcb8ac.npy +03001627-94e289c89059106bd8f74b0004a598cd.npy +03211117-602570deed9cebea66ae7844c5fcdd1f.npy +02958343-a077e24f8983d3d3476c231adfa21265.npy +02933112-92c111f0456557c14da5feafe6f1c8fc.npy +04379243-febbc5702f304c16f51fa0238791f5dc.npy +02871439-a372136702c46b0250a059086f5706fb.npy +04530566-ecdd85e25c18ea404d73ca91c97c0cb3.npy +04530566-b1ed34ab6779919510f652915f26dbdd.npy +02924116-498d3ec19a132718bda733a39f84326d.npy +03211117-afda884544124320642ac1f4cab4f5b.npy +04379243-b8ffc016a4e080a6d2e5fdcf2bc010e2.npy +02958343-6b79cfceb6f614527e7afb83f93db294.npy +03636649-fbcd17479bc96e0a899bad344dc01f2f.npy +02828884-ec4733130fe285d03d23022ce06f940d.npy +03001627-7263fe53bb4601efa37f3fc191551700.npy +04090263-1345ba2c3b27ba786bb9681d4604e123.npy +04379243-7f7d80803ccc727137b816e68e48019c.npy +04090263-75368dfd449ea1d729712ea5520175b6.npy +02871439-f7eaf1291613f3932ade7345ab5b0cf6.npy +03636649-ebd783f677be6825b5495e8609a528b6.npy +02691156-56c79a936f57ef3f7b164268a44f7712.npy +03691459-f6954ca2e4c2b03c67b2ae8c967fcba0.npy +02958343-714d3c11eaa39f106e28ffc6e1f368fe.npy +03001627-3e5e00868a2dfffa7a31dd5af93fdb5c.npy +04090263-18598beeeedb20729a6e43b878d5b335.npy +02691156-a3a3a3d2ccc590eeaef99de91a3e555.npy +04090263-69e884912b10faa880c2e60c312b0f09.npy +02924116-3080d86e8424187d4d44f5db04bf14b8.npy +04256520-9d54e00d9428c07e76e9713f57a5fcb6.npy +04379243-69689176b53be82df51f77a6d7299806.npy +02924116-6ad564360b6d18e814d1291d9f969ff8.npy +04256520-3d0aea03fdbcbcc1dad4c6b86f1850a6.npy +04401088-e8d826158072a6bf1455397a420729a1.npy +04379243-a072caf10178224ad038992c6975ea76.npy +02958343-aa41aa1837c809e1e12eceaa46673a5d.npy +03636649-16258409337ee2914a200f5f1797d729.npy +02933112-4427e5eac495c14e40a7c7e360f68f9b.npy +03001627-7380789e95676518e7c7920f6a65a54d.npy +02958343-6471b4eccdbba210ba9a2870774c1424.npy +04256520-117c47d75798788a5506ead0b132904c.npy +02933112-a64be5342dd3c9f782ef94da039e491f.npy +03325088-908bae8a91cc3af72a38aae7db90ad57.npy +03211117-8f032c701a2d1de772167aadb6db5f77.npy +04530566-4a523f749fd08ffa698137c717c4ad11.npy +04379243-1b0dadf0e60a563b3671949e4f99cc76.npy +03001627-b5b77de7a8a05ab4f09df371fae9d63d.npy +04379243-6e29841d23d6a8a06cee93ad801259bf.npy +04379243-9f286ec40676d24e3dfc74c6ca03fa25.npy +03636649-d2c124b8c6a888fedc7a10bd316015b2.npy +04090263-e66332d7d5d35ad1871adec4b4ff0fcb.npy +03636649-635a3e20af086ce8c0a31f7b214b7805.npy +03991062-d30095f634231fda2c59a4d90e63212.npy +04379243-fd7a4cdd680495c7dbe9c90af547c85d.npy +02691156-7aac10eb5b285098774a720fca15e35b.npy +02958343-5c29bf38845b4ecbea0f3fb9c87b9c6a.npy +02691156-bc2deb55a1c952beca9f0727e23831d9.npy +03691459-54047a2d59ac5eae3ef7ad0f5cedb0e3.npy +03636649-9fde9f07e6217b7490c2e24416edfe5b.npy +04379243-e6b3255eb51908a53c99073e1068144.npy +03001627-5d6a45296fa6c1ff7c21c7b1e8b3e343.npy +03001627-7fcde5fc8e023dd2a6fee8e2140acec9.npy +03948459-76e10c1cb25e814fe7d6f3ee02d4059f.npy +03046257-e78af014ac35bc68f546596ce7364503.npy +03948459-1660ef4b3f20b1e2a94b922b533051b7.npy +04379243-34105c5e1e64f66b23eb3ad3d378722a.npy +03001627-bc523df998d94c7223ac0bd64c9cb255.npy +03001627-66de742ac6ee931390a9ce3e4b15521e.npy +02958343-110ab054cfc351f46a2345809e2bb169.npy +02691156-177fadcfa6b4a8346aa3bf023a2b42a5.npy +04379243-52c2b3f2ee5b3519febad4f49b26ec52.npy +03691459-ed981b60651d5ad8265d1076b4b6c5c.npy +02958343-79febc9d103c4d1c247a5be450795511.npy +02828884-aef0765eabe46794d2b12aa6a0f050b3.npy +04379243-41eda879e1b7eee2dec2e3fb3c73544.npy +04225987-ae28ad55a38200ff1c5f9eddd7cde6be.npy +02691156-a20db17555286e06f5e83e93ffcfd3f0.npy +02958343-d569a1b7066ce775b738b317b28286f9.npy +03001627-3a885865c614a5a35510d59f3ab1ed64.npy +02818832-f388c768c0511cdff72f7a2cfcd9c0f3.npy +04379243-23d4170c7a0a2a014b3c42e318f3affc.npy +03928116-7aa18769bd5d996934d6aa31914c287d.npy +03636649-e97ef0ba839e1e915412c66cb6f267da.npy +03001627-beae73bea87f36a8f797b840852566c8.npy +03325088-60a6cd1194397b4bd3acd54d47e688e9.npy +04379243-2a0676c50108be8842d09291b1705b96.npy +02958343-1cf17a1e1841d10c9e6a3356df3f3d9a.npy +04090263-df2cec0219c10e0ddae3730658b53fef.npy +04379243-a9504a750945231f91bed99343331f7c.npy +04256520-96e21b275c9bd83bec7cbf3284585a40.npy +03001627-80dabf9ddbdc92f681806e3880250dff.npy +02828884-84bb6a30b1c5a87be008ebe8273a693f.npy +03001627-98ef942e35e90be3de8d5f2cba401802.npy +04379243-c6591f825c72dc6553a2cae48abaea7d.npy +04090263-8caf6dcbdebba2221326f2506129299b.npy +04530566-bd04c982ef479f160014fe834c82238.npy +03691459-ab79e12684746d0273e1b2d018c0512.npy +03467517-5238adec0790595930c206f77b5cb4d0.npy +03001627-33c4f94e97c3fefd19fb4103277a6b93.npy +04379243-1e60953829fa7e0530bbd4cddd04c77b.npy +03325088-21c83317b5617925b48d1e811c2d60b8.npy +02933112-9524af09747661fbe0f91080da8431d7.npy +02958343-cb0bffd770644cebcfd826dd468a5497.npy +03797390-1c9f9e25c654cbca3c71bf3f4dd78475.npy +03593526-546025d656c166562887a88b1b446ef8.npy +04256520-13b60f5be9af777cc3bd24f986301745.npy +04090263-35f61b951ad15590d2a0074bc2b80d37.npy +03207941-6f006ce5ec9c41029a8ef44e1d2c5b75.npy +04379243-775b3e38da839158ecab93c7630e9242.npy +02933112-caa4f65053f07a64548804f91c2c5c3d.npy +03991062-19042f85f93a8b239f7e329438453d00.npy +03211117-93e260150e7788ab574b5684eaec43e9.npy +04379243-aec823460d983866d23df9ad1134a651.npy +02808440-fda9e9a38854dcb72101dcac4ed75d3.npy +02871439-97bd21b29826854a23500a5b036df62e.npy +04379243-cb7114df1c8ad743af04c22d77ac98f.npy +04379243-41d9b3064aca3c74e7d71bdc5700ff8b.npy +04401088-c1c23c7a80e4bf388c34a8518a7b6811.npy +03211117-dbfc22d7d096f66d5f1b26547b9ff327.npy +03001627-46363a10e242999c69d8d5b35c38db0d.npy +04379243-50323d86b68db6fbc35131da26f8061a.npy +03593526-e6a47ba0a8cca8a14725f67267e31c89.npy +02691156-2269715ca42c218fe3921ab5df3d2707.npy +04379243-6b6ea2e841e2f00b60eb699207aa149d.npy +04379243-5b51e63726f21bb6a75d03186a0409e2.npy +04379243-1fcc1a3a879b2a037d43e094da89ace.npy +03636649-8464de18cd5d14e138435fc2a8dffe1b.npy +04379243-5aa08289fc85d4d2ee51e40b76ccdf20.npy +04256520-c943da3efba4955d3ed66fc182459935.npy +03001627-937bea562c1db4fe5ba41eea807f5d3c.npy +04379243-7bbd4240f837e20a6716685cf333d2c1.npy +03636649-23a8eaabd1343badfcb8d8c6d4df8143.npy +04401088-f973c91a4c239da9dd14866f469b6370.npy +03001627-374fe2584abb594da094848ea4d06501.npy +03001627-9ab690ed709e7131b1b2ecd73d1717a3.npy +04379243-43a7d89c62a2fa86a5aee46eeae32d13.npy +04090263-f2b4650a52cca500b4cdad9a5bf52dd5.npy +02958343-4d52395f788af7e5a413908c0e169330.npy +04379243-4fad9f5ab1d22ea95445fd9f27a38098.npy +03691459-ba56fb3205a34768d4b4ae2ff4c58b57.npy +04468005-5eac87cfbf9188cc1aa15c8505e5645.npy +03642806-6008f256f3beafd9988abef1fd117e7.npy +02801938-2056cbd13e92764a61b3b6f2928a81b2.npy +03636649-c81470e576e437a495f1c4bba38e85d.npy +04530566-b91c482da95cf3055f41c9ba4474959f.npy +04379243-c011010ac01b73c78e43a810a63361f0.npy +03001627-8b39b501c9fa4d349b9f2eb77f5e247e.npy +03211117-882619bc31c4e4c88091986dc5b9a01e.npy +04090263-390d25757d6532d5dd8e6e2fb6475d03.npy +02958343-a5d32daf96820ca5f63ee8a34069b7c5.npy +03001627-1da9942b2ab7082b2ba1fdc12ecb5c9e.npy +02808440-84c48592fa2c0d82b73e9e930f636032.npy +04530566-767e561fa1214fb83651bb31f42d2f80.npy +03001627-f10263256eeb840b732c9e6120e90cf8.npy +02691156-bc33901245943313d6d949577c389a84.npy +04401088-fcd923f9bcf1e859e2a1e51fbada37b3.npy +03001627-34722e50142652e53a5e6305a3a7adee.npy +02828884-f80f3251391f3cfccbfa849e0f7f0b10.npy +02876657-fd0ccd09330865277602de57eab5e08f.npy +03636649-787bd789cf2aab676e0185e256a599cc.npy +02958343-3339caa48a18e4c358db0ef36af1d3c5.npy +04379243-68a6c680b48dbed292a0bc4ecc8b2ed9.npy +04090263-a2570eec88282cb3d8569d1a6c25406f.npy +03691459-2f41de1a2faf854d860e5e56395d4d1b.npy +03636649-29985e44b73051d923500a5b036df62e.npy +04256520-61ce96ea92a12f402e0ec510458499fa.npy +04379243-2a6010074025d1d85dc3653f8341633a.npy +02876657-b1271f402910cf05cfdfe3f21f42a111.npy +02958343-792a93f2b8dcfe7116abce8cb03e7794.npy +03001627-336ec0b3142fec15aaf0ad030fc37d94.npy +02958343-1acfbda4ce0ec524bedced414fad522f.npy +04401088-85a94f368a791343985b19765176f4ab.npy +02992529-c56262f4a6a7fbe5fcae16e8230396f7.npy +02992529-39cd15c429c6007e2826f529d0b74d3a.npy +04090263-365589510c76c7cee603a5ccfc8229e4.npy +04379243-f9bac9ba3b878cf23a6e0d0a575f76a3.npy +02801938-2ae75c0f4bf43142e76bc197b3a3ffc0.npy +02691156-f1295a30fd857249224c86fc0bbbbedc.npy +03001627-47dcabdd8618e5c4b3c9a4ebefe3bae0.npy +04379243-63fedc0334f5552dbec3a71604e140e3.npy +03001627-b46ad21b7126049842ca7cc070f21ed3.npy +03691459-90120bf8e84315de6873d49607c1f87.npy +03642806-ac3ca8ae5e3203117f2411014f221968.npy +04530566-4be2461bad10aa82a875c848d0fb1664.npy +02691156-72fcc9dfb927311935fc197bbabcd5bd.npy +04379243-bc842e548e68a3cbb48513409ae7c51d.npy +03467517-d50d06b159363b1693f0194265a9746c.npy +04530566-e687e0074b0dc5bc470938161c06eb7d.npy +04401088-58c6118bd15ca3b48dd025faf4cea27d.npy +04379243-21c58ff6f87b750cb9a0f5d18f1ce54c.npy +03710193-e79cc4e58f69eadc5bee258e658f9767.npy +03991062-87d72b1c98c0f8548c159f8d5e761b17.npy +03001627-308ba1f8c1eed4fbbf80985a99195eb8.npy +04090263-aa47591498e4eb615dd9d441afd49974.npy +02992529-82aeb34ab6fa282766148e8aa85ea356.npy +04530566-988e1d7106b705d692336765b86c93d9.npy +02958343-8c0fd2f204d6008da1b543d55837199.npy +04256520-76e0b10288997462c51b240dc7b068a0.npy +03325088-28568aa9e333a421c36fb70296e45483.npy +03636649-185b2436cc0404096ef2faffa907bc32.npy +04379243-e94b1ab02a3264c89eaa55bb236fb6e1.npy +03593526-ea4b33d425d8535047efcaa87d68903f.npy +03211117-a151ea6f6bf27e2c9a7c2b8fd801b3e8.npy +04379243-7478ed7307756ccba10ff7fd5e43a633.npy +03211117-751f46191d0baf99f541411dc07303c.npy +03001627-ffd3064cff5757695ecd29875b6f0d44.npy +02747177-46e777a46aa76681f4fb4dee5181bee.npy +03001627-32284e0d1700dc55e7c7920f6a65a54d.npy +04074963-25182f6e03375c9e7b6fd5468f603b31.npy +02691156-3ee352a759364cdfbd46d022fd7d80aa.npy +03001627-e0df9f745fe38b389bac1502ed0eb150.npy +03593526-86fc09510df14f9d9f53fb212867331e.npy +03001627-e5f405ad8aeca327d9b53420a5458c53.npy +04401088-8ce0fff87979560bed1f9cd2184d7b73.npy +02958343-6dbb3c5d7ce105243afcf7df86a03c60.npy +02924116-a0e5a36bcb4e2298e1da81584e31b667.npy +02933112-cafb0ae07b0e2fb055f46d55537192b6.npy +03691459-4a10811da56f40a989542bab68e6843.npy +03046257-1ca3587bf68d70d571810a8e7ede71b3.npy +04379243-75e3cbf4b1ef0df971a782a4379556c7.npy +04256520-ac5a9b215a7d5be123448769dbb64afa.npy +04256520-d47eb4149fbcd0c7907a5a34fd8df2f1.npy +02691156-e413c15ded9ba57a23fc69eefd95e6d3.npy +04256520-2a310d5bb9e5b1ec162227055a96104e.npy +04256520-b922bbdf49b4100659f8e31ca87c470e.npy +04530566-fe7362e8a02d00072e4aadf908a27d12.npy +04379243-79b7bd0c910e833ba5dde908aa701435.npy +02828884-367e5ca5d5791739d4d8765e3910f617.npy +03938244-68316f18573e3449622179425ac4ebe9.npy +03001627-29cd7fbcf6c7c33df51f77a6d7299806.npy +04379243-b4cc6b735f911fefcfff181817262617.npy +02808440-9c1664de95b39e30ccd0340812259a39.npy +04379243-c6fc2ce48ae9867d688ad7d3969cd02a.npy +04379243-fc2ae302325d2c796820bd77cbfc18d6.npy +02992529-b442b550e827cbcc8ea897fbf75dc392.npy +02808440-3b4a28f7e078ac063321831d2245cf06.npy +02958343-30d360f644e8cd472eff38f357a7b528.npy +02691156-39fce052e13f97a57a10aa3eec436422.npy +02958343-1feeeaeb8b56e46d2dfaf88f42097063.npy +02691156-b738666a0403a7fa6818e4a1f2613507.npy +02958343-139718b631cbca546a36136419d55d5c.npy +03593526-8c45ab7f96998dc0feb02b0cb8b196e3.npy +02924116-2852577a7f4a67216f03051f81ab06b7.npy +03211117-118083b82350b53cb23e7e4bd2944793.npy +02818832-698ef3d1a8c0c829c580fdeb5460f6d6.npy +04530566-9f34d1dbf06b4d989330265a9fff38de.npy +03001627-ccd5e24c9b96febd5208aab875b932bc.npy +03001627-4a329240c6a9d2547b11ae648ea92233.npy +04090263-bd7b5781568afa0f46177b6d1ecbf989.npy +04530566-1039c49d2976eb87d5faf4905977884.npy +03467517-83b2ecf5caced214e313875ff213ee10.npy +04379243-30ddc80e5fd46bbef51fa0238791f5dc.npy +03467517-8465e902e1aa1686e52028751701a83.npy +03001627-d0d786244fc2d7a9ecf03af5e7a1277b.npy +02691156-228fcd24cea34febc0909d98a1ff2b4.npy +03467517-f146c58eaa06f5e4d57700c05b1862d8.npy +03691459-e6ac4bf60e270a6512da48a027621f2b.npy +03001627-e1ab1f421891fb01f302352a74d4e413.npy +04401088-5d1652fdd7cd46d0dbb1de10c9529bf7.npy +04379243-40f8588bf78172a129e4b5aa807bb4e7.npy +03001627-d64c618e8b0c7db73ded7580b6cd3bad.npy +03001627-f1dac1909107c0eef51f77a6d7299806.npy +04401088-a3193340929f4bdd146def56c5fc9b3a.npy +02871439-32c3e3a86698a175a7942170a4965f4.npy +04379243-97d1c4b5a82891e33002761e7a3ba3bd.npy +03593526-7c1303d3a19a1cef51f77a6d7299806.npy +02828884-a762de549efd8f2899d9a264095450d7.npy +02924116-350d4061f4cd94b9a855be96518ce9f0.npy +03001627-5bba0c3a964662a6881e525dd6501111.npy +03636649-7527ef1898765c09fcb8d8c6d4df8143.npy +04379243-34c00f5a77147ac6b041f249f731e3da.npy +04256520-64ee5d22281ef431de03ab2a27ba7531.npy +02958343-6c22203e5ed35df9ca4aeb694e04f8df.npy +03001627-f9dcf630e370f7d5a320e34dad7c78bd.npy +02992529-a698b67778c02fcb5a0a15c8380e928f.npy +02933112-227d258c1045acbe9e4965f0106e00d9.npy +02691156-5f46f3c62e353c7bb4f5fdc59ce06e88.npy +04530566-a7f5b96f138649c6bc30e923e47d8bd4.npy +04090263-c4d201c44ab9b1f3e1f2a1daf140ac9f.npy +04256520-33eaa3a6a05575ab14038d588fd1342f.npy +02691156-6193ca8f5b4419bfd86ebdaa02a63c4b.npy +02828884-57afec727772346f30bbd4cddd04c77b.npy +03001627-8b4b176d9393676d5e1f306d831137e1.npy +04379243-3838d78a4b4a76282027cee422df2aa3.npy +03001627-fca55be264355b1ac30ba10ebbf8ea21.npy +04530566-ccf527bf6ea742f0afe1d4530f4c6e24.npy +02876657-e8b48d395d3d8744e53e6e0633163da8.npy +04401088-e4a8822c5faa386fa9976d676758bbee.npy +02808440-6e4a0d8f65be087458da1271ffd33120.npy +03636649-e0aa085dfdb0ac03ef3a2c64cef919d0.npy +02747177-2c09ad6e78554a6ead5067eac75a07f7.npy +02933112-29c7cd661bce3e50c59350d819542ec7.npy +02691156-ef26ad836cd29010f2acf00738ce9d0d.npy +03001627-a750f7309fcc4b0473672ae855b8c82f.npy +04256520-628f7a321ce4f90fcf01bc59d215f0.npy +04379243-27a0e85f8fd0c7a819fb4103277a6b93.npy +03691459-3fd4d9909c72fe47dc4f6934317af74.npy +04401088-8b11b38e035143ddb007a3ad40c5add6.npy +03001627-f36e83dff72cba53ba9ae5e8f97b3d4.npy +03928116-4e370af4ed086e088b3c4b6eb338e363.npy +04090263-80432cdae538023ef13eed41b64dddca.npy +02691156-33faf711ed54a4d3db22b838c125a50b.npy +02933112-2df3eafe6c699c1a6baba085b51d97.npy +02958343-b659b096b9cd0de093532d4a06abe81.npy +03001627-d4f38e40aedc67f779368d1198f406e7.npy +04379243-3eef676eb5cb9db4e56bf1253ce74bd.npy +04379243-f835366205ba8afd9b678eaf6920cd86.npy +02691156-7117ac29aef4f1c4951971f8370d9050.npy +02958343-ab7b5025c9e9c1921cb81cb1632a5e.npy +02808440-2426e758dc1d2681ccd0340812259a39.npy +04256520-d3425554004d834f6dbc9d74bad392c.npy +04379243-c9ab6dcc7e4606adf00f0216ab99ff30.npy +03046257-a39bd192df9ec7475e6e4a5422e31446.npy +04256520-9aef63feacf65dd9cc3e9831f31c9164.npy +03593526-9c60d16fa781095fb866188bf6825255.npy +03211117-4d74d8c3df7a85051d225d751745cd28.npy +02691156-a9dff753cf97f9c5354ab1decf4fe605.npy +03325088-804cdf67685d7e592efffaf8e146c9c.npy +02747177-59aba635f6d79bd72bcd3c046a99811e.npy +03593526-4a53c4af240c562537048583edf8ef2c.npy +03691459-b648f6cd54d07a1023e70120ea31089.npy +02876657-32074e5642bad0e12c16495e79df12c1.npy +02958343-fe16b8e790f23ab8c6fcb4b4f04936c2.npy +04090263-ae1a6e01d2ea5d2cc75e2dd4efaea578.npy +04530566-6fd0071445c70e9297e6e890ac2fb198.npy +04379243-4e76319c1489ee71f4a4c7b91852bb65.npy +04090263-f50efdafb9e486f4519f927f2bf92da9.npy +02992529-2098a0f7cef1e593f6c5597dd1efe723.npy +04090263-6e23faad8bff1e12f7bd077790d66b82.npy +02876657-4301fe10764677dcdf0266d76aa42ba.npy +03046257-dcd8f3705e7ebf7fb2f671e673cf292b.npy +04401088-1d9169471bf9223423e378ba27e11ea6.npy +04256520-98e6845fd0c59edef1a8499ee563cb43.npy +03938244-86bcb4eb29d5effe157f5033576317e1.npy +04090263-70928b07af4272df2d07d103eb3a7540.npy +04530566-14fff3ebab1e144d6b77971fd22cc80d.npy +02828884-25f916e08a803ad5067eac75a07f7.npy +03046257-845f1b53ad2e0d53b87e0c7ed53711c.npy +03337140-38c55928e088fe1b47f6dcad69d89980.npy +02958343-854bb96a96a4d1b338acbabdc1252e2f.npy +03593526-be4e86198d0b8d438edb5be732846826.npy +02924116-f4f5bc6fc08ca19962ea3c59193a008.npy +03001627-e3eb5422bda98fa12764cfba57a5de73.npy +03636649-4deef34d95367b58c0d95250e682f6ee.npy +02691156-e6d6e9544e353f9f75e49fe23848bbe5.npy +04090263-c4d31507a1c0f7b7c3972dbee3e8d0f9.npy +04379243-e1b3412d67d2c18c59f8e31ca87c470e.npy +03325088-1d584bae2bb2ff963ca0c4be71e7b721.npy +04256520-5c9b1a32f54b12cf81f667e2a25e0619.npy +04530566-4f513b39cfce2d269eddf484109e2999.npy +03001627-5609756359a6dd2c1933ffef19678834.npy +04379243-5ec15b09dedf4dfe961b3f02493c4f73.npy +02691156-8d54e30dea0e2508bbf3143b1cb6076a.npy +02992529-5d1652fdd7cd46d0dbb1de10c9529bf7.npy +02958343-72ad8ebcd7dfbc87368990af61c704f7.npy +03337140-3c519e2bb9f20e284c3aee8e9d3a6ffa.npy +03691459-3b55f9d0fecbc561de9a8c37f2997f.npy +02828884-c83b3192c338527a2056b4bd5d870b47.npy +04090263-639b18f1cbf26228e666ec68139b7ff7.npy +04090263-a4051a1e8a1b78003940cfb719120315.npy +02828884-c3d4204f6f0613b1959f51f2c68b3ef.npy +02818832-b928b7904901c8849abd6ac8761170b2.npy +04379243-4d43a00b356701d914f14c67f445762b.npy +02933112-b4d82c9706931d29d1d193a59606317a.npy +02691156-c47a2cb459ab849c493ab0b98cb45d3.npy +02876657-3a9516eb02206108e0c8359faeb78bbe.npy +02828884-3db1d3904f058b574a9ca2c84bced0dd.npy +03001627-111720e8cd4c613492d9da2668ec34c.npy +03790512-6819949f5625ca12d0f568c31c1cd62a.npy +04379243-845c77d01efe2f2e425fe98d8cc1c2c.npy +03001627-64871dc28a21843ad504e40666187f4e.npy +02933112-14dff09acf069b63c59350d819542ec7.npy +03001627-ebed17a73a2e9e981882515d09f3979e.npy +02958343-985763be7e2b18ec16abce8cb03e7794.npy +02958343-b9c0f9dbfb5a1c0f99684c8184952917.npy +04379243-a4e595d77097b224e2b372d25f6c9482.npy +03001627-8da6959dc59296c9f2f43e6f841bd32b.npy +02958343-e1a694f11100ace082d20fd7268a10a.npy +02924116-607d400470141f8d8f8940e918ad4591.npy +04379243-a55454529b463a1eec56aed2da084563.npy +03636649-907fd296708ae71dd5fab5deb286066.npy +02808440-cdc30ab10100ed23fc4743bde9e89079.npy +03001627-90129d2f4a5cb57799982a4d6320875e.npy +03593526-cf184ee375cf827eeee0d5e82f0b9cab.npy +04379243-e6cb56c84042891b201e82f29479384c.npy +03991062-c1abad416a011faa2c59a4d90e63212.npy +04379243-20647984dbeb990ea6c03a53cf0a14c9.npy +02691156-29120728132e5dce42a2048a31b7df8c.npy +03710193-85935473b4685e24769119a7d27b495b.npy +02691156-2d9a7863dcfb5663d208f79049825a82.npy +03211117-3209637ef61547c040feea836646b66e.npy +04090263-c4f73b23f4fa46364785ea41f043d735.npy +02924116-58017ca7c738b89dbd69e36f5d4705c8.npy +03001627-92bad575037b0552d7bf6fb68df7f786.npy +04099429-651f56b608143df0cfb3f4d4e98ee41e.npy +02691156-e02485f093835f45c1b64d86df61366a.npy +04256520-8f5c8cdc0fc4d84aaa4296a266fbc9c0.npy +03790512-c8d62fbab07d49a7e398c671c3b93e96.npy +03001627-d7dfcd99197d6ae7b6dbfb7eb145012e.npy +04379243-9b42cb91ccead6d42f6d10c5d1d56320.npy +04090263-2b997d20df6ec1b7e290ca81b042ebb4.npy +02933112-3a2afbdc240a7f073fe047712e43e185.npy +03001627-360b02dcfeabe768492d9da2668ec34c.npy +03001627-8e2b44ec14701d057c2b071b8bda1b69.npy +03593526-1c47c52b9f57f348e44d45504b29e834.npy +03636649-9459660f359235abd9010e2a1af5e34e.npy +03001627-450d40600ed92c7de9ad5e44c87685c0.npy +02933112-5a5e9a046d79bcc7859a7164d38b0d13.npy +04379243-f64138f5515e5031f785f45147f3e474.npy +04530566-583ef94812afcd26e025e00c738da634.npy +02691156-e6ed2c677e158daa1059f490634fcf62.npy +04379243-72010b2aabc328ba2d1beed6f591ab11.npy +04379243-fcc3a9a4e880b5f35966c5a46a5a6ec8.npy +03001627-9b42dd8043ba84f7492d9da2668ec34c.npy +02958343-12796524ffbadb755400f0dc3171dfcd.npy +03001627-b4371c352f96c4d5a6fee8e2140acec9.npy +03207941-e5aea3a902e5cb8e2116f4e646b32073.npy +02933112-2726971c1ed929eaa733727fd41bdb33.npy +02691156-d3198154076f49a86f0778e65d2e88ad.npy +02691156-341f5b3c74970a618d0dbc7502fb16f2.npy +04379243-a6a7ea033ff20abac133e11c42c6f6f4.npy +04379243-fd7ed06e2ceb26d766c55b7c01b230bc.npy +04379243-4a47ff44cd2f024635cf289fa8ad7115.npy +03761084-eb7dd094761f3647fcfa1e01912deb2c.npy +03001627-e71d05f223d527a5f91663a74ccd2338.npy +04090263-7713f61fc0b829f3e196b48bc93a41a.npy +03001627-8117c55b8bbdbbc54c5c5c89015f1980.npy +02691156-1a6ad7a24bb89733f412783097373bdc.npy +04090263-7ffa338b2693aef651cfdb4c9f126c12.npy +04379243-57fbb082f660c4f7716b680dedf77108.npy +04379243-98412ad8301f965210c709fd84118ff1.npy +03991062-386b99b2357ba64aa2c59a4d90e63212.npy +04401088-1a0fab14a11b39d1a5295d0078b5d60.npy +04379243-37d500b1bf8b3a5beedb4c8fd29e2d1.npy +03001627-e31d71ed32273fede42ac999db581f5e.npy +03593526-fa9e6aa9d67d5329e5c3c7284848bbfe.npy +03001627-373089aa7a44565b7215a1e3ffbff428.npy +02871439-46df0d838e68cedbd42b9650f19dd425.npy +02871439-a74ce03cd895bf07316bfcab702f4c34.npy +02747177-8026b11c2f66d77ed5a4ff0c97164231.npy +02691156-d2bf5f39131584c0a8cba409c4409ba9.npy +03691459-46ec6741dbbe69bdbc052c28a9e28ccd.npy +02958343-d2592adba4e8e62648368c1a2f71c5f3.npy +03211117-2d828dc0e75a47ab760433abc0037bf6.npy +03636649-28793511c46b4fa030f6e0ede20c4525.npy +02958343-c4ee4b9fc4501a9380c4d64ac66d8b56.npy +04379243-6e3a2f1de25bcde5ed6c51d5b9c713e3.npy +04379243-c527f1e7ae2c7b8a4f7482420c2e91df.npy +04379243-6b678921222e3375f9395f1ee40f845e.npy +03001627-622552cb1f5670a614038d588fd1342f.npy +02958343-c12424d1cb48ce0fd0a4f72b67c7f064.npy +03001627-1953d62a63721f17df6cfab91d65bb91.npy +04379243-6159304c015c2d54bd7b3ab3cb320beb.npy +02933112-63c195f60442eb5a32cdc35a3ef7141.npy +04090263-d2f505aca92ee65fbdb8512730b99253.npy +03001627-6621723f7af35f2dcd344c2b2cefcda6.npy +02808440-cdf47d95ba14768d48ad5e70a514c4da.npy +04379243-f62766dc071eb88472f944a50941537.npy +02958343-98a1a92a94a025aed28935fb3c99dc7e.npy +02828884-6c8d7faebd2ca60ef3b7873c9ffd02fd.npy +03211117-8bf89a26f5e7824a8eb91f418e60b82e.npy +04379243-94be8cf5e1538257f51fa0238791f5dc.npy +04379243-81ece5ee42a4f814d384177e3e0b693c.npy +02992529-d2636f3af00fb3e2538f655e65b0b57.npy +02958343-fdd3f02c294518341944f01d3ab2091b.npy +03691459-f07c69a33e0a1f54b6c84941dc90c1d2.npy +02992529-44d7b5d87c26896944608b3255ca1886.npy +03636649-a801be11157a7f243d39d8012919dd25.npy +04256520-df19f437c753b93a72814c9aa90ee14e.npy +04401088-ef2b505068cf120efe48f52a0ccc160d.npy +02691156-2f3bef6d679273d062b600da24e0965.npy +02691156-74a5f937c22aa08a3e70653c1b3170b5.npy +02933112-6f03b6ab474c04a243e5ff23b077c03a.npy +03797390-6faf1f04bde838e477f883dde7397db2.npy +04468005-2a56202ffe3cedde53a3d395d3382ee.npy +02828884-1d6150ae91a07cf6f4fb4dee5181bee.npy +02808440-cc98d2d5157aab693321831d2245cf06.npy +04379243-fcf216336b414bfd2ea86336b05b146a.npy +03001627-600f028f0bd5e7c2c8e0227722a7d821.npy +03467517-375ef808d47a832684097c4f3f6953fd.npy +03636649-9a98a0088ac6d37a2c5b2f528cea9dd6.npy +03001627-d3f4ce51467fb777525211e12d56c55f.npy +04468005-eecbec1d6360c2c77b4c98ce79dd9c8f.npy +04090263-3722e5b8425d025895f22290198b089.npy +03636649-7c8d71334a6bbe8eb3d57d6094a92e4e.npy +04090263-42b231fa5ac25f7dbac3a27910198725.npy +04530566-217966c23fe43ab83bde759c61eecdb6.npy +04090263-ce38b5d04d546346f27eb335b754fdaa.npy +03948459-12eedf28d9a948556c1cd53dbc9f7b8e.npy +02933112-4116f2d56897d9ec1bc4df4f6291380a.npy +02958343-150f2cf6e9c54d08c24a350006d347c.npy +03001627-c4c598c29a542a5f150539b40d03634f.npy +03337140-ef16caeae076c1a530bbd4cddd04c77b.npy +04090263-259edfd9a26c68104c16ba0acd861632.npy +02880940-3152c7a0e8ee4356314eed4e88b74a21.npy +04379243-d497f192ea400165da22561748cba914.npy +04379243-73ce68f6021be015122dab9909481e14.npy +04256520-42f33746d7f0a8a24d3485a4d7c3a3ee.npy +03691459-93900698e7d9ff4d104831d5b063e54b.npy +04401088-5e6ee0c5d155d2298b13932a0c28e98b.npy +02808440-800da11834a991da3321831d2245cf06.npy +02773838-5afe31025e8574ea8d6e12c39b2d5023.npy +04256520-33ee49115aa7125ddc37657f7fe19edb.npy +03001627-9d36bf414dde2f1a93a28cbb4bfc693b.npy +02942699-4700873107186c6e2203f435e9e6785.npy +03001627-4719c75b8ce30de84b3c42e318f3affc.npy +04530566-2fb7d918e4a738fd97556ba76bc2663.npy +04379243-553c416f33c5e5e18b9b51ae4415d5aa.npy +03691459-943e9abfee56144fc194eaff7ea54233.npy +02958343-283d78cf3eebff5e9aae70753d127b0b.npy +03001627-2787a03f47ffb80360cc99f89622808e.npy +03636649-5488a4df2e78fa1eb184155425111e9f.npy +04090263-c146b0aa5541bc1fc0f919a9a9f1e7fc.npy +02691156-3794aa3159c10929da116749c2415b0f.npy +04379243-6db3d1818431bf97e785ff1b79dea9cb.npy +04468005-296497a4bd7466f3bf5d6261979dd437.npy +02958343-41f087af6d5af9e1c05a03162270a7ea.npy +02992529-4a60039ed657d838fe5c7c47101442e0.npy +04256520-7e2d1762fba4c38112ad7c55c944504a.npy +04530566-6c00d47d1c8b81fb90142192ec795d.npy +03211117-21ad9636dfcc9578c78df40cf2e9097a.npy +02828884-17a7a1a4761e9aa1d4bf2d5f775ffe5e.npy +03691459-1a14b00578f19b1f5c38e15d823f1476.npy +04530566-d9e771ae62f0bebd28642b2f4910862d.npy +02958343-a56dca5eab44489ca7fd25564c2e888e.npy +03938244-68131b4f51579263f7b57f419ab26207.npy +03325088-944985ecba6082483792c04fd8184496.npy +03636649-11194326770b1225d49b2e04785f8492.npy +04379243-b66ea953531a8d78f0c92c2dfba3cdce.npy +04379243-9323cd461b771e8ecb503f63ed915ed2.npy +04379243-229b99c5f07fc657798b7aa9a1ef8938.npy +03001627-5fe6b94dce63fc59d4589db494f55afa.npy +03467517-4d10edebb598202263e148e250c0340d.npy +03001627-4c668aab2c49f9ac9bf4d6e8e41d9e5b.npy +04530566-f8d3af1d1a20123c249ba97ee36ba54.npy +04256520-82460a80f6e9cd8bb0851ce87f32a267.npy +04379243-bcac0b4a07a61efed498ea2919be2102.npy +03691459-e12178cbc10606bbb48374d47d81a219.npy +04530566-203d75b8112369d66a4afad911312b2b.npy +04379243-4f9bfdae2b76536b3212177d8262e8ae.npy +04379243-10ff43e8fb49af1719fb4103277a6b93.npy +03001627-af30cef615a3338599426e1733531ba.npy +04379243-8ad1486390608fb936da5f8a6c22b2dd.npy +02992529-a86eec9735db06a8226bc3b9ce9ff2a1.npy +04530566-f61eeef9235a776073fab9f1733a68f6.npy +02871439-3285b8271f126ea84767450bcb30e5f2.npy +03636649-b0871c4ac8505d9c3d39d8012919dd25.npy +03001627-8a232028c2b2cfad43649af30eba8304.npy +02924116-6f50c339a2fb88cdf0ef31d4eb6dabb7.npy +04379243-52bc4d1cdb3789407ff6ace05b36a5.npy +04379243-6351840a6f3b29d0a15e691028c09e34.npy +04379243-6146dea482c1e5eaf713a1a6bbd3da86.npy +04256520-e8840d7ef11fc9d4a54b9afa882a89ed.npy +02876657-2f4ec01bad6cd5ac488017d48a7f7eb4.npy +04554684-6bb98df3d7f7d3e1e5bd38daa40d76f8.npy +04090263-418439dbd9a2e674a81ccece899902be.npy +03046257-6da867f9fd8aefebc26e81144f3196d5.npy +03642806-662bff93f075e8f29a4b8c8271f09050.npy +02924116-6082930ceabb5ccee0b240915f388193.npy +03211117-bdea41fb7dc360b57639b23a4f342494.npy +04379243-16570d98a47c9907bd1aeba6ff85928a.npy +02924116-8ad16d5986708c0ec98c13d6112727de.npy +03001627-94b39e206f1bd77c69e31bb722067900.npy +02958343-74cf231265731c2f8a1aed4fb5fe5280.npy +04379243-ec59bd4b5288991e9bb952e15a37e248.npy +02828884-9bf1e702777f4f5292694c864c93195e.npy +03001627-c44413bb705968bb71a782a4379556c7.npy +03790512-bc1a3e925e6da7a97bf525c97f9f490c.npy +03467517-5c569af400d756335e98dae1ae7ba143.npy +03691459-eda3d466ae38e9112a40b4a3ef70af61.npy +02828884-86ab9c42f10767d8eddca7e2450ee088.npy +03001627-dab5b7b9df65d2e2cf0bcb121cf32b53.npy +02828884-6d23e04807a5c840307005544420ecd4.npy +04530566-4c433697f371db56459e601c4b110252.npy +03593526-84a8a8a36901d3c4500158c23c4c5a8e.npy +04090263-57dab7fa939cb30d9f703ae3d7bd0308.npy +02808440-abb5f87e6c6705e1d43b13ed5ceb051e.npy +04379243-75ddfe6d71b14184134155606601dcb2.npy +03207941-9112f0ee6b1cdf5082ec48ff3a4fe07c.npy +03624134-d5167211e757e79f012465c621a63e3.npy +03928116-f4849c546734104a5fcfbea90545e502.npy +03211117-93d0756b41670e89ce2fdea99c5936e8.npy +03001627-98f42a66467c264377fe1aa9b41a89c5.npy +02691156-7078ad51c3c30972b310347ab50a9dea.npy +04379243-82e5309809e455d5f15fed2243deb166.npy +03636649-f7c52d5d91e5ffbfbf82a0d508a096d3.npy +02992529-e14de927fca30e267a351c9c1f605db0.npy +03991062-380af31bb5f03b12a2c59a4d90e63212.npy +03001627-c993ac723dbaf479a4929a32e32d23f3.npy +03691459-b68e0b294c799771ebc9199df8e5ab6.npy +03467517-e2dd8689a41a4eb7a62113f6bf783f69.npy +04530566-46fefa9e95b353f4b1bb46d2556ba67d.npy +04554684-cb6febe6334cbf7791219aad82abc053.npy +03001627-5c61d56d4147e55d5213cec267286d18.npy +02808440-25d3c9f5d30682ec1562059f17dc3c45.npy +03001627-f3573756e64259f2b29d280b4e59c527.npy +03991062-c20d0e4ebd8d85fb97b54645ed3317a2.npy +04256520-60ad8be4124fda92408442c6701ebe92.npy +04256520-6b036756d21b6d8548eb521885c87e13.npy +03938244-343e3dedabdb067193e60794f9200b7.npy +03636649-df31746077d19233448e1c9934d83117.npy +03001627-7824cba870f915ba2922dc9c4df31134.npy +03593526-718d999b71ac3d28c33cda78d407d98a.npy +04256520-9e2a48a4263b77a06f37a8be59c15bbb.npy +04379243-56c627c74e9c78c65ed9439580e8c076.npy +03790512-269bfe1b994ac28617798af67b81f2f.npy +02958343-6c39e401487c95e9ee897525d11b0599.npy +03325088-9406afb358319bdf1aac9a952ec41bdd.npy +04379243-aec39c7f691c2ad15a824ea0c4d9b625.npy +03001627-6678f63c9b584a549d9e5580ae9f8738.npy +03624134-7048d3ea565fad8da737721d7c8987b.npy +04090263-f5b35e6452c2138de1f2a1daf140ac9f.npy +04090263-9168d4697d83cb9215bec5c0df04f3.npy +03207941-a62b6a19d2093bc91cbd656f2f1bc2ff.npy +04379243-904141878e75b065f48f3ef41449c816.npy +04401088-ff8676e76a0fd471fc115be4ff5cfb9e.npy +04256520-d53620b3769bcbd664518692a46d31bd.npy +04554684-6b056e83f0ae99f3792911e05e8927e7.npy +03211117-286a7629b62426b5427c20e7fc0367ac.npy +02691156-c5e04f903e3472c31883411175051361.npy +02924116-3e1860cc19efb87df6cf361e85e34a53.npy +03636649-ced76fc046191db3fe5c8ffd0f5eba47.npy +03001627-5ffc415d0cd8bf1d86db7993cf8d36e1.npy +02958343-6edcd628ecd0142b4f2f12fbdc4e6f1.npy +04379243-68ae56275d366ed6cea003eff0268278.npy +02691156-8e47730a471abb7f43afdb9c81ff2967.npy +02691156-37d2da0de056f5045bb2b764fed1d166.npy +02933112-cb70b087e5bc5e9522e46d8e163c0f81.npy +04256520-921a1610397b62a7db03e4f5c01cf109.npy +03761084-c35fb15786c7622cdf3a1b0d597ce76e.npy +03325088-2712bb3da10799b150da8b99982a3057.npy +04379243-a334f2d3eeebaccab40f0ac0fb9a650d.npy +02691156-29c81ffc84f2f7ba1adbb4c4e06ad649.npy +04379243-b04e9713af0d7048ce87696fce7b6aee.npy +02992529-cfdd44745ba101bc714ce1441b585593.npy +04256520-80ae351dff2476fd1fa9db366c777d84.npy +04530566-11e101e938688081d3b936925082270f.npy +02933112-bd0a87c4356e53d4630bc2b026b477b8.npy +02933112-1fe25f0be8d71d6ce2e1a0e8b25f573f.npy +04225987-484a49065ab1430624256fd51423318f.npy +03001627-c61e3ca5004f3e8667816b64852d28f.npy +03001627-271012d5de261d08101accd22c701b9.npy +03636649-26d761549dcc3c61a1b5ceeca96f6fbc.npy +04530566-7edda9af5147eeb25fc186cfb5f359d1.npy +04379243-b0ee655c0c84e70be03211c8d614b25a.npy +04379243-54a0067eb07dad5ad1a59a9e9888beb8.npy +04401088-7dc461c63f3aa4a3a2c7c5886f4bbc93.npy +02924116-3a3904d55b7a6c9bd8636d0a91468281.npy +04256520-e0f30a6af7bb75b8265d1076b4b6c5c.npy +04256520-48e31e3a3e2aa5c0cabc196a7f35f1aa.npy +03001627-6498a5053d12addb91a2a5174703986b.npy +03001627-5987ae6521cfcc53877929062720130b.npy +03325088-580ee100add1c4d854d7082b34825ef0.npy +02933112-71aaeb4dc7a7d41ef51f77a6d7299806.npy +04256520-f87682301c61288c25a12159dbc477b5.npy +04379243-96ede227209cde474042244fe2d8ace9.npy +02691156-76eaa5ea5f272c2f5986032c1ed37f74.npy +02992529-3bdd569911660da81229c79e4cce736a.npy +03928116-8775d936d5f3f38176145360ae4439bd.npy +02691156-70d9304de59792a9515d73fcb34092fc.npy +03001627-6714df9bb34178e4f51f77a6d7299806.npy +03928116-6a96d703d058790fa6491c91cd8d7770.npy +02828884-7ec901eb9f5204739a6c869309041adb.npy +03991062-efee3fed1b8bdda0d95c2d5388ec1aa8.npy +02871439-20e2da108eb42b52c16a7f7cb5642902.npy +04530566-954c459bc6762abc24f2ecb72410a6d9.npy +03624134-3d2cb9d291ec39dc58a42593b26221da.npy +03211117-44f363137d006f3cf7fe2bde3ab894f.npy +04379243-54317236f4b56413002761e7a3ba3bd.npy +03001627-b1add8182311f2a9f71e06115e9c3b3e.npy +03948459-bb71588fb21e67f67ed475464ab76870.npy +02958343-a990f6d75c669f4351a95aaa6caba1d3.npy +04379243-8141866ff4665b814038d588fd1342f.npy +03001627-ce935c8e977b8c58aa53a70b14c57bcb.npy +03325088-22f10b1903b8f285b362845c6edb57fc.npy +04256520-150da8f39b055ad0b827fae7748988f.npy +02691156-94d3a666d2dbc4385ff3feb917a6004b.npy +02691156-6b84749eaca0e657f37f38dedb2f1219.npy +04530566-8fb16643e061a3bd82b5804533e545b1.npy +04090263-30d2c5e8e703abe3f6503cf22f39c9c4.npy +02933112-61905b24b17eee756aea2f18ee404fd5.npy +03001627-b0f35e0dbfd5d75620fc2acf581b444e.npy +02933112-b45bae45ccfdd7b9824080f516909671.npy +03001627-9635dbdc4e34b7efffcd08faf4fccd0f.npy +03211117-462ba756d3337b475f16c469ffeb982e.npy +03046257-7504532221badbe449c9c494c2fb14ce.npy +02691156-f110a2ce31dee1b3c16ef5c633c71b56.npy +04090263-1939215162425a252bf06c32262648ff.npy +04090263-a95a7781d89f271a6ecdf20adf3e54ce.npy +04090263-e62ccd699b99b48a58dc97820d1d9537.npy +02880940-446583d7bf857dced5cb6d178687b980.npy +02828884-76976adc8a170036ae23680cee12f145.npy +04530566-8185d9e558f822c177cb090a86675a1a.npy +04379243-57a50a7bca63cd91e03b4418ed1a4f3.npy +04554684-ea961e30236b2b76a0ea52c7b90036b2.npy +04379243-2c9f91ed0b0584e196a3517f50eeb9f4.npy +04256520-39b0b5513ce0af42cb25d116843b43a4.npy +04379243-89478118c3618b353e615cf0ba033d62.npy +02958343-cdef1867e841d4bfafdee870abc9eca.npy +02691156-4dfe2199fdd333d09837a3d08a6a1966.npy +03001627-6ad86f428cd45b5b258d4ef9a9977ede.npy +04256520-6a6228e06f53e31b63c49003cfba744b.npy +04379243-8416d97c1e7b4ab323eb3ad3d378722a.npy +03691459-2af99551fe3644504798316286c07255.npy +03991062-7ce5fa012d569b576ea1c514a0de6d2d.npy +03636649-d190d56a1e6213e420ebca9c2a65e97d.npy +04090263-a5f7776b13c11e3194deaa9fff391d41.npy +03691459-4fef29cfa7ff1498442ed26ceeb35a60.npy +03046257-89b1770087ea083cc082c344e4f1192c.npy +03797390-e9499e4a9f632725d6e865157050a80e.npy +02933112-3084dcbd0a28399170ad2e9733c71638.npy +03337140-5bf29b17ff338ef4c3aee8e9d3a6ffa.npy +03790512-c90d74aa63043e5ad0f568c31c1cd62a.npy +02808440-ec906d77906e85d53af30a3946d92feb.npy +02992529-d41b332b9e6efddaa0eb5a85db887292.npy +02958343-a5464210795a915f9aa6f213afdff14d.npy +03001627-69a6407f21509325a04c9785f6d4e317.npy +04225987-380433d04091e04d3270ed754ff7ec06.npy +04379243-34121f5cc12135148c1cf3f7d7f0373.npy +02818832-f49119184f72bbb0b868f531409e0fc4.npy +04379243-992c967b4b1535f5f5346848b67e4cad.npy +03642806-bfd92b43d97b6d27f2b46e2da97eabda.npy +03001627-1e1b70bdfafb9d22df2fa7eaa812363c.npy +03001627-7786f1205337093d6051d49e4b21b83c.npy +03001627-9bbccaed652a88d0ad4feb1e0e9b77d9.npy +02992529-556b1ebe82977992c51777c7f8bdea09.npy +04090263-dda8e93517cb8c0ac9e18dbb8de06b45.npy +03325088-c20df659d0b79497f235ab3c41aeb5b6.npy +02933112-45342795c9bf86d94b8710a3469971b1.npy +04379243-59f04ddbd896f4f5430644dfe647c381.npy +04379243-476e60bceae151e768f8796d69d0c486.npy +04090263-2616ad4d3e8f3ab88af39b443dc477ce.npy +02828884-2d238b5250ab9eb3c55f85313e3bbc89.npy +04530566-c386c703e0f06a9b3a980283f1a7085f.npy +02691156-5958285db82a82cbc0909d98a1ff2b4.npy +04090263-47a5a10a047f2c2582950cbf0fcd4d4f.npy +04379243-a34afa94c100e8e2a45e8d2f28a9ea98.npy +02958343-bbca0e2391217de71e95a82bd2f5907a.npy +04379243-6f87ef47500b9d20768660cf080d12.npy +03001627-c7c7079b7555bf075e994da5ba753c34.npy +04225987-d4abd88611997d2cc4647061c0a60dc9.npy +02933112-181cfc93cd44af805a0e5699b3040a35.npy +04379243-6a4a9790706a558c2f84a7804aae667f.npy +03001627-58919c88a1b5b0b65cc7bfbb0ffaa52.npy +03691459-e031b24fd58c84c12633ff66beb9cf31.npy +03001627-a99be8e57aea8592a38859fd71bee28c.npy +03001627-c045514b5d4e4407b0ea0348afc5cb87.npy +04090263-efa6700a7609d9a59c4feb3f1af9fe7a.npy +02828884-2220c6ade811851cc13e020d985215e3.npy +02958343-d4e7286d53a7236374b5e1a654a4b1fc.npy +04256520-51142db12ba0b421997d55757516b24b.npy +04090263-9db0f94cbc2ada72847c4fc4f8c08820.npy +03593526-ee3b373aee74624ef228e31b813ebbce.npy +03001627-288143f68d5b9f7462acff507939719.npy +03636649-35e76406291b06dd66c1e3622e549d2f.npy +02691156-240fd3c1fd804ec1b8cf782e8c539948.npy +04401088-a2b921dea6df33765282621e4b0cea7.npy +03325088-3a30f6f46c4f1774e4e346ee2650d150.npy +04090263-57d7f154da3864e951dc50bfb39cd6f5.npy +03636649-ec639d4850ba9aa6fcb8d8c6d4df8143.npy +03691459-f982748287ef2c7ace029fab54b6cfbd.npy +04401088-4534e6754bcc38f78bc584bb94b0b13b.npy +03211117-79c623657fc683a54112e839a470cf05.npy +03001627-2a9cac5daa8e99cbd9b53420a5458c53.npy +02828884-d7d7a6bada0ba7705fceaa39a8353bde.npy +04379243-b99ad68ca697301a88386fe1512ed26f.npy +03948459-aa858f23b682f5616314c3b6a3a65519.npy +03636649-55f607d043cb587d5c10b08ea69398c3.npy +03325088-61df07c03d2b6836b362845c6edb57fc.npy +04090263-26516d0ce97296dd49352dd33f95cb9e.npy +03001627-ed72205562ef8407d7f7a4c4609b0913.npy +02871439-b8eb9918623a90fe14b86d5282eb8301.npy +03337140-3b8c6261122fbbeebe35466fcaf1ce30.npy +04256520-1ea101b73352ccd9822a33e080d0e71c.npy +03046257-9e059e591d0daaba3ad3591a780fa12b.npy +04379243-9611888ee0db1ecaf7d4d3ced798ad90.npy +03928116-204c770e23ba19adf42eaa666c73e416.npy +04256520-92447fe6aa69f89fd25437aef1f56568.npy +04379243-431340a089f0b3f5f320b5d9bf24e8e9.npy +03211117-9994c527e9c39bc5b50d0c6a0c254040.npy +03001627-5a643c0c638fc2c3ff3a3ae710d23d1e.npy +02691156-266ba93989037e6d48e8405d6c51a908.npy +03001627-d298e7f6e0e335a0e4197c3ebc03326f.npy +04401088-d56bca3888d3a595e93f5e23021ef900.npy +02691156-7af9fcb4a2c4079b873ec74c119307b9.npy +03325088-6ff015e04892ffee7adc0d0db36f4fc8.npy +02958343-65ea0311528b1e5f16abce8cb03e7794.npy +04256520-1aaee46102b4bab3998b2b87439f61bf.npy +03337140-92d05d86fa641a91820018801b237b3d.npy +03046257-7af418de6847137d2ea98d69e91ba870.npy +04379243-58f6e2538ba750008223f9660fdfaf1.npy +04530566-5fa144c3a8cb5234379339ae6512a12.npy +04004475-bd95856a16347f45242f8291aafac22.npy +03001627-b360f2264526521f1dee989d1177ef4e.npy +03636649-4604090264ab99ba6c1400a7733f9e62.npy +04256520-4f2fc9895ecc6a858032f428909bd170.npy +04530566-429dea3aadb0c3bdc753f4f2b4288d6.npy +03325088-9b827d4c19232237b7a867e9b35a1295.npy +03001627-47caca00f993bc4e4b3c42e318f3affc.npy +04530566-1a9bc7dd64da10f344ebbc705ad8c07.npy +04379243-cca18c7f8636606f51f77a6d7299806.npy +04256520-7a82cfb4878d1162986fdea3c9eacb1.npy +03207941-195c883e2d5e63c76621db2c3226f08.npy +02828884-57ded7ea16600342639efb65b33fee62.npy +04379243-ea093e60ddd1c7467afee304cce81d6f.npy +02958343-83fb99fe62dab5308b55a52bfd1cce7a.npy +04401088-d809653bf5a21f10e5b8860dcdb97aaa.npy +04256520-2e04a6dedc7cc5334b3c42e318f3affc.npy +04530566-5810aaf1a0818553b05dfc874f00d5f3.npy +02691156-f771c5a1b9bbac21f4fb6842b3610149.npy +02933112-c0d2f9960e0db8957ed335507280450f.npy +04379243-56ffb40d5f85f46f1a72c98fc69f22ac.npy +04256520-857c44dca7247e5757baa11b83badc8f.npy +04530566-30f5a0395aa8ce14d152039c9a3ad601.npy +03467517-d84d2877bd385d9c69da8e7f9a803d12.npy +04379243-9aff0e9f8722f063c0169cd3bf2650a0.npy +03001627-a59a49a0f9e8f4cda249f8489bc060dd.npy +03691459-c90cbb0458648665da49a3feeb6532eb.npy +02958343-bf8c14637ee36251ae3e053f6a533410.npy +03325088-f1be1113f7ac9625b362845c6edb57fc.npy +02828884-dbb5cc73da4780feed98cca8f0ccd5f7.npy +02691156-1a74b169a76e651ebc0909d98a1ff2b4.npy +04090263-ed1e56bac79b13df0e1c0df18936d05.npy +04090263-c6cd0f7ad931ca7c997b5c86bd7c8962.npy +02958343-3a7e096d05d688548413778731d6cd28.npy +04225987-a6d560508fb2fe2858dda0079c7c30f2.npy +03636649-417039be1c492fd4212785a561e3d296.npy +04379243-b4e22060a8aa48c9b1b2ecd73d1717a3.npy +04379243-42c231c89dcc0f115213cec267286d18.npy +02801938-52ef27eb43134d5150da8b99982a3057.npy +02942699-a9408583f2c4d6acad8a06dbee1d115.npy +03001627-d06c9ea39c0dade1d6b5d21cd4e3fbc.npy +03001627-3dc79f23cd284bd8ece416489129c313.npy +03593526-e9462bac4a8f334369df8a5173959bca.npy +04379243-c793946b036d1a9caa53a70b14c57bcb.npy +03001627-288837a47f55c0e9d8d964adc0b6502a.npy +02808440-fb269f5b1fec0b94d2285085273a3475.npy +03636649-713fa0e1076c99c1763bbfff01efee31.npy +03211117-1a98ee5b62f49c95f64616b54f9ba882.npy +03636649-43fce04e5e4e22bbba9ea396e14c59f2.npy +04530566-78c2790d999b0f9c1403af6fa4ab17f0.npy +03691459-b6ff46015b57bde9abacd1c615a34b0.npy +04379243-499be58242407271391e4d6c585a697a.npy +02992529-ca2e71c5e101797fa524f6bfc21eae12.npy +02871439-32da870ada4f6ef3aa2b654345545ea.npy +04379243-747f4ccdbbe2e4452099d3739c2967d6.npy +03001627-88ef1cc314d8dc0423500a5b036df62e.npy +03636649-b46eea8a6ed035279c92366a6d55d37.npy +03938244-359576c82de003cf96907985b34a7ba3.npy +04004475-9718d7c7af5d3a377eb1cef1676cbcb7.npy +03636649-544f2afb57934bbeffb8dd272bf2a810.npy +04256520-107bce22d72f322eedf1bb0b62653056.npy +04530566-cfa697be9ee40b5357018179649e2bb7.npy +02691156-ffd13ca14b85fec66cf1b4a8fc3914e.npy +04256520-e68758f3775f700df1783a44a88d6274.npy +03691459-8956eaafa0afdc142633ff66beb9cf31.npy +03046257-bdc3be534ccf65e09ce47e8a833eec11.npy +04401088-b7049148a4ffa22fdfe197f9f37aa72d.npy +04090263-94510c7e5c40166d1fabf3cbd0fc77bc.npy +03691459-faeb2f5501c8618ae47833b310955a9f.npy +03211117-6afc906811e9b40421d7ca6ede0e9373.npy +02828884-31375f94c8739fdbb043c7d18f748c2e.npy +04530566-cd4240b8246555df54102e7ecaeb1c5.npy +03691459-b544aafb047ec5014c40f34de8f3bdb8.npy +04256520-543eaf7f7a9885d57cbbb0dbdf037373.npy +04379243-e34d1be103e9d88145a1bc3ecd3d162f.npy +04090263-455a8f48d4b305bdc70a7659d08b7b72.npy +03046257-14556ed62cba8483365bd0790b72f2a1.npy +02828884-665eb42db0c44bdc81faebbdea6bd9be.npy +02992529-af3c1e4367942543264e721f309fb873.npy +02958343-dbe0b25edb8508babcf922304761e55e.npy +02958343-870086475e8af25bae57d337a2e5e53.npy +04256520-986f6fb4a7e513614e4975e87c20ce53.npy +04379243-2b564ff0989caf58ab610b0c94236463.npy +04379243-4282180ccf703ca59ccce4c6d5bb195f.npy +04379243-8cabaa720e1fe52723eb3ad3d378722a.npy +03207941-3f1e8fffc2e33a4b66e9ca8568fd3989.npy +04379243-b41f2b0ec15892e3153afb488ead2325.npy +02958343-4fc276424133528cf04f0bf74eec9639.npy +04256520-ff02fa8cfce2d39113dd6eafe1477be1.npy +02924116-9803debfea832718a3ae38981e422be7.npy +04090263-d35379324caf0e7380c2e60c312b0f09.npy +04090263-418f388062cce47ab2b92fdc09121c9.npy +03325088-71fa90c64528cd58b362845c6edb57fc.npy +03691459-3b1a3eee64e3412b6aa8ee471986facb.npy +04090263-64559ac87f100d517246c79258663695.npy +03046257-5b85d1cd4b278549a506c8b68491bf64.npy +03001627-239bb149aa17d0ddc1c43efc967e5428.npy +02871439-93ea6a4c9068dd65ba5b64592e406eca.npy +03211117-e7b9c172059d23a6f12f3a2695789ca4.npy +04090263-5d667fb09f0ad799c2e0257dfc41d300.npy +04090263-c8b20ee08253136b77b7d0d4764c121d.npy +03001627-6409f917fdae612f492d9da2668ec34c.npy +03001627-e6b80e51ceb5c2771a782a4379556c7.npy +04401088-e33124aa016bd1f19c1db271ad9472a7.npy +02933112-24c781a3aa6310a44da5feafe6f1c8fc.npy +03991062-433fedbf96f140fb25ebd1cd0b422e32.npy +02880940-6494761a8a0461777cba8364368aa1d.npy +03001627-716eba8ec4825ecb19fb4103277a6b93.npy +04379243-e3d7cdd0224a4fedd810b14a81e12eca.npy +04379243-bb201d4811ab271ecf5469d07a8db811.npy +04379243-17ceee4f264733871dfa540c3e10c55d.npy +02933112-493593c78a647030cbb5746221d658f3.npy +02958343-c72e9ce6c6f16bb83b8642d7bb5bef13.npy +04090263-29c57a599a25868f57c012eda7b00ebc.npy +02958343-db45ce3926c3ac69e8d8ad3bdef6aca2.npy +03001627-cd06d0034224a701fb7c76304cb719f8.npy +02933112-fe8c34a5275804d451f8aaa850306632.npy +03691459-b4d4338a36711ccdb113389b677f57ff.npy +03797390-5582a89be131867846ebf4f1147c3f0f.npy +02958343-9d400df8825de9a62514ed2901e978de.npy +02958343-707dd25fa8ebe7b73a6cc070f17a46d7.npy +04090263-e0824487f2bc4502e9acddb06da3928e.npy +04379243-8acbc1b934489d6fefe244bf6a6a9769.npy +03337140-373fa1f12ba203de4bf3cfb743192941.npy +04530566-3e408017d8b03ec5a5e52d43f595c657.npy +03001627-ce60636e30770f9d8193714e438a24d5.npy +02691156-2590dff7d8f19797bd46d022fd7d80aa.npy +02958343-8aeeed96e4597ca6853c6f214c15e60f.npy +04090263-d2b09323f863db7a71ed4e55cca1417d.npy +04379243-29b55c6cc05c37606e066e11deddab75.npy +03624134-c141abaec55e87e691687e259c21528d.npy +03636649-dba95c4ca95048982d9c07d3b9171829.npy +03211117-de66399eb8aaaad44913c6e8e05bb2fb.npy +03636649-5077728a780b5873f8d6a4359d6a181b.npy +04379243-71a782bd942c4b0147d5777b892afbf7.npy +04099429-b094ce5268143b1f28eba1f0b7744e9.npy +03636649-71c61e41a85671c91b82f1530fe53352.npy +02992529-aa833540c3f2d77e2915acf4d1de24fe.npy +04401088-3ef278f78ddb1db52a39b1d7ef8834b0.npy +03467517-a0b6f040538d26e3ac61a2f8346a8f.npy +03001627-43f222e3b4b0952c1a4cdca72ed38d39.npy +03691459-20b0ddd49c8cda71eef785963bb59c49.npy +02691156-eae54f8d47cf07c0aeec93871310e650.npy +02747177-e7de8a24dfc385d92715de3ea7b582d7.npy +02958343-189cffefcdd5cb071a126804ae24042.npy +04256520-dd7dc4e40e7d015c19fb4103277a6b93.npy +04530566-6436ddeaa11efffdcdd34f38f87d26cf.npy +04256520-8920c0e0737409e29f2349486c570dd4.npy +02828884-8a6f07f3d357fbfd2b12aa6a0f050b3.npy +04225987-39edba395f3d860c5a96bae7b017a6d9.npy +03001627-e4274fc2b9e4a5511882515d09f3979e.npy +02992529-70fe91a7bc072c39cf81faac56233ce6.npy +02992529-9028fceed53a144e10bc2436075f6a52.npy +04256520-94699d5b8a8682067ff6ace05b36a5.npy +03001627-e5a65fb8c660ef96dbbc9440457e303e.npy +04256520-bda4b8e6a69e1fc63f07ca1042ba5dfc.npy +03001627-55e6d1251fc63e1f71a782a4379556c7.npy +02691156-4bf2c942aafb4a2cbd46d022fd7d80aa.npy +03001627-85d0d147adcb6318b8e1b99345a5afd4.npy +02747177-b689aed9b7017c49f155d75bbf62b80.npy +03624134-444e269649312fa20005c20ac894a3b.npy +03001627-d045654d572bc46f19fb4103277a6b93.npy +04379243-9dfe5cbbb78cd26c9ccce4c6d5bb195f.npy +04530566-9b87bdd824e68950f4a06efdbafdd7ea.npy +04401088-b1537f1eabb7f5009f7477e2986c440f.npy +04379243-6bfb122ded9082de7ff6ace05b36a5.npy +02828884-bbf019371f76366b8fb2c146d92deb96.npy +04379243-1c431bd426e880e24719088c8e42c6ab.npy +03948459-d68f31ea513d3a5d6a816b111e5f1b47.npy +02691156-8682729ee0259ceaca8607f540cc62ba.npy +03467517-d0fee35bc3efa83367a66e84fcbfe789.npy +04090263-19035d7059eaa5b1a27aa199c0989017.npy +03991062-f1f7ec7a146470a272652f4081ec5a77.npy +03046257-a41444ea20bb2ea6e105ed0a3d82ba.npy +02958343-2d4ccc24a821360f8acb0ff76f4aec7d.npy +04379243-a15a936f2949d518a6fee8e2140acec9.npy +02933112-6352c69907b70c0480fa521a9c7198a.npy +04090263-3d8bab78941943f7cfe6670bda9305bc.npy +02691156-84b396dde837c81994445a3e8b9de59d.npy +02958343-c5bdc334a3df466e8e1630a4c009bdc0.npy +02933112-7aee2d4c1e70d27c921dd903dd0b8b17.npy +02801938-bcc429595319716b726dbbf7bc5e4df3.npy +04379243-f6e14672ef1ca30130aad3a2f98e3b63.npy +02880940-dd15ee7374954827c5be64abd4416cc9.npy +02828884-9c95f498f2726883bdc8e7e780fbaa21.npy +02924116-83cb38ac1fdc5f97a8aca93a0ba06ca2.npy +04379243-f9f122b492c3f1273084c5a9cbef5cd.npy +04379243-19c9beb4e4a5ea352c79b4f0fac9a79d.npy +04530566-ce5db5f4082b56b2eb2c303a0e0d287b.npy +04530566-1378b7d4dc05adba9069b3c9aa123329.npy +03001627-d6e5a8e9e0d5dfedb0957d845ac33749.npy +02747177-9f4bf5a25f85d12ead5067eac75a07f7.npy +04401088-f649a5368586aa77eecb4e0df212ad9.npy +02958343-8361aa7ae1f7dcb582ea71649733f2a6.npy +02924116-2f5f986070ea126996db382b382d7132.npy +02691156-c9063c31d7b42fa564ed556128c71bda.npy +03211117-854a48e0d902d97f9ba2cfdf95405270.npy +03001627-af7331f7b96ebed663b2acb037dfbcde.npy +03691459-168150439eb31ea1ab5fa92a7378b5c0.npy +04256520-6226851e0bf7fca877b7247857f4c82f.npy +02691156-84b07419645a3418bbf3143b1cb6076a.npy +02691156-b9e1ba3782922bab6ad6a28101cd3ecd.npy +02933112-5a639987ce024c8223dd83e725809894.npy +02828884-21e7b25522c63209cb2a965e75be701c.npy +02828884-60757e398b7d51c5c143e86eb74c3988.npy +03636649-a885ba00108cbb63e49675db0062ac74.npy +02808440-537205d65f040f701b9d8cf5b1327a12.npy +04256520-a995c3e90cc656e0c81bdfff91c7f69.npy +04379243-83120585ebf07ee93002761e7a3ba3bd.npy +03467517-fd277b425390a46ba059f9af4d1abb14.npy +02828884-272a4cf3cfff3eb1e173cee47fbaa88.npy +03001627-280d49c0833e2dcecbdbd70308cc5247.npy +04379243-f28a91c02b1f32c7126e8f891cf24099.npy +02933112-d599d283cc1d2615a7547743355554a7.npy +03325088-eea4dfd9dc2a08c3979c556124bee033.npy +02691156-b3fbc7a0b0e3a821fd279055f27928f7.npy +03691459-b4bc7d540893226c507038fac66e20d6.npy +02691156-4d6ec762d1583ded46555ee25941a22e.npy +04401088-15bc36a3ce59163bce8584f8b28da0ba.npy +03991062-6998db7278a59310beedb4c8fd29e2d1.npy +03046257-b43d328f4acf10464b3c42e318f3affc.npy +04379243-657aad273d665f5dd9823f45c4411583.npy +03211117-f7a5ed426a6195d97c8d48014e04ccd1.npy +03593526-e0bf4bf06f17f07a8f5635ac8b18fdb9.npy +04379243-6d1416c57e8a875b214a15a5a42c49c0.npy +04379243-37f8726074a5bbf42979546ca769ba4d.npy +02691156-654a5b26c59c12e5d2c4ce8118ff5045.npy +04379243-81808dc89c4461bd9a3d6682397a3947.npy +04379243-952da8ad85350267b9b072e1f62798f5.npy +03001627-a08870dc5fc0c8aca19799a9cde9e06f.npy +02933112-676bf8a039a5937eeab2bd7322386ffd.npy +03642806-b28638f8c153b9333639bdeac6c4cb9a.npy +02871439-8951258ea1dcbb6eb66213207f46bee7.npy +03991062-eb8d2e7e18906c7f25ebd1cd0b422e32.npy +04379243-83fa3b7b8c9d388144f6e9c2368992d3.npy +03001627-3799a4d787d31c0bc580fdeb5460f6d6.npy +04530566-88ba72c3f33343ae9e6f7dedb7e5f584.npy +02958343-2f1001870f90e06bc48492b454f1615a.npy +02933112-433082675f5505c3c59350d819542ec7.npy +04379243-e630732939f6188957f5e6dcbb0b7930.npy +04379243-93d6b4ad8a164927febad4f49b26ec52.npy +02808440-bc98f11895cecfeb3321831d2245cf06.npy +04530566-693272dde72519813cee85b510079413.npy +02958343-96ca20dd7caff0bb851f021b9ed69c58.npy +03001627-85ce56c719ed2a1df30b232143ef026b.npy +03636649-176c8eee2d45e5d0535a7b6b7a43b6cd.npy +04090263-989b655cb51914dde423072102e0bc5.npy +04379243-88dbdfd6e8cccf1ca9f547acc5e1dd79.npy +04379243-1f05e080ea6e8b64ffcd08faf4fccd0f.npy +02828884-3dec9b1439c42797815b2b467e8e2eac.npy +03928116-93a3f5462dbad13b678c55004ea7d7ee.npy +02880940-32f9c710e264388e2150a45ec52bcbd7.npy +03928116-eb4787175e2f4b2bb55155963a8c9e1c.npy +02691156-952c5b41a44f6f3166cf1b4a8fc3914e.npy +02828884-59c914e55665b02cf24b3c783ba45ac1.npy +03636649-4d61bb37c5edb2903f7bd0762436c545.npy +03636649-935a5b22007014838047317417e6f5d7.npy +03001627-d1af84d4d2af1181c442c1fbb1afe9c5.npy +03001627-eac5ffc4c4a7da80b13f3ad708be4bf6.npy +04379243-f6df49d754e3adfa29e4b5aa807bb4e7.npy +04256520-996265f3d98601ea3bec56bff764ba78.npy +03691459-560a626f93c664ff9069c2d361390698.npy +04379243-6f530fe373def431a6fd617b2ff5d2d.npy +02876657-ab5ca2f648a9daa1b5ad628041310f96.npy +02691156-b785b39d10c33b5de9f07d25f575b2d4.npy +03593526-9e03b1cd20644a638c37cfe791015e2f.npy +03001627-d1c2afb3c53dc7c8c563fcc2752ece39.npy +04256520-c8e37189356e5d1249655ac7c771b113.npy +04530566-2212bb44240a9f0b57cf4c4836e6df44.npy +03691459-f1fbb16afaac70231ad88f716ea80910.npy +03001627-2f6b0ddf12d1311795bea7c29e873d16.npy +02691156-f31be358cb57dffffe198fc7b510f52f.npy +02747177-b537facfbab18da781faebbdea6bd9be.npy +03001627-536dcddf1ca6cd76d7f81f50826c13f0.npy +02958343-2468ceab72b4be041d9cc9d194c8533.npy +03710193-be7157be54725e76cf105027cea05a42.npy +02933112-9e53d5b34c4b403841b765d3dbd065f7.npy +04004475-422e02def4efcfd7175eaa02afd87c2f.npy +02691156-a1d2c8b24476c8ee70d98a97e17b4da3.npy +02828884-3d92cb6fe0abdf9c4ab121f03cb11a77.npy +03790512-ff1fb5a9dd255b059036436a751dc6c2.npy +02933112-ac2f35da065a451c72ddb537ecda2719.npy +03001627-a10370a1cf036ef82d4725b469da72d.npy +02801938-a8943da1522d056650da8b99982a3057.npy +04379243-e9038664b7d35e6b436e6787c76ef3f0.npy +03642806-b210db4bca21536ed6daca3908cc94ab.npy +02958343-e885df5686133eeef43db49cede9f847.npy +02747177-30a637a211d5c2f66e181e3da8402358.npy +04090263-c740e2cadab236e56423adc2e6f1b28d.npy +02828884-427df0fbd51ba54560f140e76bfa752a.npy +04530566-94a0345790869eace074faa875b76f82.npy +02691156-7a57a9b261f60dcb2296d88107d065f6.npy +04530566-b1c2fda8665fa9b19a6e43b878d5b335.npy +04256520-5171a910435f4c949a502993c14408e4.npy +04379243-520fad3fdb9cba4f1f335cc23d448de8.npy +02876657-dc2c07ff617d1da0197a35146ee825cd.npy +02828884-f39401db6cc45a3ae3e15116d1de599a.npy +03001627-56cb679a49a3568998d5fc0473d00a1c.npy +02992529-67c6c3db87a1d72b7b8e0bea6a77fb50.npy +02958343-bd188c1db4c52a2ac35f22936e5aea5c.npy +03001627-cb6ddcf169bb7a0aa9bdc22a1e02e82.npy +02933112-760d765845cfb99b770ba9dfcb1fabed.npy +02992529-ba21b515df2f8a8f19db431d2a67219.npy +03636649-4aba50849f4d24d7581fd19c35a5c8c.npy +04530566-e16e0925ab21f2d3a45eddb1d745bdff.npy +04379243-7d3fc73ccd968863e40d907aaaf9adfd.npy +03991062-28d39c9673775f601a3b47d6d0918049.npy +02933112-1f610516a159e0ce8916d0991ded06e.npy +02691156-383d7574448bf7f235fc197bbabcd5bd.npy +04379243-8662bfcaec06798ac46037df6c915494.npy +02958343-523673c5b3c12ffcf2c89d2df097ef4.npy +02691156-9f5dda6f01bbe29bf810506e9ae2dcc2.npy +04379243-afa91ef326c0309768966ba896bb15dd.npy +02871439-ad4ca1e6d178dedfbdc5348d65406054.npy +02691156-cc630f80fc235ab360c9b6e4c75a092a.npy +03001627-de3e16703bf6581df050758b903e6054.npy +04401088-fabcaa4858df16e35817e30de1dabac4.npy +03001627-9c7b2ed3770d1a6ea6fee8e2140acec9.npy +03046257-9f47c0e99e0edbc8868fb986bc092533.npy +03636649-4c62e3c4f9e46d015da963e90d88cb74.npy +04530566-1d451877c6270d97fe755e3418b63110.npy +03046257-93b1f050ac34adaa7dfe817feb27b203.npy +03046257-8d59e5ca3852b37e4b3c42e318f3affc.npy +03001627-ae1650cc10002a69d65a961d7336a090.npy +03001627-9040047cab148e55e8f8c11a24c52ebb.npy +02691156-b4f41b2faeb528fbf37f38dedb2f1219.npy +04401088-6449223cebdb2dc9c8c3ac9bcbcd9687.npy +02876657-97179a870ed9f12da452d8ffbbc0126.npy +04090263-6454206429467056cfe6670bda9305bc.npy +04090263-78eef5df96ad0496e7c0ece95532142d.npy +03636649-21bca6a33809c7f26f2deb6dd348d3c7.npy +03636649-ff08713d837d87edf2098a9f7fc86999.npy +02876657-f35f3a1ce31850e8b9ca8a85614dd727.npy +04530566-48a037d4699261d3b274bf54d5e89093.npy +03001627-2f4fe1db48f0cac1db573653825dd010.npy +04379243-f856245a7a9485deeb2d738c3fe5867f.npy +03001627-720fd0a6c8cf65e772ee08e78374a212.npy +03001627-e488826128fe3854b300c4ca2f51c01b.npy +04379243-8709ac2f3822955de650492e45fb14f.npy +02954340-a1494210f6774b87b3e0e60b857dde8f.npy +04379243-cca695e66b222f6214038d588fd1342f.npy +03467517-a02ea7bcabae6de39b54ba41102517c4.npy +02691156-b2509e9f52a19466c1006ed55bc1a3fc.npy +04379243-1eab315da8b2588d285aa2b556211c86.npy +04256520-a49f6cfce3d854c7dbbc9440457e303e.npy +04379243-74f407ed9d20d799df0d738d0f301367.npy +03001627-675e25ef07ef717cc8bd7a04c9659f1.npy +03001627-9d7a3b2b7dad91fd611b2c263b5df599.npy +04256520-f125875fefd6a02af487e71bd57b6e0c.npy +04401088-9b91faa0835a0287db45a112fe2d5592.npy +03467517-148ac4fc49e8d965b48e9ff3519bfb40.npy +04554684-38ff66fecee0d18f4f782ac57aea97b.npy +03001627-6b94ccd432d37555fc1390934d948e09.npy +02747177-afe2cc6a31c13eff2b8e1e034cf1c1a9.npy +03001627-5ad4512976afc746564eaedaeaa04f28.npy +03001627-13b6648bdc843b767b5f4d129cc2873d.npy +03001627-b36ec4a65d474384629bdb3bad305eb4.npy +02933112-718f8fe82bc186a086d53ab0fe94e911.npy +03691459-4f53602d946e024af7617b7ba3f8e259.npy +03691459-95268fb7d50ddf77f398d0c5832df00e.npy +04256520-8d61836ca7137a07291d22c7a0bd7119.npy +02691156-73f6ccf1468de18d381fd507da445af6.npy +02691156-89a697d339c01c19452b96e716decae1.npy +02828884-31615e201e29cc11c7f46e918e672933.npy +03001627-fdd8b499294575175f1548797747d63.npy +03211117-55ee60e04ea3816e94accef64b26a3ff.npy +02958343-85f0d4c31c765f33ab91fe0bf146bca2.npy +03467517-c0dc0328e787d4795c0be177939e290.npy +04256520-4bdfbfa1871f2ca114038d588fd1342f.npy +04379243-bd10eeed8d8190ccb041f249f731e3da.npy +02691156-74334440119b4225951971f8370d9050.npy +03593526-e750ae0bc277c1d8afbf399e6f6c09e3.npy +02828884-6ee844357bbc5bddd4d8765e3910f617.npy +04379243-ac7280f9774cd16432bb5d496e1304f7.npy +03001627-8c90c2739c56c5f0327289c00b6dc9ca.npy +03636649-87254ebbd9e57bb84dd6c3274cd9823.npy +04530566-a99574a44a78208981f422b7e55b97ef.npy +03001627-bced50190a0b63cf19fb4103277a6b93.npy +02691156-3baa3ca477d17e1a61f1ef59130c405d.npy +04379243-b2da5c4c116c40a241b160b9adc112fd.npy +02808440-45dbfd115089e0665d107d8487108589.npy +03691459-4b29063d6237b062eabe53d90550c4a6.npy +04379243-242055fadd675e626bf0788e630e3deb.npy +04256520-58d4563bd1114e6a76e9713f57a5fcb6.npy +04256520-656ebb911f3963a81a291b1dd4baf49.npy +04379243-f9d9ef770e04c5772b3242897b354191.npy +03790512-744ab910c5fa999fa036c9ce469c98ce.npy +03691459-84cabb92bca7c3fdf2198539cbd3b69c.npy +02992529-ed52bccead5926dfa9fe1734a6086750.npy +02828884-d0c8a593361ab77d5c3d5e3801c5ac29.npy +02828884-b6ed4377ece0567c78cf4e63fa47661.npy +03691459-eb2545337b85fb987695b38431695f3.npy +03325088-76824ba9aa51eca28ca4aeb5e3b33af7.npy +02808440-56e2c0a605db987e28baeef8b0265e92.npy +02992529-2c1cf34eb46756c1aa8ee930afa0ad31.npy +02691156-f894972de285088da0896c4491cb3db6.npy +02924116-8843d862a7545d0d96db382b382d7132.npy +02992529-610a9f79a2f2faacc43c9f60fcc79b4c.npy +03691459-71c5756cce7bdf8cd6317d54cfc1018f.npy +02958343-35155f8cacf6d72471fc7d1bbf34b979.npy +03593526-6db6c54e6967dfea3481efcd727db3ad.npy +03948459-1c5d487fd6ab7ee88be2a30dd556a09.npy +04256520-16632d002fc0eec9917b96045c9b6dea.npy +04530566-2b7ce6a0492cb7818c0e3fdb2a94c91d.npy +02946921-d3e24e7712e1e82dece466fd8a3f2b40.npy +02958343-37a049a9e32c17b2afe1d4530f4c6e24.npy +02958343-6782126a676ca77d7a04ba129c539b64.npy +03593526-32dc55c3e945384dbc5e533ab711fd24.npy +03797390-1305b9266d38eb4d9f818dd0aa1a251.npy +02876657-f1ae9b2eb551ba466dc523ea4bf73f1c.npy +04090263-57cd6329f163043a551f49d4582a8d17.npy +04379243-487bdb1274b8942ab8e1b99345a5afd4.npy +02958343-eea7f5d02088d49dfdb3c05088c091ae.npy +04256520-932be91adcd83bcf1336f52415aa0825.npy +04530566-3bf976118908886611b5f34c8a675124.npy +02933112-622dadb90004f49fb84959963148f2a2.npy +03001627-701300d51960efc8932a5c2746cd09a4.npy +02924116-6ecb28d595b0afdfd6bb28faf86cc36f.npy +04379243-ab7b56ba63f481af9cd431573238602d.npy +03691459-92658be9ec3307545f7109466a688ac.npy +03636649-d91cf049fa961ccb59f8e31ca87c470e.npy +04379243-e86e665af1e1cae8c2f0a1a44c64aad4.npy +03636649-ce3b5fdadd2b73216aea2f18ee404fd5.npy +04379243-5b5f613742a2d960aec74bea859ea8a3.npy +04256520-1faa4c299b93a3e5593ebeeedbff73b.npy +04256520-388aebe52bbe88757143b902ce4e435d.npy +04379243-817b41f37bc9f022812e3ecbeaae3980.npy +03211117-909bd886fceb080a6facfc0053fedfbe.npy +04256520-d97b919139287ace7842a9c47d0b96c6.npy +02828884-eb7cc5c0c5f8a289d2b12aa6a0f050b3.npy +02924116-43754b18fa7421c57b4161cc118e61c0.npy +02958343-3db034e1e5651f6e6a2345809e2bb169.npy +04379243-5fed2b96d705323b8bec49a2a30e37ed.npy +03691459-b2705ec086216be91a68031139d740d.npy +04554684-62e22f4d1846d8c1fdc6c1669e5c540.npy +04379243-d6410c33772aa719dcafa176d8811639.npy +04256520-6c4e0987896fc5df30c7f4adc2c33ad6.npy +03642806-6ab94ae2ac08a1ff100b1bd8b508fdbe.npy +02808440-569401dd38ba970a45bb0997ddc5cc23.npy +04090263-c80a831394e5fd78f0fea2ee98610322.npy +04530566-a2e82524f7920e12d3ded2945a65f23f.npy +03467517-80f912aac9b3be34e1f2a1daf140ac9f.npy +02691156-df6aae66a8c378ae9029a69fa5fc9ad.npy +03001627-cd939609247df917d9d3572bbd9cf789.npy +03636649-1a3127ade9d7eca4fde8830b9596d8b9.npy +02924116-e4a59aeca9c4b2cbd214cfa3887b8972.npy +02958343-15cc37ac9b3b756acfd826dd468a5497.npy +04379243-831c0e0316d51292df562efe672dd5.npy +04530566-30dcb4eb8ae2163792e235fb0f1931f3.npy +04379243-15985d08df01b47bf0bb193323cf7c6b.npy +03211117-63d4e03c4effa06d6845a0762dd07baf.npy +03001627-8d18fba375d0545edbbc9440457e303e.npy +02942699-a8961c59576972cb57682b709eb0ab19.npy +02924116-ab4c69b08f7fde0d24ac9431afe675b9.npy +04379243-56210576a4afb9cf88d13d4705fa91f.npy +03928116-b3b6d2d1a9ac4032403974271f1920d3.npy +02828884-7c1cf879c84904a4e82028a475156419.npy +03001627-cd9702520ad57689bbc7a6acbd8f058b.npy +03001627-a9422478728741108e21d20fbef78328.npy +02871439-644db4b15b8d63ee62e6dfe993b22a3c.npy +03593526-8da5db60ba2c5f9318694f1cc6fb1f8.npy +04379243-dd0377d3a40b57c360885f79b3a5579a.npy +02958343-616279642d73621812f039db97ce1ef.npy +04379243-5362db12d934a50719fb4103277a6b93.npy +04379243-d5978095ef90e63375dc74e2f2f50364.npy +03691459-a50af511d8cbc8df520f563b6d5bc71a.npy +03991062-31d6283d08bbee76c8a7d034483a2972.npy +02958343-6b896508bdd231887c3c6f82a395b347.npy +02933112-3eddbe968ac08030c59350d819542ec7.npy +04256520-8d98a04f7217d91ad85fd2587ec5bc19.npy +04379243-c621493100ff715f80d6227ff9b21190.npy +04554684-d0960395317be024543213f6b2e6b4ac.npy +03636649-703b4edd4d407a10f8ddacb75f806b29.npy +03001627-18052e6175456b9e7984fb9ec7e40829.npy +03636649-6e2ccf5c1b61a09b6e56ccb2c92c79c.npy +04090263-efb99da78fea81e3534b1adc2aa1709.npy +04379243-98079c9fb39bc736f287ec53a469521.npy +02958343-4024c9fccd9fce80bda733a39f84326d.npy +03046257-374814b7c9a221d6c5f11660af3a01a8.npy +02958343-4fd5c18c1536d65be129fc90649e41d3.npy +04090263-cd60840ecdb0138e4b787ba27f895fbc.npy +04530566-54b6788d413eb45bf6b4f9d652536b82.npy +02691156-ddfbeb997ef83cab884a857d19f7439f.npy +02933112-2a5535f9e24338c7107bd4405fb99a1b.npy +03001627-eee08ec7de613898567232766992241d.npy +02876657-7446fa250adf49c5e7ef9fff09638f8e.npy +04225987-4f409f31b182075511b6d7dda2bf041e.npy +02933112-36bd3f2daa4ed31a921dd903dd0b8b17.npy +04401088-34e36249166b8c6bc3f912172873d52f.npy +04379243-938c5e8ec8703d5f7ff6ace05b36a5.npy +04090263-b8137473d975e1a23111ffeb58c3d257.npy +04379243-c5fc106c1c426fd1db63c1c69fa4f81f.npy +03691459-1e82e94cf9f6bda8fe893ed5dfb6041d.npy +04379243-e7169243daef074dc82dc2efb3363de1.npy +04379243-b96a360ca5a86bcbc48d90eef8384210.npy +04379243-63b6ffe53e027e83aa49ce7283f547d9.npy +03325088-6a8665f6cac2eaf73321831d2245cf06.npy +02933112-1715965e2e1e33e1c59350d819542ec7.npy +02691156-b19771099e1d3cd4d86ebdaa02a63c4b.npy +04379243-9d7a8d4c013bdc8321cf7471b191cb89.npy +03001627-6a254cc3d81881c91a3b39b07e4b3d0f.npy +04256520-a3ec914d44cd2bd8498bd5a555c21b1c.npy +02828884-c0976144b3ec94381076bdfcbbc20a9d.npy +04379243-fefd88656d9d0d2d82e6c3a4e742651d.npy +03691459-63c4583afc2b82237f299e32f8ffced9.npy +03928116-417deddb98e00babb1c932b2548fb93a.npy +02958343-164c8597d8eae2f6f21c3b61f0b564c4.npy +03001627-33334eb57a9d7bbba19d006f28e25379.npy +03211117-e85041124d09cb07318461dc09ee739c.npy +04379243-f4f168b88686872f785f45147f3e474.npy +03001627-2b7335c083d04862ca9c7c1ff5a28926.npy +04379243-77f6685f2df21522bc31aa2bac13542b.npy +02691156-513c955bb46d739683651cbc8e49e4f.npy +03691459-da2fdf0220908ca42744bf8869518694.npy +03001627-2f7a68f4a75dabd41c8c7b57a94dbb2e.npy +03001627-55eeb952519ceb87c3bd24f986301745.npy +04379243-9768599990ec4b54575fb26548334725.npy +04379243-a44a0a014b0c1d60609fb05dbd8681bd.npy +03001627-6534f04a1c349a3c8c6540fe6bc16d6f.npy +02933112-86838c0e4486ee7a8369c37b40e82efa.npy +03001627-65122866840aaccce3d8061f5c8a6fca.npy +04379243-3822df9afd06c2d875a82b88fe6e733f.npy +02691156-8c344cf05ad1bcb7709f5d258bc9a906.npy +02946921-637006720b7886e0c7a50f701fe65efe.npy +04401088-3dac1f92b3e13977d19f91734fdc72ea.npy +04379243-fd5c4da3a081cf115ec69be1b6d2571.npy +04379243-62be982d61ccf61d92e675672199574.npy +02828884-e9a9c499e74c2989d4d8765e3910f617.npy +04379243-d5deca423faade89bb814dc1a3fcda86.npy +03467517-2295ad16efd16ef5fd5758ca36056ece.npy +03593526-c8d8974642d4e88e906c240b881af04f.npy +03001627-e6a8f28b36533f8239b3360f500ac52a.npy +04379243-8504c3823e5485f8951c1fffab4f5807.npy +04379243-88e9d1f8c3f988e62f21cf17406f1f25.npy +03001627-8754831d577cca437c23ad67f25bcfd0.npy +04530566-bf0084fbcc74d5632754043d4b10740c.npy +03001627-d8f3c4bf9266150a579147ba03140821.npy +03001627-8b3619396de4df10db8860d0872e9c55.npy +04379243-2b7fd6106236d935b516de42b9c9697a.npy +02828884-b5b52ba71f6c3c67ad5067eac75a07f7.npy +03001627-401e07ff01b1bfe64d85e9aeb23ad69a.npy +04379243-ed2d5ed8ad10f323593ebeeedbff73b.npy +03691459-115354ddf0cea683c9603934b9e8f5dc.npy +02691156-1ce5b9a79420e946bff7790df3158906.npy +02691156-b3d034788411421019ba010ddb4974fe.npy +03797390-414772162ef70ec29109ad7f9c200d62.npy +03624134-13bf5728b1f3b6cfadd1691b2083e9e7.npy +02828884-6b262d977ea93d23ba6cf6cbb9f4c2bb.npy +03593526-af4c5fab6584a6ead5cc6270d226b60d.npy +03636649-5115f9a3af3470ddfcb8d8c6d4df8143.npy +02958343-ca85286b0ff3b33b16abce8cb03e7794.npy +03001627-38e672f611588c0546863a778f871cc.npy +03642806-22367d72d95e021aa458f8df8b43cd95.npy +03691459-85bbc49aa67149c531baa3c9ee4148cd.npy +04379243-2fd962562b9f0370339797c21e8801b1.npy +04090263-65cc9c9436e0b2c8a50ef3fc203c6ba0.npy +02828884-a31ae6a0f58526af2056b4bd5d870b47.npy +04090263-6acc9c34a79f98d0ff790997f2048517.npy +03001627-3d697c411b8bf8a0df6cfab91d65bb91.npy +02818832-734d564442cc75472b0c00d36a59e875.npy +03691459-da706fc7141b22ece029fab54b6cfbd.npy +03046257-5586a1f6745126e25e0d2ab0e6ad9dae.npy +03928116-3e7cc9b8333865239ff9560d055ab12.npy +03001627-db812fdfacf4db8df51f77a6d7299806.npy +02880940-538db91266f2829bc0f7e0e05bae6131.npy +02828884-9c1a78d3846b8137d839166e2dcdb427.npy +04090263-bc82cf27b55cdf2ed735fa1ab17311ec.npy +04256520-5ec9b56623d25cf1e7d9f0fed41b005f.npy +04379243-d722d42dd739e2a35e0bc0e32d71e297.npy +03710193-e4300f07c82ba3e9d5cb6d178687b980.npy +04379243-d6b61af7935d36a6f0aeabfdcb4e1dd9.npy +04530566-9a6b9049576b97649bbc565383eee97c.npy +02933112-3761d6523fb9d7a73f7e27638e63d848.npy +02691156-1998ee1bf3806b05818b286e41cc1a3f.npy +04401088-177a44b5e36fe9856e10bfa9f3e32b96.npy +03691459-556eebe71c16acc9e17b9e33c097dbff.npy +04090263-8c0e6b3a8ff3e1e75427d4172e3eb61f.npy +04379243-b11f985f0b3aa23379368d1198f406e7.npy +02954340-89717260f663fe13a9d8b37b5c73935c.npy +03211117-6dab3e32b5cb52f1d67173c00f9e1676.npy +04379243-2afb64e4868b6dcb8775a2d8ffff3881.npy +02933112-401960cb8526894f4b8710a3469971b1.npy +04401088-63e84b82309bae535b6795b7faa3170f.npy +03636649-b3ee8dcfd2d814253e793fd9530521a8.npy +02924116-7143a7cb46facddbe550942ea36e5443.npy +03928116-ad905de0c46408bd6e4af8307559a06.npy +03001627-e6daa4f9485362aa37ecff2686b754f4.npy +04401088-b140bdd32b0287a64a21fc95f845c2fa.npy +04256520-d7220a39bcedbb89a14c5748cc240cc2.npy +04401088-521fa79c95f4d3e26d9f55fbf45cc0c.npy +03001627-f68b7c3a1ed7506bedd9ab1253e1a9c4.npy +03642806-5be7aff08cd8dc37253cd18ba2e1c61e.npy +03642806-1d1947a3104bdbf4752cca7e96f0bf86.npy +02871439-702b30de33018393e3c9c743e6bdf782.npy +02958343-4836466e85175a462c4cef95ae3d6c50.npy +02691156-1c798f3e8bcaaed6f34c3a85e57ba71c.npy +03001627-99c8513bc738a21d440d6814caa3115e.npy +03211117-1f6cf74de609bae7f5542066243014cb.npy +03001627-de2bb45b7e200d6916d102513d0383c0.npy +03046257-6e67cbc95bade487603bf63caa67eee0.npy +02924116-b9e51da09e8bac24fd9cfa6c7f5305bc.npy +03001627-4c86a55673764f05597976c675750537.npy +03001627-eeef39917dd113e053624ac0db0f7e5b.npy +04379243-57c935da692d6e4c27c29012942420f.npy +04256520-81afa90f6229e7b456cbf78e1e89022.npy +04401088-136ef91c95ca5c2d4b9a4e1a888c5f59.npy +04256520-9abd7abc15a5f7893eb520ff7cd241f0.npy +04379243-5ad5b050fdf84825ec7962e39e3d3af9.npy +02828884-f48b666e87f0c31f43cda5120584006e.npy +04379243-a42a58b3fae9ce5054f5039bed03ee12.npy +03046257-d8e27d8d60a9a0c091aca0a9b5efd2ce.npy +04530566-df73ce22935c8081b04c44c0f84a941e.npy +03001627-77d71ae4116844e02025d98fb9de28cb.npy +04256520-e3d3c8dfcb19d920cc3e9831f31c9164.npy +04090263-49a566dd82ea542af026df30a0cc38a9.npy +03636649-df908dc58159c82b1b3ffe2c05ec7aca.npy +02958343-6a758f23f6dbf27923978edad4629e6d.npy +04256520-a126dacc76977e063755f577b497208.npy +04256520-543e257122d8fcfacdea6af8dfcc2b18.npy +03642806-78f6f380548e0f7d3fd8284eaee3b0fd.npy +02818832-d61eeba48577fcd511891d07929500ae.npy +03636649-221e2caf85f9bc5a2f9aa70de681f2c4.npy +02828884-22c5aed5cfd1ef997666aea996e0bd15.npy +02828884-abcb5dc91337f47682db9fca4b68095.npy +03001627-681b792d7bc9fdf8305e886266e302e1.npy +02828884-683ddfb4cf9c8f2883f21c04f5e0acd2.npy +02828884-a2678cebeac0a8c9cb2a965e75be701c.npy +02691156-2a966a7e0b07a5239a6e43b878d5b335.npy +02747177-5f2cdda3d519b5a25e96e67cce8b41a9.npy +04530566-73e6d10ad309d831ddb86907b4b5f05d.npy +03001627-9e15b5ae461fe0318fcdb0fca07ec8af.npy +03046257-354a0b83e35282843aab6d48f7ec1b67.npy +04256520-f100212c5848f7d3898b4cd86bfa936c.npy +02958343-8aa1b368270797bdca92a4cdad802b45.npy +02958343-654bf6800566c8ed95b02c654da6c998.npy +02828884-b3b8b909ff02f03ead5067eac75a07f7.npy +04379243-eddd80bdb6f6c8b48bfc6c6704f4dffd.npy +04256520-852abac2613701ed7de67b59dfb031b.npy +02933112-5feaee9848b44d44824662341ce2b233.npy +04256520-e74d866f44f857e77b5d58e18a4bdcae.npy +03790512-a2ee365a26f7ec623228b702032404a6.npy +02691156-72985b83dd9c31955dcafa83e2819ac7.npy +04554684-91cec7275a9b3266a6eaed098287ffd3.npy +03001627-690f208bc221e05d6c891822a43c9279.npy +02691156-cdd4dc06cea48b5faae529ab4a75c4af.npy +04256520-c708f4b2649d5b2c3070413801574f.npy +03624134-3851471620390fd4f43b696124fb3bf.npy +04379243-c0de139953efa6ea2b151d8b52c53b90.npy +03001627-2d4efb02b4369af2473f10e6caaeca56.npy +02933112-aa249df1e594036f730fe631274bee9c.npy +04379243-db09ccbc677e2afc9f60147421585c0d.npy +04379243-a656b27fafb027dbaab26ebe15e9175a.npy +03046257-471eff2ad3d20a6f329dc8ba1de916ab.npy +02871439-e517dc5a967361c3a570c6c691c987a8.npy +02691156-4bd5f77521e76e6a2e690fa6dfd5d610.npy +04530566-25f20d56a125b4028d8e8d98cb30b332.npy +04379243-b48d333e39b8aa1c663191fd557d3a61.npy +03211117-7185d52bc9a5425e2f84cb7932f866fd.npy +02958343-3f18c23d7628966848368c1a2f71c5f3.npy +04379243-18635aca8099ec5a3eec26c23f5bc80b.npy +03001627-6d3081bce72521e088e9c1fdc7b9075c.npy +02946921-a087f6b5ea424ccc785f06f424b9d06.npy +02691156-fe0c4db38fb6399990b1d6deb98feec6.npy +02924116-88520c248bb0d53841cefd10ce5d6cc0.npy +02828884-f264c4d430891732d97248c4337f8439.npy +03991062-c16542905741bce9a2c59a4d90e63212.npy +04379243-17e773bf0007544ce76bc197b3a3ffc0.npy +03467517-93744e9777361d001082f2ea630bf69e.npy +04401088-f75cac5b112f14002c32dcd0becbedb7.npy +04379243-7fa4f9f5b204af31e95cd0dc8c2f0e83.npy +04256520-b69fd1046deab785b3a010e5a9dcf3a8.npy +04256520-59c32d74e6de63643d41bddf307a46a8.npy +04379243-f73cc62cf8ca9d954c7384dbb75cab0d.npy +02801938-6dc3773e131f8001e76bc197b3a3ffc0.npy +03624134-d3ba7967cea5550405f236096897d.npy +02958343-718c595ae03a78208b58723318e7adc2.npy +03636649-4c757abf44253f8360ad823977adaa23.npy +03636649-16ae2568c9e62681f8b8d4a282992be4.npy +03325088-51c0b5604dfebf537fededae3a8b5db1.npy +04401088-7f5b9c8fdb46cf7c562c8e1ac545ef78.npy +04090263-d3fa347a5df7d6207969ab08647690bc.npy +03001627-8538245c2d93c60864c85287e21825c4.npy +02924116-6bba759a037998851bc2b9eaeed055b5.npy +04090263-9b8eb0dfb6dee992572dba079470b351.npy +02828884-1da4abf560002490391b7a189305050.npy +03991062-57202d9819dc44c67d8ecc181daf1385.npy +04090263-173476ce3541392d735fa1ab17311ec.npy +03001627-6c25ec1178e9bab6e545858398955dd1.npy +03624134-be91489dcbb0ce3f1acb5c3b0f893db.npy +02958343-c5758de60af178a11922758510ef0672.npy +04090263-d0eac7ba7e964d72cc34b900bb2492e.npy +03636649-64fe64c30ac05282443f70ad172f4dd5.npy +03337140-ec6fefa43577c689670bb97cf787128f.npy +03636649-13badfc11837c16cc01e0156f398b4d2.npy +02876657-2d912be96504cb8cd5473a45f1da0225.npy +03046257-e5b583b0cf478984d781754d41e2576e.npy +03624134-2fc5036e98cbdf4953cea6a99b7d6232.npy +03636649-efedd8c990f9926c48d945252c13120a.npy +02933112-568a719ffacc4e12f648065fbcc749bc.npy +03636649-69429d8ffb5009a82060e7309fc3fc6.npy +02747177-1d3a7ed6ff0dfc9e63b2acb037dfbcde.npy +03948459-3a8478c9f2c1c043eb81825856d1297f.npy +03636649-923c324c530e9fc412060d1ff2024b3.npy +03948459-a7a340a901d63486260a770f90456bf7.npy +02958343-633dd9755319ce369dfd5136ef0f2af.npy +03001627-e32ee21232d2d5604747ada1cb39a749.npy +03636649-377df6e7a3d84edfa123ce0dff5bf4e6.npy +04401088-eb58b011745519194fde46457697d80.npy +03001627-7905bbf9abc0c264f3443b22038d340.npy +02958343-6026684ab31d567328044fe9244db50a.npy +02958343-b40436b4639e80b8d61b6a34f3fd808c.npy +03001627-ac03fd26e5c499eafbe6ed8d24e16d28.npy +03948459-ed29dd43ad28f042d1987c07c912c6e1.npy +04379243-9d1f337286e7a4d39aabd1d2b22d025.npy +04379243-2e2894138df855b26f88aa1b7f7cc6c6.npy +04090263-8b5cb45c763602a73a70335e147b440b.npy +02958343-453164c9199ebec7e80b7eb39c475065.npy +03001627-4fa8eaacaaad472819fb4103277a6b93.npy +02933112-2d13507d53d201cfc59350d819542ec7.npy +03467517-648a820e550bdfd093f0194265a9746c.npy +04379243-5d59c0f64642450911794406b17d66b.npy +03001627-606bd97f7337bf39b40f0ac0fb9a650d.npy +04379243-7b356bbece2dd658278d386bfa54545.npy +02958343-4a536a6a685e08ea678026e3eac5bb0a.npy +03790512-9f9de88a95b56660b37378f3c85478b4.npy +04379243-1cf7bee4c0dad464c3bd24f986301745.npy +03001627-b10798977605fd017a4de8972b988aa.npy +02828884-ff8f8d280de66226d2b12aa6a0f050b3.npy +03691459-b4cd1e4296c3e9b55ed2ad7d2e018058.npy +02924116-4233caa4bda5d30f481aa8b5531c68a9.npy +04379243-8cb6a2e9ba365c94593ebeeedbff73b.npy +03001627-797b37d3462592b9c8687ff9b0b4e4ac.npy +03001627-5a5b11daa1b5344fb516c05d046e8e45.npy +03001627-2433f576edbb538aae8c9d3b8c4b9bc3.npy +02958343-b09376c77d8fe18eeaa60d48e24f18e0.npy +03001627-3925bf96c05c49d362e682c9809bff14.npy +04379243-50b6c4c7681aa3fcbaf2e78ed413860a.npy +03001627-3c8362c1e57c30d7e6c5cd45aa112726.npy +04401088-d72b00ba0cbe10a1157f4a560c24391b.npy +03636649-ee9cb649ef64105b62095c48c7bd5960.npy +04379243-aee3dc454d9b5af0dccf03d91dc58d38.npy +02828884-e01f988796268414ad5067eac75a07f7.npy +03001627-66c9a5aa7b4e528a290d57214c8512a4.npy +03467517-5b7fcd85ce6fd1931377689fa4e4b2d6.npy +04379243-725f69c0f29b712e8c6540fe6bc16d6f.npy +04256520-fd124209f0bc1222f34e56d1d9ad8c65.npy +03001627-fa89a0401873e5a6bbc7a6acbd8f058b.npy +04256520-a513bc9521717f2593ebeeedbff73b.npy +03642806-5508b5ce2820e4c36efcef06c0770d26.npy +04379243-af53fe05e692a7ea2e09703471e30fff.npy +04379243-87ca3e8e37367054dcabaa2ad147fa73.npy +04379243-400393a56fc243c442c39a4fb8d01418.npy +03001627-43c99f65e19e5c657746f1e767f87dbb.npy +03691459-c58d1c25553a224ad9d271f9da38313c.npy +04256520-7d532887fcd3aef82ddd352288e7672d.npy +02691156-9e57a7d6a7f488dfbd46d022fd7d80aa.npy +02828884-1d9270d0708fb8a1262707c3863d044.npy +03948459-52a1ca1d9bd900ba3ffeeaac0d1e84d4.npy +04090263-5a86afb38048ecc6b2c8bb96250e4a0.npy +03691459-72da46839789175eb6ba1e8b5cf30e.npy +02691156-a5639c976e677ce6e719b5362fe06bbb.npy +02933112-54cbe81983534dc153b10fab8d9d7b30.npy +04379243-2d96d4929d945740b1e23c7675c49239.npy +04379243-ddbcb5a22a0c3aab35de8f8daf95ff3e.npy +03001627-8f668f18d84a6960b27c368aa9b96968.npy +03001627-48f2c6ee2c8ea7538cb22acd3160c793.npy +02691156-c9ad8451915ebe6bbd46d022fd7d80aa.npy +04401088-7bf76e92b684d32671ab0d8014490a7d.npy +02747177-60b4017e16fd9c4f2056b4bd5d870b47.npy +03928116-35732cb2a41f413f645da737acb3ce13.npy +04401088-a9d358ce2d54d95e54c7ab6aa5674ccc.npy +03325088-efac508cef643820979c556124bee033.npy +03001627-55b00797abf243c3cce5160f0c502ac3.npy +03636649-53bac55dfe78177282889f551cb32a81.npy +02828884-27eb79ddf26fd7ac7898580cb9d16864.npy +03001627-893bc32a68f387b0b675b353faa5a26.npy +03211117-1df7bf502e4b0e8647dd811b692e315a.npy +02828884-8bb2354519a2ca276d9eb2ed02ef01ed.npy +02933112-19492e2263ea82e4da5feafe6f1c8fc.npy +04379243-1eece111c9bc0a126172e4028919692e.npy +04379243-31551fca6e4c5d8e80ab58c152cb7c44.npy +03636649-b6d6a772087d456a3dfad56d2a4eefcd.npy +04379243-b36ee7cbb41ad82c9b11da89c22111dd.npy +03001627-8cebf6dde257cfc591a2a5174703986b.npy +04379243-2c6dcfd1c08950554b3c42e318f3affc.npy +02691156-337e7f2c3745e07789d7e2c40a194e8.npy +02876657-d4a8a5243b976630e3eacec6011567b3.npy +03085013-6cbd981e310a0f09a8107a4c74d58321.npy +03790512-40d84e407c46e8d8b31e74d456742c7.npy +04379243-b117aac2e13630bb5d23c9bbb429abf9.npy +03001627-cbf18927a23084bd4a62dd9e5e4067d1.npy +02691156-95e589163afd0a7a609e2d916fa0da27.npy +03001627-bcc73b8ff332b4df3d25ee35360a1f4d.npy +03001627-cace287f0d784f1be6fe3612af521500.npy +04379243-58595b39bcad6b2fad5067eac75a07f7.npy +03001627-ee5ee3f6759aabacf2f43e6f841bd32b.npy +02933112-3b5d7b7fb89b178d50711e66b0db6ed.npy +02933112-b235be00006f3c03e6513d84422cefc4.npy +03001627-fb22d2e3174ed0519fb4103277a6b93.npy +04379243-6c413dd8728bc004d22730b0728b2fc9.npy +02691156-945b33ed9d6844591596c26b5af806fe.npy +04379243-26d174935d283cfd4ea7ef03cbe21992.npy +04379243-130d574de3f9d7e4c3bd24f986301745.npy +03001627-ae02a5d77184ae2638449598167b268b.npy +02958343-34211d29d94cbd52b7c4f0665aafbacd.npy +02933112-95bda55d633ca1824da5feafe6f1c8fc.npy +02691156-dfed744828fceb4d28cd0e56fe42c08.npy +03636649-2a39d5ec8856dba0fcb8d8c6d4df8143.npy +03691459-5bd42cdbb91db055f7e08add4085d009.npy +02691156-194098fb0aefc4a0666bd6da67d3abc2.npy +04379243-7f1edef2e2fe5aee33ed950c745c5ef8.npy +02946921-19fa6044dd31aa8e9487fa707cec1558.npy +04401088-a2dedd1d1369d4ae25bdb70a4d3731d4.npy +02691156-4e66465abe540ee326ccedfb0470de8f.npy +02946921-ac66fb0ff0d50368ced499bff9a86355.npy +03001627-63687e533c0b16b6868fb986bc092533.npy +04401088-7c134eee62290ae7fd130953acb6f543.npy +03001627-1b5e876f3559c231532a8e162f399205.npy +02958343-edbace6013d1c12ae9e1016860f17753.npy +02691156-4cb164f1fce7849762b600da24e0965.npy +04379243-40ff8ae39ad13d014a873bbe35452b88.npy +02691156-46c259e87609c54fafc0cc47720c0ef4.npy +03691459-40efb91680a2a39476ec75ad1a6d21e9.npy +03928116-45166dc50bbf0315ed1c1c47436c7974.npy +04090263-fb38cf43741e1189396ce275998d65f5.npy +04379243-b94ea1b7a715f5052b151d8b52c53b90.npy +03001627-b78fb2778adeba267c26dd76207404f5.npy +03001627-8cbf3d97df981d511fc6bd4aed49cc41.npy +03691459-c8018ed73c5f4087eb927391bdd6c8e8.npy +03046257-636e572331f872e3e7c7920f6a65a54d.npy +04379243-cd6f5c39cdf1b57a93bf4c26a8803fd4.npy +03046257-dcfc273d2a1fd128890f8f44c05e7d8b.npy +02958343-dfa6e60e478d5053705278f93079331.npy +04090263-b266dfc3d3d3606dd281b302c458427.npy +04379243-85a20e4f7fc9256eba9cbc5d66bac4b8.npy +04379243-b3cf5b09372826af658d908a2254f194.npy +03046257-a157e9b6449d763bab2f5d1a742ca172.npy +03001627-b8e4dfe08a43badabaed5cf8a752d243.npy +03325088-1f833904413559adc837473125b7231e.npy +04379243-da3e68c20b832c47a3b06ba374e12b77.npy +03948459-c693ffa50f62a2825fca1d021553f9e4.npy +03624134-d6e9e4e07bafca0fa37f3fc191551700.npy +02828884-c273ce2890d74ae18cca710901c2e97b.npy +04379243-9c44b336e78684647523c0c037b61ec6.npy +02691156-a828cbaf4b3bd253e163b5a191403a0f.npy +02828884-9fc5473602fe0f595896bab37ddebe7.npy +02828884-c2b940127ae286832d07d128adae16ff.npy +03001627-671a43756d51eb613d4c64859ad102f7.npy +04256520-a3970706133f033861b5428f30b376d.npy +04379243-5d63f11757a433b914038d588fd1342f.npy +02691156-66493aa4ae7dbe40b6b87e72ead132ed.npy +02958343-324434f8eea2839bf63ee8a34069b7c5.npy +04256520-c43bb99091f5a02cfd60059ad8523f1a.npy +02691156-30acfedb688a62e72ce638efd383ace8.npy +03001627-bbef7baa438869dd52bee19dc0453f5e.npy +03790512-329e47988e39df1b8c1912cd8631ab82.npy +02933112-275b26f0555e85acf858430284b28022.npy +02958343-7fd2f1d8342aa0acf3aaed7e86215c7b.npy +04090263-73e0ab2e1d0ea752bc6e84bc30e573cd.npy +02828884-616833ef9cfdacba583f5c4be082f8f6.npy +04379243-3e0ae5d25ad60ea285d624cfcd9a37a7.npy +04379243-10c0eecb17d1bac64b3c42e318f3affc.npy +03211117-99ab7f145618ec841a1272c8e47f5670.npy +02691156-4b0f44a76ef66ec9491bc6c980bcf9e4.npy +02691156-8f4416cb67c3807bcf155ddc002a8f77.npy +02958343-eb1d1ac801d6bafbf949c235bf4afe6e.npy +04379243-b11e0feb428f61edf008d8a3590fb522.npy +04379243-83dcf79646ad3f0cf4b6538438a0b930.npy +02924116-a23ee9c160122941193d7855ecfc1bd3.npy +04090263-2bab6ea5f35db3a4aca4b8a57632be04.npy +03001627-2e079c4e7bb26dce9d1cedd9b694fb2.npy +04379243-e52f7c8abd860fb923fe3501bb9e7193.npy +03001627-20ae4b27e86521a32efc7fb40a53aaac.npy +04379243-44295d4ec0d1e1ae4eb7315d59c5142c.npy +02828884-ee50d76492226837926fe0a4cdbf03.npy +04090263-3919b70a16c630f9d735fa1ab17311ec.npy +03001627-4c9b6e0823be25ae52bee19dc0453f5e.npy +03001627-4c6c3346b5d0f071f4b6538438a0b930.npy +04074963-58156300ed442f981047874d2f3335a.npy +03001627-5aa2a53207ff556d473f10e6caaeca56.npy +03636649-292f1f97a543d735dedf3c967c85981a.npy +02958343-487ccd6e9af920e7a7fd25564c2e888e.npy +04379243-11103f4da22fe6604b3c42e318f3affc.npy +03642806-8a4c725dc347e1106ec6e4721582ad38.npy +03001627-b68180bfde45f5a7e450a02d8032dbb0.npy +04379243-8502520f19688aaee12186cc8c5022c7.npy +04401088-2d5f1105a92045c8af0fa49592cf7bc7.npy +04379243-89552ce12717e70d40ef1c8b63a628f9.npy +02924116-a4ea8e5a6c096784b129901f80d24b7b.npy +03001627-6e46e4cce527abc114d449899f34bd9d.npy +04401088-638695025ca04d351d57a73214dd2a04.npy +04379243-72e0f3f2f8f8fcf12f788f981151c5d5.npy +03691459-83f72a05685b80bdc7c51d4ea74651a7.npy +04379243-dbb5de72508efbbbcad4c3cef7575bef.npy +04256520-4c1ac8bd57beb2a9ce59ea70152320fa.npy +04256520-ed6704f132eebc3ef13ce777d031b4b2.npy +04379243-437d7550e95cdf39c0ca344f487323e.npy +04256520-47da08d9c7cd7e104b3c42e318f3affc.npy +02946921-d801d5b05f7d872341d8650f1ad40eb1.npy +02958343-61251733434b9b0c15a23f2b45e10de5.npy +03001627-72da26fc9b49ecd3c3bd24f986301745.npy +03001627-b98b73f29673d7fb6da16f7df2c9a5b0.npy +03001627-914c92a6b9d8e7956160139444912022.npy +03928116-6c084236171a186dcf9cbd6252de4730.npy +04379243-d45385e0a60f71e1427fcd6e404d0cf5.npy +04256520-d5931526b56b157cab610b0c94236463.npy +03636649-efc262f7c8bc9fe66b1291e0cfc0c93d.npy +02958343-b47070a91102db1abe40bb45ea25a041.npy +04256520-8b3b675ddd2305b98eca6e74f79ccd04.npy +02691156-a2712db5540766cdf6a602e459585636.npy +02747177-6f77d79dd74a31fa56f6fc4b4ce1db04.npy +03001627-cd9e22cfd389e5d9d330ae3d046a415c.npy +03001627-5ef4db0419932fe12e5ebb32d8476df8.npy +04379243-f563e9cd92a0dbe5a07b1c1d0ca9cf45.npy +03691459-22e37482f8499fa53a081cb8ab2c8e61.npy +03001627-6d5c6eee9e25b314b3c42e318f3affc.npy +04379243-9ebaa0f7c3a7229be1fb37eefa671b59.npy +03001627-4a5332f5aaa3144836b0f2a1430e993a.npy +03046257-ac4a052a9d8f0985276206fae5d3c473.npy +02933112-2d7bad601f84c83686d53ab0fe94e911.npy +03211117-9b1362da6b7eef2b290d7f93e1252a27.npy +03691459-b5a2b8202014ae157a3d98bc650d077e.npy +04379243-c8cf1c77bbb79d214719088c8e42c6ab.npy +04256520-6b25476464cb4934e039576a17a0737d.npy +02691156-e037cb87e6cdcd76df39601c41fbe0ba.npy +03001627-8590bac753fbcccb203a669367e5b2a.npy +02691156-2026699e25ba56c5fd6b49391fda17.npy +03337140-89595cf7ef0acc6d57f3bb43ed044708.npy +02958343-e00fde4225d166b1ce929ad7e848003e.npy +03797390-d46b98f63a017578ea456f4bbbc96af9.npy +04379243-dbe17b86d79a24f1ae96150e4aa362f9.npy +04090263-8c7f0954c7bde4edc8a5aac636aa172.npy +04090263-5a420b1aff4cbaddeeda694c82280de.npy +02958343-a750b467d629df3e2268f50ab9844c64.npy +03691459-460d5cc9d09ec59eb34ed614d2670aca.npy +03001627-8363376d07da8aebb76e29c9c43bc7aa.npy +02924116-728bbdd6880278e51894d116f1c652.npy +04379243-221812e480905c5464810cc21086da42.npy +03001627-858e98a193f0d82f1a5838237ecfb290.npy +03001627-28fad854838ac444e9920dbaf13176cb.npy +02958343-f655d1adac9c96d53b05c2ad25b4380f.npy +02801938-d5ec4fb3e3a5ff31dd84b16d3edceb0b.npy +02958343-202648a87dd6ad2573e10a7135e947fe.npy +03001627-590d04438aeffbb58f447453fccbd9d3.npy +04090263-608d83aab75edf3c48a76f6e8e0499a6.npy +03001627-bc184c3cbe3349b19fb4103277a6b93.npy +02924116-2060f00f9a4f3d7437277701a400254a.npy +03691459-d97a4771b9d796a22d1a40e420084a6.npy +02691156-572d374ddb49e77a828204947d78b9af.npy +04090263-1c2fb199540516e2b30eb7cfb209da0e.npy +02828884-3b2ef85bafb7669d35382c4d59d1fdb6.npy +03636649-58483a0c6c6dc7056b1291e0cfc0c93d.npy +04379243-51a2b4db530f383339797c21e8801b1.npy +03001627-30f4c4d94f4fcffaf51f77a6d7299806.npy +04379243-ecdcc12d56c119c5a67f11eba80d4fdd.npy +04379243-b9089b8cf70c95e1f4b6538438a0b930.npy +03001627-554f63beeeaa1ca81acd2074f8939f43.npy +03948459-57b571c990cea8a8e1f2a1daf140ac9f.npy +02691156-2c9331f57865a9d2bd34bbc5253f83f8.npy +02828884-7a9a3abadf052b3bbc2f63672224bac8.npy +03001627-8b45782142fe42b02314deb821327685.npy +03001627-364a43c9f94f315496db593b49da23e5.npy +03001627-a5a2d09e5384237869513d0907f19c8f.npy +04256520-fa563ce2209de1961f98c0761af40e04.npy +03001627-b6e744f896a202c119fb4103277a6b93.npy +03636649-6a6fac314f0f295047a478fc5fc970de.npy +02691156-4f8952ff04d33784f64801ad2940cdd5.npy +04379243-2823fa4b1076324dbe0367f0d905ee09.npy +03948459-2625d5e4ee0a349844608b3255ca1886.npy +02691156-d8719b491412ea0bb1cb87d703a74b6f.npy +03991062-2ac7173684edbb4a6d33c50a0ba3f8df.npy +03001627-d9dc32f36e03d9f5ea65a95e759e03d9.npy +02691156-c2f3e3a227aee9ecca8607f540cc62ba.npy +02828884-afaaadcde1146dc2ad5067eac75a07f7.npy +04379243-4380ce2f9c06f92744175b4dddf5be08.npy +03691459-be5e0dbd5a8a589ca04f967bd94443cb.npy +02828884-646caeea9d317c9581faebbdea6bd9be.npy +02828884-abc01ead2541d73f97485073216729ca.npy +04379243-e39bfe8848fbf76540a98a90bd0efcca.npy +04256520-c67a9bc21455b0d9c018b720578a03bd.npy +04256520-ff99fb65f116dc1b24e1cdbdc9a22905.npy +03001627-d8edf163d5f87b055369e32fb818f337.npy +03001627-24fdf6e5090bc3442370db05a58bf9c6.npy +02958343-40e7559b88089f4ba7fd25564c2e888e.npy +03001627-dae6ba7440a71e5152470de2774d6099.npy +03991062-4a53c4af240c562537048583edf8ef2c.npy +02691156-7196ea15821ad2fdd8ff6111270336a9.npy +03211117-6a5ff378aeb44691a3fc5ccb0f902d07.npy +04256520-e7eb561c782fd92163d467b618e97922.npy +03001627-8f248770aa0b4d41e6fe3612af521500.npy +02691156-e3aff5ae3e8f2a7c4c2c88971423d0be.npy +04379243-69adc52c58477affe074517a246f1e65.npy +04090263-ffe08785458e09666314c3b6a3a65519.npy +03001627-8af802214afcb014bd15bdbf03199e85.npy +02691156-b58058567bfe6976b30e3fbc7205ab54.npy +02691156-c2352a98200942e5b39b85af85a55aef.npy +04090263-8d5354101880490994deaa9fff391d41.npy +03001627-7af12c69626b5c1814038d588fd1342f.npy +03691459-93c5159d17de18f02899849b3f61c3c5.npy +04256520-2b49c5bb1f8f8e50febad4f49b26ec52.npy +04379243-96c2ac95683fa21d80a13a8344996270.npy +04379243-70f90f5959de7752c0f947750540fb22.npy +03001627-5e44499940fc3dbe57a847db7547c1f3.npy +03991062-81591729f0bac11821fbc1a8044f930b.npy +04379243-54af9e8e80a0030c42c28aee4f9d8a89.npy +03001627-6f764c190cdf1629307776da88d1350f.npy +04256520-c805dab667ee341ca3ee83e6cad78356.npy +03001627-f294980dc63731dcd0ad32b8d8cec005.npy +03001627-74b3e4fa65510952e6fe3612af521500.npy +03948459-6119e9b1c0566e749f433921788191f3.npy +03001627-798fc5fd5faf3a0580067e3fdc6db24c.npy +02691156-ebb5a048015c13cd35fc197bbabcd5bd.npy +03001627-31dbef39a3c46b07bb8e07e9ebf0b9cb.npy +03211117-2ddb8a9c6a81f7c1be7e1d42d63ca9f0.npy +02876657-d8021dc9fc9109b130612f5c0ef21eb8.npy +03001627-37b6df64a97a5c29369151623ac3890b.npy +03636649-699a8b91af86f5a782db9fca4b68095.npy +02933112-1a9fa73ca819aa994da5feafe6f1c8fc.npy +04256520-9e18b198e803af3513f0322d0d7e53c7.npy +04256520-3415f252bd71495649920492438878e5.npy +04379243-739a2551d3826d5ad25ca1a27cf9bdec.npy +02876657-109d55a137c042f5760315ac3bf2c13e.npy +03991062-df754d2e9170be3581faebbdea6bd9be.npy +02691156-2ba980d080f89581ab2a0ebad7754fba.npy +04090263-a718521e2963077fc24d00518a3dd6ec.npy +03624134-ec1eb959cc203f1de5a365227cfe63ec.npy +02691156-4ce24828099fdb5e744ca709c13b7abe.npy +02773838-774fcae246e7ad25c8724d5673a063a6.npy +03001627-96419956c44757fe71a782a4379556c7.npy +03001627-53316b8bdd729c87a516ad65be981ae.npy +02691156-2ce02b8bb91ecd05c503a3776fc280fe.npy +03325088-64b7cc23f9fe4196b7a867e9b35a1295.npy +02691156-f4453381943f6039eba96cf317eae721.npy +02828884-7de0323af143c38bd4d8765e3910f617.npy +03046257-c527589d3b5780d11217e9f9630541c3.npy +02691156-795894b9a1105df34d210d9468aedaf2.npy +04379243-c017ca698294d3143d27d1af90f27023.npy +02958343-4856ef1e80d356d111f983eb293b51a.npy +02691156-67b7039f53759e92f4fb6842b3610149.npy +04379243-277e13392e16006557183d3afb0a522.npy +04090263-47db3b9c4b94ed61223d66e29bde9a55.npy +04379243-1a42167b30554eb8f5a6c82f073f291b.npy +02691156-caf80ecbad22a7384e1799d9d4d697c3.npy +03001627-6d6a92847f46d8e27b57eb4fc830f67b.npy +02958343-7f42d57ca7041f2df43d27ed950b5659.npy +04379243-32760b2e81bd4deac67fbc2559fd3fde.npy +02958343-b866d7e1b0336aff7c719d2d87c850d8.npy +04379243-4ccb70092f002d124212ff51b27f0221.npy +04090263-da6ec2d5f4d750303d7c323cf1653143.npy +04379243-720024ff80f13fd16fcd22503aabbe.npy +03211117-d0792c5556bdca56d1f6a4fe2f47b311.npy +03691459-c51823c76ebc7f6e464e6423c0222f3b.npy +02828884-3dd362593be47490ad5067eac75a07f7.npy +03001627-8affc6302970a589febad4f49b26ec52.npy +04379243-35f6b25bc7e016228cbb8bac2032149c.npy +03001627-591e310f3cea35a6d6134c153bee8ea0.npy +04379243-f3f6e3dc8c3b0eaf97b6421ec010dd0d.npy +04379243-bda99c11fd261f1ffc980c1b685e9930.npy +04256520-4faad33041ab0f80dd8479d78721b157.npy +04379243-171a3677999c79b32c8109e73b98d509.npy +02691156-a1f740e10229b43a82401bb74114a99.npy +02958343-9698778dc63d5874eee70745894f83bc.npy +04256520-356ee11c9803f1d2fa6df2d54fa43ce.npy +04379243-c4388c59f863de596edd3f7982f0bf26.npy +04379243-ce6e4aa17c710b3cd6d67789347621.npy +02691156-cb5fe2eaa25b2518afd477f714c68df9.npy +03001627-51439579ad42e9cdb52d092517b6bea6.npy +02691156-a271ac76b0e6bbbbb87697d3904b168b.npy +02958343-52f2a2472411fe2e6b418c7d9fedcaa9.npy +03211117-73c5898bf63748ff110eeb6ed2bcbbc.npy +03001627-307b8798217c08579e392c6acd0dd9b0.npy +03691459-79c3e029d9ffbccbe58eb6a4fe5a2344.npy +03046257-2124dd3d1d47f3873f6e4e0af3a53c1b.npy +03211117-1a4216ac5ffbf1e89c7ce4b816b39bd0.npy +04379243-f73fe719094a76ef62e5325f0ce7656f.npy +03046257-69d16120042e134f6cff9b44fdf0517e.npy +03211117-98a4d71b85b581fec92f2f0063445de9.npy +04379243-afbb16b9771a020d123691872d565e10.npy +04090263-347c9ad6b867bf885d0dded52efeb4fd.npy +02691156-45145c5e7924dca8e991cc67fb9c11f.npy +02946921-7e9ea6ccb5a1689a3299d37e620d2f2.npy +03691459-ca5fe10073293be01de55fee5ac2c5c2.npy +02691156-f9cd8293c30f1aaab87697d3904b168b.npy +04379243-132bfde1fabe9ab771a782a4379556c7.npy +02958343-35e4f3bca48aad294361eef216dfeaa6.npy +03046257-60fce7b1ddafa0c0435b6c388b558e5e.npy +04256520-33bd97e462ad2a851b17743c18fb63dc.npy +04256520-3946d23c7716c30d91857b3d2399f830.npy +03691459-375b903579b795abe3917427ea7a0e20.npy +04379243-91c2adae3b942b60d1f4836ba5ad2863.npy +04090263-cd157c59d1caa30b1d9b004d9d8d2781.npy +02958343-38ddc240001c3bd147a34c33abd32f7e.npy +02942699-a59cbd50ecf38a1be2dc67b821479cc4.npy +04090263-a5335cd2243b2d8312b38b1d99376c0b.npy +03046257-e80493545791aa9215bef14ca5ac3fd1.npy +04379243-5fcf8f8ae6c226b03002761e7a3ba3bd.npy +04379243-e2cc21f9d13d06e6a0ab1d82ef09f78f.npy +03001627-41396db6d7b550a411f7226d5cab1e9.npy +04379243-7c71421a06cee4eb85718c281d7fdf61.npy +02691156-e28e5714139535e7a9b2becd26dc2fc1.npy +04256520-f37c09d7ebf82cd642ac3369eef7a7b2.npy +04379243-5b5095b6d5612d298877c667ba5c2021.npy +02958343-d3f0b077f7134654e20af544ce47dd47.npy +03636649-80d86a40527fd0a7edd4171cd40b3feb.npy +04090263-7231363d3ec4da1c9a6e43b878d5b335.npy +02958343-6f7ba033fc5c0784468bac13e007a6e9.npy +03001627-8cc5a1e56c814d86c3cbab763f583b3.npy +04379243-c7f57e76cc1ac45d1ee2805756841071.npy +04379243-34b7b563f09f3e937848af3cb674ead1.npy +02691156-4ff50b9f815c58acca8607f540cc62ba.npy +02958343-8cbc8e27e885eb763ffe0e5069bf1eb5.npy +02958343-5a5b0e1cbb38bdb12d08a76380360b3b.npy +03001627-597cb92a5bfb580eed98cca8f0ccd5f7.npy +03325088-d9e07672c0ee46cc3321831d2245cf06.npy +03001627-41d9bd662687cf503ca22f17e86bab24.npy +04379243-7a488c92c601f83c821340ef6a9a830d.npy +02942699-82819e1201d2dc583a3e53900c6cbba.npy +03691459-52e827d2f969a2b61f2b6130e0fe93a6.npy +04379243-2437cb5665522ae3e329950ec40f6dd.npy +04379243-ba48c686c1070c63f37af16b2893f1d4.npy +03085013-b4795b53530c26c58b13932a0c28e98b.npy +03001627-9531ea3018e8bc70f81c330016997d42.npy +04256520-2fc5cf498b0fa6de1525e8c8552c3a9c.npy +02876657-dc0926ce09d6ce78eb8e919b102c6c08.npy +02773838-151d033af5381fd4c1e1e64c8ea306ea.npy +03211117-2d0b890161ac04b4a4d9f38918617d27.npy +04256520-6d25000aa000a97919fb4103277a6b93.npy +02747177-6a79fcbbe8eb1ec0162da3dc7be329d5.npy +04090263-dffd6f18fbc4f7ec4bd9916dfc5dd6c7.npy +04256520-da07e1f3d336532c2346f81928a3e5eb.npy +02801938-b37a77cec9643bae5257c4bca2a1f0.npy +02828884-943dde2754ddc7822e8ff3556a90169.npy +03948459-282153d65f0f1d3ff913329f55a53c5.npy +04379243-f7d4a0beda480047448174f83c9a5f1f.npy +04256520-a5d1e07789845c85a5aa2898f4de80a0.npy +03001627-5f7615668d2a7b313b8d5c0ebdd194c8.npy +03001627-8c4dd9891dc997b75a627be422951096.npy +03001627-ffa1e25f499e586694e98ee4fdfd7464.npy +03001627-917707ebea9dc26d7ee217c21e683487.npy +02828884-d9de3b770e53a41d5b7bc62e486d578c.npy +04256520-b56d901b6dd62332813204830fbed813.npy +04379243-691b01b959200d20e44c4b5687d5d5c8.npy +04256520-21bf3888008b7aced6d2e576c4ef3bde.npy +04379243-4c804ebc195b99d3f0b45b4b4c7e33b7.npy +03001627-1937193cf5079b623eec26c23f5bc80b.npy +02691156-f067fb1b12badf2b732bda87f2718525.npy +02691156-56c7e0b6f27cc498f3ad4b0977199f23.npy +04256520-fd7aa76019f0149b6626d14151ce40bf.npy +04379243-28f3a48bdca643e22b151d8b52c53b90.npy +04379243-8885e21ea12d6fc2b41f1e9ce6f64e36.npy +04256520-e62ed35d1643a56dc9f016d57db96408.npy +04379243-273f79cbdf5d793c6d5053bb66ea65ce.npy +03001627-294f11afc4b60827d3ddd69b7fa8d158.npy +03948459-70459a553f42c300f85b811e02bb4272.npy +04379243-4da850645da27913a82a6374374c9dbf.npy +02880940-1f910faf81555f8e664b3b9b23ddfcbc.npy +04379243-e0aec1747c4d7c11f24f0645d0949356.npy +03691459-481705a12fb7d10a20363e2561dd589a.npy +03636649-20118bc320eac59890c2e24416edfe5b.npy +02958343-9ec59185338edfde4cb9bf7caeb24dd3.npy +03928116-7bab2683b90d3f5a28f880349b6f36d.npy +03001627-e287403fb2f4234560b08e5f4e1f1a8f.npy +04379243-711d3e719d7655adb8183a4a81361b94.npy +04379243-a70f937b5c1a26e68962005ce0e986db.npy +02828884-f100d0524db0b12c2c031fa3f6d7bfc7.npy +03001627-40f1e0c4aa317c4d492d9da2668ec34c.npy +02958343-85abcf26aa761e9b21e570d3da54bf9d.npy +02691156-c9a6dcf87d1f15bca8607f540cc62ba.npy +04379243-9c21b194e13b84bff51f77a6d7299806.npy +02828884-2c8435941798069d35580c572d992e6.npy +04379243-a6cadf8f6d6e5d26f12d7184a2ad3430.npy +04256520-daf0e2193c5d1096540b442e651b7ad2.npy +04379243-a069fa41fb01fd06ac88fc1a919bbb85.npy +04379243-95e2a1ebabfa741cead99961c8c0ca99.npy +04256520-4c395a8a8fb634d5febad4f49b26ec52.npy +04256520-49a60133d6b05b8d19fb4103277a6b93.npy +02691156-e2116e0b34db656dfca1f1143bb6bc17.npy +03001627-f609378d4f5c755c9df2fbafa78e52d9.npy +02691156-1adb40469ec3636c3d64e724106730cf.npy +03636649-2e18c1bd23e4d89dbb6d3a4b6666d91.npy +04379243-f21154a95d49ca29e6c5cd45aa112726.npy +04379243-c0470c413b0a260979368d1198f406e7.npy +04090263-8e36f1a160e0b98c93cea328065cbce9.npy +04090263-7bd5d9982d9bde427b34e94db5d1bebb.npy +02876657-5f369e223697e7d11901008155be15ef.npy +04090263-3360456861b9f22020a8bc477aad122c.npy +04256520-9f5fd43df32187739f2349486c570dd4.npy +02828884-e9bf24b026df9624ef9a8aedf51bb497.npy +02880940-4cf18594e8851a3d3a5e6305a3a7adee.npy +03691459-fff40d102ca88fdb52648dc23b25b1d.npy +04379243-aff5771db62fa63d2406c215cad9df09.npy +04379243-a0f2dfdf0d8be7ae8a543abce4efe920.npy +03001627-9d9a0d778da758b043e03cfc9885bfb3.npy +02691156-c48af98d47f76002deed0e4a55ad5dd6.npy +03001627-28e147166eb68b2763ed57e35c972b4b.npy +02876657-9eccbc942fc8c0011ee059e8e1a2ee9.npy +02691156-a63e9d5df0c56b3f099bfb561edad43.npy +02958343-af0a12fa33b063ee38ceb1581969287d.npy +04256520-cc32fde4ca022cdf965e01bcaa1587c5.npy +04256520-b0a46e739da332985beab21ea89ae12d.npy +02818832-e354524c42b86792b4c1312ce8c8f69e.npy +02691156-ac3336c2f47b17d5acf77e718d93f3e1.npy +03001627-9f6a7ac15495575f6672e04a03e08d1.npy +04090263-6a7ee4fa2412e0c48c4d70537b8cc0a9.npy +04379243-b22bf7aa80627ee61ded04ad3995fc44.npy +03211117-3dd60d646dc8a3da988b29896df44cd8.npy +04379243-a75a5570ba1571447e1dc03b595bd36c.npy +03001627-86199aed92fa1f68fd60059ad8523f1a.npy +02691156-5b76fbabde77889c99399ee63318a21b.npy +03211117-fb1ca7e50ec3013b493a838ac2ced544.npy +03691459-afa628c3dd7558be89367e7bd925ea7c.npy +02828884-f713433b5702975aad5067eac75a07f7.npy +03001627-110ad013a9ae7a1ab0f4eaf0533e82bb.npy +03211117-9297e108b9780fe7da0ccb8671dd235b.npy +04379243-5d90d0c150935fe6a564497a1c91b4a.npy +02958343-8e39ba11949027ce14914b7641b2fd67.npy +03211117-4a21927379f965a9e4b68d3b17c43658.npy +02818832-b7a13b04910ac53415dd7d7985e749c1.npy +03001627-b058cc77e628ac01c433ba3e0e025e8c.npy +02691156-d99ddce71988c822475045ea78b20eb7.npy +03636649-b5012f398c4e62a330f6e0ede20c4525.npy +03001627-934ad9821e964219c3cf9ae716575390.npy +03790512-5bd41c7d3e158ac93ff4d2f5a7608a24.npy +03636649-732a2b4f7626ca61d197f67767b32741.npy +03636649-ea9721231b1369c93ffd072b23bde58.npy +04256520-e70e0e198e8de08dd23e51328875746a.npy +02691156-b17142a2f2fee3d4e2c19eec35e842ff.npy +03001627-c9817f6e253b7a93a5ac563ee2a0cd75.npy +03001627-bb8d64bab582c3f324e55bc028ee0805.npy +03211117-d96ab618ee698f008eaad608e74402f5.npy +03001627-33442081ed6e32c4504af6e1321617aa.npy +04379243-de96be0a27fe1610d40c07d3c15cc681.npy +04379243-ce7a0aaab23c9317a71c812e027f94d9.npy +02691156-204f4e737fa14aef33ba31f6ad43c835.npy +03325088-d7616893b24c10a2f6f4bab4c9f7b677.npy +03001627-b39ebd5957397e6a5dca6305fb9f97ca.npy +04090263-8145a8a2b974f4df8ae8d8f46e8d6c0.npy +04379243-7b023a0954a15f6b37b9035bdec8f884.npy +03001627-29827b7059783559febad4f49b26ec52.npy +03325088-e179aecff91323b8f538e468c975fa84.npy +02958343-28093822cc7fe487ed3696d854eee1ec.npy +02876657-be16ada66829940a451786f3cbfd6769.npy +03636649-236e0f8f6e74578ccbc9e602dbf6a4a.npy +02958343-924e1a54fad65f4de74f89cd7bde93ef.npy +03691459-5015233bfd8fee3f3e066187e0f408fb.npy +02828884-c70b020a21a7b2de67f2cdc0901bfcfe.npy +04379243-2c6d08c15a19891079dea5ba5d13aa5e.npy +02876657-35ad544a3a4b25b122de9a89c84a71b7.npy +04379243-bd7b7927d8e36c38c563fcc2752ece39.npy +04256520-e9821fb7af7db92b26f6c8b5b75f0ee9.npy +04379243-2199d0e64187366629d8eecf3827c486.npy +02691156-fc7387d630c84bb9c863ab010b80d9ed.npy +03001627-b2bfe0be6956fe34f51f77a6d7299806.npy +04090263-8f520b668fe5212e9f433921788191f3.npy +03797390-9880097f723c98a9bd8c6965c4665b41.npy +02691156-166c9abfb0f5256bbf46baa68c6e37d4.npy +03001627-ee1c0e545ab8dce862b3a719b353f115.npy +03636649-aa34fbd699f88094e5c7ea227b17d897.npy +03001627-41852b57b492559eb36178084a593098.npy +03948459-f377665c5b17d0ce61b636d79e46a7e9.npy +02958343-d9034b15c7f295551a46c391b387480b.npy +03001627-4fdcd44fd622400a97fe55e7ac43b9fd.npy +04090263-2eb8897f028d20bda27aa199c0989017.npy +04256520-2a56ff0143d4e69fe6fe3612af521500.npy +02691156-794fe891e20800d37bbc9fbc6d1fd31d.npy +02691156-117830993cc5887726587cb13c78fb9b.npy +03001627-7ae007a84e6e616d5781796ac0b9d597.npy +04379243-6122a22d4275acc796fcae44a3024b7b.npy +04256520-a11d94a5675bc703265c64fa53bf2c02.npy +02828884-7462c18d6934c5a3a83826e22c7812a6.npy +02958343-25bd9f423333c691f606d4ef0b8dbe5b.npy +02958343-47716b1acaae5b8083653a771e25099b.npy +03691459-c1fd0e8de18620ba27e7754e513f7fef.npy +02958343-c76c5d215cfd21cdee10575a68c30871.npy +03211117-4230f614a9d9a13625acf8f19a51a492.npy +03001627-9a41550ba7dd31e3bf80985a99195eb8.npy +04090263-38d7ad99e308ddc334c4a8f12da88608.npy +02958343-1eae4fcec701c176e742b0b5e87bec54.npy +04256520-33d6c09be1a1a88a48fda83c10428379.npy +02958343-e19292592dd67f1f5400f0dc3171dfcd.npy +02958343-aebaeaf0dfeb9fbe13ded1857c15b5b6.npy +03636649-d582dce8cd58bc57899bad344dc01f2f.npy +02880940-f2ef5e5b49f2bb8340dfb1e6c8f5a333.npy +02958343-96e3179460185d889130d420a26edb84.npy +04379243-cb4cd38679773e6aa1fdf150cebcb587.npy +03790512-b649be9c09e2b332429f1c522640e6f0.npy +04379243-1b82432d7a959b8dfebad4f49b26ec52.npy +04256520-e9e5da988215f06513292732a7b1ed9a.npy +04379243-5a7039feb89ab32f5e6d4b8e7c0423c1.npy +02691156-2da62d609cc59f9a10b920f84a47c477.npy +02876657-940b9e91a4a32a4130612f5c0ef21eb8.npy +04090263-82ed6ca9d8f6e80ba46487e924d32c5c.npy +03790512-94a021f2078cab18da3e5772fc0cd087.npy +03991062-10e72272bc46378a2c59a4d90e63212.npy +03691459-eb7b66a6557a05a4ab7f9d2da6fc61cf.npy +03991062-3167747de7918463ea0d2b3f25b232bb.npy +03636649-f8ca4809b68d1ad6157d629c9921fc15.npy +04379243-3f63afde3842a73affccbd0b169a39.npy +04090263-b6799bf6047f717e7f3efc94c2d31dc5.npy +03046257-c867f47e2bae884fc86d37abb4719793.npy +02691156-cbe8994d1dea1bcb4c3a35cee92bb95b.npy +04379243-6d9d1411a046934418b5d5fe1f3ec412.npy +02691156-a0fd595fdbd3a85113a96c178eda1cb8.npy +02801938-4fcb0ea751f75df936b0f2a1430e993a.npy +02958343-3469d3ab2d353da43a3afd30f2e86bd7.npy +02691156-cc80380c511ec8e2c91a9d486db717.npy +03928116-72f4c5af69cbae5df4e0e15368c84346.npy +04379243-8616d1bc989f83ef2df099df387d2211.npy +03624134-a9a091c148dcd07a156edd8a0a2b1378.npy +04379243-1377448893b499a5a8e4e5c9426fb9cb.npy +02691156-236932c4f4b2f557f5c7319b71bdce6e.npy +04379243-f61d6422de7447bc4c772d26a83f790c.npy +03211117-f4a259b4778a77b37b2bb75885cfc44.npy +02958343-3397f15757f51279e55e3ad998a1ecb4.npy +03001627-17352867f5661212c8687ff9b0b4e4ac.npy +04379243-155a08c8e150e7008c4f202fffc87396.npy +04090263-1b7f1ca21e6ab9cecc34b900bb2492e.npy +04256520-608d9d8434e52a71eaf14273fa406ffc.npy +02958343-ac6977ed53e041392b03387fa8b1d3d5.npy +03636649-5dd2f4d3b253058dd554ab0a45f30de7.npy +02876657-592f62e338fcac1eb0be98650cd7fb6f.npy +03001627-2de1c5525d24c1c988dcbe86402c7c15.npy +03325088-8bff3a6cc3208b86b7a867e9b35a1295.npy +03991062-43890c1681acdb96192cb9598e6d5392.npy +03001627-64ac9e029c4c9eb1671565dae7014737.npy +04256520-e0fd6cc8f2e62ed6d1151897037aebc.npy +04090263-604f91e5b306393fa884e15a61a5f4a2.npy +04256520-1e6d5797be45c5a4443764597a072223.npy +04379243-811a7be3be14bd2b62103e4bff47b4cd.npy +03001627-40e73a326cf95d0361c93c4994c91bd1.npy +03001627-3968956c7bccc24c203eb08a0c3b4355.npy +03691459-e3a37b904381c61a46407779dbd69b2d.npy +03636649-a34db84654a9685f54386f3e4b944407.npy +03624134-ae66cb2b08eb34c0e887497dd1ca4081.npy +03790512-c62066c1ff268bcb9624f6cadda65407.npy +02958343-354274e1c27653a318d9ca1acf6633f6.npy +03001627-89d510c94145f0e0f7628281ecb18112.npy +02958343-bd29875d6aa7be1b2a80b185a779af6c.npy +03797390-c34718bd10e378186c6c61abcbd83e5a.npy +02691156-a95734cb8f7511cb46ed10e8f7fe336e.npy +02958343-27495a8836ead3d55c5dd9508493909b.npy +03001627-a8dd9990ecd74c45435897641a7ee684.npy +03001627-bbe71bb58b7f8f74f51f77a6d7299806.npy +04379243-77daa3ded63dc634d83e8d4109d37961.npy +04090263-108c7545e089109c9838402e8211bd73.npy +04090263-78a0c4ff75258ecf16b34c3751bc447d.npy +03001627-c763d59c0b5c73394925bc492489de9c.npy +03001627-6033c5fa61cb7b79b50d0c6a0c254040.npy +04256520-bc5a26c2915a592091a3aa674c7ec1a3.npy +04379243-25eefc5a3c7b30e1f103d473de33521a.npy +03001627-c3c159a5a56614aad7b20fded0142d7a.npy +03991062-e3fcf5ec83e5fdc54b3c42e318f3affc.npy +04379243-6f052c8606dd3ac3de03ab2a27ba7531.npy +04379243-9b10ca8fefd82fad5c10b08ea69398c3.npy +02801938-cebf28243694a6136aea2f18ee404fd5.npy +04090263-85d730adf18e0c43a06a81572261e82e.npy +02691156-bc7ead8b45952ab8822054a0a020bf4a.npy +04379243-e0194110e31c999aa91c75874136f43d.npy +04256520-4b86c8d86e181ed8f51f77a6d7299806.npy +03001627-5e191b9696ff301e821a29f3de4d7cce.npy +02691156-f6f5efa1554038ce2154ead1f7ab03aa.npy +03001627-445d6cef46b853ee713decb1a0563b12.npy +04090263-166508e16d31488a6a34aa94ca8a3355.npy +02801938-b852202f803c3dfe90c794d3b20112e6.npy +03636649-c5b6259812704f11e3ebe8b18779c486.npy +04379243-8c8690ed4cd0a297e4bbc5bb7fd2afa.npy +03948459-8c9e592c95f95e7c9a6e43b878d5b335.npy +03991062-fe897824c2edaf4fffc6e457221b9271.npy +03046257-6c436e74fedfb0d54fa6e466c3dafd05.npy +04379243-dd528cd176c8d99686de8d6734d81fc9.npy +02691156-d60ec60e091e9d7ade125dc914c4bb9c.npy +03624134-1483e2654c791dbe9f647b36386f24ae.npy +04256520-218a7b0cfc87312925a3aaf903a41c90.npy +04379243-ab08125b4f53c1779595137b79304890.npy +03624134-e31978ce34a288461b22d29e47ec3f2.npy +03928116-fd6034ddb67af9615b39a37797d4a0c4.npy +03636649-5d97be0e2414bfe0a8930422448288ea.npy +04379243-d40ba4b29c5ae69dae14646a8c8ddd34.npy +03001627-30d2d3c887f9592551ae1a6e89264401.npy +04256520-54f81ca969051442e9362c2e21d265df.npy +02691156-4a3950ebb6fe6aca8afca43ae0909988.npy +03001627-cee98619dbdb0e34c5fc2b846c38d941.npy +03991062-93aa00349b151dd37df4feb40f08ca17.npy +04256520-f1e174f8ac0f5254490ad276cd2af3a4.npy +04090263-a7b088a849fdd41c25975e984b0e050b.npy +04090263-e57483ce26ca69b08f70fa6e7b12c70.npy +04379243-6a3ee73d42228f8581654cb17c02fd.npy +02958343-42f45d024ab3309eff673973a435017f.npy +02828884-22da6d7559e28ac9d2b12aa6a0f050b3.npy +03636649-85f0a7c268fd095cfcb8d8c6d4df8143.npy +04090263-eca245f9c180e7c71d9b004d9d8d2781.npy +02958343-1e54527efa629c37a047cd0a07d473f1.npy +02828884-49989a15860936d6601104cd2d998272.npy +04379243-180c5218bb39d31f5510d59f3ab1ed64.npy +03001627-756487465c12a5332165c54dcecaacb4.npy +04379243-14e9f568cd3309dd75becd8a4c3f1866.npy +04379243-b5fe80b6cbb9f5d1a6c03a53cf0a14c9.npy +04379243-a48e4c2930d39f289d297e74104d3ac3.npy +03046257-fdb5537f0899ced0744fc85fe0d3e26e.npy +02958343-b38361e0d9eace2fcf2b292150d31034.npy +04256520-4f5611a5b8b1362e73800789ccff9705.npy +04090263-796816a563f04373c24d00518a3dd6ec.npy +02828884-2e5b449d584725dead5067eac75a07f7.npy +04090263-24ba1a3b18e25e46a3a714c763a6fafd.npy +04256520-ff35b2519455b6577b76a7024ccebf5.npy +03001627-5ca5e3357e5a6d9b45c6cb69e0968783.npy +04090263-a02f13c708f259f97ed475464ab76870.npy +03636649-255dd61372b3509a41657e31b569b105.npy +03325088-3805c03602ebf679c36fb70296e45483.npy +02691156-49e21b81565a51e6493c5f51f14398c7.npy +03691459-bc7938b4fc00ff71984102bc982dc4a5.npy +03691459-28b5a90b428358e173e1b2d018c0512.npy +02691156-b224e74c6de1185a6f498c6206a06582.npy +04379243-3fc5f57053b75b5a91cd5c82dce55c17.npy +03001627-d67d52783e2ef9b76179a6634d17b74.npy +02691156-3b95867a47a8afafe593bc205a118b49.npy +04090263-22063ea2a9d53b569628553cade61af2.npy +03636649-a721beef2162858ca2331382fbc36f94.npy +03001627-5874e2ea2c2b71471b356ab8b24c147.npy +03691459-231104a34a7b7a52c67a971de046381d.npy +03636649-d4bbd93c0d85e77d7934a0d24a61231.npy +02828884-dd56a9259a0eb458f155d75bbf62b80.npy +03790512-2f32164c5a422fe8b44d82a74ebc14c0.npy +04090263-20cbbde170e264f320152153c3a56171.npy +02958343-3cad25b218e0cd506436916a86a90ed7.npy +03001627-ea628b4568d4eb527085b4353236aad.npy +02691156-59043812c2139ea8bbf3143b1cb6076a.npy +02876657-e23f62bb4794ee6a7fdd0518ed16e820.npy +03001627-6534de9a07438b52ee3907b60a74e8f8.npy +03001627-f1f40596ca140cc89cfc48dba5c0e481.npy +02828884-8ff44d4849eeb577ad5067eac75a07f7.npy +03001627-f52c7425a47ff55f79c8c47a54f30eb.npy +02691156-7201e35e5062683571d03b466c72ce41.npy +03001627-6b70334926f7dac3f91663a74ccd2338.npy +03001627-8aa597e8f5498bb0165de6c381540e39.npy +03691459-d414b33288a735c955b62c3398327a83.npy +02958343-30e84a2b779b0e89473f10e6caaeca56.npy +03691459-3fa75b15090b5139ec507a9b4c133ee1.npy +03001627-79c5542f068830463002bb98777d6df5.npy +02958343-62b14fc115d98999f0776ca5816850f0.npy +03948459-f2ab639004ccdb749a6e43b878d5b335.npy +04074963-e739278e9039922dff7f69173a1ae6d4.npy +03636649-3343296bb39a9e679410a04d09c14d1a.npy +02691156-6f8e17cf5180fa96a911ef3962f7cae2.npy +03001627-cb68461343aa852772dadd9292b51ceb.npy +04090263-d805bfbfee78282e6b2c8bb96250e4a0.npy +03001627-609cfbe0dd76c64042e1bb4fe264125f.npy +04090263-3d76e67762cacc714b49cd65dfcc3a9a.npy +03636649-ba3f51c0e1e0adef4cc30865d6337b9c.npy +03325088-dda2fa1732a011278b63cb6175467ac9.npy +03691459-1d4bb07ac73996182339c28050e32573.npy +03636649-213d911cc489c352b5db3f95d706a0c9.npy +03624134-3ef87a241213eb129f30f02514717f00.npy +03691459-29c140fb4eba078c7909eb62c64c0070.npy +04225987-55f0e38a64ba2c2d813b65629a36678.npy +03325088-c4b98fbd29336c5276c18e71fd49c4dc.npy +03624134-b0079bce8ea7d247d647ce6a3f0800a0.npy +02828884-7bbd4d3fed3c4255626d7e3d07da8352.npy +02828884-9ff0e30c911ef3a3cb2a965e75be701c.npy +02691156-32e7224d196e5866bd564bd76cf3cbec.npy +02828884-7540e6df58bf00ff13eaf3e3f6d466d9.npy +03001627-a1e6226c3a23ec808a653a9f65a410f6.npy +03001627-93e72cd3140b32513b5ed5cb2d36de1e.npy +02942699-ff74c4d2e710df3401a67448bf8fe08.npy +03691459-519b0f5581c72a25db30e42459dcb06f.npy +02691156-1eb3af39d93c8bf2ddea2f4a0e0f0d2e.npy +03691459-1db62b6137f51cee8ae98a75d7488e57.npy +03001627-7e433512ef8beb51b17743c18fb63dc.npy +03991062-127b3453b1f73505a2c59a4d90e63212.npy +03691459-370ab315439047cba2fc84df67c2df42.npy +03001627-38f87e02e850d3bd1d5ccc40b510e4bd.npy +03948459-686be742e65eab7816cf8b1cd2155e02.npy +02958343-3f16d6ac013aa946977e464a4b82757d.npy +02691156-f66bf1a9b6d2d109a34fb3db6a11a22d.npy +03001627-198bd40d94930950df6cfab91d65bb91.npy +03991062-4eedf4a65907a4c7a2c59a4d90e63212.npy +03001627-96885d760de5c5e174335c2737ecf4d.npy +03691459-132257fddbebc02ff14235268cca03a3.npy +02691156-66c37aeffd6e73f284306f3bf0a1f2d7.npy +03624134-ca430e94c7e2e3ad8e40258f05c88f27.npy +04090263-4a4387ccf5b0b4a6589c07868201b17e.npy +02691156-a805c30d4b09f11f62347b4731688b0f.npy +02691156-fb2e4eb19ba19bde5fe6cff21a9e8496.npy +03211117-9972709345d24fd31ee6305032661052.npy +02958343-80cae0cc66dcb8a88acb0ff76f4aec7d.npy +02958343-e213d976734431773a3afd30f2e86bd7.npy +02958343-3df6230b2382ec12473f10e6caaeca56.npy +03001627-9c8685c65403dfba2f134420f7b0d7e6.npy +04090263-f8af5b4ded94bfcb9905a3939c890ad2.npy +02958343-30964e51b5218487577fbd27130e143.npy +04090263-bf6268d9d4bd22d89cd99d3d15a8756e.npy +03001627-a23e9e5ace917aa350ff3fe5a0fcba13.npy +03001627-c1d4fcbf5bb6ad11c5beea20858a99d5.npy +04099429-c3f7e3b188f6fe139a6e43b878d5b335.npy +02691156-975c00ab85218a05430355e13bc86b4e.npy +02958343-31055873d40dc262c7477eb29831a699.npy +02691156-de519752147a225032387cdb9b2a84d5.npy +02880940-754634abeb7bffc32977b68653eb2e1e.npy +02691156-4c07126c6ecf5436b7bd17e458d0dcb.npy +03691459-64ba67a67d83811c2b688d771932c023.npy +02691156-707cc578bfec0f671aa9d8d95b6740cc.npy +03211117-bb870360cda15433e441f5bb6f88ca61.npy +02691156-3f387e8586f92b6b7d3b11085e75c7ad.npy +03325088-61c12f5b031b80beb362845c6edb57fc.npy +02691156-e2a6bed8b8920586c7a2c209f9742f15.npy +03636649-6650c1c61c8aefc782db9fca4b68095.npy +03001627-e2809feb8c0b535686c701087a194026.npy +02876657-738d7eb5c8800842f8060bac8721179.npy +02691156-62bc07e9813d75ead46f37bdc1dd4b45.npy +02958343-6ee6fa5c8d664f1349314ffcec1f2f7f.npy +04090263-ad209c1cf7e2cd6249352dd33f95cb9e.npy +02958343-1be075751d7cfbf9ee8e9bd690a19ec1.npy +03636649-402f7ce2b87e7d1ac066b9622c005c53.npy +04090263-ade16e09e79526d487ec12cf5e4563a4.npy +03991062-5dbe8e5eef057cdf17395ba6d552088a.npy +03691459-5b6ffc53d44363b57f2a00f370c25e25.npy +03001627-da264a41dd8fdd655357c338ec9641.npy +04090263-59aee3729d8ae9a6a8304814541fbf2c.npy +03636649-9f5c3ea9f8254b8bd42b9650f19dd425.npy +02958343-b370e4c0d05df8eaf48062edccab3fbd.npy +03624134-3ffc61a3380f4104823590ed8a67d74b.npy +02958343-61645b21c344e22a65dc1e664bdf2e6b.npy +03948459-dd549fdfd38ce511fc43d5b32fa230f.npy +03636649-7eaa7d0cadf48bbfa9bdc22a1e02e82.npy +02958343-222cfde10e0f62e04b00d8f4cd3fae63.npy +02880940-bb7586ebee0dc2be4e346ee2650d150.npy +02958343-b2e13c37cfaba983321ad52c1815971d.npy +03636649-4b6ba211c9731d334c614ad0ec154eb5.npy +02958343-2f839e1e2072a11be55e3ad998a1ecb4.npy +04090263-4407c14eb6e7ba83160ce3b5a19029bc.npy +02691156-d4a8134b2463a8bca8607f540cc62ba.npy +03991062-c045cdd855fdec2b7b6fd5468f603b31.npy +02843684-ef5c972369cdd9bef953ec7f4b3cdf4b.npy +02691156-2efa2cfc42f2ff481b27cd1681a3d0e7.npy +03636649-87d8b99b8a43e2f930f6e0ede20c4525.npy +02691156-845d7718879d26f9a45fa73059b12336.npy +03636649-8581a3ae1f77319ac066b9622c005c53.npy +04090263-193520be26b57b77a5f9d279e263a051.npy +03991062-fab65459e5a9e94ad4d8765e3910f617.npy +04090263-2f86138fadf4e2f5af56497f051566ab.npy +02828884-b023f42464e9591867c8e42cd3ac65ef.npy +02828884-77c2f1b7a7c0a4d15ca1f314f1afc186.npy +03207941-4a4f0713fbabb6e514b35a7d7cea7130.npy +02876657-2976131e4621231655bf395569b6fd5.npy +02691156-dc344ae06e26aa55615ba7bf3620290d.npy +02958343-36cf21268838ce6011718baa6d4afc0b.npy +02828884-778ad8517a34927d2056b4bd5d870b47.npy +02828884-359c7abaf431a05181faebbdea6bd9be.npy +02958343-57ce5193c3ecd067c05c2f3d0d461abf.npy +02691156-5a399ad6696d587d5e37076261ed63.npy +03337140-d879a859aa635c4b91c352d02061b3f7.npy +04090263-fc6bb157d603772d81eae2a60736179d.npy +04090263-e1fd9153928081d93b80701afa3beec5.npy +03991062-7d45da94216b4056a05876905ab3aec3.npy +02828884-44085381e0708de48ee8b7b79b7a0cdc.npy +03624134-e355bd01c8bacaa53630ed68aee4bf94.npy +03207941-37fde5302327d2594a44340bf227e40.npy +03991062-5562563aa6a2f57ec8995c27271d380.npy +02958343-1f5e1b0661b340fc81dcc09cafd93d2e.npy +03337140-b29dbf1f80164b31ebf17edfda20712b.npy +03325088-9599bd738a7a178d76c18e71fd49c4dc.npy +03337140-40129bba38f40b4c4c3aee8e9d3a6ffa.npy +03325088-c7480d5acf4527c5979c556124bee033.npy +02958343-85bb9748c3836e566f81b21e2305c824.npy +03624134-5e515b18ed17a418b056c98b2e5e5e4e.npy +02828884-73a6a42f5e45b3e7a3879b7d5fe7c612.npy +03948459-db78bea32b311c1f873aebd175ac6f11.npy +02958343-b990ae1858bb82c133f84f942f9a2bf5.npy +02691156-8615ac14d65e76efbde09007ce74853c.npy +02828884-ba363a93cf76f9a12056b4bd5d870b47.npy +04090263-cca52c1d48b777b227be842e82df28b3.npy +02828884-b60b9fe791be0f4b1191025061735ea3.npy +04090263-b7e7192d2b8686fb418bdc8c2bd0fb7c.npy +02828884-51197dd964f598fdcb2a965e75be701c.npy +03207941-aa4ad2f41efb815cb022c94235bc8601.npy +03948459-49e379dd689f01258dc97820d1d9537.npy +03325088-bc25edce4945567776c18e71fd49c4dc.npy +02801938-d9f0f7cff584b60d826faebfb5cddf3c.npy +02801938-33a623a68ac3a6541c8c7b57a94dbb2e.npy +02880940-519f07b4ecb0b82ed82a7d8f544ae151.npy +04090263-3b3839d2a22ffe94c5a12959f98a115.npy +02828884-4f9e40b167665d793a0ed7b4771fe31.npy +02828884-e82eace9941d82f34ff3e3166b80bde9.npy +03325088-6412b168fb8b4a66c36fb70296e45483.npy +02828884-2d1dda55020a0c4bad5067eac75a07f7.npy +03991062-64de833b09fd52c3a324047aa5b1f068.npy +03710193-c0a7a35c64ca731aff8240d22dfd73.npy +03325088-677080f1736892d7de9f0235251bc840.npy +04090263-469fe5d0ea2bba70650d38f01656985e.npy +03211117-c4a41bdc2246d79743b1666db9daca7c.npy +03207941-ff421b871c104dabf37a318b55c6a3c.npy +04090263-d11b1767a70922edb99f5bb707709184.npy +03790512-6a9db96b3ed76f956dc3fd80522499a5.npy +03710193-13867ae4ccb3bd627369dcfc2ed54ea4.npy +03928116-804adfb0fa907adc238ec815c61acb8.npy +02828884-7f218ef91e835a90b515d1675be6b5d3.npy +03991062-152ecc698f56f89de499b3a7593b4ee7.npy +02801938-b3b341fb9a2e406e36b0f2a1430e993a.npy +03991062-785bc2c44f44cb1cad250fed8c7992ab.npy +03325088-110a839cc3fbc8013321831d2245cf06.npy +03211117-24f34f582f9072eedc3e7f8ad872247f.npy +03211117-14c9e39b05dd2cf2a07f2e5419bb2c4.npy +04090263-de5438deca7f9f0712b38b1d99376c0b.npy +03211117-58426d216f393034d24e3068806a8c67.npy +03325088-32d86098142a1662842514f9336b4377.npy +02843684-5af661f12389edb3ed772ffb17600448.npy +03325088-1a3a4611409e306c1a832e2972cd1e0d.npy +03211117-dce03c1f0b8365c335f8aa71d1d146bc.npy +03211117-7706cc4ddbc96d4975d665dad1b6a18e.npy +03948459-e6017a1e15095b4e6314c3b6a3a65519.npy +03337140-f44029207e03c4be4c3aee8e9d3a6ffa.npy +04090263-84f068d182437e65b7266db39263f546.npy +03928116-156c4207af6d2c8f1fdc97905708b8ea.npy +04090263-48620fb309184d4bc5e86946f2168706.npy +04090263-48cd9104129535283623b64770edb4be.npy +03207941-3bee2133518d4a2c1f3168043fdd9df6.npy +02876657-134c723696216addedee8d59893c8633.npy +03337140-3faf894d55e26f434c3aee8e9d3a6ffa.npy +03624134-a6efcf0b80f3bc836da16f7df2c9a5b0.npy +03211117-cc5e011d644edf395eae7316b4dfcbbe.npy +03624134-2676cb39be54c6e1bafba8433f5e7ea2.npy +03211117-a20887f46f9974d9a23949c21eddef76.npy +03337140-1d77e77d4324fbd3ce5d6e9371bb5c33.npy +03624134-6f8b660661269406504c6b6d62466c67.npy +03325088-b7758e9c5ce71e1b488d970db5b03bc1.npy +03085013-277e8f771b0aa88a6c71abf53b20bc9c.npy +03928116-a5aa3c091202411a7af9c4121d4bb913.npy +03991062-7bbbae0f1cc9778968423e46bb192f69.npy +03948459-ed051e6c8ac281facb14d3281c3904f0.npy +03211117-2bbf7f77d43b74338a331b18e58c6914.npy +03624134-e79481b2fde3a3ab340fbf70397ab69a.npy +03337140-c3881ea3a2cc38af4c3aee8e9d3a6ffa.npy +03337140-885b945da192390c4bf3cfb743192941.npy +03710193-e7c766dcfb8ed0164b0fc5c705797d05.npy +03710193-985e3c90320c7088d4f2f5e5cacbfd3c.npy +03337140-7ea3fc2b73ab02a91c352d02061b3f7.npy +03948459-263afcd618780865bbace5122b1001f5.npy +03337140-7ae9a738d4a6976991c352d02061b3f7.npy +03325088-4f9b778e5bc6e251a8f6851a5d3f13b6.npy +03325088-dd98f4c4066ad773792c04fd8184496.npy +03325088-5ded149f15be08af526fd4dfffaede08.npy +03991062-c2e11c90827c10a559f9892433e1b1f4.npy +03790512-6b6cf38ed305dc11ab13c10f92a32fc1.npy +03325088-d49e9fdb4246026ed93768e7b9b1eabf.npy +03337140-1a0995936b34c17367aa983983f9bf36.npy +03325088-be5925e681268f3b3321831d2245cf06.npy +03325088-4a9a49b9d5b267d4b7a867e9b35a1295.npy +03325088-c94828ee293222faf38c4a12750d961b.npy +03991062-aa391239edea23a16ba14bfd91a75020.npy +03207941-cbc2eab86b38a9f0275d003e423c59ba.npy +02801938-f0c2ecb032e4230c50da8b99982a3057.npy +03991062-932b6e28eac69cf8ffc6e457221b9271.npy +03991062-abad49fcabe9a8ddec6aad92a03b8466.npy +03991062-ca5fafe57c8c28f8f7a5ccfc89bfeff1.npy +03928116-42911b5824d49af774cbf1cd482c6ca0.npy +03991062-a16d89d5ca6c73aae88c1d6fc3580355.npy +03948459-8fa0dd437e6b8a819f433921788191f3.npy +03624134-9746101f20473d346bbd83c2bc4c3b2e.npy +03991062-415acc982c4a05179d4753b107dff904.npy +03948459-7e868c7ec96377df86ac88920b2701aa.npy +03337140-8aa227e32612e2137f45370489ca3156.npy +03337140-aab0358ff3aaa39691c352d02061b3f7.npy +03624134-df1d7bc513c304c3196b7bf084026530.npy +03624134-db13421379091e50e0b68f51ad1c0011.npy +03991062-55d7d4f52d9eeb2a6727079394e24d70.npy +03624134-3fb80a70e65eff5dd65ee87f16099336.npy +03991062-1732f2d2119b9adc72652f4081ec5a77.npy +04074963-b1a97d944c1b3fa2357f57aad9e1b3cc.npy +03085013-477b37c996a9ae6b61b37d2f08c1bc03.npy +03948459-f5462fcbf5366bd03571d7763ba5a413.npy +03337140-c387da71c07332b13542091189dc62b5.npy +03624134-cf8fe702232541376e5c3f959847ffe.npy +03991062-937e900f03934af4d24a2477b5d154a7.npy +03207941-4bca315fd61741797fb96900a295055a.npy +03991062-44aca0de3323a7adfb0f1b7266d79466.npy +03337140-db11905ab6f06469412dfc90452742c7.npy +03948459-f2e592962a9df3de1d27f57617a4976d.npy +03207941-fb15942e4096d8f0263a7f81856f9708.npy +03991062-dc5f68b4e89c7af3cdca8f9aeee8cb4e.npy +03991062-a66d993b9ced28d843e5f2a8f5f1723a.npy +03991062-e81a175e6b8fb1e1eee538eef7a50e4d.npy +03624134-5da842254c99b0379d40dc50674e6347.npy +03991062-6c9a25f120cdcacc25ebd1cd0b422e32.npy +03991062-3ac8ac4f319e5c0c785f06f424b9d06.npy +03991062-819795e285ea031625ebd1cd0b422e32.npy +03624134-3ca548ca4f557a4cda3cc9549ae4a7d3.npy +02843684-c9a3538b8408c66a33f19716eab42752.npy +04074963-b2c79f7add7cb56ac03df0bb156692e3.npy +03624134-7568cd60cd4d4f143f4deb9ad19fc17.npy +03991062-4f45d2e31a724df4f8d5100b5d851ce4.npy +04074963-259539bd48513e3410d32c800df6e3dd.npy +04074963-6411d7e5e038534c13b3690b5eeccc36.npy +03207941-38a5c62d5c03ae0992270dc2e45328b.npy +03085013-c680be5b4715de9cde3e0c162cb2b41b.npy +03085013-bde7724c6a2c984d4c7427583b874cf1.npy diff --git a/cv/point_cloud/Point-BERT/pytorch/segmentation/data/shapenet_synset_dict.json b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/shapenet_synset_dict.json new file mode 100644 index 00000000..712903d0 --- /dev/null +++ b/cv/point_cloud/Point-BERT/pytorch/segmentation/data/shapenet_synset_dict.json @@ -0,0 +1 @@ +{"02691156": "airplane", "02747177": "trash bin", "02773838": "bag", "02801938": "basket", "02808440": "bathtub", "02818832": "bed", "02828884": "bench", "02843684": "birdhouse", "02871439": "bookshelf", "02876657": "bottle", "02880940": "bowl", "02924116": "bus", "02933112": "cabinet", "02942699": "camera", "02946921": "can", "02954340": "cap", "02958343": "car", "02992529": "cellphone", "03001627": "chair", "03046257": "clock", "03085013": "keyboard", "03207941": "dishwasher", "03211117": "display", "03261776": "earphone", "03325088": "faucet", "03337140": "file cabinet", "03467517": "guitar", "03513137": "helmet", "03593526": "jar", "03624134": "knife", "03636649": "lamp", "03642806": "laptop", "03691459": "loudspeaker", "03710193": "mailbox", "03759954": "microphone", "03761084": "microwaves", "03790512": "motorbike", "03797390": "mug", "03928116": "piano", "03938244": "pillow", "03948459": "pistol", "03991062": "flowerpot", "04004475": "printer", "04074963": "remote", "04090263": "rifle", "04099429": "rocket", "04225987": "skateboard", "04256520": "sofa", "04330267": "stove", "04379243": "table", "04401088": "telephone", "04460130": "tower", "04468005": "train", "04530566": "watercraft", "04554684": "washer"} \ No newline at end of file diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/__init__.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/dataloader.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/dataloader.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hierarchical_data_manager.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hierarchical_data_manager.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hook_wrapper.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/hook_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/model_wrapper.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/model_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/runner.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/runner.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/utils.py b/cv/semantic_segmentation/apcnet/pytorch/mmcv/device/ipu/utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/tools/slurm_test.sh b/cv/semantic_segmentation/apcnet/pytorch/tools/slurm_test.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/tools/slurm_train.sh b/cv/semantic_segmentation/apcnet/pytorch/tools/slurm_train.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/train.sh b/cv/semantic_segmentation/apcnet/pytorch/train.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/apcnet/pytorch/train_dist.sh b/cv/semantic_segmentation/apcnet/pytorch/train_dist.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/Dockerfile b/cv/semantic_segmentation/deeplabv3/MindSpore/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/README.md b/cv/semantic_segmentation/deeplabv3/MindSpore/README.md old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/CMakeLists.txt b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/build.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/build.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/fusion_switch.cfg b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/fusion_switch.cfg old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/inc/utils.h b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/inc/utils.h old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/main.cc b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/main.cc old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/utils.cc b/cv/semantic_segmentation/deeplabv3/MindSpore/ascend310_infer/src/utils.cc old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/default_config.yaml b/cv/semantic_segmentation/deeplabv3/MindSpore/default_config.yaml old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/eval.py b/cv/semantic_segmentation/deeplabv3/MindSpore/eval.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/eval_onnx.py b/cv/semantic_segmentation/deeplabv3/MindSpore/eval_onnx.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/export.py b/cv/semantic_segmentation/deeplabv3/MindSpore/export.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/Dockerfile b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/convert_om.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/convert_om.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/fusion_switch.cfg b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/convert/fusion_switch.cfg old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.cfg b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.cfg old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.pipeline b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/data/config/deeplabv3.pipeline old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/docker_start_infer.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/docker_start_infer.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/CMakeLists.txt b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/build.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/build.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.cpp b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.h b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/DeeplabV3.h old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/main.cpp b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/mxbase/src/main.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/requirements.txt b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/get_dataset_colormap.py b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/get_dataset_colormap.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/main.py b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/main.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/run.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/sdk/run.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/infer/util/get_vocval_lst.py b/cv/semantic_segmentation/deeplabv3/MindSpore/infer/util/get_vocval_lst.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/mindspore_hub_conf.py b/cv/semantic_segmentation/deeplabv3/MindSpore/mindspore_hub_conf.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/config.py b/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/config.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/device_adapter.py b/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/device_adapter.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/local_adapter.py b/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/local_adapter.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/moxing_adapter.py b/cv/semantic_segmentation/deeplabv3/MindSpore/model_utils/moxing_adapter.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/modelarts/train_start.py b/cv/semantic_segmentation/deeplabv3/MindSpore/modelarts/train_start.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/postprocess.py b/cv/semantic_segmentation/deeplabv3/MindSpore/postprocess.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/requirements.txt b/cv/semantic_segmentation/deeplabv3/MindSpore/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/build_data.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/build_data.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/docker_start.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/docker_start.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s16_r1.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s16_r1.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r1.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r1.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r2.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_distribute_train_s8_r2.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_onnx.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_onnx.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16_gpu.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s16_gpu.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale_flip.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_eval_s8_multiscale_flip.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_infer_310.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_infer_310.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_cpu.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_cpu.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_gpu.sh b/cv/semantic_segmentation/deeplabv3/MindSpore/scripts/run_standalone_train_gpu.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/build_seg_data.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/build_seg_data.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/dataset.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/dataset.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/get_dataset_lst.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/data/get_dataset_lst.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/loss.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/loss/loss.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/deeplab_v3.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/deeplab_v3/deeplab_v3.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/net_factory.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/nets/net_factory.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/get_multicards_json.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/tools/get_multicards_json.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/__init__.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/learning_rates.py b/cv/semantic_segmentation/deeplabv3/MindSpore/src/utils/learning_rates.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/deeplabv3/MindSpore/train.py b/cv/semantic_segmentation/deeplabv3/MindSpore/train.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/.gitignore b/cv/semantic_segmentation/gcnet/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/CITATION.cff b/cv/semantic_segmentation/gcnet/pytorch/CITATION.cff old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/LICENSE b/cv/semantic_segmentation/gcnet/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/README.md b/cv/semantic_segmentation/gcnet/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes.py b/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes_769x769.py b/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/datasets/cityscapes_769x769.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/default_runtime.py b/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/default_runtime.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/models/gcnet_r50-d8.py b/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/models/gcnet_r50-d8.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/schedules/schedule_40k.py b/cv/semantic_segmentation/gcnet/pytorch/configs/_base_/schedules/schedule_40k.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/README.md b/cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/README.md old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/gcnet_r50-d8_769x769_40k_cityscapes.py b/cv/semantic_segmentation/gcnet/pytorch/configs/gcnet/gcnet_r50-d8_769x769_40k_cityscapes.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/dist_train.sh b/cv/semantic_segmentation/gcnet/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/activation.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/context_block.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/norm.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/padding.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/plugin.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/registry.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/scale.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/transformer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/upsample.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/resnet.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/weight_init.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/test.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/file_client.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/base.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/io.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/parse.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/colorspace.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/geometric.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/io.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/misc.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/photometric.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/README.md b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/README.md old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sigmoid_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/softmax_focal_loss_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/focal_loss_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/focal_loss.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/deprecated_wrappers.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/focal_loss.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/focal_loss.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/info.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/sync_bn.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/_functions.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/collate.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_container.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_parallel.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/registry.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/scatter_gather.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_module.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_runner.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/checkpoint.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/default_constructor.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/dist_utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/epoch_based_runner.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/fp16_utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/closure.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/ema.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/evaluation.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/hook.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/base.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/text.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/memory.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/optimizer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/profiler.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/iter_based_runner.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/log_buffer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/priority.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/config.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/env.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/ext_loader.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/logging.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/misc.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_jit.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_wrapper.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/path.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/progressbar.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/registry.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/testing.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/timer.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/trace.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/version_utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmcv/version.py b/cv/semantic_segmentation/gcnet/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/inference.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/inference.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/test.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/train.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/class_names.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/class_names.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/eval_hooks.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/metrics.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/base_pixel_sampler.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/base_pixel_sampler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/ohem_pixel_sampler.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/seg/sampler/ohem_pixel_sampler.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/misc.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/core/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/cityscapes.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/cityscapes.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/custom.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/custom.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/dataset_wrappers.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/compose.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formating.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formatting.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/formatting.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/loading.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/test_time_aug.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/test_time_aug.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/transforms.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/datasets/pipelines/transforms.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/resnet.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/backbones/resnet.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/builder.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/decode_head.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/decode_head.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/fcn_head.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/fcn_head.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/gc_head.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/decode_heads/gc_head.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/accuracy.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/accuracy.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/cross_entropy_loss.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/cross_entropy_loss.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/utils.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/fpn.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/fpn.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/ic_neck.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/ic_neck.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/jpu.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/jpu.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/mla_neck.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/mla_neck.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/multilevel_neck.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/necks/multilevel_neck.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/base.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/base.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/encoder_decoder.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/segmentors/encoder_decoder.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/embed.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/embed.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/inverted_residual.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/inverted_residual.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/make_divisible.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/make_divisible.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/res_layer.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/res_layer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/se_layer.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/se_layer.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/self_attention_block.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/self_attention_block.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/shape_convert.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/shape_convert.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/up_conv_block.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/models/utils/up_conv_block.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/encoding.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/encoding.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/wrappers.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/ops/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/__init__.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/collect_env.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/logger.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/mmseg/version.py b/cv/semantic_segmentation/gcnet/pytorch/mmseg/version.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/docs.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/docs.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/mminstall.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/mminstall.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/optional.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/optional.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/readthedocs.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/readthedocs.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/runtime.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/runtime.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/requirements/tests.txt b/cv/semantic_segmentation/gcnet/pytorch/requirements/tests.txt old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/run_train.sh b/cv/semantic_segmentation/gcnet/pytorch/run_train.sh old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/setup.py b/cv/semantic_segmentation/gcnet/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/analyze_logs.py b/cv/semantic_segmentation/gcnet/pytorch/tools/analyze_logs.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/benchmark.py b/cv/semantic_segmentation/gcnet/pytorch/tools/benchmark.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/convert_datasets/cityscapes.py b/cv/semantic_segmentation/gcnet/pytorch/tools/convert_datasets/cityscapes.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/get_flops.py b/cv/semantic_segmentation/gcnet/pytorch/tools/get_flops.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/print_config.py b/cv/semantic_segmentation/gcnet/pytorch/tools/print_config.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/tools/test.py b/cv/semantic_segmentation/gcnet/pytorch/tools/test.py old mode 100755 new mode 100644 diff --git a/cv/semantic_segmentation/gcnet/pytorch/train.py b/cv/semantic_segmentation/gcnet/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/.gitignore b/cv/super_resolution/basicVSR++/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/LICENSE b/cv/super_resolution/basicVSR++/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/README.md b/cv/super_resolution/basicVSR++/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/build_env.sh b/cv/super_resolution/basicVSR++/pytorch/build_env.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/configs/basicvsr_plusplus/basicvsr_plusplus_c64n7_8x1_600k_reds4.py b/cv/super_resolution/basicVSR++/pytorch/configs/basicvsr_plusplus/basicvsr_plusplus_c64n7_8x1_600k_reds4.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/dist_train.sh b/cv/super_resolution/basicVSR++/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/docker/Dockerfile b/cv/super_resolution/basicVSR++/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/docker/README.md b/cv/super_resolution/basicVSR++/pytorch/docker/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/quantization.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/arraymisc/quantization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/alexnet.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/activation.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/context_block.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/drop.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hswish.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/non_local.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/norm.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/padding.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/plugin.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/registry.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/scale.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/swish.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/transformer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/upsample.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/resnet.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/weight_init.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/vgg.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/engine/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/engine/test.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/file_client.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/base.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/io.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/parse.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/colorspace.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/geometric.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/io.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/misc.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/image/photometric.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/deprecated_wrappers.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/info.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/modulated_deform_conv.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/modulated_deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/sync_bn.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/_functions.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/collate.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_container.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_parallel.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/registry.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/scatter_gather.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/utils.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_module.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_runner.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/checkpoint.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/default_constructor.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/dist_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/epoch_based_runner.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/fp16_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/closure.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/ema.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/evaluation.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/hook.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/base.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/text.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/memory.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/optimizer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/profiler.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/iter_based_runner.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/log_buffer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/priority.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/utils.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/config.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/env.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/ext_loader.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/logging.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/misc.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_jit.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_wrapper.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/path.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/progressbar.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/registry.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/testing.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/timer.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/trace.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/version_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmcv/version.py b/cv/super_resolution/basicVSR++/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/generation_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/generation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/inpainting_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/inpainting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/matting_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/matting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_face_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_face_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_video_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/restoration_video_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/test.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/train.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/video_interpolation_inference.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/apis/video_interpolation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/ema.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/mask.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/misc.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/dist_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/crop.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_pp.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_pp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/base.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/builder.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/aspp.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/aspp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/contextual_attention.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/contextual_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/conv.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/downsample.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/downsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/ensemble.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/ensemble.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gated_conv_module.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gated_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gca_module.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/gca_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/generation_model_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/generation_model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/img_normalize.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/img_normalize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/linear_module.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/linear_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/mask_conv_module.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/mask_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/model_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/partial_conv.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/partial_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/separable_conv_module.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/registry.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basicvsr.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/models/restorers/basicvsr.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/cli.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/cli.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/logger.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/setup_env.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/mmedit/version.py b/cv/super_resolution/basicVSR++/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/requirements.txt b/cv/super_resolution/basicVSR++/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/setup.py b/cv/super_resolution/basicVSR++/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR++/pytorch/train.py b/cv/super_resolution/basicVSR++/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/.gitignore b/cv/super_resolution/basicVSR/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/LICENSE b/cv/super_resolution/basicVSR/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/README.md b/cv/super_resolution/basicVSR/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/build_env.sh b/cv/super_resolution/basicVSR/pytorch/build_env.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/configs/basicvsr/basicvsr_reds4.py b/cv/super_resolution/basicVSR/pytorch/configs/basicvsr/basicvsr_reds4.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/configs/iconvsr/iconvsr_reds4.py b/cv/super_resolution/basicVSR/pytorch/configs/iconvsr/iconvsr_reds4.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/dist_train.sh b/cv/super_resolution/basicVSR/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/docker/Dockerfile b/cv/super_resolution/basicVSR/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/docker/README.md b/cv/super_resolution/basicVSR/pytorch/docker/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/quantization.py b/cv/super_resolution/basicVSR/pytorch/mmcv/arraymisc/quantization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/alexnet.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/activation.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/context_block.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/drop.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hswish.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/non_local.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/norm.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/padding.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/plugin.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/registry.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/scale.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/swish.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/transformer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/upsample.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/builder.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/resnet.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/weight_init.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/vgg.py b/cv/super_resolution/basicVSR/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/engine/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/engine/test.py b/cv/super_resolution/basicVSR/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/file_client.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/base.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/io.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/parse.py b/cv/super_resolution/basicVSR/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/colorspace.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/geometric.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/io.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/misc.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/image/photometric.py b/cv/super_resolution/basicVSR/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/info.py b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/ops/sync_bn.py b/cv/super_resolution/basicVSR/pytorch/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/_functions.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/collate.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_container.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_parallel.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/registry.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/scatter_gather.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/utils.py b/cv/super_resolution/basicVSR/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_module.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_runner.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/builder.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/checkpoint.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/default_constructor.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/dist_utils.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/epoch_based_runner.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/fp16_utils.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/closure.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/ema.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/evaluation.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/hook.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/base.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/text.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/memory.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/optimizer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/profiler.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/iter_based_runner.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/log_buffer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/builder.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/priority.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/runner/utils.py b/cv/super_resolution/basicVSR/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/config.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/env.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/ext_loader.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/logging.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/misc.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_jit.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_wrapper.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/path.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/progressbar.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/registry.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/testing.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/timer.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/trace.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/utils/version_utils.py b/cv/super_resolution/basicVSR/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmcv/version.py b/cv/super_resolution/basicVSR/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/generation_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/generation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/inpainting_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/inpainting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/matting_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/matting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_face_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_face_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_video_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/restoration_video_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/test.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/train.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py b/cv/super_resolution/basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/ema.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/mask.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/misc.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/dist_utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/crop.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py b/cv/super_resolution/basicVSR/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/edvr_net.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/edvr_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/iconvsr.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/backbones/sr_backbones/iconvsr.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/base.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/builder.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/aspp.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/aspp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/contextual_attention.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/contextual_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/conv.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/downsample.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/downsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/ensemble.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/ensemble.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gated_conv_module.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gated_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gca_module.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/gca_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/generation_model_utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/generation_model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/img_normalize.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/img_normalize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/linear_module.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/linear_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/mask_conv_module.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/mask_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/model_utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/partial_conv.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/partial_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/separable_conv_module.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/registry.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basicvsr.py b/cv/super_resolution/basicVSR/pytorch/mmedit/models/restorers/basicvsr.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/basicVSR/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/utils/cli.py b/cv/super_resolution/basicVSR/pytorch/mmedit/utils/cli.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/basicVSR/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/utils/logger.py b/cv/super_resolution/basicVSR/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/utils/setup_env.py b/cv/super_resolution/basicVSR/pytorch/mmedit/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/mmedit/version.py b/cv/super_resolution/basicVSR/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/requirements.txt b/cv/super_resolution/basicVSR/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/setup.py b/cv/super_resolution/basicVSR/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/basicVSR/pytorch/train.py b/cv/super_resolution/basicVSR/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/.gitignore b/cv/super_resolution/esrgan/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/LICENSE b/cv/super_resolution/esrgan/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/README.md b/cv/super_resolution/esrgan/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/configs/esrgan_psnr_x4c64b23g32_g1_1000k_div2k.py b/cv/super_resolution/esrgan/pytorch/configs/esrgan_psnr_x4c64b23g32_g1_1000k_div2k.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/dist_train.sh b/cv/super_resolution/esrgan/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/docker/Dockerfile b/cv/super_resolution/esrgan/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/docker/README.md b/cv/super_resolution/esrgan/pytorch/docker/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/get_div2k_anno.py b/cv/super_resolution/esrgan/pytorch/get_div2k_anno.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/alexnet.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/activation.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/context_block.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/drop.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hswish.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/non_local.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/norm.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/padding.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/plugin.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/registry.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/scale.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/swish.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/transformer.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/upsample.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/builder.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/resnet.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/weight_init.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/cnn/vgg.py b/cv/super_resolution/esrgan/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/engine/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/engine/test.py b/cv/super_resolution/esrgan/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/file_client.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/base.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/io.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/fileio/parse.py b/cv/super_resolution/esrgan/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/colorspace.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/geometric.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/io.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/misc.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/image/photometric.py b/cv/super_resolution/esrgan/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/_functions.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/collate.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_container.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_parallel.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/registry.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/scatter_gather.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/parallel/utils.py b/cv/super_resolution/esrgan/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/base_module.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/base_runner.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/builder.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/checkpoint.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/default_constructor.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/dist_utils.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/epoch_based_runner.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/fp16_utils.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/closure.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/ema.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/evaluation.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/hook.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/base.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/text.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/memory.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/optimizer.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/profiler.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/iter_based_runner.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/log_buffer.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/builder.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/priority.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/runner/utils.py b/cv/super_resolution/esrgan/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/__init__.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/config.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/env.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/ext_loader.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/logging.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/misc.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_jit.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_wrapper.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/path.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/progressbar.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/registry.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/testing.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/timer.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/trace.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/utils/version_utils.py b/cv/super_resolution/esrgan/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmcv/version.py b/cv/super_resolution/esrgan/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/generation_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/generation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/inpainting_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/inpainting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/matting_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/matting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_face_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_face_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_video_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/restoration_video_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/test.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/train.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/apis/video_interpolation_inference.py b/cv/super_resolution/esrgan/pytorch/mmedit/apis/video_interpolation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/esrgan/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/ema.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/mask.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/misc.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/utils/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/core/utils/dist_utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/comp1k_dataset.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/comp1k_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/crop.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_annotation_dataset.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_annotation_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_folder_dataset.py b/cv/super_resolution/esrgan/pytorch/mmedit/datasets/sr_folder_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/rrdb_net.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/backbones/sr_backbones/rrdb_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/base.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/builder.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/aspp.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/aspp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/contextual_attention.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/contextual_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/conv.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/downsample.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/downsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/ensemble.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/ensemble.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/gated_conv_module.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/gated_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/gca_module.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/gca_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/generation_model_utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/generation_model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/img_normalize.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/img_normalize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/linear_module.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/linear_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/mask_conv_module.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/mask_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/model_utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/partial_conv.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/partial_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/separable_conv_module.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/components/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/components/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/modified_vgg.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/components/discriminators/modified_vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/gan_loss.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/gan_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/perceptual_loss.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/perceptual_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/registry.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/esrgan.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/esrgan.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/srgan.py b/cv/super_resolution/esrgan/pytorch/mmedit/models/restorers/srgan.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/esrgan/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/utils/cli.py b/cv/super_resolution/esrgan/pytorch/mmedit/utils/cli.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/esrgan/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/utils/logger.py b/cv/super_resolution/esrgan/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/utils/setup_env.py b/cv/super_resolution/esrgan/pytorch/mmedit/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/mmedit/version.py b/cv/super_resolution/esrgan/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/requirements.txt b/cv/super_resolution/esrgan/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/esrgan/pytorch/train.py b/cv/super_resolution/esrgan/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/.gitignore b/cv/super_resolution/liif/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/LICENSE b/cv/super_resolution/liif/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/README.md b/cv/super_resolution/liif/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/configs/restorers/liif/README.md b/cv/super_resolution/liif/pytorch/configs/restorers/liif/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/configs/restorers/liif/README_zh-CN.md b/cv/super_resolution/liif/pytorch/configs/restorers/liif/README_zh-CN.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_edsr_norm_c64b16_g1_1000k_div2k.py b/cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_edsr_norm_c64b16_g1_1000k_div2k.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_rdn_norm_x2-4_c64b16_g1_1000k_div2k.py b/cv/super_resolution/liif/pytorch/configs/restorers/liif/liif_rdn_norm_x2-4_c64b16_g1_1000k_div2k.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/configs/restorers/liif/metafile.yml b/cv/super_resolution/liif/pytorch/configs/restorers/liif/metafile.yml old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/dist_test.sh b/cv/super_resolution/liif/pytorch/dist_test.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/dist_train.sh b/cv/super_resolution/liif/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/docker/Dockerfile b/cv/super_resolution/liif/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/docker/README.md b/cv/super_resolution/liif/pytorch/docker/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/__init__.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/dataloader.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/dataloader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/hierarchical_data_manager.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/hierarchical_data_manager.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/hook_wrapper.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/hook_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/model_wrapper.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/model_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/runner.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmcv/device/ipu/utils.py b/cv/super_resolution/liif/pytorch/mmcv/device/ipu/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/apis/generation_inference.py b/cv/super_resolution/liif/pytorch/mmedit/apis/generation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/liif/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/apis/test.py b/cv/super_resolution/liif/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/apis/train.py b/cv/super_resolution/liif/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/liif/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/liif/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/liif/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/hooks/ema.py b/cv/super_resolution/liif/pytorch/mmedit/core/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/liif/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/mask.py b/cv/super_resolution/liif/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/misc.py b/cv/super_resolution/liif/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/liif/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/liif/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/utils/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/core/utils/dist_utils.py b/cv/super_resolution/liif/pytorch/mmedit/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/generate_assistant.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/generate_assistant.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/random_down_sampling.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/random_down_sampling.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_dataset.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_gt_dataset.py b/cv/super_resolution/liif/pytorch/mmedit/datasets/sr_folder_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/liif_net.py b/cv/super_resolution/liif/pytorch/mmedit/models/backbones/sr_backbones/liif_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/base.py b/cv/super_resolution/liif/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/builder.py b/cv/super_resolution/liif/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/aspp.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/aspp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/contextual_attention.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/contextual_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/conv.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/downsample.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/downsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/ensemble.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/ensemble.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/gated_conv_module.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/gated_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/gca_module.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/gca_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/generation_model_utils.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/generation_model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/img_normalize.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/img_normalize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/linear_module.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/linear_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/mask_conv_module.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/mask_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/model_utils.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/partial_conv.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/partial_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/separable_conv_module.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/liif/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/components/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/components/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/mlp_refiner.py b/cv/super_resolution/liif/pytorch/mmedit/models/components/refiners/mlp_refiner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/liif/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/liif/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/registry.py b/cv/super_resolution/liif/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/liif/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/models/restorers/liif.py b/cv/super_resolution/liif/pytorch/mmedit/models/restorers/liif.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/liif/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/utils/cli.py b/cv/super_resolution/liif/pytorch/mmedit/utils/cli.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/liif/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/utils/logger.py b/cv/super_resolution/liif/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/utils/setup_env.py b/cv/super_resolution/liif/pytorch/mmedit/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/mmedit/version.py b/cv/super_resolution/liif/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/requirements.txt b/cv/super_resolution/liif/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/test.py b/cv/super_resolution/liif/pytorch/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/liif/pytorch/train.py b/cv/super_resolution/liif/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/.gitignore b/cv/super_resolution/real_basicVSR/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/LICENSE b/cv/super_resolution/real_basicVSR/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/README.md b/cv/super_resolution/real_basicVSR/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/build_env.sh b/cv/super_resolution/real_basicVSR/pytorch/build_env.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_c64b20_1x30x8_lr5e-5_150k_reds.py b/cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_c64b20_1x30x8_lr5e-5_150k_reds.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_wogan_c64b20_2x30x8_lr1e-4_300k_reds.py b/cv/super_resolution/real_basicVSR/pytorch/configs/real_basicvsr/realbasicvsr_wogan_c64b20_2x30x8_lr1e-4_300k_reds.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/crop_sub_images.py b/cv/super_resolution/real_basicVSR/pytorch/crop_sub_images.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/dist_train.sh b/cv/super_resolution/real_basicVSR/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/docker/Dockerfile b/cv/super_resolution/real_basicVSR/pytorch/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/docker/README.md b/cv/super_resolution/real_basicVSR/pytorch/docker/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/quantization.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/arraymisc/quantization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/alexnet.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/activation.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/context_block.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/drop.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hswish.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/non_local.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/norm.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/padding.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/plugin.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/registry.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/scale.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/swish.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/transformer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/upsample.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/resnet.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/weight_init.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/vgg.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/test.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/file_client.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/base.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/io.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/parse.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/colorspace.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/geometric.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/io.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/misc.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/photometric.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/common_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/modulated_deform_conv_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/cuda/sync_bn_cuda_kernel.cuh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cpp_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/common/pytorch_cuda_helper.hpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/modulated_deform_conv_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/cuda/sync_bn_cuda.cu old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/info.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/modulated_deform_conv_cpu.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/pybind.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/csrc/pytorch/sync_bn.cpp old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/deprecated_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/info.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/info.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/modulated_deform_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/sync_bn.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/ops/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/_functions.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/collate.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_container.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_parallel.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/registry.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/scatter_gather.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_runner.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/checkpoint.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/default_constructor.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/dist_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/epoch_based_runner.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/fp16_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/closure.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/ema.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/evaluation.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/hook.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/base.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/text.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/memory.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/optimizer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/profiler.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/iter_based_runner.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/log_buffer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/priority.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/config.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/env.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/ext_loader.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/logging.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/misc.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_jit.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_wrapper.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/path.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/progressbar.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/registry.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/testing.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/timer.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/trace.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/version_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmcv/version.py b/cv/super_resolution/real_basicVSR/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/generation_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/generation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/inpainting_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/inpainting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/matting_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/matting_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_face_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_face_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_video_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/restoration_video_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/test.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/train.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/apis/video_interpolation_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/ema.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/mask.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/misc.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/dist_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/core/utils/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/blur_kernels.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/blur_kernels.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/crop.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/matlab_like_resize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/random_degradations.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/random_degradations.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/basicvsr_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/real_basicvsr_net.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/backbones/sr_backbones/real_basicvsr_net.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/base.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/builder.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/aspp.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/aspp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/contextual_attention.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/contextual_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/conv.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/downsample.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/downsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/ensemble.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/ensemble.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gated_conv_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gated_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gca_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/gca_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/generation_model_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/generation_model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/img_normalize.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/img_normalize.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/linear_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/linear_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/mask_conv_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/mask_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/model_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/model_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/partial_conv.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/partial_conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/separable_conv_module.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/unet_disc.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/components/discriminators/unet_disc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/gan_loss.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/gan_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/perceptual_loss.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/perceptual_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/registry.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_basicvsr.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_basicvsr.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_esrgan.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/real_esrgan.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/srgan.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/models/restorers/srgan.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/cli.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/cli.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/logger.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/setup_env.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/utils/setup_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/mmedit/version.py b/cv/super_resolution/real_basicVSR/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/requirements.txt b/cv/super_resolution/real_basicVSR/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/setup.py b/cv/super_resolution/real_basicVSR/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/real_basicVSR/pytorch/train.py b/cv/super_resolution/real_basicVSR/pytorch/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/.gitignore b/cv/super_resolution/ttsr/pytorch/.gitignore old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/LICENSE b/cv/super_resolution/ttsr/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/README.md b/cv/super_resolution/ttsr/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/checkpoints/args.txt b/cv/super_resolution/ttsr/pytorch/checkpoints/args.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/checkpoints/train.log b/cv/super_resolution/ttsr/pytorch/checkpoints/train.log old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/dataset/cufed.py b/cv/super_resolution/ttsr/pytorch/dataset/cufed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/dataset/dataloader.py b/cv/super_resolution/ttsr/pytorch/dataset/dataloader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/eval.sh b/cv/super_resolution/ttsr/pytorch/eval.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/loss/discriminator.py b/cv/super_resolution/ttsr/pytorch/loss/discriminator.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/loss/loss.py b/cv/super_resolution/ttsr/pytorch/loss/loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/main.py b/cv/super_resolution/ttsr/pytorch/main.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/model/LTE.py b/cv/super_resolution/ttsr/pytorch/model/LTE.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/model/MainNet.py b/cv/super_resolution/ttsr/pytorch/model/MainNet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/model/SearchTransfer.py b/cv/super_resolution/ttsr/pytorch/model/SearchTransfer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/model/TTSR.py b/cv/super_resolution/ttsr/pytorch/model/TTSR.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/model/Vgg19.py b/cv/super_resolution/ttsr/pytorch/model/Vgg19.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/option.py b/cv/super_resolution/ttsr/pytorch/option.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/requirements.txt b/cv/super_resolution/ttsr/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/test.sh b/cv/super_resolution/ttsr/pytorch/test.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/test/demo/lr/0.png b/cv/super_resolution/ttsr/pytorch/test/demo/lr/0.png old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/test/demo/ref/0.png b/cv/super_resolution/ttsr/pytorch/test/demo/ref/0.png old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/train.sh b/cv/super_resolution/ttsr/pytorch/train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/trainer.py b/cv/super_resolution/ttsr/pytorch/trainer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttsr/pytorch/utils.py b/cv/super_resolution/ttsr/pytorch/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/LICENSE b/cv/super_resolution/ttvsr/pytorch/LICENSE old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/README.md b/cv/super_resolution/ttvsr/pytorch/README.md old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/configs/TTVSR_reds4.py b/cv/super_resolution/ttvsr/pytorch/configs/TTVSR_reds4.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/dist_train.sh b/cv/super_resolution/ttvsr/pytorch/dist_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/alexnet.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/alexnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/activation.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/activation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/context_block.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/context_block.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv2d_adaptive_padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_module.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_ws.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/conv_ws.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/depthwise_separable_conv_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/drop.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/drop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/generalized_attention.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/generalized_attention.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hsigmoid.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hsigmoid.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hswish.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/hswish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/non_local.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/non_local.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/norm.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/norm.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/padding.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/padding.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/plugin.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/plugin.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/registry.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/scale.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/scale.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/swish.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/swish.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/transformer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/transformer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/upsample.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/wrappers.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/bricks/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/builder.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/resnet.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/resnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/flops_counter.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/flops_counter.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/fuse_conv_bn.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/fuse_conv_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/sync_bn.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/sync_bn.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/weight_init.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/utils/weight_init.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/vgg.py b/cv/super_resolution/ttvsr/pytorch/mmcv/cnn/vgg.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/engine/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/engine/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/engine/test.py b/cv/super_resolution/ttvsr/pytorch/mmcv/engine/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/file_client.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/file_client.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/base.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/json_handler.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/json_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/pickle_handler.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/pickle_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/yaml_handler.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/handlers/yaml_handler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/io.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/parse.py b/cv/super_resolution/ttvsr/pytorch/mmcv/fileio/parse.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/colorspace.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/colorspace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/geometric.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/geometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/io.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/io.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/misc.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/image/photometric.py b/cv/super_resolution/ttvsr/pytorch/mmcv/image/photometric.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/_functions.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/_functions.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/collate.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/collate.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_container.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_container.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_parallel.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/data_parallel.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed_deprecated.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/distributed_deprecated.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/registry.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/scatter_gather.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/scatter_gather.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/utils.py b/cv/super_resolution/ttvsr/pytorch/mmcv/parallel/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_module.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_module.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_runner.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/base_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/builder.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/checkpoint.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/default_constructor.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/dist_utils.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/dist_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/epoch_based_runner.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/epoch_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/fp16_utils.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/fp16_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/checkpoint.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/checkpoint.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/closure.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/closure.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/ema.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/ema.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/evaluation.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/evaluation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/hook.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/hook.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/iter_timer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/iter_timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/base.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/dvclive.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/dvclive.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/mlflow.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/mlflow.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/neptune.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/neptune.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/pavi.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/pavi.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/tensorboard.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/tensorboard.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/text.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/text.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/wandb.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/logger/wandb.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/lr_updater.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/memory.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/memory.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/momentum_updater.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/momentum_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/optimizer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/optimizer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/profiler.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/profiler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sampler_seed.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sampler_seed.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sync_buffer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/hooks/sync_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/iter_based_runner.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/iter_based_runner.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/log_buffer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/log_buffer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/builder.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/default_constructor.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/optimizer/default_constructor.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/priority.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/priority.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/runner/utils.py b/cv/super_resolution/ttvsr/pytorch/mmcv/runner/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/config.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/config.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/env.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/ext_loader.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/ext_loader.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/logging.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/logging.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/misc.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_jit.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_jit.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_wrapper.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/parrots_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/path.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/path.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/progressbar.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/progressbar.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/registry.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/testing.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/testing.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/timer.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/timer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/trace.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/trace.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/utils/version_utils.py b/cv/super_resolution/ttvsr/pytorch/mmcv/utils/version_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmcv/version.py b/cv/super_resolution/ttvsr/pytorch/mmcv/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/apis/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/apis/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_inference.py b/cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_video_inference.py b/cv/super_resolution/ttvsr/pytorch/mmedit/apis/restoration_video_inference.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/apis/test.py b/cv/super_resolution/ttvsr/pytorch/mmedit/apis/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/apis/train.py b/cv/super_resolution/ttvsr/pytorch/mmedit/apis/train.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/distributed_wrapper.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/distributed_wrapper.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/eval_hooks.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/eval_hooks.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metric_utils.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metric_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metrics.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/metrics.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/niqe_pris_params.npz b/cv/super_resolution/ttvsr/pytorch/mmedit/core/evaluation/niqe_pris_params.npz old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/export/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/export/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/export/wrappers.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/export/wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/visualization.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/hooks/visualization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/mask.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/mask.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/misc.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/misc.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/builder.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/optimizer/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/lr_updater.py b/cv/super_resolution/ttvsr/pytorch/mmedit/core/scheduler/lr_updater.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_sr_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/base_sr_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/builder.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/dataset_wrappers.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/dataset_wrappers.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/augmentation.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/augmentation.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/compose.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/compose.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/crop.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/crop.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/formating.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/formating.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/generate_assistant.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/generate_assistant.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/loading.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/loading.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/matting_aug.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/matting_aug.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/normalization.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/normalization.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/random_down_sampling.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/random_down_sampling.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/utils.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/pipelines/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/registry.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/distributed_sampler.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/samplers/distributed_sampler.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_folder_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_reds_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_multiple_gt_dataset.py b/cv/super_resolution/ttvsr/pytorch/mmedit/datasets/sr_vimeo90k_multiple_gt_dataset.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/ttvsrnet.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/backbones/sr_backbones/ttvsrnet.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/base.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/base.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/builder.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/builder.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/flow_warp.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/flow_warp.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/sr_backbone_utils.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/sr_backbone_utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/upsample.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/common/upsample.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/pixelwise_loss.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/pixelwise_loss.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/utils.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/losses/utils.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/registry.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/registry.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/basic_restorer.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/basic_restorer.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/ttvsr.py b/cv/super_resolution/ttvsr/pytorch/mmedit/models/restorers/ttvsr.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/utils/__init__.py b/cv/super_resolution/ttvsr/pytorch/mmedit/utils/__init__.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/utils/collect_env.py b/cv/super_resolution/ttvsr/pytorch/mmedit/utils/collect_env.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/utils/logger.py b/cv/super_resolution/ttvsr/pytorch/mmedit/utils/logger.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/mmedit/version.py b/cv/super_resolution/ttvsr/pytorch/mmedit/version.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/requirements.txt b/cv/super_resolution/ttvsr/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/setup.py b/cv/super_resolution/ttvsr/pytorch/setup.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/tools/dist_test.sh b/cv/super_resolution/ttvsr/pytorch/tools/dist_test.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/tools/slurm_test.sh b/cv/super_resolution/ttvsr/pytorch/tools/slurm_test.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/tools/slurm_train.sh b/cv/super_resolution/ttvsr/pytorch/tools/slurm_train.sh old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/tools/test.py b/cv/super_resolution/ttvsr/pytorch/tools/test.py old mode 100755 new mode 100644 diff --git a/cv/super_resolution/ttvsr/pytorch/train.py b/cv/super_resolution/ttvsr/pytorch/train.py old mode 100755 new mode 100644 diff --git a/fairseq-tools/README_bart.md b/fairseq-tools/README_bart.md new file mode 100644 index 00000000..17a964ff --- /dev/null +++ b/fairseq-tools/README_bart.md @@ -0,0 +1,51 @@ +# Bart + +## Model description +BART is sequence-to-sequence model trained with denoising as pretraining objective. We show that this pretraining objective is more generic and show that we can match RoBERTa results on SQuAD and GLUE and gain state-of-the-art results on summarization (XSum, CNN dataset), long form generative question answering (ELI5) and dialog response genration (ConvAI2). + +## Download data + +``` +cd fairseq +mkdir -p glue_data + +cd glue_data +wget https://dl.fbaipublicfiles.com/glue/data/RTE.zip + +unzip RTE.zip +rm -rf RTE.zip +``` + +## Preprocess data + +``` +cd .. +./examples/roberta/preprocess_GLUE_tasks.sh glue_data RTE +``` + +## Download pretrain weight + +``` +wget https://dl.fbaipublicfiles.com/fairseq/models/bart.large.tar.gz +tar -xzvf bart.large.tar.gz +``` + +## Finetune on CLUE RTE task + +``` +bash bart.sh +``` + +## Inference on GLUE RTE task + +``` +python3 bart.py +``` + +## Results on BI-V100 + +``` +| GPUs | FPS | Train Epochs | Accuracy | +|------|-----|--------------|------| +| 1x8 | | 10 | 85.2 | +``` \ No newline at end of file diff --git a/fairseq-tools/README_convolutional.md b/fairseq-tools/README_convolutional.md new file mode 100644 index 00000000..e933c9f8 --- /dev/null +++ b/fairseq-tools/README_convolutional.md @@ -0,0 +1,51 @@ +# Convolutional + +## Model description +The following instructions can be used to train a Convolutional translation model on the WMT English to German dataset. + +## Download and preprocess data + +``` +cd fairseq/examples/translation/ +bash prepare-wmt14en2de.sh +cd ../.. + +TEXT=examples/translation/wmt17_en_de +fairseq-preprocess \ + --source-lang en --target-lang de \ + --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \ + --destdir data-bin/wmt17_en_de --thresholdtgt 0 --thresholdsrc 0 \ + --workers 20 +``` + +## Train + +``` +mkdir -p checkpoints/fconv_wmt_en_de +fairseq-train \ + data-bin/wmt17_en_de \ + --arch fconv_wmt_en_de \ + --max-epoch 100 \ + --dropout 0.2 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --optimizer nag --clip-norm 0.1 \ + --lr 0.5 --lr-scheduler fixed --force-anneal 50 \ + --max-tokens 4000 \ + --no-epoch-checkpoints \ + --save-dir checkpoints/fconv_wmt_en_de +``` + +## Evaluate + +``` +fairseq-generate data-bin/wmt17_en_de \ + --path checkpoints/fconv_wmt_en_de/checkpoint_best.pt \ + --beam 5 --remove-bpe +``` + +## Results on BI-V100 + +``` +| GPUs | FPS | Train Epochs | Bleu | +|------|-----|--------------|------| +| 1x8 | | 100 | | \ No newline at end of file diff --git a/fairseq-tools/README_environment.md b/fairseq-tools/README_environment.md new file mode 100644 index 00000000..0f123243 --- /dev/null +++ b/fairseq-tools/README_environment.md @@ -0,0 +1,13 @@ +# Fairseq + +## Description +Fairseq(-py) is a sequence modeling toolkit that allows researchers and developers to train custom models for translation, summarization, language modeling and other text generation tasks. + +## Environment + +``` +cd fairseq +python3 setup.py develop +pip install sacrebleu==1.5.1, dataclasses, hydra-core, regex +``` + diff --git a/fairseq-tools/README_roberta.md b/fairseq-tools/README_roberta.md new file mode 100644 index 00000000..14067cec --- /dev/null +++ b/fairseq-tools/README_roberta.md @@ -0,0 +1,51 @@ +# Roberta + +## Model description +RoBERTa iterates on BERT's pretraining procedure, including training the model longer, with bigger batches over more data; removing the next sentence prediction objective; training on longer sequences; and dynamically changing the masking pattern applied to the training data. + +## Download data + +``` +cd fairseq +mkdir -p glue_data + +cd glue_data +wget https://dl.fbaipublicfiles.com/glue/data/RTE.zip + +unzip RTE.zip +rm -rf RTE.zip +``` + +## Preprocess data + +``` +cd .. +./examples/roberta/preprocess_GLUE_tasks.sh glue_data RTE +``` + +## Download pretrain weight + +``` +wget https://dl.fbaipublicfiles.com/fairseq/models/roberta.large.tar.gz +tar -xzvf roberta.large.tar.gz +``` + +## Finetune on CLUE RTE task + +``` +bash roberta.sh +``` + +## Inference on GLUE RTE task + +``` +python3 roberta.py +``` + +## Results on BI-V100 + +``` +| GPUs | FPS | Train Epochs | Accuracy | +|------|-----|--------------|------| +| 1x8 | | 10 | 79.4 | +``` \ No newline at end of file diff --git a/fairseq-tools/README_transformer.md b/fairseq-tools/README_transformer.md new file mode 100644 index 00000000..3dfada57 --- /dev/null +++ b/fairseq-tools/README_transformer.md @@ -0,0 +1,57 @@ +# Transformer + +## Model description +The following instructions can be used to train a Transformer model on the IWSLT'14 German to English dataset. + +## Download and preprocess data + +``` +cd fairseq/examples/translation/ +bash prepare-iwslt14.sh +cd ../.. + +TEXT=examples/translation/iwslt14.tokenized.de-en +fairseq-preprocess --source-lang de --target-lang en \ + --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \ + --destdir data-bin/iwslt14.tokenized.de-en \ + --workers 20 +``` + +## Train + +``` +mkdir -p checkpoints/transformer +fairseq-train \ + data-bin/iwslt14.tokenized.de-en \ + --arch transformer_iwslt_de_en --share-decoder-input-output-embed \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr 5e-4 --lr-scheduler inverse_sqrt --warmup-updates 4000 \ + --dropout 0.3 --weight-decay 0.0001 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --max-tokens 4096 \ + --max-epoch 100 \ + --eval-bleu \ + --eval-bleu-args '{"beam": 5, "max_len_a": 1.2, "max_len_b": 10}' \ + --eval-bleu-detok moses \ + --eval-bleu-remove-bpe \ + --eval-bleu-print-samples \ + --save-dir checkpoints/transformer \ + --no-epoch-checkpoints \ + --best-checkpoint-metric bleu --maximize-best-checkpoint-metric +``` + +## Evaluate + +``` +fairseq-generate data-bin/iwslt14.tokenized.de-en \ + --path checkpoints/transformer/checkpoint_best.pt \ + --batch-size 128 --beam 5 --remove-bpe +``` + +## Results on BI-V100 + +``` +| GPUs | FPS | Train Epochs | Bleu | +|------|-----|--------------|------| +| 1x8 | | 100 | 34.59 | +``` \ No newline at end of file diff --git a/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE.md b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..5c4c4493 --- /dev/null +++ b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,3 @@ +## 👉 [Please follow one of these issue templates](https://github.com/pytorch/fairseq/issues/new/choose) 👈 + +Note: to keep the backlog clean and actionable, issues may be immediately closed if they do not follow one of the above issue templates. diff --git a/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/bug_report.md b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..a7f4f0a9 --- /dev/null +++ b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,43 @@ +--- +name: 🐛 Bug Report +about: Submit a bug report to help us improve +labels: 'bug, needs triage' +--- + +## 🐛 Bug + + + +### To Reproduce + +Steps to reproduce the behavior (**always include the command you ran**): + +1. Run cmd '....' +2. See error + + + + +#### Code sample + + +### Expected behavior + + + +### Environment + + - fairseq Version (e.g., 1.0 or master): + - PyTorch Version (e.g., 1.0) + - OS (e.g., Linux): + - How you installed fairseq (`pip`, source): + - Build command you used (if compiling from source): + - Python version: + - CUDA/cuDNN version: + - GPU models and configuration: + - Any other relevant information: + +### Additional context + + diff --git a/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/documentation.md b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 00000000..3a6e2e9e --- /dev/null +++ b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,15 @@ +--- +name: 📚 Documentation/Typos +about: Report an issue related to documentation or a typo +labels: 'documentation, needs triage' +--- + +## 📚 Documentation + +For typos and doc fixes, please go ahead and: + +1. Create an issue. +2. Fix the typo. +3. Submit a PR. + +Thanks! diff --git a/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/feature_request.md b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..93c86680 --- /dev/null +++ b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: 🚀 Feature Request +about: Submit a proposal/request for a new feature +labels: 'enhancement, help wanted, needs triage' +--- + +## 🚀 Feature Request + + +### Motivation + + + +### Pitch + + + +### Alternatives + + + +### Additional context + + diff --git a/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/how-to-question.md b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/how-to-question.md new file mode 100644 index 00000000..4beb180d --- /dev/null +++ b/fairseq-tools/fairseq/.github/ISSUE_TEMPLATE/how-to-question.md @@ -0,0 +1,33 @@ +--- +name: ❓ Questions/Help +about: If you have questions, please first search existing issues and docs +labels: 'question, needs triage' +--- + +## ❓ Questions and Help + +### Before asking: +1. search the issues. +2. search the docs. + + + +#### What is your question? + +#### Code + + + +#### What have you tried? + +#### What's your environment? + + - fairseq Version (e.g., 1.0 or master): + - PyTorch Version (e.g., 1.0) + - OS (e.g., Linux): + - How you installed fairseq (`pip`, source): + - Build command you used (if compiling from source): + - Python version: + - CUDA/cuDNN version: + - GPU models and configuration: + - Any other relevant information: diff --git a/fairseq-tools/fairseq/.github/PULL_REQUEST_TEMPLATE.md b/fairseq-tools/fairseq/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..b28ff98e --- /dev/null +++ b/fairseq-tools/fairseq/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +# Before submitting + +- [ ] Was this discussed/approved via a Github issue? (no need for typos, doc improvements) +- [ ] Did you read the [contributor guideline](https://github.com/pytorch/fairseq/blob/master/CONTRIBUTING.md)? +- [ ] Did you make sure to update the docs? +- [ ] Did you write any new necessary tests? + +## What does this PR do? +Fixes # (issue). + +## PR review +Anyone in the community is free to review the PR once the tests have passed. +If we didn't discuss your PR in Github issues there's a high chance it will not be merged. + +## Did you have fun? +Make sure you had fun coding 🙃 diff --git a/fairseq-tools/fairseq/.github/workflows/build.yml b/fairseq-tools/fairseq/.github/workflows/build.yml new file mode 100644 index 00000000..a2d44dd5 --- /dev/null +++ b/fairseq-tools/fairseq/.github/workflows/build.yml @@ -0,0 +1,50 @@ +name: build + +on: + # Trigger the workflow on push to master or any pull request + push: + branches: + - master + pull_request: + +jobs: + build: + + strategy: + max-parallel: 4 + matrix: + platform: [ubuntu-latest, macos-latest] + python-version: [3.6, 3.7] + + runs-on: ${{ matrix.platform }} + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Conditionally install pytorch + if: matrix.platform == 'windows-latest' + run: pip3 install torch -f https://download.pytorch.org/whl/torch_stable.html + + - name: Install locally + run: | + python -m pip install --upgrade pip + git submodule update --init --recursive + python setup.py build_ext --inplace + python -m pip install --editable . + + - name: Lint with flake8 + run: | + pip install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --extend-exclude fairseq/model_parallel/megatron + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --extend-exclude fairseq/model_parallel/megatron + + - name: Run tests + run: | + python setup.py test diff --git a/fairseq-tools/fairseq/.github/workflows/build_wheels.yml b/fairseq-tools/fairseq/.github/workflows/build_wheels.yml new file mode 100644 index 00000000..72617085 --- /dev/null +++ b/fairseq-tools/fairseq/.github/workflows/build_wheels.yml @@ -0,0 +1,41 @@ +name: build_wheels + +on: + push: + branches: + - v[0-9]+.[0-9]+.[x0-9]+ + tags: + - v* + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + steps: + - uses: actions/checkout@v2 + + - name: Install Python + uses: actions/setup-python@v2 + with: + python-version: '3.7' + + - name: Install cibuildwheel + run: | + python -m pip install cibuildwheel + + - name: Build wheels for CPython + run: | + python -m cibuildwheel --output-dir dist + env: + CIBW_BUILD: "cp36-*64 cp37-*64 cp38-*64" + CIBW_MANYLINUX_X86_64_IMAGE: manylinux1 + CIBW_BEFORE_BUILD: git submodule update --init --recursive && pip install . + + - uses: actions/upload-artifact@v2 + with: + name: wheels + path: ./dist/*.whl diff --git a/fairseq-tools/fairseq/.gitignore b/fairseq-tools/fairseq/.gitignore new file mode 100644 index 00000000..a7c45771 --- /dev/null +++ b/fairseq-tools/fairseq/.gitignore @@ -0,0 +1,132 @@ +# JetBrains PyCharm IDE +.idea/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# macOS dir files +.DS_Store + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Checkpoints +checkpoints + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Generated files +/fairseq/temporal_convolution_tbc +/fairseq/modules/*_layer/*_forward.cu +/fairseq/modules/*_layer/*_backward.cu + +# data +data-bin/ + +# reranking +/examples/reranking/rerank_data + +# Cython-generated C++ source files +/fairseq/data/data_utils_fast.cpp +/fairseq/data/token_block_utils_fast.cpp + +# VSCODE +.vscode/ftp-sync.json +.vscode/settings.json + +# Experimental Folder +experimental/* diff --git a/fairseq-tools/fairseq/.gitmodules b/fairseq-tools/fairseq/.gitmodules new file mode 100644 index 00000000..07a55d45 --- /dev/null +++ b/fairseq-tools/fairseq/.gitmodules @@ -0,0 +1,4 @@ +[submodule "fairseq/model_parallel/megatron"] + path = fairseq/model_parallel/megatron + url = https://github.com/ngoyal2707/Megatron-LM + branch = fairseq diff --git a/fairseq-tools/fairseq/CODE_OF_CONDUCT.md b/fairseq-tools/fairseq/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..a0cbeaab --- /dev/null +++ b/fairseq-tools/fairseq/CODE_OF_CONDUCT.md @@ -0,0 +1,77 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq + diff --git a/fairseq-tools/fairseq/CONTRIBUTING.md b/fairseq-tools/fairseq/CONTRIBUTING.md new file mode 100644 index 00000000..4d7ca6a9 --- /dev/null +++ b/fairseq-tools/fairseq/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing to Facebook AI Research Sequence-to-Sequence Toolkit (fairseq) +We want to make contributing to this project as easy and transparent as +possible. + +## Pull Requests +We actively welcome your pull requests. + +1. Fork the repo and create your branch from `master`. +2. If you've added code that should be tested, add tests. +3. If you've changed APIs, update the documentation. +4. Ensure the test suite passes. +5. Make sure your code lints. +6. If you haven't already, complete the Contributor License Agreement ("CLA"). + +## Contributor License Agreement ("CLA") +In order to accept your pull request, we need you to submit a CLA. You only need +to do this once to work on any of Facebook's open source projects. + +Complete your CLA here: + +## Issues +We use GitHub issues to track public bugs. Please ensure your description is +clear and has sufficient instructions to be able to reproduce the issue. + +## License +By contributing to Facebook AI Research Sequence-to-Sequence Toolkit (fairseq), +you agree that your contributions will be licensed under the LICENSE file in +the root directory of this source tree. diff --git a/fairseq-tools/fairseq/LICENSE b/fairseq-tools/fairseq/LICENSE new file mode 100644 index 00000000..b96dcb04 --- /dev/null +++ b/fairseq-tools/fairseq/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/fairseq-tools/fairseq/bart.py b/fairseq-tools/fairseq/bart.py new file mode 100644 index 00000000..0e304759 --- /dev/null +++ b/fairseq-tools/fairseq/bart.py @@ -0,0 +1,40 @@ +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from fairseq.models.bart import BARTModel + +bart = BARTModel.from_pretrained( + 'checkpoints/bart', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='RTE-bin' +) + +label_fn = lambda label: bart.task.label_dictionary.string( + [label + bart.task.label_dictionary.nspecial] +) +ncorrect, nsamples = 0, 0 +bart.cuda() +bart.eval() +with open('glue_data/RTE/dev.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[1], tokens[2], tokens[3] + tokens = bart.encode(sent1, sent2) + prediction = bart.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_fn(prediction) + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) \ No newline at end of file diff --git a/fairseq-tools/fairseq/bart.sh b/fairseq-tools/fairseq/bart.sh new file mode 100644 index 00000000..7a83011b --- /dev/null +++ b/fairseq-tools/fairseq/bart.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +set -ex + +TOTAL_NUM_UPDATES=2036 # 10 epochs through RTE for bsz 16 +WARMUP_UPDATES=61 # 6 percent of the number of updates +LR=1e-05 # Peak LR for polynomial LR scheduler. +NUM_CLASSES=2 +MAX_SENTENCES=16 # Batch size. +BART_PATH=bart.large/model.pt + +mkdir -p checkpoints/bart +fairseq-train RTE-bin/ \ + --restore-file $BART_PATH \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --add-prev-output-tokens \ + --layernorm-embedding \ + --share-all-embeddings \ + --share-decoder-input-output-embed \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 \ + --arch bart_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.01 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-08 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --save-dir checkpoints/bart \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric; \ No newline at end of file diff --git a/fairseq-tools/fairseq/config/config.yaml b/fairseq-tools/fairseq/config/config.yaml new file mode 100644 index 00000000..66723e70 --- /dev/null +++ b/fairseq-tools/fairseq/config/config.yaml @@ -0,0 +1,7 @@ +defaults: + - params: training_params + - task: language_modeling + - model: transformer_lm + - criterion: cross_entropy + - optimizer: adam + - lr_scheduler: inverse_sqrt diff --git a/fairseq-tools/fairseq/config/config_eval_lm.yaml b/fairseq-tools/fairseq/config/config_eval_lm.yaml new file mode 100644 index 00000000..5a93cb5d --- /dev/null +++ b/fairseq-tools/fairseq/config/config_eval_lm.yaml @@ -0,0 +1,7 @@ +defaults: + - params: eval_lm_params + - task: language_modeling + - model: transformer_lm + - criterion: cross_entropy + - optimizer: adam + - lr_scheduler: inverse_sqrt diff --git a/fairseq-tools/fairseq/config/criterion/adaptive_loss.yaml b/fairseq-tools/fairseq/config/criterion/adaptive_loss.yaml new file mode 100644 index 00000000..a85a7eed --- /dev/null +++ b/fairseq-tools/fairseq/config/criterion/adaptive_loss.yaml @@ -0,0 +1,3 @@ +# @package _group_ +sentence_avg: ${params.optimization.sentence_avg} +ddp_backend: ${params.distributed_training.ddp_backend} diff --git a/fairseq-tools/fairseq/config/criterion/cross_entropy.yaml b/fairseq-tools/fairseq/config/criterion/cross_entropy.yaml new file mode 100644 index 00000000..a85a7eed --- /dev/null +++ b/fairseq-tools/fairseq/config/criterion/cross_entropy.yaml @@ -0,0 +1,3 @@ +# @package _group_ +sentence_avg: ${params.optimization.sentence_avg} +ddp_backend: ${params.distributed_training.ddp_backend} diff --git a/fairseq-tools/fairseq/config/lr_scheduler/cosine.yaml b/fairseq-tools/fairseq/config/lr_scheduler/cosine.yaml new file mode 100644 index 00000000..0f91e0d2 --- /dev/null +++ b/fairseq-tools/fairseq/config/lr_scheduler/cosine.yaml @@ -0,0 +1,7 @@ +# @package _group_ +warmup_updates: 0 +warmup_init_lr: -1 +max_lr: 1.0 +t_mult: 1.0 +lr_period_updates: -1 +lr_shrink: 0.1 diff --git a/fairseq-tools/fairseq/config/lr_scheduler/inverse_sqrt.yaml b/fairseq-tools/fairseq/config/lr_scheduler/inverse_sqrt.yaml new file mode 100644 index 00000000..0eac7d88 --- /dev/null +++ b/fairseq-tools/fairseq/config/lr_scheduler/inverse_sqrt.yaml @@ -0,0 +1,3 @@ +# @package _group_ +warmup_updates: 4000 +warmup_init_lr: -1 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm.yaml b/fairseq-tools/fairseq/config/model/transformer_lm.yaml new file mode 100644 index 00000000..3837ea54 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.1 +attention_dropout: 0.0 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 512 +decoder_output_dim: 512 +decoder_input_dim: 512 +decoder_ffn_embed_dim: 2048 +decoder_layers: 6 +decoder_attention_heads: 8 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_baevski_gbw.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_baevski_gbw.yaml new file mode 100644 index 00000000..30b1a4f1 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_baevski_gbw.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 512 +decoder_output_dim: 512 +decoder_input_dim: 512 +decoder_ffn_embed_dim: 4096 +decoder_layers: 12 +decoder_attention_heads: 16 +decoder_normalize_before: true +no_decoder_final_norm: true +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_baevski_wiki103.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_baevski_wiki103.yaml new file mode 100644 index 00000000..1154cfa6 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_baevski_wiki103.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.3 +attention_dropout: 0.1 +activation_dropout: 0.1 +relu_dropout: 0.1 +decoder_embed_dim: 1024 +decoder_output_dim: 1024 +decoder_input_dim: 1024 +decoder_ffn_embed_dim: 4096 +decoder_layers: 16 +decoder_attention_heads: 8 +decoder_normalize_before: true +no_decoder_final_norm: true +adaptive_softmax_cutoff: "20000,60000" +adaptive_softmax_dropout: 0.2 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: true +adaptive_input_factor: 4 +adaptive_input_cutoff: "20000,60000" +tie_adaptive_weights: true +tie_adaptive_proj: true +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_big.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_big.yaml new file mode 100644 index 00000000..30957531 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_big.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.1 +attention_dropout: 0.0 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 1024 +decoder_output_dim: 1024 +decoder_input_dim: 1024 +decoder_ffn_embed_dim: 4096 +decoder_layers: 12 +decoder_attention_heads: 16 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_gbw.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_gbw.yaml new file mode 100644 index 00000000..30b1a4f1 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_gbw.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 512 +decoder_output_dim: 512 +decoder_input_dim: 512 +decoder_ffn_embed_dim: 4096 +decoder_layers: 12 +decoder_attention_heads: 16 +decoder_normalize_before: true +no_decoder_final_norm: true +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_gpt.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_gpt.yaml new file mode 100644 index 00000000..2c6cb7be --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_gpt.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "gelu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 768 +decoder_output_dim: 768 +decoder_input_dim: 768 +decoder_ffn_embed_dim: 3072 +decoder_layers: 12 +decoder_attention_heads: 12 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_big.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_big.yaml new file mode 100644 index 00000000..a08769a1 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_big.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "gelu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 1600 +decoder_output_dim: 1600 +decoder_input_dim: 1600 +decoder_ffn_embed_dim: 6400 +decoder_layers: 48 +decoder_attention_heads: 25 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_medium.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_medium.yaml new file mode 100644 index 00000000..64261d79 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_medium.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "gelu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 1280 +decoder_output_dim: 1280 +decoder_input_dim: 1280 +decoder_ffn_embed_dim: 5120 +decoder_layers: 36 +decoder_attention_heads: 20 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_small.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_small.yaml new file mode 100644 index 00000000..702e81f4 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_gpt2_small.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "gelu" +dropout: 0.1 +attention_dropout: 0.1 +activation_dropout: 0.0 +relu_dropout: 0.0 +decoder_embed_dim: 1024 +decoder_output_dim: 1024 +decoder_input_dim: 1024 +decoder_ffn_embed_dim: 4096 +decoder_layers: 24 +decoder_attention_heads: 16 +decoder_normalize_before: true +no_decoder_final_norm: false +adaptive_softmax_cutoff: null +adaptive_softmax_dropout: 0 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: false +adaptive_input_factor: 4 +adaptive_input_cutoff: null +tie_adaptive_weights: false +tie_adaptive_proj: false +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/model/transformer_lm_wiki103.yaml b/fairseq-tools/fairseq/config/model/transformer_lm_wiki103.yaml new file mode 100644 index 00000000..1154cfa6 --- /dev/null +++ b/fairseq-tools/fairseq/config/model/transformer_lm_wiki103.yaml @@ -0,0 +1,36 @@ +# @package _group_ +activation_fn: "relu" +dropout: 0.3 +attention_dropout: 0.1 +activation_dropout: 0.1 +relu_dropout: 0.1 +decoder_embed_dim: 1024 +decoder_output_dim: 1024 +decoder_input_dim: 1024 +decoder_ffn_embed_dim: 4096 +decoder_layers: 16 +decoder_attention_heads: 8 +decoder_normalize_before: true +no_decoder_final_norm: true +adaptive_softmax_cutoff: "20000,60000" +adaptive_softmax_dropout: 0.2 +adaptive_softmax_factor: 4 +no_token_positional_embeddings: false +share_decoder_input_output_embed: false +character_embeddings: false +character_filters: "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]" +character_embedding_dim: 4 +char_embedder_highway_layers: 2 +adaptive_input: true +adaptive_input_factor: 4 +adaptive_input_cutoff: "20000,60000" +tie_adaptive_weights: true +tie_adaptive_proj: true +decoder_learned_pos: false +decoder_layerdrop: 0 +decoder_layers_to_keep: null +layernorm_embedding: false +no_scale_embedding: false +quant_noise_pq: 0 +quant_noise_pq_block_size: 8 +quant_noise_scalar: 0 diff --git a/fairseq-tools/fairseq/config/optimizer/adam.yaml b/fairseq-tools/fairseq/config/optimizer/adam.yaml new file mode 100644 index 00000000..e5264f89 --- /dev/null +++ b/fairseq-tools/fairseq/config/optimizer/adam.yaml @@ -0,0 +1,5 @@ +# @package _group_ +adam_betas: "(0.9, 0.999)" +adam_eps: 1.0e-8 +weight_decay: 0 +use_old_adam: false diff --git a/fairseq-tools/fairseq/config/optimizer/nag.yaml b/fairseq-tools/fairseq/config/optimizer/nag.yaml new file mode 100644 index 00000000..4ab27456 --- /dev/null +++ b/fairseq-tools/fairseq/config/optimizer/nag.yaml @@ -0,0 +1,3 @@ +# @package _group_ +momentum: 0.99 +weight_decay: 0.0 diff --git a/fairseq-tools/fairseq/config/params/eval_lm_params.yaml b/fairseq-tools/fairseq/config/params/eval_lm_params.yaml new file mode 100644 index 00000000..6f27055d --- /dev/null +++ b/fairseq-tools/fairseq/config/params/eval_lm_params.yaml @@ -0,0 +1,105 @@ +# @package _group_ +common: + no_progress_bar: false + log_interval: 100 + log_format: null + tensorboard_logdir: null + seed: 1 + cpu: false + fp16: false + memory_efficient_fp16: false + fp16_no_flatten_grads: false + fp16_init_scale: 128 + fp16_scale_window: null + fp16_scale_tolerance: 0.0 + min_loss_scale: 1.0e-4 + threshold_loss_scale: null + user_dir: null + empty_cache_freq: 0 + all_gather_list_size: 16384 + model_parallel_size: 1 + checkpoint_suffix: "" + quantization_config_path: null +distributed_training: + distributed_rank: 0 + distributed_backend: "nccl" + distributed_init_method: null + distributed_port: -1 + device_id: 0 + local_rank: 0 + distributed_no_spawn: false + ddp_backend: "c10d" + bucket_cap_mb: 25 + fix_batches_to_gpus: false + find_unused_parameters: false + fast_stat_sync: false + broadcast_buffers: false + distributed_wrapper: "DDP" + slowmo_momentum: null + slowmo_algorithm: "LocalSGD" + localsgd_frequency: 3 +dataset: + num_workers: 1 + skip_invalid_size_inputs_valid_test: false + max_tokens: null + batch_size: ${params.dataset.batch_size} + required_batch_size_multiple: 8 + dataset_impl: null + data_buffer_size: 10 + train_subset: "train" + valid_subset: "valid" + validate_interval: 1 + fixed_validation_seed: null + disable_validation: false + curriculum: 0 + gen_subset: "test" + num_shards: 1 + shard_id: 0 + max_tokens_valid: ${params.dataset.max_tokens} + batch_size_valid: ${params.dataset.batch_size} +optimization: + max_epoch: 0 + max_update: 0 + clip_norm: 25.0 + sentence_avg: false + update_freq: [1] + lr: [0.25] + min_lr: -1.0 + use_bmuf: false +checkpoint: + save_dir: "checkpoints" + restore_file: "checkpoint_last.pt" + reset_dataloader: false + reset_lr_scheduler: false + reset_meters: false + reset_optimizer: false + optimizer_overrides: "{}" + save_interval: 1 + save_interval_updates: 0 + keep_interval_updates: -1 + keep_last_epochs: -1 + keep_best_checkpoints: -1 + no_save: false + no_epoch_checkpoints: false + no_last_checkpoints: false + no_save_optimizer_state: false + best_checkpoint_metric: "loss" + maximize_best_checkpoint_metric: false + patience: -1 +common_eval: + path: null + remove_bpe: null + quiet: false + model_overrides: "{}" + results_path: null +eval_lm: + output_word_probs: false + output_word_stats: false + context_window: 0 +bmuf: + block_lr: 1 + block_momentum: 0.875 + global_sync_iter: 50 + warmup_iterations: 500 + use_nbm: false + average_sync: false diff --git a/fairseq-tools/fairseq/config/params/training_params.yaml b/fairseq-tools/fairseq/config/params/training_params.yaml new file mode 100644 index 00000000..2ce94f92 --- /dev/null +++ b/fairseq-tools/fairseq/config/params/training_params.yaml @@ -0,0 +1,95 @@ +# @package _group_ +common: + no_progress_bar: false + log_interval: 100 + log_format: null + tensorboard_logdir: null + seed: 1 + cpu: false + fp16: false + memory_efficient_fp16: false + fp16_no_flatten_grads: false + fp16_init_scale: 128 + fp16_scale_window: null + fp16_scale_tolerance: 0.0 + min_loss_scale: 1.0e-4 + threshold_loss_scale: null + user_dir: null + empty_cache_freq: 0 + all_gather_list_size: 16384 + model_parallel_size: 1 + checkpoint_suffix: "" + quantization_config_path: null +distributed_training: + distributed_rank: 0 + distributed_backend: "nccl" + distributed_init_method: null + distributed_port: -1 + device_id: 0 + local_rank: 0 + distributed_no_spawn: false + ddp_backend: "c10d" + bucket_cap_mb: 25 + fix_batches_to_gpus: false + find_unused_parameters: false + fast_stat_sync: false + broadcast_buffers: false + distributed_wrapper: "DDP" + slowmo_momentum: null + slowmo_algorithm: "LocalSGD" + localsgd_frequency: 3 +dataset: + num_workers: 1 + skip_invalid_size_inputs_valid_test: false + max_tokens: null + batch_size: ${params.dataset.batch_size} + required_batch_size_multiple: 8 + dataset_impl: null + data_buffer_size: 10 + train_subset: "train" + valid_subset: "valid" + validate_interval: 1 + fixed_validation_seed: null + disable_validation: false + curriculum: 0 + gen_subset: "test" + num_shards: 1 + shard_id: 0 + max_tokens_valid: ${params.dataset.max_tokens} + batch_size_valid: ${params.dataset.batch_size} +optimization: + max_epoch: 0 + max_update: 0 + clip_norm: 25.0 + sentence_avg: false + update_freq: [1] + lr: [0.25] + min_lr: -1.0 + use_bmuf: false +checkpoint: + save_dir: "checkpoints" + restore_file: "checkpoint_last.pt" + reset_dataloader: false + reset_lr_scheduler: false + reset_meters: false + reset_optimizer: false + optimizer_overrides: "{}" + save_interval: 1 + save_interval_updates: 0 + keep_interval_updates: -1 + keep_last_epochs: -1 + keep_best_checkpoints: -1 + no_save: false + no_epoch_checkpoints: false + no_last_checkpoints: false + no_save_optimizer_state: false + best_checkpoint_metric: "loss" + maximize_best_checkpoint_metric: false + patience: -1 +bmuf: + block_lr: 1 + block_momentum: 0.875 + global_sync_iter: 50 + warmup_iterations: 500 + use_nbm: false + average_sync: false diff --git a/fairseq-tools/fairseq/config/task/language_modeling.yaml b/fairseq-tools/fairseq/config/task/language_modeling.yaml new file mode 100644 index 00000000..58a2ad13 --- /dev/null +++ b/fairseq-tools/fairseq/config/task/language_modeling.yaml @@ -0,0 +1,10 @@ +# @package _group_ +data: ??? +sample_break_mode: "none" +tokens_per_sample: 1024 +output_dictionary_size: -1 +self_target: false +future_target: false +past_target: false +add_bos_token: false +max_target_positions: null diff --git a/fairseq-tools/fairseq/docs/Makefile b/fairseq-tools/fairseq/docs/Makefile new file mode 100644 index 00000000..c2f5b1a8 --- /dev/null +++ b/fairseq-tools/fairseq/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = python -msphinx +SPHINXPROJ = fairseq +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/fairseq-tools/fairseq/docs/_static/theme_overrides.css b/fairseq-tools/fairseq/docs/_static/theme_overrides.css new file mode 100644 index 00000000..2a076419 --- /dev/null +++ b/fairseq-tools/fairseq/docs/_static/theme_overrides.css @@ -0,0 +1,9 @@ +.wy-table-responsive table td kbd { + white-space: nowrap; +} +.wy-table-responsive table td { + white-space: normal !important; +} +.wy-table-responsive { + overflow: visible !important; +} diff --git a/fairseq-tools/fairseq/docs/command_line_tools.rst b/fairseq-tools/fairseq/docs/command_line_tools.rst new file mode 100644 index 00000000..c16300ff --- /dev/null +++ b/fairseq-tools/fairseq/docs/command_line_tools.rst @@ -0,0 +1,85 @@ +.. _Command-line Tools: + +Command-line Tools +================== + +Fairseq provides several command-line tools for training and evaluating models: + +- :ref:`fairseq-preprocess`: Data pre-processing: build vocabularies and binarize training data +- :ref:`fairseq-train`: Train a new model on one or multiple GPUs +- :ref:`fairseq-generate`: Translate pre-processed data with a trained model +- :ref:`fairseq-interactive`: Translate raw text with a trained model +- :ref:`fairseq-score`: BLEU scoring of generated translations against reference translations +- :ref:`fairseq-eval-lm`: Language model evaluation + + +.. _fairseq-preprocess: + +fairseq-preprocess +~~~~~~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.preprocess + + .. argparse:: + :module: fairseq.options + :func: get_preprocessing_parser + :prog: fairseq-preprocess + + +.. _fairseq-train: + +fairseq-train +~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.train + + .. argparse:: + :module: fairseq.options + :func: get_training_parser + :prog: fairseq-train + + +.. _fairseq-generate: + +fairseq-generate +~~~~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.generate + + .. argparse:: + :module: fairseq.options + :func: get_generation_parser + :prog: fairseq-generate + + +.. _fairseq-interactive: + +fairseq-interactive +~~~~~~~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.interactive + + .. argparse:: + :module: fairseq.options + :func: get_interactive_generation_parser + :prog: fairseq-interactive + + +.. _fairseq-score: + +fairseq-score +~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.score + + .. argparse:: + :module: fairseq_cli.score + :func: get_parser + :prog: fairseq-score + + +.. _fairseq-eval-lm: + +fairseq-eval-lm +~~~~~~~~~~~~~~~ +.. automodule:: fairseq_cli.eval_lm + + .. argparse:: + :module: fairseq.options + :func: get_eval_lm_parser + :prog: fairseq-eval-lm diff --git a/fairseq-tools/fairseq/docs/conf.py b/fairseq-tools/fairseq/docs/conf.py new file mode 100644 index 00000000..fc2bb721 --- /dev/null +++ b/fairseq-tools/fairseq/docs/conf.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# fairseq documentation build configuration file, created by +# sphinx-quickstart on Fri Aug 17 21:45:30 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys + + +# source code directory, relative to this file, for sphinx-autobuild +sys.path.insert(0, os.path.abspath("..")) + +source_suffix = [".rst"] + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinxarg.ext", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "fairseq" +copyright = "2019, Facebook AI Research (FAIR)" +author = "Facebook AI Research (FAIR)" + +github_doc_root = "https://github.com/pytorch/fairseq/tree/master/docs/" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = "0.10.2" +# The full version, including alpha/beta/rc tags. +release = "0.10.2" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" +highlight_language = "python" + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_rtd_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +html_context = { + "css_files": [ + "_static/theme_overrides.css", # override wide tables in RTD theme + ], +} + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +# html_sidebars = { +# '**': [ +# 'about.html', +# 'navigation.html', +# 'relations.html', # needs 'show_related': True theme option to display +# 'searchbox.html', +# 'donate.html', +# ] +# } + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + "numpy": ("http://docs.scipy.org/doc/numpy/", None), + "python": ("https://docs.python.org/", None), + "torch": ("https://pytorch.org/docs/master/", None), +} diff --git a/fairseq-tools/fairseq/docs/criterions.rst b/fairseq-tools/fairseq/docs/criterions.rst new file mode 100644 index 00000000..d6b8ca6b --- /dev/null +++ b/fairseq-tools/fairseq/docs/criterions.rst @@ -0,0 +1,31 @@ +.. role:: hidden + :class: hidden-section + +.. _Criterions: + +Criterions +========== + +Criterions compute the loss function given the model and batch, roughly:: + + loss = criterion(model, batch) + +.. automodule:: fairseq.criterions + :members: + +.. autoclass:: fairseq.criterions.FairseqCriterion + :members: + :undoc-members: + +.. autoclass:: fairseq.criterions.adaptive_loss.AdaptiveLoss + :members: + :undoc-members: +.. autoclass:: fairseq.criterions.composite_loss.CompositeLoss + :members: + :undoc-members: +.. autoclass:: fairseq.criterions.cross_entropy.CrossEntropyCriterion + :members: + :undoc-members: +.. autoclass:: fairseq.criterions.label_smoothed_cross_entropy.LabelSmoothedCrossEntropyCriterion + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/data.rst b/fairseq-tools/fairseq/docs/data.rst new file mode 100644 index 00000000..6a390cb3 --- /dev/null +++ b/fairseq-tools/fairseq/docs/data.rst @@ -0,0 +1,58 @@ +.. role:: hidden + :class: hidden-section + +.. module:: fairseq.data + +Data Loading and Utilities +========================== + +.. _datasets: + +Datasets +-------- + +**Datasets** define the data format and provide helpers for creating +mini-batches. + +.. autoclass:: fairseq.data.FairseqDataset + :members: +.. autoclass:: fairseq.data.LanguagePairDataset + :members: +.. autoclass:: fairseq.data.MonolingualDataset + :members: + +**Helper Datasets** + +These datasets wrap other :class:`fairseq.data.FairseqDataset` instances and +provide additional functionality: + +.. autoclass:: fairseq.data.BacktranslationDataset + :members: +.. autoclass:: fairseq.data.ConcatDataset + :members: +.. autoclass:: fairseq.data.ResamplingDataset + :members: +.. autoclass:: fairseq.data.RoundRobinZipDatasets + :members: +.. autoclass:: fairseq.data.TransformEosDataset + :members: + + +Dictionary +---------- + +.. autoclass:: fairseq.data.Dictionary + :members: + + +Iterators +--------- + +.. autoclass:: fairseq.data.CountingIterator + :members: +.. autoclass:: fairseq.data.EpochBatchIterator + :members: +.. autoclass:: fairseq.data.GroupedIterator + :members: +.. autoclass:: fairseq.data.ShardedIterator + :members: diff --git a/fairseq-tools/fairseq/docs/docutils.conf b/fairseq-tools/fairseq/docs/docutils.conf new file mode 100644 index 00000000..526acffd --- /dev/null +++ b/fairseq-tools/fairseq/docs/docutils.conf @@ -0,0 +1,2 @@ +[writers] +option-limit=0 diff --git a/fairseq-tools/fairseq/docs/fairseq.gif b/fairseq-tools/fairseq/docs/fairseq.gif new file mode 100644 index 0000000000000000000000000000000000000000..5782fdbc7e0014564725c3ad0fc6be5c6bcd9983 GIT binary patch literal 2664833 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�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

O3Pl|?VP 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ΠAznjaOh#2|x8 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
}n* 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 z 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 z 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%0DF)xOoVi=mYKd6t&M~{@@H0N&fr$? z#kot^J17ZxAj2%c2AzesxDcCt97>B7tS%7kL{!U21-}rTNh0!32Wk-oyC8w!M=Tr8 zngQaK4{75Z@W2n}k(H;TsFWHsvO1%eA6Hb&b|~)qE1EyCzI2B5+g!cOYO$s`OhX5lf#>y4M9wD4EJVTHKSekZ^S7K~j3y0iF6hNl z&ER(Y!$g#z0gARXsSAYurN;SUr}35!;r0sqC3UBPn=n5DTo~N^k~M(Z)GX9gDc+R% z*A~ThUJB!;73C%7OT9!2l`;oCefHgoS!T3G)?f9x16SyoG&8VPGYR?0ylMXkqyT`- z`wMe2aqxsfPMJ~Nk&yF~R-8pmJ(IRsA6@s;R*tk9jswLbc-0kdB!%mR>ocSWSeouL zyO9L9y(fmo1gRk2a?cTEGOjwdof7rC2D^*YP;Ylwt(!h$C#)LG>6Xi*_!PQe*YYa-G0d_Tf&vl`OO3&amtc)nn#Pzfjk}xyUn1m z0sO9%*p9-Wk_Y#wTz=u8dRAn`Wl$HeJhPy5C><`ukPW}2Ho`v%2T~A$MB4cpu6z0(Cc2PZ@|h|OVs}B8rVY?nbA>>8L-ik zDsX8+YLLCk6#l+tGBW|85yi{?c=B(+c;4{j*Wc{DOydpsDcd74kjoS!e{AO;t#=e= za9G01-sHEv7e4@lm#E-(eN*T^kyiW}bkzRryNbJ5&U9ea-KE#O)=<38G?K`7(Dzyd z(e~7|QSB=!*HRMaw{9+)b ziopq~`x{XvhLXxj=WAjUJ}sc+_0epJ=pQ>$zU<93gb z!`-h=$YRXEvvlqYtvOBd=*pR~Y|2^$Zk_*zBhueyj;iERt|EoZ-k1x?nCW zx0!6e3};S8IG?^DzE!vKg1_E}C_o~wMZm8_z|lCGIh)m>8f1YMvL|v$kC$8IXqadS zREaEMl%@TefvBs8_scLY4K;2|zenPE)y^O#g>WUNl{w>wo$sHW65%o!c-IxUD&R9C z{}$_DloZE% ztLt%2tEktM#Et1j)_U3;@+b66{2|~FEdbvJr00&8C1`#Bh3Q@N6O}&za8!Ll9vpVw z>M-z!(iNhtKTsL-JmQGb)TV6SRgQTVanZz2EdSQm?3o?E!Oh7m{)gPLzVInka+t_6 z9ZgYE$q!~c(7EwY0>Pi~Pz>k~8K|fpGv8z2{{<{&S@%;G1njamJsH$=x+RCoY=A%F zgOPm^8#vELuNz5{m7C;C3(hb)d+e+XWQZcPyAAO?fGqh@G7j<8mqG5mdcBH0I#|7PyS=F(#a@6=h12qB9hw8I@#!*?`p({Wm^8>S1J73${x z-?*E!Q%?-1)uw62pdF;juw}I)`Vd>Vo{KFS4CHtNsk+t3t@co@Kr5EZX2-h5rtZd& z#KH1(t<)TU?T_R#T=cKKdwO}-zB;sdf9#1hK?;lpo*lk<#(p4WXyyO+A3cxVzH`6O z_sP89=mz{t!Hol{O0wr*591N9biV!3?WqFIQr*YX%Znod50!4TzjJ$4!H{v~ACKct zulLW-)t@!rhplzqW0*<1-qo_}`(Y^gl0o4gq1Ly+5K)c%_Ocg6*wB+}g-*ZkfBVR2 zcolTR+b?d5^uVC##@}D{@1|L=gYwp=?;ScSy(Sg?jrjNXuW}hlHd-R-PQwvae*0PG z^y*G&jD)C+X0B*Mw1i~5 zsSvm4f1t}7ynZ0hD*Q{Nnr14)e=z!3esqL}F6?$y*xO=KKVM~8vvF^@B}ueGmwBh` z1_Let=gNTlY9RSqSKjQob<0?f@S7OPRe)&-TRSR)pI(9>9&9^YPvW3|s^01cy~@hD zTe1OP7miiMCHCFGokAL(8!D~|b4Mhe0BDWmr5Mr8_RkB$Ggf6cG(|erTcN6h6m{dL zKX`=C6;*HNzInRo8dGBxaJwKlj*0cJoq{{MFkXbK?!i|Y2LYG1&{p@#A}!EH+LY(m zIgck-CznUv3w`$jUA(bDQJKl%-JA8Ve@=|(v$)cITzK!ZEgMF-AT;8f_0_+(lUnab zYX202re^MO+4~N(4D5EK+veun$CFL?)&YAE0NJ_^P`+Ki{6Y8bua>kCYGedYkNv#$N`96DLV13 zdT=rDL_hA4$d~9U{u0sqRj=gB@7|bO&pv#6ow^N7(DIA0i=OC7%%gFbF5ri+S^l*@ zJ~_Dz{GqAyRFW-S;~(p^{2Dit>bG00EyODd3^6N!o@;r(M>l!O9yrq#Ri=J=u6wS? z!;@@{gVUnQ*7^3goUI8Jc(xiwI#w?imXC5B6UUT$3>QUimWMgvM)9T$MT=LB zK0-PH$H;)~=cy@+h?2b)6P459)`y`NI=$rVe7ie)>3hPj$c4xA0kW8|#5k*bPMFlb z?v!(1m~hZ2SO?qHmm|Z!Wyh#5qJUSpFBJo{8wSW>BSoOMW#>N6sFb{Ur6u8#Cgmb% z9R|-9yq#?N_?Y9*k~^7Qe*+k8J$jABlK9M>g4OF=pK!fHma^PVfJ(7kvZ}_OK``mD zdu}cPXPHjv0rD51RzF|0h)M~Do~pZvr`^uAX_J$j_<#dvI>VhSgjL?0w>ruJ+h{o0 zDuO+zC6}$lo(Ou#yXq~mh=cD6KX69nZF;>^lm9#+@dQ=))pc3(N2rJu($aq0c}~ky z6vDw1LnpLw%S8#!eQ$c8kXFx;jlr2lCSsUQgk0%-n2-^@04{kt4q)5v;AHUwq~um_ z4X9bC#z)MTi{bkKSmT^~ZN31K*S3kK$Z)Jsro60TWYw7Lm4Ym>2TXW(Z&wd;GTWPK zrh_ei5FCl5997$Dg6P~jZK!3fLf|2H{U+v_h2j<957aZ~3a<2O3IEWWypl)ZPjk!L zJh^FNJ!5}`l3RQ97#NuV=09x4yPi&jFv{X+8O-1HZ@v*#A&i_Gs3rwcg;3bY-LffE+j)CLG{irKi(331=Z$J=_l^)ad8L z#7gE-9D_{bG9Q;)16Lm|d_(fT6A8Bl(S!yH`J?u!d)DU!Ey1w?zBO67>tAEJj^Gtk z-p|9FrCqmVg6$1rTNos|H8xuTxf6G8fN5sBZY#Z5ob-(g%-_(sqxNobDtI`s@JH7j ztrJ!C1Vi0^wJ%=`mfTc^vlz6GT!?2OG={rok62*!#@~QGr3sJLj-?t3Wt#>D% zC{LCO2*#^$Sshgsz0#WO6G`VmK5vdG_Aq+R(BO>-2pdUj4W4~3zLU3m+my2O;`(9* zL&x(5;USv;QoeX9@I^8N-LZ-JV}s=(*EZ|e^iM|Vj@ypj2dPXihfk|iS`%e-0@6La zPsBbRx_uRX;Pk{-Q0Su<@uqTi)%W{WOo~5ni~>fqwCAYD+|t#WMwTeK?=>Nq4@_r$ z1HT^%*e}q~^Nxu2avu(Q;a*B~$e8Xe)$E^{@_6%2hd5V!iIbO}UKiZPb^S+sm|M02 z6i*%PxGHdv)+eXBZnrTmD6o$XiF_|kBr4Pf_+}^s%d@@-x+9dVcK?Kto3XlR&TNf_ z{!Ykl`8q}kw0HPlbH zJlMI9snatRx>HTGU0dXyRb?7VdI-Q9;Yrn+A5FmFhi6XH;%%kMAHa-bD-4D+&`Jx)2JAVp}AozVLJjLG_oQ; zMPZ_8MfI?VUr%X)C0JG+7?h0+(y3C#VDS+c%9Wi6{$3cbPKe2`j{17Q9SeVFVWzO} zFB~)udZHVgVZ-dYa)bro3+`SRu8&k8fb~0OnFg>?GrqF}3jHL55TYgyZ0o3A0&Kno zWmd>!`G>u?0b*0*;Ku;)WWZW0!qfv1W*(i@02cFIoXOA*J}SmiPz0%HexPGlT}(q; zN*hq4F~?d?#Whs6M6PyAI*7id4ct>Q#vp1dY_Ki&LI-nY77%}pgL3%5;3jd~2CEq^ zY2}Kgm7OzdT=K~fVP+rB#gEUqCjXKCbA3ox_i;qyacSvwlOphon1B1Nb`-U(LJ8bw zM;g3q%92i$SQB2Ee%KO16k!&jP#*)OFyK7U3PCjnNE7ynVPf4emouNp^zxm^)YW%K z81$KVhSy;A`U5y{3<|Y%;+;fsLP8O)5!m*-@Z!VXpu%F*a(PXgo`C_y`K8j=U0A3F z@E9K-SU^9PRA>9FLR>i@(HxTvwI8@ug2ohqrPQ5cj>%jEuSqEm6%0wG4$X=P%Mir; z98g*y0Jd2Ql2%OkxL2k15NuYNVS2;;G!Bfy3-~dC*Uq8Xc35O08ywlC6qxeRc`wXH z8k}X1iFqln_D!jl-lvr~V!YDdpSKN@LIn|*)7DlCOpz;90{7z#&K*9$OX(fji|T!b zJw^?{I8;gnC?$l*cDrJh??s$bgiU>ue;JV^a*Pua5qh_W0uP{9o(jk`1F-B&H+Q5EH27Z(6K~e&0P1{n7e8C5(H1e_`M*(WaCb8va9s4+p7_ng1 zL9n0ssHZeK6eNMqjy0dAp5fF`ra>>sSQ0xnTI@J@tAiiTj^iBCCh;No%!>{~P(yQW z_@PpCZiEIGm5+EIYUt$`iT0G=_C&~=r~cL$zf`al>opGG%|UJHxHJHra*bFxS~V5m zwGRe$0#-+5ph;oSmy~c4)$vVY4SzVsF;}R*J3YN>c&6wmf}GV7tl_{rPLGQd5SlGY z?&C=QF=k66^fIiW997AHfVWw;%`rtl6m0!V@Q&ja$362=+15l1bTYYq+#gxuaSR%o zP06Yx7XBGw&#M*dlXCKG+@m5*$UAIGx)V1tz|lHV92`AJ3Al>DYzAoh1A-1pxY}>R zmA%8dv@tTkbh^a2-Z0IFVVKB+*Rylj-Z2MHJ(PnjYh0=#rzDfkjpFnpBMsiy1k9&mrW+nP@Cb zCkhMSW|*%99EzeEIu-*~8lLtK$Jj1cH!cr$LJ6KF*DpNQDawRkOrQj&OunJ1wSTp0zEn+Bjffdi!qa$E}aHi`K(-ZoPW9`#fOvyd2ckOx=Wv3Y0&`%p%* zDTnZ=Mvi07erSu>*dlBW(f5W2WAleZSY%RX1s~dDJr13Vj*Qe{dJ@i##pDF_kHK>Z z3=3z#7;0CEnSGea&GkCbkXG|c;`{Lj|ObL83TzFN?Gjr9UZs zRH{KXatL;7(!qipdg+&8?`V{3OP&;MB7@C#P42S!d&XalXtk-B_tOhj zT(W>tfO5 zJeoF}4%I)KO7rUl9_fC94G_wSq@P94{|xpfNELpB_CeB7TPazZIMq9M}WAMI6 zzy5l}i#vrad)Qgf=hi31-%gijjzLQrCy!cNZ~b-5!y2L?LMxu*!;?d>8W!0Rz}!*6 zk{SUldCyK}>o+DBxgXfye8$o=f7-ywChh>UzyZ-H!O@CLwk6dfuq( z3^QEI7+nlXK+=1;f$B$SVUVrfx;?oZ!+*xY9LLsuIl=n^$8ks)mj$f;ZVRWHS$ch` znkC-&+i91N36^}6Wb5*Tyxa%eF&5eUajW=v3tCsxk8E;RI%)3GIwKmUs%GP&dL&=j zqz(gwvUOcE(4IxS+0juK$FX=@2y?_WjuN{bT8%M6A+Xiej(n~(7B%7rB{69|_}iA90%|O_p5Kn!?tar@59dFTx#61}H|GzhIY2dxj-0w@*yXL@ zPEQP4oK+`Xx;HB8aQ-H67X}@k`g*^<=UyytODIlEUmt_E5S$4ln0>4rj$^9P&lSIZ z)O(y^-^cJmwGzzqLa5^e5WJ*vGS-@XlSn6tEemGQxvCHt*HE}6oV4Qm88T&HReB~b ztvww=3mR@dn>E)zRhY9D2<@FdvrIpqcf@uR9+&TRxcKhAS$grqi|VdR;YldiA%wwO zpaH(D@*|6XIfO|O-W93vK!_=VrzL?7eVY4f|r#S6ZG~P`Sge{bnXvY_pbE%<6}=XG&gjDZ8R10M{X=ougip*6XD)GQFVm z=`?TMB%SrY8MuUA`?B(KG{M_Q%PxKP_}E;m0v)*U@K_~H<0 z{QYi6wiTF<>JG|W(802Xh3<7c!<8Mlnkk4|rs;JTq(UpE_G6CfaGl%>yWp((&(t3%TtwV_Zm?O~0k) zb+Jkx1gS-2f1Y9L=Gc$))my+MuIiK1#^eq3&v{PfEmQ~mhJ_yjStb8!O&48aM&d%m zNVN%9@GH!Ta;J{e$MdVi-8hOiKN_fNv}$u^K6-xJ6h;^Snj4mC9*uG(|CC-V5&i_t zbAEzEDySpOlic~e5u)2byi?Yldm{EG3!g}6JK+^IVd8@Zc^=2hfk&DMUmD**nhJhm zO*|jkn$tz@g4eP+Fi=w8GdO$kMC7Y3|Ddn*gCbg&5eD_n^pPt0@?P55J>}+JTO4Zu z13mzSZ51GvF{rp()NUTI4N6=jTv?keaOSM2g-O<>4(M;G@KE6&8R_< C!uYvmd?eIPVuOp7vqvu{lWSN)DOLI8ID+$ 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

#X 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 z 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

2uP$ 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

!6*nAO46!>68H$6&DfqQb866gqCfs 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�%u0fv@Z<+eYd`VdGP!qS_AY(y+_*t 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 IM<|b-b|_d1IsK##Z-@4+}Rw9p2dC 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 z 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

lb_sYsKO-}?YpBqR>)t^LT)WM4!#fDX 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ǰa&_y>ZCm<&r2Wnuy31pS<& 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 F_|dIZb=RUx~rK$I^=g4f%GL^2=7v+ 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 z zXOVaNJw9uaVuD9g8(Tc_0Kf&J^hp|=g!$|=&1Q0A4YraeaKwo z-o`%rbG@S*m^j$#jNKB&AF$wXnkRN z1keImme0uPf!*gLVTs^KKRo`A1;d?WSFkc1J7NesYrU` zyi0Tr^Zr_28QdK$XSFnhC{R`@kEX?(Amy;RV;skQCa72REgvsSzek8^L?@FL!D`{iX)-Bt_fm*ciP2tye{X}~^kdQEN@U6_F@sF)-NF_0 zU=btfN~l2#t!PPBm7KS2`t-=teL^)2SARpx7~27K;PvQ_z_83smt^TJj{z_8=$F(= zC9>PmA`i~l!q3AeCr=4(IsI3ZS>`uN3P(H=ED62tZcw7+i2cXO1V+<=t~-7Q6WIO> z2#riFR++LPOBpRR`$~b7l+>II;U#~)E0lNY)xu{nko3wwmI|&p#9_i|Yc4igcHd`c z>dno033k?1FG_Q|fc~NsN%D~We%kcON`9H%VKOB%#msk81n|M{`}larA(aXJpeK)Y zxVklG>#`fz1$YSY$M%w;E|wq{rf8mZ&AAU>(;`_RosWM!GB8{xjm0$wqpOgKky znS)e(_=%hEK8~z-+;;Hn!= zT8mPz6zNZv;u4NujkYrQN)@Xj%IEE2@NJ=raQLdviM z_Y$G$ZcWQ{jI|40$|UQt+OOIgL}_jb5yZBh9q0;~U*z?W8U!=@ii!p~?97FD$0W|q zYHG)A$NP4?PpkTy!8-O{nZX|)iK$CzIjozl4EKBuPD^JQq7 zt$g=$Zi5|-Wz5kEcf1M-f`RLO=Hp&hJNarKB=7*<=Tj9HY@hExeUww2-2#11Wc;U&|nleG=d+35-?*x$}Z0Bo3rO(~pYC%bGm;6iEZaetz3jj53hn zZ+xRiwL;C>Zw?zf&MmE5B>?t!l62XBxU^AhdPBH9cH)jA0yEpAQVi5?#GebDN8J%n zLH0`5xx)>z5#z1Me);8!Xo{;svCn?$zh3LEzhf`hlD@u=tbQKb(|qT@69gHSASC`T zSKRRC>gArl8_56HKQ)uDqwPn`921*eHczLkjR0Y{n7@OfIm4e^oeP~rbduzHieg6i1 z1Y)`0+I+I^{+$FJ_fMcy_|a%A{RZ${e?sHi*b=Kk*VD7rTZ-kj*6XU%u`9pS4_S*sys_F`^e0c z2r7f-l_+@R{|J=q-n3!^C1(Mp^?0eRQf#1v-9S!6;PJkD6h-W~k;L^o1WOR1;p*5c zu3u8J!GFKv+NH+@VhKV)*cychhbnDlOG$KXljv3Kiav|S{6i3B8o!yq9VPG5{kIE?i_6RX=&G|# zE2{f$hp6+TN7W0f>Ml$Fx#BwKhy5b7!*o$QA0#z1=aeGd`1TJT&c@ksR(*D(acY=P zM!GaEy4mS8twi2AYA&DEIBG#Wj`??>#D*Uup8AsZY3tQi#rJknGn*mHUwDj@(iRsY z9Su0#xv)x*>6xyKnN{g=5A8((VK1!(*rSip=YTx$hV1|wC}p_(C5Xz?A^xU=(_x{0 z{<9IWxnC88`NZhT(Ua`X_gxAsxlTg&hyp!2ZUdF83_hmQ>rUw1-h7wbL^6nfWPUxB0(TtlO!okcrr13f-Y>n^5x`O7{+k`$rnt6gryH92 z%*zQt4ZOIkn-weNKv!#vq486aXdl1$PC2?K(&?AP?SARcU)`0_dXwmOvs+p+wl-Ey z6L5(zZerelwPGiL4V1R4vF|K?jBSdyLwXv%_s~3(%R1{hBKPb6>0AF`H0LV`KL|w; zRCX!%^7rMU&-dRyt~A}!Lssso6Q6C;sJB1LZkl;{!zf=!YHt6&O8!^TV4<9O9(gq2dgy*65B?PFftmSm16f}NV)oC1s=+zeIQ zeEBp#ia^wcwbR3n2mUDE5iOFMp9zwE6k>&E=RkK_mG~b7;Q%EiujN?lSQNkXQDN`J zN-^RJp!xQkMH(kDwqIGXSKQva{u+!JscagG9+kv!w>SswLW8gNs^WV)QEqXCm^>bJ z#vme&qKZOhb%VZaai|;LVqu*16`6y1rO5A;0XiKV^(3$XT2yiI7snJ);|tCtIyzPk ztZX1|+J@;SkG;`YDA*J0f4+ipYA=^i`SRDv;zN;C_ZvyINrSC8r1J#KlvJ4pt>8sc zn**9W==&eQ85QKkLc-Mffz!j5AH}r9Bni^g3Y^n9-fbm}&-K=w@HmJEY&@EEkB3_s z#@||VdTQp!`Ib&`)E?u}N1r4)EN}acjH8>8JEwb5m25 z>wGKiMwzwXEz|#h?7j6{l>OiJJHya14Bd?|bV&+0^w1$CD$-KYNQw;IDJddd0@5HL z(k0!3N+S)@Ai{H^*Y%A%_ObUb`?>c%oRWiGXnYw!&rwu{NjB6Df8DBJtf zocwF6HH_mHTTWr|dMHo5@@fuZV~U#44;RPp{0T};uvGu4Aez|ZGQul|#O349&_6E^ z6yHyhf-(rwByEdm)w#9N z{TS7+=UghLlCIg$%J5VO;)D_z03V5{y5@S=n(3KO(JA9 zI{iAL@5yMWXnVlwT0`}x<+oTbN^#Z%U!4zFYgDIC53GqaonH?+#Z+f}S9|h3Cuhi0 zpYh&(Z(~ubBMxu??)0K6PErjd{vrN6K4Q8(>RVs7@&rnr!eTi784k`_(|hWZ zO84o(+ud=p*4i{%ErK=c2uXX}3`R_4X11_+u=TcU{!vJL$L7&Z zm;cuLP;rCreG&H}`G2Hb0wexw{!H&*__IGzSZ^-%=;}|~8|C8k+xxiT&qP~j#5CWu z+Ht*ZpfTZn2Q)-Ul#WHR;Qf#1ak(@)R&Q(&`4A>i34KUf|s*7w7l3G3V~Sm(`7HBR(pPSk6PD0T%&E@6^9K zye~?q=euq`{gqwsyksyf$F)yuv*tMcp22h1<^p`Yc3m1aa`kHmV91gl?A|bB5c;!u z1TK_PSMr1#p8ZgTNp~@b0yAkbi1yj~;(w)FBD2fTfGBLr`bN13BmbdXR^sHz0p((G zD*#X~$(=XK<$RP5P%f78-VgtcKVzqoHDf^&0F;Y;9T0^%b$hX?_b?cx2o zT{G?Qb0=mw_fW=jdH3hqy4KDEKC0`he9mENKC2)7KH|f}gZJF6k2caZo?G629GiEH zmd4Tm5YPFf+UshB(up()-d7j1xjk1&(;s>-e^OJaU;jG8>!UnQv)g!l*d9qNX_E30 z?IO$v6Ntj}#v(uP@C$qn>=(*8K`?gZ+LLh;i(n_VLB08z)_!JT62-^=nVR)j?USo4w_&wmn3L*`aeZ0TLGNPL8dA)Dik+LwrB1X#W)*oLMv+cmb z6&E79ncEq?u0gM$8*Z?o6TulE?_vB!pS%OvEtvizDq5#gXk;<^}ZX+4F zI5OB3E#flp^WjR${UcgcFN^Gxcej6#YT}~5EM|?lC>QK7oIOZx7|7?Hx40YF8yMeo zTca!NN56^UciQ<1#SfVNP&8b0>e$c)4&`8xrL>lICPF2b3kP^smIjO5YS@|Sid766NuU*^NZ`3u zeZpD#E=Y)*J-=8()GXljRBwLIIb2kEVf?rEp!eU-B{cpuzhU_a8(sN5TPFwl*CC++4^7(mmCcSQfjK(buhP>lRb-9)oP;z5aWE=d+_6g# z#YbSGQTkgc)4XKDXRR$&P$7I)5jbB$o-+8IbhfBc`iH0XHxACDeLljOMwxul$d-Q5$BFcov z{`q@S{fgaFRumah|JSRy_KBU3*yIs7yRQ}!`5W3s<=O(GYrqhF-H&*j#Yz%RV|%aj z+I=u8JD|SYgp4Ar_k$}Uf?dJMPGXw6kA5I0D3(j;PO_-ry`I2?Nq2$HyA7sI6Qv^* zd9^?RT=wApcW^A7>lTD9W?FBj3(O$Y-|Mm}pd4mv$rEV-**dODEp%BD$ld*5wc9JT z5WgmZwYpH?04Nt#QWWdJIg4W)%Cf-sNet2-Lf5)~j!u^}84_Gg{eD|oA!7=~*m(cc zdMWfI3`HueJ34ky(S|lM0+yT|d9D!#!Hfgh5`5N4ty3xX3Ph>+phL)k!-*k@-xN0x zSXOPvpl4Zjljva9-`R>xhVhjR?Kh-INus7LT(1*QCu&>k!B4TzA5LU%m+gcO zn8$wAXADmx4R?&_>?2SVm7i@R5WvFvLWO$PKynZxG4RR}d==JQ+p|L^e)tVIN!*I1 zk?dMTqk^#N{kW$_XwJ2gfWY~eS&08J{EO}HN1s>60kZ%3tIyQDREs~vHAB!TUAir- zt7O!QuX4Eurx<&phr9}~D}>&X34@|j!G^+-Ek^tM>*LISXqP(^VJVHb37Sq;N9tU+ zzTG_fp%eY9xxbnKyTa|qhQgJPIKaQ;hW-jqt_AoPflm)Oo3e!zrzJn|ob2iKx0_FvFB zxdJv58kL}BvPpX?GS#9^tp7G-T>!!IIQjRZfBy>|nlLi}oqIP7f;Lt+3XLRAfafTP z+!hEt*h z!?JqD@Bi>G#wiS3vHcW#_m-g%(;xm0JpRL@|5xBaYCy}+y=3_N(ck{jb64VteGwxT z;4y5hMA-GA3yVNL>3+tuAc6Sa88Acef*FgHGWe*~Z|J-pc=Vlmcuv2#P2bEyupHkY zC)bIm^N@}l+=VEs9nyb$^uLu3Bp6(A%wtH28BDp9*`3R`8Ga>}5`CU&Ds}HujmBny zBitJZJj#>Dt8N~Br{wAb<@vBE0QPy@DSErj;N1HM?M2y~=+sE0)a%iIKZbIGo>O{eE$}cQ>qt zqi5`@KGzdJ&Oeu#F|)J~2t0OZYWWqA0hM>KE}lGRWa^e8ww58yXL&)FH#)-!5Pu;f z^67U>qoGCZErXenuvMIKc}7}n-vlqUb&Jw8YBXE{_Cz7;i%@#M@f_jrEDTRwg3{(l2dmYH zqNIXJFfsoW)6d4zhY}SqVt)iTO_++c zuwB~6gp-=0+Guo4#%bJaP&%;J8EPMA)N*Z-Rp%qXU2Vig@ePWL{-&$UNu2u2BK5SM zl$b*)C2TH|(FBC6wX2=!6Tb#!ML%WnN7OvX7QkPq9TQe1#~cX&;rll(0w)wO&AugA zFVronwOc2*Lg?~RxG(lY^mpwt_V+!w?`l&sUaKyk(VVqnYg7bK4E$pjLVFC`UY(Ky zxHhIXj5BtV2#i((6eba6V_?rUi|k|k5MV+@Zps-vYbMt2s_K@5l^!VQgSS} zIU+%i^8vCFe?$X5F|pyZYpoM=Dy%Q|Z(XrDhpexX&DrxTO-0D$f}W?0g%Jnb3Jva} z6qLa{kR*|y7=SSF3%ytT$%mu+Oxu<`EbsHw6NL|TJFk8BySa|QyN&t5qZmpK+A|kJN`BZ@c@?6muK!J! z;P%sU@4I+$JZKR-akf~mSU&THq2crIy13HRqG98CkR><_=rWE|SAsCL_;`f3vz5+1zTBI{p{kN!07H3? za#xs2dps_}GZ1r5D}_sFVwbv>&9A}gz00y}n2a&zpTag;RnKEt{q9syC~s?}U~kkV zp474DZ{m(B4+Rp#{5f6=$4VMLEw%FM?93QK-l4k^n`sKX@D>~7US21h~yXf#0j|u$qiPn4YQ`qW-#;5KT5Vmyfq$d6z(*D)a9LA zYDI0$Vf`Rei)!+aYrQx4wZmi9%yzyP>p){DgJ)-LBv@I|u0u-dbx)2x6i znd@d|O5A9z z?8=S$fWcM%;1YBZlUKaAOBmPoTB-9%9CRzf0;$@v6MB>C z@o#VoQiCsv9QU&IBD-i=ChU3`L%9$BEiB=l5k73#cH|TM`F6Nnc1BqWd>t zN%JX!`}Cn0!{ZW^BhQ|%d)tikhXMb`*GWrovL@%XSr(fiAC4~CE4PI=@2)O_g@>?bZ_x10cGxWc>4vtU)S|wy7L@_%w#Z&I$2F~r5I2-r7PVXY{WM3q-wJyqawNCzGZsQI5uW<19_Q^ zGutN27?}zuJA5s`p8PhPN<5%VlsTL-AD}6Wtd+uh)#-KvaZWF=UpEm|DW4TBF%4V3 z7w0{QM;%hLz5r+nwF6`-C5VRaK8vc0Aoq!rg+UAWgXY0HgZu4UT8(1jHJkQ3%7ujD=`VUxis!(aV)f=%6IWkQ;Lk{j;~0;=RZ?{>EzY6aN`W`=sk8 z@Yz8o$TCl+APsteK`P!7wfo3r%dxABMgW$BrwV#1zXY8eaQ#sA4wlrA zj81|JsrXcd(hL1Y9p9o{T8h$Th$c0qB0d_v0bGuXRsh!kTaJ3g#OB2&DkkA7m|iHK z;~~@;Tlz-;d2VVDeLn~@BOn{!Ewz&~L4Y8sswRzGr9|g*`vh36olkbP`*zSGuBO^? ziDg3|yLEh&Gq#>{HSLyBYEn#szGc4gWT=q`DnfQdrZ5nM!B^l6O)l@q^R|p+fgP!T zU8tqy?~2i?kH1Ttc-79oy`xv+3Modv_Cq48> zYC9(TMn*%sIb=;HL5GTxzwGaJ+)gz7uZW0v*akDA6=^XPcf-8>Ayh3V-32J8_*pX1WZ?@EC zMjUBQJFHh}tB-e|>Itj9O?YMW)6!nLpJzP?s42EAY=xPyA97EiFg}I5Ojq!{Pb;SC zWg$S{9)9Z6_rpdPGYR0vlg~EJjKm4UCx^ymanNS5VIvljgj|86?WQ+jN$D*d+G2Yb zIiA-b)G3i45XNZ#ae?L9+|Z8Msm zGrbyhRVjnpR(F1W9*L=|`53%v^Ks?9!-O#^Qx5b1rs z4k=MSN+AxSY7z@^Ckuw(&W7q+@RkV>5jrR_RTS3Dhg+;YFdB&RA!w=W7BPSGEnI`I z7~jft>Gob}I4+!Yv6$JS#Hv*(U}3M6s@7nV8CpwcVevSU2xmPPClJT{mvjX&SJSe* zS(@+IsjfqZnLi(LGf`l-y~vCgdh^ANoZs`U2*PpF%Vb6V3B^RN#&OAmuQ@^8+T@0h zHs0Fhjpdv)=0D~+31jphw>Whn_Xbh9r#xc8r4)MQGvmS?{0lf3`F+I0?WFlGE7<0Z z>-0_#7-JKGWj`uY?(7-_iRqw;t51~qrQyYp4MdaDw3^U+Ug2@MJ+B`>Mt_rJ*7=p@ z{=&kgj5Pg<-vIj-;hkP_6$Woq>oUHMx8vjhN`sKi>6iul9MjqOb+b1p`o znuo=~q??w6WJbof>%5OcDcB9Ue~F=g$zN>$JN8uN|7CK7=F3eL>1$Km9LU%Aw;0;E z0Y=D-2O26(a)kjahJE^m91-dv{cXiO7LKG>H>zpzJ^hm8r|M9J>H{c|n!hNK*Zw62n2soNd5i21$KmTY>}in- zND^RAA6_W~Vu&}zq`>EC|3;zhXy3FaO9Jj@gm)&uo|fi_Bi~B4T;l>&q;6~5vSPm# z%d+Nj%Rxhhh}pMJI|O#z!BzBcxAmvEfA{}=Y|_T`@g}nWwqkakW*N$@`)T|A7DHQc z!UdQ4yG=~55B2yUq;q6}`vn^tpsCA5jTR8zR3s;uB4hL;z@9p(E%5x!o{}2a|LCH8 z^0yVk7@AQGL@Q2jd*{sy6&w9jg0H*S;*JI`5^aH3uZCXLm(cL37o0Q0PvX zvm*P~(Lt35fO&&mUGi|8c(8(-OZNs4L5!O_P7VL|ZD{W}#Gg%t3=W|&VVu}*HV@w7 z8qOGW@+p1EQlF^Sb4_Z(Gv!X_7VbdNpV3g@72^UJhoIwE-f*OROXzca_x|jq9t+ zYV<>)U%AAGXzSU#(FL?4VHn`Tyu0;0FwR9GJSqBKN=OpK^*)tK2i%h?58o2Lh8WVn zErx&+7kEz!0oSv8+sSb|{dsA_#qd3%54xNbe}pX%cv#DRCF`@2#9vChR)KdiQ~wB4 zCdT5n3hDegv(FN3mqS`e`EnZ^9|2dnAxAjrT;k;iFLEeT4&>v%YBJ8JE>KFEgH;$0>6X{}7%jx~0Sz zs$$P55La_<1)J>qG*$!&F?_GcGyDEG3{w83|ISA7HIp-Wr_N<_EFaaufWKm}$vh=o z8PuT>2(=1Ff1fKS%KAY_!%Y@9c%FyPo2Co#n+A~!mRbly438b%t+P5ZF;d#E$r zlH6h<{ln_eGQf&4A$V)p)2Qc`6-Zmw$A14QNsBKWD-d0K)rdz9n~i@F*96|ds?`>0 zbC%C|u|FZcDK^~&XqLn*2xWOII;&VRj!6~-?pgUNAnZwC@U5r{*@kF~Z8Xw|r`*K5 zocB#Zj*KTW8dg~5IZs!@X;-zdvSr0!rq@|!Fca7gSwBCnX_gD8?ei?A^3Lq+qOsDI zGpJ0QdGsSS=K2_n4n|L=7_*IKTHad=Otzf`+_(gWYpEez>rNOw#@VoTq@KrAJmJqc zEkARB6qUvMfjuh`>(w%7y*k9m-ZK=UOT zJC`i!`;sj#;y6&gNgN8?ieOxZzfz`FETI-U!CjPPl{UkpYfq0vhb(~dB^Y7&%@*)` zGNCbr0yy1cZS`TgPg`XX#mvj-*G*=MdHlV2A=>sVgWF_bNd|Z%B-Y~W-`Dq<22G>2 z{lWN&NHr6#_9vqw_4KnctYKsi!Yn4_xFvbbbE$G)i)nU{Si*m}Yg*lddLqP3hO(vW zP`DEOvXo)0{h90+U|o{c(i&1M9?HdVixI(*^cHx^3v-6NqCnaj+8$m>0bGS#&+!-; z&1cW#pr%n~6y?HcHQ76fMOEl@QPrVhL6x|sQIKw~WmKF^{_Dl3a+K|8-Qpy_si@DwI6{!*Tv7Z+hpv&85=T+vM3 zRWu>GBONN%o$dT0MRA1fTJwFs!O%f+Q-(If3md)MC2-8g%eCoZcUiZXHw2`@7;t{@ zkWg+A_{?`b4F`mV+3K2?+xacp;rgn4F*CChkJP8bQY z(rlWY9y+Nz3<6_fH_c&HyG1b~z^oMxInOjR#ik9<#b zmLOz#U5>kPs-C)8nXoU@(tA`z?&Gn0q>GwGkWM~q)wDMx#50mENA9odi(d%jU1t6q ziV(lX*b#@72EO2U@quU>C*doZV(U3~;n{h8C(e)I7wpd|dIz+1QI_DB;;gOUeRdXx z3iq-cE69%*r%Jb`rpcm0nNE~6rwhFaipYSj{-=6>Ng_0ReI|7*!b6bS+JP4}aAcaD z;}<*3(m-PEJN$VH>Q(~@ZH1qJVPH*VfJm6UbaJ5NOd!XSq~;bNU0ux(V5k%P*Br=4H zSr`ji5lXk89uzWEtVdMmU@Y>(UV5_L=@m#mB6+wU$)=0t&JSA73KJo=2Oou{GDUN1 zyX_(z?l{o%R3mvNgGDz>Tsj6|Q z*W+(8$c6p!;1_@lS}PE0_P7CqX62@@Z^)o0OODfNH)PP6_tp!2`E_Yu7oYppjlyqu zU(5Wu`YfvDe}O?3D}}}ePtm~^D9Q?ykttgE@6tkMtG5|{x8=PE{)q_v@#|RbhhM^1 z;%@zr0VJxQn-WluqKc>2__v8FMpvs>^f{1K(}zw1#?RGPj3 zh>%5g;ytR1xQ_2xC!=j-Kw5}p{ihy9M+Um7M{%acC(p8H>#17y!@OxQH#Um$o{>H- zW^|7LB)zf>RM8}q4BbprP3T9Kvd{V3{zim= zdQ^LHzi3bJjYQQTjpEp-dyx5OL>|jh?q)>(w_o?C9<|@9C&fb7)`uDBRDJAL|0gYs zYf+2h=AQ67)b#(!Z2hCh!%VPMYTgsyrF=FsBT+kYHhgk;5Q% zajTGyyzqTsw#hefQex#7H%X6<-*5M=)U9-$U#eDJ=W*Hbl&?tF@wCZzi$N*zcOh;w z<(APWB?a(iAT7L3fAm*c_`U4(FGR>6i`O%>#6(i;4c5J9|3HLz&*N8Vx7{B>HR+v3 z(mkYYc=U~S&j0r7u0*Bz7~JYMD}-V+#%hlfyteg9%(!>&e;c}!bU1Q(N6!yRxVzfT zm+W$Im-(*0xT}z+#XS|GV2vMRgdB?npFM^pJ-^*K&j@b`eKR_=R`|{@CJZ>v_VW0b z#+`)yu$HS|!V=P9Ioo62fQ^P)CMz%=_$KBr= zd5mGuDM4WS)GtkCc8eZOHcaY?KQ71Pm;KIJA2x<5NoL z4w{|OMa64F_E?&dPA(UYV3VZewyX(3WUmSc%Zk2}8C=;YPS3eo)xZ1N8C zcRd>{e%Ae%q#dbow6h_RF?YI@t$MqM2LieFs{2LF43#Qw6Y;Wao9o6=CJR${MhDao z5VD~4$V(i=$3g!75J$S7c=j`6j3HGILVOH3ve^MdNGJW^rIqX(;Hyy5JyA66 zT*%{!ca3p0415GZg#JQDBaj|S5I)wz=M7|sJ%oayKdP~ni=A_Ihg5Dta(Jwtm#jzs5g8YTTp5`jPF(-J%p|ojy={t`W06-wVi@9$1?sA)I|9p zL9vFvPtXgf`ze^n%JiDX=Zjfp4^{c2739nC;+ldIDY2z`v&m7g1S2}iR;+dfXjnQ6 zRj`RHQGZ3`Vw@b^@j9bglCZApB!q4y>>F=?oQ`IV4Tw8Q>7LjVtu~V&+KUP$i8=wC z{A4C7wD2BrLGj6|^i`LkJN;r&DtP?ZVEkr8oP@XcK;x_)@3KtKy%-}*)`x9mXhgSY z?rP~}wz6>J8^zwnYzyjPwx-)OiNq?TMB71Fm!Fu}J$aR`+ASc&nY5#9Q@oT_a7~LL z^JTx2tQ9o;&}zRTX0*qM-8uLUD~m(|hJ#6td9b&k_xhgG&AI>i8=IZS| z<=?~pEz?`S^6qu-ls(O zfpTY)j89mUr52&sDztijQCPDFkMgX=;^9acOF90zw_4(#px|~;OO#a`ck4CC&Y@bV zUyTe8-+#!Z1rLn9&pZ_`JnY|%_vT!U0y-Tr=+Sog8fmhGU_c*=Iax_#0Vb-LLExm2 z2sC2Ey4oH2Ub$qRELlljSt?tk~|3e|UPAG~_m2YfI6=g1oWF=>yp4u!-d<^c8OcwzlGrj#(# zEYb;18Fve*t}%xFQ?0f60guNLyyo3G4?lt(NaP6fK0%a_&l1%3LzcVHe?2=> zXXbUj$_6b-&4R8_DCH7PKubse3zAxW3Ja`lsaoj`uXe>r3OTK@&MZAE( zlK3Xou6k?Al&Drw;?Yz>q9qujEm^q>F2lRf$7YJ|{z&3-+;aCIKV z=-J~~U?%9~vo+U+!L0p%V6kr0mGZCa@kqqxKF?WeMUkLbuE8Dme^FN}FGaarS5seH zc*xxU!~O)?Y!u-|sM-Bic!WUQ9@j)^kw@m}sz z{30Ouq1PWH8H(CEi55QMC0yOXc*OflyFW4i>^O`=NlSbpa5C}u%iWVi4T&`KA;V?9 z2UnIS34o;93)TFXu>9p?-mi;0=UzZ{j4{mmUQ7u~eJF*cn(&!zBvasW>Wv`E_3kYoroUckhQ#$-M5m z`f=CvL%GR8anIp3=NTFKRS(S}Hr-dwDygbVSm?cMZtaJBe(yh7 ztVe%Xtbl3aJ+hTxzR^VmiOOt#{2+>NPBb*iNj<0;tp|!hW;IUZ9TaIYj6S3*VZ_Bq zLOmIOy9UfSC{-)2K9N$kXV!k$k7(9icr1&U`E^|gOZ5$lWuM0x$ox?+07-{3U(sz{ zQ>lTK(ZBe^VioJ&uvoW(;mEi(oN9TN-z?U^cYwvB`isRn38hDE1FLEY_2zsgU0+))l~F{dE0{#d;aD_zxDVsQzyjD_9+iWfowuUj8Q* z%bS!p9$>L{7^b<=MqjqCxjNB)W8&T%TlTa8RVT#%oT5O;Gny&L*>3EfY291PLLcJW%PgmLieMX z$1;Z#SnU#|#RYn|!Lv997%sug4`nE|$YAv%dC;SvMUdvS$J7PfSp2|sO&>$-~ z;H-KSEh@lDA1XbNjl~ufApHGoFA|cQ;oWORVX(gs!fjA2**)WCRh*YA)5hdScF?b6 zVTH$X&mBN}NK9ZM(!Hn{2vKrBEe^MOb7+kFx;cfVb(d+xc7r?j+v{+%aDObMQ^tWr zDpYhT^wr1G`sW`uvX@dj;l0`4JKRl}SV1U55g3^wOIOcD1s10w6ZE-1k?UNvu#v10evom;RYqF+?&>?oSTV= zIko~p+}}(IH~Wg5k#kP`fBd=FnPL*ra)^vwcUEZh!5=PANDHe!+1f zret0HG|hD){j0MKSJV)}p10~-tP^^2NCePi$47wAPa;0@weO*V5HHYS$ab#VA>eI^ z1>e4QkP!?pF=?0F1lkdt#>4~&pI6G1gT$U$kf=EYhHuv+5q)zcnMu>D?DDx4pPpzO zrq5lji4DIW^0-MuFTW!QB?_ofJlQW42>p6(#42~_-z+A6yb`G5&E_SOiB4xDoKD6X zU{=BvS6Gv)Z1pkdyNCB_byKnM;9=kEXKJuef}7{nUp%=}Izqv>|< zr}b2Lgg$GfSWT18sb5q-@Ce_iemrN~yke>gM#1S>S+fqa4tfNk7T@%DMX73D3TX7sKM1eJ<3d~y-B7u}(yJ!LE ziix+LfO!E?Aof`xLX0AoEJ)rkNZ$nq0t--t6LYx}KS~i%@ub^kq}Oa9{-hI3Cu8T5 zi-8?1Cl&8UN(_A{#*{;bm`Q=Tumhu9(1#<0>PXq+eY#&kw59b#h7Cc*z>d)Zd$5P- z6Mwc(9T;i+pe4`?0m0A?l3?kaz=psu1@fFQ&l#e^YPxvC@O%+Z!fX-~!@s5C@2vQL z!%orv4RB8XW@W%1B6K7Idb`k}{dq%SK#V^LH8moV`Gpi(+x1c?@}aG3M60jIO;+4^ zdkEm=im3cQ*Vsj!;Zpml`(*2vuk9}4J!qR{^8>WPZnboKt;DM}1iOCx8{R|&HOw&HQd=zyIfHbw8K-&yg^R(u@} z5kpV|2Rl-w+wgnFUt94T-&4b2ojtE#{KocmrfznMymN$O6dTRJH(kA`2gW6Tc8a3V z{eZ3bC^Y0|@vYDI$TVI&B;_o@bH1KlVyd|5>ZvgW-*ojh?NXgfK5xF$hpOHfaa-&x z{US|Mw~x}!ORC2eRCj9O8UcSBaUrS{5=%OFkpDVc+0FH?exyieruoeFWlXJh8}pFV zxp4`T!8qohuAY;J^<>q42X-Is4LJAjS@Eg+pd{1qoNC|UCWOCV^k#bKZPkDSnc$~S zAqau#(!-&gn8RYpRA72&_+~49w0Abt?R_Jz{BEN--`6r=dZ^kiSVt%?1$R&)Ls<6q z@8u!nW$nA)%R`q-M*E-9pC>}UNPSTE7_B|?t*_cbUQ>J$-kuN3PhRQsqgwg9_xely9zd~c-U0d?%>+MAVurEm9~KD(9; z{499agmJmwhmk9BaBFx_((rk1-rJ6VyL-9ftNHR($31$(zfKqM*nH1cQXE?f*0YQs z@_c&pj*Y9PY52+I!4_5Q>9LZq*A>Zp_eZOSpN~^$Z-cgR_|@gaRX&eYeuP96%inSV zc8ZW~xJFJabJ!t>tkD)cUS;|(RH<0kDbYmU8{%}V3{z^ovZr*zx4`z<_`o$sV74+O z=_2&dsTTm}Mi|e2F2-J02xP{R{?N6I%!WDNChg)OQfBrwU0HFC^|r}F-LX&|&lDqZ z|H8{ElhJ?Dkeb+4oR6~DCK8Zdj`s}Xk0$1LCDBchxZb8MX4}LPx1TL91N+&0X zkrp}`|GGVCo43#;!k z`Reh{jO$Y!jg3|J2Xm{L$g((6%hcB?Fj&F@*k^2}->*REyzgUZVi0FnRaU(-0~`D0 z5lvgH=hMHDFE#4UPHAp51AX@|vA89upI(|vEB_;ikao1U)P)3%mS4tYLWb8AI~#vh zU}y7kgMH}wOpO}ZfF^pS(mI>AP-3zO!bxuj7p(Nq8Xy9Mw@3BAqCn`zRJ;ZW-U%^l z!c=RFN{>Wek-M$~`Vgl0EUEo#?M$EyBsGZ8I-AhtsIJ*0zDN83g3FL)1{x%IjqVmy zTlKjzMp`bIP*K3&nU=hTfT_*tG?D~%&UY7$K3KY2hA_XEqzwxI)wY!r^W)?g(2Ny) zY7f476qB1-(%_08pm3QQay}d)e*_EQCwcpNlFGtDq>5C`D}853kVr)-(42YYLN4t^ zDmqDNHsLI}I47A5R$$yiY<~OPKH6?F!e)68ntd4aW|orldWHUT3+rwnT?AUQFA)SE zbPXn^?)O=f3ss)UrLS7eekGN&xNB%gcLBqq(-K(n%(<_N2E)!UWd(dT1nVP**bFXT zC?InQ+ead=jm|>Ay^NziB4ZLq@lnd$qH;pC?Fizhtl}>WDRae?q&R)8u}*;5bL#~C zA=B7LXKt@ZJLws+bqSw$np2GQS91-=e{QiM7tbXRW*#lUt`K=znfeu|G>a z1-GbgasdP+Oa3ynU%ZoP*G)6{^KMLi^LO<<@4279!8xk2&(BZua&Mi~YZP%grEs$? zU`*S*@o?V>y7N$|>vQ;S7@iOQ}QW8lyz_K!4#?|YRTSR4l`6VR?njd3Nl zoZ-%sK{J%dPT?z7;*sWCM0;N__@UaCi5Z%XjAz4l53Es6cT@o2&Q0my3+#)e<`O@^ z+qE8QObKts`0QfT`n^p$@>%D07M$tPIH`IC-$1i@|5;n`OX0iMw`kTqze`pe)epbj zeKy?m?X-N4yBdy{X(cqT-M*$k*usj5eY~g;;4j5R-*$f;Y|hr=`4YZRKaylR`O4y~ z-$%N@HdK50E@1+?WJ_xjXH1m8r(k%+DOqYSQuZw>nW9JLa>RnkMpW~x?sA4Qk^U@$Q&@VNdhe}ntSblV~ z4DY2+lqWBJnp}VFe^lO$R?c$EY7$-8Q!ZQHBMMTz_1Dw^1Ox$b{|_5!`ah`M|Ibi6 zyuA<9UK0Mo*Li_^AANx>rdIUFD>tj(+r*x@|Co9FkMb$ESQZZXLS0pFmEr5yf2>0t z)xQV5+`T)G{Z_X;wi|LdR8sd-UA*-G7;TpIuzNU)bhL0Cn;bJ4Y%AsLag!I~{?tE# zBP`H5d^8hTTRn!)h$Yz*^MEz5&NR0gfqecbUBbb!uV2WjhgB0m?MOTlRsTlqL~l^L z@zFpU8-TK7-*8`!YwGm;FXfYn@p2?0Eb*pyz#^^*PYJUCj zd-a=w@P@K`;_KMi+ahV-|FO32!T8;eqe4y}ZyiszKG;i@te97*IR)esF!NXqPG@r}yb9rruihY9 zejxa~*8`HM{J(XJ60zmvMX+$>Qd#D-dcg}Q47PA-gv~yR+XlU$D((T^69w}!L^QoU zr8F*1;^tEfdWX^>FuG1~Sebb&mkbTtgM<#!o8cv-MF%MyhG>+3oJO1v$05)1<#*wE zb(Fi#i9>zApw~+#Xg0!dtyB0RM6t%rtcf=Kl@6SRzEe_}yBQ^KcDYO&UrHdP7mz`r zb`XBomq5h0kElDGm_}}!-#6m|3>XN)2$QSMdZ8QFqNa{Syb-B zgv}D8k(?a@JN=4Q3QPa_!Oz85GB2dVhiX ze9~RrLg4T{*&9KR&~K;!^SY#P)%Y$%aTi&ZBNoW@*u&)*hJ(|r402Ovzl8)q`rf+H zEr0z%j!CyF{LWjb7P_IvUcB`*Qn^QlPz*SRO{%h|e#A7qBqhvAKeKDMHa-o02>Tet zvA^#93WmA-1fn{+dZ^=%M#9)2ph5`>;`@>c0y>t^wSDBvIrx}heq%;pYcMd~q!HoC z#|T2{v;;&*qDC{pl>Xo&NGY{wDTJwlzq31=lA-k_i0lB&XZ(;-^&CNYL5by?mO<`b zV+E5<#Z1ByN)jYRc|g|pl0P#e-PV_J)rwLA-t>YX+h^CZdKPGuN2XBHx&01G8Gp3$ z+>EE#DD@Xre1tvxAkw@d;r4x*=sp=0CM#1APp?3xl11!PRy$VTNKg7x>mbz13@hab z$RQ+vv|)7_`gls|1fAgBA8M>EJmi2Dnt6^3LG;`SECK+sUxrb-y(LIeu9wfJ zs7ME0WCpC%;OiRI`qQxCA+kyUbF<(JQ~pd(N{lV$Ow3N_yzxyS&-eA->=@tGiWG0M5a{f#gg={x-;jMHvEACxn!Nd80CdhJhlUfgJIV#2Ny< zOx+}lh@Uvo-i4Da?4!%|5~T|NbtF<6F8|roge4(JsfgPM28DoqWCET8&62xq7=~do z?pjz76MF?0^IshSso5dim2OkjBKBcauAw(H+kUXW-a1TC+sSJt)Tu3)SldzL@6#{8 zMIaPd>eTqZSnBls*S#wxpA*RlTIH&|zC`%F-}e^#ym-y~GnAbkNu@)#z7B|j*oJ_6 zi@0j=(Ae{X$1N{f9WBQQTeVCYd%A{lj0+l8*E+FGw#|IS#h!J*ZscWA?k zK@Z{{%m950>8J!4+oKN_8^sV`n6XiSQh4&M^>-QXD+##BCBN$wD!k{MCjK_?z9{|0 zH&{1G1JtFj3-@?2LzMS_(e>7EQN4k;_6$P|F+FrRlr+*EGjz8|sgweWNGc%e3?W0$ zP}1EYDWxDK9RmVVB3=4H5RouAp7TBL`R)A|_O`*NKq6GB{z7IPWPDl&C!W>0^9$34qxmiCg z6uzFeKO^oJ*S#XUa82jKVV?3E*l=dz#5+x+$A*7&pgIjVH=tT);AR>b;3EMi<8dW2 z<-wnuuAd3MOoyLXKD|`{gm94~5^+o2LX^jJ2*p9xgD{k3_$DdBJpAvhXR+Raz>9UG zQVE?ktwL^=m)9>!9#i~i2pj9zCj6u6cyOWi24L`QF-#KFonmK!acCte)2ooj)K^WU z0m)6v5uc-d?liNgJfO-nHJ~-6w~PRtHI-s-uI%pQ&oR{tnSqdK4jHNiWs&=R8UC(Nm(DLihoB_`RHK~%~nTp=B}@*b^Z=? zGfCqL3VqKa)l}~NHOC1z*Ps+=;F#j9nUk3Lgh=Of6;;%uRh^5#8v(exMnRJ^-;gDq z#u!etmrYjUI7R&~&)uJ7le%#$byHP|(||RlHS=j=sd4g{sQl%h_gvOb#!^Q?N+057 zhr>*5ln28KEnRQQmJCSW0NoK<3wS8-{ceQc_6nc@YNM=OwEW?wR@f8j8_F!&H0!KC z*aOYK;Kw|W!lYt-h~HSX*c!&J7$0#epLb4HdFtq@Wsz! zI^RV5Qj@3hdzlvu!f?{>5@VU7ywLT{oKWGzdq^jGJAn_HFG$6rXK<@WXZpQJQ9+(! zL;}5ivetVx-{%O&LZdY4$B9o zIWfrM-F{JrqgcDKqW>Xv{$JL28{!62H*>8g4ae+mtimhl1mD17&NViD<$s=f{}MNj z|AGhQcuEqeq&EOR3=Fgu8%V?w{wpYUeN7e}a;O}b7c#9MVG9%goRa#u*hYC17L zb>oUIyAd{hI+gm!9cPniWP!AVJ!^}&;u;d|umVhP8Y`8!A2aGS?fXK3t^om@70TqbICPHk;k_9<4Pj)b6gdn<3nuF9j3UU8dAzPx5nZ!mP=a7JFN14&Xiw!;Dt+;#_KNsD56@}GlaNWC-C%_m~$Ig)AQLx{C2@aNa^4L@4;XB zTrW2;6}6+MnyZHjAV6(Z*dNZeG95wuS`Lx=bR=TO+zFhvq59@=)s1GBlDcPtU}x6v zlq3$VYLF83ts7PI1M9Cbi4VN_EI1YhkR^@L8R7=0Lc4bgz3|^}zq-*_Exht!X`-$C zYJ}okm~l{ONMwt2pgW{YUuw0yZVjrr|G?N`hOZxH{Rj1sPG)%p%Gy+X=Rd!v_nnp% zZnWCFQ+t4=Nelb$YeF$Pj{I80gV2wdl|MeX-ldy|$*pfe1=@k}_o|Px6yJVhzJ^;? zT{*UTjQQDFhyAX4`Rk+^JL}Z%Q4m(*b`$ zeD-Y}OvkFE!f_flna6jz5p+GfYjy<(v3uKs723HgI#0A=)Uxl~a% zoo-M9Ed3=6L`$Kt_s6tztqYgWmc7|F-z<{B_O6D`C@554X%@R*O0uuk&}&JM?_}`$ zvQ_W?C@?kq!2@Z!?4iT)QT(;4dlk(cO9tE8?PPH;o?oG?!hOb%-+kJ4T{?qai85>c zw!RnP87f<$^wWCo=@$;>0;UTk7P9rrmk-W%#&=joyrXkp{t{i5TYe_ReQ3MEY8Ewj z=U`GFGLC*X;5c@2SrF_2H)9iJh+3iB3$mU7`d?C9;bM1-JobUkAaic1Dv|EjvRz2+?i?x6e3b#u zI57M3oAG&9JD9m8k&j19KL73mE#xOMB!b@Wi>3b1r^!=B>2rxnzKdJF>FQ z2cr33UNUoWarCEf<3%r5#NPyq&C6E^;f_S4d7yEDkA6(4M=+vjCd@VahWc}>D<~UM zm%tJ+w6;nOuvonL^I;wHn!f9oacA|jONg=&lcnVZ*KNV*{GsWX-@i@yHTk=Q8uNrC z6a}qUVvOF|U4E%c`W-yB4Rg4qW`m!EfBWlrij|}L^{~Qs{f=he&EtrY;%jMZs*wn2 z3$#K1naEMd6$1Q3A0N8LqD;p|Sa(MCJT2Cyd zz}rHHbUH$3@B#%$6)^aEzbDG&VQ`@jpD=T(A5?@GLFWRK$$*OpD;~@QJK2PN)_N=- z9LWHTu#N`P$#W{m>8Q`&PG$-H-4kSxfvi=4XtL=&!#)g`!{4y+CT{s8Zwnnij#@6g zDbR-A*XOV(RQ;<57a6>2jqnL21Vv)JMpE&)h$v5CMD}B6s`tJsLKaV6vN{O*n(rb> zh0i}<-nd`+@r6kbBjhYvZtanW9eR3;Ufh#kUkDbrt3z&jA=?^7?H;44!(J{6Unj*F z_b`?j=$#ZWSFJs-5Y_=9E=$H_6 zoDJgn=Ho*VitE0x0XCL7l!Apczl09c;?R{PBCD2Of(Sx^0=PyYL$}yie1lmxk6_sW zcb*Xwg~-q*1mjRId)1*TPfD;|D%MTWR{NrSjP~0`!PRk4_!kdvDk~1 z`Ch#UV2xB_78qcc*i?}WCbPQnKRAw4YIs!4k}N>4!!F1CzJ(lI$lznZcFoXT_;Mln z^Y_HZ(wtM;Yy*8MD$1!k_NjWA2=Pi*1t1%9NGcz1s+qFlLJ#9dQasLufkI-N3r@xG zku3ii;lXLzF0kS?zSrIClif*Gg~`^u>9-A^8AL)JTXGn-GuPcf-)RusDnL=}(17!F zJ!P_zCA0ox=qX%e#f~uQpMv#+`76U^r(c?p$&-alLG&4dkviW=87?kq(nqQ%m@Bd| znGQeHOvx#?(M&%vg7L%XkC+UTLaKQZAeJijV&sed(K| zJtb(`9o^E7JUM*%n4CIbh|bndq3ubJ$Yi;-hXx8{S+7A}x912;=U88oC655v8-58O z-}EP5Zt3)ScY$oR=jh}Z6koB&b>X}Nd#x_#)C`X-=NX|NtLf*;$RED2IRGQo5oDVl zEpuYK3u60>P0|%AkX^%q9MH~dfz(I2MpLOV$b4-A^h1SiMM$AhQ)Xxni}Cl2!Hir@ zm)z@-^q@l+!@Z(@woI+Ye9OHe9T&YRuVRTKve}gIOeU*SPo_O}5stS6%Ypt(fq)tE zAv0)M8Q3|6(Zf(rhMoCrp+p=9Q!_#{a-duobWT_EEf5@9l)PIGXwQ)ZOF~I@WrHR6K9hz1~yxXra;+kz|g8jrc*FfYnNc z9L#$;I0R=72kNrEqLD%Gc=fTYRgoY8*At7RP-+AUIqXH5_g1To3v1q2RmcsaFw*(X z5wK_@_$~<+;lTdSQt8oCEgM>Cg@gU1#F_hXnPk;!^WuM6$nMvdYD#0T+gCo^U=de_ z{ar*FyVhD0YJXJ8l^#`nfy2HO2ycq28v{w2`$)bI5Zw;6iVD1=3cbRBZqBT?T1)7^ zP`%(lEgP~J5ukbYNViy&NHc9GUJmr8SefDztzytF~GfGCvhV zvA1(}(WCi$QF8Xhnt@z~h}RMgOfl7M!G%!D2qI{qL8O6`H>6QX3iR42+*iQrss{eAED>Vl^8Pl zl!V#pZgQpV=vS#UU2B=*)WKY~Hl25%bKf8bw4aGu&{X{D%q=WlT79dHdn?LYFVp;5 z*G2TJ7+Jy?xo_buWyw*ksyFHTMyRm;{0mxTvlCv3Qb!`^3m7a#Q7YBKsqD=t?RUCU zobyk*DSkC)77`3<$UsClQo7Axjv7?J^kuZ?4=$71ujcy~gvMI0+pog*`@QI6^nzuM zksrf1LXY^^6_GfYo)Ubpij?09Nn?B~fb0E4)sOSL#?R58OBM^wMx-KOWWJoLxIT`C zo~NJzX_p?khF%+|C~(g!F+!&|uuTNl=fO3|KyJ9f-jjZTx*Tt!)Yw0f0TnRBRdHo7Wv{JEbdDtcD_W@+dNMPy^ zmsS-%f^bw#NV=3?X2G{8^NF3BfB8{S!cexWVNw2!%`c ze-8{d3DNtA_{f1k0^Ba_B}pl;0nrxwO4)R#!uMXYVU2oexU{thuozW zZe&akYV;4hqA23*PY?ht!q&t>bqoGGn19Ox%4qm1ymJ+n&cpB&>4)n64u^eqerMiZ z$Np+fUT>YVVTHzzQf$hm53J+zTNRcJj1pU5rhg@a=;N}Q++UIZYg-?`+*ZiJ zeh%|iRn*kj>^E3?y6#JWOmJtswoGlD|4-*DS*GnNqAqDwzw}2<*4O6I z#hyrE!0fvUdK>VenkZH{)Ni~5QG>tm(TddA zziBhWccl9G7EBAessD$gb2aup0_Nif*9L-$ImT^@Ib&WyNCI3lA=8S(RpwBNkcunAfMq`V{h2*H$ba!xyG;9I|fneUGTbF zS5_0fY5V8+dA}F|cj*y|6b|jeo_|@iZd@44{$YrkLxE%CChZiX7T-RNB(JlU$A{ z`H*AAFx0o+mk!+hr-vlvNW`ubcCrfH;5UslXI-&l09nwymDT%nA?^AW?j{}0_-V6M zTtNE@d*j6EMcgE{pBB z=j$r}A$EMZq#wGeNONjUYvtB+cC0cM`law(=^Ro5d=b7NBVesQNZ!l~s3mmIcSGy( zIekOvF_u3i8LEB^2*JyJCPC1eE9+_sCGX&Wy=MLL;QE({H8Bii#o`-Qj)KO(g~Ns* z(p0d5r4`S8Syhy1Ci&*b30FhC8|Z{!dMFqPlCwAmNMl#KfoR%&{tOG3UMWzBM5GeM zIgiLJajQSWazihXTm2a|yVa(C*x6hq3Y>uH0`BSEs=0CPwniYBF7?UzRGxbH5pqC) zP4=pKDC0Q&a;Ej3RT*a-M6HALqPv2x6QQH;j+rFxWIdzdwEb$=XyU;z7JcnXk27dH zO>lSmMji0`s;JZG(bw*3&}1!V{po>oFP(G;z}Oqp;;kXQ-6I0`bQwvLxD8cpFLM58 zwA(pW!!r+sov0j?zGU@Uoi1ZdAB(13y}S7OlKH3LS??;|8)T~^$4@HN8f5PqYsqyw z_urD8!i|l#SAI;Iw0p`~FZsi6e5}*acFxh6nQxP>%61O9ei(WE+F#p0H~)rRI9D=8 zmd0Y7=cr5douV}fR06x4_e~Ie=kAwCiTTYf3Yq2 z4t|}M;Xv>#yrj{H`Aa6Ghq?)MSad&+)8Y+-ShB~MG_F^tK&aL|pkRm=ESMcI;Y1{Q zxte&k+_}};WU6_Y^DsC0#fOKOk8&3Sm(875!|1a#l)ob^u;UGPF-MXeaz#$-($c)k zdRpQdhWdi9#if`zgj%#EL{mq(aYe>9GFvh9f@B#9=BC$dj22D$WGmV%?=JffT(4gI z2?TtlHG0u{hxI~ljxc~I=kf}8udr0Q8&*5{+F!h8EOKR2nCDe+c^rY=LKtr;GypY23kL4_kr(_)csV-4OZVfU-xfP~V_!My%CPDWRXc zdgCp6$-u23=x&EsxzH`T(GcEb{ma}ZdCbDOH|V~f3kE*>#K94XdDh|GH0jf{u>=2p zT6TM!8{k!Sz`Q$?{la9oy;AJrZeH!@-_35#bV6?rlXhmUFpkmt4oa_}kL*jTW`W95 zeb)xnj<>GX%xn77Jo@iA>Z|?2a1`;Dd2Z*|(Bu5#-8r>K3m)YrIW@R0y82A#Tcm;z zhM&8`Lta8%!5de&3ex*ec(XB2zariiciKCKj%MORzh`ZR%6J|jEV z8C$2fope1t{rs>i`!_9{PgyP>|J|n{RBFuS`?!7D4C?0Br_2<5#Ky~re+1kItMrcs zsDPF^2;}LOTU77R--!JvqT70N0Q@R2?Z>wGJk16S^$UvT!t;MoxBQrgtydIBN zyJ2Wzt{q87#h7!s^D$RS1O!U*Z+9>92`U@D_~eF(8ATcN8yK2BYBZIKH4rEaNL;9= zq?G?=Kv`C%Is`^M>;q*`Y?X~2tSZgpb`3c1w;SJ@exXO-GoUFa1CCnlOYPLTD?`r@ zv+CO9ImZkhrYf7>lZ+Dfylh@hs%kg&QJ^7zqV`aFuWaUzgueU*bXT5jHzVhO9)6AV zP`f1HvHY?9-#6}KlWxn6SJ;RIo6q!ZRH(;XsV;cET7>+c&hX8XDHhe^sMyd)VL z>MNVVgW8T&=GttofM+BDlx1rca5)e#Z5M@&bw+qWU!dk=GPtY<%_o3;$fRp(H z+VI%x1>u-P-LIE7XhRW!HtC}JB0BDwwn>4azL+GgBo*!svT@BHdZd{Lyd+yt~hp#dSaB}bux(IIENGO;sGCS$V7X3oa zPAJ?KKI^7i+ywr2k=Q;a{V$n6EI;z;rjlU;D?7>BlPm^#%(%g9!98jIV_sK1UmsMM z90Jj#0>0UsW!~!lLTDx|6?G*8eoOY2rY;tP0TbvgELO{))QQe6+sf2pk&zZVp`XXU zg~5xY34!mV0HOMNIdvl#-OcjGxX}Qf{ zNhRB#`rCdmd#k%3oA5QfdLtnKRLC`SE^qIfOPU$dPMgody zEso#eT9^QW?O~BD$ga%2``y*E)-m;7&y_eK_ zmyS`{B1X<;XOLW8QhC~|RNMUMR%#u@{JW-a)UC@JpbCZPZykJJ<*N46#aSM>^ zFeKyVJg&+^E4Ax(uBa^6u zQ02fhLym!(SMIjDp8pK6^b4mXmv6nns!Pgs*1Pk@YrpLDR?sU~b=J*~39ytp^djrQ zd_r``ZP@dp(e@zB-dSAw;B7=uhTBTOJJprk{GvZ8rI*-;v44#bnoDnbLOPVQHRJJs zpyO*mxg0fPAj6wX&hDJhj^+=X&9f*N8ZR^QhIA08v;@8eB>^#Q4vU%KDPprC@6BDIuDTOsHOJ z5{(xUMA5}}J~-D3Kg6pqHDUJD2=f5d-_VcQuP`3BzBRosDtY!~=P>f2MuwrW*9(su9 zV?r`|YKd6_6ngM1TzDH0`e_DTAmwenGx`P_-fve&umoa;2NI+JAU3@7nB=Yg_&?SP z^fN57Oh^XDxZH~OjTzAaXdzB3;)*qb9SgY61@IQYGcMpk$0+4Ejc^QrrvAWB$rSPU;F9F0&BV|eygqemMvZJZ zv1-8x2;F^^_LfBMCkDGq<%!49v<(3d4KLuzI$Yoi6EM+)SnHi~wHgwtq;3J0#>eSw zV}QGk;JRjbl?|f$D^Y0FKvYDsxFp_FtKx2hWVsU*TF^j4GGNYpBfbj^$B)Kibr*+5 zVk-v8)C4uq*td!y=3#8FlDZc}yQ zuNLkm50oSo{vH`rL(pwdQv^)oi29fHC6HyRnEU+$HuuN-yoSjb&L__OKKmN4os47X zO*Pj>-kgoc36CkgDcspCEuB^f$IIl26$j6lGFO@xkm#Md9hAL5Ll@tFTMdLvhRX>St$YZ@nD@yE+VhU>$0 zwI)Og1#+GE{0kn=Z27l_=ua7K4DPwrsMwgQMuzt{fLjbrhC^)r!OO<)GwFdW0Nh(s z3Eg_n-|8^a>y>c<{+n*)-x`PoTir5B7)O`K|AL28@FJztgbEF&f@$$wtKT-n-#>^F zHyMD=vCD2KnVUqBe}4dH@s|u004CoL*Fhh8;MN2Rpx}5Kcxa{gdO9-LI(%qSDS@b1 z+o;+}Dx5b^!M^bcW#<2vgep;m8&D+%&j5)tqzaq33>yN40GuZP!Bl1^HWqhc&A5ri z4^jlAW}}>K2yHXQ^5Oh!RM*&u+?d&hd4m3f>o&TxiInR%Ynk-<8H>&ugD|mjqNod} z(qg5W*u@^Q?>llvg8v!E&Qx^fp+ae!Z5cVi>kYjtXZ(WaTrW_{PngQp>XoOHV4X#D zP^~!2e_#csxS%^%<)!m|W9bHc%YV{$0>SS*(1|9+Wyu-whb1u14k^D2e)n0fCs~nv zN+N8Qb`z=dWy*7xJ8j`&L(t9a`GogeIrA_0uoeE8*saa^WC>=&Y^EFV@VmGsqWr>3 z2)l|im3rht7KDAGF*?whDw2aP`Sn8nA5ueY&Uumji}g2gnIr{s4E6SuT*GxoELpCILg!Zia-q-_IxKah zp$mhkIT{__Y%PgSMOzBXep|j;$C0LEKZSVOem zeAI*bo0qqc%c9b?pG^_3&Xz|2Jyu68-V)4KSuflxK6?2tZq)+{o+MUK=D9BVMML6z zPf$;Y(O&Z}g25~IzV~2a$j0Ka8)>k|CyA4d$skqfrD14Th~s_X+pjxyPEVk2I*1;b z50NC(^C8K%vL77Bn4iF-{V=!O!y8AvQxsF`C%tbrDy;y1CO-LxeLP92nD2l?G6Uvs z`5`Tpj{yZG38kUYaffvf{Ch^}hBzh5ULrZW1PK^puk&1W=ul3fUh3^`Sk{i-yq;)l zLp-QjZNSX?W={a|AGe5WajTIF8MhMUUGZGRcDI<{5XP)dlG=y%t6fatvxeOF*Na!z zFW)FhORq=-w~74RGAZJm*ZU53I|eL^#}E51aQ4Ll0du|Zv2PZ&T!y@0$(c@G?WBU3 zu3F;HW@7us3wEE_d1LZ{o79W1;K*Rtddw&jn+0|c|Ha*%(UGnJb!SPKetr$0uYpLf zk4UP}UKG~hjG!dh@wc_{1kyy$Nu#B`|yPev3?C>XjWC24>YU& zT1&jk15jgmTYg;zJzuA7yDdgbZ~r>E)_96kASGOUcZ5hE{s{n6+Toj(gamKdFY^f1 z66FTcxiec2jI78N>-Bci4QNejl{6kKp>k6ol$QSU`*bdP-tabjG83+R4R9I8g@0n9 zcS$NfKl5k?Ktkp>oc6j_7d;Z^W!e8!Kg*M_onSZk4M@8x#D0iB>QMg5Uq5NnCu&8c zI{a7{JVEb?=fE$cmG72zua;tF9z-(>E<_6npQ_($+ z3`HBB1w+v*{rH4i3}8;YN6IFe&=BvedzrOgT8{`^O$vytC%?FZ^fc-5GHhgtGkugV z(=GqR49o%tR#zyf#7CUo9RA~@F&F+g6^zs?CZ_XQA5(pa~gPlLbZ0w<0TqP`sia|$P^7SD?}l9wHBPJWbK}U zyH?)(7mD^7RI6hW5z2dhcSrHzD-^m;QyM_Kx(Zt#(K=1}w(+AEuj@~t`*^oJ;@`23 zv-puZB(I5a@kxOl235;Qo8L}!qPup~+tC|lA`JS`bEZa=H6>tA==gu`ID#2#lWwvQ zahpNmRT{9@6CGVlujKI5U{k6?L#XG^#=|<$Xt+3D7bIoM#0{Xr0Bl)LEPJkLEFWI5 zDPt9Xev<-F&szR0fkoF)oaM})=mY54>Vn=eUZM|!Xe3&OLW3He1Bn$ATeb*q9Xtb3 zSyW`~+O>E^3o3T_hx`3Mtq9Q}26Ue$P9F&XiGxfPHu(5fCTcr#X0P{gOu<%$V`1Gt z94@|bUnbgoB0e(-+AcUFI0GKGFs0^L4mp|fUr$u5&k{%`!g@Sr#5GTeV?m*szpK;w0vPMw=fh}adm_P4 zbL4yom~+y6ND}3IelLVz_jGphG3lfErRqmdj(~43+n&~Uhb3ZzdTz(M&7H4)E4{&g zY$mf4cZD(5hfvKFNBc=N7dR_O=3UgjN9+}D;(^S? z`j5Yac}s!;e)t_zjCe5j>nSb>l9PrAq-A0f_VmSv6Bv*frQO3d017T-Rby}z@lQ)< z;@uA>Zvc?AX}+>Aj|4_iMQ=2E?|l~>%aGx|r$j8m5HeM+YhguJg(&I3M-$W>sauqA zB&~DBUaIg+43oIdIB`vMF2=6Owq|(Mxij?oV6w#hxm9ww*N40WWdUMZi@(Hvf!*oB z@>_|IQ0Hpa?Zk*@Q_wx*)Njt0%`Z?lOll6UZ4Ny*%}R}*&gmMF60t6+d5GPbOxO32 zE6*(54KKg$f0cW7>E2An_42Ft76m%yUp+oP`0tmZ@6eB3ZkyAy&5od+>sN0d{8s+4 zJ6&%5+%t!#J-V;Y$ei|-f^W!oqc5*~{;FO4xU*BbqjBVfJ9`zwI>z(%?Zxkl)8o2e zv%i5G?x~5|fS>w{YOd;XFtwxj$CyZj5nIX=)Pmb8VB~sG;)_sn%48(m7R+bzGb)%b zcBetnQUT;{H3%3=y)j{QT%*LQ%)mpvqFu!H<7RB}g4>h=iB+;-Tf*QJIuAS zyh~C7b$gOiSPW&lJ*=h&9W^eOm#rGSQ~mcs?AMR zj>&zc9!!yVN~OP!3(`TsUI_DwdS)l6WLZUhLc0$GKClUR=$+M<(7Xis$^u@5PSC)L zcZUPE0LQ5u_C>16mI=A=1nmlKYK@MP;B%7jO0DX3YeAzdCR@-U;AX0s<;x)J{!334&r&zE zGmevYoPkXb1l}hpA2GH1MXKtTpV%`v6b%Eu|HvExeCls1RpMveY&J3+*f=mbwE7Wq zSKtLxdN27%1=~UsqmGx@b{1tt!SxlYueFF4_9^>Cd93yLHVAkV=~xu z+Sk^Ub!KMs#p5~3>F;c1Uyf!|wRP4^cWgfkc|Lle#SgkPEX1+?1oN#8Cl-yl$Fo(T zucC1mO10GAfCA|LRo(CZ|EdLY3>u2w$Fa%Y<04)AJdlLZ z{(n{X#F|#K($SYfTf-5CO=aWRN&)-J%9h-d`B+F*F>CX!PQqFE|5V-Mj`NHWZeX@IvNqfFR3zzq7{$ieq9_6{yW{Yviz1zyu|1xlul6rGPWk$6-XZamIt;}#Y z<=bR1yjuCQjuzLf#`M@`YB70bTTru#R7zol>x zrs$I|8Lyxdd;DlF4eun7l7){nRrgPJ0(dzHTb>-c(LOGm(aWTAiqgpgk5vLZ=s3}o ziluoKI|Ml_z||`QCn8x(wLckldy`43<_#zptqCTbiSW-o{Qo}NA6L^K@Vf+<;V^t9 zuDYGM0g3m)|8Nn2|GLX~jJPGxQ0H92t<6Asnd*iu_QUZEZFl^mbBM@*^RWH4%E~Lr|dzMJ_1Z zh7}hV?rvK=#eH0YjoE&QlA*3VzN1yN`XNDn$Ub&fmMQai=f%@9BZnf|_7E$(ex^&z zI@a1kWmEel(?80CqQ4v^avRe`BUvYYz3BP}gAmKQr_v=gRg`<><7O_9{mEA#JASz2 zJ1$3fbt(s%TXGyKpl29JuLEsyI6wB*8i#`gUoU4-!s((ysWI(y7)Z@@w^)H*0T0g{NG@Jnlo}# zo$J&%%U32zrwVJtV~7Z4^7@Kan}A@OuvcHAxwO7sZQe6J72#;Y?(WL6KME#09nabl zWZ&0-|1^zjna%vNm=f62rQvGT0;j&GmftXu{XojCVw>3%dTi?L#{D0~?)*}mRux44 z_(Q8MtWQ=85N&fk$EZDafR#?LE5#RmgSr8Cqog)tCFil^w%Ym8r_zaztJFU0+XC^Z z2eiOrCRbC!Gq~D@+L9?jB~vzaANi>=F;?n(i)8KuHTe=%yj{mH&;4I1FbSE1*>z`oEr~La@F;FYnRKK8w_#{ETS3T#c5|v0r9CAR(TzM7Qcx*MRJ7#g1g4oRID=?`itn- z`UIW@PA84bl*`Fi>JcuibC5wLirk`_X)?s*eCdLSX>xEXc z)wVQZR!R4WS+uhiHz4u8#no!L zY4{9>9dutWAZR@-N9pu0UO$1Sm2 z+uP~2CN5=8B+h?os`SqP(rTPxk)Lzyt~CIBzC1a{-mV;D?x2_C<#qZJ3sw}&egCH> zN^vaZB>89c4KFEc4qjJi`5{cOrP^q4KlQCoRR5*CAH$z+*V^4v(OvbSC$AeBj?Dz$ zJBZ}RXMUHfbefQPCSc(An982l<9(&sBbk5qDsEG`wA=1z)aUQ2aT$}{oel{5Jx43M zf_^(*kk5!p{oAygzk4pwaq}grd?;bk&6A}|0q*1rXip-Bo3L;@GF62y^PO!8 z-M`p{>YRviDD4j`H7Y<2Y5r=YXY(DlXpGeTC{55&U#Z|H+>g+V2>mXD1nXqCnmv~h z01r(zFND0>^9|mnK^=MW;{MFNMZvr-%r7Nywlx*2pri(-@V`)JEAyW-dG~*63+xr! z^j`42Rcji9f>}M5HWy2P%=wW$Ccd}(pRQ<-ax}xi8u3N%epktTWungJj4na^{A-+V z+PE2)ksWYOYuMfT{Y#*tLhI&ViRND=i`N~c*l9iwDYrd1%uLvx%GQnS%MJI50|dUE z-o7#*_6+sl+R1Ff<*uUk!$u#XT+#68)plK#X9!hJupqGvKKAhp=jGa+D-BP~*!hDA`R}nz*Q=f~N%vUu zQ|Bgq)wx5T!NX{eAx(C~QK@?_CZl!uBb@4cI^bCZhn`4`d5F?zf%-9{{ZFTc;oxim zs_Y04qY#vTDCF749J_`06E5Fu!{L8K0&*ke6W=jsvX!0+?@cN@Onon>cn{vF9PAo0 z3%kNwb^=<}yWGufj9Ywcu?KQ~cKYki7vRv-{0j=X`&A>vq3(14{k&KgUw!#a;~-r=*N&*lPemjxNtl?4sC@!mSG>{QY1Yu2HwnqOQ23A>bDnLZsDHpq(Y7 zyQk1q>+t*Y{Jm3*^Q$jR3mN95MEKewj};>x?!r-aa6KYw_vIC?Hs*eK6hmJ$?nv_~ zn~VOX8ypvW=ln35hAe4z#L_7RmvM6|d8g!q9`c5H|@_6y7LL~ST>94kaBBAzeJE8mWIVPYAlDh&D1mWVZN(Qr1mv$QK~j3$1XCx}#_q345hvDh)e6d?r7|ENlpWoQd4Rh!W1RMj{yk(&QU!aa_FVygh^!PZSMR z*3~13Z)GMu8n%k$N~uIrHKr*MQpzetk4Oqt?bt4SiViP|yB*PkfVDJ0+2&tjECmM6 z5i;|_pAI3zd&pxrtT7WMVV%||9E2#xGL{D3w`>{C)^o!l&TKG4WdQDu~RP^^C8TIR$>?-E(Q(7`2~< z|60J=?7%#uqZ~N`Y_mR(E(@X80M!gm7jJl`Kmb3c_B$N6shwv8Y7Bqa4o!INtEnx z@y8R4@8P(F3k0jKf#6YF7Nv-Eh+bByf;7x1w9ttI`3D&58Y_RJw@8#+cDG7#G8i@E zA_BXJv1%y0Ze6Y+Ecc{CD!gYBDNg+TZIwGPk5JBY?xT$9s1>Tyt z5)nVxpl9VJn-~a>zsFL^;gXko3Hz>e9adQi3j$@tkS5TBw?N- zmUqgC5m6*#6Dnr0jw@2FJrp4rj9yYfuI$&V8`de2(N(_WPxh$au??J$U={v?ha3pA zN08Il$8=(ib3!owMu?%b-{b}B!^;zrCr7>zqnqASDBeale>ktCTe(lh3mj{t* zeIJn%!=XQl&M{OAfj8WXW8S)G@%BS^W+7DHu!1ZYKfq&v)UQM09FC+==B^CB=bVI5 z`1hWc0oG=bLRgN9*7<6VTXviMTEjU8_PD2Hq}Pjfr#w%ULvo@0XAy^&D)OIIng{Xb zDld%JQMx9(gSO~JzeS3uWve8ijULgSF5TLZ%^XNyDR>n68Q)>bD>}i6>?FT|xUjj0 zzNJt#4IUw110d)4R<6ta*WZd|-uRWzGfHe>-hzQ|ul2U79zj-B19ntz)>9x`97v@- zzSeB`PwX4S8ex#w2gyVumcMTd zmsAE2r;rELa8YZfWo)m)Z&p8`(0M^0L!pXr$2-Y}p7d;lPdL{{DZrN7TLv5q)!IMx zJxqh?9{8vaf0ii`r%1O9zZDO6!M%44i!oH}Q=)>r%1~dcLKIo`H{9rhNz3E^O#|Bo z0+x%vbZ5C=Hn2QXgY#5#?_*g9Lx9lrl|zKXJ*0V6?=_dg=r8YT!*CJe#X~Bdu+8B&-de#=+VIgM2hs8m zT{`>5a9i~SY*VlA2et1yk5*c-NB}uSwQ|OtaB=o9F=J#$4LrvlYV?+y-N5ftJTCqT za!IPj#|3tGS+(gGjDk7XpEf4cmhH7(7A&f&3ony)qTO; zcr@@O%j2#K?9^hS)OtFoP{m0Yk-ombU`bB@gDZ;dfdR*j-;y2G;M>M*`&K2$gL7 z)YCmI=h6&c8`f_id(^Ofou+qMW*5`}{V&Ge`m4>r-_}e>fM5~a-8EQoch^Fp7PNTL z;%)HY!KFZh6?bT9aVy#uD^MsDceer+hVMCdX3nfxcdh#eBtK=nS^M)odq2{5V3#c3 zK^lVn3tUl{P=1eA)*Id-y5dDh7vDI+i-0+8DazZ9vBfY7ewGZ9+YeI=+{J|I zr!h%KcfjQ>!1*z71kD@wc&mW9@H_Q-8^`k6iWC5*jClVM9*A1ZyxFp?6&SC9NA1J= zjY+O;+5potJn1C5>~M8sd}C}T9vkC#)_!Lc}9K;~L251=ouoV}a&?pNoN zb>?Ps-i^ewA=7EV17SDnJBA;4ej;mwfQ#=8$k&j&MCJ#+wXmXGGJi1&7_K|; zFT5?O58$}!-=Mjr)&7k9N zEy4_{WaK~L`9DfYRiJ~Ug`{-+>s&7prhJF!IQiq{`J^1_RK_hT6&k5$<9Ig5?Do*> zyZ`@KX6{%E*d)4NUJ>bfLiPihn&K1YL5K;!)3~#H!4Qnar<3L|xeLNfYUp$862(~Rv=&n6CoRywMJ%D!6URs2K z2kP0_S$>H*#?t4)jK9`M_+-OHmqK0z^v1%R3tpb0Ve)olI*ag@zzp-WUmzqb_|=uq z3ke|=rk3SnTf-}eiuk7jxCj&Cmoe1bj*+?cx}FF5#7N?K7xdddAr8d!9%>ZPdtPhg z^7062AEt-}E}Ygc?)ZNfEt?yB&bUx8*6}koX_wkNWSE8BPFfMoS$) zQ235Ow&&yC@KajFNLtat7H|08x3vF>x@)I$85F4Jm~QB13O(+OtT0)Yjl3kT|DD4mUYezStTX$=-8{=hkK?4_iAexI=cHGbR@<-n|i52Eo+FOZUiwNX4+{74GugBHsxuvjSt1)h2d zeuTQ14%e%8NRhjsUO6lgVpC4KB>PZIPw0KWXFj7*t~yKTm!1SY@vrJZ9jCJdg2a!38*Mhd^yn~aoh!4k$Qgj~(W!ozgSx7unn4$UU}j8PJ%nxpB>rg}|( zNZE~rH=3seiM-Sq|FOEHl=#SNeCt$$(k&;O%ZUx<0XQ1B@-~)(B`qHdFDq4EF3Xzk0S+UH(}Shoy=G)v<9PgvwiP{gOj; zipsn>q2!q0gD?T@{X&fnY}EJ4k{oae_xDBei5N~SstrP(>)GNrbm9)6WDoLbAtgR_ z%mdn%?oRu0Rc=lDf%!>M(mKoNh^uL$7cDS?2RUsSGTpeC$VU_(HWL&fVUaQ7E|rE| z7Th)fQrg}|;WxJ~ALJ;sSyv*U+|0@YmAfihx2WLr7Aw7c!|Cn_s=fK$r>P@*GE?n& zy{L$5)hpJWc66htE9bzySmuxK+vMtC`k0~hL*+SKIBvT%z4Vorf%aHITx)n12AW`h4lr&f%(eBbC!7fsBh+@6Vok1sT_e|MD{^E0! zjSc>o*0)yb=(j%+PfB7d%J?EBwsIv5f83IhG~ghHw}Iu0HT%2t`%%ot-L!fhL)grY z6He|ccD0dcsv^Jub8o9E;tOvcp|Bl*!l#f@w72`v*h~5vI}iBtLWzPK!)U38k^b~v zo1CxEhR@2*-2NRC?13RqoN4UYp;T7}CMh!x zo}hAuc4K4^5t|B+e@^8y0&?ww+jttiRH-~O!!zrShs7je6}euY)-wm)bY$+I)jI~A z-CvYQJ2S?HBfc-|7yE9RF~&0PT21k*EGUzt8)N7EBEj5PM;G|}k*Vwnk>Q~&i+lA3 zE7K_=2E}(yiiW`{P9GEML|$|95&E8%Ch3p>EX&?oK-O>^u$jJg*RBf{0*_eySDcEG0 zj&Si}FYYU6=OF>rqq!38@FMwJBr+Mwxf9QTK_kg>F4wcAwI3H^3nPl^X7Kd?GvY!SvVVYVO7PR*Yq{E*89wMb6mgzt8ImG66JVJ1+^u^ z(Zg^}tW``&Bpt_a5GxL3bx`fHze6UPIwMhIr;XneF&7?rA-tyFi-&ExpNxAaA$@V+ zsd|qEFMu=G-R8;m0(%NJaa$enhNmVlZ0clKj?1YFraCvaqmZ={UrfuM(Xo2_D<`;I z*kg^tnyIc|N~H}MjQ~Gv$69fEN5`cY^gf8*>(#8l-0LM30fu zjvPz9MKhEw!vg*BDW3oX`r26kIu60fZ4a|Z|E%E4w024&k7C^JN*U3un(~VBp|CO> ziVKULy?IeUjSSS$jx&0WXl~yd(K7q3ghaB;~V&xx8(4|3LT;V|cVC z7ld5tW;{liyh2Zb{eH4e{ge=S!ajm+HaJ$1k~fulfS8TdB`zENFf}CMuj(FOo6Iqy zJG*(iPj8ngcpF+D*gAN0|KE_F-D-DH$|>X4)$jaqjU>O(8svNf)YV+Lx25myII~Qk zIU{;qznFE5`uDPN&zX={;y0R3{lz2~p~A*MN7+|(e&IHjpxrN12AczmSsCz0%M zu9mA#Jl}3|ATc)%6igd4*Oq?=a6WdfQ0`Iw-5nDLCtyLBi=Tp&=0GmjAO(Qp04r1p z2b-c(7GH^o9FHJRpuTQ}#FS&iTEj&V3A71}0LrWt)~xGRIe7%ZzlvnZ9>QEK0h=d& zsJ0U8SjNIxQqXl$0Zz5DobSk~dqfU8S)Z+f!VBe15Yo@MbAI6u6W-qQL55@6uZEzx ztc0A$U_N=Zn2-4*Y|yp`#evy`5|2{J)}ga^s}FIocwiL!GC`Qo1~T(UI? z90`0bKWLB+SqXw*7zYJO-nYYbR?0P_Q39#sS}RV(6XP+DTf^PQ3H_GYRUT1V)q^Ov z(djPQ(Z_ji%jH$dI@8+Ox2D5bxOPP=nu@>hs9TdfB|{7lB^uU`IYyU&Ny8t=t`5CU z1u|LxZV7K4PWOZv-!L|=7e@}gJ?140g-46QO9?{yAAhLH3K+@I4pVzg?8Qmsu#RbK zkLwMuL!?Ps)1hSnf%(NrXcA2ZDDV=Q*V z1mST&6@6?sU_cPQ_Oahu4Eli)%_Yq}zaDpt$oB+_v5wUudVR&~fC@SbXP9lr- zq&NEm{ULE8s#@R1C$a-XBH4{e<8nzmAi3IiZ1Y6rk9cHY>}OY_>}B?&KEebU)eLFg z7#&QuAQ8!ZWAXV)7*p(@v0}1B$gQ}*y|nr_3E8!~)0k4{sZ3h^Zk$*!oX`eN7+gOz ziHq>?)bmn~rOie&>KRtGVhDpE`;l=%)n=LS309_9?I@0DX*r*vzSQo|GA3pn*|om) zG0xcp;(2lO0VY`KxHUF&P)>|cKJm{nOzg^QP<&j0?QpWw;Fxc$!!dC}w^G?Mx>|NJ z6Wf18o49h7bxIrKd~8-RNAUhfYE2&TL{DA16A-pNT?HsfH|FT*#yoO>5bPS&WY-;D zjZVW!L+1!g=HvOfhz1ZzZi)Ks$3qDZxZn0nWNuG-C2H{s)wZz?B}p605wSctAo1Rw z(iE+s&=JrUpOUGZd=fu*o8no>>K&&ZiV3SBPRf7~W%F89JxCj83Fud`x`_8-B_wiB zALS?eqHI+)89$sOmx!tkEhSd(9|Iz_pCl4#U8EgWQQ`)O^FuMEbl=7Lbi3e2&lgDE zTqIGEAp#bYNbCx`wo4r5)b(oO$R2QGczM%uB&Npk@#CcOJ`y+5c_=f^6OLvG#T%# z3LjNP2NU_~LZ?%hg&n4(BQAWA!u2yIFz8WN_oLS~tmCD`pHd;s2P88C#I@f@tbYLJ z$wpHiV97l7*I5C#CJR3#dg?c>q1LI7D|tmdkc2%Ed_5@~hxJW;?6qqb+%ReBF8)Vd znELIE`bb)d&Wa!HS8RxbW+y#}zFHzoy7hq?87h~>`p@*P75Br^WUKJ`3T?nMJBTZT z@xixdDdTYR(Vv(6PeHV%(+|S&Mjw}B$e4q5ri=}I&*Ga>!!F4sG1>sUwB{+e*s};B z@G*+RXTEEkF8WyXaxrO{i|fZX;)%}?V>OK~R#dEUO|wl7ZCXQQ0P1c#UeF21resc%E zBvvXZ4j;9-R=x!m1#UOc{q*EmZ$)Kc?)@`>7;|I8((XCQZKw0nDnN-8MloRHn&26m z+iJ9da-&o19791Uq$OX$B9cCi0y-N-jQtW1K<=b56Qwc(q8{#KelZ~#e}*-7-at54 zJZOzd!@TYUD9=DN{ir#3A+c$#Q;={D?PUzTOCdA5kUN&OK3r-UTsaBiF5yw@l9K7QlH8Z(W5(Bb5!Dgni*XUM92Pe6U2eUkXOBH~tm4&p^t zSX)o*H^k`vCof6-U;kk&;YE)n$fitOE0G+ILvo#P;`{rgV&w!IX%I27 zgMguAhQfxPb~*TY4|^I2cK>leQ=g~r5rqCKL^V`MSW2oZ=s z6TlwV6{+os|Asig$*2tHnFR1kyUIE?ggkR1c*cw2@r-d(_Ub&&X`d!z7r}UX#sCBG ziKvb*Wk9g9u7GY;+OP3$*yl;v*q-$9Kr~5Y`Dr;OL#_ZsLx;YV4S)#Jk-iI!H5`MW zuzQ)=F^;?t|MBp<8ZHIQ2i_2w4DosW;b6LZKg(FcPnxRDS%YnoP-m_)8x>upo!yTm z3^qR0R8IsuSh~03cWNiNOM^_hQ%!UFL*R0r+YpxaS;B;~49_@e)ZzGDG1))Hm)8d* zMRY3@!{$$vNg3G>Al9(+$-2stDm1StCww*@?ulgbSdMms$LLQ)+Fbe2be;H4xSdVJ zx83Q|hK>_Zhm&uivD}VtUoQP^@vu z82|O`7tyUR{wfx@O@i3*~gZiHgoZs(=ql}QAnf1x?>E4 z1u)MBjeVcE!{A$q&3I`9iFy;~Op7Kkf*6d0U)EnF)ki&qM}GmNgyMcpUf~jqI~N7g zPI2ck^`66&-#VR03(-ANe7R^P{iZ^~rZuwHkV0ku*hgLdG162Cfc}(YXYcG^`B`!5 ziwYB8zNQz(6!W&f=pt5UBaFYE`uXLnG#_c8G}Y9OiNbVWDowDO&M#t{;G~JZMaZAd zZvu%6og zN33VP$KwBo^?dor(&&!$ME+;i`2S`-hnu#P15Zyk7%*SUCW^Jw_$9AAD$Fue-{|J+ zw%oCvh`p9Phy=ey-c{U7CcSsnRux-!$kMYTL4%-k;>M{hq1uJJS>xRn>1JD*(1*Xc z$#`1pSNbq4nG{*s>yJveCT%GfS{ogTZwV&%7KAo3J&wm7Cv6`wtJ#D2cf_|2H)N7& zMNFKx+?x;DYTmYrE8KshJVLG^m3NW6a1axU$i1h4pQGq$W*GhX`l{8hpgUPp334bk zY`Kx}^j2%zP5C0auG6Y&{(NQT6trx7rqJ2>H^SUL?n5$May5A3^VFDf3zzyA!1t4~ z<#0l#04y&E*YMOER*^z3Pf2|_D(-IM07Zsulu$)*9&$cXxmouya-}@jB4=#hDE;a? z!>MhGB9P%lPz_#fg2Txj9uygM?o6#<#V)uwQ+WoiCXr7`J;&~maY2k;Zj&~1s%|Vd zbETo?&->9f#F|Npohy@?8aZU+TmKBjpV}X#GJVVlL$8AXsbK9<5Lv0sQarMi4^1jjq*BrLd|oI zRd;Hz0%FF>C3;HgR>=Ies}?wg#3Fq6#ol4t@h5?!_VXFnqmHZ1_$~fFmvZ0uK`rc_ z0{1US>N_EQ!Gz4DYhL$R{Pj1q#o8eKge*{_jbY2+{S;(JEGc$qh|Nq=n*$_KbZQn) zYHK_!n6_~;cv|2##P-yn5yJ6QviA%Sv#ftM-dXe~gGG@<9l~aQ-5@?;to4_C>Y3;P zX8OUinhQ-;vu_w?(C7AxIeW`Mo6sC||FszKAB$`V!)?Eo zRV>6E!xk$3L3>4isZeYM!=arBfAO5ZwLeYO7A^ z{@0_UF84&#;_a?_C-5ye0EGKtPVA%{yWjhWOnu~frYv=ZX)r*70l$hdyay5u=FObU zIyLT<=Bx>Sz`Q?<@obTkN2|JCoS75fslnPlR7XpX6+-PMdzfVHBk51_V7D>lLasQh z4>hOld~Rt!x9U-}VM0;e495WfVPcrY4_An~#A z?>xAEyNDe*Lhi2c+7gM$h;mysPy?;7Ztf(q!*~F2sKQ4tHo<=&>!5AT2mjeW`Km5` zBYf2aYs5bw+;Uu4>pP4yAV13<`U5eR%^7pF-N1fHcq^erGxmr(Dt$`6l#~!TRD8_$ z`unh?7ORJvl*625F6VLNii@R5} z^iMC-lsaowpb?Nf#gX=`MlF=klMrzL}{W|A`%Btz(1_S@{u7dYmJq^`oMwOXLE zWV=oSq0IGJqWiRM!*GFVBfv(~UMj08T^bpl`l^6rx;!;i+!=;9|nl<@a7WS8K z)naWrhqpcUk>4mmyM?FOs&x@5?N~nvsUX2IDa$DTEl!Y6D7Vj-(=4HtQJq>xM%XQ* zP$KZlTRgFXX3}j%cWUm7W9_GTdenhvm$xj!%`-vqz;STV7x?@uJwfpsHtLfON9~F zL-h;zFDqn&ZtL4N!J#+_9hZhB@|}@|%TE8s=^pARh{jLIN%e#@1KZBWj>Qzx8gVuT_!6{iv^p97Bw@VN^q&wC|2E4*Em|J#eW0i*fQy!^E zsb|+oVO~)@%EI`!vHlDEuOT@p~mjGt?X z0@S*)au+zK$ec+u=@f|Myk}b%=$opcy_(Wzc0mcC8z#r$J@J4mZ`N zz~g?Jf57bgD%<<<`k4chQ!2$TLd5JWd;sfh+=S;5j+Tpp6>pK(`@?_LzapPNsG9gg zQpo&EB?(#K=1~v!>J6u|5C^9L94mZYvr^tjcxm_DM+8w>ffR`FGu8+-UmjsvljT$x ztkjE7)Su5QjC&~PGUX+U{fqf6?#jEJ$jgY9v#@)#CXcc>uUWm^D5Ge8&S}5+bz3N`@yIz{f@}G9HGuaI0s9 zs;q@AV5H#4hH$94SkM3~Sy@&P_=MZPH&%?As&tzigc0iIMr1m1e$|MC_r&#M zq;^?jA9#@sQcJbQIC`EK2Bajw3!w%92_1dWAY-pNX{E41y_vbh^CI1!=qPQV>*|$o zJ<@iE#}Ge&Vm&KqxRH~C7v0R0d?`j59u3>ZIYiNJ?uV5 zB9n!;-4M2;5B;gnGUSEONH*evH|3-k^&kuGZwf_JAch80E?4;?ol==8&F0Hf_thR| zZKoEiJ=Izz>*2(T-CoN!o2JU>$QMo6ejQIx$Wf$!Z(girDA8@HcC9qfou>CeQdP|S zdrB(BvxG)9(h$cCwz7=8DM_OpCEGr@FA}hMm65szk#^3sO3QTlp6PL&=}DL6EtBON z$W)~T7bdjw`!3hrnDttm803j>X$&TuNPU@euQMegz%QGmP}8X?C2BYugpdHC zH)Edii;G!`iv28>RRv2ahb5t+MH$ybZO^2FI4JSU)BOUGpax>JbGChiHN++d{5BS} zY$DfBWHFAPr~I0xL6q#Swth?nR~AQNfqcdkqQj4vkO1yuDwb{_3q}6o6;KP2e3=Ra zDdXWG@T6{4ENX{?jxb1WRDPofbeF%gN{rgzdlgRRd6lX!tQVS(U0Sv4rj8m@zRzSSg?WSWjJXca6eA%;)qPeA12&!}Qd=LQdiM8~($=&m) zlx>SRep-VMmw!LVdkvSZyAI@pmpNEVPX(4)tN^FzRD5q9gvg2*+TyXuQoqP8i_R~lXr+{40Ql@zSFio`g0$_=F{ z902sBUW%nul6{~62M{3P1ZaR!7?3~(V1Dujgsj3#scNqT;$*3%Sm9@u6qVVE2RS9$ zh^nVHV0$)Da7ra2N|-K|synypGPT+c4j?hEF3N?ojaO1m0NKzLo!&q^AgF&X9&}DH zCkr3|RKp5u0(WbT)oLl(s(%sG-Jihg%9YxoFW8NvV!J^B`Qd|swIRiI{(V)!C%z8E zwU#}APr3;Dc-xfB`UfWs*R~CmVE|%Qhj?#0{FLgQkM+`Fc+1}_@KhSEZ^Z~eXgvQ3 zp!`D9i8-wIib{iC(h3O>f>&|7`mTFpbWIBB;6M|*8a$O6t}vkZ4JzdYn5(GeqNfE^ z50=M)0#d;CuffrX@^sF;nnpg~!eIXhmCw2N%ws828ss9fg(hV+w}z#xdjwTR?wm^; ztGIXM4_i|=iJV+pP5a))Ewm>6ZpH4IFVcTVfA}FYn93vgL+(STmX9AKB8oqsD-_6m zl$ucT;*EI`L0sahp;qsy@=1c}ls`~FgKE6u7q3W~p2R~hXe6D<2LY;>1)uwhV0Jq<*!cXbqFD%FuYvb-|B4+E7J^@C! z(5a?S*Rp~^DA+Fgqi<|J31cbJLfP zLDN@D<@>UhE4Sk}yuS{wrc>!4C>)^ls>lgqGH6G{j?}>somL!_FTC*6y4@}SpN{YZ zz62xgVM#gJJO*76%ir-sPv2^%tLI7(>!Z2rP5MsRnb~d|faKkv=U8u6LHO@$#BTvA z7yV*B;D9*-82ks}Aov8}1hd3_+)(e9UMZ5WffY^AAdH7;3W0Pe!UqjN>TWnDq(qzk zdHFsy`{+XufEdLZ+DAU@t);eOo&PVc;epp^Mq!cc7z<#C48=-%-ZQ2yCLy86zDwVJ z=><%jA0<_V5v~$N;b6nsV>aPQjYt6b@`&jPa4eWI^Aj*@pIk+^$>|Syf8JL$G0Gbx znJt*nd0DHLH(1g%R4jXf2tO%>SqKB| z_%KgljTb*Xw;(MqYrhoRpsXnIFc!93KOS0C@Kv9EnXle1^=@bg~HiRWuNTjKm+LZOL|j9vW& zA5$%V0M3U}f5@$S?MCOCD5+sRH^M&eU;_XfHX2QQ1Yw)u_yTmN;R-V09$wM$7y>#R^TrMD&~JHN(CCrxp{a`v<(!fx%B{TaexPh zDvo;%*NbbB60mhvMj_=DxrX&CU25?0`a{s>GcQ=1yvR~@z3Idv;mW3V*w%65DyQib z1XOmTy6na*!Y#M`E`{vmUVX;{LXF@#{(lxC(3qhrc{-3tN<9nmlPskEOztU#&$G+t;+Ku#7Z4Ld zCMD>p2S3g8W4V;nUNrnSicyf=`C$rCCCM>poQ`DT_~OKP1_eX8liz(kcm?V&0MA8{ zc4MLI%6HSm&*)YV}tiu17_3i(69xc18!bj|mWf`r=7J@fy@*dPV zE0h=)|Mz(``Gm6fb=F;}y$S^z38sHn{k_Rah4~vs_~&f1#YGJV$@|*H|C~put~}~~ zcA=kNQb`-V>2?jwZRToUfwLA`)vU*l3cYqI`-l0vj>Qjq*QEtejzhcA)d0u zs%3AsvJ5gNHCHM#*XpykWN`WoE##tl7A;fbrypMyBk*)-@`pl5OV0as{*D`+;2Gz* zFG)1B-5v`RVz--yo$Y~LTgNMMzf3=i_GN$dvE=FcH|BG5KJbj!xxG*3Cp`U4D42fz z=aUU}zlA^pzNqmqkf;UJk1SB!Fbq7?l&QS`_#MlmJ>Ma=$F$_;$ruS4Ug|iAFdPYl2ij};{QQ)6d_HxBH5Q-Ec^#m8GrgW_tjV{LZf@bck@3K> zVk7g>i=B-uR5agawmm_MZjRI2ip^ZNcYHrtJw6TRvH6ZTZ{-JUR%{i7T<$#63m{z| zWQ+B++J1xKwx(c-yGLx9Z@IK`_xe?|7s3|#sDiLG&thYc9ZzL`r@TZK%%hTsG~KPN z=I5+Xe${--zgG>RQ{Ag+-HdyP`*^v#SEtN&%3n_}DF)!3Asr`d7`wN(-!!f%aL_!> zuWQ&sQb=J=ck?J-=*jDQwve|!@iYjdHs%Mk*kdudhlW2o<7Zi7h8QTyFN^#tRfM7H z7H_XVg1c4m!EVPrkkLV>-beg9m>N@|fqE?#$G~mZ1=9LMwhP03FF#?AD?+wUz5T0$ zf;tI}>VIqZ8-1Zg#qL$nf`3jwOK(-5eNo6CJNv3kD0DuqPUC()A#<_hNk!)d6(^vTA;bMeuwjU~T z+}nwLlN7XOSMwxrrgl)cP1{j0ph={uZJlhNrLXr=DvTtGQ-)?~%zqxZnIz2(`f>L8 zWTY(d#ku8okU~{Wg<NOx+ahy=q5N|t5^Poh9`6uc9R4h zN4#W1Kx#D8K}mO2_~}H+!xhDiY-E&4BP(fzV;pMiIC{(^S#~+5uM0CS`EJi9>lS13 z9xaKFRs|DDn5XoYm#Rfy^FN`G#8U~L06jKKzkeElmn;}`XML;A4C-}~C}I`0E@Um% zHeYEAZzi>VV^*x$ubE81R~pCTwVXAAMBDlrC()%WG@r6!rva(v_{}=ux&GRPHVrA* zgc437b7(_{s7Uvuz+eJ(XlAG6#En zWA*E}FB5$}tar0o!(`=v8kNvYcn5AI*BQ6f8m;&&;gAcr3X^E}g7)1uUUJR0@9VUa zQyOWOP`*DPa*L>{x|Y#=-(U09Q$##tgqwzUPuWBJkY|1?iMYm6w8rm#F|@hxoFgva z(+iv88Sl4|f#o&HDrzZ-@vUMk8!d4GHJl&NyM6D*N1}ZP8B)h=c{@7fHMGsu(|1p^ zbkCM`P0CKm#+m0NM;9T&_>J=!`jRtNT;7&h^@AhMmdYU_M zK>U?x{V1XA@$c1pOhEJO6jx9D>Wq+gzT z5d!r29_F;Pw4a8Mt7feaSdQLrWJBzI`kri0H-;}eC{=%_m!!78jdl8Gs=zDW6*xZB zDj}@>*W!3cx{B!TQr_gNsbkUbAv@vzWrm1qh?9y45j^R|R3p2=j_$*o$?Px9Z>2u( z7-~f_kbYP*joWu-u83e~bn~rV(V9b-dQWhma;EiVCi#y%S6&sI7vp0l z2*EP&lMJ0NV?dsUD#ttfi<|FB6nCqO-6T$C6_A-rqK}I3Oyy_47esAD!&Ff_r0Cy2 znpZFH2e1Nt&v@~e;1Ec(L1hqje(|dIt7SVArQcSt(XW>kMF0L)+0&GN&Cx5*(uVK6 z+==K1+er89^@W9vzFwmE+WLu${3y{UZZ_jZ-4jKWSMr;6YxwQaq{8xq6Ou+wh!z&t zqn8*?c_jy4C(s)Nvr`W&~vk-OY(eBrBG$RDPOWZwrbXy>mu%)W0Lmjs6gS6XtJo4o$J-dH;=&wUtgL)V5 z{GIpsScf;nlQX4Al?lvY3VUASkzwgCFF)?|KwqGLFOHM5m>eoZuOgBegnnzx3;9La zaC)pLaZh|P(l@(j9;tIIcjL$=cNv(rb#S|Jvjlr}TR|=O@AUQUpKYVAo5fH!W-H5etdH9ev-7l68=S z9!+CRW01NfVm9gPl;WS)gO-Z$@qYiZ)(dEs>WeMoU5*iB4DcjWdCrG{zXygs^~U!_ zO2*O%@p^{U*}(2V(ixP_;x9Aq@o-C^??*2NePamay+~z;$fQ)(Dq}ERG4wgYhBJWr zX%E=XF3NBv(l{JX1H+q8CVm4T*2Y4wa8l3!I3Eua)msk^UarrB2&QpgR$dXI2&guI z7?1501Q_KA`4qCHKEOccqi6Vo5>cj~zKFo?pdssz7g05j)Dz^6U`03C{QB zGz%x*q-$aCSE**jqByA^S7ha?Roq z_~KxxLkwTFr9WYk>BRue-C!g02m276Uqgup-Q!t1 z10wV{9D1WnlHmFD$w_+aHpP^`(hZ6%5+3Ou7S-CI^9$l(SeRU1PjZ8b`rhD;KLKRC zb~{^68%7h~C})lWU)*j|-5{Yg^<pWu^Ywr^2_lk#yE}J4_hsr`5I*f$=%1H4d2kNkLlfVJI#Wt5HvW0rGRa{Q!DS_BB zJ%210F%pm#tGLSwT|kk|pmM8BeJy{{l6M2WbGV9WxYk*rt4JtWERVl`;0rB4l@!%i zK19ByjF?)s`)w-5u>k;@$VYLjYW?EsxXyn_L<1au{ZNJDr&N0O^IfyxS$ZG{vBhaDLcin~xOcQd!5UX!T6W4P ztbkU^+eee;tws2U%g{&lrJubqz!qKYpi-3+>SwZW`N}eB73yVW2Oxg&N7H-}Kj&o%;OZ$hjt#Kw(fvm3q=X-Nadjr2LgU=6_`r>a{ zST1?2m)57Mq=cUHoiy$d^v6HLO8>pUKk8BnGGzXD8^7}civ~bhQAV0f+fTzt?` z+H@^ReyMa&C4tc!6Cr!)wClw2yWf2%(#2Io4iw` z$95csvMxKN*^Vx&On9LcJ7o%ocz4|&()yp}<@}nP6&3GxcdP0@{Uk{y)j7lhdu`zrm6sO~d#28YG9U>zS^H zAGY6C9e&(@_aCt2hG^UD(SYl7)11YsBlCj8y(8lv)4z|p!NuR6_ds~6k9$egw3Y$m zLov>Rp!NCsCwr6v#!ufo0U31~FZ!Phak6N9HQ*|%_I4m?#M|!^FmgDlW*l@o`|srR z`I{JENPbT~`K!u*l9M)1&H1Fh)WP}xlbrn2>oGnTGmrcaE@ojGuSMtL!u>^>>|e_( zi*$y7&I=?Sm|1>UO{MvHuktGAJE?QTE&f@a0qL=U%o%Rc-{koo-)De#w@+*597g_f z?MsIE_*goL3$et|M@}P0;b%)ut4Ob3XUex@LLYH+aD((FWPba{h|>`9-v_P!a^H<# zkw_#DeIOM1bKL(*;)8x8P2HbU`4|68Km8O_D%k1$4r)K2|E|{IIco>Y--84t`~Fh> zJPzJm)w(tk!K+X+7hNxVzR!1R1lC(>2;wkaybwQsXZDu_2O!k$#-l$*L-cWY4P3}S z=N@6U4bgn8yxf;mV0Gr5SdY9}^2rLWmz2}m$Z^ZmgBE-TwmcIBX-Jx1Ju*sy-A0oc z(nmjkEST9=2=yOQ^Ua8O#XelPd^Qx+Qe6uHs5YAG?NEW*6SBRdf*L%=~TmfIi$8(n31Un-gz;F;8mu+tvFXwfAW zCnrsEu!{H%s?eWe{TmHsb}>T=0}&~S=8%1M=c-3G*wk#nRVf!y6)YHp$x%nJ$f+g- z>x-q^>c+5|IP)xoHFB5PZ)6DbjmoJsX10Q}B%j10o@}0G3977o!)({la39#1=HU)L zs*XYe*Ze`%+BCzq`Y3vhSc>6n`PHywm&$lNP_~vJ-96azM*BP>lgFCj69_642Lp>9 zLYfdRomUf)Eht*3?BRS%k?0$)VM7ZMIUke{F^$LlerP3LBhxrfNv`V%$EZyG8n-q` z4;;s_-=F?o#7~N4HV_=9uT?3-K#|O&Zo^=e?6<~|%>mopS|X3K$ZbPFxgL{0A)B!y z(;u93KIrnP#mG|2kYDKRdj8ZXRh=p(=eD~zE;R#XK!evu%gsVfG@9rOi8Adfz(4^@ zwtk&(Wv^-%>r!QKiAD20ZC4NXCBVoHUEe^4#<}MknIm0xyaP!N_l-TD({DO=GNl*B zA$%(Dg60%oQnhX<=$GzxwcbhHHbK9lfkg7v>Hku~D66N`{$^41q){$cj&kj+60;KQA!$Sv|LNBipeR8Bj+g-QLx=~b!doD` z6?EtT1+bzd(?03-4B;`!;_<<+Zj8J@IE|YK1@fwg|92I2FbW89jp+^$gU#2w*nF`E zq}{Z{MM_4jgqMgWM%QS&>h-TceeCb}FOF~lMrQnl*&g99Ctj8|3{2uNjBytY*x-^U z-)f7WOi}8A<(0$P;!7M2?->wMtKz{i4j_{r@AP8Ono#idsJ{*X_=z0|ja1g)RVJ3D z%0vTMyKg@e0OEnG`cxuw0|Xi>G3Fxo9Kr2Y>SDA**%RTwlYzi-9(pwZH4-iJ27mB3 zzvvUrd}i7o_+SfyGxa6-w&tzXR4Gw6P&~idDB@;XYzJ6L_z9r(aQ!neZFjn*!L#~o zYxY{|p&W4;C-sLLU*Bhr&=O!b@27E-fSkh0Bi#4C}GgkuSaKQC~OITFc_t29X! z!=5`iEU@RoS|!iY5`=tzeC!=8m~hYXX_6Ddb2(|-dd%}_^7qo!m-n5&J|DgO{rl%P zm;N5WOKOFyo{zmP?}MnHJp!p=I%51<%^z?*&!K#6!;Fka>aA1y!=gS#J8%pgn4aWF z1OldS|1b95GAio6|Nb2qI%b9jC5G;91RP4b8x$!ik?zo;8-|cnq#G$|P)fQ)B?JYe zQ@R8>U-Y_u_jRBD{rjyG56(Jk{h!R^nYHG@{_OqQ`_0m1ti=5mP1j^)!9;Y}g4lfj zO8$FoSF=lt8fp3yxkdfUj@SDsR4+yQ=Oo8I&C5!%2G;t7DL*4#G-xaLUEZn@q`-GK z#xNw&o@C_eOO=`=fcukXD5y2!VKfvPd%J=rXoBu2S-&W~wh832^|r*sAU;VzEiB_G z(-!?=lYm^d-(NE)Tii!?4OV!WOJ}2<1XW!)ON|6$H0(!8rg;CL=4GR&Y|)p!3nKP` z?=Ue0;W9j95Q50#;F4`GKCo`)ObL>qJwwjv7Cj;}9wk#+2$%X41nrDaMDO_0itu_> z>bnqfTM72V=j~{@&^t+ekESjw(bq2tbAB06ulrvYm8_9kkkacc`~LLM6rp5Mvjmwc z!ViVXe)wH}AX2032#$SvnwL{UyDLbjfFkJb3%oidl?oCt>|oz#rB=7FINDRpMm_8G zM(PqF0g0cW@8)Y^o^VQ>x26DLh2!HqqwY7HilAAPyEiWolu%EqVH+g2=(3s%MNcOH zqYP^czZVN>ogLHh8O1kehawA2nd#v0K2WAL?Uz zvlc;s*OIgrhAf<5)dg~_6_iC3tl#Nqp#9i@QR4!MCym6IfI-(?G~;Z^&-R`?=tP@8 zB_rU2H8%*?t>7BM16YeF2S0=uSom6AcZM6}lWduLS^HQTD^VU!!SP|XI1AyZb)ipn zz-vK@ABQK)2!>}4Ds75(^5J>L2D`K+w(es@hmpSxht)UHQktW&ySR>PLry^+r3_$E z1o@o>YMF5&8FNhM4%~5m3~(+)Rg7~L1zm+%J9OQ?<4b z`M5eETgdiw{8&x=E@i@j7;$|eXPS$|p%EFiKJiC3$u3ITZ3Nww5Am@8ii!wYCw9lg z+~gdGY_S@}G(lH?gv8Z$Cq{!VbYNapClHnrWi}FF%_Q!1VJ^Uvv|O>)v6b$laDi1O zUpwYw9HQZB=&2nC7zSw+KTN>NO}3x#CAaW;oC5h-Epc2A<5y;tREB-F;9p)yX7MFr z{YVQ73fH7kVO4sT)&$c$3*sPx{R7ix0^xvE{`(w)2iV>H&uUt`Om(34f5o(a=Mb3{ zhMMbgz6U(S%nol#KmJzJnF85e-si*<`HJ;hou2pGZ`3r`P&DO-75v8r4$_{Evx6^H zZ*mC2>&34_ja47K!D|~NJ|k6gDi{4|BEvuqk@*eFI*{v_R>oHEvi7!GbKP2e2Bt~O z&kP6AUY8PAo)HN)-7H;^R`QiG<@`7oryhIi5(P9i2tp{VQbfVm-gu)7&wYw6%-ZBbILzR-GB(edh>HnBR z7@KigrrNJ&Fa!nPK?~N zL5jg|H66Y1!q}~Bqc|s=W3!|n)xkj}64nz@T>M*2OJC0@0%{tsM7Uu!+6L_=hsX;1 z#j#!8L;iTXrk|yJyOf1zi%a9gDC{F0Md{hL(w?zzfBl@-))QOhK+YRAt;$KiT9n0H zzj>pk=LFDyv?Zw5(dSQ2_^-5Iocvs2`h~@{*MUI+J4-3tc8E^~V$%;3cS>66; z4)I$}7nlh`Ki)k>KOVctkvvuv?B_?mF?@GlVM@A=9yVp3_T;2vse^OOp+3MJz_k0g zy+>(A+g+Q`*<<-;ybQ0oLIu_+hppzZ2#e6)i;?h*Pb~#l=}Sv-YPg7x6Leq=U^WtL zNF1S^jf^HG7oMy0-J`wOD4CM*+pK6DrI`P|*qyWWX37ar(`#nQ-&)29n-MvuJbOXt z#@ubK3K}9tYki_WE)T~Q6a4lj44tozr)_zerH1=Ln@^CL4C9dt4_o83aA+KZJW3|A!@x@cK9mvD2Dc z;vj^?+T7EZm%&@U9_R0-ON~|*6wD(|>+fNas1cfNS^(u}cd@Fd(9W1-kTu$&99^{a z_DUHjuutC$WD+r4K30Z|{XNNRHSvodA^v4Q-e(S%;BcDNk(A8_Wy(l*C{H>=SgUQK zmVXg#q*%AGgL*ZSuLs8&cs(4?lCZ2q#5urf+26~!KhD6ajV|tKH_nVjU6{;KJSej$ zhpK!*86rS6Wbzj3)liVkkexUrWnl?Q+Fr@y+7MulI*-*m0n21sQ#-) z*{(q$F{+N`MWh&rNaelN7XsF9f|*3~=))H=z`pN?0gYD=lIRsJZSG_p5!#Q|sjjAD zGyjOXX8!f0Kl_q^ZCdXGJ~$#EIIJw|!81ihroad||NtaS$-9G?wY0ov>U zNh2q5eRC>T#hLF{vSaXVTfROf3f41)lR|tji!}&4u|$wlSsk_2k?IweVYh-|TqiYy ze&u>Rcr$}06`83c6*i(nGoyYdb=*B%b_zg1pKkt!c!S-+-3q-gJ`Buc7yU2`4;^;x z!`z^Uw(j5^lZCf;(#VyB&{cE!f~FM28xnG#L-FS%ErC49jb6qv4F7(Zk_8$DB?t}1 zN6`RTetE{}6z|vp+cog!F?MrQVG{a7Vx0pnCZkIzC+TrljA@a+a!gC3yErSr)7?1t@3gwSl8cYE3|aLQc1a(@xx zKBSxvawe$h+5kuc8T`qSswyYi;7TNX1IOcUrEHB6mpLbAImWujsxpIPjy5s;U~_&6AijHOR-Cr?AvxBBRY2LGg;z@dWCUl1Rk!NBa>n(X)_ zC(ct7sRHL5XAUll2R#Jli?xpm2Z`lCL7Z=eJoz-~*35ma}Dl^P5WuL6!+|ht0%&=iCtUSfP1nNRvY0orBUZvU28BH{OO@C62;qqeLQR4U> z7mz*lOO#5SRlCQd7UQWca9^PKKHdI~a9{7tP$bg<00*jl`PiAQ8ULp zAJ7~Nsoz#9uJFzyJcmQ}DSDZe3~nVXyi=qm{V*=gkc(^M(M>zok9{p>QxpGi?mPJ_ zm%f>ipaAn14~ZAnu_?M-A+C{fax5(TVsK}eiK#X1GN1469-eIn^c#wB7lq~8LGT%c zYnwyZ*$A~YC&=I<=r+gAFozx@13n`$8?^{~U9g7DaX-SKI|!^a5ac8Wx(9-07OPzC z!LeA$^4%d5r!e^%GL|Cxoju%CbKH$S!jldH+Xcu83VP8&;0Xdgp++#=sy@P<9Ly?n z=-D`dQ3uqv7&;2WPR$A4e><71DLTy3B^11X^FkH$r{9PDy4g}rR zLS7*JR{>jg4}X6lbO#2V=^$J~VI{$!dnl|#6eR4riEz)Hz?CmD+y^r1g71pJy)+MW z?xP&X7Fiv4dsRagVGG&L0lpvpDAI2k88DKAc{xrnxShGEzl)zG;d4IkF%21|eJ#b?wXe80+)uJZZzBQaCQ zp&RBA+-GqoeE6>B_!%AX+v&JfE|5ztY}9njDhjI;2Vx6~oHK{aA)(vmzWWP==NQoM z9kCbY1V$*lwGP4=WL#{g$G)~Zk!uKMGIYxvx;u{a)FNEUpATuC{wK?u*Ey7Gt%mxbDVieJC z1dW|WZNQ@%VT3AYu^+XdiwG@vJT_!SRjb9fUbeEzG6du zu|4gH^j$^8*HuT{iDM6Mfa6{*K=R;_Tgu72Obiz;Y4{=3!)#2Gkt8{|Bq5Dfk7b}M zd=Snv*`Ou=s6?{h2FM{2I@t)P%cJM451Y(LSzgEp@b=z2HzIQ&Hr;0k_JZWCG2VUj zQa#oG1-5Q!F=Pb^p<}qS>E*xDlcz%O6O;n2%6(N!pD&Nb6sj1NGPy-@UhAxmw(y1>zpLBQ|N zQsqzmXnRzCI2EBtcjwK#>&i`*T#k6Ok?&kf^YI z^Fh~V`zo-n<>cN%4Q0KY%ZSne;sUub7wx7EQD@9!e%J=|#FECC;zw;*ibh2mmtrDB1> z8v9Y);#dILh^I)9TnRQh)RZuGW!vxNJy z3r+p)_e-7vFO;iN*dS;e{i>Gg-csyQ_aRpDn-RLDpJSr4c+A|b`;wK%&DhU$H5yE_ zxGbl6Y!y#t`1IpM284_R4?4b9z8oiDsbe?=sS_*+OL5L$S1w4+e$p}bm>_^-OER6t zSc|9WN2pJtv#*>kr!4gh3Pu}dSAP);%x^B95*sF2e#Ppbxl}0l#e1{jI@E8gx{v4Q zb}qSkYr88H<78(OPwd-t+i$<0!ufI^@o*^yVZ(UyLSdC0+vRyl(Vnht<$2ZgwL<_Y zHXHI-b9FJz`Pcb+ah3F%4Rguc=pLhM>8RaS1wYf%v4oF;n;m40Uzb19`7FywHGwpL z`~4LC9o+WYaJWMb2J3pV+cJcC#f}zJv|pxKY=?^GKG{!MyTV^1MbzVwn7I0dooGr< zVKKNl#_MR^n|6_|_u26V9U^H9NekIlr$-I0J;Y>bRr&&t|9YWlybskNh!&Igjzhnv zt-g<1Bx~$fNVU^c(c8+S9MJFK&)ko-YfBR|C#n}(?T@B4etCOMsc&MAH`a4ohxo8x zG2Ol3Z zX2FRr^)DEqRHc0qNBe!KN^{T(?0fIt2bJ_?P0qb)>jVfK#es69$)^UrS0e5-_tVyJ zqf}zIZmyxg!+6d^Wz(KMpcbspMt9|w&OcJCu8W10%zs#j-@d_oF24W7)g*I7=sZ>U ze!k}S?eCpVxcNG4jI>8W%3N(V*9w-GOVlmaM0fRTUsCMp#6Hp^5^}vT6KQGi8YnXjhSMIQB82Lbv=c<4aWE4y23gfF`n2A@xhny3t;8Icx^ zTQJH@M}1@&&`gw~Ayy|M?#y`|DIh@>DfL}jCm&t8V9A3cxy+t8&JUwRhnrBPZtyeV z+c)LrQrYr!ULUImODb%_62;9fV&jWE?`>9V-fp~@Y%v)1ljBwr-Pwd&#_GfERvte~ zVVb7h$^HF8p%|L(l{l$E#Z{<2wIg*=@sc@fuCVzKuAgu#Pd!Wh1APip$#^E4<|l#5 zsIwfC%8D+|a>_7wlP%Im*D28?2J7go>wa&ml@RFp!7^A_AaGDDm{w06j*Hb1r0t1- zQ{q_Q+!Mb4CAA-8q<;5RQu){2+DI_%-foCA{2P%}V;i7K%r70A5*dCs-~|Yd?2(A#)#JO&**xias~rl8c7mgLzcA4;D!6JOKmOH-u1bj%;E3PaOD-1Ne908MFV2;@CT*#Obfsb@t;kE6> z0i)F_^W~sz(OO&!sxAaUhTEtDeXO`Vc!;DAD>Cvf`)UV>u$|A<)@5&Bj7Ms`$)gxq zzjx>211kPaK_44Nk@^>I^J)@~akhTdMoh8(TS6L@4!XZGh5Iz|xu_>YCa3yjYjnVRl=Xy*(x#t@YZyS3c1I-$grx6TFz;FOW26xKab*|ouMzl*$Iq@6gPro zrYb&_P{#1j4OxGF4qrKp$va+gKA_W2Fk@9RR?$DoC!Kw1#+(Pup6VonqRr=7f+_pl zm-%BtjD8&xEtVp1MhSxW@*xeNSCem5s?^_i(++q>hz_Gcg7~g&Y{y4iEuSSiBC>54 zd}OcN&xoSLrsb()?^1l{kxg*1Lj#W0rLHf&L#a)7{Q|=j5X}goAfN8_&Q4kpX2z{k z9`alohU?ph_O7O}vyiTP(6w)39KPQE3j6)P{XJW6zD}RBary!|*D+C$PyysDRO5X7Zqcc=Qm%@LYd8k2b_95l zV-+iaia*MOC4^*APRodRPE?F&(bs|GFH`$BB61@c@Ba^y(Sz;BoVYK^|6R$L$^TF~ zY%3BkCBoIRz4$oguk8^d(_UR1XERy9quRd^5s736`7~axFMwqH%hU$o`jHE#1<644 zs!EUVPRQo=ND@x7wy9ZUKHIavJHt)2D?{l)I#hNePgcirbX1L5rQwOgNs4+usjIvCp<2)O$eI$ROrL}q z1a1^qp@JcK6uH4N@2wJoD9d_DWpC$AS!mJO{C9}Rq+PyR`CJKrh}=lVW+iu|c4lK?aQ=9V(T`yp21CsFuu3znmVEka< zKPfW#dwaxdYp1bv2k&o0q;`2gq^9Vh3Sf9=@s4r`#ieQM81Q$9%{$hQ1{l~13u>+e zbPrk$27*UGjy}|0K1+nKde`~bD=%ZGd0=~F_SbcHW25`^%blsY9-&3;t z&X!P$Jb%OWwy)1uUwCUYbMX3Sm-l5yIRU12@#_n~)Q)!*r@gC?y=7pf{&Qzza-#5S z)9Eh2!~B+vA>m^mu!+nr4~A_+A=AyrI&O!dWx?FX5gG|sIfs1hS7r%MudBDe-=^?5 zw@>0liO1(xt?H^#g=w7aR#7pOAFoxtQ{LTq#_G*Gk$r6~P>%*6B5rO3=(lwwIEd_m zlyZqBeXu+6zAFck19#>MCt|vvz(m&=2L)SBWO&{)Ix$m|h!7-qk+*0uANl7JWYxKBca!vy)R)L^2p~L5n;p;au4C#jNgV9qxUR&(nv=bl~Nd@ z2kBqO!<`v9QQ@Lz`R~)IHEH$raE+FAq6NMz`#4n?-da-XlK@QZpE^B)dyz~pAAGo% z+uy5jCWeywRbr9xu@C&@d7OAJe+>V{(u#&_5*x9O#NnO_xbh&5)r^?mB~%r5*FH_y z=6xbo5EHw?(fddxx98Qdg z4(98qlfi;V#UFsHPWE!?_9SQ;G%h0(gy>HGEUzgA&mY;vmCphjS&L0kRhx}sG0cR`4Bf$NCti!ThkZT578!{ zwBmd|Ds+Za#I0hG(Zc|U4t}mp&nedn-gHH( z=nx~1E9}(EO{Q9kC=J|E?&lqbGcAeAQ6aC(_B)JABuHycNHE#=>~T{4o;QE@WJFLR zA42^zFewo=vBJ0(rItZxY9h5U^dK}x56M}Jle)Z_ZJP~Q10U`ap0v*-xWjl~A|xB? zZwqrd+Qz72T*HwKM%oDUdoi=^Z3c{uJ3Csy>@O**r=jb3;5HT& zy2LS17-nAUsGkv{{v--hVY>6R7+WD3&cg>UP~C4%-;3GA;cC2C%Gqn`Yn1Pdk9&hA z`Bv}!2DdVHl8SaR>G?a&dvkFSD`=D9p;c9Rm?&;Pv{bGPL+`J(uUjZrQ!2@;sMz{L z-^Y^7kZ)gi^XEBx4Euc{3d|W|4HkS?6wM&b>qWa~bl4-Uwc@csrr`E^FG_5|Ms{(g z*6~-A@ok!oY)A8M_X+pHMEe!>S?!P64FggOM4LKGSnrB7>dS=5f|#_Rd47H&1YGXx z`fKv&)a#(6&O*DDZ4>tK5fvBVE>rJL6Af*aA#^MO$46hg+muY0uyi~oEJe!)Ebu#& zvB$T~XZ@HVlnC@}eOp`OS&pT*gjhv8Li@aKhKn)LVIz|&}N^+_;L7@c^| z3!yIYSLLogOAAIE@zTRJE_#dwi(ptp=ew`$2SJ(TxDEK{%WVdZtl@U)FC!%O(aG~> zz=-ypA|FMkvlMp4;T6T`o;wN*cF!3LR$=zoqIQ;1XnY~W;DreEO4ApKnmvo`&03*O zjtMDKr!=0(DDp|{qzkrwN)hLND(M4+6RMkfQ9V5K71>e(TuP5(t)I#!H|HfQ##+UG zQ*=vnMb1bTTsOjB-jX2RqyNG1)Yds@m=n@?CzK#@yj4n7Jt2IOkv2Z61wkI=adp(4 z6iyfUL6xvIL-zrr2OUDJ_M4iWbLgiA7>*c*TYJ!byN-Q{i0{cgu3@2O%=XXv#oI#Q z{smTP2J?8G`Coh@)7@Cq=y{dnH7{1Dm~s#L+jWnqVgITZ-axXt|F0q0x>aRAk=v8y zw%XZk0q1UbG%9ayAlc+wQr@m+3Wa~w3-!}vcvC<29hUtYBwO}Cb#ETwXWUxzC)PJ? zChUl4{9*L$^b(JD*ln=G{sM>dr0iZ+`+F3la{+_aE7JkMH2WrL^a&(niDkW_mbtV( zSg1QS=d1tlt^cmx&qtdAHQTdI(CpEX*2W)z0=ipZ!1LjDE1Jn7@s|LxUH$$(lZ^L-AWxlMoCR0%US{L`-TuQSEL_PJskdFHv!Tavr^)(0! zhr|m^M41|diSBtT_#=J)f*MqsZ6TD@z-}>&(xzlFoZ4%BF#;a`4+UiD5MS|MknE(L zm43t=&Lo{gQoj{oni-SO%97h#tKOykO926?$#PxKk|4ajpyEzahN|V>p7k%Z_!! zZWPe(df{&cL^PsyzA}0802S(JKVs0D{)%+?Gw+8G-F1#hxns4hiuj9|f_H#v_Eri| zKuv2Jj^f;}jtB=@uz3SC0_6nTvTNw*mgbuRt>W4TKid1tq$+9}9N5r1NjZ%W>5U$l zpX*(nw4>F3)L2ayOg$S(f>OU-YURDYga>I}r!UPp7hPT0eg*!49uuyEoo_(**l96^ z%;nVz5sDU7K`_a0q7D|(D2#k>q9d)J2mmzY;|q~e!M;XJGu2v*v(Pau#)%bou`pMM z@sXwqYort1>fH-h5T|+nYf;>#Io|xFG~)1@c86EJB~3_TF-C zkGHlt=unBiVRc_V-HxCBbRqL^(sa}B0~xkfop&YJhkL_J#%!IK#;kxu0IwV2vlv&` z>1q^69Z6XANS-ZwOGqjpi3;ODQEsv%F+NnAY_~D|aio3XQMox;4QVv?YCPqf;+cL0l>WVg=Q>ezT#pLk-^sXfm}jk6rWz#30M)b(g4HJ+M)9V2$?~L3 zIEV4R`9zRV=}~JIqzKChDJFBq^AEKzlx%X<=H}8I} zyZq)t9xHxQzxS6zOZz*KQg3{($DsRluV}v%AhH)VkQ$LLU@hz?utAj&2_egzTg8Y2 z*LYuP4+)yKk_fkg50D)h`l`(mB}J8qq|BoNHg)@ifYOQ7mZL(xIQ9pSPVJ0dY&CH8 zbM@8`9QikP#run3t)&n=y-1sqwWRmNZE*Z!nbGuc0U10jzRzeKA=E4K4$jhW7{ty~ zf(SJzfzR?rB@kKu5Kuskjl=aVWX3E$<@dibe@M^$%pq0XasRpdRQrX#fmyxEgKLS@ zXh&4F`YkTYm^{OkH~N*X4=Su#Re@Na+(3hDLn8CDe2shun5l_N>5SQAz{8xL2^3@` z0wbGDZ3w7}t8{c`3PQU+dM?X`7^Kj)1%X}q0ZbHI)z+Vw0G1}07&!H0rgly$2vOe` zx9ghA`E}E&9D7oj9PH;$gh7Bnn<0zw=I#0#6uJ?ZZ_sACYvf}K?qt{!lFhK7x7y@<8?+= zLjR_F$CuTSifZ49v(9?hG-{%?KjA$2{2rU|K{f4V&d27IPFMQf(Xs7XtG*R%gcgnJ zueOw>maBA*&`lSOZ@2lN>F?u7{8YjtEQ30}eJqW86q95~FkdHzg)dDq44y@Jv8h=1)t`ha*s_brzp_iQ|2_7u$oEzvQqM8U~lR9q0IM#c!~&pe== zNj#k8F*v=9ox=0GC|AV9M+xj)j*<1CM+S(%w|4rxN7Ep6V}vTB3eFd5a@L3a7*tK; zrHxVckePVM>hu$&M=*?a{6^CqE6TnjUZ=XvEA1sQI0v}HtG>}85Z|8lm098Dg#Pj($;lrQ7as+LJHbA%;Hi?~&BtJ_LQsP4g0y&)J=jjcxSA z3R1gGKL?LsSBJ7J zP}L)ehiRT%Vsu~E0C?3&|KAeK8^%%*-R{3@EdBS4rRx8{SO)(G#?s+mjOCxk(o16^ z#+HElegBnU-q=x2V}GHQk6O@7ckpP{nyO8l!L_%{sGol|>qRjt76^=+d`ZdMRsI%B z1gY5sd>6kdqWqsxw+g^v`=QmI!+H_VaJhd-gT@}4Ja z<;9I|=Ei~JzL;>CO_Ur=JZ(cUAqb%zijuleup@f5d{k@@v{@pTiNG{qvyh=NStk)+ zuF(Ay!R8cBD$7|UhKP~rT>l;`G-(GUn5%!=QU6LX#p-VoOc7rqHjTd+%SZBY_y3t- zDn-SflhN6rN7(?3<-i1uQ!jh5lHc&Z8cX6NbfIVLY-+|QM(a6$i?Q{5e0o_JU4-m! z#!}@09biYXKc5WX*hFE*I&7BSdmROcu^YzHRrVSOXe>P)G_PzLwNB6%yK+seXnq=M z79W9eBgO`w>;18#qOcr_tHyVgpZsntmB%`6RhoaqSZAr8|IX&rypAre{8wWMn8J-+ zAAbA;6f$>XNBu*L#S#mZG1=^OF%-Hx=~YMOQ+3y8E0Hym+E(lXVr)2-UAIs_rjJQZ z$nnOGI{3E)b9-6%aC**_SHinutVimdPzW`6@77V5KJ^IyZFH(ipt1D$4y54#X)q+J z4NT!q-p7|TpF-#5)M`JJAQX8g%jO>6%8>nF+>B%IPVFq1NorKoV8vbF>w4<-jZq~z z$J1;3?2uyq0a3iz_jb+$&wE77KC7;}2@n3OY~qC=CY z8u>C>@e;P4`jMZ{rpq_SBbBvN`iUKAs~nym8BE%q+Z}X^IwjVcw2L?s*m_XQHEJLt z2tt679FED7<5o44y?nPtjy`&sM|L%=>_s3XBTugH%XY$V?MEu90gRGu$4J@t`KVr8`>4rFx{N}HhZ z+8g)Pzx5Nrz9*{oh{Y*>*Y3WXB=5XgO{dmxtAu-1nfS0Pf`Y!ZYIHv_DZS$5jDR?^ zf@DatX;%+u6K9Yiur|f3rjNPxfN(o^Liu`ciL=wP7j5`Ss>a0v=tA*%=;A@z4lyHN z1XZ^mSyFm`K|1a22?jbAUD^4CMZrMpc;7kKOtD**$bzU5r%^SscCj4Mpq@Hc^eEc1 zacuUH0gWticld$JqdQM}>U3YbXK&U-%m)}>$BPil$DPHZr1(UjW|+>PK7tZi!3H&_ zqL4s*{RG|y$`7~E^716U>&X^`eTerv%7+t{{!5INsu&LHFp1>pa92WTEmb~demN=< z8!62qE!EY)LnCNiFLe)ve@dRiF^2+6y7kF!qzylfE{Hs2-fv2)^FV8F?KsH zHzzDN>QkAll^rR!`HX`hW*+>8BQ(!RI2N}Aj~s%^VW-|>!$B-OZ`BFQawV)V#~xzC zr7V5oXT@ak)6cM*$BTy!-Y<|fHQ8r!QkyiKU_$GtC~zfW??QT9K6_VYRIwmEjs)!+qF#{HESOVo+F zTt37XA52stZ!0W5atBWQ?mT@|`%O6dTcqXJz0A|Lb@eL0siAKtEvN0<3Y-D%wIZQ9 z-fxA_xSpCGq~q^Sl~ocN_+G1;cP)R;y4BD506#VvbXZbLFsY19js7bC-dPvrs7rKP zV!!?^B0KiIj^O6d&%BmaaP08CRHdBnsnpYc6fV^oTjdt=?K1C#Pn4cux~cO%K)|2U z44BD{Tk1x2E3oV#V`r4R(5QV~{hwQ=xYiS&uTC?$wAZF)t;};5TX&rPtU=ssD`A=c z@mk@jo|IhxBYsNywf^n&>SIZmHScNpsMo0A2v^0L^c}o5vB54UX#+gu&~0FMc-{AN~N)T$6|l&r_I-q+apduCjKv z+7FjVRqDC>c1ldka^XsI?kNws*1f6ap&7Qp-@sz^LYh0Mr^SZOrZZXw%gMMwp_lab zNK`K-F+>A$M{11{CSWEFGS>^RQYpT02JMo(dKWrhz`t}m%?#zi=F<9rMGf(%)bW2Q z|N4K1ObP!l$kc;>B2$Jh{u45#@&}o6JKO|H9lR<|;JtGiKyX;J-;h$?05a8w;%BH- zR>+ZVNd(-VVXCqcG`k)GoY~*V6z}Gc_t=BY`en1B?8+n|ApZi!rFKrgfqL6Q@aZ(# z&P?YW6QO(*WH0yE#WV0&DUsNM$0uBCbC<0OcXJJVj&wNkKe|6|%gR7S+HRVG z<6jl&--1KO=LVVb`A8>?#cr+ULjWLCY-mw`@~^*39aN-@1~#RS3}Pu6VDzDm>^7)4 z!2L-8mfn@pZGV?KT8bkO@jdp%(QoFOiTwResGie-dsfMTeRsk5SCLPRuv`K;GSPC))8BY{(9niucjU>$Ja`7Nb98!s>C^`DBgfRIw`jdYh43d`tWYoLbiW(|`1hu+%^H{p>{e)=%88wJUR?)D(?RZpo z@>Ca6tEeey@sWxX`}h+truuQWkP(S%+vtP1aRSo1@17)JHubT0X82q;&1XjbRv9eG z+ae111$tjDOG6rqDkQJL-f9OueJbMqst%rNSd*3`qG5Oa)Zg7v{^}F?H6`Rk?F1$b z@ zbQ&(}w)W%tT8v$BN=GMt4h^VCJI0J=Cw8a+?vJbro$Vl6oDl-0gVi>R`Ex?LZrm!Q z+gM9nKJ9s)5kcsfwu*MNC1lm{eJE6(-nolHn(E6Qu)S}g%T&_+DiZ8A75NZ)T}PS# zfdGO-K59Q0;|-I9t1*8-9%-@C`zKLga;b95sL->-A$wq4%0ululd_ljb9JoUr*xu^ zJ_Qan`*Ed2%Zm4v_YV`0FVwmx`Pw(h z$R|Id=d4d$X(rdXEL5DAkC`~Xgx(P+nK84RS;S+#A5xrrKo?EEdWAoTzq2q%Z{!tjT+ZC|ekpQ-hNYEytBEapm{d zR18rS<7~kdTTdtQr{0P@DMk|xO}q5VmD{${2rWcqhCesL+s~~rHV!j1;E$e1G_Vim zkg`^cV`|(N_5&_UVK8Ba5DPp1UfArcb1#o{hdFbR0@tiBmiP{sNx88THw5L2Y z{iom%C~ONPd#oo3H#_}uD%Yp3^t7=KZJ`LLKs5buOyNWR!t)V9Lv(;n{LM498a11C zl)XH0g7Cj0;MEn%(ga@?ULZjjGzQ8bEOX?h7aRi(vi}Ar=R0}p*?Yct*ZY*_Na7(M zLA+iZbW)e4x>ySk+q$cDEgzCRR;*7}I+h4az%tn!0Zx zX;tL*(4%1obLT??jLhaO*lKq?HeVyCV0F0AHj*aeR0r!})o@`OXpsyX_s`z@w(V66~PCsVqzxlbj7Afuw7QCJY22R`}-C_4R9 z23=7iN~!_?T|&U=(mc3xg9&pX`zXl9o}{CqRMgJCO*t$1N(((`x&Gky$FiBZ*F|_JmHvce5_ix;wYT+9u z$peVy+_%iy|3q_819t*GtHpl8GSyMZq5^-|S^#57g6H8DLGCPf@h57pkkh8S*GD3| zt-is>pYSBt&d+8&x3RNhGTY29Uy%__+#S1{-(G2&``%1qgOb!dXqukVTx);&<9tXa ze;6usTAMN@4ECR+xtsl({tp~HzxQhZILR*Lzu=_5+@NMthI;^-bevS8gzvgE7^Jc$> z{6z6@I0eR%+c;}nLRI0Mm`AYg9IBC>H{6X;p!`|%KVULZHXQo3b7R7&y zvo}*usig1FF*WYAon{kB=ygxxZ@gVA9jtqQsvL0OGYS?u^rynR>d4cqG98(GW_$%) zQ+U~)uF3z1RAS;89ZPtAX4S6?mgjv>vpzm=y8OvcqYj9(m{Ox(g!-?SpI*vECoOzv z0o@u`pS_cVPEnF#_9-r?x|3Ern@AW(mYw!XO-^ccrxYQu{K>&ihodOQ1;KNq!DY%t zxunUaU}~D^&3=_LORwHg(xN|P)DypD-H34^O9uDN#=DjaO}K5t93h9Hvnx`IZtr6y ztsINHyKDj6bXVXhjLcJaDSq#%UlU_akWbl1$qN`bvC?kFqb8)$j`uO*z~WYM=&53X zAe8>hnI%P{U7j$*E-5P!19hSxwCZe(V;=M!j@zx!)bEn$)of{SWCxR$J&;k2jilop z7|`%LNLKJ;VpCM+o10{(;0!1S4 zEm15nH8ASca`+wnD>HBNd~e?7-%^$cpPN*Ptfccx|K`%DE?7@RmJT`tE{uc1JhYS4UeM ztwE9}9EF8a8SLubgSy);ImO24XgEj}z2GqBBI8bb?KBf|5VW%7g z!iXj3#8X0AYqnC1IrO}#pozY5gOaXOL>i=T+#om-t%M2@$%sf&Ht*oU_86ts;7)+Jg+$-&?-a42&X)`BW|;TN6P>4kjRs~m=e z*kQF`)cagZ1w5ecyjk(V{VZoY zxh1(^u@Vy4aShJeF))$(^oYV0KIC`H-9kI9Q%0X`%_kZCQi}vU6yT5&-!PF51nVUAjfQ*(tKbWoPFkmdlq$qxW zWL3*$4zI$Rlq&m~f5&n`jy&$T+Ka0JWaI&AcB(Hi{*FXr$}uu$Nv*CtaGWwwcmdR zBue}g{EgU>B!J~GXRULJYMD;KGK=2+u#1qvHS$f!Z4nDBW~>gVv(FmfGT{hrn#UXj z+^(LC)ozkMsw93vzplT#CniRE6)&-D9XA8o?+Ih*x7@g77ZSyj!&R>i|-QqV1KvYI| z`&FONqcWf%U-UbQbI0Nkzbj^U0@W=ip%vFX1;hfZ@`ZsncMN!CoCEaw(TZXtcOxSeC=BW;!{yTZ7 zMqas5!Y9GXZof_5RLIZmH$Nvm0Cwp0otl+50TZH3KX@+p#Lo!{_x%Rr17eX&Cvn0j zJeq4em=AcQj0dxxpB*;|D{6^<3Ry`$o;$_*q;V(1YSd^+)KuE#Eb02!kVxLPXvd<$sImSva{9R844_`zFkeBDqc%D2fm5p&qYmUH<* zx3;w<{tx!fE2;^8d((kXLLikQozQ#l)r8)q3xY_Mj?$E-Um`WsPz4mEccphwdha5j z0@9m+Ac9z#=sD*0BC30H5k?K`>ZSxJcSPG?pEES|}^)!r^l-GW$K9aibw3K`rW3vr%Oyc5X(?h@qIU zpRhA97Yz@yFwf&?=T}n=ywt;~aOeJbYO+R=4}C}TC7r~`y&t`0gxlO;J+jyhR1q+R zZIu_Yy^Bz{|DVoP>|6CjcIfZ9s-1PcP&5&iMd47Db&nDe>z-n?(HE0DNJ(D~PrNq8 z8_yezVfYwtCjoJNL`TzI0mM=&b}P=UgriZc<@K> zI`!R5kjxm~36G`JMcELJs~S@Gy48s-=yl#Gp)&I4-z>)7&9CT^0=tEyOt5qkm!*>c zid6z6?om=&`#BHeg{T|j53#rP1Fd1C7>}qiyEU1tB&M6zoy~iUraV21SL>|H z01TC>P#jU4#4!w$0l^$EgYMcei#XO#mu1jT-c4MsSc8UL^r4`2f7zj;a>TpJco^K% zLG_}bG(fO#Lt!cR+1r7^c?WihF{t1dIxuX2G(5x2 z3^A6;^(45gMLl4hO9aX7)O|~vhI6`?u>W7oBfr}Rs5fTOZG>q`5DV98Ez}P zZGpG-o;)v|3PD`A>=+KXA&i2nL`0H3rO)_{9wgDc_K`L6Mq@suwhhS)ZIMYA!HIm+ zg+$OtfD;{Hof^(b>$0kz+gw_tNT>FmVi?GAA>C?bP;kzq$#$W@7R^&@qlLJEs%Lnu z68u#0ooC3b{u;Jm;L9M)54AY_`$}VxkeE)uh0*B!% zQ^TOv0`6P2oA;jetAQ!cX&5MI$U0A!CR(4T?j0oszB{o&`y!5gagAZil89goodY0R zxpNiCfVLj5g5#Y_Nng#!l1pG8J^Whgfre(#_@Xn}j&Fn5E){!`3MUjZ+1wo4vAc;* z#sLZaKP5L%IwiKW0k|)$YiL;LooS&jg)BGC9y6kcGd{CL!XKb=j>l(h#$?k)LU{Zb z(XvvK0H3?ul0g#D^D&NiLzU=Cz!RmwMaR6VhGHAvuevIBqF+gP=*NMchP3=M|ngsxfJE;UB^>o#jo4j-YwGQBSJRMqD^USzJ~W+E1vqWPP#CFxWnji zRVe+qP2KtmRjK>4PeAjI#CtF30vDZKCs6@plGLOZ;-9YYe3z$FZ3u*0V)KKPjP3^_ zhnbch!{k_rszX}EY)f!O$-t|Gx_ryM{fB%FiUW>7yxMA?4RmwzRj?s3- zJFQ|uko0tI>#xSxh{ysJ-p1aZtL0u74pwOPA=p+B_d$2Q9DYE00XftzWdCXnZsl1g zpda*R(~1jseK*EjqU=Z1B-+nD0dFT?(qGND!vw4j{f?kCW&81EcJDc>wbe7fnscg3 zZXE)v>+zRkN}@~cE${;lHli~b?s-_2q?AY1_~8)Sw}{_jxGqdEOQS_2-<{69CkzZo^KZ14XlUSr~YRB}DsThaOPpNyK`{RCo0jbjh@ zpEb~+AisV%Txus*Op&Q5FZhqv0Q)zi295+_!jEnK656|W9;gs+bQ(7__DW@bPy2 z=%0*Qt`zBEV~|n6v#chwj`gN@_k=fiR-*rNqx(=0A=VyI{a+cifA?b(DImtuPp`O2 z`h18KPynpE@}90`Gw5H0ww?2hCS7ky%~tz=t%3d!+W)!HsS{mlqlmA){{7!se@Yn= zU25oR=}TL!NjTA^HmO1>+SsrmAe?-=DO~!m#<;QTo2rj^EonuV*tA(6aY?ij8}B$z zepo`*#Ti6aLHBo z)}@@-SkyKp|C3RZv`PGvQ9JtfuL79=exsY5)mSzRY+x@DB>ly&T>1V>)tAGH!Pjzs zGHNQrUnR!R?WACzDi3|xYJSG_^#A@j8*=T|!m0p?t>pT=jt4YU@cGh%sHJ40)}Ws^ z`SXCOiQc`^*CAe53iQDms(%co=gEdK2zaK^E z$DCT27sCF|GR0g*JFQw!J;c;qo-_$btc<>tPD-cC&4U!(n(&B_9J1M~tBj*H?tTDQ zVOIj50`|hR+Mvz^(!M7D`mO%5la z(`;^YE%9^838uE{9O*(zwJ(l(-l3;1-K?=hxuOwWn@HNSNLkPUiM(|tcLMoIp;C`C zEP8_5s*zS#Y-i;18un~9dk=8yYSl(OKh#1CtKc5bl|gV8{89iX6f#bf zYs-%kp`bZzqRE_2N<>V`UqYKWW!>Oas}D?32lR>Ae`n#Go|7Z(sxXddc%4TqfXSi3 z5Z6F+S|JWXYa*3qU0S1mp`d?>*V1I0Dw%KqN<-|MNXEu0oMewlPcI2lCJG26CjoUj zSyd{~R{y!to$!#bJxKI<_|)sVuETu$z9kX=(G|xHy?MoaPShG4z(TORMEs{tm5Bea z{|o;iY~fv1k=7_8{*x8;FZ@SAu0i52{quIBu=x-D<96#~2Kyxu|7koM{R+yqeNV)H zBF3r$k2dt+F%{9NxuA@jFFU27-l!S7?8mUeG^ZC{*taj#`;`6%>jM`M>zu-|MG ziOAhf`4Hhyo8GL`7hlVAgDitS7~Fc5f0oUR{%HL%EbXGVy!Ph=5&v;ww<7T`8 z{)Wc1qanUegNXmc*5P|dmRj$4iaHT2n~*1^tvt6>>r=zFR(PMeyxa||L-YMCV=tPj zmSwk4)g6Bcp$QIVkF85vKj1~vsSdpM zt;(|mB~Nw9^!n+D{>|%Cyrx*|h3^uW>$istDy92d6L$6E@uL#!4JFE{fUEp+lU}`O zNKihoc^A-9rbr4IT1&L55iEO>B%3x}M|Vt`#2=L+t2=C}d-F%TaN-v#mFLt+b{xe6 zVv0a%vU+dZ*odbc2b5v&ROnykaxY5y#Z>9!n;%1yqFaXM zvF{CIAAY}4f+kZqTuj0N-GJae{okJ#%RBhl zzm6~(`4R#zYFdnb8~mH@0Rn&kk^fV={r}TF|DW#pzeV@F1aw&J1Ll9G8Fz!8&BqH- z$#>57Ky^g?j5m$`rELA*(LMfmg(9W8YlLrkYmcL*4nDQ?Odm-0ZT&t?tXC(m@=;N` z(pBB{Aw8mc26}C{abQ$cG{^vbEms0Ek7lh2u;P%3=&!b3?g!|-KE1Q>Ol->+p~g6P`*C|f&PPepzq@3mYVk+$l(@*W}rjHOknJHL29Ot=40 zwpOzEWsa!sJY6pKhhza3YhbY zP>T81TYCpZM0)T$>H*wZk1qTQ6?^koB$Rq-y9s2R|&iW{>6!N{+(_gwZf-Q3xs=Dh0Ss=wC{VDewK-ReBk*P=?Nz% zB0cohfRln+^M4~fsLcODdQ{GW{}-gkK2GhwkRDVwTz9k~`ByTP3Cnxw%arEk)-EE_ zL$D&Rrn1z>S_2thDBLG|i`<)_~ zZ~TzfI}EwZq`s;y57!m)N`?KyuE381^hB8>u_TP>Ha1YtLwONVQo_HoUDrDqC>U4! zMCNI5l8*r7{fi>bi~z7NO|}S4J~>;SWHQ7#5*N70!#E9aN9C|mwA8UJ(BQjp0)+`B>rFzIeY+q}@Tbo!`brxQLj(2o zzEreCtwNs zamqxbN3w1xI~9;}t9{t+l8E%EtNF_=bZkkyf^q6FEb;x5vfssqkzO+0{EwP4_q!Cw)FY>t*(|k3`IaG!6?q3rCT^xx zZZ-Fcb&~Uq9y^d1CNj357{P3g3uOiPfZtX{N&e9KyPRCspmSI*kLwcuM#i&LOL8uu8|F~ycw}sXTZI3 zYrYj*x~3X%pCeU6wCmMBPmcu7XcgfT_Y##sYuwWe!=OckpQ!AHrh41i{gDTtUP(Z( zZ6NJ?z?PpTREffe_8EGW&1H%8R_m#eCOB0Css{e;wvi~%)?ghcoZD;?MV*+LWp{nA zXazGuPc|73oZxz=C&LwKoCst+O;T&60ZchzqJo#zw*_`JrM_aN2LO7L{?{I&R*Dg} zyR9Px`L~fS@C>-30`{sMn2$dROYxl`t3#!Q!W40G!}EYPuQSncP>D@#J?MR;1HMiX zAZBMAT4)mPe^#zu6YiWSbNvBxM#QRwMbe{gV#+*P?jNw{$LC-pPr_rNyMF@qB2;Gy`nCuU(f4>Nt$8w|bZ6pxSjO%;#T0^eM*Q}Cj5Shpgc zl^!&2a;xX0(nG_^wrIBid#o-{vpy*NE~a|V>n5hNK9Eo8!(@L|JMddk@-SHG;A z)2eQKrOlWv^sjUMGfmO6W%=lh$g76JmxE$@vQ>0vR|4$Vq|7C$Hw~pHd8Fk`w^&c3 zwBw^D2+Tv?5V}14#&ffgX!`lLVZd=E!Zr=wKlwft`H`vJmJ6$8?5#PsY1Mib{cDLH z@Jd8IaH3~3sQi*Fdk3ANacw!k;OxSrHJM*&>>q>u>C;KBL|Rox=17`slycOyqfhFxq{%IU|Jb{O*8 z#Brn~BiA}*xDTH1T$`$h0k+)k$%u@SqBPCN3_H??)95J!3=6=|kjb-z+fjmkoX(oT z@^L-K(JkwiJ9iaQ1{dLezTY`vmoa~KIDdj&TpD@K@>7cwLWWDvkQ&=^f}@*wtEYtw zEyDw1e@cA+pgg*RQh(HxB6wkn)i|rh!o)j)QLJmbgG!TrNkNSpY^E<-^+Bl0>cF28#Og@Kt7>6beMKrc5?Lrv3Paq* z8fr+hR4OIg(Ag{?XSVUSTw(>KD%w1|nP*t^i5^@n@bu}52uP{J1|IO@HR|JB9~%Sm zn(I96(_OMMj?ehZsepZ2Sg^ZW{yNoE&}U38g_eL4OrH=e6^IJI>n6_uo{3`CEDX&r zS7(;g(xK@_B;F;{Wx>o6;=UAfiwf#ryJ42`qOpYMricE`II{>{XFvozR)=!hEW1~x zR6NSVBudF5XS5MD!r09fJZg#qWRy_6-P3{9n^i(JE6EfqF~21U7{)@>Rasr@p6{h=ZV-hrhgRsks(=kj1ss1p<1I zlQ$%+g*6fns$G8EAdKkCAw-+1U8oA*YB)3()E&_o}$;AQ_k?=k9BOFXPW zneglLpJLum53dxewS%{^NhJ^M;TS>c2N zNza-~`603D-N$u~ZkCK8_RZeB>>U8}M@O7yFiPe{U6Sy;g*^=!;&8%1i9Gf7RKC-o zvfOYY)00g;j>r+xy$H1SnuWl%fzcT~e(|`2P26}I0(DfM1zW!fhzS`t?WspY!Q0(g z_b%zBtfX^F8g6#YDIydH;}Z(Fw|0N_3=so$emkt?N*`T&!`(GwZi?*keITKiUk-3+ zHQd#|QVdIQZ*be~Hk~~xsbKs41>j;xJ(bQ-tUbwH;rkX2Cg zqOte0`g#{5vr>eEU#d~KYs-AA$W4$GypcCcpy+U_+o5K?x*?AJ!i?X2)sw5yK^&e%w#uO)9 z-X3-MbhsJnvSbB;88So^-id^F2<`~9{o^hPVwBz*|6x2L7o9{)pv;X&a}Wt6GeiQ2 zd+n;nzD&|fq_U#OZaJf(eeW;0$Nf@va(jt4C4D)hy94VYlA05c)6af)L|S57PZl9| z`^Cb3>s$pbhGa*ID#77Llo+jHTwxI4c1|(n<9Bg0ztgkL2ad!X6|Z=hYKhPD<%hON zV5T|yZ3jvYW$I#gOoII%+0xKC>frf(gG}0rieC$Nf=mO&#HL@_E4^?73z^+Y^|8Kb zV#|&`GVKlPHt*!^lA~Ej6i<2Qp3V~;{PMF~Z!jL+H8=(vf0qqQSzBP7&hcfwOqWjX zFKcjNtKU&O-7tM}70dM5L{Lp*kSGB#NYAshHr5tGy58X2@ev`;hrauIcs8jS{NjV>}x_kVh#Mw4Jfbhwl z4{3;Az{}(y)uzF^JRYhfItS0AuA8WdWEh;H@ZbN=pN|t6OZH&T|=%0gl9T%o*Y54jv-k^uN z+FkpsmcAN;eNnDO<{uwuNtDn-%ZBNy2Fi~x}bF^U|0aax`*iw?sL=b(N#|qn5hIxv3$R| z8R8V^1?QQh$mj=JQ<$B({R2`JPVTu|r3&CR*<|R)&r^a6z=4;HjM6sFB1~z<8p%$k zEN^HTM}g^TA?do=>H6Q)b59sTQ&J2B5!y@{mql!ycOjFEbfo}DJZB;c6IYT>2E-a} zu1I%o!Ypn^oqIw?yJdTAch;eN5}S!X%zc70RILU=ND`3*UwNPmEYHR`d4_RxCnJ!a3$ z-gp}vhInFPnyp|eg>8=7VtOXONzME=q*743Qyu0v^6b(dHV>dCJ%Q{|(aA??f2)0_ zeFFJbo@mO6q4-YcC>cb?nP)(f5wHGC69>J$s8yX^5WJBcI>TVdm3^%*_i9S6UL+Op z7)BFU*rl7TvHnbwsz|d=dk$apGvZ3Je{S#${j&-!E+IN@!D3=7>T-VmDHFyB!+lDC zb>(N?w#ebzD>lKv)b!~fH|X60VI*MsB2Kd7y^?EwrE84z&-StnD%BTIasl6Iaqv{{ zQM&ta8q0TKnQIwF!7v&jm{fb2(G0Z-PPyR{L!;VLHWg6Vy;h)EkZeN2aLAeUAg)}> z6sB8Ho&@FyjYD!vC-_RGYnWci2q}+T(6Z{Ov@3Z0RG;qrg6>N<>%ugBZ5(ZNO3Dlq zT|-@k)Cnw3smfgj7NNtPs*hylsTL%GOx{3N7nGQ#Kwq`fjd@lZ&QL3i(4rilxkSLC z+e5yg${%wUh~XHzZWLt-(SLD(^vrRgJ+~n@9mM@=R(;XkUHLq0$bSdcr`ogb4LFY2kzp z!-OwJ>Gr$5CHOVOo8(LT#nNB1G2iw~D#t|$c z3XVUK44tZ$2Qo5qFN9ONd=RaIm_9ewAy7db+7XOUq4T7<;_scm)y>LH+sBG)rjKq3 ztM0n44>yno*j}>sLJGtvRN7@y2sk|an%%ITjOvmtcSZuS!5un{O{)XaO?8Jz;nIXf zXkEQWD57ho(a*^`;UyQznts{IA{pGV16&B2?}Q=g9x|`W(MxlAU=O%m1%Sc~GhsUD zo%?>7(=EVX2{>v9WBInJ$5-p==a{Rc*Oa%=g$YY^JF|2r*s=KpZK_DvOq=8|t9mRG z15GvR!#H9>8NoS2ZHJG!MZ;}jHpY#id^;_&MS~s|f~iQdSLTTGMW7ey)8*IzxS2g)~rwH=%|L#*nQM$Pe8G7v4y3Kb9aN zxM=?ZH$r*~`>x`-I_X?RYzS07e3Z7Q?p`jutDvORx=Emb>7M$K@q;DTImS1a?v>wu z!Y=@ev@`uoYt&$~rnN4(df$gV8%)&qkQDp^oRVu z8rp_khb7F4kNyh;+#b$6fpmC|e0&H;|K9v@yY+c)$~w3i?)O^Al$mBMcfV`Z?#QvJ zdZk|)!1fL1<0Z+qx8{|XxIZCGTlRLjstH=x@e?vB`((ZJkk6=C{Ql*UBMv%tI4%{O z3xAsf^NUyyJt6Rzv8=$coTIlCMZP?S_#j@>A||o#m~6xl3guAa$-P@L{+|=! zVsYr!18(^fnq_9jICK#=$r@QN;l+xp?Gdq-tTr)4;T9+C)%&4o+`3RVg)MHQM@{<` zWwLPHuxr%{L;p7t%()YK_Mtfe|;?C2PFcr);^~oVDWuNwyGuUF0oAXF}X5ap@E~`c(w5V=P_>T5T0>eH! zR81e&!luSNL#@Ge2s+tAIIbvuijFpdYgZx2Lgr~#5K3$9q<*AX63pigpAD|M-OJ)siB!o69|zCCK=8Br`}A9 z5)(Ve7alzP`x1Nbcv#Gh#Ls5$Kx(D#g6npwb&xtqJu|4-%i}vm%{)Q`-QzK%!J<(! z^0;cmsKnthH+)_UE_6AWyifh^!Q!iD$PZ!AkxRexj8fVrNgk;=s;&a+mlDj%if7zU zVAUka3s;#=?jG@(rmlQ|ZxNvOli?H3;3bMM0PapV)*lEdRhB=-4QvaT6N zFKXYPWxAoA#HRX?jLB?MHh}0)!qRAm7cH z{Q{r>jknav`#}UOPA!Vra^Iqo<%CKGyoe3nY*CR9=4rl0PiZ zE_uZ;ZkxhW`zf=JWJIa(3fpRXu{?hFGL~^Eyspf1rRxEU{Sz3+46cV_T!ZE9^%@e9 z9ptChdnliXonHOR+^(&y1hF`zbgZbYTVe=TYGT#RU!muyt8V>AGv5Z%Pi+#%AFC;u zhEB_ug(nwQeO`<2IEQ|TQ^MO%3qK*TY8_6%)#k)@CiY6eF%bEsTB-QhI9U0zS}0MP zJD)9H2~c#A6mn%{EeCVC$iynRQp8qsfq7GnxIqP8lDeD^-a{BHdB7j}cGV4qM{wP# zyDVOVp1wujelwZ!tXma>^zmk_QiiEtW+;+OuJ8LjBGjSI{8v-OE_q^8qG&qi|X~o z<=ZLPBDzy4#}mwM?(rK^)K8lmPf_ze39#sjjrI7P9^2u1W8KoqF$Ut9OYA|MMg5Zd zURvFxElZW-pemJaeQly{5XC6_?!3@$J;a=g+~~8fiPx0Y0++ckb4<6Zxc+%nP!=m* zF+fy5NNP}bU+(6L1rk;bC}Znpcg-K!equc_BD&^Bx$BwlLZN$6c;|@Cft4uTT)dU6 zI(SxCC156K(q^5p+nKyRa=0;P(jc&e1MrM-g|6hr8Xn!a*XH(2Imf%jTxFe!C2r-3 zh*gc@i(N`Dm*0xZBcJ`GEW>VLo)=}7a5zsHwxk0;=@ zp=RuwdI;9lhkRsJx4lk`Kgu{-N3-zlqh=O!GG~^MdXBz(I#0t0L-$(ShGmbOGtzV= z@VCgEKkOrvn<1L4)^(Ih7Zf!lWPYfri)bq9c|<^YgbY26GyBdgP~_L`F+LZ=Ioa=2B!T529@`ZJWN^j^TCId@8#MD?ZOz?sfLA z)X;^T6Ld=Tben}Td4f4mP5$IfaJ%RrlPfk;{|SA~|m1ae$k zpNu6o%uVfVgxy}0l&5yd4NV@$pk_qIa=ANx&~Z&DVcM{{8}FRmhEPl&2uH<6RtL3Qj@Itxss)PP?lMg)WF-hGX4pI z(l92;<@a3q$3T9@EG!wC?M=mZmwujR&Y{4p?I)^I!_?0_&DF4JtctHGt+ce0{N1NA zZH+28X(Rzx56th+T5D;&jI&xeq(C4&G`SK(WqmIz zzyCbNs1sF8_MlE^n7jHKZ`3oTJ|aaZXRg$N25L2&Mr!BpRyy8Q^2k0oO)I2dVEg2QM4 zav%FH!MBd{q13&kpBnsRP2D5Hry+vGY?AX(Q0jV?XhIx`T?D+>5Y}ocifk_`rFEGg#or zyyta|ttX&VOd931Q>uVs^D8xYA^3aR$WoRQVf9mO04u3&M1QvgYQQhF$W`VmvnWDA zJS$#({h7<^OTOBsR*d>>;&3X|_duV`D?M2;d6UCJAB9a1Y0iEZfqZ-xPun9I#1J5PZeoI zoBoFTWqij_rRw?-uKyhm|Ip*{f>fRW9_I?yXD_^5);>6HbgIgihFB8%yrvz3QPHekG+!``E_4?4VR@r@G9qNA5i=~^8O8k>HcU` zhW)3D4yF7%*5*+_kQkMUScF>}h?$5l>o-N1+2P?VpKhuA*rZ`|i`Sjq2I+s_a4d%g z^eeohFb)48&l6ffU|+#-{)#4h?mxkgAT54*XJ1%ni%vnoQ+}6y%QhLoSa69R(!L7c z;7-o`?2o2E6TNPNy~}HEF$NxP*A}SK-Y>_KEsM-{IjXIa1Un~09!Q4kiaqP>xc-5Q za~FGnAS3xCcZn{hP;=6R4)$c<;%>H5iHFzZVmO7!Ir5t?oDtAgwIA`EU(Hd$iwGtK z1z}n=P)4Xv1AYAVD*hNC+#to^*N$7nQvOV=jp#l{DNLK!o_HmHQ-(*{%9OuGuhG&X zs#@SY3G#s2D3(+>iUeMcKEujyZU9)8;4pWbAZ^+sY<7Ga*l}3xdOQ|-44~bFQ|n&k zG{tiE0Crgb%JH-hvM2)`+AHspGtI$`u{fLr0LX|HIuH{Op}Cwfka^FN`O^zQX-+kP zR+prqQpo|eZorw)0BKf$3=bCg77L(F;{&STQ2=rQ#k5m2Wbg4DI_C3hG0D>|1{(lc zr4Ps0Pxdj9=4mY8_=;M8-$)OBoCPVf6bsAhJ{svqcY+jY(v(HC2!NJFTi5`wC#e>D zwEx0NGybY~ispDMrW!CEPis-F^-Pxp3KF-`gj+7fUX_t>NRJ~YK4sy9XINSHry!4? z+IOql05r62wu6POvS&Xa$cv6RxXyX)Af!i|Ff3{2jo2~M?!_kE)04h)03kju$agiN zeyt+AB>3Q=#KoSzMePJeO-nKoq0^xQfL1~l?`6$#OF(+u&j7IqxF%=FK;+XwAr%^4 z0X)V68?4y~TO8;GQ3qZSFE@#mHp6EMgLk}j$uJVe08LW3UcyD6k!HdwGhSL#L)m;p zf?FbSE_PjCC+KGuE;3E0IPRHnNb6`zSB?l)uEfeBu^N#w`c-83`s&d{6~&)VKtH+1<4ihpWI$w$2FVWN z)-vPx#@OL>!?@ZeX!rPdu|a}BOgIfD1SM7dZj8{~T@H|;iyS~(5dS^^8=A%uC>0v? ziUa^|WmNfK*(VljzlyoQe*``j6OLRNpa zMDUY%)<4r0RCtA(5zDPWir0OV%s5RVV3Mjkoj^42OyfuvaU>v8P=*PZJPsrqOAbln znVyaVOyjJl$z>mLGm?r+#IkiymlHn*F@ho08zeyk&`mqP5F?w?|g#7-(;XF`4JY8>j z@NPmtaN7@$D|;;ERl&)ZFD#P5?ZXNC)sAMU4MEZ=7N`vUq)Jp;_@bHW+3NrVYU{^q z41H=v1#g@}j5yDnmJh7?Ku$Yqj?=WOc0csZ!SMxyfJlT}#!S3ty(Q&?0fRjo>UMOW^YYl|47dRu4cx>3V zn3Cy|^7=HpNAP{RQVW%ZMZ1G!vj%1K76ersd)#hQv8!(!F}kcL)hP=yUQLQWgNUug z7qSWT2We7=Cy<~PD4%O+0e#zT~sbFh@e-~L$^<)FkubS2DG zG|L_N>hiEduPqpcD*-jh&^tc|V*}L=3S(vC-T@t%0W?%Z2~(JnMN#@O15FSK5)a$jQV59t^QW|%H5!D9oUk!3=$H@zwk zRq_}J0bR-3NdGbnSr;vp)gbx)$bRBm&oc>AP8$VlUMkAhl8C(ck=;?qF@R&m=+i9r zQnputifcXVR)xfyguBaF*(*~Y-;rEQAfa}RAmbXg)~2icSEd_$~P}JE8N1i zsY7=Q21Mf+6}AYv+X|du_zQ6G3()%jwBL#&ez-mP4dGo8m`;{P*f(kj~svdXJTAl z+#{*CkZ-%cBs|-6NstoC{a8y>SO@-LoSvBYjuI?8&+zd5UNYPR(&p9H8WW+F;QTxH zb|_4<2b(jANiU@;|6&vGF8Rc`)0P_-q1^a&)T<)P8;`~Q;>Gk5)_!RgR=h1^wMd>( zSZs9h>R|;%b`;02)}@_8_$;M_;%~m#(I}Rnberqei+YFrOLkT4tLTMQT7}`Ar>30#1KkU_|pcETlRbz*uMg_NCrK7-! z8wxCo?eWJxWFcvXVl-5%I1!N7n_7~a#}qHuSnh8_f(#DkOkQ8J-|){DaC#?oqNY2> z4lpX+fP53**N(p&a7%XKl1$EU^uz3QW%aWvSLY~Q zn%?iz{9`mw7f`_iaNNWiJd67Qt`!-6#3_TF4<9E%2M9gZBU#^nRUk=aXmDQMe03<` zPy!&GJmJXg+c&H^Sgl^C89+wBo|2wbqDkb-CKwd&^=1jHqDzEh;^=B(>s=%nFdAg# z*t=dSxX!z6!9ZRD$ww6ptxt5pSuvGP$+k?1*Dos?z0Z3I+T{87+R@ks7X*rK!1hym z#CQzr*IInHedR+b^6#JQKP5uXVzm-JuUOwx-&wls4IY>a)J@+sS_zJjBI~!{$UO27 zSgBpX?|R%HV%~fM9b~{emBs5&>ie*QZVjFjiR)M1x_fM?d^!$s5;pN>s6BWr`=Z*K zFD(6^;g}uG9tb$~Y43c69K*PF!1d4H0LT(8cJBS*bF1X&s);!l!)Kb0lQ+Lsg2E21 zLjjg|jCV9ut_77-K09E-P76IU$Tr72pp^zg4<#fvpMaWov`W~ADrLUMw|?E2`HEZp z(RG!}zqJwm?w*I&@tK1jzWigR0+Evck&OLZa!Cb!`E}H-j5j#qJ2Wm}F(KS4k3I9e ztaXE7c(BaGkl^4w^$8?X1E$o)YPS8%s}R53x03Zqm3b=^-F{(EbjBs+_H7V$ep{8_a?Cy5x z3Z<3zKiECt9wu<<5o!NvZBzTc2)^KUFe<>b9No_p(t~LfK}` z%dQn_BnvGsTCh!*o0XaIdiZv~sT7&m8*Beuc|FqM%#l~uO8DKg?cQh=1Hz$Bt;bGi z#QV&Twk=8v_F8WD#a6o?QPPTeU)(jk4E;h=8S&0AF@296t~}A@1R6S=@>5`4d>Kt z2wyk37fJ#ac;ip?Hevnolp;Vrz)89(qy8$pvwuQ7|x@l?~GLt;S+=O)p5jbdQ z-`uu?4W*I>DvOFZZa>HQ0!@F%NBCUBo$L+#}p(` zttoatC7*CQP@m%qq^>|ao-<+IyLOn%-U$676v7onTjjEJ{?1)`Qbq%QW$mu>b9eI4 zQ%}qnWa+1B3e)xjO}~4^FLVyvQ!CZ$+HF%6zcOn=<@XkyuPIRYz20qMvfVbqldqk6 zrEz3X!xZekIJ2w1!ZBZSxZF)Y-NvL0dlu#bMKTKRjiaZNAnA1F zi>zuhQ~Jbg?1?r(b^c3{UiBU7LH|ymyQC~;2KnVo`xm1x&8zMHqAcCHW*>N7W)63< z+Me$C6q9p6e{ZSXNS7P-$lhCj{7?xA%f0D1=XlJsWmvpbyk4M8nM{$)(MvC4_vEjRfuz74yVFw8kp2xJJ1}KhY`edR&mSq?j3g^l#fw7sm>#H*_GPCyXUDaJj_#q)`^eo@+yW zWrO3Q9(+%-^;EXOoz0ngyi>2SRryejz;>b3Uu0DGk4%=f+))AE#9Cq>%;iPHysyjC zeIzscfKvP3SQu99db4#JyXUAcsDR@w%r6*-yjzzYYN3C5bw4*~s`ygC9J@GOKx_2Q zq{@5)LIrD=nKTX&e~%aT9*+a~!LqXD_`I9_@jy`Oxi$k^qzDloe;s_MfQNoVhe4G9 zk(w$%L~O=v@8e>OrsSWtmi+^HX5L-vb$Gfj8Z*_{yke6-{}ERE|Hb(+ zwmu6(88QY#X{`0nM{|?|w&w=}irVsV(FjXDY4?s$$Ugml;rtvM_&obV(GM?d>pd4Z zCOz@uXYFuN&%Ltge0i~K-63*ScZ2FXe?`*OEz>%Yj-jBI`-Ik30z}(5ZO?5nf1hQ& zmzaUo2vsQUe1G4x!s*Ec`qV2Y!TG8o-nZg9joJbYWEcPOSpE$bbd2SJ-+oTIaN}n5 zcHb70$lmp_8T|C<^UOzOp3&(BO`p}rJ)7e?A2IFRM)GNt5RLCFBKALvC{jJUbH>7p zN$K&UIm6#gCZ~#yYN+l0JPP3Bh+K2w(It92a}wvtrQ^y!{oIx!S%MBzjHy@}mT-gc zy#jo#3V1Ar^_j(jLAMu$tai1Q$ysX*rZX0`)FW_ykPDrj!T!vTdsO`!!2yYA@et9jcqO~JW}e0 zFTt3vp?@%{zTMZSsK7bWla&Mzmh0MVJec)I;XJ`2Mk`|UCO+rh=5d9fC|6c|VpO1Y z@g(f(8c8dyh!H| z10Ggza*e~YWn1wp~bXUkoA(0tc2E?S3Q~O zr>3jFL6{l%Z52RuOBO$>{C-5?W~n%>;>nx4??2gWX#B9!Og!ru!>!78j7u!;B>~;n z_?SygUl#4Z!IQo#aK2&2dyO-@OFubU&%L4WPW|Lt#G|n`Vd@Jj>w-xZcWJ?gMlQyY z4*>Nq>T|}Cs#)6U+vtVzlmwaGn6QmLwYcA(uNdedzQf9U9W~d<+SXHwc3vqOWpZx> zenKV=+us@{2F@fw8v4j@Hgrb+;$~UDKd|_rd`aEo;DtcO;p)hl=H=tBk0y<{d*(pr zZyZ5nuZK{hf=~SK#c9R&_^EUfA-wuM4EB3bZ2zrfI5%@*VTDjV{r{)a!eDcZx94(Y z{?B2helN#=Xw!2G@%H#cYZ#V@`;TEIv4tUad>pGMsgLHX>x({?k-3T?F*d)~iL~4& zs_GQMZnWr1^~)qcJYr!zqJZoJKjKXcAJ4~u{)=t<$-YU&TpOF0Bj=Z~fg{B{M+185 zP*?QpB^vzh-sPyiTCA^vJ|DbQ|8gA#83Bsb`r}J9v`-~_wXX`zl^I;|uS?5x6cE*p zr_ouV$FSrPz8uY`);*(EEeL~t?lpdYq|A^*2mmwOQXM^Q4X|wu4 z|FGnns)t$QNzZWzJP9ls06>=3a3l}1j@Kb}U}s(F75i9}lLa=WOc)(J%K3h6heQ z8k#CqP%OV3d1{f14k}UN7Qa*~Mh{B5oR^D@Z}BLh}zVtZ5|7 zA9<3pX+MGaMNT&l}PtGpYj9KsPxP4-)&;@h9*7KEGXg5XBhjTN)tktgECiZ26= zzl^?`bY>o!?+t7oo>tp4f9B{XWi1o-4!rYP;no|e`_*!!O=}k9%9>kv?<>dMx<;{) z)dUwBZD`+18_{TTr4u}G@wt(V#P7e=^b5np6Rle>-&xf#&@bED=m(2!N$$Eyk1Rhc zYp%P|kr16VNkZMveELvk-`q;ox^y*2Lg?4`_>(On%N?OE88yy|)y_Yy?pqno3naM@Bh=$aHkux758QG{Z>wTXGI6Q0>cl|2xI-H!Xs|Lyn1`|E#DI(yETNV~u;Nx0f>AMIN{59-bhexLK5 zGXKWdTqj;`uL|U_z@T!hIsA9d{m`JX^0|{7<|QQ{kaJo76|6)lkwj7xT6poVG`Q5b zJ^7}(=-k<7kxI^epSaI43xG#VT2_QVh46=eDb#;7vMBq3Hno}JzP-Ollo#wXm%tFU zkt>%dGLO|&59-&3E9ne8xBXm={@jWaK<{;vbA#w6VH3g ze9uB(96T{}en_6a`|efb_{*is>G!o!uw~pU1asiH<9A^2YgZcTUaxt0g89Z0wVs;w zp7+Kcse0fNJKnEQxgDF?6+aEg`Dai+h~~WP5r5S~xu;Cykg4#*v352%N02Hf#*HC_ z$v+exI-P4f8~e`r2Kp_}U$KC^7{!#X$5~v@j>Na#sn~-LOJT&fHsx3qAh{ zS-O0-`Lr(alTXbS#OcA2%Kba7FHCt=(KA*}W?z3^%^tN-f$dg&O#iZX=>lEf`4pZ2 zat9Vo5!-Juu|f~=6R5IO*clnYp~U)TPy2K)l=>J|VahQBVJp^S-jM|seeX!RK46DR z)f9OCRuG#e6GUup=|w77PDFl+jI=;8N@qq}qF@AyyQQp{Bz1&p3+l@ehN8s0y>v;t zB}QXH<~N4DQYOg3?4glutl)B#MWK|VACki*_WE(GKp+MNjT7~YF$D+NnlZYH0yp)e z?m(sLCm3gz;*1L!KFWykDaRa$MEkg-(9lqe$Ok92kq&s6S(!{Y8^&;kC~{kY_Dq?X zd!I-{xnKfj?T`WF@$pG5@j`s@m(7r4rDE|bBpbfSk`_#{2*C(X3g8nsSImXIM^`{G zmhMcI#mvOx1bS+CJXE-G0Mpfi?tn6%ImH>*Qr+K-Z?i?u0Gc=o_dX%E?>_vZD4uQ~ z@}VV(6OW|SGY_?3-j>E+B$fS#(v)OJ zzm&t7N2ZaFBm|KMn~%_Dth~X^ANj&7 zTQH(q(aL;W+n`i7ku(i<^h8U#;!VUY9K?j4Nv9Q)n8|cm9)D7h7E(%;BlB3LFz#2d z;$WdvJeZtjO#><5kC%;e3PE>vV+?G0@v}^`%TF}35-_dkuyQ6Z9Q*grpCp&03eK9E%>3$s_IIXioXG0Nt3R<_w%%t zb7dous|EQqhG@N7geK{Um@~r#vBD5p4$i1(4QI+vLZQfVj#^|oyCK)fQg|UHlh%`k zfiF7;!etYJpFAmoPG#l2M}5d*I%;K7AoJ316)XA$hHMt{p(HRBkv@gq{=SihLwHVT zK}exA1c+V36)-%3>xMqV$s!Hx3+*}3f0yH(LKSU_ip2e%yPj%}1v7nc7K5Ln_&+gu z7%D2LmRd~kY7E(=MIkQ?Nry3%X~~Llo*l!}BM~90F~m01z0xuZzdNTjUK+9`Vt&Ye z_i|}=35YM@4of+&S$@tT@?UFlfhT^S9`kivQx{x%B?vx(#@zf=p~m+xjRBQahDqOt z*O+GH8(h3-2*ezh|Di&fouZysyinys_Of%fLNWfHXn>(ANxw2kwyaAG=nF-kezhx_VpOmuUnSPN)dBCia zhNvNNG-Ewe{Ao2`jCyM*N|1#4ERJ4gsLk@IRxZR;I8o+XOE_|(j|k#6{MEp|>omFg zZbps3F!NU|QlJiQ=Y;Heg)1l1BKuAC7Hsj8jyPC_PbuylN=Su4{aGk6nM${QOH0i4mtbK1{I{9q|fH&H)N@P&Yi8dcxW>%reOK z=;|YQ;~b`FvcuubkIlui!$zQfU?1HGf}em|*!`OOisjnPN>{@a*Y?_>6YbI~ovQor zoja&+U#browQ9!U(VS@IEq+iX@XNOrz0BCz-KA37EeGcCGGl;r)4FkXhx>CUrxp}D zpv+&Ok4?K-oZ%nZ(E0l9*kxg<;+{7*k$=^y6#|g@d<7hQ71C%l5&E=$4s-hTb@?QR zu3yUp8b-(Y^j8@0Mzlw$Q0`4PTo%^%iI3Gc6{(X8RNO40|AQ8Btdv0I`FZ-8=PJD; z_7%nf1~3wMs#m$Ee^VIvkOR2XzPULcZnV+Q>W3WfPMFbt$-yUnsS=26XJS)s4f<36 zwI=)4Sr1Eedkd`=@*re@fwqn>5~=4=^E9NC*A^W(0{BS|S_vbYomn49qT^s}$*`e5 zNM|@-;=m9pFC5_U?6u!-fmIIi2-aZG#Y{S+wxnTc#+FBOVWsNN6d|lDj3fM(2zu2T zOuMyMA#xKp9O1%p0mUgUmpjysPqafyUO_jv137jGvv4NC+VZS@D>V3X}Y6+OJ+(6LY}IED-6&JUxWzscGl+qw)t-pQ?|C z6u)bDC4u;cQD=j(NC9g`6D)$1hIrQ-E8j72S6k=s4|J5C9rwINUm3x=LLe$m+-RFcfc0N=R1K7g9yy z*iDS5{r=*Lk3LYFrM-8EUaF|Z#!TIL)=J5mhTt@3SQq@@OnPh{gi_0k}7gh??gr#O&t3{&N7JH=&Ih5}`;A7uvzOgRGk+Q1&@ zl^}-i*a>m@33rz4#CV09+j83%N7dJNSSxyC(avI}RozVcvm$~O8)rMfD6Ee|1vHHV z4jkCF3kGVNKT%QU6#3o@Tf(%hMV{94wadGP;Mn^L7_a(&_JGtLD@8*5W;i1eG4V*r zY)0;69CM}ul#jeDOR3QYJIf$92ym;So*!7|N~%TV@*)zybV&pB#rTCd0p52_>t+NX zl?z~SV2(M|_7eY^2B@cIP?pjFpoaBjKfAZH?M%{BzOhT{K$K-bXjQ76G?dgBV0eK} z`Zt@ZKhU|njO1ZYjG7chAw8!x)#XOUo^YxB)f|#pf-Y0>NTF5s7O(I(x7U9VonVZj zUTFwZIIba*i`e6OKGO%@Fc(9^H9@nWW(0~BW&U3N?1XKEdzQYI#d;s!IL?^thHPAC z-X=)h`t#*j=@ZZDxIn?`vJwc1Lp8SnA$tpiip{$(C1$ID*d3tHl<@?-d=@=@_c5a( zKcHhuV_NXUR~?v@0o@!bFYa8DKFv&~BCoWFfQl2!sCw8Uku}j7hemEcx@D-G;fA$T z5YzSc-@yFXmPxC~BDpGzve0FW{xZJJ+SmB-C9)_ReqW0T>C_YR4S3_-LC)n0H)=sl zWId{7Y2)s}uN+a)Rooyo4#Y<=jKLLr}Ot&@3Ya9hr)?mw~ct4XVn zUY5mfc##1+I_s-|bo3%&Sz@<%tQ^Djy=(Rm$<905w2N1wQ`CPQzU8Zt$uhJ6?2Y za3-+)Ii~ADPdqX(|G@zPseTiV+5{TPV=S1CAu`D5v*YdC3Kz_{8-4fhjvYf~xyJJW zb#By=DZ(OvOYFiayQqwtkI4Nl#Nya9{^hB!xM7s}&!&g|ao=SKWq@yO@qy`=Es_N?7ATw`V2bc!Vqmya6tQ806){J2@`#*7h!GUmwE8>^|ou%Q#f7k$l*qe zjKFhk;!D1Fb8`z_MBW?!T$gFSY2?l3-c$)NKdklg(FD^8*5Du-*?NWklk7%(?mq&` zI-?y`YqS`p`(%2fr{wh;CWI$NTA9&PH9AaJb!t`fXbIy5Zv@+(cVXO0YA9XE7B2(x!}6K28*jwK?fFQdR9M7%&+PO>Cd96gsg0CaHj%#eI7D} z=MiN(>uYOjt7P!MnIOJ^5sE2a*x3GsZl{b}_qshCJwAT;&fr;sz0B6S`^gbY$Y-J002m8qSsnkAsM_L+6@7Rls+P*pOYSo=v;BG^;W z-CnksgAV*VXwslC_SD%}Ni(NXm(Td|tZ$QTN{+}H7z2g1(hR(*uIg={%H zK6W`8VZuYuE851tbqV9LZW~VZpX!b#(pvl~iq&FB|rlHNWg zE$jucgUnPt761-VZ+0}^h#W4i^5gl1xiI}F#2}SzkHL3P!SzF-!X^+TG+Fqu%!u2(boGC_wFT-9$g=} zXoH!qdPksZ%`=z}d`7;L+sjk+9noE2$!H8s zAqPF%X7>iOAWhreu)~;a3V1gq>U(SVJKN*5st7@<^FYs^i3D3Oi51(I-9H_k*O%ixmkV`>p^`mgKZ`?oZ zcW)cME>9s>N7DZo_(l#f=+A^_kSB_;jCDo@;RG-Cv(~o;slk|?$UZ6^*)_c>Hvrvt zkk!UfDnwLJi;7qcYnxqD=@rtzAt>3Yt)*9=v>KCFE#w3kOV#f)U%fy<(um1W;BA3d zA{lO_cbPp^O*U_YH{j@LWO;P-ou~pXKlknmAK_U@O^U0#1^GUb%s+>25^TG}Lk>4m z5_vY6ig;Gs(&~r{k#DW&&@JlX6L!tDv&i{8<(A4
(Hxbq{uY}jACc(+hyHZSl2 zIh*K|pIzw9!ECNIKdP((e5fii+Cf*h6btw-Z}0s+ww)RbmcrnFn;FbMsQ6`x9RV>F*`n3tz#JRWrrSefgWdED07V-yYrDE_+~MytK=@Nra)i$b=`btkjS=zL`C z1N+*Dft_%E0`*!+I<`&7IG6`oGOL23BzN!_MuPtUGj6PVl)EO{4D^f#3|U5tTPMO` zXwXvI2dvL{E#6cT)xRR#av*gOmv*+p61sY??}8@joUS79Z3u&C_V;u!GPfE*c!8cq z&~4uOiGRJnr(1VhzoqG+^D1gv z-q6auv_Ej9XhUudvr~L_sWpVQzuh;FUpIcFaS$o=b#U-&KzziB_-D>uIqD(H=Xi6e zbcE@QC%v6CmFr)W5uGkrN7m=XsK@p!qV|qCTlXF0q?=~%EVljm_i##wtz~gTWK{IU z(wqe#aLQ|v8)Z_=M`e43^$`1Dt&R%jM354|%|n3uZG#%9cl=oIF8Y^rKNuCfuVnMb zC?*jg3qG9hk)chfM_wDd$Fv2{fKGOYbJk1I9oWs%|FtcuwuU$ zpq+}h8rQ>k9f;?3h0@M8>&uuNMEU+%=D;ayIeFjY%xLG6fBU&NC~ZO&p;JP<@*0#1 z1SSE0p&Tlw+NA5iR~l!K8XMt#;cg(=G(t^JUsd}_{?AIJ2Gm;=svnJxNekfqYFj-p z`|c&s_`C1ZzkVnltCIFBzQlq1WTNIazd-%?U>n=uTRQovr|mfqUKXywNA578trNO^ z!yLLRg4OFJ*as1T5e}Mnekp_Bw{%xQ%7-%V^M5SSR)75+mUAFV?G3ncmlDHv*maTl z=Rx%+2`PZObIPa1v(HDda*Sa-XJISS6^WOm9~>~#gsmw(HC~;$Qjm8kV%ui%G=uBk z&&D&sb)UuG3PqolyDt6X_;!nvu29c>u~)0v+M0%^zlsIt^<>%3{+$DlD{ml8TQJJBNkl7y3oRUY}>AZqNSGukgEbi zy@;4W#0yhgiD}o@vZQ{<3yws!D18_@2I7M1x;U<`&9_D;g{ zWVD5i7!lZ)XASyXnUkPA*$QkT4B;!^V)|6>OY%j_-Xap$VJK-wn<0n+jF_npCzNm~ zFlgvNS40bnfX1lJriJ4y#AXB7osAXMw;&p|DqHZ6p|n|?o?AV^SQ2{Kk@3Lpg;Z|- z?lLIkl}NK>-=Cwq>GzI&?=1YVW9{RIkKUoASdP z+T8|4{eioyT>4C*QNu+dHp^`lNV9{qnW_mA=}9StGOi_1iy!ffAb##41TL3?pTQj* zf_#z~GeNHwd~>%>8a!n-vlPfod%*>AP zM>G%)>lo4;Ut>&niH^$oc`^*%BBY>Yzk-Zd!XL4)<@V=RJB4Ly3|5_j2w>C8Nts$G zQ4nuUT$2~$!#BZ*|qTk|V{8UsXg@0tWq5Vo06D3&VYzh;vEKVA7 z%E}udC8OEJ>Eqw#!rq2Rj5Lti152jvkTl*mB{^Z^2>q2_r0PKva@nX(VYIg>DF`4Y zlOpMT>z=D~PR?-6{-N)Ny?Zn>@|gWyT-iGq zIu<>EqUw0rP-8$;HqvP26&#iLJVfafSKQJOoJzka*GS^4D>_T_y&63*Ss462hD=CP zy{Iq>g%0%{Wsdyztm+Sjmsm*g;k!rccRNb-~ecd*+uzri%5a zqK`S$KGfffNvz9lZgRKWnR#D`qY<<<{VY1U=v0eMNVK)5^)E3inj!cYl9DFbEdyZJ zjx_X@oSnQ6-nH;Fo;=D@*g-=i(>e# zG!{nQ?_PF@6)>a@9^=DcW6e;24x5e{rDTIklX FaW_V}^#b5rgFYPM$4SB*U}iJw}t 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 |_B5G+Z$Ry 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 literal 0 HcmV?d00001 diff --git a/fairseq-tools/fairseq/docs/getting_started.rst b/fairseq-tools/fairseq/docs/getting_started.rst new file mode 100644 index 00000000..fa5971dd --- /dev/null +++ b/fairseq-tools/fairseq/docs/getting_started.rst @@ -0,0 +1,206 @@ +Evaluating Pre-trained Models +============================= + +First, download a pre-trained model along with its vocabularies: + +.. code-block:: console + + > curl https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2 | tar xvjf - + +This model uses a `Byte Pair Encoding (BPE) +vocabulary `__, so we'll have to apply +the encoding to the source text before it can be translated. This can be +done with the +`apply\_bpe.py `__ +script using the ``wmt14.en-fr.fconv-cuda/bpecodes`` file. ``@@`` is +used as a continuation marker and the original text can be easily +recovered with e.g. ``sed s/@@ //g`` or by passing the ``--remove-bpe`` +flag to :ref:`fairseq-generate`. Prior to BPE, input text needs to be tokenized +using ``tokenizer.perl`` from +`mosesdecoder `__. + +Let's use :ref:`fairseq-interactive` to generate translations interactively. +Here, we use a beam size of 5 and preprocess the input with the Moses +tokenizer and the given Byte-Pair Encoding vocabulary. It will automatically +remove the BPE continuation markers and detokenize the output. + +.. code-block:: console + + > MODEL_DIR=wmt14.en-fr.fconv-py + > fairseq-interactive \ + --path $MODEL_DIR/model.pt $MODEL_DIR \ + --beam 5 --source-lang en --target-lang fr \ + --tokenizer moses \ + --bpe subword_nmt --bpe-codes $MODEL_DIR/bpecodes + | loading model(s) from wmt14.en-fr.fconv-py/model.pt + | [en] dictionary: 44206 types + | [fr] dictionary: 44463 types + | Type the input sentence and press return: + Why is it rare to discover new marine mammal species? + S-0 Why is it rare to discover new marine mam@@ mal species ? + H-0 -0.0643349438905716 Pourquoi est-il rare de découvrir de nouvelles espèces de mammifères marins? + P-0 -0.0763 -0.1849 -0.0956 -0.0946 -0.0735 -0.1150 -0.1301 -0.0042 -0.0321 -0.0171 -0.0052 -0.0062 -0.0015 + +This generation script produces three types of outputs: a line prefixed +with *O* is a copy of the original source sentence; *H* is the +hypothesis along with an average log-likelihood; and *P* is the +positional score per token position, including the +end-of-sentence marker which is omitted from the text. + +Other types of output lines you might see are *D*, the detokenized hypothesis, +*T*, the reference target, *A*, alignment info, *E* the history of generation steps. + +See the `README `__ for a +full list of pre-trained models available. + +Training a New Model +==================== + +The following tutorial is for machine translation. For an example of how +to use Fairseq for other tasks, such as :ref:`language modeling`, please see the +``examples/`` directory. + +Data Pre-processing +------------------- + +Fairseq contains example pre-processing scripts for several translation +datasets: IWSLT 2014 (German-English), WMT 2014 (English-French) and WMT +2014 (English-German). To pre-process and binarize the IWSLT dataset: + +.. code-block:: console + + > cd examples/translation/ + > bash prepare-iwslt14.sh + > cd ../.. + > TEXT=examples/translation/iwslt14.tokenized.de-en + > fairseq-preprocess --source-lang de --target-lang en \ + --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \ + --destdir data-bin/iwslt14.tokenized.de-en + +This will write binarized data that can be used for model training to +``data-bin/iwslt14.tokenized.de-en``. + +Training +-------- + +Use :ref:`fairseq-train` to train a new model. Here a few example settings that work +well for the IWSLT 2014 dataset: + +.. code-block:: console + + > mkdir -p checkpoints/fconv + > CUDA_VISIBLE_DEVICES=0 fairseq-train data-bin/iwslt14.tokenized.de-en \ + --lr 0.25 --clip-norm 0.1 --dropout 0.2 --max-tokens 4000 \ + --arch fconv_iwslt_de_en --save-dir checkpoints/fconv + +By default, :ref:`fairseq-train` will use all available GPUs on your machine. Use the +``CUDA_VISIBLE_DEVICES`` environment variable to select specific GPUs and/or to +change the number of GPU devices that will be used. + +Also note that the batch size is specified in terms of the maximum +number of tokens per batch (``--max-tokens``). You may need to use a +smaller value depending on the available GPU memory on your system. + +Generation +---------- + +Once your model is trained, you can generate translations using +:ref:`fairseq-generate` **(for binarized data)** or +:ref:`fairseq-interactive` **(for raw text)**: + +.. code-block:: console + + > fairseq-generate data-bin/iwslt14.tokenized.de-en \ + --path checkpoints/fconv/checkpoint_best.pt \ + --batch-size 128 --beam 5 + | [de] dictionary: 35475 types + | [en] dictionary: 24739 types + | data-bin/iwslt14.tokenized.de-en test 6750 examples + | model fconv + | loaded checkpoint trainings/fconv/checkpoint_best.pt + S-721 danke . + T-721 thank you . + ... + +To generate translations with only a CPU, use the ``--cpu`` flag. BPE +continuation markers can be removed with the ``--remove-bpe`` flag. + +Advanced Training Options +========================= + +Large mini-batch training with delayed updates +---------------------------------------------- + +The ``--update-freq`` option can be used to accumulate gradients from +multiple mini-batches and delay updating, creating a larger effective +batch size. Delayed updates can also improve training speed by reducing +inter-GPU communication costs and by saving idle time caused by variance +in workload across GPUs. See `Ott et al. +(2018) `__ for more details. + +To train on a single GPU with an effective batch size that is equivalent +to training on 8 GPUs: + +.. code-block:: console + + > CUDA_VISIBLE_DEVICES=0 fairseq-train --update-freq 8 (...) + +Training with half precision floating point (FP16) +-------------------------------------------------- + +.. note:: + + FP16 training requires a Volta GPU and CUDA 9.1 or greater + +Recent GPUs enable efficient half precision floating point computation, +e.g., using `Nvidia Tensor Cores +`__. +Fairseq supports FP16 training with the ``--fp16`` flag: + +.. code-block:: console + + > fairseq-train --fp16 (...) + +Distributed training +-------------------- + +Distributed training in fairseq is implemented on top of ``torch.distributed``. +The easiest way to launch jobs is with the `torch.distributed.launch +`__ tool. + +For example, to train a large English-German Transformer model on 2 nodes each +with 8 GPUs (in total 16 GPUs), run the following command on each node, +replacing ``node_rank=0`` with ``node_rank=1`` on the second node: + +.. code-block:: console + + > python -m torch.distributed.launch --nproc_per_node=8 \ + --nnodes=2 --node_rank=0 --master_addr="192.168.1.1" \ + --master_port=1234 \ + $(which fairseq-train) data-bin/wmt16_en_de_bpe32k \ + --arch transformer_vaswani_wmt_en_de_big --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr-scheduler inverse_sqrt --warmup-init-lr 1e-07 --warmup-updates 4000 \ + --lr 0.0005 --min-lr 1e-09 \ + --dropout 0.3 --weight-decay 0.0 --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --max-tokens 3584 \ + --fp16 --distributed-no-spawn + +Sharding very large datasets +---------------------------- + +It can be challenging to train over very large datasets, particularly if your +machine does not have much system RAM. Most tasks in fairseq support training +over "sharded" datasets, in which the original dataset has been preprocessed +into non-overlapping chunks (or "shards"). + +For example, instead of preprocessing all your data into a single "data-bin" +directory, you can split the data and create "data-bin1", "data-bin2", etc. +Then you can adapt your training command like so: + +.. code-block:: console + + > fairseq-train data-bin1:data-bin2:data-bin3 (...) + +Training will now iterate over each shard, one by one, with each shard +corresponding to an "epoch", thus reducing system memory usage. diff --git a/fairseq-tools/fairseq/docs/hydra_integration.md b/fairseq-tools/fairseq/docs/hydra_integration.md new file mode 100644 index 00000000..9b77dd83 --- /dev/null +++ b/fairseq-tools/fairseq/docs/hydra_integration.md @@ -0,0 +1,113 @@ + + +## Hydra + +Hydra is an open-source Python framework that simplifies the development of research and other complex applications. The key feature is the ability to dynamically create a hierarchical configuration by composition and override it through config files and the command line. The name Hydra comes from its ability to run multiple similar jobs - much like a Hydra with multiple heads. + +## Train models with hydra interface + +#### Provide parameters in `.yaml` files +For example, if we'd like to train a language model with transformer, we could provide parameters in yaml files. Note that the modules used (task, model, criterion, optimizer, lr scheduler) in training must be migrated with hydra interface already (See session below). + +- Provide top level choices on which generic parameter file, and which modules to use: `config/config.yaml`, this will look like for example: + +``` +defaults: + - params: training_params + - task: language_modeling + - model: transformer_lm + - criterion: cross_entropy + - optimizer: adam + - lr_scheduler: inverse_sqrt +``` + +- Provide generic parameters common across different training jobs: `config/params/training_params.yaml` +- Provide task parameters: `config/task/language_modeling.yaml` +- Provide model parameters: `config/model/transformer_lm.yaml` +- Provide criterion parameters: `config/criterion/cross_entropy.yaml` +- Provide optimizer parameters: `config/optimizer/adam.yaml` +- Provide lr_scheduler parameters `config/lr_scheduler/inverse_sqrt.yaml` + +#### Command line overriding +`train_hydra.py` is the main entry point for training with hydra interface. If we specify all parameters we want in `.yaml` files, then we could simply use command: + +``` +# task.data is requested field marked by `???` in yaml +python fairseq_cli/train_hydra.py \ +task.data=/private/home/abaevski/data/wiki103 \ +``` + +Alternatively, if we need to override certain params from the command line, we could do so as below (note the structure of where each parameter sits) + +``` +python fairseq_cli/train_hydra.py +params=training_params \ +task=language_modeling \ +task.data=/private/home/abaevski/data/wiki103 \ +task.tokens_per_sample=512 \ +task.sample_break_mode=none \ +model=transformer_lm \ +model.share_decoder_input_output_embed=true \ +model.dropout=0.1 \ +optimizer=adam \ +optimizer.adam_betas="'(0.9, 0.98)'" \ +optimizer.weight_decay=0.01 \ +lr_scheduler=inverse_sqrt \ +lr_scheduler.warmup_updates=4000 \ +lr_scheduler.warmup_init_lr=1e-07 \ +criterion=cross_entropy \ +params.common.fp16=true \ +params.common.log_format=json \ +params.common.log_interval=1 \ +params.dataset.max_tokens=1024 \ +params.dataset.num_workers=4 \ +params.optimization.update_freq=[16] \ +params.optimization.max_update=50000 \ +params.optimization.clip_norm=0.0 \ +params.optimization.lr=[0.0005] \ +params.checkpoint.save_dir=/checkpoint/mtian/transformer_wikitext-103-hydra-args-cli \ +params.checkpoint.save_interval_updates=10 +``` + +## Migrate existing/Creating new modules to hydra interface + +In each of the modules we want to migrated/create with hydra interface, fundamentally we need to + +- Provide a dataclass that layouts the parameters used in the module. + +- Modify the builder and/or constructor that previously takes `argparse.Namespace` argument `args`, into taking `omegaconf.DictConfig` config objects. At this moment we allow `Union[omegaconf.DictConfig, argparse.Namespace]` to support compatibility. + +- For `add_args()`, we need to extract argument from the dataclass defined in the same file, and append them into `parser`. This is also to support compatibility. This is simply supported with `gen_parser_from_dataclass` API, see examples files below. + +#### Migrated examples: + +- Task: `fairseq/tasks/language_modeling.py` + +- Model: `fairseq/models/transformer_lm.py` + +- Criterion: `fairseq/criterions/adaptive_loss.py` and `fairseq/criterions/cross_entropy.py` + +- Optimizer: `fairseq/optim/adam.py` and `fairseq/optim/nag.py` + +- LR scheduler: `fairseq/optim/lr_scheduler/cosine_lr_scheduler.py` and `fairseq/optim/lr_scheduler/inverse_square_root_schedule.py` + + +## Interpolate parameters across different places + +## Support of legacy interface +If you still like to pass legacy style arguments in command line, `fairseq_cli/train.py` can support this. Internally it coverted `args` into hydra config objects whenever there are migrated modules aligned. + +``` +python fairseq_cli/train.py --task language_modeling \ +/private/home/abaevski/data/wiki103 \ +--save-dir /checkpoint/mtian/transformer_wikitext-103-hydra-args-cli \ +--arch transformer_lm --share-decoder-input-output-embed \ +--dropout 0.1 \ +--optimizer adam --adam-betas '(0.9, 0.98)' --weight-decay 0.01 --clip-norm 0.0 \ +--lr 0.0005 --lr-scheduler inverse_sqrt --warmup-updates 4000 --warmup-init-lr 1e-07 \ +--tokens-per-sample 512 --sample-break-mode none \ +--max-tokens 1024 --update-freq 16 \ +--fp16 \ +--max-update 50000 --log-format json --log-interval 1 --num-workers 4 \ +--save-interval-updates 10 +``` diff --git a/fairseq-tools/fairseq/docs/index.rst b/fairseq-tools/fairseq/docs/index.rst new file mode 100644 index 00000000..591db86c --- /dev/null +++ b/fairseq-tools/fairseq/docs/index.rst @@ -0,0 +1,49 @@ +.. fairseq documentation master file, created by + sphinx-quickstart on Fri Aug 17 21:45:30 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +:github_url: https://github.com/pytorch/fairseq + + +fairseq documentation +===================== + +Fairseq is a sequence modeling toolkit written in `PyTorch +`_ that allows researchers and developers to +train custom models for translation, summarization, language modeling and other +text generation tasks. + +.. toctree:: + :maxdepth: 1 + :caption: Getting Started + + getting_started + command_line_tools + +.. toctree:: + :maxdepth: 1 + :caption: Extending Fairseq + + overview + tutorial_simple_lstm + tutorial_classifying_names + +.. toctree:: + :maxdepth: 2 + :caption: Library Reference + + tasks + models + criterions + optim + lr_scheduler + data + modules + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`search` diff --git a/fairseq-tools/fairseq/docs/lr_scheduler.rst b/fairseq-tools/fairseq/docs/lr_scheduler.rst new file mode 100644 index 00000000..bbc09dc2 --- /dev/null +++ b/fairseq-tools/fairseq/docs/lr_scheduler.rst @@ -0,0 +1,34 @@ +.. role:: hidden + :class: hidden-section + +.. _Learning Rate Schedulers: + +Learning Rate Schedulers +======================== + +Learning Rate Schedulers update the learning rate over the course of training. +Learning rates can be updated after each update via :func:`step_update` or at +epoch boundaries via :func:`step`. + +.. automodule:: fairseq.optim.lr_scheduler + :members: + +.. autoclass:: fairseq.optim.lr_scheduler.FairseqLRScheduler + :members: + :undoc-members: + +.. autoclass:: fairseq.optim.lr_scheduler.cosine_lr_scheduler.CosineSchedule + :members: + :undoc-members: +.. autoclass:: fairseq.optim.lr_scheduler.fixed_schedule.FixedSchedule + :members: + :undoc-members: +.. autoclass:: fairseq.optim.lr_scheduler.inverse_square_root_schedule.InverseSquareRootSchedule + :members: + :undoc-members: +.. autoclass:: fairseq.optim.lr_scheduler.reduce_lr_on_plateau.ReduceLROnPlateau + :members: + :undoc-members: +.. autoclass:: fairseq.optim.lr_scheduler.triangular_lr_scheduler.TriangularSchedule + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/make.bat b/fairseq-tools/fairseq/docs/make.bat new file mode 100644 index 00000000..baa9d02a --- /dev/null +++ b/fairseq-tools/fairseq/docs/make.bat @@ -0,0 +1,36 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=python -msphinx +) +set SOURCEDIR=. +set BUILDDIR=_build +set SPHINXPROJ=fairseq + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The Sphinx module was not found. Make sure you have Sphinx installed, + echo.then set the SPHINXBUILD environment variable to point to the full + echo.path of the 'sphinx-build' executable. Alternatively you may add the + echo.Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd diff --git a/fairseq-tools/fairseq/docs/models.rst b/fairseq-tools/fairseq/docs/models.rst new file mode 100644 index 00000000..054622d5 --- /dev/null +++ b/fairseq-tools/fairseq/docs/models.rst @@ -0,0 +1,104 @@ +.. role:: hidden + :class: hidden-section + +.. module:: fairseq.models + +.. _Models: + +Models +====== + +A Model defines the neural network's ``forward()`` method and encapsulates all +of the learnable parameters in the network. Each model also provides a set of +named *architectures* that define the precise network configuration (e.g., +embedding dimension, number of layers, etc.). + +Both the model type and architecture are selected via the ``--arch`` +command-line argument. Once selected, a model may expose additional command-line +arguments for further configuration. + +.. note:: + + All fairseq Models extend :class:`BaseFairseqModel`, which in turn extends + :class:`torch.nn.Module`. Thus any fairseq Model can be used as a + stand-alone Module in other PyTorch code. + + +Convolutional Neural Networks (CNN) +----------------------------------- + +.. module:: fairseq.models.fconv +.. autoclass:: fairseq.models.fconv.FConvModel + :members: +.. autoclass:: fairseq.models.fconv.FConvEncoder + :members: + :undoc-members: +.. autoclass:: fairseq.models.fconv.FConvDecoder + :members: + + +Long Short-Term Memory (LSTM) networks +-------------------------------------- + +.. module:: fairseq.models.lstm +.. autoclass:: fairseq.models.lstm.LSTMModel + :members: +.. autoclass:: fairseq.models.lstm.LSTMEncoder + :members: +.. autoclass:: fairseq.models.lstm.LSTMDecoder + :members: + + +Transformer (self-attention) networks +------------------------------------- + +.. module:: fairseq.models.transformer +.. autoclass:: fairseq.models.transformer.TransformerModel + :members: +.. autoclass:: fairseq.models.transformer.TransformerEncoder + :members: +.. autoclass:: fairseq.models.transformer.TransformerEncoderLayer + :members: +.. autoclass:: fairseq.models.transformer.TransformerDecoder + :members: +.. autoclass:: fairseq.models.transformer.TransformerDecoderLayer + :members: + + +Adding new models +----------------- + +.. currentmodule:: fairseq.models +.. autofunction:: fairseq.models.register_model +.. autofunction:: fairseq.models.register_model_architecture +.. autoclass:: fairseq.models.BaseFairseqModel + :members: + :undoc-members: +.. autoclass:: fairseq.models.FairseqEncoderDecoderModel + :members: + :undoc-members: +.. autoclass:: fairseq.models.FairseqEncoderModel + :members: + :undoc-members: +.. autoclass:: fairseq.models.FairseqLanguageModel + :members: + :undoc-members: +.. autoclass:: fairseq.models.FairseqMultiModel + :members: + :undoc-members: +.. autoclass:: fairseq.models.FairseqEncoder + :members: +.. autoclass:: fairseq.models.CompositeEncoder + :members: +.. autoclass:: fairseq.models.FairseqDecoder + :members: + + +.. _Incremental decoding: + +Incremental decoding +-------------------- + +.. autoclass:: fairseq.models.FairseqIncrementalDecoder + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/modules.rst b/fairseq-tools/fairseq/docs/modules.rst new file mode 100644 index 00000000..9631c93d --- /dev/null +++ b/fairseq-tools/fairseq/docs/modules.rst @@ -0,0 +1,9 @@ +Modules +======= + +Fairseq provides several stand-alone :class:`torch.nn.Module` classes that may +be helpful when implementing a new :class:`~fairseq.models.BaseFairseqModel`. + +.. automodule:: fairseq.modules + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/optim.rst b/fairseq-tools/fairseq/docs/optim.rst new file mode 100644 index 00000000..c3326456 --- /dev/null +++ b/fairseq-tools/fairseq/docs/optim.rst @@ -0,0 +1,38 @@ +.. role:: hidden + :class: hidden-section + +.. _optimizers: + +Optimizers +========== + +Optimizers update the Model parameters based on the gradients. + +.. automodule:: fairseq.optim + :members: + +.. autoclass:: fairseq.optim.FairseqOptimizer + :members: + :undoc-members: + +.. autoclass:: fairseq.optim.adadelta.Adadelta + :members: + :undoc-members: +.. autoclass:: fairseq.optim.adagrad.Adagrad + :members: + :undoc-members: +.. autoclass:: fairseq.optim.adafactor.FairseqAdafactor + :members: + :undoc-members: +.. autoclass:: fairseq.optim.adam.FairseqAdam + :members: + :undoc-members: +.. autoclass:: fairseq.optim.fp16_optimizer.FP16Optimizer + :members: + :undoc-members: +.. autoclass:: fairseq.optim.nag.FairseqNAG + :members: + :undoc-members: +.. autoclass:: fairseq.optim.sgd.SGD + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/overview.rst b/fairseq-tools/fairseq/docs/overview.rst new file mode 100644 index 00000000..026b3b5c --- /dev/null +++ b/fairseq-tools/fairseq/docs/overview.rst @@ -0,0 +1,74 @@ +Overview +======== + +Fairseq can be extended through user-supplied `plug-ins +`_. We support five kinds of +plug-ins: + +- :ref:`Models` define the neural network architecture and encapsulate all of the + learnable parameters. +- :ref:`Criterions` compute the loss function given the model outputs and targets. +- :ref:`Tasks` store dictionaries and provide helpers for loading/iterating over + Datasets, initializing the Model/Criterion and calculating the loss. +- :ref:`Optimizers` update the Model parameters based on the gradients. +- :ref:`Learning Rate Schedulers` update the learning rate over the course of + training. + +**Training Flow** + +Given a ``model``, ``criterion``, ``task``, ``optimizer`` and ``lr_scheduler``, +fairseq implements the following high-level training flow:: + + for epoch in range(num_epochs): + itr = task.get_batch_iterator(task.dataset('train')) + for num_updates, batch in enumerate(itr): + task.train_step(batch, model, criterion, optimizer) + average_and_clip_gradients() + optimizer.step() + lr_scheduler.step_update(num_updates) + lr_scheduler.step(epoch) + +where the default implementation for ``task.train_step`` is roughly:: + + def train_step(self, batch, model, criterion, optimizer, **unused): + loss = criterion(model, batch) + optimizer.backward(loss) + return loss + +**Registering new plug-ins** + +New plug-ins are *registered* through a set of ``@register`` function +decorators, for example:: + + @register_model('my_lstm') + class MyLSTM(FairseqEncoderDecoderModel): + (...) + +Once registered, new plug-ins can be used with the existing :ref:`Command-line +Tools`. See the Tutorial sections for more detailed walkthroughs of how to add +new plug-ins. + +**Loading plug-ins from another directory** + +New plug-ins can be defined in a custom module stored in the user system. In +order to import the module, and make the plugin available to *fairseq*, the +command line supports the ``--user-dir`` flag that can be used to specify a +custom location for additional modules to load into *fairseq*. + +For example, assuming this directory tree:: + + /home/user/my-module/ + └── __init__.py + +with ``__init__.py``:: + + from fairseq.models import register_model_architecture + from fairseq.models.transformer import transformer_vaswani_wmt_en_de_big + + @register_model_architecture('transformer', 'my_transformer') + def transformer_mmt_big(args): + transformer_vaswani_wmt_en_de_big(args) + +it is possible to invoke the :ref:`fairseq-train` script with the new architecture with:: + + fairseq-train ... --user-dir /home/user/my-module -a my_transformer --task translation diff --git a/fairseq-tools/fairseq/docs/requirements.txt b/fairseq-tools/fairseq/docs/requirements.txt new file mode 100644 index 00000000..c734a1f0 --- /dev/null +++ b/fairseq-tools/fairseq/docs/requirements.txt @@ -0,0 +1,2 @@ +sphinx<2.0 +sphinx-argparse diff --git a/fairseq-tools/fairseq/docs/tasks.rst b/fairseq-tools/fairseq/docs/tasks.rst new file mode 100644 index 00000000..5f65c3c8 --- /dev/null +++ b/fairseq-tools/fairseq/docs/tasks.rst @@ -0,0 +1,61 @@ +.. role:: hidden + :class: hidden-section + +.. module:: fairseq.tasks + +.. _Tasks: + +Tasks +===== + +Tasks store dictionaries and provide helpers for loading/iterating over +Datasets, initializing the Model/Criterion and calculating the loss. + +Tasks can be selected via the ``--task`` command-line argument. Once selected, a +task may expose additional command-line arguments for further configuration. + +Example usage:: + + # setup the task (e.g., load dictionaries) + task = fairseq.tasks.setup_task(args) + + # build model and criterion + model = task.build_model(args) + criterion = task.build_criterion(args) + + # load datasets + task.load_dataset('train') + task.load_dataset('valid') + + # iterate over mini-batches of data + batch_itr = task.get_batch_iterator( + task.dataset('train'), max_tokens=4096, + ) + for batch in batch_itr: + # compute the loss + loss, sample_size, logging_output = task.get_loss( + model, criterion, batch, + ) + loss.backward() + + +Translation +----------- + +.. autoclass:: fairseq.tasks.translation.TranslationTask + +.. _language modeling: + +Language Modeling +----------------- + +.. autoclass:: fairseq.tasks.language_modeling.LanguageModelingTask + + +Adding new tasks +---------------- + +.. autofunction:: fairseq.tasks.register_task +.. autoclass:: fairseq.tasks.FairseqTask + :members: + :undoc-members: diff --git a/fairseq-tools/fairseq/docs/tutorial_classifying_names.rst b/fairseq-tools/fairseq/docs/tutorial_classifying_names.rst new file mode 100644 index 00000000..40a3cb6f --- /dev/null +++ b/fairseq-tools/fairseq/docs/tutorial_classifying_names.rst @@ -0,0 +1,415 @@ +Tutorial: Classifying Names with a Character-Level RNN +====================================================== + +In this tutorial we will extend fairseq to support *classification* tasks. In +particular we will re-implement the PyTorch tutorial for `Classifying Names with +a Character-Level RNN `_ +in fairseq. It is recommended to quickly skim that tutorial before beginning +this one. + +This tutorial covers: + +1. **Preprocessing the data** to create dictionaries. +2. **Registering a new Model** that encodes an input sentence with a simple RNN + and predicts the output label. +3. **Registering a new Task** that loads our dictionaries and dataset. +4. **Training the Model** using the existing command-line tools. +5. **Writing an evaluation script** that imports fairseq and allows us to + interactively evaluate our model on new inputs. + + +1. Preprocessing the data +------------------------- + +The original tutorial provides raw data, but we'll work with a modified version +of the data that is already tokenized into characters and split into separate +train, valid and test sets. + +Download and extract the data from here: +`tutorial_names.tar.gz `_ + +Once extracted, let's preprocess the data using the :ref:`fairseq-preprocess` +command-line tool to create the dictionaries. While this tool is primarily +intended for sequence-to-sequence problems, we're able to reuse it here by +treating the label as a "target" sequence of length 1. We'll also output the +preprocessed files in "raw" format using the ``--dataset-impl`` option to +enhance readability: + +.. code-block:: console + + > fairseq-preprocess \ + --trainpref names/train --validpref names/valid --testpref names/test \ + --source-lang input --target-lang label \ + --destdir names-bin --dataset-impl raw + +After running the above command you should see a new directory, +:file:`names-bin/`, containing the dictionaries for *inputs* and *labels*. + + +2. Registering a new Model +-------------------------- + +Next we'll register a new model in fairseq that will encode an input sentence +with a simple RNN and predict the output label. Compared to the original PyTorch +tutorial, our version will also work with batches of data and GPU Tensors. + +First let's copy the simple RNN module implemented in the `PyTorch tutorial +`_. +Create a new file named :file:`fairseq/models/rnn_classifier.py` with the +following contents:: + + import torch + import torch.nn as nn + + class RNN(nn.Module): + + def __init__(self, input_size, hidden_size, output_size): + super(RNN, self).__init__() + + self.hidden_size = hidden_size + + self.i2h = nn.Linear(input_size + hidden_size, hidden_size) + self.i2o = nn.Linear(input_size + hidden_size, output_size) + self.softmax = nn.LogSoftmax(dim=1) + + def forward(self, input, hidden): + combined = torch.cat((input, hidden), 1) + hidden = self.i2h(combined) + output = self.i2o(combined) + output = self.softmax(output) + return output, hidden + + def initHidden(self): + return torch.zeros(1, self.hidden_size) + +We must also *register* this model with fairseq using the +:func:`~fairseq.models.register_model` function decorator. Once the model is +registered we'll be able to use it with the existing :ref:`Command-line Tools`. + +All registered models must implement the :class:`~fairseq.models.BaseFairseqModel` +interface, so we'll create a small wrapper class in the same file and register +it in fairseq with the name ``'rnn_classifier'``:: + + from fairseq.models import BaseFairseqModel, register_model + + # Note: the register_model "decorator" should immediately precede the + # definition of the Model class. + + @register_model('rnn_classifier') + class FairseqRNNClassifier(BaseFairseqModel): + + @staticmethod + def add_args(parser): + # Models can override this method to add new command-line arguments. + # Here we'll add a new command-line argument to configure the + # dimensionality of the hidden state. + parser.add_argument( + '--hidden-dim', type=int, metavar='N', + help='dimensionality of the hidden state', + ) + + @classmethod + def build_model(cls, args, task): + # Fairseq initializes models by calling the ``build_model()`` + # function. This provides more flexibility, since the returned model + # instance can be of a different type than the one that was called. + # In this case we'll just return a FairseqRNNClassifier instance. + + # Initialize our RNN module + rnn = RNN( + # We'll define the Task in the next section, but for now just + # notice that the task holds the dictionaries for the "source" + # (i.e., the input sentence) and "target" (i.e., the label). + input_size=len(task.source_dictionary), + hidden_size=args.hidden_dim, + output_size=len(task.target_dictionary), + ) + + # Return the wrapped version of the module + return FairseqRNNClassifier( + rnn=rnn, + input_vocab=task.source_dictionary, + ) + + def __init__(self, rnn, input_vocab): + super(FairseqRNNClassifier, self).__init__() + + self.rnn = rnn + self.input_vocab = input_vocab + + # The RNN module in the tutorial expects one-hot inputs, so we can + # precompute the identity matrix to help convert from indices to + # one-hot vectors. We register it as a buffer so that it is moved to + # the GPU when ``cuda()`` is called. + self.register_buffer('one_hot_inputs', torch.eye(len(input_vocab))) + + def forward(self, src_tokens, src_lengths): + # The inputs to the ``forward()`` function are determined by the + # Task, and in particular the ``'net_input'`` key in each + # mini-batch. We'll define the Task in the next section, but for + # now just know that *src_tokens* has shape `(batch, src_len)` and + # *src_lengths* has shape `(batch)`. + bsz, max_src_len = src_tokens.size() + + # Initialize the RNN hidden state. Compared to the original PyTorch + # tutorial we'll also handle batched inputs and work on the GPU. + hidden = self.rnn.initHidden() + hidden = hidden.repeat(bsz, 1) # expand for batched inputs + hidden = hidden.to(src_tokens.device) # move to GPU + + for i in range(max_src_len): + # WARNING: The inputs have padding, so we should mask those + # elements here so that padding doesn't affect the results. + # This is left as an exercise for the reader. The padding symbol + # is given by ``self.input_vocab.pad()`` and the unpadded length + # of each input is given by *src_lengths*. + + # One-hot encode a batch of input characters. + input = self.one_hot_inputs[src_tokens[:, i].long()] + + # Feed the input to our RNN. + output, hidden = self.rnn(input, hidden) + + # Return the final output state for making a prediction + return output + +Finally let's define a *named architecture* with the configuration for our +model. This is done with the :func:`~fairseq.models.register_model_architecture` +function decorator. Thereafter this named architecture can be used with the +``--arch`` command-line argument, e.g., ``--arch pytorch_tutorial_rnn``:: + + from fairseq.models import register_model_architecture + + # The first argument to ``register_model_architecture()`` should be the name + # of the model we registered above (i.e., 'rnn_classifier'). The function we + # register here should take a single argument *args* and modify it in-place + # to match the desired architecture. + + @register_model_architecture('rnn_classifier', 'pytorch_tutorial_rnn') + def pytorch_tutorial_rnn(args): + # We use ``getattr()`` to prioritize arguments that are explicitly given + # on the command-line, so that the defaults defined below are only used + # when no other value has been specified. + args.hidden_dim = getattr(args, 'hidden_dim', 128) + + +3. Registering a new Task +------------------------- + +Now we'll register a new :class:`~fairseq.tasks.FairseqTask` that will load our +dictionaries and dataset. Tasks can also control how the data is batched into +mini-batches, but in this tutorial we'll reuse the batching provided by +:class:`fairseq.data.LanguagePairDataset`. + +Create a new file named :file:`fairseq/tasks/simple_classification.py` with the +following contents:: + + import os + import torch + + from fairseq.data import Dictionary, LanguagePairDataset + from fairseq.tasks import FairseqTask, register_task + + + @register_task('simple_classification') + class SimpleClassificationTask(FairseqTask): + + @staticmethod + def add_args(parser): + # Add some command-line arguments for specifying where the data is + # located and the maximum supported input length. + parser.add_argument('data', metavar='FILE', + help='file prefix for data') + parser.add_argument('--max-positions', default=1024, type=int, + help='max input length') + + @classmethod + def setup_task(cls, args, **kwargs): + # Here we can perform any setup required for the task. This may include + # loading Dictionaries, initializing shared Embedding layers, etc. + # In this case we'll just load the Dictionaries. + input_vocab = Dictionary.load(os.path.join(args.data, 'dict.input.txt')) + label_vocab = Dictionary.load(os.path.join(args.data, 'dict.label.txt')) + print('| [input] dictionary: {} types'.format(len(input_vocab))) + print('| [label] dictionary: {} types'.format(len(label_vocab))) + + return SimpleClassificationTask(args, input_vocab, label_vocab) + + def __init__(self, args, input_vocab, label_vocab): + super().__init__(args) + self.input_vocab = input_vocab + self.label_vocab = label_vocab + + def load_dataset(self, split, **kwargs): + """Load a given dataset split (e.g., train, valid, test).""" + + prefix = os.path.join(self.args.data, '{}.input-label'.format(split)) + + # Read input sentences. + sentences, lengths = [], [] + with open(prefix + '.input', encoding='utf-8') as file: + for line in file: + sentence = line.strip() + + # Tokenize the sentence, splitting on spaces + tokens = self.input_vocab.encode_line( + sentence, add_if_not_exist=False, + ) + + sentences.append(tokens) + lengths.append(tokens.numel()) + + # Read labels. + labels = [] + with open(prefix + '.label', encoding='utf-8') as file: + for line in file: + label = line.strip() + labels.append( + # Convert label to a numeric ID. + torch.LongTensor([self.label_vocab.add_symbol(label)]) + ) + + assert len(sentences) == len(labels) + print('| {} {} {} examples'.format(self.args.data, split, len(sentences))) + + # We reuse LanguagePairDataset since classification can be modeled as a + # sequence-to-sequence task where the target sequence has length 1. + self.datasets[split] = LanguagePairDataset( + src=sentences, + src_sizes=lengths, + src_dict=self.input_vocab, + tgt=labels, + tgt_sizes=torch.ones(len(labels)), # targets have length 1 + tgt_dict=self.label_vocab, + left_pad_source=False, + # Since our target is a single class label, there's no need for + # teacher forcing. If we set this to ``True`` then our Model's + # ``forward()`` method would receive an additional argument called + # *prev_output_tokens* that would contain a shifted version of the + # target sequence. + input_feeding=False, + ) + + def max_positions(self): + """Return the max input length allowed by the task.""" + # The source should be less than *args.max_positions* and the "target" + # has max length 1. + return (self.args.max_positions, 1) + + @property + def source_dictionary(self): + """Return the source :class:`~fairseq.data.Dictionary`.""" + return self.input_vocab + + @property + def target_dictionary(self): + """Return the target :class:`~fairseq.data.Dictionary`.""" + return self.label_vocab + + # We could override this method if we wanted more control over how batches + # are constructed, but it's not necessary for this tutorial since we can + # reuse the batching provided by LanguagePairDataset. + # + # def get_batch_iterator( + # self, dataset, max_tokens=None, max_sentences=None, max_positions=None, + # ignore_invalid_inputs=False, required_batch_size_multiple=1, + # seed=1, num_shards=1, shard_id=0, num_workers=0, epoch=1, + # data_buffer_size=0, disable_iterator_cache=False, + # ): + # (...) + + +4. Training the Model +--------------------- + +Now we're ready to train the model. We can use the existing :ref:`fairseq-train` +command-line tool for this, making sure to specify our new Task (``--task +simple_classification``) and Model architecture (``--arch +pytorch_tutorial_rnn``): + +.. note:: + + You can also configure the dimensionality of the hidden state by passing the + ``--hidden-dim`` argument to :ref:`fairseq-train`. + +.. code-block:: console + + > fairseq-train names-bin \ + --task simple_classification \ + --arch pytorch_tutorial_rnn \ + --optimizer adam --lr 0.001 --lr-shrink 0.5 \ + --max-tokens 1000 + (...) + | epoch 027 | loss 1.200 | ppl 2.30 | wps 15728 | ups 119.4 | wpb 116 | bsz 116 | num_updates 3726 | lr 1.5625e-05 | gnorm 1.290 | clip 0% | oom 0 | wall 32 | train_wall 21 + | epoch 027 | valid on 'valid' subset | valid_loss 1.41304 | valid_ppl 2.66 | num_updates 3726 | best 1.41208 + | done training in 31.6 seconds + +The model files should appear in the :file:`checkpoints/` directory. + + +5. Writing an evaluation script +------------------------------- + +Finally we can write a short script to evaluate our model on new inputs. Create +a new file named :file:`eval_classifier.py` with the following contents:: + + from fairseq import checkpoint_utils, data, options, tasks + + # Parse command-line arguments for generation + parser = options.get_generation_parser(default_task='simple_classification') + args = options.parse_args_and_arch(parser) + + # Setup task + task = tasks.setup_task(args) + + # Load model + print('| loading model from {}'.format(args.path)) + models, _model_args = checkpoint_utils.load_model_ensemble([args.path], task=task) + model = models[0] + + while True: + sentence = input('\nInput: ') + + # Tokenize into characters + chars = ' '.join(list(sentence.strip())) + tokens = task.source_dictionary.encode_line( + chars, add_if_not_exist=False, + ) + + # Build mini-batch to feed to the model + batch = data.language_pair_dataset.collate( + samples=[{'id': -1, 'source': tokens}], # bsz = 1 + pad_idx=task.source_dictionary.pad(), + eos_idx=task.source_dictionary.eos(), + left_pad_source=False, + input_feeding=False, + ) + + # Feed batch to the model and get predictions + preds = model(**batch['net_input']) + + # Print top 3 predictions and their log-probabilities + top_scores, top_labels = preds[0].topk(k=3) + for score, label_idx in zip(top_scores, top_labels): + label_name = task.target_dictionary.string([label_idx]) + print('({:.2f})\t{}'.format(score, label_name)) + +Now we can evaluate our model interactively. Note that we have included the +original data path (:file:`names-bin/`) so that the dictionaries can be loaded: + +.. code-block:: console + + > python eval_classifier.py names-bin --path checkpoints/checkpoint_best.pt + | [input] dictionary: 64 types + | [label] dictionary: 24 types + | loading model from checkpoints/checkpoint_best.pt + + Input: Satoshi + (-0.61) Japanese + (-1.20) Arabic + (-2.86) Italian + + Input: Sinbad + (-0.30) Arabic + (-1.76) English + (-4.08) Russian diff --git a/fairseq-tools/fairseq/docs/tutorial_simple_lstm.rst b/fairseq-tools/fairseq/docs/tutorial_simple_lstm.rst new file mode 100644 index 00000000..f5298850 --- /dev/null +++ b/fairseq-tools/fairseq/docs/tutorial_simple_lstm.rst @@ -0,0 +1,518 @@ +Tutorial: Simple LSTM +===================== + +In this tutorial we will extend fairseq by adding a new +:class:`~fairseq.models.FairseqEncoderDecoderModel` that encodes a source +sentence with an LSTM and then passes the final hidden state to a second LSTM +that decodes the target sentence (without attention). + +This tutorial covers: + +1. **Writing an Encoder and Decoder** to encode/decode the source/target + sentence, respectively. +2. **Registering a new Model** so that it can be used with the existing + :ref:`Command-line tools`. +3. **Training the Model** using the existing command-line tools. +4. **Making generation faster** by modifying the Decoder to use + :ref:`Incremental decoding`. + + +1. Building an Encoder and Decoder +---------------------------------- + +In this section we'll define a simple LSTM Encoder and Decoder. All Encoders +should implement the :class:`~fairseq.models.FairseqEncoder` interface and +Decoders should implement the :class:`~fairseq.models.FairseqDecoder` interface. +These interfaces themselves extend :class:`torch.nn.Module`, so FairseqEncoders +and FairseqDecoders can be written and used in the same ways as ordinary PyTorch +Modules. + + +Encoder +~~~~~~~ + +Our Encoder will embed the tokens in the source sentence, feed them to a +:class:`torch.nn.LSTM` and return the final hidden state. To create our encoder +save the following in a new file named :file:`fairseq/models/simple_lstm.py`:: + + import torch.nn as nn + from fairseq import utils + from fairseq.models import FairseqEncoder + + class SimpleLSTMEncoder(FairseqEncoder): + + def __init__( + self, args, dictionary, embed_dim=128, hidden_dim=128, dropout=0.1, + ): + super().__init__(dictionary) + self.args = args + + # Our encoder will embed the inputs before feeding them to the LSTM. + self.embed_tokens = nn.Embedding( + num_embeddings=len(dictionary), + embedding_dim=embed_dim, + padding_idx=dictionary.pad(), + ) + self.dropout = nn.Dropout(p=dropout) + + # We'll use a single-layer, unidirectional LSTM for simplicity. + self.lstm = nn.LSTM( + input_size=embed_dim, + hidden_size=hidden_dim, + num_layers=1, + bidirectional=False, + batch_first=True, + ) + + def forward(self, src_tokens, src_lengths): + # The inputs to the ``forward()`` function are determined by the + # Task, and in particular the ``'net_input'`` key in each + # mini-batch. We discuss Tasks in the next tutorial, but for now just + # know that *src_tokens* has shape `(batch, src_len)` and *src_lengths* + # has shape `(batch)`. + + # Note that the source is typically padded on the left. This can be + # configured by adding the `--left-pad-source "False"` command-line + # argument, but here we'll make the Encoder handle either kind of + # padding by converting everything to be right-padded. + if self.args.left_pad_source: + # Convert left-padding to right-padding. + src_tokens = utils.convert_padding_direction( + src_tokens, + padding_idx=self.dictionary.pad(), + left_to_right=True + ) + + # Embed the source. + x = self.embed_tokens(src_tokens) + + # Apply dropout. + x = self.dropout(x) + + # Pack the sequence into a PackedSequence object to feed to the LSTM. + x = nn.utils.rnn.pack_padded_sequence(x, src_lengths, batch_first=True) + + # Get the output from the LSTM. + _outputs, (final_hidden, _final_cell) = self.lstm(x) + + # Return the Encoder's output. This can be any object and will be + # passed directly to the Decoder. + return { + # this will have shape `(bsz, hidden_dim)` + 'final_hidden': final_hidden.squeeze(0), + } + + # Encoders are required to implement this method so that we can rearrange + # the order of the batch elements during inference (e.g., beam search). + def reorder_encoder_out(self, encoder_out, new_order): + """ + Reorder encoder output according to `new_order`. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + `encoder_out` rearranged according to `new_order` + """ + final_hidden = encoder_out['final_hidden'] + return { + 'final_hidden': final_hidden.index_select(0, new_order), + } + + +Decoder +~~~~~~~ + +Our Decoder will predict the next word, conditioned on the Encoder's final +hidden state and an embedded representation of the previous target word -- which +is sometimes called *teacher forcing*. More specifically, we'll use a +:class:`torch.nn.LSTM` to produce a sequence of hidden states that we'll project +to the size of the output vocabulary to predict each target word. + +:: + + import torch + from fairseq.models import FairseqDecoder + + class SimpleLSTMDecoder(FairseqDecoder): + + def __init__( + self, dictionary, encoder_hidden_dim=128, embed_dim=128, hidden_dim=128, + dropout=0.1, + ): + super().__init__(dictionary) + + # Our decoder will embed the inputs before feeding them to the LSTM. + self.embed_tokens = nn.Embedding( + num_embeddings=len(dictionary), + embedding_dim=embed_dim, + padding_idx=dictionary.pad(), + ) + self.dropout = nn.Dropout(p=dropout) + + # We'll use a single-layer, unidirectional LSTM for simplicity. + self.lstm = nn.LSTM( + # For the first layer we'll concatenate the Encoder's final hidden + # state with the embedded target tokens. + input_size=encoder_hidden_dim + embed_dim, + hidden_size=hidden_dim, + num_layers=1, + bidirectional=False, + ) + + # Define the output projection. + self.output_projection = nn.Linear(hidden_dim, len(dictionary)) + + # During training Decoders are expected to take the entire target sequence + # (shifted right by one position) and produce logits over the vocabulary. + # The *prev_output_tokens* tensor begins with the end-of-sentence symbol, + # ``dictionary.eos()``, followed by the target sequence. + def forward(self, prev_output_tokens, encoder_out): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (Tensor, optional): output from the encoder, used for + encoder-side attention + + Returns: + tuple: + - the last decoder layer's output of shape + `(batch, tgt_len, vocab)` + - the last decoder layer's attention weights of shape + `(batch, tgt_len, src_len)` + """ + bsz, tgt_len = prev_output_tokens.size() + + # Extract the final hidden state from the Encoder. + final_encoder_hidden = encoder_out['final_hidden'] + + # Embed the target sequence, which has been shifted right by one + # position and now starts with the end-of-sentence symbol. + x = self.embed_tokens(prev_output_tokens) + + # Apply dropout. + x = self.dropout(x) + + # Concatenate the Encoder's final hidden state to *every* embedded + # target token. + x = torch.cat( + [x, final_encoder_hidden.unsqueeze(1).expand(bsz, tgt_len, -1)], + dim=2, + ) + + # Using PackedSequence objects in the Decoder is harder than in the + # Encoder, since the targets are not sorted in descending length order, + # which is a requirement of ``pack_padded_sequence()``. Instead we'll + # feed nn.LSTM directly. + initial_state = ( + final_encoder_hidden.unsqueeze(0), # hidden + torch.zeros_like(final_encoder_hidden).unsqueeze(0), # cell + ) + output, _ = self.lstm( + x.transpose(0, 1), # convert to shape `(tgt_len, bsz, dim)` + initial_state, + ) + x = output.transpose(0, 1) # convert to shape `(bsz, tgt_len, hidden)` + + # Project the outputs to the size of the vocabulary. + x = self.output_projection(x) + + # Return the logits and ``None`` for the attention weights + return x, None + + +2. Registering the Model +------------------------ + +Now that we've defined our Encoder and Decoder we must *register* our model with +fairseq using the :func:`~fairseq.models.register_model` function decorator. +Once the model is registered we'll be able to use it with the existing +:ref:`Command-line Tools`. + +All registered models must implement the +:class:`~fairseq.models.BaseFairseqModel` interface. For sequence-to-sequence +models (i.e., any model with a single Encoder and Decoder), we can instead +implement the :class:`~fairseq.models.FairseqEncoderDecoderModel` interface. + +Create a small wrapper class in the same file and register it in fairseq with +the name ``'simple_lstm'``:: + + from fairseq.models import FairseqEncoderDecoderModel, register_model + + # Note: the register_model "decorator" should immediately precede the + # definition of the Model class. + + @register_model('simple_lstm') + class SimpleLSTMModel(FairseqEncoderDecoderModel): + + @staticmethod + def add_args(parser): + # Models can override this method to add new command-line arguments. + # Here we'll add some new command-line arguments to configure dropout + # and the dimensionality of the embeddings and hidden states. + parser.add_argument( + '--encoder-embed-dim', type=int, metavar='N', + help='dimensionality of the encoder embeddings', + ) + parser.add_argument( + '--encoder-hidden-dim', type=int, metavar='N', + help='dimensionality of the encoder hidden state', + ) + parser.add_argument( + '--encoder-dropout', type=float, default=0.1, + help='encoder dropout probability', + ) + parser.add_argument( + '--decoder-embed-dim', type=int, metavar='N', + help='dimensionality of the decoder embeddings', + ) + parser.add_argument( + '--decoder-hidden-dim', type=int, metavar='N', + help='dimensionality of the decoder hidden state', + ) + parser.add_argument( + '--decoder-dropout', type=float, default=0.1, + help='decoder dropout probability', + ) + + @classmethod + def build_model(cls, args, task): + # Fairseq initializes models by calling the ``build_model()`` + # function. This provides more flexibility, since the returned model + # instance can be of a different type than the one that was called. + # In this case we'll just return a SimpleLSTMModel instance. + + # Initialize our Encoder and Decoder. + encoder = SimpleLSTMEncoder( + args=args, + dictionary=task.source_dictionary, + embed_dim=args.encoder_embed_dim, + hidden_dim=args.encoder_hidden_dim, + dropout=args.encoder_dropout, + ) + decoder = SimpleLSTMDecoder( + dictionary=task.target_dictionary, + encoder_hidden_dim=args.encoder_hidden_dim, + embed_dim=args.decoder_embed_dim, + hidden_dim=args.decoder_hidden_dim, + dropout=args.decoder_dropout, + ) + model = SimpleLSTMModel(encoder, decoder) + + # Print the model architecture. + print(model) + + return model + + # We could override the ``forward()`` if we wanted more control over how + # the encoder and decoder interact, but it's not necessary for this + # tutorial since we can inherit the default implementation provided by + # the FairseqEncoderDecoderModel base class, which looks like: + # + # def forward(self, src_tokens, src_lengths, prev_output_tokens): + # encoder_out = self.encoder(src_tokens, src_lengths) + # decoder_out = self.decoder(prev_output_tokens, encoder_out) + # return decoder_out + +Finally let's define a *named architecture* with the configuration for our +model. This is done with the :func:`~fairseq.models.register_model_architecture` +function decorator. Thereafter this named architecture can be used with the +``--arch`` command-line argument, e.g., ``--arch tutorial_simple_lstm``:: + + from fairseq.models import register_model_architecture + + # The first argument to ``register_model_architecture()`` should be the name + # of the model we registered above (i.e., 'simple_lstm'). The function we + # register here should take a single argument *args* and modify it in-place + # to match the desired architecture. + + @register_model_architecture('simple_lstm', 'tutorial_simple_lstm') + def tutorial_simple_lstm(args): + # We use ``getattr()`` to prioritize arguments that are explicitly given + # on the command-line, so that the defaults defined below are only used + # when no other value has been specified. + args.encoder_embed_dim = getattr(args, 'encoder_embed_dim', 256) + args.encoder_hidden_dim = getattr(args, 'encoder_hidden_dim', 256) + args.decoder_embed_dim = getattr(args, 'decoder_embed_dim', 256) + args.decoder_hidden_dim = getattr(args, 'decoder_hidden_dim', 256) + + +3. Training the Model +--------------------- + +Now we're ready to train the model. We can use the existing :ref:`fairseq-train` +command-line tool for this, making sure to specify our new Model architecture +(``--arch tutorial_simple_lstm``). + +.. note:: + + Make sure you've already preprocessed the data from the IWSLT example in the + :file:`examples/translation/` directory. + +.. code-block:: console + + > fairseq-train data-bin/iwslt14.tokenized.de-en \ + --arch tutorial_simple_lstm \ + --encoder-dropout 0.2 --decoder-dropout 0.2 \ + --optimizer adam --lr 0.005 --lr-shrink 0.5 \ + --max-tokens 12000 + (...) + | epoch 052 | loss 4.027 | ppl 16.30 | wps 420805 | ups 39.7 | wpb 9841 | bsz 400 | num_updates 20852 | lr 1.95313e-05 | gnorm 0.218 | clip 0% | oom 0 | wall 529 | train_wall 396 + | epoch 052 | valid on 'valid' subset | valid_loss 4.74989 | valid_ppl 26.91 | num_updates 20852 | best 4.74954 + +The model files should appear in the :file:`checkpoints/` directory. While this +model architecture is not very good, we can use the :ref:`fairseq-generate` script to +generate translations and compute our BLEU score over the test set: + +.. code-block:: console + + > fairseq-generate data-bin/iwslt14.tokenized.de-en \ + --path checkpoints/checkpoint_best.pt \ + --beam 5 \ + --remove-bpe + (...) + | Translated 6750 sentences (153132 tokens) in 17.3s (389.12 sentences/s, 8827.68 tokens/s) + | Generate test with beam=5: BLEU4 = 8.18, 38.8/12.1/4.7/2.0 (BP=1.000, ratio=1.066, syslen=139865, reflen=131146) + + +4. Making generation faster +--------------------------- + +While autoregressive generation from sequence-to-sequence models is inherently +slow, our implementation above is especially slow because it recomputes the +entire sequence of Decoder hidden states for every output token (i.e., it is +``O(n^2)``). We can make this significantly faster by instead caching the +previous hidden states. + +In fairseq this is called :ref:`Incremental decoding`. Incremental decoding is a +special mode at inference time where the Model only receives a single timestep +of input corresponding to the immediately previous output token (for teacher +forcing) and must produce the next output incrementally. Thus the model must +cache any long-term state that is needed about the sequence, e.g., hidden +states, convolutional states, etc. + +To implement incremental decoding we will modify our model to implement the +:class:`~fairseq.models.FairseqIncrementalDecoder` interface. Compared to the +standard :class:`~fairseq.models.FairseqDecoder` interface, the incremental +decoder interface allows ``forward()`` methods to take an extra keyword argument +(*incremental_state*) that can be used to cache state across time-steps. + +Let's replace our ``SimpleLSTMDecoder`` with an incremental one:: + + import torch + from fairseq.models import FairseqIncrementalDecoder + + class SimpleLSTMDecoder(FairseqIncrementalDecoder): + + def __init__( + self, dictionary, encoder_hidden_dim=128, embed_dim=128, hidden_dim=128, + dropout=0.1, + ): + # This remains the same as before. + super().__init__(dictionary) + self.embed_tokens = nn.Embedding( + num_embeddings=len(dictionary), + embedding_dim=embed_dim, + padding_idx=dictionary.pad(), + ) + self.dropout = nn.Dropout(p=dropout) + self.lstm = nn.LSTM( + input_size=encoder_hidden_dim + embed_dim, + hidden_size=hidden_dim, + num_layers=1, + bidirectional=False, + ) + self.output_projection = nn.Linear(hidden_dim, len(dictionary)) + + # We now take an additional kwarg (*incremental_state*) for caching the + # previous hidden and cell states. + def forward(self, prev_output_tokens, encoder_out, incremental_state=None): + if incremental_state is not None: + # If the *incremental_state* argument is not ``None`` then we are + # in incremental inference mode. While *prev_output_tokens* will + # still contain the entire decoded prefix, we will only use the + # last step and assume that the rest of the state is cached. + prev_output_tokens = prev_output_tokens[:, -1:] + + # This remains the same as before. + bsz, tgt_len = prev_output_tokens.size() + final_encoder_hidden = encoder_out['final_hidden'] + x = self.embed_tokens(prev_output_tokens) + x = self.dropout(x) + x = torch.cat( + [x, final_encoder_hidden.unsqueeze(1).expand(bsz, tgt_len, -1)], + dim=2, + ) + + # We will now check the cache and load the cached previous hidden and + # cell states, if they exist, otherwise we will initialize them to + # zeros (as before). We will use the ``utils.get_incremental_state()`` + # and ``utils.set_incremental_state()`` helpers. + initial_state = utils.get_incremental_state( + self, incremental_state, 'prev_state', + ) + if initial_state is None: + # first time initialization, same as the original version + initial_state = ( + final_encoder_hidden.unsqueeze(0), # hidden + torch.zeros_like(final_encoder_hidden).unsqueeze(0), # cell + ) + + # Run one step of our LSTM. + output, latest_state = self.lstm(x.transpose(0, 1), initial_state) + + # Update the cache with the latest hidden and cell states. + utils.set_incremental_state( + self, incremental_state, 'prev_state', latest_state, + ) + + # This remains the same as before + x = output.transpose(0, 1) + x = self.output_projection(x) + return x, None + + # The ``FairseqIncrementalDecoder`` interface also requires implementing a + # ``reorder_incremental_state()`` method, which is used during beam search + # to select and reorder the incremental state. + def reorder_incremental_state(self, incremental_state, new_order): + # Load the cached state. + prev_state = utils.get_incremental_state( + self, incremental_state, 'prev_state', + ) + + # Reorder batches according to *new_order*. + reordered_state = ( + prev_state[0].index_select(1, new_order), # hidden + prev_state[1].index_select(1, new_order), # cell + ) + + # Update the cached state. + utils.set_incremental_state( + self, incremental_state, 'prev_state', reordered_state, + ) + +Finally, we can rerun generation and observe the speedup: + +.. code-block:: console + + # Before + + > fairseq-generate data-bin/iwslt14.tokenized.de-en \ + --path checkpoints/checkpoint_best.pt \ + --beam 5 \ + --remove-bpe + (...) + | Translated 6750 sentences (153132 tokens) in 17.3s (389.12 sentences/s, 8827.68 tokens/s) + | Generate test with beam=5: BLEU4 = 8.18, 38.8/12.1/4.7/2.0 (BP=1.000, ratio=1.066, syslen=139865, reflen=131146) + + # After + + > fairseq-generate data-bin/iwslt14.tokenized.de-en \ + --path checkpoints/checkpoint_best.pt \ + --beam 5 \ + --remove-bpe + (...) + | Translated 6750 sentences (153132 tokens) in 5.5s (1225.54 sentences/s, 27802.94 tokens/s) + | Generate test with beam=5: BLEU4 = 8.18, 38.8/12.1/4.7/2.0 (BP=1.000, ratio=1.066, syslen=139865, reflen=131146) diff --git a/fairseq-tools/fairseq/examples/.gitignore b/fairseq-tools/fairseq/examples/.gitignore new file mode 100644 index 00000000..1ef816f2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/.gitignore @@ -0,0 +1,2 @@ +!*/*.sh +!*/*.md diff --git a/fairseq-tools/fairseq/examples/__init__.py b/fairseq-tools/fairseq/examples/__init__.py new file mode 100644 index 00000000..209ded36 --- /dev/null +++ b/fairseq-tools/fairseq/examples/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +__version__ = "0.10.2" + +import examples.noisychannel # noqa diff --git a/fairseq-tools/fairseq/examples/backtranslation/README.md b/fairseq-tools/fairseq/examples/backtranslation/README.md new file mode 100644 index 00000000..73675f11 --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/README.md @@ -0,0 +1,297 @@ +# Understanding Back-Translation at Scale (Edunov et al., 2018) + +This page includes pre-trained models from the paper [Understanding Back-Translation at Scale (Edunov et al., 2018)](https://arxiv.org/abs/1808.09381). + +## Pre-trained models + +Model | Description | Dataset | Download +---|---|---|--- +`transformer.wmt18.en-de` | Transformer
([Edunov et al., 2018](https://arxiv.org/abs/1808.09381))
WMT'18 winner | [WMT'18 English-German](http://www.statmt.org/wmt18/translation-task.html) | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt18.en-de.ensemble.tar.gz)
See NOTE in the archive + +## Example usage (torch.hub) + +We require a few additional Python dependencies for preprocessing: +```bash +pip install subword_nmt sacremoses +``` + +Then to generate translations from the full model ensemble: +```python +import torch + +# List available models +torch.hub.list('pytorch/fairseq') # [..., 'transformer.wmt18.en-de', ... ] + +# Load the WMT'18 En-De ensemble +en2de_ensemble = torch.hub.load( + 'pytorch/fairseq', 'transformer.wmt18.en-de', + checkpoint_file='wmt18.model1.pt:wmt18.model2.pt:wmt18.model3.pt:wmt18.model4.pt:wmt18.model5.pt', + tokenizer='moses', bpe='subword_nmt') + +# The ensemble contains 5 models +len(en2de_ensemble.models) +# 5 + +# Translate +en2de_ensemble.translate('Hello world!') +# 'Hallo Welt!' +``` + +## Training your own model (WMT'18 English-German) + +The following instructions can be adapted to reproduce the models from the paper. + + +#### Step 1. Prepare parallel data and optionally train a baseline (English-German) model + +First download and preprocess the data: +```bash +# Download and prepare the data +cd examples/backtranslation/ +bash prepare-wmt18en2de.sh +cd ../.. + +# Binarize the data +TEXT=examples/backtranslation/wmt18_en_de +fairseq-preprocess \ + --joined-dictionary \ + --source-lang en --target-lang de \ + --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \ + --destdir data-bin/wmt18_en_de --thresholdtgt 0 --thresholdsrc 0 \ + --workers 20 + +# Copy the BPE code into the data-bin directory for future use +cp examples/backtranslation/wmt18_en_de/code data-bin/wmt18_en_de/code +``` + +(Optionally) Train a baseline model (English-German) using just the parallel data: +```bash +CHECKPOINT_DIR=checkpoints_en_de_parallel +fairseq-train --fp16 \ + data-bin/wmt18_en_de \ + --source-lang en --target-lang de \ + --arch transformer_wmt_en_de_big --share-all-embeddings \ + --dropout 0.3 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr 0.001 --lr-scheduler inverse_sqrt --warmup-updates 4000 \ + --max-tokens 3584 --update-freq 16 \ + --max-update 30000 \ + --save-dir $CHECKPOINT_DIR +# Note: the above command assumes 8 GPUs. Adjust `--update-freq` if you have a +# different number of GPUs. +``` + +Average the last 10 checkpoints: +```bash +python scripts/average_checkpoints.py \ + --inputs $CHECKPOINT_DIR \ + --num-epoch-checkpoints 10 \ + --output $CHECKPOINT_DIR/checkpoint.avg10.pt +``` + +Evaluate BLEU: +```bash +# tokenized BLEU on newstest2017: +bash examples/backtranslation/tokenized_bleu.sh \ + wmt17 \ + en-de \ + data-bin/wmt18_en_de \ + data-bin/wmt18_en_de/code \ + $CHECKPOINT_DIR/checkpoint.avg10.pt +# BLEU4 = 29.57, 60.9/35.4/22.9/15.5 (BP=1.000, ratio=1.014, syslen=63049, reflen=62152) +# compare to 29.46 in Table 1, which is also for tokenized BLEU + +# generally it's better to report (detokenized) sacrebleu though: +bash examples/backtranslation/sacrebleu.sh \ + wmt17 \ + en-de \ + data-bin/wmt18_en_de \ + data-bin/wmt18_en_de/code \ + $CHECKPOINT_DIR/checkpoint.avg10.pt +# BLEU+case.mixed+lang.en-de+numrefs.1+smooth.exp+test.wmt17+tok.13a+version.1.4.3 = 29.0 60.6/34.7/22.4/14.9 (BP = 1.000 ratio = 1.013 hyp_len = 62099 ref_len = 61287) +``` + + +#### Step 2. Back-translate monolingual German data + +Train a reverse model (German-English) to do the back-translation: +```bash +CHECKPOINT_DIR=checkpoints_de_en_parallel +fairseq-train --fp16 \ + data-bin/wmt18_en_de \ + --source-lang de --target-lang en \ + --arch transformer_wmt_en_de_big --share-all-embeddings \ + --dropout 0.3 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr 0.001 --lr-scheduler inverse_sqrt --warmup-updates 4000 \ + --max-tokens 3584 --update-freq 16 \ + --max-update 30000 \ + --save-dir $CHECKPOINT_DIR +# Note: the above command assumes 8 GPUs. Adjust `--update-freq` if you have a +# different number of GPUs. +``` + +Let's evaluate the back-translation (BT) model to make sure it is well trained: +```bash +bash examples/backtranslation/sacrebleu.sh \ + wmt17 \ + de-en \ + data-bin/wmt18_en_de \ + data-bin/wmt18_en_de/code \ + $CHECKPOINT_DIR/checkpoint_best.py +# BLEU+case.mixed+lang.de-en+numrefs.1+smooth.exp+test.wmt17+tok.13a+version.1.4.3 = 34.9 66.9/41.8/28.5/19.9 (BP = 0.983 ratio = 0.984 hyp_len = 63342 ref_len = 64399) +# compare to the best system from WMT'17 which scored 35.1: http://matrix.statmt.org/matrix/systems_list/1868 +``` + +Next prepare the monolingual data: +```bash +# Download and prepare the monolingual data +# By default the script samples 25M monolingual sentences, which after +# deduplication should be just over 24M sentences. These are split into 25 +# shards, each with 1M sentences (except for the last shard). +cd examples/backtranslation/ +bash prepare-de-monolingual.sh +cd ../.. + +# Binarize each shard of the monolingual data +TEXT=examples/backtranslation/wmt18_de_mono +for SHARD in $(seq -f "%02g" 0 24); do \ + fairseq-preprocess \ + --only-source \ + --source-lang de --target-lang en \ + --joined-dictionary \ + --srcdict data-bin/wmt18_en_de/dict.de.txt \ + --testpref $TEXT/bpe.monolingual.dedup.${SHARD} \ + --destdir data-bin/wmt18_de_mono/shard${SHARD} \ + --workers 20; \ + cp data-bin/wmt18_en_de/dict.en.txt data-bin/wmt18_de_mono/shard${SHARD}/; \ +done +``` + +Now we're ready to perform back-translation over the monolingual data. The +following command generates via sampling, but it's possible to use greedy +decoding (`--beam 1`), beam search (`--beam 5`), +top-k sampling (`--sampling --beam 1 --sampling-topk 10`), etc.: +```bash +mkdir backtranslation_output +for SHARD in $(seq -f "%02g" 0 24); do \ + fairseq-generate --fp16 \ + data-bin/wmt18_de_mono/shard${SHARD} \ + --path $CHECKPOINT_DIR/checkpoint_best.pt \ + --skip-invalid-size-inputs-valid-test \ + --max-tokens 4096 \ + --sampling --beam 1 \ + > backtranslation_output/sampling.shard${SHARD}.out; \ +done +``` + +After BT, use the `extract_bt_data.py` script to re-combine the shards, extract +the back-translations and apply length ratio filters: +```bash +python examples/backtranslation/extract_bt_data.py \ + --minlen 1 --maxlen 250 --ratio 1.5 \ + --output backtranslation_output/bt_data --srclang en --tgtlang de \ + backtranslation_output/sampling.shard*.out + +# Ensure lengths are the same: +# wc -l backtranslation_output/bt_data.{en,de} +# 21795614 backtranslation_output/bt_data.en +# 21795614 backtranslation_output/bt_data.de +# 43591228 total +``` + +Binarize the filtered BT data and combine it with the parallel data: +```bash +TEXT=backtranslation_output +fairseq-preprocess \ + --source-lang en --target-lang de \ + --joined-dictionary \ + --srcdict data-bin/wmt18_en_de/dict.en.txt \ + --trainpref $TEXT/bt_data \ + --destdir data-bin/wmt18_en_de_bt \ + --workers 20 + +# We want to train on the combined data, so we'll symlink the parallel + BT data +# in the wmt18_en_de_para_plus_bt directory. We link the parallel data as "train" +# and the BT data as "train1", so that fairseq will combine them automatically +# and so that we can use the `--upsample-primary` option to upsample the +# parallel data (if desired). +PARA_DATA=$(readlink -f data-bin/wmt18_en_de) +BT_DATA=$(readlink -f data-bin/wmt18_en_de_bt) +COMB_DATA=data-bin/wmt18_en_de_para_plus_bt +mkdir -p $COMB_DATA +for LANG in en de; do \ + ln -s ${PARA_DATA}/dict.$LANG.txt ${COMB_DATA}/dict.$LANG.txt; \ + for EXT in bin idx; do \ + ln -s ${PARA_DATA}/train.en-de.$LANG.$EXT ${COMB_DATA}/train.en-de.$LANG.$EXT; \ + ln -s ${BT_DATA}/train.en-de.$LANG.$EXT ${COMB_DATA}/train1.en-de.$LANG.$EXT; \ + ln -s ${PARA_DATA}/valid.en-de.$LANG.$EXT ${COMB_DATA}/valid.en-de.$LANG.$EXT; \ + ln -s ${PARA_DATA}/test.en-de.$LANG.$EXT ${COMB_DATA}/test.en-de.$LANG.$EXT; \ + done; \ +done +``` + + +#### 3. Train an English-German model over the combined parallel + BT data + +Finally we can train a model over the parallel + BT data: +```bash +CHECKPOINT_DIR=checkpoints_en_de_parallel_plus_bt +fairseq-train --fp16 \ + data-bin/wmt18_en_de_para_plus_bt \ + --upsample-primary 16 \ + --source-lang en --target-lang de \ + --arch transformer_wmt_en_de_big --share-all-embeddings \ + --dropout 0.3 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr 0.0007 --lr-scheduler inverse_sqrt --warmup-updates 4000 \ + --max-tokens 3584 --update-freq 16 \ + --max-update 100000 \ + --save-dir $CHECKPOINT_DIR +# Note: the above command assumes 8 GPUs. Adjust `--update-freq` if you have a +# different number of GPUs. +``` + +Average the last 10 checkpoints: +```bash +python scripts/average_checkpoints.py \ + --inputs $CHECKPOINT_DIR \ + --num-epoch-checkpoints 10 \ + --output $CHECKPOINT_DIR/checkpoint.avg10.pt +``` + +Evaluate BLEU: +```bash +# tokenized BLEU on newstest2017: +bash examples/backtranslation/tokenized_bleu.sh \ + wmt17 \ + en-de \ + data-bin/wmt18_en_de \ + data-bin/wmt18_en_de/code \ + $CHECKPOINT_DIR/checkpoint.avg10.pt +# BLEU4 = 32.35, 64.4/38.9/26.2/18.3 (BP=0.977, ratio=0.977, syslen=60729, reflen=62152) +# compare to 32.35 in Table 1, which is also for tokenized BLEU + +# generally it's better to report (detokenized) sacrebleu: +bash examples/backtranslation/sacrebleu.sh \ + wmt17 \ + en-de \ + data-bin/wmt18_en_de \ + data-bin/wmt18_en_de/code \ + $CHECKPOINT_DIR/checkpoint.avg10.pt +# BLEU+case.mixed+lang.en-de+numrefs.1+smooth.exp+test.wmt17+tok.13a+version.1.4.3 = 31.5 64.3/38.2/25.6/17.6 (BP = 0.971 ratio = 0.971 hyp_len = 59515 ref_len = 61287) +``` + + +## Citation +```bibtex +@inproceedings{edunov2018backtranslation, + title = {Understanding Back-Translation at Scale}, + author = {Edunov, Sergey and Ott, Myle and Auli, Michael and Grangier, David}, + booktitle = {Conference of the Association for Computational Linguistics (ACL)}, + year = 2018, +} +``` diff --git a/fairseq-tools/fairseq/examples/backtranslation/deduplicate_lines.py b/fairseq-tools/fairseq/examples/backtranslation/deduplicate_lines.py new file mode 100644 index 00000000..50e45832 --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/deduplicate_lines.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import fileinput +import hashlib +import sys +from multiprocessing import Pool + + +def get_hashes_and_lines(raw_line): + hash = hashlib.md5(raw_line).hexdigest() + return hash, raw_line + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--workers", type=int, default=10) + parser.add_argument("files", nargs="*", help="input files") + args = parser.parse_args() + + seen = set() + with fileinput.input(args.files, mode="rb") as h: + pool = Pool(args.workers) + results = pool.imap_unordered(get_hashes_and_lines, h, 1000) + for i, (hash, raw_line) in enumerate(results): + if hash not in seen: + seen.add(hash) + sys.stdout.buffer.write(raw_line) + if i % 1000000 == 0: + print(i, file=sys.stderr, end="", flush=True) + elif i % 100000 == 0: + print(".", file=sys.stderr, end="", flush=True) + print(file=sys.stderr, flush=True) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/backtranslation/extract_bt_data.py b/fairseq-tools/fairseq/examples/backtranslation/extract_bt_data.py new file mode 100644 index 00000000..e766391e --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/extract_bt_data.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import fileinput + +from tqdm import tqdm + + +def main(): + parser = argparse.ArgumentParser( + description=( + "Extract back-translations from the stdout of fairseq-generate. " + "If there are multiply hypotheses for a source, we only keep the first one. " + ) + ) + parser.add_argument("--output", required=True, help="output prefix") + parser.add_argument( + "--srclang", required=True, help="source language (extracted from H-* lines)" + ) + parser.add_argument( + "--tgtlang", required=True, help="target language (extracted from S-* lines)" + ) + parser.add_argument("--minlen", type=int, help="min length filter") + parser.add_argument("--maxlen", type=int, help="max length filter") + parser.add_argument("--ratio", type=float, help="ratio filter") + parser.add_argument("files", nargs="*", help="input files") + args = parser.parse_args() + + def validate(src, tgt): + srclen = len(src.split(" ")) if src != "" else 0 + tgtlen = len(tgt.split(" ")) if tgt != "" else 0 + if ( + (args.minlen is not None and (srclen < args.minlen or tgtlen < args.minlen)) + or ( + args.maxlen is not None + and (srclen > args.maxlen or tgtlen > args.maxlen) + ) + or ( + args.ratio is not None + and (max(srclen, tgtlen) / float(min(srclen, tgtlen)) > args.ratio) + ) + ): + return False + return True + + def safe_index(toks, index, default): + try: + return toks[index] + except IndexError: + return default + + with open(args.output + "." + args.srclang, "w") as src_h, open( + args.output + "." + args.tgtlang, "w" + ) as tgt_h: + for line in tqdm(fileinput.input(args.files)): + if line.startswith("S-"): + tgt = safe_index(line.rstrip().split("\t"), 1, "") + elif line.startswith("H-"): + if tgt is not None: + src = safe_index(line.rstrip().split("\t"), 2, "") + if validate(src, tgt): + print(src, file=src_h) + print(tgt, file=tgt_h) + tgt = None + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/backtranslation/prepare-de-monolingual.sh b/fairseq-tools/fairseq/examples/backtranslation/prepare-de-monolingual.sh new file mode 100644 index 00000000..5e67b2b3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/prepare-de-monolingual.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +NORM_PUNC=$SCRIPTS/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$SCRIPTS/tokenizer/remove-non-printing-char.perl +BPEROOT=subword-nmt/subword_nmt + + +BPE_CODE=wmt18_en_de/code +SUBSAMPLE_SIZE=25000000 +LANG=de + + +OUTDIR=wmt18_${LANG}_mono +orig=orig +tmp=$OUTDIR/tmp +mkdir -p $OUTDIR $tmp + + +URLS=( + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2007.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2008.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2009.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2010.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2011.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2012.de.shuffled.gz" + "http://www.statmt.org/wmt14/training-monolingual-news-crawl/news.2013.de.shuffled.gz" + "http://www.statmt.org/wmt15/training-monolingual-news-crawl-v2/news.2014.de.shuffled.v2.gz" + "http://data.statmt.org/wmt16/translation-task/news.2015.de.shuffled.gz" + "http://data.statmt.org/wmt17/translation-task/news.2016.de.shuffled.gz" + "http://data.statmt.org/wmt18/translation-task/news.2017.de.shuffled.deduped.gz" +) +FILES=( + "news.2007.de.shuffled.gz" + "news.2008.de.shuffled.gz" + "news.2009.de.shuffled.gz" + "news.2010.de.shuffled.gz" + "news.2011.de.shuffled.gz" + "news.2012.de.shuffled.gz" + "news.2013.de.shuffled.gz" + "news.2014.de.shuffled.v2.gz" + "news.2015.de.shuffled.gz" + "news.2016.de.shuffled.gz" + "news.2017.de.shuffled.deduped.gz" +) + + +cd $orig +for ((i=0;i<${#URLS[@]};++i)); do + file=${FILES[i]} + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + url=${URLS[i]} + wget "$url" + fi +done +cd .. + + +if [ -f $tmp/monolingual.${SUBSAMPLE_SIZE}.${LANG} ]; then + echo "found monolingual sample, skipping shuffle/sample/tokenize" +else + gzip -c -d -k $(for FILE in "${FILES[@]}"; do echo $orig/$FILE; done) \ + | shuf -n $SUBSAMPLE_SIZE \ + | perl $NORM_PUNC $LANG \ + | perl $REM_NON_PRINT_CHAR \ + | perl $TOKENIZER -threads 8 -a -l $LANG \ + > $tmp/monolingual.${SUBSAMPLE_SIZE}.${LANG} +fi + + +if [ -f $tmp/bpe.monolingual.${SUBSAMPLE_SIZE}.${LANG} ]; then + echo "found BPE monolingual sample, skipping BPE step" +else + python $BPEROOT/apply_bpe.py -c $BPE_CODE \ + < $tmp/monolingual.${SUBSAMPLE_SIZE}.${LANG} \ + > $tmp/bpe.monolingual.${SUBSAMPLE_SIZE}.${LANG} +fi + + +if [ -f $tmp/bpe.monolingual.dedup.${SUBSAMPLE_SIZE}.${LANG} ]; then + echo "found deduplicated monolingual sample, skipping deduplication step" +else + python deduplicate_lines.py $tmp/bpe.monolingual.${SUBSAMPLE_SIZE}.${LANG} \ + > $tmp/bpe.monolingual.dedup.${SUBSAMPLE_SIZE}.${LANG} +fi + + +if [ -f $OUTDIR/bpe.monolingual.dedup.00.de ]; then + echo "found sharded data, skipping sharding step" +else + split --lines 1000000 --numeric-suffixes \ + --additional-suffix .${LANG} \ + $tmp/bpe.monolingual.dedup.${SUBSAMPLE_SIZE}.${LANG} \ + $OUTDIR/bpe.monolingual.dedup. +fi diff --git a/fairseq-tools/fairseq/examples/backtranslation/prepare-wmt18en2de.sh b/fairseq-tools/fairseq/examples/backtranslation/prepare-wmt18en2de.sh new file mode 100644 index 00000000..f6fd2753 --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/prepare-wmt18en2de.sh @@ -0,0 +1,135 @@ +#!/bin/bash +# Adapted from https://github.com/facebookresearch/MIXER/blob/master/prepareData.sh + +echo 'Cloning Moses github repository (for tokenization scripts)...' +git clone https://github.com/moses-smt/mosesdecoder.git + +echo 'Cloning Subword NMT repository (for BPE pre-processing)...' +git clone https://github.com/rsennrich/subword-nmt.git + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +CLEAN=$SCRIPTS/training/clean-corpus-n.perl +NORM_PUNC=$SCRIPTS/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$SCRIPTS/tokenizer/remove-non-printing-char.perl +BPEROOT=subword-nmt/subword_nmt +BPE_TOKENS=32000 + +URLS=( + "http://statmt.org/wmt13/training-parallel-europarl-v7.tgz" + "http://statmt.org/wmt13/training-parallel-commoncrawl.tgz" + "http://data.statmt.org/wmt18/translation-task/training-parallel-nc-v13.tgz" + "http://data.statmt.org/wmt18/translation-task/rapid2016.tgz" + "http://data.statmt.org/wmt17/translation-task/dev.tgz" + "http://statmt.org/wmt14/test-full.tgz" +) +FILES=( + "training-parallel-europarl-v7.tgz" + "training-parallel-commoncrawl.tgz" + "training-parallel-nc-v13.tgz" + "rapid2016.tgz" + "dev.tgz" + "test-full.tgz" +) +CORPORA=( + "training/europarl-v7.de-en" + "commoncrawl.de-en" + "training-parallel-nc-v13/news-commentary-v13.de-en" + "rapid2016.de-en" +) + +if [ ! -d "$SCRIPTS" ]; then + echo "Please set SCRIPTS variable correctly to point to Moses scripts." + exit 1 +fi + +OUTDIR=wmt18_en_de + +src=en +tgt=de +lang=en-de +prep=$OUTDIR +tmp=$prep/tmp +orig=orig + +mkdir -p $orig $tmp $prep + +cd $orig + +for ((i=0;i<${#URLS[@]};++i)); do + file=${FILES[i]} + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + url=${URLS[i]} + wget "$url" + if [ -f $file ]; then + echo "$url successfully downloaded." + else + echo "$url not successfully downloaded." + exit 1 + fi + if [ ${file: -4} == ".tgz" ]; then + tar zxvf $file + elif [ ${file: -4} == ".tar" ]; then + tar xvf $file + fi + fi +done +cd .. + +echo "pre-processing train data..." +for l in $src $tgt; do + rm $tmp/train.tags.$lang.tok.$l + for f in "${CORPORA[@]}"; do + cat $orig/$f.$l | \ + perl $NORM_PUNC $l | \ + perl $REM_NON_PRINT_CHAR | \ + perl $TOKENIZER -threads 8 -a -l $l >> $tmp/train.tags.$lang.tok.$l + done +done + +echo "pre-processing test data..." +for l in $src $tgt; do + if [ "$l" == "$src" ]; then + t="src" + else + t="ref" + fi + grep '\s*//g' | \ + sed -e 's/\s*<\/seg>\s*//g' | \ + sed -e "s/\’/\'/g" | \ + perl $TOKENIZER -threads 8 -a -l $l > $tmp/test.$l + echo "" +done + +echo "splitting train and valid..." +for l in $src $tgt; do + awk '{if (NR%100 == 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/valid.$l + awk '{if (NR%100 != 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/train.$l +done + +TRAIN=$tmp/train.de-en +BPE_CODE=$prep/code +rm -f $TRAIN +for l in $src $tgt; do + cat $tmp/train.$l >> $TRAIN +done + +echo "learn_bpe.py on ${TRAIN}..." +python $BPEROOT/learn_bpe.py -s $BPE_TOKENS < $TRAIN > $BPE_CODE + +for L in $src $tgt; do + for f in train.$L valid.$L test.$L; do + echo "apply_bpe.py to ${f}..." + python $BPEROOT/apply_bpe.py -c $BPE_CODE < $tmp/$f > $tmp/bpe.$f + done +done + +perl $CLEAN -ratio 1.5 $tmp/bpe.train $src $tgt $prep/train 1 250 +perl $CLEAN -ratio 1.5 $tmp/bpe.valid $src $tgt $prep/valid 1 250 + +for L in $src $tgt; do + cp $tmp/bpe.test.$L $prep/test.$L +done diff --git a/fairseq-tools/fairseq/examples/backtranslation/sacrebleu.sh b/fairseq-tools/fairseq/examples/backtranslation/sacrebleu.sh new file mode 100644 index 00000000..a70da23f --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/sacrebleu.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +if [ $# -ne 5 ]; then + echo "usage: $0 [dataset=wmt14/full] [langpair=en-de] [databin] [bpecode] [model]" + exit +fi + + +DATASET=$1 +LANGPAIR=$2 +DATABIN=$3 +BPECODE=$4 +MODEL=$5 + +SRCLANG=$(echo $LANGPAIR | cut -d '-' -f 1) +TGTLANG=$(echo $LANGPAIR | cut -d '-' -f 2) + + +BPEROOT=examples/backtranslation/subword-nmt/subword_nmt +if [ ! -e $BPEROOT ]; then + BPEROOT=subword-nmt/subword_nmt + if [ ! -e $BPEROOT ]; then + echo 'Cloning Subword NMT repository (for BPE pre-processing)...' + git clone https://github.com/rsennrich/subword-nmt.git + fi +fi + + +sacrebleu -t $DATASET -l $LANGPAIR --echo src \ +| sacremoses tokenize -a -l $SRCLANG -q \ +| python $BPEROOT/apply_bpe.py -c $BPECODE \ +| fairseq-interactive $DATABIN --path $MODEL \ + -s $SRCLANG -t $TGTLANG \ + --beam 5 --remove-bpe --buffer-size 1024 --max-tokens 8000 \ +| grep ^H- | cut -f 3- \ +| sacremoses detokenize -l $TGTLANG -q \ +| sacrebleu -t $DATASET -l $LANGPAIR diff --git a/fairseq-tools/fairseq/examples/backtranslation/tokenized_bleu.sh b/fairseq-tools/fairseq/examples/backtranslation/tokenized_bleu.sh new file mode 100644 index 00000000..c6d6aaa1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/backtranslation/tokenized_bleu.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +if [ $# -ne 5 ]; then + echo "usage: $0 [dataset=wmt14/full] [langpair=en-de] [databin] [bpecode] [model]" + exit +fi + + +DATASET=$1 +LANGPAIR=$2 +DATABIN=$3 +BPECODE=$4 +MODEL=$5 + +SRCLANG=$(echo $LANGPAIR | cut -d '-' -f 1) +TGTLANG=$(echo $LANGPAIR | cut -d '-' -f 2) + + +BPEROOT=examples/backtranslation/subword-nmt/subword_nmt +if [ ! -e $BPEROOT ]; then + BPEROOT=subword-nmt/subword_nmt + if [ ! -e $BPEROOT ]; then + echo 'Cloning Subword NMT repository (for BPE pre-processing)...' + git clone https://github.com/rsennrich/subword-nmt.git + fi +fi + + +TMP_REF=$(mktemp) + +sacrebleu -t $DATASET -l $LANGPAIR --echo ref -q \ +| sacremoses normalize -l $TGTLANG -q \ +| sacremoses tokenize -a -l $TGTLANG -q \ +> $TMP_REF + +sacrebleu -t $DATASET -l $LANGPAIR --echo src -q \ +| sacremoses normalize -l $SRCLANG -q \ +| sacremoses tokenize -a -l $SRCLANG -q \ +| python $BPEROOT/apply_bpe.py -c $BPECODE \ +| fairseq-interactive $DATABIN --path $MODEL \ + -s $SRCLANG -t $TGTLANG \ + --beam 5 --remove-bpe --buffer-size 1024 --max-tokens 8000 \ +| grep ^H- | cut -f 3- \ +| fairseq-score --ref $TMP_REF + +rm -f $TMP_REF diff --git a/fairseq-tools/fairseq/examples/bart/README.glue.md b/fairseq-tools/fairseq/examples/bart/README.glue.md new file mode 100644 index 00000000..a010934e --- /dev/null +++ b/fairseq-tools/fairseq/examples/bart/README.glue.md @@ -0,0 +1,99 @@ +# Fine-tuning BART on GLUE tasks + +### 1) Download the data from GLUE website (https://gluebenchmark.com/tasks) using following commands: +```bash +wget https://gist.githubusercontent.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e/raw/17b8dd0d724281ed7c3b2aeeda662b92809aadd5/download_glue_data.py +python download_glue_data.py --data_dir glue_data --tasks all +``` + +### 2) Preprocess GLUE task data (same as RoBERTa): +```bash +./examples/roberta/preprocess_GLUE_tasks.sh glue_data +``` +`glue_task_name` is one of the following: +`{ALL, QQP, MNLI, QNLI, MRPC, RTE, STS-B, SST-2, CoLA}` +Use `ALL` for preprocessing all the glue tasks. + +### 3) Fine-tuning on GLUE task: +Example fine-tuning cmd for `RTE` task +```bash +TOTAL_NUM_UPDATES=2036 # 10 epochs through RTE for bsz 16 +WARMUP_UPDATES=61 # 6 percent of the number of updates +LR=1e-05 # Peak LR for polynomial LR scheduler. +NUM_CLASSES=2 +MAX_SENTENCES=16 # Batch size. +BART_PATH=/path/to/bart/model.pt + +CUDA_VISIBLE_DEVICES=0,1 fairseq-train RTE-bin/ \ + --restore-file $BART_PATH \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --add-prev-output-tokens \ + --layernorm-embedding \ + --share-all-embeddings \ + --share-decoder-input-output-embed \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 \ + --arch bart_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.01 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-08 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric; +``` + +For each of the GLUE task, you will need to use following cmd-line arguments: + +Model | MNLI | QNLI | QQP | RTE | SST-2 | MRPC | CoLA | STS-B +---|---|---|---|---|---|---|---|--- +`--num-classes` | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 1 +`--lr` | 5e-6 | 1e-5 | 1e-5 | 1e-5 | 5e-6 | 2e-5 | 2e-5 | 2e-5 +`bsz` | 128 | 32 | 32 | 32 | 128 | 64 | 64 | 32 +`--total-num-update` | 30968 | 33112 | 113272 | 1018 | 5233 | 1148 | 1334 | 1799 +`--warmup-updates` | 1858 | 1986 | 6796 | 61 | 314 | 68 | 80 | 107 + +For `STS-B` additionally add `--regression-target --best-checkpoint-metric loss` and remove `--maximize-best-checkpoint-metric`. + +**Note:** + +a) `--total-num-updates` is used by `--polynomial_decay` scheduler and is calculated for `--max-epoch=10` and `--batch-size=32/64/128` depending on the task. + +b) Above cmd-args and hyperparams are tested on Nvidia `V100` GPU with `32gb` of memory for each task. Depending on the GPU memory resources available to you, you can use increase `--update-freq` and reduce `--batch-size`. + +### Inference on GLUE task +After training the model as mentioned in previous step, you can perform inference with checkpoints in `checkpoints/` directory using following python code snippet: + +```python +from fairseq.models.bart import BARTModel + +bart = BARTModel.from_pretrained( + 'checkpoints/', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='RTE-bin' +) + +label_fn = lambda label: bart.task.label_dictionary.string( + [label + bart.task.label_dictionary.nspecial] +) +ncorrect, nsamples = 0, 0 +bart.cuda() +bart.eval() +with open('glue_data/RTE/dev.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[1], tokens[2], tokens[3] + tokens = bart.encode(sent1, sent2) + prediction = bart.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_fn(prediction) + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) +``` diff --git a/fairseq-tools/fairseq/examples/bart/README.md b/fairseq-tools/fairseq/examples/bart/README.md new file mode 100644 index 00000000..394503f2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/bart/README.md @@ -0,0 +1,218 @@ +# BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension + +[https://arxiv.org/pdf/1910.13461.pdf] + +## Introduction + +BART is sequence-to-sequence model trained with denoising as pretraining objective. We show that this pretraining objective is more generic and show that we can match [RoBERTa](../roberta) results on SQuAD and GLUE and gain state-of-the-art results on summarization (XSum, CNN dataset), long form generative question answering (ELI5) and dialog response genration (ConvAI2). See the associated paper for more details. + +## Pre-trained models + +Model | Description | # params | Download +---|---|---|--- +`bart.base` | BART model with 6 encoder and decoder layers | 140M | [bart.base.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/bart.base.tar.gz) +`bart.large` | BART model with 12 encoder and decoder layers | 400M | [bart.large.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/bart.large.tar.gz) +`bart.large.mnli` | `bart.large` finetuned on `MNLI` | 400M | [bart.large.mnli.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/bart.large.mnli.tar.gz) +`bart.large.cnn` | `bart.large` finetuned on `CNN-DM` | 400M | [bart.large.cnn.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/bart.large.cnn.tar.gz) +`bart.large.xsum` | `bart.large` finetuned on `Xsum` | 400M | [bart.large.xsum.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/bart.large.xsum.tar.gz) + +## Results + +**[GLUE (Wang et al., 2019)](https://gluebenchmark.com/)** +_(dev set, single model, single-task finetuning)_ + +Model | MNLI | QNLI | QQP | RTE | SST-2 | MRPC | CoLA | STS-B +---|---|---|---|---|---|---|---|--- +`roberta.large` | 90.2 | 94.7 | 92.2 | 86.6 | 96.4 | 90.9 | 68.0 | 92.4 +`bart.large` | 89.9 | 94.9 | 92.5 | 87.0 | 96.6 | 90.4 | 62.8 | 91.2 + +**[SQuAD (Rajpurkar et al., 2018)](https://rajpurkar.github.io/SQuAD-explorer/)** +_(dev set, no additional data used)_ + +Model | SQuAD 1.1 EM/F1 | SQuAD 2.0 EM/F1 +---|---|--- +`roberta.large` | 88.9/94.6 | 86.5/89.4 +`bart.large` | 88.8/94.6 | 86.1/89.2 + +**[CNN/Daily Mail](http://nlpprogress.com/english/summarization.html)** +_(test set, no additional data used)_ + +Model | R1 | R2 | RL +---|---|---|--- +`BERTSUMEXTABS` | 42.13 | 19.60 | 39.18 +`bart.large` | 44.16 | 21.28 | 40.90 + +## Example usage + +##### Load BART from torch.hub (PyTorch >= 1.1): +```python +import torch +bart = torch.hub.load('pytorch/fairseq', 'bart.large') +bart.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Load BART (for PyTorch 1.0 or custom models): +```python +# Download bart.large model +wget https://dl.fbaipublicfiles.com/fairseq/models/bart.large.tar.gz +tar -xzvf bart.large.tar.gz + +# Load the model in fairseq +from fairseq.models.bart import BARTModel +bart = BARTModel.from_pretrained('/path/to/bart.large', checkpoint_file='model.pt') +bart.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Apply Byte-Pair Encoding (BPE) to input text: +```python +tokens = bart.encode('Hello world!') +assert tokens.tolist() == [0, 31414, 232, 328, 2] +bart.decode(tokens) # 'Hello world!' +``` + +##### Extract features from BART: +```python +# Extract the last layer's features +last_layer_features = bart.extract_features(tokens) +assert last_layer_features.size() == torch.Size([1, 5, 1024]) + +# Extract all layer's features from decoder (layer 0 is the embedding layer) +all_layers = bart.extract_features(tokens, return_all_hiddens=True) +assert len(all_layers) == 13 +assert torch.all(all_layers[-1] == last_layer_features) +``` + +##### Use BART for sentence-pair classification tasks: +```python +# Download BART already finetuned for MNLI +bart = torch.hub.load('pytorch/fairseq', 'bart.large.mnli') +bart.eval() # disable dropout for evaluation + +# Encode a pair of sentences and make a prediction +tokens = bart.encode('BART is a seq2seq model.', 'BART is not sequence to sequence.') +bart.predict('mnli', tokens).argmax() # 0: contradiction + +# Encode another pair of sentences +tokens = bart.encode('BART is denoising autoencoder.', 'BART is version of autoencoder.') +bart.predict('mnli', tokens).argmax() # 2: entailment +``` + +##### Register a new (randomly initialized) classification head: +```python +bart.register_classification_head('new_task', num_classes=3) +logprobs = bart.predict('new_task', tokens) +``` + +##### Batched prediction: +```python +import torch +from fairseq.data.data_utils import collate_tokens + +bart = torch.hub.load('pytorch/fairseq', 'bart.large.mnli') +bart.eval() + +batch_of_pairs = [ + ['BART is a seq2seq model.', 'BART is not sequence to sequence.'], + ['BART is denoising autoencoder.', 'BART is version of autoencoder.'], +] + +batch = collate_tokens( + [bart.encode(pair[0], pair[1]) for pair in batch_of_pairs], pad_idx=1 +) + +logprobs = bart.predict('mnli', batch) +print(logprobs.argmax(dim=1)) +# tensor([0, 2]) +``` + +##### Using the GPU: +```python +bart.cuda() +bart.predict('new_task', tokens) +``` + +#### Evaluating the `bart.large.mnli` model: + +Example python code snippet to evaluate accuracy on the MNLI `dev_matched` set. +```python +label_map = {0: 'contradiction', 1: 'neutral', 2: 'entailment'} +ncorrect, nsamples = 0, 0 +bart.cuda() +bart.eval() +with open('glue_data/MNLI/dev_matched.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[8], tokens[9], tokens[-1] + tokens = bart.encode(sent1, sent2) + prediction = bart.predict('mnli', tokens).argmax().item() + prediction_label = label_map[prediction] + ncorrect += int(prediction_label == target) + nsamples += 1 + print('| Accuracy: ', float(ncorrect)/float(nsamples)) +# Expected output: 0.9010 +``` + +#### Evaluating the `bart.large.cnn` model: +Follow instructions [here](https://github.com/abisee/cnn-dailymail) to download and process into data-files such that `test.source` and `test.target` has one line for each non-tokenized sample. + +```python +bart = torch.hub.load('pytorch/fairseq', 'bart.large.cnn') +bart.cuda() +bart.eval() +bart.half() +count = 1 +bsz = 32 +with open('test.source') as source, open('test.hypo', 'w') as fout: + sline = source.readline().strip() + slines = [sline] + for sline in source: + if count % bsz == 0: + with torch.no_grad(): + hypotheses_batch = bart.sample(slines, beam=4, lenpen=2.0, max_len_b=140, min_len=55, no_repeat_ngram_size=3) + + for hypothesis in hypotheses_batch: + fout.write(hypothesis + '\n') + fout.flush() + slines = [] + + slines.append(sline.strip()) + count += 1 + if slines != []: + hypotheses_batch = bart.sample(slines, beam=4, lenpen=2.0, max_len_b=140, min_len=55, no_repeat_ngram_size=3) + for hypothesis in hypotheses_batch: + fout.write(hypothesis + '\n') + fout.flush() +``` + +Install `files2rouge` from [here](https://github.com/pltrdy/files2rouge). + +```bash +export CLASSPATH=/path/to/stanford-corenlp-full-2016-10-31/stanford-corenlp-3.7.0.jar + +# Tokenize hypothesis and target files. +cat test.hypo | java edu.stanford.nlp.process.PTBTokenizer -ioFileList -preserveLines > test.hypo.tokenized +cat test.target | java edu.stanford.nlp.process.PTBTokenizer -ioFileList -preserveLines > test.hypo.target +files2rouge test.hypo.tokenized test.hypo.target +# Expected output: (ROUGE-2 Average_F: 0.21238) +``` + + +## Finetuning + +- [Finetuning on GLUE](README.glue.md) +- [Finetuning on CNN-DM](README.summarization.md) + +## Citation + +```bibtex +@article{lewis2019bart, + title = {BART: Denoising Sequence-to-Sequence Pre-training for Natural +Language Generation, Translation, and Comprehension}, + author = {Mike Lewis and Yinhan Liu and Naman Goyal and Marjan Ghazvininejad and + Abdelrahman Mohamed and Omer Levy and Veselin Stoyanov + and Luke Zettlemoyer }, + journal={arXiv preprint arXiv:1910.13461}, + year = {2019}, +} +``` diff --git a/fairseq-tools/fairseq/examples/bart/README.summarization.md b/fairseq-tools/fairseq/examples/bart/README.summarization.md new file mode 100644 index 00000000..d7fecc9c --- /dev/null +++ b/fairseq-tools/fairseq/examples/bart/README.summarization.md @@ -0,0 +1,121 @@ +# Fine-tuning BART on CNN-Dailymail summarization task + +### 1) Download the CNN and Daily Mail data and preprocess it into data files with non-tokenized cased samples. + +Follow the instructions [here](https://github.com/abisee/cnn-dailymail) to download the original CNN and Daily Mail datasets. To preprocess the data, refer to the pointers in [this issue](https://github.com/pytorch/fairseq/issues/1391) or check out the code [here](https://github.com/artmatsak/cnn-dailymail). + +Follow the instructions [here](https://github.com/EdinburghNLP/XSum) to download the original Extreme Summarization datasets, or check out the code [here](https://github.com/EdinburghNLP/XSum/tree/master/XSum-Dataset), Please keep the raw dataset and make sure no tokenization nor BPE on the dataset. + +### 2) BPE preprocess: + +```bash +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt' + +TASK=cnn_dm +for SPLIT in train val +do + for LANG in source target + do + python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json encoder.json \ + --vocab-bpe vocab.bpe \ + --inputs "$TASK/$SPLIT.$LANG" \ + --outputs "$TASK/$SPLIT.bpe.$LANG" \ + --workers 60 \ + --keep-empty; + done +done +``` + +### 3) Binarize dataset: +```bash +fairseq-preprocess \ + --source-lang "source" \ + --target-lang "target" \ + --trainpref "${TASK}/train.bpe" \ + --validpref "${TASK}/val.bpe" \ + --destdir "${TASK}-bin/" \ + --workers 60 \ + --srcdict dict.txt \ + --tgtdict dict.txt; +``` + +### 4) Fine-tuning on CNN-DM summarization task: +Example fine-tuning CNN-DM +```bash +TOTAL_NUM_UPDATES=20000 +WARMUP_UPDATES=500 +LR=3e-05 +MAX_TOKENS=2048 +UPDATE_FREQ=4 +BART_PATH=/path/to/bart/model.pt + +CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 fairseq-train cnn_dm-bin \ + --restore-file $BART_PATH \ + --max-tokens $MAX_TOKENS \ + --task translation \ + --source-lang source --target-lang target \ + --truncate-source \ + --layernorm-embedding \ + --share-all-embeddings \ + --share-decoder-input-output-embed \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --arch bart_large \ + --criterion label_smoothed_cross_entropy \ + --label-smoothing 0.1 \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.01 --optimizer adam --adam-betas "(0.9, 0.999)" --adam-eps 1e-08 \ + --clip-norm 0.1 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --update-freq $UPDATE_FREQ \ + --skip-invalid-size-inputs-valid-test \ + --find-unused-parameters; +``` +Above is expected to run on `1` node with `8 32gb-V100`. +Expected training time is about `5 hours`. Training time can be reduced with distributed training on `4` nodes and `--update-freq 1`. + +Use TOTAL_NUM_UPDATES=15000 UPDATE_FREQ=2 for Xsum task + +### Inference for CNN-DM test data using above trained checkpoint. +After training the model as mentioned in previous step, you can perform inference with checkpoints in `checkpoints/` directory using following python code snippet: + +```python +import torch +from fairseq.models.bart import BARTModel + +bart = BARTModel.from_pretrained( + 'checkpoints/', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='cnn_dm-bin' +) + +bart.cuda() +bart.eval() +bart.half() +count = 1 +bsz = 32 +with open('cnn_dm/test.source') as source, open('cnn_dm/test.hypo', 'w') as fout: + sline = source.readline().strip() + slines = [sline] + for sline in source: + if count % bsz == 0: + with torch.no_grad(): + hypotheses_batch = bart.sample(slines, beam=4, lenpen=2.0, max_len_b=140, min_len=55, no_repeat_ngram_size=3) + + for hypothesis in hypotheses_batch: + fout.write(hypothesis + '\n') + fout.flush() + slines = [] + + slines.append(sline.strip()) + count += 1 + if slines != []: + hypotheses_batch = bart.sample(slines, beam=4, lenpen=2.0, max_len_b=140, min_len=55, no_repeat_ngram_size=3) + for hypothesis in hypotheses_batch: + fout.write(hypothesis + '\n') + fout.flush() +``` +Use beam=6, lenpen=1.0, max_len_b=60, min_len=10 for Xsum Generation diff --git a/fairseq-tools/fairseq/examples/byte_level_bpe/README.md b/fairseq-tools/fairseq/examples/byte_level_bpe/README.md new file mode 100644 index 00000000..65709266 --- /dev/null +++ b/fairseq-tools/fairseq/examples/byte_level_bpe/README.md @@ -0,0 +1,88 @@ +# Neural Machine Translation with Byte-Level Subwords + +https://arxiv.org/abs/1909.03341 + +We provide an implementation of byte-level byte-pair encoding (BBPE), taking IWSLT 2017 Fr-En translation as +example. + +## Data +Get data and generate fairseq binary dataset: +```bash +bash ./get_data.sh +``` + +## Model Training +Train Transformer model with Bi-GRU embedding contextualization (implemented in `gru_transformer.py`): +```bash +# VOCAB=bytes +# VOCAB=chars +VOCAB=bbpe2048 +# VOCAB=bpe2048 +# VOCAB=bbpe4096 +# VOCAB=bpe4096 +# VOCAB=bpe16384 +``` +```bash +fairseq-train "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \ + --arch gru_transformer --encoder-layers 2 --decoder-layers 2 --dropout 0.3 --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9, 0.98)' \ + --lr 5e-4 --lr-scheduler inverse_sqrt --warmup-updates 4000 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --log-format 'simple' --log-interval 100 --save-dir "checkpoints/${VOCAB}" \ + --batch-size 100 --max-update 100000 --update-freq 2 +``` + +## Generation +`fairseq-generate` requires bytes (BBPE) decoder to convert byte-level representation back to characters: +```bash +# BPE=--bpe bytes +# BPE=--bpe characters +BPE=--bpe byte_bpe --sentencepiece-model-path data/spm_bbpe2048.model +# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe2048.model +# BPE=--bpe byte_bpe --sentencepiece-model-path data/spm_bbpe4096.model +# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe4096.model +# BPE=--bpe sentencepiece --sentencepiece-model data/spm_bpe16384.model +``` + +```bash +fairseq-generate "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \ + --source-lang fr --gen-subset test --sacrebleu --path "checkpoints/${VOCAB}/checkpoint_last.pt" \ + --tokenizer moses --moses-target-lang en ${BPE} +``` +When using `fairseq-interactive`, bytes (BBPE) encoder/decoder is required to tokenize input data and detokenize model predictions: +```bash +fairseq-interactive "data/bin_${VOCAB}" --task translation --user-dir examples/byte_level_bpe/gru_transformer \ + --path "checkpoints/${VOCAB}/checkpoint_last.pt" --input data/test.fr --tokenizer moses --moses-source-lang fr \ + --moses-target-lang en ${BPE} --buffer-size 1000 --max-tokens 10000 +``` + +## Results +| Vocabulary | Model | BLEU | +|:-------------:|:-------------:|:-------------:| +| Joint BPE 16k ([Kudo, 2018](https://arxiv.org/abs/1804.10959)) | 512d LSTM 2+2 | 33.81 | +| Joint BPE 16k | Transformer base 2+2 (w/ GRU) | 36.64 (36.72) | +| Joint BPE 4k | Transformer base 2+2 (w/ GRU) | 35.49 (36.10) | +| Joint BBPE 4k | Transformer base 2+2 (w/ GRU) | 35.61 (35.82) | +| Joint BPE 2k | Transformer base 2+2 (w/ GRU) | 34.87 (36.13) | +| Joint BBPE 2k | Transformer base 2+2 (w/ GRU) | 34.98 (35.43) | +| Characters | Transformer base 2+2 (w/ GRU) | 31.78 (33.30) | +| Bytes | Transformer base 2+2 (w/ GRU) | 31.57 (33.62) | + + +## Citation +``` +@misc{wang2019neural, + title={Neural Machine Translation with Byte-Level Subwords}, + author={Changhan Wang and Kyunghyun Cho and Jiatao Gu}, + year={2019}, + eprint={1909.03341}, + archivePrefix={arXiv}, + primaryClass={cs.CL} +} +``` + + +## Contact +Changhan Wang ([changhan@fb.com](mailto:changhan@fb.com)), +Kyunghyun Cho ([kyunghyuncho@fb.com](mailto:kyunghyuncho@fb.com)), +Jiatao Gu ([jgu@fb.com](mailto:jgu@fb.com)) diff --git a/fairseq-tools/fairseq/examples/byte_level_bpe/get_bitext.py b/fairseq-tools/fairseq/examples/byte_level_bpe/get_bitext.py new file mode 100644 index 00000000..6ac1eeec --- /dev/null +++ b/fairseq-tools/fairseq/examples/byte_level_bpe/get_bitext.py @@ -0,0 +1,254 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +import argparse +import os +import os.path as op +from collections import namedtuple +from multiprocessing import cpu_count +from typing import List, Optional + +import sentencepiece as sp +from fairseq.data.encoders.byte_bpe import ByteBPE +from fairseq.data.encoders.byte_utils import byte_encode +from fairseq.data.encoders.bytes import Bytes +from fairseq.data.encoders.characters import Characters +from fairseq.data.encoders.moses_tokenizer import MosesTokenizer +from fairseq.data.encoders.sentencepiece_bpe import SentencepieceBPE + + +SPLITS = ["train", "valid", "test"] + + +def _convert_xml(in_path: str, out_path: str): + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + ss = s.strip() + if not ss.startswith("", "").split('">') + assert len(ss) == 2 + f_o.write(ss[1].strip() + "\n") + + +def _convert_train(in_path: str, out_path: str): + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + ss = s.strip() + if ss.startswith("<"): + continue + f_o.write(ss.strip() + "\n") + + +def _get_bytes(in_path: str, out_path: str): + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + f_o.write(Bytes.encode(s.strip()) + "\n") + + +def _get_chars(in_path: str, out_path: str): + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + f_o.write(Characters.encode(s.strip()) + "\n") + + +def pretokenize(in_path: str, out_path: str, src: str, tgt: str): + Args = namedtuple( + "Args", + [ + "moses_source_lang", + "moses_target_lang", + "moses_no_dash_splits", + "moses_no_escape", + ], + ) + args = Args( + moses_source_lang=src, + moses_target_lang=tgt, + moses_no_dash_splits=False, + moses_no_escape=False, + ) + pretokenizer = MosesTokenizer(args) + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + f_o.write(pretokenizer.encode(s.strip()) + "\n") + + +def _convert_to_bchar(in_path_prefix: str, src: str, tgt: str, out_path: str): + with open(out_path, "w") as f_o: + for lang in [src, tgt]: + with open(f"{in_path_prefix}.{lang}") as f: + for s in f: + f_o.write(byte_encode(s.strip()) + "\n") + + +def _get_bpe(in_path: str, model_prefix: str, vocab_size: int): + arguments = [ + f"--input={in_path}", + f"--model_prefix={model_prefix}", + f"--model_type=bpe", + f"--vocab_size={vocab_size}", + "--character_coverage=1.0", + "--normalization_rule_name=identity", + f"--num_threads={cpu_count()}", + ] + sp.SentencePieceTrainer.Train(" ".join(arguments)) + + +def _apply_bbpe(model_path: str, in_path: str, out_path: str): + Args = namedtuple("Args", ["sentencepiece_model_path"]) + args = Args(sentencepiece_model_path=model_path) + tokenizer = ByteBPE(args) + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + f_o.write(tokenizer.encode(s.strip()) + "\n") + + +def _apply_bpe(model_path: str, in_path: str, out_path: str): + Args = namedtuple("Args", ["sentencepiece_model"]) + args = Args(sentencepiece_model=model_path) + tokenizer = SentencepieceBPE(args) + with open(in_path) as f, open(out_path, "w") as f_o: + for s in f: + f_o.write(tokenizer.encode(s.strip()) + "\n") + + +def _concat_files(in_paths: List[str], out_path: str): + with open(out_path, "w") as f_o: + for p in in_paths: + with open(p) as f: + for r in f: + f_o.write(r) + + +def preprocess_iwslt17( + root: str, + src: str, + tgt: str, + bpe_size: Optional[int], + need_chars: bool, + bbpe_size: Optional[int], + need_bytes: bool, +): + # extract bitext + in_root = op.join(root, f"{src}-{tgt}") + for lang in [src, tgt]: + _convert_train( + op.join(in_root, f"train.tags.{src}-{tgt}.{lang}"), + op.join(root, f"train.{lang}"), + ) + _convert_xml( + op.join(in_root, f"IWSLT17.TED.dev2010.{src}-{tgt}.{lang}.xml"), + op.join(root, f"valid.{lang}"), + ) + _convert_xml( + op.join(in_root, f"IWSLT17.TED.tst2015.{src}-{tgt}.{lang}.xml"), + op.join(root, f"test.{lang}"), + ) + # pre-tokenize + for lang in [src, tgt]: + for split in SPLITS: + pretokenize( + op.join(root, f"{split}.{lang}"), + op.join(root, f"{split}.moses.{lang}"), + src, + tgt, + ) + # tokenize with BPE vocabulary + if bpe_size is not None: + # learn vocabulary + concated_train_path = op.join(root, "train.all") + _concat_files( + [op.join(root, "train.moses.fr"), op.join(root, "train.moses.en")], + concated_train_path, + ) + bpe_model_prefix = op.join(root, f"spm_bpe{bpe_size}") + _get_bpe(concated_train_path, bpe_model_prefix, bpe_size) + os.remove(concated_train_path) + # apply + for lang in [src, tgt]: + for split in SPLITS: + _apply_bpe( + bpe_model_prefix + ".model", + op.join(root, f"{split}.moses.{lang}"), + op.join(root, f"{split}.moses.bpe{bpe_size}.{lang}"), + ) + # tokenize with bytes vocabulary + if need_bytes: + for lang in [src, tgt]: + for split in SPLITS: + _get_bytes( + op.join(root, f"{split}.moses.{lang}"), + op.join(root, f"{split}.moses.bytes.{lang}"), + ) + # tokenize with characters vocabulary + if need_chars: + for lang in [src, tgt]: + for split in SPLITS: + _get_chars( + op.join(root, f"{split}.moses.{lang}"), + op.join(root, f"{split}.moses.chars.{lang}"), + ) + # tokenize with byte-level BPE vocabulary + if bbpe_size is not None: + # learn vocabulary + bchar_path = op.join(root, "train.bchar") + _convert_to_bchar(op.join(root, "train.moses"), src, tgt, bchar_path) + bbpe_model_prefix = op.join(root, f"spm_bbpe{bbpe_size}") + _get_bpe(bchar_path, bbpe_model_prefix, bbpe_size) + os.remove(bchar_path) + # apply + for lang in [src, tgt]: + for split in SPLITS: + _apply_bbpe( + bbpe_model_prefix + ".model", + op.join(root, f"{split}.moses.{lang}"), + op.join(root, f"{split}.moses.bbpe{bbpe_size}.{lang}"), + ) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--root", type=str, default="data") + parser.add_argument( + "--bpe-vocab", + default=None, + type=int, + help="Generate tokenized bitext with BPE of size K." + "Default to None (disabled).", + ) + parser.add_argument( + "--bbpe-vocab", + default=None, + type=int, + help="Generate tokenized bitext with BBPE of size K." + "Default to None (disabled).", + ) + parser.add_argument( + "--byte-vocab", + action="store_true", + help="Generate tokenized bitext with bytes vocabulary", + ) + parser.add_argument( + "--char-vocab", + action="store_true", + help="Generate tokenized bitext with chars vocabulary", + ) + args = parser.parse_args() + + preprocess_iwslt17( + args.root, + "fr", + "en", + args.bpe_vocab, + args.char_vocab, + args.bbpe_vocab, + args.byte_vocab, + ) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/byte_level_bpe/get_data.sh b/fairseq-tools/fairseq/examples/byte_level_bpe/get_data.sh new file mode 100644 index 00000000..c3d55d49 --- /dev/null +++ b/fairseq-tools/fairseq/examples/byte_level_bpe/get_data.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +PY_BIN_ROOT= + +# PyPI dependency +${PY_BIN_ROOT}pip install sentencepiece sacremoses + +# Get data +if [ ! -d "data" ]; then + mkdir data +fi + +if [ ! -f "data/fr-en.tgz" ]; then + wget https://wit3.fbk.eu/archive/2017-01-trnted/texts/fr/en/fr-en.tgz -P data + tar xvf data/fr-en.tgz -C data +fi +${PY_BIN_ROOT}python get_bitext.py --bpe-vocab 16384 --byte-vocab --char-vocab +for VOCAB_SIZE in 2048 4096; do + ${PY_BIN_ROOT}python get_bitext.py --bpe-vocab ${VOCAB_SIZE} --bbpe-vocab ${VOCAB_SIZE} +done +rm -r data/fr-en data/fr-en.tgz + +# Generate binary dataset +${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_bpe16384 --joined-dictionary \ + --workers "$(nproc)" --trainpref data/train.moses.bpe16384 --validpref data/valid.moses.bpe16384 \ + --testpref data/test.moses.bpe16384 + +${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_bytes --joined-dictionary \ + --workers "$(nproc)" --trainpref data/train.moses.bytes --validpref data/valid.moses.bytes \ + --testpref data/test.moses.bytes + +${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir data/bin_chars --joined-dictionary \ + --workers "$(nproc)" --trainpref data/train.moses.chars --validpref data/valid.moses.chars \ + --testpref data/test.moses.chars + +for VOCAB_SIZE in 2048 4096; do + for TYPE in bbpe bpe; do + ${PY_BIN_ROOT}/fairseq-preprocess --source-lang fr --target-lang en --destdir "data/bin_${TYPE}${VOCAB_SIZE}" \ + --joined-dictionary --workers "$(nproc)" --trainpref "data/train.moses.${TYPE}${VOCAB_SIZE}" \ + --validpref "data/valid.moses.${TYPE}${VOCAB_SIZE}" --testpref "data/test.moses.${TYPE}${VOCAB_SIZE}" + done +done diff --git a/fairseq-tools/fairseq/examples/byte_level_bpe/gru_transformer.py b/fairseq-tools/fairseq/examples/byte_level_bpe/gru_transformer.py new file mode 100644 index 00000000..d4efa93a --- /dev/null +++ b/fairseq-tools/fairseq/examples/byte_level_bpe/gru_transformer.py @@ -0,0 +1,107 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn as nn +import torch.nn.functional as F +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer import TransformerEncoder, TransformerModel + + +@register_model("gru_transformer") +class GRUTransformerModel(TransformerModel): + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return GRUTransformerEncoder(args, src_dict, embed_tokens) + + +class GRUTransformerEncoder(TransformerEncoder): + def __init__(self, args, dictionary, embed_tokens): + super().__init__(args, dictionary, embed_tokens) + self.emb_ctx = nn.GRU( + input_size=embed_tokens.embedding_dim, + hidden_size=embed_tokens.embedding_dim // 2, + num_layers=1, + bidirectional=True, + ) + + def forward_embedding(self, src_tokens): + # embed tokens and positions + x = embed = self.embed_scale * self.embed_tokens(src_tokens) + if self.embed_positions is not None: + x = embed + self.embed_positions(src_tokens) + + # contextualize embeddings + x = x.transpose(0, 1) + x = self.dropout_module(x) + x, _ = self.emb_ctx.forward(x) + x = x.transpose(0, 1) + + if self.layernorm_embedding is not None: + x = self.layernorm_embedding(x) + x = self.dropout_module(x) + return x, embed + + +@register_model_architecture("gru_transformer", "gru_transformer") +def gru_transformer_base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.no_cross_attention = getattr(args, "no_cross_attention", False) + args.cross_self_attention = getattr(args, "cross_self_attention", False) + args.layer_wise_attention = getattr(args, "layer_wise_attention", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + args.layernorm_embedding = getattr(args, "layernorm_embedding", False) + + +@register_model_architecture("gru_transformer", "gru_transformer_big") +def gru_transformer_big(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.3) + gru_transformer_base_architecture(args) diff --git a/fairseq-tools/fairseq/examples/camembert/README.md b/fairseq-tools/fairseq/examples/camembert/README.md new file mode 100644 index 00000000..5ef4fe3f --- /dev/null +++ b/fairseq-tools/fairseq/examples/camembert/README.md @@ -0,0 +1,75 @@ +# CamemBERT: a Tasty French Language Model + +## Introduction + +[CamemBERT](https://arxiv.org/abs/1911.03894) is a pretrained language model trained on 138GB of French text based on RoBERTa. + +Also available in [github.com/huggingface/transformers](https://github.com/huggingface/transformers/). + +## Pre-trained models + +| Model | #params | Download | Arch. | Training data | +|--------------------------------|---------|--------------------------------------------------------------------------------------------------------------------------|-------|-----------------------------------| +| `camembert` / `camembert-base` | 110M | [camembert-base.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-base.tar.gz) | Base | OSCAR (138 GB of text) | +| `camembert-large` | 335M | [camembert-large.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-large.tar.gz) | Large | CCNet (135 GB of text) | +| `camembert-base-ccnet` | 110M | [camembert-base-ccnet.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-base-ccnet.tar.gz) | Base | CCNet (135 GB of text) | +| `camembert-base-wikipedia-4gb` | 110M | [camembert-base-wikipedia-4gb.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-base-wikipedia-4gb.tar.gz) | Base | Wikipedia (4 GB of text) | +| `camembert-base-oscar-4gb` | 110M | [camembert-base-oscar-4gb.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-base-oscar-4gb.tar.gz) | Base | Subsample of OSCAR (4 GB of text) | +| `camembert-base-ccnet-4gb` | 110M | [camembert-base-ccnet-4gb.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/camembert-base-ccnet-4gb.tar.gz) | Base | Subsample of CCNet (4 GB of text) | + +## Example usage + +### fairseq +##### Load CamemBERT from torch.hub (PyTorch >= 1.1): +```python +import torch +camembert = torch.hub.load('pytorch/fairseq', 'camembert') +camembert.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Load CamemBERT (for PyTorch 1.0 or custom models): +```python +# Download camembert model +wget https://dl.fbaipublicfiles.com/fairseq/models/camembert-base.tar.gz +tar -xzvf camembert.tar.gz + +# Load the model in fairseq +from fairseq.models.roberta import CamembertModel +camembert = CamembertModel.from_pretrained('/path/to/camembert') +camembert.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Filling masks: +```python +masked_line = 'Le camembert est :)' +camembert.fill_mask(masked_line, topk=3) +# [('Le camembert est délicieux :)', 0.4909118115901947, ' délicieux'), +# ('Le camembert est excellent :)', 0.10556942224502563, ' excellent'), +# ('Le camembert est succulent :)', 0.03453322499990463, ' succulent')] +``` + +##### Extract features from Camembert: +```python +# Extract the last layer's features +line = "J'aime le camembert !" +tokens = camembert.encode(line) +last_layer_features = camembert.extract_features(tokens) +assert last_layer_features.size() == torch.Size([1, 10, 768]) + +# Extract all layer's features (layer 0 is the embedding layer) +all_layers = camembert.extract_features(tokens, return_all_hiddens=True) +assert len(all_layers) == 13 +assert torch.all(all_layers[-1] == last_layer_features) +``` + +## Citation +If you use our work, please cite: + +```bibtex +@inproceedings{martin2020camembert, + title={CamemBERT: a Tasty French Language Model}, + author={Martin, Louis and Muller, Benjamin and Su{\'a}rez, Pedro Javier Ortiz and Dupont, Yoann and Romary, Laurent and de la Clergerie, {\'E}ric Villemonte and Seddah, Djam{\'e} and Sagot, Beno{\^\i}t}, + booktitle={Proceedings of the 58th Annual Meeting of the Association for Computational Linguistics}, + year={2020} +} +``` diff --git a/fairseq-tools/fairseq/examples/constrained_decoding/README.md b/fairseq-tools/fairseq/examples/constrained_decoding/README.md new file mode 100644 index 00000000..cfca9c91 --- /dev/null +++ b/fairseq-tools/fairseq/examples/constrained_decoding/README.md @@ -0,0 +1,123 @@ +# (Vectorized) Lexically constrained decoding with dynamic beam allocation + +This page provides instructions for how to use lexically constrained decoding in Fairseq. +Fairseq implements the code described in the following papers: + +* [Fast Lexically Constrained Decoding With Dynamic Beam Allocation](https://www.aclweb.org/anthology/N18-1119/) (Post & Vilar, 2018) +* [Improved Lexically Constrained Decoding for Translation and Monolingual Rewriting](https://www.aclweb.org/anthology/N19-1090/) (Hu et al., 2019) + +## Quick start + +Constrained search is enabled by adding the command-line argument `--constraints` to `fairseq-interactive`. +Constraints are appended to each line of input, separated by tabs. Each constraint (one or more tokens) +is a separate field. + +The following command, using [Fairseq's WMT19 German--English model](https://github.com/pytorch/fairseq/blob/master/examples/wmt19/README.md), +translates the sentence *Die maschinelle Übersetzung ist schwer zu kontrollieren.* with the constraints +"hard" and "to influence". + + echo -e "Die maschinelle Übersetzung ist schwer zu kontrollieren.\thard\ttoinfluence" \ + | normalize.py | tok.py \ + | fairseq-interactive /path/to/model \ + --path /path/to/model/model1.pt \ + --bpe fastbpe \ + --bpe-codes /path/to/model/bpecodes \ + --constraints \ + -s de -t en \ + --beam 10 + +(tok.py and normalize.py can be found in the same directory as this README; they are just shortcuts around Fairseq's WMT19 preprocessing). +This will generate the following output: + + [snip] + S-0 Die masch@@ in@@ elle Über@@ setzung ist schwer zu kontrollieren . + W-0 1.844 seconds + C-0 hard + C-0 influence + H-0 -1.5333266258239746 Mach@@ ine trans@@ lation is hard to influence . + D-0 -1.5333266258239746 Machine translation is hard to influence . + P-0 -0.5434 -0.1423 -0.1930 -0.1415 -0.2346 -1.8031 -0.1701 -11.7727 -0.1815 -0.1511 + +By default, constraints are generated in the order supplied, with any number (zero or more) of tokens generated +between constraints. If you wish for the decoder to order the constraints, then use `--constraints unordered`. +Note that you may want to use a larger beam. + +## Implementation details + +The heart of the implementation is in `fairseq/search.py`, which adds a `LexicallyConstrainedBeamSearch` instance. +This instance of beam search tracks the progress of each hypothesis in the beam through the set of constraints +provided for each input sentence. It does this using one of two classes, both found in `fairseq/token_generation_contstraints.py`: + +* OrderedConstraintState: assumes the `C` input constraints will be generated in the provided order +* UnorderedConstraintState: tries to apply `C` (phrasal) constraints in all `C!` orders + +## Differences from Sockeye + +There are a number of [differences from Sockeye's implementation](https://awslabs.github.io/sockeye/inference.html#lexical-constraints). + +* Generating constraints in the order supplied (the default option here) is not available in Sockeye. +* Due to an improved beam allocation method, there is no need to prune the beam. +* Again due to better allocation, beam sizes as low as 10 or even 5 are often sufficient. +* [The vector extensions described in Hu et al.](https://github.com/edwardjhu/sockeye/tree/trie_constraints) (NAACL 2019) were never merged + into the main Sockeye branch. + +## Citation + +The paper first describing lexical constraints for seq2seq decoding is: + +```bibtex +@inproceedings{hokamp-liu-2017-lexically, + title = "Lexically Constrained Decoding for Sequence Generation Using Grid Beam Search", + author = "Hokamp, Chris and + Liu, Qun", + booktitle = "Proceedings of the 55th Annual Meeting of the Association for Computational Linguistics (Volume 1: Long Papers)", + month = jul, + year = "2017", + address = "Vancouver, Canada", + publisher = "Association for Computational Linguistics", + url = "https://www.aclweb.org/anthology/P17-1141", + doi = "10.18653/v1/P17-1141", + pages = "1535--1546", +} +``` + +The fairseq implementation uses the extensions described in + +```bibtex +@inproceedings{post-vilar-2018-fast, + title = "Fast Lexically Constrained Decoding with Dynamic Beam Allocation for Neural Machine Translation", + author = "Post, Matt and + Vilar, David", + booktitle = "Proceedings of the 2018 Conference of the North {A}merican Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long Papers)", + month = jun, + year = "2018", + address = "New Orleans, Louisiana", + publisher = "Association for Computational Linguistics", + url = "https://www.aclweb.org/anthology/N18-1119", + doi = "10.18653/v1/N18-1119", + pages = "1314--1324", +} +``` + +and + +```bibtex +@inproceedings{hu-etal-2019-improved, + title = "Improved Lexically Constrained Decoding for Translation and Monolingual Rewriting", + author = "Hu, J. Edward and + Khayrallah, Huda and + Culkin, Ryan and + Xia, Patrick and + Chen, Tongfei and + Post, Matt and + Van Durme, Benjamin", + booktitle = "Proceedings of the 2019 Conference of the North {A}merican Chapter of the Association for Computational Linguistics: Human Language Technologies, Volume 1 (Long and Short Papers)", + month = jun, + year = "2019", + address = "Minneapolis, Minnesota", + publisher = "Association for Computational Linguistics", + url = "https://www.aclweb.org/anthology/N19-1090", + doi = "10.18653/v1/N19-1090", + pages = "839--850", +} +``` diff --git a/fairseq-tools/fairseq/examples/constrained_decoding/normalize.py b/fairseq-tools/fairseq/examples/constrained_decoding/normalize.py new file mode 100644 index 00000000..4ae2b511 --- /dev/null +++ b/fairseq-tools/fairseq/examples/constrained_decoding/normalize.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys + +from sacremoses.normalize import MosesPunctNormalizer + + +def main(args): + normalizer = MosesPunctNormalizer(lang=args.lang, penn=args.penn) + for line in sys.stdin: + print(normalizer.normalize(line.rstrip()), flush=True) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--lang", "-l", default="en") + parser.add_argument("--penn", "-p", action="store_true") + args = parser.parse_args() + + main(args) diff --git a/fairseq-tools/fairseq/examples/constrained_decoding/tok.py b/fairseq-tools/fairseq/examples/constrained_decoding/tok.py new file mode 100644 index 00000000..b1f888a8 --- /dev/null +++ b/fairseq-tools/fairseq/examples/constrained_decoding/tok.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys + +import sacremoses + + +def main(args): + """Tokenizes, preserving tabs""" + mt = sacremoses.MosesTokenizer(lang=args.lang) + + def tok(s): + return mt.tokenize(s, return_str=True) + + for line in sys.stdin: + parts = list(map(tok, line.split("\t"))) + print(*parts, sep="\t", flush=True) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("--lang", "-l", default="en") + parser.add_argument("--penn", "-p", action="store_true") + parser.add_argument("--fields", "-f", help="fields to tokenize") + args = parser.parse_args() + + main(args) diff --git a/fairseq-tools/fairseq/examples/conv_seq2seq/README.md b/fairseq-tools/fairseq/examples/conv_seq2seq/README.md new file mode 100644 index 00000000..95fe7e79 --- /dev/null +++ b/fairseq-tools/fairseq/examples/conv_seq2seq/README.md @@ -0,0 +1,25 @@ +# Convolutional Sequence to Sequence Learning (Gehring et al., 2017) + +## Pre-trained models + +Description | Dataset | Model | Test set(s) +---|---|---|--- +Convolutional
([Gehring et al., 2017](https://arxiv.org/abs/1705.03122)) | [WMT14 English-French](http://statmt.org/wmt14/translation-task.html#Download) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2) | newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.v2.en-fr.newstest2014.tar.bz2)
newstest2012/2013:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.v2.en-fr.ntst1213.tar.bz2) +Convolutional
([Gehring et al., 2017](https://arxiv.org/abs/1705.03122)) | [WMT14 English-German](http://statmt.org/wmt14/translation-task.html#Download) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/wmt14.en-de.fconv-py.tar.bz2) | newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.en-de.newstest2014.tar.bz2) +Convolutional
([Gehring et al., 2017](https://arxiv.org/abs/1705.03122)) | [WMT17 English-German](http://statmt.org/wmt17/translation-task.html#Download) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/wmt17.v2.en-de.fconv-py.tar.bz2) | newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt17.v2.en-de.newstest2014.tar.bz2) + +## Example usage + +See the [translation README](../translation/README.md) for instructions on reproducing results for WMT'14 En-De and +WMT'14 En-Fr using the `fconv_wmt_en_de` and `fconv_wmt_en_fr` model architectures. + +## Citation + +```bibtex +@inproceedings{gehring2017convs2s, + title = {Convolutional Sequence to Sequence Learning}, + author = {Gehring, Jonas, and Auli, Michael and Grangier, David and Yarats, Denis and Dauphin, Yann N}, + booktitle = {Proc. of ICML}, + year = 2017, +} +``` diff --git a/fairseq-tools/fairseq/examples/criss/README.md b/fairseq-tools/fairseq/examples/criss/README.md new file mode 100644 index 00000000..a5340562 --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/README.md @@ -0,0 +1,51 @@ +# Cross-lingual Retrieval for Iterative Self-Supervised Training + +https://arxiv.org/pdf/2006.09526.pdf + +## Introduction + +CRISS is a multilingual sequence-to-sequnce pretraining method where mining and training processes are applied iteratively, improving cross-lingual alignment and translation ability at the same time. + +## Unsupervised Machine Translation +##### 1. Download and decompress CRISS checkpoints +``` +cd examples/criss +wget https://dl.fbaipublicfiles.com/fairseq/models/criss/criss_checkpoints.tar.gz +tar -xf criss_checkpoints.tar.gz +``` +##### 2. Download and preprocess Flores test dataset +``` +bash download_and_preprocess_flores_test.sh +``` + +##### 3. Run Evaluation on Sinhala-English +``` +bash unsupervised_mt/eval.sh +``` + +## Sentence Retrieval +##### 1. Download and preprocess Tatoeba dataset +``` +bash download_and_preprocess_tatoeba.sh +``` + +##### 2. Run Sentence Retrieval on Tatoeba Kazakh-English +``` +bash sentence_retrieval/sentence_retrieval_tatoeba.sh +``` + +## Mining +##### 1. Mine pseudo-parallel +``` +bash sentence_retrieval/sentence_retrieval_tatoeba.sh +``` + +## Citation +```bibtex +@article{tran2020cross, + title={Cross-lingual retrieval for iterative self-supervised training}, + author={Tran, Chau and Tang, Yuqing and Li, Xian and Gu, Jiatao}, + journal={arXiv preprint arXiv:2006.09526}, + year={2020} +} +``` diff --git a/fairseq-tools/fairseq/examples/criss/download_and_preprocess_flores_test.sh b/fairseq-tools/fairseq/examples/criss/download_and_preprocess_flores_test.sh new file mode 100644 index 00000000..ed4b390f --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/download_and_preprocess_flores_test.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +SPM_ENCODE=flores/scripts/spm_encode.py +DATA=data_tmp +SPM_MODEL=criss_checkpoints/sentence.bpe.model +DICT=criss_checkpoints/dict.txt + +download_data() { + CORPORA=$1 + URL=$2 + + if [ -f $CORPORA ]; then + echo "$CORPORA already exists, skipping download" + else + echo "Downloading $URL" + wget $URL -O $CORPORA --no-check-certificate || rm -f $CORPORA + if [ -f $CORPORA ]; then + echo "$URL successfully downloaded." + else + echo "$URL not successfully downloaded." + rm -f $CORPORA + fi + fi +} + +if [[ -f flores ]]; then + echo "flores already cloned" +else + git clone https://github.com/facebookresearch/flores +fi + +mkdir -p $DATA +download_data $DATA/wikipedia_en_ne_si_test_sets.tgz "https://github.com/facebookresearch/flores/raw/master/data/wikipedia_en_ne_si_test_sets.tgz" +pushd $DATA +pwd +tar -vxf wikipedia_en_ne_si_test_sets.tgz +popd + + +for lang in ne_NP si_LK; do + datadir=$DATA/${lang}-en_XX-flores + rm -rf $datadir + mkdir -p $datadir + TEST_PREFIX=$DATA/wikipedia_en_ne_si_test_sets/wikipedia.test + python $SPM_ENCODE \ + --model ${SPM_MODEL} \ + --output_format=piece \ + --inputs ${TEST_PREFIX}.${lang:0:2}-en.${lang:0:2} ${TEST_PREFIX}.${lang:0:2}-en.en \ + --outputs $datadir/test.bpe.${lang}-en_XX.${lang} $datadir/test.bpe.${lang}-en_XX.en_XX + + # binarize data + fairseq-preprocess \ + --source-lang ${lang} --target-lang en_XX \ + --testpref $datadir/test.bpe.${lang}-en_XX \ + --destdir $datadir \ + --srcdict ${DICT} \ + --joined-dictionary \ + --workers 4 +done diff --git a/fairseq-tools/fairseq/examples/criss/download_and_preprocess_tatoeba.sh b/fairseq-tools/fairseq/examples/criss/download_and_preprocess_tatoeba.sh new file mode 100644 index 00000000..4579d65a --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/download_and_preprocess_tatoeba.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +SPM_ENCODE=flores/scripts/spm_encode.py +DATA=data_tmp +SPM_MODEL=criss_checkpoints/sentence.bpe.model +DICT=criss_checkpoints/dict.txt + +git clone https://github.com/facebookresearch/LASER +mkdir -p data_tmp +declare -A lang_tatoeba_map=( ["ar_AR"]="ara" ["de_DE"]="deu" ["es_XX"]="spa" ["et_EE"]="est" ["fi_FI"]="fin" ["fr_XX"]="fra" ["hi_IN"]="hin" ["it_IT"]="ita" ["ja_XX"]="jpn" ["ko_KR"]="kor" ["kk_KZ"]="kaz" ["nl_XX"]="nld" ["ru_RU"]="rus" ["tr_TR"]="tur" ["vi_VN"]="vie" ["zh_CN"]="cmn") +for lang in ar_AR de_DE es_XX et_EE fi_FI fr_XX hi_IN it_IT ja_XX kk_KZ ko_KR nl_XX ru_RU tr_TR vi_VN zh_CN; do + lang_tatoeba=${lang_tatoeba_map[$lang]} + echo $lang_tatoeba + datadir=$DATA/${lang}-en_XX-tatoeba + rm -rf $datadir + mkdir -p $datadir + TEST_PREFIX=LASER/data/tatoeba/v1/tatoeba + python $SPM_ENCODE \ + --model ${SPM_MODEL} \ + --output_format=piece \ + --inputs ${TEST_PREFIX}.${lang_tatoeba}-eng.${lang_tatoeba} ${TEST_PREFIX}.${lang_tatoeba}-eng.eng \ + --outputs $datadir/test.bpe.${lang}-en_XX.${lang} $datadir/test.bpe.${lang}-en_XX.en_XX + + # binarize data + fairseq-preprocess \ + --source-lang ${lang} --target-lang en_XX \ + --testpref $datadir/test.bpe.${lang}-en_XX \ + --destdir $datadir \ + --srcdict ${DICT} \ + --joined-dictionary \ + --workers 4 +done diff --git a/fairseq-tools/fairseq/examples/criss/mining/mine.py b/fairseq-tools/fairseq/examples/criss/mining/mine.py new file mode 100644 index 00000000..c86f73ae --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/mining/mine.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +import argparse +import glob +from subprocess import check_call + +import faiss +import numpy as np + + +GB = 1024 * 1024 * 1024 + + +def call(cmd): + print(cmd) + check_call(cmd, shell=True) + + +def get_batches(directory, lang, prefix="all_avg_pool"): + print(f"Finding in {directory}/{prefix}.{lang}*") + files = glob.glob(f"{directory}/{prefix}.{lang}*") + emb_files = [] + txt_files = [] + for emb_fi in files: + emb_files.append(emb_fi) + txt_fi = emb_fi.replace(prefix, "sentences") + txt_files.append(txt_fi) + return emb_files, txt_files + + +def load_batch(emb_file, dim): + embeddings = np.fromfile(emb_file, dtype=np.float32) + num_rows = int(embeddings.shape[0] / dim) + embeddings = embeddings.reshape((num_rows, dim)) + faiss.normalize_L2(embeddings) + return embeddings + + +def knnGPU_sharded(x_batches_f, y_batches_f, dim, k, direction="x2y"): + sims = [] + inds = [] + xfrom = 0 + xto = 0 + for x_batch_f in x_batches_f: + yfrom = 0 + yto = 0 + x_batch = load_batch(x_batch_f, dim) + xto = xfrom + x_batch.shape[0] + bsims, binds = [], [] + for y_batch_f in y_batches_f: + y_batch = load_batch(y_batch_f, dim) + neighbor_size = min(k, y_batch.shape[0]) + yto = yfrom + y_batch.shape[0] + print("{}-{} -> {}-{}".format(xfrom, xto, yfrom, yto)) + idx = faiss.IndexFlatIP(dim) + idx = faiss.index_cpu_to_all_gpus(idx) + idx.add(y_batch) + bsim, bind = idx.search(x_batch, neighbor_size) + + bsims.append(bsim) + binds.append(bind + yfrom) + yfrom += y_batch.shape[0] + del idx + del y_batch + bsims = np.concatenate(bsims, axis=1) + binds = np.concatenate(binds, axis=1) + aux = np.argsort(-bsims, axis=1) + sim_batch = np.zeros((x_batch.shape[0], k), dtype=np.float32) + ind_batch = np.zeros((x_batch.shape[0], k), dtype=np.int64) + for i in range(x_batch.shape[0]): + for j in range(k): + sim_batch[i, j] = bsims[i, aux[i, j]] + ind_batch[i, j] = binds[i, aux[i, j]] + sims.append(sim_batch) + inds.append(ind_batch) + xfrom += x_batch.shape[0] + del x_batch + sim = np.concatenate(sims, axis=0) + ind = np.concatenate(inds, axis=0) + return sim, ind + + +def score(sim, fwd_mean, bwd_mean, margin): + return margin(sim, (fwd_mean + bwd_mean) / 2) + + +def score_candidates( + sim_mat, candidate_inds, fwd_mean, bwd_mean, margin, verbose=False +): + print(" - scoring {:d} candidates".format(sim_mat.shape[0])) + scores = np.zeros(candidate_inds.shape) + for i in range(scores.shape[0]): + for j in range(scores.shape[1]): + k = int(candidate_inds[i, j]) + scores[i, j] = score(sim_mat[i, j], fwd_mean[i], bwd_mean[k], margin) + return scores + + +def load_text(files): + all_sentences = [] + for fi in files: + with open(fi) as sentence_fi: + for line in sentence_fi: + all_sentences.append(line.strip()) + print(f"Read {len(all_sentences)} sentences") + return all_sentences + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Mine bitext") + parser.add_argument("--src-lang", help="Source language") + parser.add_argument("--tgt-lang", help="Target language") + parser.add_argument( + "--dict-path", help="Path to dictionary file", default="dict.txt" + ) + parser.add_argument( + "--spm-path", help="Path to SPM model file", default="sentence.bpe.model" + ) + parser.add_argument("--dim", type=int, default=1024, help="Embedding dimension") + parser.add_argument("--mem", type=int, default=5, help="Memory in GB") + parser.add_argument("--src-dir", help="Source directory") + parser.add_argument("--tgt-dir", help="Target directory") + parser.add_argument("--output", help="Output path") + parser.add_argument( + "--neighborhood", type=int, default=4, help="Embedding dimension" + ) + parser.add_argument( + "--threshold", type=float, default=1.06, help="Threshold on mined bitext" + ) + parser.add_argument( + "--valid-size", + type=int, + default=2000, + help="Number of sentences used for validation set", + ) + parser.add_argument( + "--min-count", + type=int, + default=50000, + help="Min num sentences used for each language", + ) + args = parser.parse_args() + + x_batches_f, x_sents_f = get_batches(args.src_dir, args.src_lang) + y_batches_f, y_sents_f = get_batches(args.tgt_dir, args.tgt_lang) + margin = lambda a, b: a / b + y2x_sim, y2x_ind = knnGPU_sharded( + y_batches_f, x_batches_f, args.dim, args.neighborhood, direction="y2x" + ) + x2y_sim, x2y_ind = knnGPU_sharded( + x_batches_f, y_batches_f, args.dim, args.neighborhood, direction="x2y" + ) + + x2y_mean = x2y_sim.mean(axis=1) + y2x_mean = y2x_sim.mean(axis=1) + fwd_scores = score_candidates(x2y_sim, x2y_ind, x2y_mean, y2x_mean, margin) + bwd_scores = score_candidates(y2x_sim, y2x_ind, y2x_mean, x2y_mean, margin) + fwd_best = x2y_ind[np.arange(x2y_sim.shape[0]), fwd_scores.argmax(axis=1)] + bwd_best = y2x_ind[np.arange(y2x_sim.shape[0]), bwd_scores.argmax(axis=1)] + indices = np.stack( + ( + np.concatenate((np.arange(x2y_ind.shape[0]), bwd_best)), + np.concatenate((fwd_best, np.arange(y2x_ind.shape[0]))), + ), + axis=1, + ) + scores = np.concatenate((fwd_scores.max(axis=1), bwd_scores.max(axis=1))) + + x_sentences = load_text(x_sents_f) + y_sentences = load_text(y_sents_f) + + threshold = args.threshold + min_count = args.min_count + seen_src, seen_trg = set(), set() + directory = args.output + call(f"mkdir -p {directory}") + src_out = open( + f"{directory}/all.{args.src_lang}", + mode="w", + encoding="utf-8", + errors="surrogateescape", + ) + tgt_out = open( + f"{directory}/all.{args.tgt_lang}", + mode="w", + encoding="utf-8", + errors="surrogateescape", + ) + scores_out = open( + f"{directory}/all.scores", mode="w", encoding="utf-8", errors="surrogateescape" + ) + count = 0 + for i in np.argsort(-scores): + src_ind, trg_ind = indices[i] + if src_ind not in seen_src and trg_ind not in seen_trg: + seen_src.add(src_ind) + seen_trg.add(trg_ind) + if scores[i] > threshold or count < min_count: + if x_sentences[src_ind]: + print(scores[i], file=scores_out) + print(x_sentences[src_ind], file=src_out) + print(y_sentences[trg_ind], file=tgt_out) + count += 1 + else: + print(f"Ignoring sentence: {x_sentences[src_ind]}") + src_out.close() + tgt_out.close() + scores_out.close() + + print(f"Found {count} pairs for threshold={threshold}") + with open(f"{directory}/all.{args.src_lang}") as all_s, open( + f"{directory}/all.{args.tgt_lang}" + ) as all_t, open(f"{directory}/valid.{args.src_lang}", "w") as valid_s, open( + f"{directory}/valid.{args.tgt_lang}", "w" + ) as valid_t, open( + f"{directory}/train.{args.src_lang}", "w" + ) as train_s, open( + f"{directory}/train.{args.tgt_lang}", "w" + ) as train_t: + count = 0 + for s_line, t_line in zip(all_s, all_t): + s_line = s_line.split("\t")[1] + t_line = t_line.split("\t")[1] + if count >= args.valid_size: + train_s.write(s_line) + train_t.write(t_line) + else: + valid_s.write(s_line) + valid_t.write(t_line) + count += 1 diff --git a/fairseq-tools/fairseq/examples/criss/mining/mine_example.sh b/fairseq-tools/fairseq/examples/criss/mining/mine_example.sh new file mode 100644 index 00000000..92b52913 --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/mining/mine_example.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. +# +source_lang=kk_KZ +target_lang=en_XX +MODEL=criss_checkpoints/criss.2nd.pt +SPM=criss_checkpoints/sentence.bpe.model +SPLIT=test +LANG_DICT=criss_checkpoints/lang_dict.txt +SPM_ENCODE=flores/scripts/spm_encode.py +SAVE_ENCODER=save_encoder.py +ENCODER_SAVE_ROOT=sentence_embeddings/$MODEL +DICT=criss_checkpoints/dict.txt +THRESHOLD=1.02 +MIN_COUNT=500 + +DATA_DIR=data_tmp +SAVE_DIR=mining/${source_lang}_${target_lang}_mined +ENCODER_SAVE_DIR=${ENCODER_SAVE_ROOT}/${source_lang}-${target_lang} +INPUT_DIR=$DATA_DIR/${source_lang}-${target_lang}-tatoeba + +mkdir -p $ENCODER_SAVE_DIR/${target_lang} +mkdir -p $ENCODER_SAVE_DIR/${source_lang} +mkdir -p $SAVE_DIR + +## Save encoder outputs + +# Save encoder outputs for source sentences +python $SAVE_ENCODER \ + ${INPUT_DIR} \ + --path ${MODEL} \ + --task translation_multi_simple_epoch \ + --lang-pairs ${source_lang}-${target_lang} \ + --lang-dict ${LANG_DICT} \ + --gen-subset ${SPLIT} \ + --bpe 'sentencepiece' \ + -s ${source_lang} -t ${target_lang} \ + --sentencepiece-model ${SPM} \ + --remove-bpe 'sentencepiece' \ + --beam 1 \ + --lang-tok-style mbart \ + --encoder-save-dir ${ENCODER_SAVE_DIR}/${source_lang} + +## Save encoder outputs for target sentences +python $SAVE_ENCODER \ + ${INPUT_DIR} \ + --path ${MODEL} \ + --lang-pairs ${source_lang}-${target_lang} \ + --lang-dict ${LANG_DICT} \ + --task translation_multi_simple_epoch \ + --gen-subset ${SPLIT} \ + --bpe 'sentencepiece' \ + -t ${source_lang} -s ${target_lang} \ + --sentencepiece-model ${SPM} \ + --remove-bpe 'sentencepiece' \ + --beam 1 \ + --lang-tok-style mbart \ + --encoder-save-dir ${ENCODER_SAVE_DIR}/${target_lang} + +## Mining +python mining/mine.py \ + --src-lang ${source_lang} \ + --tgt-lang ${target_lang} \ + --dim 1024 \ + --mem 10 \ + --neighborhood 4 \ + --src-dir ${ENCODER_SAVE_DIR}/${source_lang} \ + --tgt-dir ${ENCODER_SAVE_DIR}/${target_lang} \ + --output $SAVE_DIR \ + --threshold ${THRESHOLD} \ + --min-count ${MIN_COUNT} \ + --valid-size 100 \ + --dict-path ${DICT} \ + --spm-path ${SPM} \ + + +## Process and binarize mined data +python $SPM_ENCODE \ + --model ${SPM} \ + --output_format=piece \ + --inputs mining/${source_lang}_${target_lang}_mined/train.${source_lang} mining/${source_lang}_${target_lang}_mined/train.${target_lang} \ + --outputs mining/${source_lang}_${target_lang}_mined/train.bpe.${source_lang} mining/${source_lang}_${target_lang}_mined/train.bpe.${target_lang} + +python $SPM_ENCODE \ + --model ${SPM} \ + --output_format=piece \ + --inputs mining/${source_lang}_${target_lang}_mined/valid.${source_lang} mining/${source_lang}_${target_lang}_mined/valid.${target_lang} \ + --outputs mining/${source_lang}_${target_lang}_mined/valid.bpe.${source_lang} mining/${source_lang}_${target_lang}_mined/valid.bpe.${target_lang} + + +fairseq-preprocess \ + --source-lang ${source_lang} \ + --target-lang ${target_lang} \ + --trainpref mining/${source_lang}_${target_lang}_mined/train.bpe \ + --validpref mining/${source_lang}_${target_lang}_mined/valid.bpe \ + --destdir mining/${source_lang}_${target_lang}_mined \ + --srcdict ${DICT} \ + --joined-dictionary \ + --workers 8 diff --git a/fairseq-tools/fairseq/examples/criss/save_encoder.py b/fairseq-tools/fairseq/examples/criss/save_encoder.py new file mode 100644 index 00000000..4d0f17f0 --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/save_encoder.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Translate pre-processed data with a trained model. +""" + +import numpy as np +import torch +from fairseq import checkpoint_utils, options, progress_bar, tasks, utils +from fairseq.sequence_generator import EnsembleModel + + +def get_avg_pool( + models, sample, prefix_tokens, src_dict, remove_bpe, has_langtok=False +): + model = EnsembleModel(models) + + # model.forward normally channels prev_output_tokens into the decoder + # separately, but SequenceGenerator directly calls model.encoder + encoder_input = { + k: v for k, v in sample["net_input"].items() if k != "prev_output_tokens" + } + + # compute the encoder output for each beam + encoder_outs = model.forward_encoder(encoder_input) + np_encoder_outs = encoder_outs[0].encoder_out.cpu().numpy().astype(np.float32) + encoder_mask = 1 - encoder_outs[0].encoder_padding_mask.cpu().numpy().astype( + np.float32 + ) + encoder_mask = np.expand_dims(encoder_mask.T, axis=2) + if has_langtok: + encoder_mask = encoder_mask[1:, :, :] + np_encoder_outs = np_encoder_outs[1, :, :] + masked_encoder_outs = encoder_mask * np_encoder_outs + avg_pool = (masked_encoder_outs / encoder_mask.sum(axis=0)).sum(axis=0) + return avg_pool + + +def main(args): + assert args.path is not None, "--path required for generation!" + assert ( + not args.sampling or args.nbest == args.beam + ), "--sampling requires --nbest to be equal to --beam" + assert ( + args.replace_unk is None or args.raw_text + ), "--replace-unk requires a raw text dataset (--raw-text)" + + args.beam = 1 + utils.import_user_module(args) + + if args.max_tokens is None: + args.max_tokens = 12000 + print(args) + use_cuda = torch.cuda.is_available() and not args.cpu + + # Load dataset splits + task = tasks.setup_task(args) + task.load_dataset(args.gen_subset) + + # Set dictionaries + try: + src_dict = getattr(task, "source_dictionary", None) + except NotImplementedError: + src_dict = None + tgt_dict = task.target_dictionary + + # Load ensemble + print("| loading model(s) from {}".format(args.path)) + models, _model_args = checkpoint_utils.load_model_ensemble( + args.path.split(":"), + arg_overrides=eval(args.model_overrides), + task=task, + ) + + # Optimize ensemble for generation + for model in models: + model.make_generation_fast_( + beamable_mm_beam_size=None if args.no_beamable_mm else args.beam, + need_attn=args.print_alignment, + ) + if args.fp16: + model.half() + if use_cuda: + model.cuda() + + # Load alignment dictionary for unknown word replacement + # (None if no unknown word replacement, empty if no path to align dictionary) + align_dict = utils.load_align_dict(args.replace_unk) + + # Load dataset (possibly sharded) + itr = task.get_batch_iterator( + dataset=task.dataset(args.gen_subset), + max_tokens=args.max_tokens, + max_positions=utils.resolve_max_positions( + task.max_positions(), + ), + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=args.required_batch_size_multiple, + num_shards=args.num_shards, + shard_id=args.shard_id, + num_workers=args.num_workers, + ).next_epoch_itr(shuffle=False) + + num_sentences = 0 + source_sentences = [] + shard_id = 0 + all_avg_pool = None + encoder_has_langtok = ( + hasattr(task.args, "encoder_langtok") + and task.args.encoder_langtok is not None + and hasattr(task.args, "lang_tok_replacing_bos_eos") + and not task.args.lang_tok_replacing_bos_eos + ) + with progress_bar.build_progress_bar(args, itr) as t: + for sample in t: + if sample is None: + print("Skipping None") + continue + sample = utils.move_to_cuda(sample) if use_cuda else sample + if "net_input" not in sample: + continue + + prefix_tokens = None + if args.prefix_size > 0: + prefix_tokens = sample["target"][:, : args.prefix_size] + + with torch.no_grad(): + avg_pool = get_avg_pool( + models, + sample, + prefix_tokens, + src_dict, + args.remove_bpe, + has_langtok=encoder_has_langtok, + ) + if all_avg_pool is not None: + all_avg_pool = np.concatenate((all_avg_pool, avg_pool)) + else: + all_avg_pool = avg_pool + + if not isinstance(sample["id"], list): + sample_ids = sample["id"].tolist() + else: + sample_ids = sample["id"] + for i, sample_id in enumerate(sample_ids): + # Remove padding + src_tokens = utils.strip_pad( + sample["net_input"]["src_tokens"][i, :], tgt_dict.pad() + ) + + # Either retrieve the original sentences or regenerate them from tokens. + if align_dict is not None: + src_str = task.dataset(args.gen_subset).src.get_original_text( + sample_id + ) + else: + if src_dict is not None: + src_str = src_dict.string(src_tokens, args.remove_bpe) + else: + src_str = "" + + if not args.quiet: + if src_dict is not None: + print("S-{}\t{}".format(sample_id, src_str)) + + source_sentences.append(f"{sample_id}\t{src_str}") + + num_sentences += sample["nsentences"] + if all_avg_pool.shape[0] >= 1000000: + with open( + f"{args.encoder_save_dir}/all_avg_pool.{args.source_lang}.{shard_id}", + "w", + ) as avg_pool_file: + all_avg_pool.tofile(avg_pool_file) + with open( + f"{args.encoder_save_dir}/sentences.{args.source_lang}.{shard_id}", + "w", + ) as sentence_file: + sentence_file.writelines(f"{line}\n" for line in source_sentences) + all_avg_pool = None + source_sentences = [] + shard_id += 1 + + if all_avg_pool is not None: + with open( + f"{args.encoder_save_dir}/all_avg_pool.{args.source_lang}.{shard_id}", "w" + ) as avg_pool_file: + all_avg_pool.tofile(avg_pool_file) + with open( + f"{args.encoder_save_dir}/sentences.{args.source_lang}.{shard_id}", "w" + ) as sentence_file: + sentence_file.writelines(f"{line}\n" for line in source_sentences) + return None + + +def cli_main(): + parser = options.get_generation_parser() + parser.add_argument( + "--encoder-save-dir", + default="", + type=str, + metavar="N", + help="directory to save encoder outputs", + ) + args = options.parse_args_and_arch(parser) + main(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/criss/sentence_retrieval/encoder_analysis.py b/fairseq-tools/fairseq/examples/criss/sentence_retrieval/encoder_analysis.py new file mode 100644 index 00000000..b41bfbe3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/sentence_retrieval/encoder_analysis.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +import argparse +import glob + +import numpy as np + + +DIM = 1024 + + +def compute_dist(source_embs, target_embs, k=5, return_sim_mat=False): + target_ids = [tid for tid in target_embs] + source_mat = np.stack(source_embs.values(), axis=0) + normalized_source_mat = source_mat / np.linalg.norm( + source_mat, axis=1, keepdims=True + ) + target_mat = np.stack(target_embs.values(), axis=0) + normalized_target_mat = target_mat / np.linalg.norm( + target_mat, axis=1, keepdims=True + ) + sim_mat = normalized_source_mat.dot(normalized_target_mat.T) + if return_sim_mat: + return sim_mat + neighbors_map = {} + for i, sentence_id in enumerate(source_embs): + idx = np.argsort(sim_mat[i, :])[::-1][:k] + neighbors_map[sentence_id] = [target_ids[tid] for tid in idx] + return neighbors_map + + +def load_embeddings(directory, LANGS): + sentence_embeddings = {} + sentence_texts = {} + for lang in LANGS: + sentence_embeddings[lang] = {} + sentence_texts[lang] = {} + lang_dir = f"{directory}/{lang}" + embedding_files = glob.glob(f"{lang_dir}/all_avg_pool.{lang}.*") + for embed_file in embedding_files: + shard_id = embed_file.split(".")[-1] + embeddings = np.fromfile(embed_file, dtype=np.float32) + num_rows = embeddings.shape[0] // DIM + embeddings = embeddings.reshape((num_rows, DIM)) + + with open(f"{lang_dir}/sentences.{lang}.{shard_id}") as sentence_file: + for idx, line in enumerate(sentence_file): + sentence_id, sentence = line.strip().split("\t") + sentence_texts[lang][sentence_id] = sentence + sentence_embeddings[lang][sentence_id] = embeddings[idx, :] + + return sentence_embeddings, sentence_texts + + +def compute_accuracy(directory, LANGS): + sentence_embeddings, sentence_texts = load_embeddings(directory, LANGS) + + top_1_accuracy = {} + + top1_str = " ".join(LANGS) + "\n" + for source_lang in LANGS: + top_1_accuracy[source_lang] = {} + top1_str += f"{source_lang} " + for target_lang in LANGS: + top1 = 0 + top5 = 0 + neighbors_map = compute_dist( + sentence_embeddings[source_lang], sentence_embeddings[target_lang] + ) + for sentence_id, neighbors in neighbors_map.items(): + if sentence_id == neighbors[0]: + top1 += 1 + if sentence_id in neighbors[:5]: + top5 += 1 + n = len(sentence_embeddings[target_lang]) + top1_str += f"{top1/n} " + top1_str += "\n" + + print(top1_str) + print(top1_str, file=open(f"{directory}/accuracy", "w")) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Analyze encoder outputs") + parser.add_argument("directory", help="Source language corpus") + parser.add_argument("--langs", help="List of langs") + args = parser.parse_args() + langs = args.langs.split(",") + compute_accuracy(args.directory, langs) diff --git a/fairseq-tools/fairseq/examples/criss/sentence_retrieval/sentence_retrieval_tatoeba.sh b/fairseq-tools/fairseq/examples/criss/sentence_retrieval/sentence_retrieval_tatoeba.sh new file mode 100644 index 00000000..0428d8be --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/sentence_retrieval/sentence_retrieval_tatoeba.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. +# +source_lang=kk_KZ +target_lang=en_XX +MODEL=criss_checkpoints/criss.3rd.pt +SPM=criss_checkpoints/sentence.bpe.model +SPLIT=test +LANG_DICT=criss_checkpoints/lang_dict.txt +ENCODER_ANALYSIS=sentence_retrieval/encoder_analysis.py +SAVE_ENCODER=save_encoder.py +ENCODER_SAVE_ROOT=sentence_embeddings/$MODEL + + + +DATA_DIR=data_tmp +INPUT_DIR=$DATA_DIR/${source_lang}-${target_lang}-tatoeba +ENCODER_SAVE_DIR=${ENCODER_SAVE_ROOT}/${source_lang}-${target_lang} +mkdir -p $ENCODER_SAVE_DIR/${target_lang} +mkdir -p $ENCODER_SAVE_DIR/${source_lang} + +# Save encoder outputs for source sentences +python $SAVE_ENCODER \ + ${INPUT_DIR} \ + --path ${MODEL} \ + --task translation_multi_simple_epoch \ + --lang-dict ${LANG_DICT} \ + --gen-subset ${SPLIT} \ + --bpe 'sentencepiece' \ + --lang-pairs ${source_lang}-${target_lang} \ + -s ${source_lang} -t ${target_lang} \ + --sentencepiece-model ${SPM} \ + --remove-bpe 'sentencepiece' \ + --beam 1 \ + --lang-tok-style mbart \ + --encoder-save-dir ${ENCODER_SAVE_DIR}/${source_lang} + +# Save encoder outputs for target sentences +python $SAVE_ENCODER \ + ${INPUT_DIR} \ + --path ${MODEL} \ + --lang-dict ${LANG_DICT} \ + --task translation_multi_simple_epoch \ + --gen-subset ${SPLIT} \ + --bpe 'sentencepiece' \ + --lang-pairs ${target_lang}-${source_lang} \ + -t ${source_lang} -s ${target_lang} \ + --sentencepiece-model ${SPM} \ + --remove-bpe 'sentencepiece' \ + --beam 1 \ + --lang-tok-style mbart \ + --encoder-save-dir ${ENCODER_SAVE_DIR}/${target_lang} + +# Analyze sentence retrieval accuracy +python $ENCODER_ANALYSIS --langs "${source_lang},${target_lang}" ${ENCODER_SAVE_DIR} diff --git a/fairseq-tools/fairseq/examples/criss/unsupervised_mt/eval.sh b/fairseq-tools/fairseq/examples/criss/unsupervised_mt/eval.sh new file mode 100644 index 00000000..03b773ed --- /dev/null +++ b/fairseq-tools/fairseq/examples/criss/unsupervised_mt/eval.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. +# +SRC=si_LK +TGT=en_XX +MODEL=criss_checkpoints/criss.3rd.pt + +MULTIBLEU=mosesdecoder/scripts/generic/multi-bleu.perl +MOSES=mosesdecoder +REPLACE_UNICODE_PUNCT=$MOSES/scripts/tokenizer/replace-unicode-punctuation.perl +NORM_PUNC=$MOSES/scripts/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$MOSES/scripts/tokenizer/remove-non-printing-char.perl +TOKENIZER=$MOSES/scripts/tokenizer/tokenizer.perl +GEN_TMP_DIR=gen_tmp +LANG_DICT=criss_checkpoints/lang_dict.txt + +if [ ! -d "mosesdecoder" ]; then + git clone https://github.com/moses-smt/mosesdecoder +fi +mkdir -p $GEN_TMP_DIR +fairseq-generate data_tmp/${SRC}-${TGT}-flores \ + --task translation_multi_simple_epoch \ + --max-tokens 2000 \ + --path ${MODEL} \ + --skip-invalid-size-inputs-valid-test \ + --beam 5 --lenpen 1.0 --gen-subset test \ + --remove-bpe=sentencepiece \ + --source-lang ${SRC} --target-lang ${TGT} \ + --decoder-langtok --lang-pairs 'en_XX-ar_AR,en_XX-de_DE,en_XX-es_XX,en_XX-fr_XX,en_XX-hi_IN,en_XX-it_IT,en_XX-ja_XX,en_XX-ko_KR,en_XX-nl_XX,en_XX-ru_RU,en_XX-zh_CN,en_XX-tr_TR,en_XX-vi_VN,en_XX-ro_RO,en_XX-my_MM,en_XX-ne_NP,en_XX-si_LK,en_XX-cs_CZ,en_XX-lt_LT,en_XX-kk_KZ,en_XX-gu_IN,en_XX-fi_FI,en_XX-et_EE,en_XX-lv_LV,ar_AR-en_XX,cs_CZ-en_XX,de_DE-en_XX,es_XX-en_XX,et_EE-en_XX,fi_FI-en_XX,fr_XX-en_XX,gu_IN-en_XX,hi_IN-en_XX,it_IT-en_XX,ja_XX-en_XX,kk_KZ-en_XX,ko_KR-en_XX,lt_LT-en_XX,lv_LV-en_XX,my_MM-en_XX,ne_NP-en_XX,nl_XX-en_XX,ro_RO-en_XX,ru_RU-en_XX,si_LK-en_XX,tr_TR-en_XX,vi_VN-en_XX,zh_CN-en_XX,ar_AR-es_XX,es_XX-ar_AR,ar_AR-hi_IN,hi_IN-ar_AR,ar_AR-zh_CN,zh_CN-ar_AR,cs_CZ-es_XX,es_XX-cs_CZ,cs_CZ-hi_IN,hi_IN-cs_CZ,cs_CZ-zh_CN,zh_CN-cs_CZ,de_DE-es_XX,es_XX-de_DE,de_DE-hi_IN,hi_IN-de_DE,de_DE-zh_CN,zh_CN-de_DE,es_XX-hi_IN,hi_IN-es_XX,es_XX-zh_CN,zh_CN-es_XX,et_EE-es_XX,es_XX-et_EE,et_EE-hi_IN,hi_IN-et_EE,et_EE-zh_CN,zh_CN-et_EE,fi_FI-es_XX,es_XX-fi_FI,fi_FI-hi_IN,hi_IN-fi_FI,fi_FI-zh_CN,zh_CN-fi_FI,fr_XX-es_XX,es_XX-fr_XX,fr_XX-hi_IN,hi_IN-fr_XX,fr_XX-zh_CN,zh_CN-fr_XX,gu_IN-es_XX,es_XX-gu_IN,gu_IN-hi_IN,hi_IN-gu_IN,gu_IN-zh_CN,zh_CN-gu_IN,hi_IN-zh_CN,zh_CN-hi_IN,it_IT-es_XX,es_XX-it_IT,it_IT-hi_IN,hi_IN-it_IT,it_IT-zh_CN,zh_CN-it_IT,ja_XX-es_XX,es_XX-ja_XX,ja_XX-hi_IN,hi_IN-ja_XX,ja_XX-zh_CN,zh_CN-ja_XX,kk_KZ-es_XX,es_XX-kk_KZ,kk_KZ-hi_IN,hi_IN-kk_KZ,kk_KZ-zh_CN,zh_CN-kk_KZ,ko_KR-es_XX,es_XX-ko_KR,ko_KR-hi_IN,hi_IN-ko_KR,ko_KR-zh_CN,zh_CN-ko_KR,lt_LT-es_XX,es_XX-lt_LT,lt_LT-hi_IN,hi_IN-lt_LT,lt_LT-zh_CN,zh_CN-lt_LT,lv_LV-es_XX,es_XX-lv_LV,lv_LV-hi_IN,hi_IN-lv_LV,lv_LV-zh_CN,zh_CN-lv_LV,my_MM-es_XX,es_XX-my_MM,my_MM-hi_IN,hi_IN-my_MM,my_MM-zh_CN,zh_CN-my_MM,ne_NP-es_XX,es_XX-ne_NP,ne_NP-hi_IN,hi_IN-ne_NP,ne_NP-zh_CN,zh_CN-ne_NP,nl_XX-es_XX,es_XX-nl_XX,nl_XX-hi_IN,hi_IN-nl_XX,nl_XX-zh_CN,zh_CN-nl_XX,ro_RO-es_XX,es_XX-ro_RO,ro_RO-hi_IN,hi_IN-ro_RO,ro_RO-zh_CN,zh_CN-ro_RO,ru_RU-es_XX,es_XX-ru_RU,ru_RU-hi_IN,hi_IN-ru_RU,ru_RU-zh_CN,zh_CN-ru_RU,si_LK-es_XX,es_XX-si_LK,si_LK-hi_IN,hi_IN-si_LK,si_LK-zh_CN,zh_CN-si_LK,tr_TR-es_XX,es_XX-tr_TR,tr_TR-hi_IN,hi_IN-tr_TR,tr_TR-zh_CN,zh_CN-tr_TR,vi_VN-es_XX,es_XX-vi_VN,vi_VN-hi_IN,hi_IN-vi_VN,vi_VN-zh_CN,zh_CN-vi_VN' \ + --lang-dict ${LANG_DICT} --lang-tok-style 'mbart' --sampling-method 'temperature' --sampling-temperature '1.0' > $GEN_TMP_DIR/${SRC}_${TGT}.gen +cat $GEN_TMP_DIR/${SRC}_${TGT}.gen | grep -P "^T-" | cut -f2 | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l ${TGT:0:2} | $REM_NON_PRINT_CHAR | $TOKENIZER -no-escape ${TGT:0:2} > $GEN_TMP_DIR/${SRC}_${TGT}.hyp +cat $GEN_TMP_DIR/${SRC}_${TGT}.gen | grep -P "^H-" | cut -f3 | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l ${TGT:0:2} | $REM_NON_PRINT_CHAR | $TOKENIZER -no-escape ${TGT:0:2} > $GEN_TMP_DIR/${SRC}_${TGT}.ref +${MULTIBLEU} $GEN_TMP_DIR/${SRC}_${TGT}.ref < $GEN_TMP_DIR/${SRC}_${TGT}.hyp diff --git a/fairseq-tools/fairseq/examples/cross_lingual_language_model/README.md b/fairseq-tools/fairseq/examples/cross_lingual_language_model/README.md new file mode 100644 index 00000000..a78f86d8 --- /dev/null +++ b/fairseq-tools/fairseq/examples/cross_lingual_language_model/README.md @@ -0,0 +1,77 @@ +# Cross-Lingual Language Model Pre-training + +Below are some details for training Cross-Lingual Language Models (XLM) - similar to the ones presented in [Lample & Conneau, 2019](https://arxiv.org/pdf/1901.07291.pdf) - in Fairseq. The current implementation only supports the Masked Language Model (MLM) from the paper above. + +## Downloading and Tokenizing Monolingual Data + +Pointers to the monolingual data from wikipedia, used for training the XLM-style MLM model as well as details on processing (tokenization and BPE) it can be found in the [XLM Github Repository](https://github.com/facebookresearch/XLM#download--preprocess-monolingual-data). + +Let's assume the following for the code snippets in later sections to work +- Processed data is in the folder: monolingual_data/processed +- Each language has 3 files for train, test and validation. For example we have the following files for English: + train.en, valid.en +- We are training a model for 5 languages: Arabic (ar), German (de), English (en), Hindi (hi) and French (fr) +- The vocabulary file is monolingual_data/processed/vocab_mlm + + +## Fairseq Pre-processing and Binarization + +Pre-process and binarize the data with the MaskedLMDictionary and cross_lingual_lm task + +```bash +# Ensure the output directory exists +DATA_DIR=monolingual_data/fairseq_processed +mkdir -p "$DATA_DIR" + +for lg in ar de en hi fr +do + + fairseq-preprocess \ + --task cross_lingual_lm \ + --srcdict monolingual_data/processed/vocab_mlm \ + --only-source \ + --trainpref monolingual_data/processed/train \ + --validpref monolingual_data/processed/valid \ + --testpref monolingual_data/processed/test \ + --destdir monolingual_data/fairseq_processed \ + --workers 20 \ + --source-lang $lg + + # Since we only have a source language, the output file has a None for the + # target language. Remove this + + for stage in train test valid + + sudo mv "$DATA_DIR/$stage.$lg-None.$lg.bin" "$stage.$lg.bin" + sudo mv "$DATA_DIR/$stage.$lg-None.$lg.idx" "$stage.$lg.idx" + + done + +done +``` + +## Train a Cross-lingual Language Model similar to the XLM MLM model + +Use the following command to train the model on 5 languages. + +``` +fairseq-train \ +--task cross_lingual_lm monolingual_data/fairseq_processed \ +--save-dir checkpoints/mlm \ +--max-update 2400000 --save-interval 1 --no-epoch-checkpoints \ +--arch xlm_base \ +--optimizer adam --lr-scheduler reduce_lr_on_plateau \ +--lr-shrink 0.5 --lr 0.0001 --min-lr 1e-09 \ +--dropout 0.1 \ +--criterion legacy_masked_lm_loss \ +--max-tokens 2048 --tokens-per-sample 256 --attention-dropout 0.1 \ +--dataset-impl lazy --seed 0 \ +--masked-lm-only \ +--monolingual-langs 'ar,de,en,hi,fr' --num-segment 5 \ +--ddp-backend=no_c10d +``` + +Some Notes: +- Using tokens_per_sample greater than 256 can cause OOM (out-of-memory) issues. Usually since MLM packs in streams of text, this parameter doesn't need much tuning. +- The Evaluation workflow for computing MLM Perplexity on test data is in progress. +- Finetuning this model on a downstream task is something which is not currently available. diff --git a/fairseq-tools/fairseq/examples/joint_alignment_translation/README.md b/fairseq-tools/fairseq/examples/joint_alignment_translation/README.md new file mode 100644 index 00000000..cd9c0ea6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/joint_alignment_translation/README.md @@ -0,0 +1,89 @@ +# Jointly Learning to Align and Translate with Transformer Models (Garg et al., 2019) + +This page includes instructions for training models described in [Jointly Learning to Align and Translate with Transformer Models (Garg et al., 2019)](https://arxiv.org/abs/1909.02074). + +## Training a joint alignment-translation model on WMT'18 En-De + +##### 1. Extract and preprocess the WMT'18 En-De data +```bash +./prepare-wmt18en2de_no_norm_no_escape_no_agressive.sh +``` + +##### 2. Generate alignments from statistical alignment toolkits e.g. Giza++/FastAlign. +In this example, we use FastAlign. +```bash +git clone git@github.com:clab/fast_align.git +pushd fast_align +mkdir build +cd build +cmake .. +make +popd +ALIGN=fast_align/build/fast_align +paste bpe.32k/train.en bpe.32k/train.de | awk -F '\t' '{print $1 " ||| " $2}' > bpe.32k/train.en-de +$ALIGN -i bpe.32k/train.en-de -d -o -v > bpe.32k/train.align +``` + +##### 3. Preprocess the dataset with the above generated alignments. +```bash +fairseq-preprocess \ + --source-lang en --target-lang de \ + --trainpref bpe.32k/train \ + --validpref bpe.32k/valid \ + --testpref bpe.32k/test \ + --align-suffix align \ + --destdir binarized/ \ + --joined-dictionary \ + --workers 32 +``` + +##### 4. Train a model +```bash +fairseq-train \ + binarized \ + --arch transformer_wmt_en_de_big_align --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 --activation-fn relu\ + --lr 0.0002 --lr-scheduler inverse_sqrt --warmup-updates 4000 --warmup-init-lr 1e-07 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 3500 --label-smoothing 0.1 \ + --save-dir ./checkpoints --log-interval 1000 --max-update 60000 \ + --keep-interval-updates -1 --save-interval-updates 0 \ + --load-alignments --criterion label_smoothed_cross_entropy_with_alignment \ + --fp16 +``` + +Note that the `--fp16` flag requires you have CUDA 9.1 or greater and a Volta GPU or newer. + +If you want to train the above model with big batches (assuming your machine has 8 GPUs): +- add `--update-freq 8` to simulate training on 8x8=64 GPUs +- increase the learning rate; 0.0007 works well for big batches + +##### 5. Evaluate and generate the alignments (BPE level) +```bash +fairseq-generate \ + binarized --gen-subset test --print-alignment \ + --source-lang en --target-lang de \ + --path checkpoints/checkpoint_best.pt --beam 5 --nbest 1 +``` + +##### 6. Other resources. +The code for: +1. preparing alignment test sets +2. converting BPE level alignments to token level alignments +3. symmetrizing bidirectional alignments +4. evaluating alignments using AER metric +can be found [here](https://github.com/lilt/alignment-scripts) + +## Citation + +```bibtex +@inproceedings{garg2019jointly, + title = {Jointly Learning to Align and Translate with Transformer Models}, + author = {Garg, Sarthak and Peitz, Stephan and Nallasamy, Udhyakumar and Paulik, Matthias}, + booktitle = {Conference on Empirical Methods in Natural Language Processing (EMNLP)}, + address = {Hong Kong}, + month = {November}, + url = {https://arxiv.org/abs/1909.02074}, + year = {2019}, +} +``` diff --git a/fairseq-tools/fairseq/examples/joint_alignment_translation/prepare-wmt18en2de_no_norm_no_escape_no_agressive.sh b/fairseq-tools/fairseq/examples/joint_alignment_translation/prepare-wmt18en2de_no_norm_no_escape_no_agressive.sh new file mode 100644 index 00000000..e3efeb21 --- /dev/null +++ b/fairseq-tools/fairseq/examples/joint_alignment_translation/prepare-wmt18en2de_no_norm_no_escape_no_agressive.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +echo 'Cloning Moses github repository (for tokenization scripts)...' +git clone https://github.com/moses-smt/mosesdecoder.git + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +CLEAN=$SCRIPTS/training/clean-corpus-n.perl +REM_NON_PRINT_CHAR=$SCRIPTS/tokenizer/remove-non-printing-char.perl + +URLS=( + "http://statmt.org/wmt13/training-parallel-europarl-v7.tgz" + "http://statmt.org/wmt13/training-parallel-commoncrawl.tgz" + "http://data.statmt.org/wmt18/translation-task/training-parallel-nc-v13.tgz" + "http://data.statmt.org/wmt18/translation-task/rapid2016.tgz" + "http://data.statmt.org/wmt17/translation-task/dev.tgz" + "http://statmt.org/wmt14/test-full.tgz" +) +CORPORA=( + "training/europarl-v7.de-en" + "commoncrawl.de-en" + "training-parallel-nc-v13/news-commentary-v13.de-en" + "rapid2016.de-en" +) + +if [ ! -d "$SCRIPTS" ]; then + echo "Please set SCRIPTS variable correctly to point to Moses scripts." + exit +fi + +src=en +tgt=de +lang=en-de +prep=wmt18_en_de +tmp=$prep/tmp +orig=orig +dev=dev/newstest2012 +codes=32000 +bpe=bpe.32k + +mkdir -p $orig $tmp $prep $bpe + +cd $orig + +for ((i=0;i<${#URLS[@]};++i)); do + url=${URLS[i]} + file=$(basename $url) + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + wget "$url" + if [ -f $file ]; then + echo "$url successfully downloaded." + else + echo "$url not successfully downloaded." + exit 1 + fi + if [ ${file: -4} == ".tgz" ]; then + tar zxvf $file + elif [ ${file: -4} == ".tar" ]; then + tar xvf $file + fi + fi +done +cd .. + +echo "pre-processing train data..." +for l in $src $tgt; do + rm -rf $tmp/train.tags.$lang.tok.$l + for f in "${CORPORA[@]}"; do + cat $orig/$f.$l | \ + perl $REM_NON_PRINT_CHAR | \ + perl $TOKENIZER -threads 8 -l $l -no-escape >> $tmp/train.tags.$lang.tok.$l + done +done + +echo "pre-processing test data..." +for l in $src $tgt; do + if [ "$l" == "$src" ]; then + t="src" + else + t="ref" + fi + grep '\s*//g' | \ + sed -e 's/\s*<\/seg>\s*//g' | \ + sed -e "s/\’/\'/g" | \ + perl $TOKENIZER -threads 8 -l $l -no-escape > $tmp/test.$l + echo "" +done + +# apply length filtering before BPE +perl $CLEAN -ratio 1.5 $tmp/train.tags.$lang.tok $src $tgt $tmp/train 1 100 + +# use newstest2012 for valid +echo "pre-processing valid data..." +for l in $src $tgt; do + rm -rf $tmp/valid.$l + cat $orig/$dev.$l | \ + perl $REM_NON_PRINT_CHAR | \ + perl $TOKENIZER -threads 8 -l $l -no-escape >> $tmp/valid.$l +done + +mkdir output +mv $tmp/{train,valid,test}.{$src,$tgt} output + +#BPE +git clone https://github.com/glample/fastBPE.git +pushd fastBPE +g++ -std=c++11 -pthread -O3 fastBPE/main.cc -IfastBPE -o fast +popd +fastBPE/fast learnbpe $codes output/train.$src output/train.$tgt > $bpe/codes +for split in {train,valid,test}; do for lang in {en,de}; do fastBPE/fast applybpe $bpe/$split.$lang output/$split.$lang $bpe/codes; done; done diff --git a/fairseq-tools/fairseq/examples/language_model/README.adaptive_inputs.md b/fairseq-tools/fairseq/examples/language_model/README.adaptive_inputs.md new file mode 100644 index 00000000..68734671 --- /dev/null +++ b/fairseq-tools/fairseq/examples/language_model/README.adaptive_inputs.md @@ -0,0 +1,39 @@ +# Adaptive Input Representations for Neural Language Modeling (Baevski and Auli, 2018) + +## Pre-trained models + +Description | Parameters | Dataset | Model and Test set(s) +---|---:|---|--- +Adaptive Inputs
([Baevski and Auli, 2018](https://arxiv.org/abs/1809.10853)) | 1026M | [Google Billion Words](https://github.com/ciprian-chelba/1-billion-word-language-modeling-benchmark) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_gbw_huge.tar.bz2) +Adaptive Inputs
([Baevski and Auli, 2018](https://arxiv.org/abs/1809.10853)) | 247M | [WikiText-103](https://blog.einstein.ai/the-wikitext-long-term-dependency-language-modeling-dataset/) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_wiki103.v2.tar.bz2) + +## Training an LM with adaptive inputs + +First, see the general [language modeling README](README.md) for instructions on +preprocessing the WikiText-103 data. + +Then use the following training command to train a model with adaptive inputs +using the `transformer_lm_wiki103` model architecture: +```bash +fairseq-train --task language_modeling \ + data-bin/wikitext-103 \ + --save-dir checkpoints/transformer_wikitext-103 \ + --arch transformer_lm_wiki103 \ + --max-update 286000 --max-lr 1.0 --t-mult 2 --lr-period-updates 270000 --lr-scheduler cosine --lr-shrink 0.75 \ + --warmup-updates 16000 --warmup-init-lr 1e-07 --min-lr 1e-09 --optimizer nag --lr 0.0001 --clip-norm 0.1 \ + --criterion adaptive_loss --max-tokens 3072 --update-freq 3 --tokens-per-sample 3072 --seed 1 \ + --sample-break-mode none --skip-invalid-size-inputs-valid-test --ddp-backend=no_c10d +``` + +## Citation + +```bibtex +@inproceedings{ + baevski2018adaptive, + title={Adaptive Input Representations for Neural Language Modeling}, + author={Alexei Baevski and Michael Auli}, + booktitle={International Conference on Learning Representations}, + year={2019}, + url={https://openreview.net/forum?id=ByxZX20qFQ}, +} +``` diff --git a/fairseq-tools/fairseq/examples/language_model/README.conv.md b/fairseq-tools/fairseq/examples/language_model/README.conv.md new file mode 100644 index 00000000..f0b6a3a9 --- /dev/null +++ b/fairseq-tools/fairseq/examples/language_model/README.conv.md @@ -0,0 +1,40 @@ +# Language Modeling with Gated Convolutional Networks (Dauphin et al., 2017) + +## Example usage + +First download and preprocess the data following the main [language modeling README](README.md). + +Then to train a convolutional LM using the `fconv_lm_dauphin_wikitext103` +architecture: +```bash +fairseq-train --task language_modeling \ + data-bin/wikitext-103 \ + --save-dir checkpoints/fconv_wikitext-103 \ + --arch fconv_lm_dauphin_wikitext103 \ + --adaptive-softmax-cutoff 10000,20000,200000 \ + --dropout 0.2 \ + --criterion adaptive_loss \ + --optimizer nag --clip-norm 0.1 --weight-decay 5e-06 \ + --lr 1.0 --lr-scheduler reduce_lr_on_plateau --lr-shrink 0.5 \ + --max-tokens 1024 --tokens-per-sample 1024 \ + --ddp-backend no_c10d \ + --max-epoch 35 +``` + +And evaluate with: +```bash +fairseq-eval-lm data-bin/wikitext-103 --path checkpoints/fconv_wiki103/checkpoint_best.pt +``` + +## Citation + +```bibtex +@inproceedings{dauphin2017language, + title={Language Modeling with Gated Convolutional Networks}, + author={Dauphin, Yann N and Fan, Angela and Auli, Michael and Grangier, David}, + booktitle={Proceedings of the 34th International Conference on Machine Learning-Volume 70}, + pages={933--941}, + year={2017}, + organization={JMLR} +} +``` diff --git a/fairseq-tools/fairseq/examples/language_model/README.md b/fairseq-tools/fairseq/examples/language_model/README.md new file mode 100644 index 00000000..dc84d8c7 --- /dev/null +++ b/fairseq-tools/fairseq/examples/language_model/README.md @@ -0,0 +1,123 @@ +# Neural Language Modeling + +## Pre-trained models + +Model | Description | Dataset | Download +---|---|---|--- +`transformer_lm.gbw.adaptive_huge` | Adaptive Inputs
([Baevski and Auli, 2018](https://arxiv.org/abs/1809.10853))
1026M params | [Google Billion Words](https://github.com/ciprian-chelba/1-billion-word-language-modeling-benchmark) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_gbw_huge.tar.bz2) +`transformer_lm.wiki103.adaptive` | Adaptive Inputs
([Baevski and Auli, 2018](https://arxiv.org/abs/1809.10853))
247M params | [WikiText-103](https://einstein.ai/research/the-wikitext-long-term-dependency-language-modeling-dataset) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_wiki103.v2.tar.bz2) +`transformer_lm.wmt19.en` | English LM
([Ng et al., 2019](https://arxiv.org/abs/1907.06616)) | [WMT News Crawl](http://data.statmt.org/news-crawl/) | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.en.tar.gz) +`transformer_lm.wmt19.de` | German LM
([Ng et al., 2019](https://arxiv.org/abs/1907.06616)) | [WMT News Crawl](http://data.statmt.org/news-crawl/) | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.de.tar.gz) +`transformer_lm.wmt19.ru` | Russian LM
([Ng et al., 2019](https://arxiv.org/abs/1907.06616)) | [WMT News Crawl](http://data.statmt.org/news-crawl/) | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.ru.tar.gz) + +## Example usage + +We require a few additional Python dependencies for preprocessing: +```bash +pip install fastBPE sacremoses +``` + +To sample from a language model using PyTorch Hub: +```python +import torch + +# List available models +torch.hub.list('pytorch/fairseq') # [..., 'transformer_lm.wmt19.en', ...] + +# Load an English LM trained on WMT'19 News Crawl data +en_lm = torch.hub.load('pytorch/fairseq', 'transformer_lm.wmt19.en', tokenizer='moses', bpe='fastbpe') +en_lm.eval() # disable dropout + +# Move model to GPU +en_lm.cuda() + +# Sample from the language model +en_lm.sample('Barack Obama', beam=1, sampling=True, sampling_topk=10, temperature=0.8) +# "Barack Obama is coming to Sydney and New Zealand (...)" + +# Compute perplexity for a sequence +en_lm.score('Barack Obama is coming to Sydney and New Zealand')['positional_scores'].mean().neg().exp() +# tensor(15.1474) + +# The same interface can be used with custom models as well +from fairseq.models.transformer_lm import TransformerLanguageModel +custom_lm = TransformerLanguageModel.from_pretrained('/path/to/model/dir', 'checkpoint100.pt', tokenizer='moses', bpe='fastbpe') +custom_lm.sample('Barack Obama', beam=5) +# "Barack Obama (...)" +``` + +## Training a transformer language model with the CLI tools + +### 1) Preprocess the data + +First download and prepare the [WikiText-103 dataset](https://www.salesforce.com/products/einstein/ai-research/the-wikitext-dependency-language-modeling-dataset/): +```bash +cd examples/language_model/ +bash prepare-wikitext-103.sh +cd ../.. +``` + +Next preprocess/binarize the data: +```bash +TEXT=examples/language_model/wikitext-103 +fairseq-preprocess \ + --only-source \ + --trainpref $TEXT/wiki.train.tokens \ + --validpref $TEXT/wiki.valid.tokens \ + --testpref $TEXT/wiki.test.tokens \ + --destdir data-bin/wikitext-103 \ + --workers 20 +``` + +### 2) Train a language model + +Next we'll train a basic transformer language model on wikitext-103. For more +advanced usage, see the [adaptive inputs README](README.adaptive_inputs.md). + +To train a basic LM (assumes 2 GPUs): +``` +$ fairseq-train --task language_modeling \ + data-bin/wikitext-103 \ + --save-dir checkpoints/transformer_wikitext-103 \ + --arch transformer_lm --share-decoder-input-output-embed \ + --dropout 0.1 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --weight-decay 0.01 --clip-norm 0.0 \ + --lr 0.0005 --lr-scheduler inverse_sqrt --warmup-updates 4000 --warmup-init-lr 1e-07 \ + --tokens-per-sample 512 --sample-break-mode none \ + --max-tokens 2048 --update-freq 16 \ + --fp16 \ + --max-update 50000 +``` + +If you run out of memory, try reducing `--max-tokens` (max number of tokens per +batch) or `--tokens-per-sample` (max sequence length). You can also adjust +`--update-freq` to accumulate gradients and simulate training on a different +number of GPUs. + +### 3) Evaluate + +```bash +fairseq-eval-lm data-bin/wikitext-103 \ + --path checkpoints/transformer_wiki103/checkpoint_best.pt \ + --batch-size 2 \ + --tokens-per-sample 512 \ + --context-window 400 +# | Evaluated 245569 tokens in 56.1s (4379.02 tokens/s) +# | Loss: 3.4164, Perplexity: 30.46 +``` + +*Note:* The `--context-window` option controls how much context is provided to +each token when computing perplexity. When the window size is 0, the dataset is +chunked into segments of length 512 and perplexity is computed over each segment +normally. However, this results in worse (higher) perplexity since tokens that +appear earlier in each segment have less conditioning. When the maximum window +size is used (511 in this case), then we compute perplexity for each token +fully conditioned on 511 tokens of context. This slows down evaluation +significantly, since we must run a separate forward pass for every token in the +dataset, but results in better (lower) perplexity. + + +## Convolutional language models + +Please see the [convolutional LM README](README.conv.md) for instructions on +training convolutional language models. diff --git a/fairseq-tools/fairseq/examples/language_model/prepare-wikitext-103.sh b/fairseq-tools/fairseq/examples/language_model/prepare-wikitext-103.sh new file mode 100644 index 00000000..75130215 --- /dev/null +++ b/fairseq-tools/fairseq/examples/language_model/prepare-wikitext-103.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Adapted from https://github.com/facebookresearch/MIXER/blob/master/prepareData.sh + +URLS=( + "https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-v1.zip" +) +FILES=( + "wikitext-103-v1.zip" +) + +for ((i=0;i<${#URLS[@]};++i)); do + file=${FILES[i]} + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + url=${URLS[i]} + wget "$url" + if [ -f $file ]; then + echo "$url successfully downloaded." + else + echo "$url not successfully downloaded." + exit -1 + fi + if [ ${file: -4} == ".tgz" ]; then + tar zxvf $file + elif [ ${file: -4} == ".tar" ]; then + tar xvf $file + elif [ ${file: -4} == ".zip" ]; then + unzip $file + fi + fi +done +cd .. diff --git a/fairseq-tools/fairseq/examples/latent_depth/README.md b/fairseq-tools/fairseq/examples/latent_depth/README.md new file mode 100644 index 00000000..a0ec55a3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/README.md @@ -0,0 +1,77 @@ +# Deep Transformers with Latent Depth (Li et al., 2020) + +[https://arxiv.org/abs/2009.13102](https://arxiv.org/abs/2009.13102). + +## Introduction + +We present a probabilistic framework to automatically learn which layer(s) to use by learning the posterior distributions of layer selection. As an extension of this framework, we propose a novel method to train one shared Transformer network for multilingual machine translation with different layer selection posteriors for each language pair. + +## Training a multilingual model with latent depth + +Below is an example of training with latent depth in decoder for one-to-many (O2M) related languages. We use the same preprocessed (numberized and binarized) TED8 dataset as in [Balancing Training for Multilingual Neural Machine Translation (Wang et al., 2020)](https://github.com/cindyxinyiwang/multiDDS), which could be generated by [the script](https://github.com/cindyxinyiwang/multiDDS/blob/multiDDS/util_scripts/prepare_multilingual_data.sh) the author provided. +```bash +lang_pairs_str="eng-aze,eng-bel,eng-ces,eng-glg,eng-por,eng-rus,eng-slk,eng-tur" +databin_dir= + +fairseq-train ${databin_dir} \ + --user-dir examples/latent_depth/latent_depth_src \ + --lang-pairs "${lang_pairs_str}" \ + --arch multilingual_transformer_iwslt_de_en \ + --task multilingual_translation_latent_depth \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --share-encoders \ + --share-decoders \ + --decoder-langtok \ + --share-decoder-input-output-embed \ + --dropout 0.3 --attention-dropout 0.3 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler inverse_sqrt --min-lr 1e-9 --warmup-init-lr 1e-7 --warmup-updates 8000 \ + --max-tokens 4096 --update-freq 1 \ + --lr 0.0015 \ + --clip-norm 1.0 \ + --seed 2 \ + --ddp-backend=no_c10d \ + --encoder-layers 12 \ + --decoder-layers 24 \ + --decoder-latent-layer \ + --sparsity-weight 0.1 \ + --anneal-updates 5000 \ + --soft-update 500 \ + --target-layers 12 \ + --share-weight 0.1 +``` +## Inference command + +```bash +lang_pairs_str="eng-aze,eng-bel,eng-ces,eng-glg,eng-por,eng-rus,eng-slk,eng-tur" +databin_dir= +model_path= +src_lang= +tgt_lang= +gen_data= + +fairseq-generate ${databin_dir} \ + --path ${model_path} \ + --task multilingual_translation_latent_depth \ + --decoder-latent-layer \ + --lang-pairs "${lang_pairs_str}" \ + -s ${src_lang} -t ${tgt_lang} \ + --gen-subset $gen_data \ + --scoring sacrebleu \ + --remove-bpe 'sentencepiece' \ + --lenpen 1.0 \ + --beam 5 \ + --decoder-langtok \ + --max-tokens 4096 +``` + + +## Citation +```bibtex +@article{li2020deep, + title={Deep Transformers with Latent Depth}, + author={Li, Xian and Stickland, Asa Cooper and Tang, Yuqing and Kong, Xiang}, + journal={arXiv preprint arXiv:2009.13102}, + year={2020} +} +``` diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/__init__.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/__init__.py new file mode 100644 index 00000000..c5fa7603 --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import multilingual_translation_latent_depth # noqa +from .loss import latent_depth # noqa +from .models import latent_multilingual_transformer # noqa +from .modules import latent_layers # noqa diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/__init__.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/latent_depth.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/latent_depth.py new file mode 100644 index 00000000..a3b9535e --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/loss/latent_depth.py @@ -0,0 +1,99 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +from torch.nn.modules.loss import _Loss + + +class LatentLayersKLLoss(_Loss): + def __init__(self, args): + super().__init__() + self.args = args + + def forward(self, layer_samples, lang_idx, update_num, sample_size): + prior = self.args.prior + samples = layer_samples[lang_idx] + eps = 1e-7 + if prior == "uniform": + # uniform prior + kl_loss = (samples * (torch.log(samples + eps) - math.log(0.5))).sum(-1) + elif prior == "agged_posterior": + # aggregated posterior + y_t = torch.stack([x.detach() for x in layer_samples], dim=0) + agged_q = torch.sum(y_t, dim=0) + row_norm = agged_q.sum(-1) + normed_agg_q = agged_q / row_norm + kl_loss = ( + samples * (torch.log(samples + eps) - torch.log(normed_agg_q + eps)) + ).sum(-1) + else: + raise NotImplementedError("The specified prior is not implemented.") + + # normalized by number of layers + kl_loss /= layer_samples[0].size()[0] + kl_weight = min( + self.args.sparsity_weight, + (update_num - self.args.soft_update) + * self.args.sparsity_weight + / self.args.anneal_updates, + ) + kl_loss *= kl_weight * sample_size + return kl_loss + + +class LatentLayersSparsityLoss(_Loss): + def __init__(self, args): + super().__init__() + self.args = args + + def is_valid(self, update_num): + if self.args.target_layers <= 0: + return False + return update_num > (self.args.soft_update + self.args.anneal_updates) + + def forward(self, layer_samples_list, update_num, sample_size): + batch_loss = 0 + share_loss = 0 + global_sparsity_loss = 0 + layer_samples = torch.stack(layer_samples_list, dim=0) + if ( + self.args.target_layers > 0 or self.args.share_weight > 0 + ) and update_num > (self.args.soft_update + self.args.anneal_updates): + # anneal sparsity weight + if update_num < (self.args.anneal_updates + self.args.soft_update): + weight_anneal = 0 + elif update_num < (2 * self.args.anneal_updates + self.args.soft_update): + weight_anneal = ( + (update_num - self.args.soft_update - self.args.anneal_updates) + * self.args.share_weight + / self.args.anneal_updates + ) + else: + weight_anneal = 1 + # compute ratio among languages + layer_utilization = torch.sum(layer_samples, dim=0) + layer_utilization /= layer_samples.size()[0] + if self.args.share_weight > 0: + # encouraging sharing across languages + share_loss = sum( + -1.0 * v * math.log(v) for v in layer_utilization if v > 0 + ) + batch_loss += ( + weight_anneal * self.args.share_weight * sample_size * share_loss + ) + if self.args.target_layers > 0: + # computed expected number of layers selected + expeted_layers = sum(layer_utilization) + # compute l2 loss wrt target number of layers + global_sparsity_loss = (expeted_layers - self.args.target_layers) ** 2 + batch_loss += ( + weight_anneal + * self.args.share_weight + * sample_size + * global_sparsity_loss + ) + return batch_loss diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/__init__.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_multilingual_transformer.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_multilingual_transformer.py new file mode 100644 index 00000000..9e075fcc --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_multilingual_transformer.py @@ -0,0 +1,59 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.models import register_model, register_model_architecture +from fairseq.models.multilingual_transformer import MultilingualTransformerModel +from fairseq.models.transformer import ( + TransformerDecoder, + TransformerEncoder, + base_architecture, +) + +from .latent_transformer import LatentTransformerDecoder, LatentTransformerEncoder + + +@register_model("latent_multilingual_transformer") +class LatentMultilingualTransformerModel(MultilingualTransformerModel): + """A variant of standard multilingual Transformer models which encoder and/or + decoders supports latent depth, as is in "Deep Transformer with Latent Depth" + (https://arxiv.org/abs/2009.13102). + """ + + @classmethod + def _get_module_class(cls, is_encoder, args, lang_dict, embed_tokens, langs): + if is_encoder: + if hasattr(args, "encoder_latent_layer") and args.encoder_latent_layer: + return LatentTransformerEncoder( + args, lang_dict, embed_tokens, num_logits=len(langs) + ) + else: + return TransformerEncoder(args, lang_dict, embed_tokens) + else: + if hasattr(args, "decoder_latent_layer") and args.decoder_latent_layer: + return LatentTransformerDecoder( + args, lang_dict, embed_tokens, num_logits=len(langs) + ) + else: + return TransformerDecoder(args, lang_dict, embed_tokens) + + +@register_model_architecture( + "latent_multilingual_transformer", "latent_multilingual_transformer" +) +def latent_multilingual_architecture(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 1024) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.decoder_layers = getattr(args, "decoder_layers", 24) + args.share_encoders = getattr(args, "share_encoders", True) + args.share_decoders = getattr(args, "share_decoders", True) + args.share_encoder_embeddings = getattr(args, "share_encoder_embeddings", True) + args.share_decoder_embeddings = getattr(args, "share_decoder_embeddings", True) + + base_architecture(args) diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_transformer.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_transformer.py new file mode 100644 index 00000000..db30239b --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/models/latent_transformer.py @@ -0,0 +1,146 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Any, Dict, Optional + +import torch.nn as nn +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.models.transformer import TransformerDecoder, TransformerEncoder +from fairseq.modules import TransformerDecoderLayer, TransformerEncoderLayer +from torch import Tensor + +from ..modules.latent_layers import LayerSelect + + +class LatentTransformerEncoder(TransformerEncoder): + """Latent depth (https://arxiv.org/abs/2009.13102) implemented in + TransformerEncoder. + """ + + def __init__(self, args, dictionary, embed_tokens, num_logits=1): + self.num_logits = num_logits + self.num_layers = args.encoder_layers + super().__init__(args, dictionary, embed_tokens) + self.layer_select = LayerSelect(self.num_layers, self.num_logits, args) + self.lang_idx = None + self.layers = nn.ModuleList( + [self._build_encoder_layer(args, idx) for idx in range(args.encoder_layers)] + ) + + def set_lang_idx(self, lang_idx): + self.lang_idx = lang_idx + + def _build_encoder_layer(self, args, idx=None): + return LatentTransformerEncoderLayer(args, idx, layer_select=self.layer_select) + + def forward(self, src_tokens, src_lengths, return_all_hiddens: bool = False): + self.layer_select.sample(self.lang_idx) + return super().forward(src_tokens, src_lengths, return_all_hiddens) + + +class LatentTransformerEncoderLayer(TransformerEncoderLayer): + """Encoder layer with each (non_residual) block weighted by samples of Bernouli + or Gumbel Signmoid samples. + + Args: + args (argparse.Namespace): parsed command-line arguments from standard + TransformerEncoderLayer. + idx (int): layer index (used to retrieve samples). + layer_select (LayerSelect, optional): instance of LayerSelect module with logits + parameters and sampling method. + """ + + def __init__(self, args, idx, layer_select=None): + super().__init__(args) + self.idx = idx + self.layer_select = layer_select + + def residual_connection(self, x, residual): + return residual + x * self.layer_select(self.idx) + + +class LatentTransformerDecoder(TransformerDecoder): + """Latent depth (https://arxiv.org/abs/2009.13102) implemented in + TransformerDecoder. + """ + + def __init__( + self, args, dictionary, embed_tokens, no_encoder_attn=False, num_logits=1 + ): + self.num_logits = num_logits + self.num_layers = args.decoder_layers + super().__init__( + args, dictionary, embed_tokens, no_encoder_attn=no_encoder_attn + ) + self.layer_select = LayerSelect(self.num_layers, self.num_logits, args) + self.lang_idx = None + self.layers = nn.ModuleList( + [ + self._build_decoder_layer(args, no_encoder_attn, idx) + for idx in range(args.decoder_layers) + ] + ) + + def set_lang_idx(self, lang_idx): + self.lang_idx = lang_idx + + def _build_decoder_layer(self, args, no_encoder_attn=False, idx=None): + return LatentTransformerDecoderLayer( + args, idx, layer_select=self.layer_select, no_encoder_attn=no_encoder_attn + ) + + def forward( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + features_only: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + src_lengths: Optional[Any] = None, + return_all_hiddens: bool = False, + ): + self.layer_select.sample(self.lang_idx) + return super().forward( + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + incremental_state=incremental_state, + features_only=features_only, + alignment_layer=alignment_layer, + src_lengths=src_lengths, + return_all_hiddens=return_all_hiddens, + ) + + +class LatentTransformerDecoderLayer(TransformerDecoderLayer): + """Decoder layer with each (non_residual) block weighted by samples of Bernouli + or Gumbel Signmoid samples. + + Args: + args (argparse.Namespace): parsed command-line arguments from standard + TransformerDecoderLayer. + idx (int): layer index (used to retrieve samples). + layer_select (LayerSelect, optional): instance of LayerSelect module with logits + parameters and sampling method. + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + + """ + + def __init__( + self, + args, + idx, + layer_select=None, + no_encoder_attn=False, + add_bias_kv=False, + add_zero_attn=False, + ): + super().__init__(args, no_encoder_attn, add_bias_kv, add_zero_attn) + self.idx = idx + self.layer_select = layer_select + + def residual_connection(self, x, residual): + return residual + x * self.layer_select(self.idx) diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/__init__.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/latent_layers.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/latent_layers.py new file mode 100644 index 00000000..a2b8ab44 --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/modules/latent_layers.py @@ -0,0 +1,86 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn + + +class LayerSelect(nn.Module): + """Compute samples (from a Gumbel-Sigmoid distribution) which is used as + either (soft) weighting or (hard) selection of residual connection. + https://arxiv.org/abs/2009.13102 + """ + + def __init__(self, num_layers, num_logits, args): + super(LayerSelect, self).__init__() + self.args = args + self.layer_logits = torch.nn.Parameter( + torch.Tensor(num_logits, num_layers), + requires_grad=True, + ) + self.hard_select = not (hasattr(args, "soft_select") and args.soft_select) + self.tau = getattr(args, "sampling_tau", 5) + self.detach_grad = False + self.layer_samples = [None] * num_logits + + @staticmethod + def add_args(parser): + parser.add_argument( + "--soft-select", + action="store_true", + help="use soft samples in training an inference", + ) + parser.add_argument("--sampling-tau", type=float, help="sampling temperature") + + def sample(self, logit_idx): + """To leverage the efficiency of distributed training, samples for all + layers are computed at once for each logit_idx. Logits are parameters + learnt independent of each other. + + Args: + logit_idx: The index of logit parameters used for sampling. + """ + assert logit_idx is not None + self.samples = self._gumbel_sigmoid( + self.layer_logits[logit_idx, :].detach() + if self.detach_grad + else self.layer_logits[logit_idx, :], + dim=-1, + tau=self.tau, + hard=self.hard_select, + ) + self.layer_samples[logit_idx] = self.samples + + def forward(self, i): + sample = self.samples[i] + return sample + + def _gumbel_sigmoid( + self, logits, tau=1, hard=False, eps=1e-10, dim=-1, threshold=0.5 + ): + # ~Gumbel(0,1) + gumbels1 = ( + -torch.empty_like(logits, memory_format=torch.legacy_contiguous_format) + .exponential_() + .log() + ) + gumbels2 = ( + -torch.empty_like(logits, memory_format=torch.legacy_contiguous_format) + .exponential_() + .log() + ) + # Difference of two gumbels because we apply a sigmoid + gumbels1 = (logits + gumbels1 - gumbels2) / tau + y_soft = gumbels1.sigmoid() + if hard: + # Straight through. + y_hard = torch.zeros_like( + logits, memory_format=torch.legacy_contiguous_format + ).masked_fill(y_soft > threshold, 1.0) + ret = y_hard - y_soft.detach() + y_soft + else: + # Reparametrization trick. + ret = y_soft + return ret diff --git a/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/multilingual_translation_latent_depth.py b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/multilingual_translation_latent_depth.py new file mode 100644 index 00000000..b5cd51a4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/latent_depth/latent_depth_src/multilingual_translation_latent_depth.py @@ -0,0 +1,194 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.tasks import register_task +from fairseq.tasks.multilingual_translation import MultilingualTranslationTask + +from .loss.latent_depth import LatentLayersKLLoss, LatentLayersSparsityLoss + + +@register_task("multilingual_translation_latent_depth") +class MultilingualTranslationTaskLatentDepth(MultilingualTranslationTask): + """A task for multiple translation with latent depth. + + See `"Deep Transformer with Latent Depth" + (Li et al., 2020) `_. + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + MultilingualTranslationTask.add_args(parser) + parser.add_argument('--encoder-latent-layer', action='store_true', help='latent layer selection in encoder') + parser.add_argument('--decoder-latent-layer', action='store_true', help='latent layer selection in decoder') + parser.add_argument('--target-layers', default=-1, type=int, + help='number of effective layers to learn; -1 means no constraint') + parser.add_argument('--sparsity-weight', default=0.0, type=float, + help='weight for sparsity loss') + parser.add_argument('--share-weight', default=0.0, type=float, + help='weight for sharing loss') + parser.add_argument('--soft-update', default=1, type=int, + help='number of updates with soft sampling') + parser.add_argument('--anneal-updates', default=1, type=int, + help='number of updates to anneal the KL loss weight') + parser.add_argument('--prior', default="uniform", type=str, + help='prior used for computing KL loss') + # fmt: on + + def __init__(self, args, dicts, training): + super().__init__(args, dicts, training) + self.src_langs, self.tgt_langs = zip( + *[(lang.split("-")[0], lang.split("-")[1]) for lang in args.lang_pairs] + ) + if self.training and self.encoder_latent_layer: + assert self.args.share_encoders + if self.training and self.decoder_latent_layer: + assert self.args.share_decoders + if training or self.encoder_latent_layer or self.decoder_latent_layer: + self.lang_pairs = args.lang_pairs + else: + self.lang_pairs = ["{}-{}".format(args.source_lang, args.target_lang)] + self.eval_lang_pairs = self.lang_pairs + self.model_lang_pairs = self.lang_pairs + if self.training and (self.encoder_latent_layer or self.decoder_latent_layer): + self.kl_loss = LatentLayersKLLoss(self.args) + self.sparsity_loss = LatentLayersSparsityLoss(self.args) + + def _per_lang_pair_train_loss( + self, lang_pair, model, update_num, criterion, sample, optimizer, ignore_grad + ): + src, tgt = lang_pair.split("-") + if self.encoder_latent_layer: + src_lang_idx = self.src_lang_idx_dict[src] + model.models[lang_pair].encoder.set_lang_idx(src_lang_idx) + model.models[lang_pair].encoder.layer_select.hard_select = ( + update_num > self.args.soft_update + ) + if self.decoder_latent_layer: + tgt_lang_idx = self.tgt_lang_idx_dict[tgt] + model.models[lang_pair].decoder.set_lang_idx(tgt_lang_idx) + model.models[lang_pair].decoder.layer_select.hard_select = ( + update_num > self.args.soft_update + ) + + loss, sample_size, logging_output = criterion( + model.models[lang_pair], sample[lang_pair] + ) + if self.encoder_latent_layer: + none_samples = sum( + 1 if x is None else 0 + for x in model.models[lang_pair].encoder.layer_select.layer_samples + ) + if none_samples == 0 or self.args.prior != "agged_posterior": + loss += self.kl_loss( + model.models[lang_pair].encoder.layer_select.layer_samples, + src_lang_idx, + update_num, + sample_size, + ) + if self.decoder_latent_layer: + none_samples = sum( + 1 if x is None else 0 + for x in model.models[lang_pair].decoder.layer_select.layer_samples + ) + if none_samples == 0 or self.args.prior != "agged_posterior": + loss += self.kl_loss( + model.models[lang_pair].decoder.layer_select.layer_samples, + tgt_lang_idx, + update_num, + sample_size, + ) + if ignore_grad: + loss *= 0 + + if hasattr(self, "sparsity_loss") and self.sparsity_loss.is_valid(update_num): + # need to retain the graph if sparsity loss needs to be added + loss.backward(retain_graph=True) + else: + optimizer.backward(loss) + + return loss, sample_size, logging_output + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + agg_loss, agg_sample_size, agg_logging_output = super().train_step( + sample, model, criterion, optimizer, update_num, ignore_grad + ) + # compute auxiliary loss from layere sparsity, based on all samples from all languages + if hasattr(self, "sparsity_loss") and self.sparsity_loss.is_valid(update_num): + sparsity_loss = 0 + if self.encoder_latent_layer: + sparsity_loss += self.sparsity_loss( + next( + iter(model.models.values()) + ).encoder.layer_select.layer_samples, + update_num, + agg_sample_size, + ) + if self.decoder_latent_layer: + sparsity_loss += self.sparsity_loss( + next( + iter(model.models.values()) + ).decoder.layer_select.layer_samples, + update_num, + agg_sample_size, + ) + if sparsity_loss > 0: + optimizer.backward(sparsity_loss) + return agg_loss, agg_sample_size, agg_logging_output + + def _per_lang_pair_valid_loss(self, lang_pair, model, criterion, sample): + src, tgt = lang_pair.split("-") + if self.encoder_latent_layer: + src_lang_idx = self.src_lang_idx_dict[src] + model.models[lang_pair].encoder.set_lang_idx(src_lang_idx) + if self.decoder_latent_layer: + tgt_lang_idx = self.tgt_lang_idx_dict[tgt] + model.models[lang_pair].decoder.set_lang_idx(tgt_lang_idx) + loss, sample_size, logging_output = criterion( + model.models[lang_pair], sample[lang_pair] + ) + return loss, sample_size, logging_output + + def inference_step( + self, generator, models, sample, prefix_tokens=None, constraints=None + ): + if self.encoder_latent_layer or self.decoder_latent_layer: + for model in models: + if self.encoder_latent_layer: + assert model.encoder.layer_select is not None + src_lang_idx = self.src_lang_idx_dict[self.args.source_lang] + model.encoder.set_lang_idx(src_lang_idx) + if self.decoder_latent_layer: + assert model.decoder.layer_select is not None + tgt_lang_idx = self.tgt_lang_idx_dict[self.args.target_lang] + model.decoder.set_lang_idx(tgt_lang_idx) + return super().inference_step( + generator, models, sample, prefix_tokens, constraints + ) + + @property + def encoder_latent_layer(self): + return ( + hasattr(self.args, "encoder_latent_layer") + and self.args.encoder_latent_layer + ) + + @property + def decoder_latent_layer(self): + return ( + hasattr(self.args, "decoder_latent_layer") + and self.args.decoder_latent_layer + ) + + @property + def src_lang_idx_dict(self): + return {lang: lang_idx for lang_idx, lang in enumerate(self.src_langs)} + + @property + def tgt_lang_idx_dict(self): + return {lang: lang_idx for lang_idx, lang in enumerate(self.tgt_langs)} diff --git a/fairseq-tools/fairseq/examples/layerdrop/README.md b/fairseq-tools/fairseq/examples/layerdrop/README.md new file mode 100644 index 00000000..394e710b --- /dev/null +++ b/fairseq-tools/fairseq/examples/layerdrop/README.md @@ -0,0 +1,154 @@ +# Reducing Transformer Depth on Demand with Structured Dropout (Fan et al., 2019) +This page contains information for how to train models with LayerDrop, based on this [paper](https://arxiv.org/abs/1909.11556). + +## Citation: +If you found this technique useful, please cite our paper: +```bibtex +@article{fan2019reducing, + title={Reducing Transformer Depth on Demand with Structured Dropout}, + author={Fan, Angela and Grave, Edouard and Joulin, Armand}, + journal={arXiv preprint arXiv:1909.11556}, + year={2019} +} +``` + +## Pre-trained models + +Model | Description | Download +---|---|--- +`layerdrop_wmt_en_de_12_6` | Transformer + LayerDrop 0.2 trained on WMT16 en-de with 12 encoder and 6 decoder layers | [layerdrop_wmt_en_de_12_6.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/layerdrop_wmt_en_de_12_6.tar.gz) +`roberta_layerdrop.base` | RoBERTa Base + LayerDrop 0.2 | [roberta_layerdrop.base.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta_layerdrop.base.qnli.tar.gz) +`roberta_layerdrop.large` | RoBERTa Large + LayerDrop 0.2 | [roberta_layerdrop.large.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta_layerdrop.large.tar.gz) +`roberta_layerdrop.large.mnli` | `roberta_layerdrop.large` finetuned on [MNLI](http://www.nyu.edu/projects/bowman/multinli) | [roberta_layerdrop.large.mnli.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta_layerdrop.large.mnli.tar.gz) +`roberta_layerdrop.large.qnli` | `roberta_layerdrop.large` finetuned on [QNLI](https://arxiv.org/abs/1804.07461) | [roberta_layerdrop.large.mnli.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta_layerdrop.large.qnli.tar.gz) + + +Evaluate performance of these pre-trained models: +```bash +# Example for Machine Translation +fairseq-generate /path/to/bped/wmt/data --path nmt_checkpoint.pt \ + --beam 8 --lenpen 0.4 \ + --batch-size 64 \ + --remove-bpe \ + --gen-subset test > wmt16_gen.txt +bash scripts/compound_split_bleu.sh wmt16_gen.txt +# prints BLEU4 = 30.17 +``` + +```python +# Example for RoBERTa + LayerDrop finetuned on MNLI: +from fairseq.models.roberta import RobertaModel + +roberta_layerdrop = RobertaModel.from_pretrained( + '/path/to/MNLI/model', + checkpoint_file='mnli_checkpoint.pt', + data_name_or_path='/path/to/MNLI/data/MNLI-bin' +) +label_map = {0: 'contradiction', 2: 'neutral', 1: 'entailment'} +ncorrect, nsamples = 0, 0 +roberta_layerdrop.cuda() +roberta_layerdrop.eval() +with open('/path/to/MNLI/data/dev_matched.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[8], tokens[9], tokens[-1] + tokens = roberta_layerdrop.encode(sent1, sent2) + prediction = roberta_layerdrop.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_map[prediction] + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) +# prints | Accuracy: 0.9026999490575649 + + +# Example for RoBERTa + LayerDrop finetuned on QNLI: +roberta = RobertaModel.from_pretrained( + '/path/to/QNLI/model', + checkpoint_file='qnli_checkpoint.pt', + data_name_or_path='/path/to/QNLI/data/QNLI-bin' +) + +label_fn = lambda label: roberta.task.label_dictionary.string( + [label + roberta.task.target_dictionary.nspecial] +) +ncorrect, nsamples = 0, 0 +roberta.cuda() +roberta.eval() +with open('/path/to/QNLI/data/dev.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[1], tokens[2], tokens[3] + tokens = roberta.encode(sent1, sent2) + prediction = roberta.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_fn(prediction) + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) +# prints | Accuracy: 0.9480139117700896 +``` + + +## Example usage + +To train a model with LayerDrop, add the following flags. We recommend 0.2, a value that worked well in our experiments. For Language Models that are decoder-only, you need only the decoder flag. For RoBERTa, an encoder, you need only the encoder flag. The encoder and decoder LayerDrop values can be set differently. +``` +--encoder-layerdrop 0.2 --decoder-layerdrop 0.2 +``` + +To prune a model that has been trained with LayerDrop, add the following flags followed by a comma separated list of which layers you would like to keep. +``` +--encoder-layers-to-keep 0,2,4,6,8,10,12,14 --decoder-layers-to-keep 0,2,4,6,8,10,12,14 +``` +Setting these flags should print a message such as: +``` +| Pruning model to specified layer configuration +``` +You should also see a smaller number of parameters in the model, for example the 16-Layer Transformer Language Model prints: +``` +num. model params: 246933504 +``` +while a model pruned to 8 Layers prints: +``` +num. model params: 146163712 +``` + +If you would like to pick up training with a model that has been pruned, simply adding these flags is sufficient. If you would like to use a script that only does evaluation (no training), you may need to pass an override command. A specific example would be for language modeling: +```bash +fairseq-eval-lm /path/to/wikitext-103 \ + --path /path/to/model/checkpoint.pt \ + --model-overrides "{'decoder_layers_to_keep':'0,2,4,6,8,10,12,14'}" +``` +This model override command overrides the training parameters and updates the model arguments so that the pruned model is run instead of the full model. + +## Reproduce Paper Results + +Looking to reproduce the results in the paper? + +1. For Translation on WMT16 en-de, we followed this setting [here](https://github.com/pytorch/fairseq/blob/master/examples/scaling_nmt/README.md) +2. To train RoBERTa, we followed this setting [here](https://github.com/pytorch/fairseq/tree/master/examples/roberta) +3. To train Language Models on Wikitext-103, we followed this setting [here](https://github.com/pytorch/fairseq/tree/master/examples/language_model) + + +## Tips + +1. If you would like to train large models with better performance, LayerDrop should be set to a smaller value such as 0.1 or 0.2. Too much LayerDrop will mean the model has too much regularization, so may not reach the best performance. Since LayerDrop adds regularization, you may achieve the best performance by slightly reducing the amount of standard dropout (for example, reduce by 0.1). + +2. If you would like to train large models to be pruned and made smaller, LayerDrop should be set to a larger value such as 0.5 if you want to prune very aggressively (such as removing half the network or more). If you would like to prune fewer layers away, LayerDrop can be set to a smaller value such as 0.2. Our experiments were conducted with low values of LayerDrop (such as 0.1 and 0.2), for reference. + +3. When pruning layers at inference time, it is best to spread out the layers remaining so they are evenly spaced throughout the network. For example, if you want to remove 50% of the network, keeping every other layer is good. + + +## FAQ + +1. How did the sharing layers experiment work? In an appendix (https://openreview.net/pdf?id=SylO2yStDr) we added an experiment on Wikitext-103 language modeling that combined LayerDrop with Weight Sharing. We shared chunks of 2 layers such that every other layer had shared weights. For example, if our network has layers 1 through 6, then layer 1 and 2 are shared, layer 3 and 4 are shared, and layer 5 and 6 are shared. + +2. LayerDrop hasn't been helping in my setting? During training time, LayerDrop can help regularize your network. This is most important if your network is already overfitting - if your network is underfitting, it is possible LayerDrop is adding too much regularization. We recommend using smaller values (such as 0.1 or 0.2) and also decreasing the quantity of standard dropout (for example, reduce by 0.1). + +3. Can you train a model without LayerDrop and finetune with LayerDrop (e.g. for BERT)? In our experiments, we did not see great performance. Models such as RoBERTa have trained for a long time in the pre-training setting, so only finetuning with LayerDrop for a few epochs on a downstream task such as MNLI does not achieve the robustness required for successful pruning. + + +## Having an issue or have a question? + +Please open an issue in this repository with the details of your question. Thanks! diff --git a/fairseq-tools/fairseq/examples/linformer/README.md b/fairseq-tools/fairseq/examples/linformer/README.md new file mode 100644 index 00000000..f8b36bc6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/README.md @@ -0,0 +1,22 @@ +# Linformer: Self-Attention with Linear Complexity (Wang et al., 2020) + +This example contains code to train Linformer models as described in our paper +[Linformer: Self-Attention with Linear Complexity](https://arxiv.org/abs/2006.04768). + +## Training a new Linformer RoBERTa model + +You can mostly follow the [RoBERTa pretraining README](/examples/roberta/README.pretraining.md), +updating your training command with `--user-dir examples/linformer/linformer_src --arch linformer_roberta_base`. + +## Citation + +If you use our work, please cite: + +```bibtex +@article{wang2020linformer, + title={Linformer: Self-Attention with Linear Complexity}, + author={Wang, Sinong and Li, Belinda and Khabsa, Madian and Fang, Han and Ma, Hao}, + journal={arXiv preprint arXiv:2006.04768}, + year={2020} +} +``` diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/__init__.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/__init__.py new file mode 100644 index 00000000..1c52f135 --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/linformer_src/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .models import linformer_roberta # noqa diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/models/__init__.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/models/linformer_roberta.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/models/linformer_roberta.py new file mode 100644 index 00000000..913351f2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/linformer_src/models/linformer_roberta.py @@ -0,0 +1,134 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Linformer: Self-Attention with Linear Complexity +""" + +import logging + +from fairseq.models import register_model, register_model_architecture +from fairseq.models.roberta import RobertaEncoder, RobertaModel + +from ..modules.linformer_sentence_encoder import LinformerSentenceEncoder + + +logger = logging.getLogger(__name__) + + +@register_model("linformer_roberta") +class LinformerModel(RobertaModel): + @staticmethod + def add_args(parser): + RobertaModel.add_args(parser) + + # add args for Linformer + parser.add_argument( + "--compressed", type=int, help="compressed ratio of sequence length" + ) + parser.add_argument( + "--shared-kv-compressed", + type=int, + help="share compressed matrix between k and v, in each layer", + ) + parser.add_argument( + "--shared-layer-kv-compressed", + type=int, + help="share compressed matrix between k and v and across all layers", + ) + parser.add_argument( + "--freeze-compress", + type=int, + help="freeze the parameters in compressed layer", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present + base_architecture(args) + + if not hasattr(args, "max_positions"): + args.max_positions = args.tokens_per_sample + + encoder = LinformerEncoder(args, task.source_dictionary) + return cls(args, encoder) + + +class LinformerEncoder(RobertaEncoder): + """Linformer encoder.""" + + def __init__(self, args, dictionary): + super().__init__(args, dictionary) + + self.sentence_encoder = LinformerSentenceEncoder( + padding_idx=dictionary.pad(), + vocab_size=len(dictionary), + num_encoder_layers=args.encoder_layers, + embedding_dim=args.encoder_embed_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=args.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.activation_dropout, + layerdrop=args.encoder_layerdrop, + max_seq_len=args.max_positions, + num_segments=0, + encoder_normalize_before=True, + apply_bert_init=True, + activation_fn=args.activation_fn, + q_noise=args.quant_noise_pq, + qn_block_size=args.quant_noise_pq_block_size, + compressed=args.compressed, + shared_kv_compressed=args.shared_kv_compressed, + shared_layer_kv_compressed=args.shared_layer_kv_compressed, + freeze_compress=args.freeze_compress, + ) + + +@register_model_architecture("linformer_roberta", "linformer_roberta") +def base_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 3072) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.pooler_dropout = getattr(args, "pooler_dropout", 0.0) + args.encoder_layers_to_keep = getattr(args, "encoder_layers_to_keep", None) + args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.0) + args.compressed = getattr(args, "compressed", 4) + args.shared_kv_compressed = getattr(args, "shared_kv_compressed", 0) + args.shared_layer_kv_compressed = getattr(args, "shared_layer_kv_compressed", 0) + args.freeze_compress = getattr(args, "freeze_compress", 0) + + +@register_model_architecture("linformer_roberta", "linformer_roberta_base") +def linformer_roberta_base_architecture(args): + base_architecture(args) + + +@register_model_architecture("linformer_roberta", "linformer_roberta_large") +def linformer_roberta_large_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 24) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.pooler_dropout = getattr(args, "pooler_dropout", 0.0) + args.compressed = getattr(args, "compressed", 4) + args.shared_kv_compressed = getattr(args, "shared_kv_compressed", 0) + args.shared_layer_kv_compressed = getattr(args, "shared_layer_kv_compressed", 0) diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/__init__.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder.py new file mode 100644 index 00000000..d6de9eea --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder.py @@ -0,0 +1,169 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch.nn as nn +from fairseq.modules import TransformerSentenceEncoder + +from .linformer_sentence_encoder_layer import LinformerSentenceEncoderLayer + + +class LinformerSentenceEncoder(TransformerSentenceEncoder): + """ + Implementation for a Bi-directional Linformer based Sentence Encoder used + in BERT/XLM style pre-trained models. + + This first computes the token embedding using the token embedding matrix, + position embeddings (if specified) and segment embeddings + (if specified). After applying the specified number of + LinformerEncoderLayers, it outputs all the internal states of the + encoder as well as the final representation associated with the first + token (usually CLS token). + + Input: + - tokens: B x T matrix representing sentences + - segment_labels: B x T matrix representing segment label for tokens + + Output: + - a tuple of the following: + - a list of internal model states used to compute the + predictions where each tensor has shape T x B x C + - sentence representation associated with first input token + in format B x C. + """ + + def __init__( + self, + padding_idx: int, + vocab_size: int, + num_encoder_layers: int = 6, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + layerdrop: float = 0.0, + max_seq_len: int = 256, + num_segments: int = 2, + use_position_embeddings: bool = True, + offset_positions_by_padding: bool = True, + encoder_normalize_before: bool = False, + apply_bert_init: bool = False, + activation_fn: str = "relu", + learned_pos_embedding: bool = True, + embed_scale: float = None, + freeze_embeddings: bool = False, + n_trans_layers_to_freeze: int = 0, + export: bool = False, + traceable: bool = False, + q_noise: float = 0.0, + qn_block_size: int = 8, + compressed: int = 4, + shared_kv_compressed: int = 0, + shared_layer_kv_compressed: int = 0, + freeze_compress: int = 0, + ) -> None: + + # Initialize linformer parameters + self.compressed = compressed + self.shared_kv_compressed = shared_kv_compressed + self.shared_layer_kv_compressed = shared_layer_kv_compressed + self.compress_layer = None + self.freeze_compress = freeze_compress + + super().__init__( + padding_idx=padding_idx, + vocab_size=vocab_size, + num_encoder_layers=num_encoder_layers, + embedding_dim=embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + layerdrop=layerdrop, + max_seq_len=max_seq_len, + num_segments=num_segments, + use_position_embeddings=use_position_embeddings, + offset_positions_by_padding=offset_positions_by_padding, + encoder_normalize_before=encoder_normalize_before, + apply_bert_init=apply_bert_init, + activation_fn=activation_fn, + learned_pos_embedding=learned_pos_embedding, + embed_scale=embed_scale, + freeze_embeddings=freeze_embeddings, + n_trans_layers_to_freeze=n_trans_layers_to_freeze, + export=export, + traceable=traceable, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + + def build_transformer_sentence_encoder_layer( + self, + embedding_dim, + ffn_embedding_dim, + num_attention_heads, + dropout, + attention_dropout, + activation_dropout, + activation_fn, + export, + q_noise, + qn_block_size, + ): + if self.shared_layer_kv_compressed == 1: + compress_layer = nn.Linear( + self.max_seq_len, self.max_seq_len // self.compressed + ) + # intialize parameters for compressed layer + nn.init.xavier_uniform_(compress_layer.weight, gain=1 / math.sqrt(2)) + if self.freeze_compress == 1: + compress_layer.weight.requires_grad = False + self.compress_layer = compress_layer + + return LinformerSentenceEncoderLayer( + embedding_dim=embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + q_noise=q_noise, + qn_block_size=qn_block_size, + compressed=self.compressed, + max_seq_len=self.max_seq_len, + shared_kv_compressed=self.shared_kv_compressed, + shared_compress_layer=( + None if self.shared_layer_kv_compressed == 0 else self.compress_layer + ), + freeze_compress=self.freeze_compress, + ) + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + items_to_add = {} + keys_to_remove = [] + + # update key name for shared layer in new version of code + for k in state_dict.keys(): + if k.startswith(prefix + "compress_layer"): + if self.shared_layer_kv_compressed: + for layer_idx in range(len(self.layers)): + new_k = prefix + "layers.{0}.shared_compress_layer.{1}".format( + layer_idx, + k[len(prefix + "compress_layer.") :], + ) + items_to_add[new_k] = state_dict[k] + + for k in keys_to_remove: + del state_dict[k] + + for key, value in items_to_add.items(): + state_dict[key] = value diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder_layer.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder_layer.py new file mode 100644 index 00000000..d27c5afd --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/linformer_sentence_encoder_layer.py @@ -0,0 +1,84 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Callable + +from fairseq.modules import TransformerSentenceEncoderLayer + +from .multihead_linear_attention import MultiheadLinearAttention + + +class LinformerSentenceEncoderLayer(TransformerSentenceEncoderLayer): + """ + Implements a Linformer Encoder Layer used in BERT/XLM style pre-trained + models. + """ + + def __init__( + self, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + activation_fn: str = "relu", + export: bool = False, + q_noise: float = 0.0, + qn_block_size: int = 8, + init_fn: Callable = None, + compressed: int = 1, + max_seq_len: int = 256, + shared_kv_compressed: int = 0, + shared_compress_layer: any = None, + freeze_compress: int = 0, + ) -> None: + + # Initialize linformer parameters + self.compressed = compressed + self.max_seq_len = max_seq_len + self.shared_kv_compressed = shared_kv_compressed + self.freeze_compress = freeze_compress + + def init_fn(): + # This needs to be set after nn.Module.__init__ is called + self.shared_compress_layer = shared_compress_layer + + super().__init__( + embedding_dim=embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + q_noise=q_noise, + qn_block_size=qn_block_size, + init_fn=init_fn, + ) + + def build_self_attention( + self, + embed_dim, + num_attention_heads, + dropout, + self_attention, + q_noise, + qn_block_size, + ): + return MultiheadLinearAttention( + embed_dim, + num_attention_heads, + dropout=dropout, + self_attention=True, + q_noise=q_noise, + qn_block_size=qn_block_size, + compressed=self.compressed, + max_seq_len=self.max_seq_len, + shared_kv_compressed=self.shared_kv_compressed, + shared_compress_layer=self.shared_compress_layer, + freeze_compress=self.freeze_compress, + ) diff --git a/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/multihead_linear_attention.py b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/multihead_linear_attention.py new file mode 100644 index 00000000..ba2c36b1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/linformer/linformer_src/modules/multihead_linear_attention.py @@ -0,0 +1,485 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Dict, Optional, Tuple + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.quant_noise import quant_noise +from torch import Tensor, nn +from torch.nn import Parameter + + +@with_incremental_state +class MultiheadLinearAttention(nn.Module): + """Multi-headed linformer attention. + + Projects the key and values down to the compressed dimension, before computing self-attention. + + See "Linformer: Self-Attention with Linear Complexity" for more details. + """ + + def __init__( + self, + embed_dim, + num_heads, + kdim=None, + vdim=None, + dropout=0.0, + bias=True, + add_bias_kv=False, + add_zero_attn=False, + self_attention=False, + encoder_decoder_attention=False, + q_noise=0.0, + qn_block_size=8, + compressed=1, + max_seq_len=256, + shared_kv_compressed=0, + shared_compress_layer=None, + freeze_compress=0, + ): + super().__init__() + self.embed_dim = embed_dim + self.kdim = kdim if kdim is not None else embed_dim + self.vdim = vdim if vdim is not None else embed_dim + self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim + + self.num_heads = num_heads + self.dropout = dropout + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + self.scaling = self.head_dim ** -0.5 + + self.self_attention = self_attention + self.encoder_decoder_attention = encoder_decoder_attention + + assert not self.self_attention or self.qkv_same_dim, ( + "Self-attention requires query, key and " "value to be of the same size" + ) + + self.k_proj = quant_noise( + nn.Linear(self.kdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.v_proj = quant_noise( + nn.Linear(self.vdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.q_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + # used for compress sequence to subsequence + if shared_compress_layer is None: + self.compress_seq_len = max_seq_len // compressed + self.compress_k = nn.Linear(max_seq_len, self.compress_seq_len, bias=False) + if shared_kv_compressed == 0: + self.compress_v = nn.Linear( + max_seq_len, self.compress_seq_len, bias=False + ) + self.layerwise_sharing = False + else: + self.compress_k = shared_compress_layer + if shared_kv_compressed == 0: + self.compress_v = shared_compress_layer + self.layerwise_sharing = True + self.shared_kv_compressed = shared_kv_compressed + + self.out_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + if add_bias_kv: + self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim)) + self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim)) + else: + self.bias_k = self.bias_v = None + + self.add_zero_attn = add_zero_attn + + self.reset_parameters() + + if freeze_compress == 1: + self.compress_k.weight.requires_grad = False + if shared_kv_compressed == 0: + self.compress_v.weight.requires_grad = False + + self.onnx_trace = False + self.tpu = False + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def prepare_for_tpu_(self, **kwargs): + self.tpu = True + + def reset_parameters(self): + if self.qkv_same_dim: + # Empirically observed the convergence to be much better with + # the scaled initialization + nn.init.xavier_uniform_(self.k_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.v_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.q_proj.weight, gain=1 / math.sqrt(2)) + if ( + not self.layerwise_sharing + ): # otherwise, we already initialize the parameters + nn.init.xavier_uniform_(self.compress_k.weight, gain=1 / math.sqrt(2)) + if self.shared_kv_compressed == 0: + nn.init.xavier_uniform_( + self.compress_v.weight, gain=1 / math.sqrt(2) + ) + else: + nn.init.xavier_uniform_(self.k_proj.weight) + nn.init.xavier_uniform_(self.v_proj.weight) + nn.init.xavier_uniform_(self.q_proj.weight) + if ( + not self.layerwise_sharing + ): # otherwise, we already initialize the parameters + nn.init.xavier_uniform_(self.compress_k.weight) + if self.shared_kv_compressed == 0: + nn.init.xavier_uniform_(self.compress_v.weight) + + nn.init.xavier_uniform_(self.out_proj.weight) + if self.out_proj.bias is not None: + nn.init.constant_(self.out_proj.bias, 0.0) + if self.bias_k is not None: + nn.init.xavier_normal_(self.bias_k) + if self.bias_v is not None: + nn.init.xavier_normal_(self.bias_v) + + def forward( + self, + query, + key: Optional[Tensor], + value: Optional[Tensor], + key_padding_mask: Optional[Tensor] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + need_weights: bool = True, + static_kv: bool = False, + attn_mask: Optional[Tensor] = None, + before_softmax: bool = False, + need_head_weights: bool = False, + ) -> Tuple[Tensor, Optional[Tensor]]: + """Input shape: Time x Batch x Channel + + Args: + key_padding_mask (ByteTensor, optional): mask to exclude + keys that are pads, of shape `(batch, src_len)`, where + padding elements are indicated by 1s. + need_weights (bool, optional): return the attention weights, + averaged over heads (default: False). + attn_mask (ByteTensor, optional): typically used to + implement causal attention, where the mask prevents the + attention from looking forward in time (default: None). + before_softmax (bool, optional): return the raw attention + weights and values before the attention softmax. + need_head_weights (bool, optional): return the attention + weights for each head. Implies *need_weights*. Default: + return the average attention weights over all heads. + """ + if need_head_weights: + need_weights = True + + tgt_len, bsz, embed_dim = query.size() + assert embed_dim == self.embed_dim + assert list(query.size()) == [tgt_len, bsz, embed_dim] + + if incremental_state is not None: + saved_state = self._get_input_buffer(incremental_state) + if saved_state is not None and "prev_key" in saved_state: + # previous time steps are cached - no need to recompute + # key and value if they are static + if static_kv: + assert self.encoder_decoder_attention and not self.self_attention + key = value = None + else: + saved_state = None + + if self.self_attention: + q = self.q_proj(query) + + k_input = query.permute(1, 2, 0).contiguous() # B * C * T + k_input = ( + F.linear(k_input, self.compress_k.weight[:, 0:tgt_len]) + .permute(2, 0, 1) + .contiguous() + ) + k = self.k_proj(k_input) + + v_input = query.permute(1, 2, 0).contiguous() # B * C * T + if self.shared_kv_compressed == 0: + v_input = ( + F.linear(v_input, self.compress_v.weight[:, 0:tgt_len]) + .permute(2, 0, 1) + .contiguous() + ) + if self.shared_kv_compressed == 1: # use shared kv compressed linear layer + v_input = ( + F.linear(v_input, self.compress_k.weight[:, 0:tgt_len]) + .permute(2, 0, 1) + .contiguous() + ) + v = self.v_proj(v_input) + elif self.encoder_decoder_attention: + # encoder-decoder attention + q = self.q_proj(query) + if key is None: + assert value is None + k = v = None + else: + k = self.k_proj(key) + v = self.v_proj(key) + + else: + assert key is not None and value is not None + q = self.q_proj(query) + k = self.k_proj(key) + v = self.v_proj(value) + q *= self.scaling + + if self.bias_k is not None: + assert self.bias_v is not None + k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)]) + v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)]) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + if key_padding_mask is not None: + key_padding_mask = torch.cat( + [ + key_padding_mask, + key_padding_mask.new_zeros(key_padding_mask.size(0), 1), + ], + dim=1, + ) + + q = ( + q.contiguous() + .view(tgt_len, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if k is not None: + k = ( + k.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if v is not None: + v = ( + v.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + + if saved_state is not None: + # saved states are stored with shape (bsz, num_heads, seq_len, head_dim) + if "prev_key" in saved_state: + _prev_key = saved_state["prev_key"] + assert _prev_key is not None + prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + k = prev_key + else: + assert k is not None + k = torch.cat([prev_key, k], dim=1) + if "prev_value" in saved_state: + _prev_value = saved_state["prev_value"] + assert _prev_value is not None + prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + v = prev_value + else: + assert v is not None + v = torch.cat([prev_value, v], dim=1) + prev_key_padding_mask: Optional[Tensor] = None + if "prev_key_padding_mask" in saved_state: + prev_key_padding_mask = saved_state["prev_key_padding_mask"] + assert k is not None and v is not None + key_padding_mask = MultiheadLinearAttention._append_prev_key_padding_mask( + key_padding_mask=key_padding_mask, + prev_key_padding_mask=prev_key_padding_mask, + batch_size=bsz, + src_len=k.size(1), + static_kv=static_kv, + ) + + saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_key_padding_mask"] = key_padding_mask + # In this branch incremental_state is never None + assert incremental_state is not None + incremental_state = self._set_input_buffer(incremental_state, saved_state) + assert k is not None + src_len = k.size(1) + + if self.add_zero_attn: + assert v is not None + src_len += 1 + k = torch.cat([k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1) + v = torch.cat([v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + + attn_weights = torch.bmm(q, k.transpose(1, 2)) + attn_weights = MultiheadLinearAttention.apply_sparse_mask( + attn_weights, tgt_len, src_len, bsz + ) + + assert list(attn_weights.size()) == [bsz * self.num_heads, tgt_len, src_len] + + if attn_mask is not None: + attn_mask = attn_mask.unsqueeze(0) + if self.onnx_trace: + attn_mask = attn_mask.repeat(attn_weights.size(0), 1, 1) + attn_weights += attn_mask + + if before_softmax: + return attn_weights, v + + attn_weights_float = utils.softmax( + attn_weights, dim=-1, onnx_trace=self.onnx_trace + ) + attn_weights = attn_weights_float.type_as(attn_weights) + attn_probs = F.dropout( + attn_weights, + p=self.dropout, + training=self.training, + ) + assert v is not None + attn = torch.bmm(attn_probs, v) + assert list(attn.size()) == [bsz * self.num_heads, tgt_len, self.head_dim] + if self.onnx_trace and attn.size(1) == 1: + # when ONNX tracing a single decoder step (sequence length == 1) + # the transpose is a no-op copy before view, thus unnecessary + attn = attn.contiguous().view(tgt_len, bsz, embed_dim) + else: + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) + attn = self.out_proj(attn) + attn_weights: Optional[Tensor] = None + if need_weights: + attn_weights = attn_weights_float.view( + bsz, self.num_heads, tgt_len, src_len + ).transpose(1, 0) + if not need_head_weights: + # average attention weights over heads + attn_weights = attn_weights.mean(dim=0) + + return attn, attn_weights + + @staticmethod + def _append_prev_key_padding_mask( + key_padding_mask: Optional[Tensor], + prev_key_padding_mask: Optional[Tensor], + batch_size: int, + src_len: int, + static_kv: bool, + ) -> Optional[Tensor]: + # saved key padding masks have shape (bsz, seq_len) + if prev_key_padding_mask is not None and static_kv: + new_key_padding_mask = prev_key_padding_mask + elif prev_key_padding_mask is not None and key_padding_mask is not None: + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), key_padding_mask.float()], dim=1 + ) + # During incremental decoding, as the padding token enters and + # leaves the frame, there will be a time when prev or current + # is None + elif prev_key_padding_mask is not None: + filler = torch.zeros( + (batch_size, src_len - prev_key_padding_mask.size(1)), + device=prev_key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), filler.float()], dim=1 + ) + elif key_padding_mask is not None: + filler = torch.zeros( + (batch_size, src_len - key_padding_mask.size(1)), + device=key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [filler.float(), key_padding_mask.float()], dim=1 + ) + else: + new_key_padding_mask = prev_key_padding_mask + return new_key_padding_mask + + @torch.jit.export + def reorder_incremental_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + """Reorder buffered internal state (for incremental generation).""" + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + for k in input_buffer.keys(): + input_buffer_k = input_buffer[k] + if input_buffer_k is not None: + if self.encoder_decoder_attention and input_buffer_k.size( + 0 + ) == new_order.size(0): + break + input_buffer[k] = input_buffer_k.index_select(0, new_order) + incremental_state = self._set_input_buffer(incremental_state, input_buffer) + return incremental_state + + def _get_input_buffer( + self, incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] + ) -> Dict[str, Optional[Tensor]]: + result = self.get_incremental_state(incremental_state, "attn_state") + if result is not None: + return result + else: + empty_result: Dict[str, Optional[Tensor]] = {} + return empty_result + + def _set_input_buffer( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + buffer: Dict[str, Optional[Tensor]], + ): + return self.set_incremental_state(incremental_state, "attn_state", buffer) + + def apply_sparse_mask(attn_weights, tgt_len: int, src_len: int, bsz: int): + return attn_weights + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + items_to_add = {} + keys_to_remove = [] + for k in state_dict.keys(): + if k.endswith(prefix + "in_proj_weight"): + # in_proj_weight used to be q + k + v with same dimensions + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.weight"] = state_dict[k][:dim] + items_to_add[prefix + "k_proj.weight"] = state_dict[k][dim : 2 * dim] + items_to_add[prefix + "v_proj.weight"] = state_dict[k][2 * dim :] + + keys_to_remove.append(k) + + k_bias = prefix + "in_proj_bias" + if k_bias in state_dict.keys(): + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.bias"] = state_dict[k_bias][:dim] + items_to_add[prefix + "k_proj.bias"] = state_dict[k_bias][ + dim : 2 * dim + ] + items_to_add[prefix + "v_proj.bias"] = state_dict[k_bias][2 * dim :] + + keys_to_remove.append(prefix + "in_proj_bias") + + for k in keys_to_remove: + del state_dict[k] + + for key, value in items_to_add.items(): + state_dict[key] = value diff --git a/fairseq-tools/fairseq/examples/m2m_100/README.md b/fairseq-tools/fairseq/examples/m2m_100/README.md new file mode 100644 index 00000000..a87c0f57 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/README.md @@ -0,0 +1,209 @@ +# Beyond English-Centric Multilingual Machine Translation + +## Introduction +In this work, we create a true Many-to-Many multilingual translation model that can translate directly between any pair of 100 languages. Our focus on non-English-Centric models brings gains of more than 10 BLEU when directly translating between non-English directions while performing competitively with the best single systems of WMT. + +If you are new to using fairseq, read the following walkthrough. Otherwise, skip to the sections below. + +0. **Generation Data** + +To download the generation data, follow the below commands. Note that all datasets need to be detokenized *before* applying SPM in the data preprocessing step. If you use these evaluation datasets, please cite their associated papers. +```bash +# WMT - use sacrebleu, example here: +sacrebleu -t wmt14 -l fr-en --echo src > wmt.test.fr-en.fr +sacrebleu -t wmt14 -l fr-en --echo ref > wmt.test.fr-en.en + +# WAT +wget http://lotus.kuee.kyoto-u.ac.jp/WAT/my-en-data/wat2019.my-en.zip +unzip wat2019.my-en.zip + +# FLORES +# download from: https://github.com/facebookresearch/flores + +# TED - need to detokenize with Moses! +# from: https://github.com/neulab/word-embeddings-for-nmt +wget http://phontron.com/data/ted_talks.tar.gz + +# Autshumato +# request to download: https://repo.sadilar.org/handle/20.500.12185/397 + +# Tatoeba Challenge +# available here: https://github.com/Helsinki-NLP/Tatoeba-Challenge +``` + +1. **Training Data** + +To produce the training data, we use a combination of [CCMatrix](https://arxiv.org/abs/1911.04944) and [CCAligned](https://arxiv.org/abs/1911.06154). Check out the instructions [here](https://github.com/facebookresearch/LASER/tree/master/tasks/CCMatrix) to download the raw data. + +2. **Preprocess Data** + +After downloading raw data, you will need to postprocess the data, then apply SPM, then binarize. Note that it is very important you run the postprocessing script, because this removes any instance of the evaluation data in the mined training data. + +```bash +# preprocess data + +# remove sentences with more than 50% punctuation +python /path/to/fairseq/examples/m2m_100/process_data/remove_too_much_punc.py + +# deduplicate training data +paste /path/to/datadir/train.$src /path/to/datadir/train.$tgt | awk '!x[$0]++' > /path/to/datadir/train.dedup +echo "keeping $(wc -l /path/to/datadir/train.dedup) bitext out of $(wc -l /path/to/datadir/train.$src)" +cut -f1 /path/to/datadir/train.dedup > /path/to/datadir/train.$src +cut -f2 /path/to/datadir/train.dedup > /path/to/datadir/train.$tgt + +# remove all instances of evaluation data from the training data +python /path/to/fairseq/examples/m2m_100/process_data/dedup_data.py + +# frequency cleaning +wget https://dl.fbaipublicfiles.com/m2m_100/histograms.tar.gz +tar -xvzf histograms.tar.gz +python /path/to/fairseq/examples/m2m_100/process_data/clean_histogram.py --src $src --tgt $tgt --src-file /path/to/source/file --tgt-file /path/to/output/file --src-output-file source_output.$src --tgt-output-file target_output.$tgt --histograms /path/to/histograms + +# apply SPM +wget https://dl.fbaipublicfiles.com/m2m_100/spm.128k.model +python /path/to/fairseq/scripts/spm_encode.py \ + --model spm.128k.model \ + --output_format=piece \ + --inputs=/path/to/input/file/here \ + --outputs=/path/to/output/file/here + +# length ratio cleaning +perl mosesdecoder/scripts/training/clean-corpus-n.perl --ratio 3 /path/to/training/data/train.spm.$src-$tgt $src $tgt /path/to/output/directory/train.spm.$src-$tgt 1 250 + +# binarize data +wget https://dl.fbaipublicfiles.com/m2m_100/data_dict.128k.txt +fairseq-preprocess \ + --source-lang $src --target-lang $tgt \ + --testpref spm.$src.$tgt \ + --thresholdsrc 0 --thresholdtgt 0 \ + --destdir data_bin \ + --srcdict data_dict.128k.txt --tgtdict data_dict.128k.txt +``` + +3. **Training Scripts** + +To reproduce the training of our models, we train with fairseq-py's multilingual translation [task](https://github.com/pytorch/fairseq/tree/master/examples/multilingual). If you are interested in model parallel training, also check out [fairscale](https://github.com/facebookresearch/fairscale). + +4. **Generation** + +To generate from our models, follow the the commands in the generation section below. + + +If you use any of the resources listed here, please cite: +```bibtex +@article{fan2020beyond, + title={Beyond English-Centric Multilingual Machine Translation}, + author={Fan, Angela and Bhosale, Shruti and Schwenk, Holger and Ma, Zhiyi and El-Kishky, Ahmed and Goyal, Siddharth and Baines, Mandeep and Celebi, Onur and Wenzek, Guillaume and Chaudhary, Vishrav and Goyal, Naman and Birch, Tom and Liptchinsky, Vitaliy and Edunov, Sergey and Grave, Edouard and Auli, Michael and Joulin, Armand}, + journal={arXiv preprint}, + year={2020} +} + +@article{schwenk2019ccmatrix, + title={Ccmatrix: Mining billions of high-quality parallel sentences on the web}, + author={Schwenk, Holger and Wenzek, Guillaume and Edunov, Sergey and Grave, Edouard and Joulin, Armand}, + journal={arXiv preprint arXiv:1911.04944}, + year={2019} +} + +@article{el2019massive, + title={A Massive Collection of Cross-Lingual Web-Document Pairs}, + author={El-Kishky, Ahmed and Chaudhary, Vishrav and Guzman, Francisco and Koehn, Philipp}, + journal={arXiv preprint arXiv:1911.06154}, + year={2019} +} +``` + + +## Trained Models + +Looking for other trained models? Check back soon. + +Model | Description | Download +---|---|--- +`12b_last_checkpoint` | 12B parameter model trained on many-to-many training data for 100 languages | [12b_last_checkpoint](https://dl.fbaipublicfiles.com/m2m_100/12b_last_checkpoint.pt) + + +## SentencePiece Model + +```bash +wget https://dl.fbaipublicfiles.com/m2m_100/spm.128k.model +``` + +## Generation with M2M-100 + +### Encode using our SentencePiece Model + +Note: Install SentencePiece from [here](https://github.com/google/sentencepiece) + +```bash +fairseq=/path/to/fairseq +cd $fairseq +sacrebleu --echo src -l de-fr -t wmt19 | head -n 20 > raw_input.de-fr.de +sacrebleu --echo ref -l de-fr -t wmt19 | head -n 20 > raw_input.de-fr.fr +wget https://dl.fbaipublicfiles.com/m2m_100/spm.128k.model +for lang in de fr ; do + python scripts/spm_encode.py \ + --model spm.128k.model \ + --output_format=piece \ + --inputs=raw_input.de-fr.${lang} \ + --outputs=spm.de-fr.${lang} +done +``` + +### Binarization + +```bash +wget https://dl.fbaipublicfiles.com/m2m_100/data_dict.128k.txt +fairseq-preprocess \ + --source-lang de --target-lang fr \ + --testpref spm.de-fr \ + --thresholdsrc 0 --thresholdtgt 0 \ + --destdir data_bin \ + --srcdict data_dict.128k.txt --tgtdict data_dict.128k.txt +``` + +### Generation on a V100 GPU + +```bash +wget https://dl.fbaipublicfiles.com/m2m_100/model_dict.128k.txt +wget https://dl.fbaipublicfiles.com/m2m_100/language_pairs.txt +wget https://dl.fbaipublicfiles.com/m2m_100/12b_last_checkpoint.pt +fairseq-generate \ + data_bin \ + --batch-size 1 \ + --path 12b_last_checkpoint.pt \ + --fixed-dictionary model_dict.128k.txt \ + -s de -t fr \ + --remove-bpe 'sentencepiece' \ + --beam 5 \ + --task translation_multi_simple_epoch \ + --lang-pairs language_pairs.txt \ + --decoder-langtok --encoder-langtok src \ + --gen-subset test \ + --fp16 \ + --dataset-impl mmap \ + --distributed-world-size 1 --distributed-no-spawn \ + --pipeline-model-parallel \ + --pipeline-chunks 1 \ + --pipeline-encoder-balance '[26]' \ + --pipeline-encoder-devices '[0]' \ + --pipeline-decoder-balance '[1,24,1]' \ + --pipeline-decoder-devices '[0,1,0]' > gen_out +``` +## Evaluation with M2M-100 + +### Tokenization + +Note: Refer to tokenizers/README.md for more details on tokenization. + +```bash +cd ${fairseq}/examples/m2m_100 +cat ${fairseq}/gen_out | grep -P "^H" | sort -V | cut -f 3- | sh tok.sh fr > hyp +cat ${fairseq}/raw_input.de-fr.fr | sh tok.sh fr > ref +``` + +### BLEU + +```bash +sacrebleu -tok 'none' ref < hyp +``` diff --git a/fairseq-tools/fairseq/examples/m2m_100/install_dependecies.sh b/fairseq-tools/fairseq/examples/m2m_100/install_dependecies.sh new file mode 100644 index 00000000..82a10547 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/install_dependecies.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +CWD=`pwd` +INSTALL_PATH=$CWD/tokenizers/thirdparty + +MOSES=$INSTALL_PATH/mosesdecoder +if [ ! -d $MOSES ]; then + echo 'Cloning Moses github repository (for tokenization scripts)...' + git clone https://github.com/moses-smt/mosesdecoder.git $MOSES + cd $MOSES + # To deal with differences in handling ' vs " + git checkout 03578921cc1a03402 + cd - +fi + +WMT16_SCRIPTS=$INSTALL_PATH/wmt16-scripts +if [ ! -d $WMT16_SCRIPTS ]; then + echo 'Cloning Romanian tokenization scripts' + git clone https://github.com/rsennrich/wmt16-scripts.git $WMT16_SCRIPTS +fi + +KYTEA=$INSTALL_PATH/kytea +if [ ! -f $KYTEA/bin/kytea ]; then + git clone https://github.com/neubig/kytea.git $KYTEA + cd $KYTEA + autoreconf -i + ./configure --prefix=`pwd` + make + make install + cd .. +fi + +export MECAB=$INSTALL_PATH/mecab-0.996-ko-0.9.2 +if [ ! -f $MECAB/bin/mecab ]; then + cd $INSTALL_PATH + curl -LO https://bitbucket.org/eunjeon/mecab-ko/downloads/mecab-0.996-ko-0.9.2.tar.gz + tar zxfv mecab-0.996-ko-0.9.2.tar.gz + cd mecab-0.996-ko-0.9.2/ + ./configure --prefix=`pwd` + make + make install + + cd .. + curl -LO https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/mecab-ko-dic-2.1.1-20180720.tar.gz + tar zxfv mecab-ko-dic-2.1.1-20180720.tar.gz + cd mecab-ko-dic-2.1.1-20180720/ + ./autogen.sh + ./configure --prefix=`pwd` --with-dicdir=$MECAB/lib/mecab/dic/mecab-ko-dic --with-mecab-config=$MECAB/bin/mecab-config + make + sh -c 'echo "dicdir=$MECAB/lib/mecab/dic/mecab-ko-dic" > $MECAB/etc/mecabrc' + make install + cd $CWD +fi + +INDIC_RESOURCES_PATH=$INSTALL_PATH/indic_nlp_resources +if [ ! -d $INDIC_RESOURCES_PATH ]; then + echo 'Cloning indic_nlp_resources' + git clone https://github.com/anoopkunchukuttan/indic_nlp_resources.git $INDIC_RESOURCES_PATH +fi + + +if [ ! -f $INSTALL_PATH/seg_my.py ]; then + cd $INSTALL_PATH + wget http://lotus.kuee.kyoto-u.ac.jp/WAT/my-en-data/wat2020.my-en.zip + unzip wat2020.my-en.zip + # switch to python3 + cat wat2020.my-en/myseg.py |sed 's/^sys.std/###sys.std/g' | sed 's/### sys/sys/g' | sed 's/unichr/chr/g' > seg_my.py + cd $CWD +fi + + +pip install pythainlp sacrebleu indic-nlp-library + diff --git a/fairseq-tools/fairseq/examples/m2m_100/process_data/clean_histogram.py b/fairseq-tools/fairseq/examples/m2m_100/process_data/clean_histogram.py new file mode 100644 index 00000000..e24e073d --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/process_data/clean_histogram.py @@ -0,0 +1,52 @@ +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('--src', type=str, help='Source language') +parser.add_argument('--tgt', type=str, help='Target language') +parser.add_argument('--src-file', type=str, help='Input source file') +parser.add_argument('--tgt-file', type=str, help='Input target file') +parser.add_argument('--src-output-file', type=str, help='Output source file') +parser.add_argument('--tgt-output-file', type=str, help='Output target file') +parser.add_argument('--threshold', type=float, default=0.5, help='Threshold') +parser.add_argument('--threshold-character', type=str, default=']', help='Threshold character') +parser.add_argument('--histograms', type=str, help='Path to histograms') + +args = parser.parse_args() + + +def read_hist(f): + ch = [] + for line in f: + c = line[0] + if c == args.threshold_character: + break + ch.append(c) + return ch + + +with(open("{}/{}".format(args.histograms, args.src), 'r', encoding='utf8')) as f: + ch1 = read_hist(f) + +with(open("{}/{}".format(args.histograms, args.tgt), 'r', encoding='utf8')) as f: + ch2 = read_hist(f) + +print("Accepted characters for {}: {}".format(args.src, ch1)) +print("Accepted characters for {}: {}".format(args.tgt, ch2)) + +with open(args.src_file, 'r', encoding='utf8') as fs1, open(args.tgt_file, 'r', encoding='utf8') as fs2, open(args.src_output_file, 'w', encoding='utf8') as fos1, open(args.tgt_output_file, 'w', encoding='utf8') as fos2: + ls1 = fs1.readline() + ls2 = fs2.readline() + + while ls1 or ls2: + cnt1 = len([c for c in ls1.strip() if c in ch1]) + cnt2 = len([c for c in ls2.strip() if c in ch2]) + + if cnt1 / len(ls1) > args.threshold and cnt2 / len(ls2) > args.threshold: + fos1.write(ls1) + fos2.write(ls2) + else: + print("{} {} {} \n{} {} {}".format(args.src, cnt1 / len(ls1), ls1.strip(), args.tgt, cnt2 / len(ls2), ls2.strip())) + + ls1 = fs1.readline() + ls2 = fs2.readline() + \ No newline at end of file diff --git a/fairseq-tools/fairseq/examples/m2m_100/process_data/dedup_data.py b/fairseq-tools/fairseq/examples/m2m_100/process_data/dedup_data.py new file mode 100644 index 00000000..58d9ed1c --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/process_data/dedup_data.py @@ -0,0 +1,91 @@ +import argparse +from collections import namedtuple +import os + +DATADIR = "/path/to/train_data" +DEDUP_FROM_DIR = "/path/to/eval/data" +OUTPUT_DIR = "/path/to/output/data" + + +def main(args): + languages = set() + for language_directory in os.listdir(DATADIR): + if "_" in language_directory: + src, tgt = language_directory.split("_") + languages.add(LanguagePair(src=src, tgt=tgt)) + + data = existing_data() + train_languages = sorted(languages) + for language_pair in train_languages[args.start_index:args.start_index + args.size]: + print(language_pair) + dedup(language_pair, data) + + +LanguagePair = namedtuple("LanguagePair", ["src", "tgt"]) + + +def existing_data(): + data = set() + for file in os.listdir(DEDUP_FROM_DIR): + with open(os.path.join(DEDUP_FROM_DIR, file)) as f: + data |= set(f.readlines()) + return data + +def dedup(language_pair, data, verbose=True, output=True): + train_filenames = LanguagePair( + src=f"{DATADIR}/{language_pair.src}_{language_pair.tgt}/train.{language_pair.src}", + tgt=f"{DATADIR}/{language_pair.src}_{language_pair.tgt}/train.{language_pair.tgt}", + ) + + output_filenames = LanguagePair( + src=f"{OUTPUT_DIR}/train.dedup.{language_pair.src}-{language_pair.tgt}.{language_pair.src}", + tgt=f"{OUTPUT_DIR}/train.dedup.{language_pair.src}-{language_pair.tgt}.{language_pair.tgt}" + ) + + # If output exists, skip this pair. It has already been done. + if (os.path.exists(output_filenames.src) and + os.path.exists(output_filenames.tgt)): + if verbose: + print(f"{language_pair.src}-{language_pair.tgt} already done.") + return + + if verbose: + print(f"{language_pair.src}-{language_pair.tgt} ready, will check dups.") + + # If there is no output, no need to actually do the loop. + if not output: + return + + if os.path.exists(train_filenames.src) and os.path.exists(train_filenames.tgt): + with open(train_filenames.src) as f: + train_source = f.readlines() + + with open(train_filenames.tgt) as f: + train_target = f.readlines() + + # do dedup + new_train_source = [] + new_train_target = [] + for i, train_line in enumerate(train_source): + if train_line not in data and train_target[i] not in data: + new_train_source.append(train_line) + new_train_target.append(train_target[i]) + + assert len(train_source) == len(train_target) + assert len(new_train_source) == len(new_train_target) + assert len(new_train_source) <= len(train_source) + + with open(output_filenames.src, "w") as o: + for line in new_train_source: + o.write(line) + + with open(output_filenames.tgt, "w") as o: + for line in new_train_target: + o.write(line) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-s", "--start-index", required=True, type=int) + parser.add_argument("-n", "--size", required=True, type=int) + main(parser.parse_args()) diff --git a/fairseq-tools/fairseq/examples/m2m_100/process_data/remove_too_much_punc.py b/fairseq-tools/fairseq/examples/m2m_100/process_data/remove_too_much_punc.py new file mode 100644 index 00000000..6c280de2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/process_data/remove_too_much_punc.py @@ -0,0 +1,36 @@ +import gzip +import argparse +from string import punctuation + +def len_no_punc(s, punc): + return len([ch for ch in s if ch in punc]) + +def filter_overpunc(len_npunc, len_sen): + return len_npunc < 0.5*len_sen + +def main(args): + punc = punctuation + "—|–" + print('Processing file {}'.format(args.input)) + with gzip.open(args.input, 'rt', encoding=args.encoding) as tsv: + with open(args.bitext + '.' + args.src_lang, 'wt', encoding=args.encoding) as fsrc: + with open(args.bitext + '.' + args.tgt_lang, 'wt', encoding=args.encoding) as ftgt: + line = tsv.readline() + fields = line.split('\t') + + src, tgt = fields[1], fields[2] + + nchar_npunc_src = len_no_punc(src, punc) + nchar_npunc_tgt = len_no_punc(tgt, punc) + + if filter_overpunc(nchar_npunc_src, len(src)) and filter_overpunc(nchar_npunc_tgt, len(tgt)): + fsrc.write(src.strip() + '\n') + ftgt.write(tgt.strip() + '\n') + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--input", required=True, type=str) + parser.add_argument('--encoding', default='utf-8', help='character encoding for input/output') + parser.add_argument('--bitext', type=str, required=True, help='language direction') + parser.add_argument('--src-lang', type=str, required=True, help='Source language') + parser.add_argument('--tgt-lang', type=str, required=True, help='Target language') + main(parser.parse_args()) diff --git a/fairseq-tools/fairseq/examples/m2m_100/tok.sh b/fairseq-tools/fairseq/examples/m2m_100/tok.sh new file mode 100644 index 00000000..ba2ec5a2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tok.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# Copyright (c) 2019-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. +# + +set -e + +TOKENIZERS_SCRIPTS=tokenizers +INSTALL_PATH=$TOKENIZERS_SCRIPTS/thirdparty + +N_THREADS=8 + +lg=$1 + +MOSES=$INSTALL_PATH/mosesdecoder +REPLACE_UNICODE_PUNCT=$MOSES/scripts/tokenizer/replace-unicode-punctuation.perl +NORM_PUNC=$MOSES/scripts/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$MOSES/scripts/tokenizer/remove-non-printing-char.perl +TOKENIZER=$MOSES/scripts/tokenizer/tokenizer.perl + +# special tokenization for Romanian +WMT16_SCRIPTS=$INSTALL_PATH/wmt16-scripts + +NORMALIZE_ROMANIAN=$WMT16_SCRIPTS/preprocess/normalise-romanian.py +REMOVE_DIACRITICS=$WMT16_SCRIPTS/preprocess/remove-diacritics.py + +# Burmese +MY_SEGMENT=$INSTALL_PATH/seg_my.py + +# Arabic +AR_TOKENIZER=$TOKENIZERS_SCRIPTS/tokenizer_ar.sh + +# Korean +KO_SEGMENT=$TOKENIZERS_SCRIPTS/seg_ko.sh + +# Japanese +JA_SEGMENT=$TOKENIZERS_SCRIPTS/seg_ja.sh + +# Indic +IN_TOKENIZER=$TOKENIZERS_SCRIPTS/tokenize_indic.py +INDIC_RESOURCES_PATH=$INSTALL_PATH/indic_nlp_resources + +# Thai +THAI_TOKENIZER=$TOKENIZERS_SCRIPTS/tokenize_thai.py + +# Chinese +CHINESE_TOKENIZER=$TOKENIZERS_SCRIPTS/tokenize_zh.py + +# Chinese +if [ "$lg" = "zh" ]; then + cat - | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l $lg | $REM_NON_PRINT_CHAR | python $CHINESE_TOKENIZER +# Thai +elif [ "$lg" = "th" ]; then + cat - | python $THAI_TOKENIZER +# Japanese +elif [ "$lg" = "ja" ]; then + cat - | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l $lg | $REM_NON_PRINT_CHAR | ${JA_SEGMENT} +# Korean +elif [ "$lg" = "ko" ]; then + cat - | $REM_NON_PRINT_CHAR | ${KO_SEGMENT} +# Romanian +elif [ "$lg" = "ro" ]; then + cat - | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l $lg | $REM_NON_PRINT_CHAR | $NORMALIZE_ROMANIAN | $REMOVE_DIACRITICS | $TOKENIZER -no-escape -threads $N_THREADS -l $lg +# Burmese +elif [ "$lg" = "my" ]; then + cat - | python ${MY_SEGMENT} +# Arabic +elif [ "$lg" = "ar" ]; then + cat - | ${AR_TOKENIZER} +# Indic +elif [ "$lg" = "ne" ]; then + cat - | python ${IN_TOKENIZER} $lg +elif [ "$lg" = "si" ]; then + cat - | python ${IN_TOKENIZER} $lg +elif [ "$lg" = "hi" ]; then + cat - | python ${IN_TOKENIZER} $lg +# other languages +else + cat - | $REPLACE_UNICODE_PUNCT | $NORM_PUNC -l $lg | $REM_NON_PRINT_CHAR | $TOKENIZER -no-escape -threads $N_THREADS -l $lg +fi diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/README.md b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/README.md new file mode 100644 index 00000000..e116932b --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/README.md @@ -0,0 +1,18 @@ +# M2M-100 Tokenization + +We apply different tokenization strategies for different languages following the existing literature. Here we provide tok.sh a tokenizer that can be used to reproduce our results. + +To reproduce the results, follow these steps: + +``` +tgt_lang=... +reference_translation=... +cat generation_output | grep -P "^H" | sort -V | cut -f 3- | sh tok.sh $tgt_lang > hyp +cat $reference_translation |sh tok.sh $tgt_lang > ref +sacrebleu -tok 'none' ref < hyp +``` + +## Installation + +Tools needed for all the languages except Arabic can be installed by running install_dependencies.sh +If you want to evaluate Arabic models, please follow the instructions provided here: http://alt.qcri.org/tools/arabic-normalizer/ to install diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ja.sh b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ja.sh new file mode 100644 index 00000000..be6f5ca5 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ja.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +SCRIPT=`realpath $0` +KYTEA=`dirname $SCRIPT`/thirdparty/kytea +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$KYTEA/lib:/usr/local/lib +export PATH=$PATH:"$KYTEA/bin" + +cat - | tr -d "[:blank:]" | kytea -notags diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ko.sh b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ko.sh new file mode 100644 index 00000000..c523d926 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/seg_ko.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +SCRIPT=`realpath $0` +MECAB=`dirname $SCRIPT`/thirdparty/mecab-0.996-ko-0.9.2 + +export PATH=$PATH:"$MECAB/bin":"$MECAB/lib" +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:"$MECAB/lib" + +cat - | mecab -O wakati diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/thirdparty/.gitignore b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/thirdparty/.gitignore new file mode 100644 index 00000000..19eb6a9d --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/thirdparty/.gitignore @@ -0,0 +1,12 @@ +seg_my.py +indic_nlp_library/ +indic_nlp_resources/ +kytea/ +mecab-0.996-ko-0.9.2.tar.gz +mecab-0.996-ko-0.9.2/ +mosesdecoder/ +wat2020.my-en.zip +wat2020.my-en/ +wmt16-scripts/ +mecab-ko-dic-2.1.1-20180720/ +mecab-ko-dic-2.1.1-20180720.tar.gz \ No newline at end of file diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_indic.py b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_indic.py new file mode 100644 index 00000000..a44fad07 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_indic.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Use: echo {text} | python tokenize_indic.py {language} + +import sys + +from indicnlp.normalize.indic_normalize import IndicNormalizerFactory +from indicnlp.tokenize.indic_tokenize import trivial_tokenize + + +factory = IndicNormalizerFactory() +normalizer = factory.get_normalizer( + sys.argv[1], remove_nuktas=False, nasals_mode="do_nothing" +) + +for line in sys.stdin: + normalized_line = normalizer.normalize(line.strip()) + tokenized_line = " ".join(trivial_tokenize(normalized_line, sys.argv[1])) + print(tokenized_line) diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_thai.py b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_thai.py new file mode 100644 index 00000000..9c72cb89 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_thai.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys + +from pythainlp import word_tokenize + + +for line in sys.stdin: + print(" ".join(word_tokenize(line.strip()))) diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_zh.py b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_zh.py new file mode 100644 index 00000000..674b5849 --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenize_zh.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +import fileinput + +import sacrebleu + + +for line in fileinput.input(): + print(sacrebleu.tokenize_zh(line)) diff --git a/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenizer_ar.sh b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenizer_ar.sh new file mode 100644 index 00000000..ad35d7ad --- /dev/null +++ b/fairseq-tools/fairseq/examples/m2m_100/tokenizers/tokenizer_ar.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env sh +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# +# Please follow the instructions here http://alt.qcri.org/tools/arabic-normalizer/ +# to install tools needed for Arabic + +echo "Please install Arabic tools: http://alt.qcri.org/tools/arabic-normalizer/" +echo "Then update environment variables in tokenizer_ar.sh" +exit 1 + +SVMTOOL=... +GOMOSESGO=... +QCRI_ARABIC_NORMALIZER=... + +export PERL5LIB="$SVMTOOL/lib":"$GOMOSESGO/bin/MADA-3.2":$PERL5LIB + + +tempfile=$(mktemp) +cat - > $tempfile + +cd $QCRI_ARABIC_NORMALIZER + +bash qcri_normalizer_mada3.2_aramorph1.2.1.sh $tempfile +cat $tempfile.mada_norm-aramorph.europarl_tok diff --git a/fairseq-tools/fairseq/examples/mbart/README.md b/fairseq-tools/fairseq/examples/mbart/README.md new file mode 100644 index 00000000..510edeff --- /dev/null +++ b/fairseq-tools/fairseq/examples/mbart/README.md @@ -0,0 +1,123 @@ +# MBART: Multilingual Denoising Pre-training for Neural Machine Translation +[https://arxiv.org/abs/2001.08210] + +## Introduction + +MBART is a sequence-to-sequence denoising auto-encoder pre-trained on large-scale monolingual corpora in many languages using the BART objective. mBART is one of the first methods for pre-training a complete sequence-to-sequence model by denoising full texts in multiple languages, while previous approaches have focused only on the encoder, decoder, or reconstructing parts of the text. + +## Pre-trained models + +Model | Description | # params | Download +---|---|---|--- +`mbart.CC25` | mBART model with 12 encoder and decoder layers trained on 25 languages' monolingual corpus | 610M | [mbart.CC25.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/mbart/mbart.CC25.tar.gz) +`mbart.ft.ro_en` | finetune mBART cc25 model on ro-en language pairs | 610M | [mbart.cc25.ft.enro.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/mbart/mbart.cc25.ft.enro.tar.gz) + +## Results + +**[WMT16 EN-RO](https://www.statmt.org/wmt16/translation-task.html)** + +_(test set, no additional data used)_ + +Model | en-ro | ro-en +---|---|--- +`Random` | 34.3 | 34.0 +`mbart.cc25` | 37.7 | 37.8 +`mbart.enro.bilingual` | 38.5 | 38.5 + +## BPE data +# download model +wget https://dl.fbaipublicfiles.com/fairseq/models/mbart/mbart.CC25.tar.gz +tar -xzvf mbart.CC25.tar.gz +# bpe data +install SPM [here](https://github.com/google/sentencepiece) +```bash +SPM=/path/to/sentencepiece/build/src/spm_encode +MODEL=sentence.bpe.model +${SPM} --model=${MODEL} < ${DATA}/${TRAIN}.${SRC} > ${DATA}/${TRAIN}.spm.${SRC} & +${SPM} --model=${MODEL} < ${DATA}/${TRAIN}.${TGT} > ${DATA}/${TRAIN}.spm.${TGT} & +${SPM} --model=${MODEL} < ${DATA}/${VALID}.${SRC} > ${DATA}/${VALID}.spm.${SRC} & +${SPM} --model=${MODEL} < ${DATA}/${VALID}.${TGT} > ${DATA}/${VALID}.spm.${TGT} & +${SPM} --model=${MODEL} < ${DATA}/${TEST}.${SRC} > ${DATA}/${TEST}.spm.${SRC} & +${SPM} --model=${MODEL} < ${DATA}/${TEST}.${TGT} > ${DATA}/${TEST}.spm.${TGT} & +``` + +## Preprocess data + +```bash +DICT=dict.txt +fairseq-preprocess \ + --source-lang ${SRC} \ + --target-lang ${TGT} \ + --trainpref ${DATA}/${TRAIN}.spm \ + --validpref ${DATA}/${VALID}.spm \ + --testpref ${DATA}/${TEST}.spm \ + --destdir ${DEST}/${NAME} \ + --thresholdtgt 0 \ + --thresholdsrc 0 \ + --srcdict ${DICT} \ + --tgtdict ${DICT} \ + --workers 70 +``` + +## Finetune on EN-RO +Finetune on mbart CC25 + +```bash +PRETRAIN=mbart.cc25 # fix if you moved the downloaded checkpoint +langs=ar_AR,cs_CZ,de_DE,en_XX,es_XX,et_EE,fi_FI,fr_XX,gu_IN,hi_IN,it_IT,ja_XX,kk_KZ,ko_KR,lt_LT,lv_LV,my_MM,ne_NP,nl_XX,ro_RO,ru_RU,si_LK,tr_TR,vi_VN,zh_CN + +fairseq-train path_2_data \ + --encoder-normalize-before --decoder-normalize-before \ + --arch mbart_large --layernorm-embedding \ + --task translation_from_pretrained_bart \ + --source-lang en_XX --target-lang ro_RO \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler polynomial_decay --lr 3e-05 --min-lr -1 --warmup-updates 2500 --total-num-update 40000 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 1024 --update-freq 2 \ + --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ + --seed 222 --log-format simple --log-interval 2 \ + --restore-file $PRETRAIN \ + --reset-optimizer --reset-meters --reset-dataloader --reset-lr-scheduler \ + --langs $langs \ + --ddp-backend no_c10d +``` +## Generate on EN-RO +Get sacrebleu on finetuned en-ro model + +get tokenizer [here](https://github.com/rsennrich/wmt16-scripts) +```bash +wget https://dl.fbaipublicfiles.com/fairseq/models/mbart/mbart.cc25.ft.enro.tar.gz +tar -xzvf mbart.cc25.ft.enro.tar.gz +``` + +```bash +model_dir=MBART_finetuned_enro # fix if you moved the checkpoint + +fairseq-generate path_2_data \ + --path $model_dir/model.pt \ + --task translation_from_pretrained_bart \ + --gen-subset test \ + -t ro_RO -s en_XX \ + --bpe 'sentencepiece' --sentencepiece-model $model_dir/sentence.bpe.model \ + --sacrebleu --remove-bpe 'sentencepiece' \ + --batch-size 32 --langs $langs > en_ro + +cat en_ro | grep -P "^H" |sort -V |cut -f 3- | sed 's/\[ro_RO\]//g' |$TOKENIZER ro > en_ro.hyp +cat en_ro | grep -P "^T" |sort -V |cut -f 2- | sed 's/\[ro_RO\]//g' |$TOKENIZER ro > en_ro.ref +sacrebleu -tok 'none' -s 'none' en_ro.ref < en_ro.hyp +``` + +## Citation + +```bibtex +@article{liu2020multilingual, + title={Multilingual Denoising Pre-training for Neural Machine Translation}, + author={Yinhan Liu and Jiatao Gu and Naman Goyal and Xian Li and Sergey Edunov and Marjan Ghazvininejad and Mike Lewis and Luke Zettlemoyer}, + year={2020}, + eprint={2001.08210}, + archivePrefix={arXiv}, + primaryClass={cs.CL} +} +``` diff --git a/fairseq-tools/fairseq/examples/megatron_11b/README.md b/fairseq-tools/fairseq/examples/megatron_11b/README.md new file mode 100644 index 00000000..945c96c9 --- /dev/null +++ b/fairseq-tools/fairseq/examples/megatron_11b/README.md @@ -0,0 +1,161 @@ +# Megatron-11b + +Megatron-11b is a unidirectional language model with `11B` parameters based on [Megatron-LM](https://arxiv.org/pdf/1909.08053.pdf). Following the original Megatron work, we trained the model using intra-layer model parallelism with each layer's parameters split across 8 GPUs. + +Megatron-11b is trained on the same data and uses the same byte-pair encoding (BPE) as [RoBERTa](https://arxiv.org/pdf/1907.11692.pdf). + +## Pre-trained models + +Model | Description | # params | # filesize | Download +---|---|---|---|--- +`megatron_11b` | megatron_11b unidirectional language model | 11B | 19Gb | [megatron_11b.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/model_parallel/megatron_11b.tar.gz) + +#### Architecture: + +Param | Value +---|--- +embed_dim | 3072 +ffn_dim | 3072 * 6 +layers | 72 +attention heads | 32 + +#### Training details: + +Param | value +---|--- +bsz | 512 +num_updates | 300,000 +peak_lr | 1.5e-04 +lr scheduler | inverse_sqrt +clip norm | 0.0 + + +## Example training command (model parallel) + +Megatron-11b contains too many parameters to train on a single GPU. Following +the original Megatron work, we adopt an intra-layer model parallel training +approach in which each layer's parameters are split across multiple GPUs and +activations and gradients are communicated during the forward/backward pass, +respectively. We similarly split the loss computation using the +`vocab_parallel_cross_entropy` criterion. + +The following training command illustrates how to do model parallel training in +fairseq. We assume that each machine (node) has 8 GPUs among which to split the +model parameters (`--model-parallel-size 8`). If you have access to multiple +nodes, you may combine this with data parallel training by increasing +`--distributed-world-size`. + +To train Megatron-11b on a single node: + + +```bash +fairseq-train \ + --distributed-world-size 8 \ + --memory-efficient-fp16 \ + --num-workers 2 \ + --model-parallel-size 8 \ + --criterion vocab_parallel_cross_entropy \ + --task language_modeling \ + --sample-break-mode none \ + --tokens-per-sample 1024 \ + --arch transformer_lm_megatron_11b \ + --share-decoder-input-output-embed \ + --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-08 --clip-norm 0.0 \ + --lr-scheduler inverse_sqrt --lr 0.00015 \ + --warmup-updates 3000 --weight-decay 0.01 \ + --dropout 0.1 --attention-dropout 0.1 \ + --batch-size 2 \ + --max-update 300000; +``` + +Note: Above was tested on `DGX-1` box, with `8xV100-32Gb` GPUs. + +## Results + +**[Wikitext103](https://blog.einstein.ai/the-wikitext-long-term-dependency-language-modeling-dataset/)** + +Model | Valid perplexity | Test perplexity +---|---|--- +`megatron_11b` | 10.64 | 10.54 + + +## Evaluating `megatron_11b` on Wikitext-103 + +#### 1. Downloading Megatron-11b +```bash +# WARNING: this file is 19GB +wget https://dl.fbaipublicfiles.com/fairseq/models/model_parallel/megatron_11b.tar.gz +tar -xzvf megatron_11b.tar.gz +``` + +#### 2. Download Wikitext-103 +```bash +wget https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip +unzip wikitext-103-raw-v1.zip +``` + +#### 3. Detokenize test tokens +Megatron-11b uses a byte-level BPE that expects raw (untokenized) input. Since +the wikitext-103 dataset comes tokenized, we apply a simple detokenization +process to restore the untokenized test set: + +```bash +python -m examples.megatron_11b.detok wikitext-103-raw/wiki.test.raw > wikitext-103-raw/wiki.test.detok +``` + +#### 4. BPE encoding +```bash +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' + +python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json encoder.json \ + --vocab-bpe vocab.bpe \ + --inputs "wikitext-103-raw/wiki.test.detok" \ + --outputs "wikitext-103-raw/wiki.test.bpe" \ + --workers 60; +``` + +#### 5. Fairseq binarize +```bash +fairseq-preprocess \ + --only-source \ + --testpref wikitext-103-raw/wiki.test.bpe \ + --srcdict megatron_11b/dict.txt \ + --destdir wikitext103-bin; +``` + +#### 6. Evaluating perplexity. +We can now evaluate perplexity on the test set. Note that because we've modified +the test set (via detokenization and BPE), the perplexity reported by +`fairseq-eval-lm` needs to be renormalized. + +Compute unnormalized perplexity: + +```bash +DATA_PATH=wikitext103-bin/ +fairseq-eval-lm \ + $DATA_PATH \ + --path megatron_11b/model.pt \ + --task language_modeling \ + --gen-subset test \ + --batch-size 8 \ + --criterion cross_entropy \ + --context-window 992 \ + --distributed-world-size 8 \ + --model-parallel-size 8; +# Expected PPL (unnormalized_ppl): [8.46] +# Note: the eval command needs to run on 8 GPUs for the released model +``` +Renormalizing formula: `2 ^ ( log_2(unnormalized_PPL) * (270847 / 245566))`. +PPL After normalization: `10.54` + +To renormalize the perplexity, we must account for the change in token count +after detokenizing and appling BPE. The formula for this is: +`2 ^ ( log_2(unnormalized_PPL) * (new_token_cnt / orig_token_cnt))` + +For the wikitext-103 test set, the original token count is `245566` and the +token count after detokenization and applying BPE is `270847`. + +The perplexity after renormalization is: +`2 ^ ( log_2(8.46) * (270847 / 245566)) = 10.54` diff --git a/fairseq-tools/fairseq/examples/megatron_11b/detok.py b/fairseq-tools/fairseq/examples/megatron_11b/detok.py new file mode 100644 index 00000000..49921b28 --- /dev/null +++ b/fairseq-tools/fairseq/examples/megatron_11b/detok.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import fileinput + +import sacremoses + + +def main(): + parser = argparse.ArgumentParser(description="") + parser.add_argument("files", nargs="*", help="input files") + args = parser.parse_args() + + detok = sacremoses.MosesDetokenizer() + + for line in fileinput.input(args.files, openhook=fileinput.hook_compressed): + print( + detok.detokenize(line.strip().split(" ")) + .replace(" @", "") + .replace("@ ", "") + .replace(" =", "=") + .replace("= ", "=") + .replace(" – ", "–") + ) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/multilingual/README.md b/fairseq-tools/fairseq/examples/multilingual/README.md new file mode 100644 index 00000000..3559c244 --- /dev/null +++ b/fairseq-tools/fairseq/examples/multilingual/README.md @@ -0,0 +1,124 @@ +# Multilingual Translation + +[[Multilingual Translation with Extensible Multilingual Pretraining and Finetuning, https://arxiv.org/abs/2008.00401]](https://arxiv.org/abs/2008.00401) + +## Introduction + +This work is for training multilingual translation models with multiple bitext datasets. This multilingual translation framework supports (see [[training section]](#Training) and [[finetuning section]](#Finetuning) for examples) + +* temperature based sampling over unbalancing datasets of different translation directions + - --sampling-method' with + choices=['uniform', 'temperature', 'concat'] + - --sampling-temperature +* configurable to automatically add source and/or target language tokens to source/target sentences using data which are prepared in the same way as bilignual training + - --encoder-langtok with choices=['src', 'tgt', None] to specify whether to add source or target language tokens to the source sentences + - --decoder-langtok (binary option) to specify whether to add target language tokens to the target sentences or not +* finetuning mBART pretrained models for multilingual translation + - --finetune-from-model to specify the path from which to load the pretrained model + +## Preprocessing data +Multilingual training requires a joint BPE vocab. Please follow [mBART's preprocessing steps](https://github.com/pytorch/fairseq/tree/master/examples/mbart#bpe-data) to reuse our pretrained sentence-piece model. + +You can also train a joint BPE model on your own dataset and then follow the steps in [[link]](https://github.com/pytorch/fairseq/tree/master/examples/translation#multilingual-translation). + +## Training + + +```bash +lang_pairs= +path_2_data= +lang_list=
+ +fairseq-train $path_2_data \ + --encoder-normalize-before --decoder-normalize-before \ + --arch transformer --layernorm-embedding \ + --task translation_multi_simple_epoch \ + --sampling-method "temperature" \ + --sampling-temperature 1.5 \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler inverse_sqrt --lr 3e-05 --min-lr -1 --warmup-updates 2500 --max-update 40000 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 1024 --update-freq 2 \ + --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ + --seed 222 --log-format simple --log-interval 2 +``` + +## Finetuning +We can also finetune multilingual models from a monolingual pretrained models, e.g. [mMBART](https://github.com/pytorch/fairseq/tree/master/examples/mbart). +```bash +lang_pairs= +path_2_data= +lang_list= +pretrained_model= + +fairseq-train $path_2_data \ + --finetune-from-model $pretrained_model \ + --encoder-normalize-before --decoder-normalize-before \ + --arch transformer --layernorm-embedding \ + --task translation_multi_simple_epoch \ + --sampling-method "temperature" \ + --sampling-temperature 1.5 \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler inverse_sqrt --lr 3e-05 --min-lr -1 --warmup-updates 2500 --max-update 40000 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 1024 --update-freq 2 \ + --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ + --seed 222 --log-format simple --log-interval 2 +``` +## Generate +The following command uses the multilingual task (translation_multi_simple_epoch) to generate translation from $source_lang to $target_lang on the test dataset. During generaton, the source language tokens are added to source sentences and the target language tokens are added as the starting token to decode target sentences. Options --lang-dict and --lang-pairs are needed to tell the generation process the ordered list of languages and translation directions that the trained model are awared of; they will need to be consistent with the training. + +```bash +model= +source_lang= +target_lang= + +fairseq-generate $path_2_data \ + --path $model \ + --task translation_multi_simple_epoch \ + --gen-subset test \ + --source-lang $source_lang \ + --target-lang $target_lang + --sacrebleu --remove-bpe 'sentencepiece'\ + --batch-size 32 \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" > ${source_lang}_${target_lang}.txt +``` +Fairseq will generate translation into a file {source_lang}_${target_lang}.txt with sacreblue at the end. + +You can also use costomized tokenizer to compare the performance with the literature. For example, you get a tokenizer [here](https://github.com/rsennrich/wmt16-scripts) and do the following: +```bash +TOKENIZER= +TOK_CMD=<"$TOKENIZER $target_lang" or cat for sacrebleu> + +cat {source_lang}_${target_lang}.txt | grep -P "^H" |sort -V |cut -f 3- |$TOK_CMD > ${source_lang}_${target_lang}.hyp +cat {source_lang}_${target_lang}.txt | grep -P "^T" |sort -V |cut -f 2- |$TOK_CMD > ${source_lang}_${target_lang}.ref +sacrebleu -tok 'none' -s 'none' ${source_lang}_${target_lang}.ref < ${source_lang}_${target_lang}.hyp +``` + + + +## Citation + +```bibtex +@article{tang2020multilingual, + title={Multilingual Translation with Extensible Multilingual Pretraining and Finetuning}, + author={Yuqing Tang and Chau Tran and Xian Li and Peng-Jen Chen and Naman Goyal and Vishrav Chaudhary and Jiatao Gu and Angela Fan}, + year={2020}, + eprint={2008.00401}, + archivePrefix={arXiv}, + primaryClass={cs.CL} +} +``` diff --git a/fairseq-tools/fairseq/examples/multilingual/finetune_multilingual_model.sh b/fairseq-tools/fairseq/examples/multilingual/finetune_multilingual_model.sh new file mode 100644 index 00000000..cfa9a861 --- /dev/null +++ b/fairseq-tools/fairseq/examples/multilingual/finetune_multilingual_model.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +path_2_data=$1 # which contains binarized data for each directions +lang_list=$2 # +lang_pairs=$3 #a list language pairs to train multilingual models, e.g. "en-fr,en-cs,fr-en,cs-en" +# pretrained can be an mBART pretrained model as well +pretrained_model=$4 # + + +fairseq-train "$path_2_data" \ + --encoder-normalize-before --decoder-normalize-before \ + --arch transformer --layernorm-embedding \ + --task translation_multi_simple_epoch \ + --finetune-from-model "$pretrained_model" \ + --sampling-method "temperature" \ + --sampling-temperature "1.5" \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler inverse_sqrt --lr 3e-05 --min-lr -1 --warmup-updates 2500 --max-update 40000 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 1024 --update-freq 2 \ + --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ + --seed 222 --log-format simple --log-interval 2 diff --git a/fairseq-tools/fairseq/examples/multilingual/multilingual_fairseq_gen.sh b/fairseq-tools/fairseq/examples/multilingual/multilingual_fairseq_gen.sh new file mode 100644 index 00000000..8c2c7703 --- /dev/null +++ b/fairseq-tools/fairseq/examples/multilingual/multilingual_fairseq_gen.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +lang_pairs="en-fr,en-cs,fr-en,cs-en" +path_2_data=$1 # +lang_list=$2 # +model=$3 # +source_lang=cs +target_lang=en + +fairseq-generate "$path_2_data" \ + --path "$model" \ + --task translation_multi_simple_epoch \ + --gen-subset test \ + --source-lang "$source_lang" \ + --target-lang "$target_lang" \ + --sacrebleu --remove-bpe 'sentencepiece'\ + --batch-size 32 \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" diff --git a/fairseq-tools/fairseq/examples/multilingual/train_multilingual_model.sh b/fairseq-tools/fairseq/examples/multilingual/train_multilingual_model.sh new file mode 100644 index 00000000..09014c82 --- /dev/null +++ b/fairseq-tools/fairseq/examples/multilingual/train_multilingual_model.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +path_2_data=$1 # which contains binarized data for each directions +lang_list=$2 # +lang_pairs=$3 #a list language pairs to train multilingual models, e.g. "en-fr,en-cs,fr-en,cs-en" + +fairseq-train "$path_2_data" \ + --encoder-normalize-before --decoder-normalize-before \ + --arch transformer --layernorm-embedding \ + --task translation_multi_simple_epoch \ + --sampling-method "temperature" \ + --sampling-temperature 1.5 \ + --encoder-langtok "src" \ + --decoder-langtok \ + --lang-dict "$lang_list" \ + --lang-pairs "$lang_pairs" \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.2 \ + --optimizer adam --adam-eps 1e-06 --adam-betas '(0.9, 0.98)' \ + --lr-scheduler inverse_sqrt --lr 3e-05 --min-lr -1 --warmup-updates 2500 --max-update 40000 \ + --dropout 0.3 --attention-dropout 0.1 --weight-decay 0.0 \ + --max-tokens 1024 --update-freq 2 \ + --save-interval 1 --save-interval-updates 5000 --keep-interval-updates 10 --no-epoch-checkpoints \ + --seed 222 --log-format simple --log-interval 2 diff --git a/fairseq-tools/fairseq/examples/noisychannel/README.md b/fairseq-tools/fairseq/examples/noisychannel/README.md new file mode 100644 index 00000000..9d101aa8 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/README.md @@ -0,0 +1,72 @@ +# Simple and Effective Noisy Channel Modeling for Neural Machine Translation (Yee et al., 2019) +This page contains pointers to pre-trained models as well as instructions on how to run the reranking scripts. + +## Citation: +```bibtex +@inproceedings{yee2019simple, + title = {Simple and Effective Noisy Channel Modeling for Neural Machine Translation}, + author = {Kyra Yee and Yann Dauphin and Michael Auli}, + booktitle = {Conference on Empirical Methods in Natural Language Processing}, + year = {2019}, +} +``` + +## Pre-trained Models: + +Model | Description | Download +---|---|--- +`transformer.noisychannel.de-en` | De->En Forward Model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/forward_de2en.tar.bz2) +`transformer.noisychannel.en-de` | En->De Channel Model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/backward_en2de.tar.bz2) +`transformer_lm.noisychannel.en` | En Language model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/reranking_en_lm.tar.bz2) + +Test Data: [newstest_wmt17](https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/wmt17test.tar.bz2) + +## Example usage + +``` +mkdir rerank_example +curl https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/forward_de2en.tar.bz2 | tar xvjf - -C rerank_example +curl https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/backward_en2de.tar.bz2 | tar xvjf - -C rerank_example +curl https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/reranking_en_lm.tar.bz2 | tar xvjf - -C rerank_example +curl https://dl.fbaipublicfiles.com/fairseq/models/noisychannel/wmt17test.tar.bz2 | tar xvjf - -C rerank_example + +beam=50 +num_trials=1000 +fw_name=fw_model_ex +bw_name=bw_model_ex +lm_name=lm_ex +data_dir=rerank_example/hyphen-splitting-mixed-case-wmt17test-wmt14bpe +data_dir_name=wmt17 +lm=rerank_example/lm/checkpoint_best.pt +lm_bpe_code=rerank_example/lm/bpe32k.code +lm_dict=rerank_example/lm/dict.txt +batch_size=32 +bw=rerank_example/backward_en2de.pt +fw=rerank_example/forward_de2en.pt + +# reranking with P(T|S) P(S|T) and P(T) +python examples/noisychannel/rerank_tune.py $data_dir --tune-param lenpen weight1 weight3 \ + --lower-bound 0 0 0 --upper-bound 3 3 3 --data-dir-name $data_dir_name \ + --num-trials $num_trials --source-lang de --target-lang en --gen-model $fw \ + -n $beam --batch-size $batch_size --score-model2 $fw --score-model1 $bw \ + --backwards1 --weight2 1 \ + -lm $lm --lm-dict $lm_dict --lm-name en_newscrawl --lm-bpe-code $lm_bpe_code \ + --model2-name $fw_name --model1-name $bw_name --gen-model-name $fw_name + +# reranking with P(T|S) and P(T) +python examples/noisychannel/rerank_tune.py $data_dir --tune-param lenpen weight3 \ + --lower-bound 0 0 --upper-bound 3 3 --data-dir-name $data_dir_name \ + --num-trials $num_trials --source-lang de --target-lang en --gen-model $fw \ + -n $beam --batch-size $batch_size --score-model1 $fw \ + -lm $lm --lm-dict $lm_dict --lm-name en_newscrawl --lm-bpe-code $lm_bpe_code \ + --model1-name $fw_name --gen-model-name $fw_name + +# to run with a preconfigured set of hyperparameters for the lenpen and model weights, using rerank.py instead. +python examples/noisychannel/rerank.py $data_dir \ + --lenpen 0.269 --weight1 1 --weight2 0.929 --weight3 0.831 \ + --data-dir-name $data_dir_name --source-lang de --target-lang en --gen-model $fw \ + -n $beam --batch-size $batch_size --score-model2 $fw --score-model1 $bw --backwards1 \ + -lm $lm --lm-dict $lm_dict --lm-name en_newscrawl --lm-bpe-code $lm_bpe_code \ + --model2-name $fw_name --model1-name $bw_name --gen-model-name $fw_name +``` + diff --git a/fairseq-tools/fairseq/examples/noisychannel/__init__.py b/fairseq-tools/fairseq/examples/noisychannel/__init__.py new file mode 100644 index 00000000..89f1aef4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .rerank_options import * # noqa diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank.py b/fairseq-tools/fairseq/examples/noisychannel/rerank.py new file mode 100644 index 00000000..4df424e6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank.py @@ -0,0 +1,422 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from multiprocessing import Pool + +import numpy as np +from fairseq import options +from fairseq.data import dictionary +from fairseq.scoring import bleu + +from . import ( + rerank_generate, + rerank_options, + rerank_score_bw, + rerank_score_lm, + rerank_utils, +) + + +def score_target_hypo( + args, a, b, c, lenpen, target_outfile, hypo_outfile, write_hypos, normalize +): + + print("lenpen", lenpen, "weight1", a, "weight2", b, "weight3", c) + gen_output_lst, bitext1_lst, bitext2_lst, lm_res_lst = load_score_files(args) + dict = dictionary.Dictionary() + scorer = bleu.Scorer(dict.pad(), dict.eos(), dict.unk()) + + ordered_hypos = {} + ordered_targets = {} + + for shard_id in range(len(bitext1_lst)): + bitext1 = bitext1_lst[shard_id] + bitext2 = bitext2_lst[shard_id] + gen_output = gen_output_lst[shard_id] + lm_res = lm_res_lst[shard_id] + + total = len(bitext1.rescore_source.keys()) + source_lst = [] + hypo_lst = [] + score_lst = [] + reference_lst = [] + j = 1 + best_score = -math.inf + + for i in range(total): + # length is measured in terms of words, not bpe tokens, since models may not share the same bpe + target_len = len(bitext1.rescore_hypo[i].split()) + + if lm_res is not None: + lm_score = lm_res.score[i] + else: + lm_score = 0 + + if bitext2 is not None: + bitext2_score = bitext2.rescore_score[i] + bitext2_backwards = bitext2.backwards + else: + bitext2_score = None + bitext2_backwards = None + + score = rerank_utils.get_score( + a, + b, + c, + target_len, + bitext1.rescore_score[i], + bitext2_score, + lm_score=lm_score, + lenpen=lenpen, + src_len=bitext1.source_lengths[i], + tgt_len=bitext1.target_lengths[i], + bitext1_backwards=bitext1.backwards, + bitext2_backwards=bitext2_backwards, + normalize=normalize, + ) + + if score > best_score: + best_score = score + best_hypo = bitext1.rescore_hypo[i] + + if j == gen_output.num_hypos[i] or j == args.num_rescore: + j = 1 + hypo_lst.append(best_hypo) + score_lst.append(best_score) + source_lst.append(bitext1.rescore_source[i]) + reference_lst.append(bitext1.rescore_target[i]) + + best_score = -math.inf + best_hypo = "" + else: + j += 1 + + gen_keys = list(sorted(gen_output.no_bpe_target.keys())) + + for key in range(len(gen_keys)): + if args.prefix_len is None: + assert hypo_lst[key] in gen_output.no_bpe_hypo[gen_keys[key]], ( + "pred and rescore hypo mismatch: i: " + + str(key) + + ", " + + str(hypo_lst[key]) + + str(gen_keys[key]) + + str(gen_output.no_bpe_hypo[key]) + ) + sys_tok = dict.encode_line(hypo_lst[key]) + ref_tok = dict.encode_line(gen_output.no_bpe_target[gen_keys[key]]) + scorer.add(ref_tok, sys_tok) + + else: + full_hypo = rerank_utils.get_full_from_prefix( + hypo_lst[key], gen_output.no_bpe_hypo[gen_keys[key]] + ) + sys_tok = dict.encode_line(full_hypo) + ref_tok = dict.encode_line(gen_output.no_bpe_target[gen_keys[key]]) + scorer.add(ref_tok, sys_tok) + + # if only one set of hyper parameters is provided, write the predictions to a file + if write_hypos: + # recover the orinal ids from n best list generation + for key in range(len(gen_output.no_bpe_target)): + if args.prefix_len is None: + assert hypo_lst[key] in gen_output.no_bpe_hypo[gen_keys[key]], ( + "pred and rescore hypo mismatch:" + + "i:" + + str(key) + + str(hypo_lst[key]) + + str(gen_output.no_bpe_hypo[key]) + ) + ordered_hypos[gen_keys[key]] = hypo_lst[key] + ordered_targets[gen_keys[key]] = gen_output.no_bpe_target[ + gen_keys[key] + ] + + else: + full_hypo = rerank_utils.get_full_from_prefix( + hypo_lst[key], gen_output.no_bpe_hypo[gen_keys[key]] + ) + ordered_hypos[gen_keys[key]] = full_hypo + ordered_targets[gen_keys[key]] = gen_output.no_bpe_target[ + gen_keys[key] + ] + + # write the hypos in the original order from nbest list generation + if args.num_shards == (len(bitext1_lst)): + with open(target_outfile, "w") as t: + with open(hypo_outfile, "w") as h: + for key in range(len(ordered_hypos)): + t.write(ordered_targets[key]) + h.write(ordered_hypos[key]) + + res = scorer.result_string(4) + if write_hypos: + print(res) + score = rerank_utils.parse_bleu_scoring(res) + return score + + +def match_target_hypo(args, target_outfile, hypo_outfile): + """combine scores from the LM and bitext models, and write the top scoring hypothesis to a file""" + if len(args.weight1) == 1: + res = score_target_hypo( + args, + args.weight1[0], + args.weight2[0], + args.weight3[0], + args.lenpen[0], + target_outfile, + hypo_outfile, + True, + args.normalize, + ) + rerank_scores = [res] + else: + print("launching pool") + with Pool(32) as p: + rerank_scores = p.starmap( + score_target_hypo, + [ + ( + args, + args.weight1[i], + args.weight2[i], + args.weight3[i], + args.lenpen[i], + target_outfile, + hypo_outfile, + False, + args.normalize, + ) + for i in range(len(args.weight1)) + ], + ) + + if len(rerank_scores) > 1: + best_index = np.argmax(rerank_scores) + best_score = rerank_scores[best_index] + print("best score", best_score) + print("best lenpen", args.lenpen[best_index]) + print("best weight1", args.weight1[best_index]) + print("best weight2", args.weight2[best_index]) + print("best weight3", args.weight3[best_index]) + return ( + args.lenpen[best_index], + args.weight1[best_index], + args.weight2[best_index], + args.weight3[best_index], + best_score, + ) + + else: + return ( + args.lenpen[0], + args.weight1[0], + args.weight2[0], + args.weight3[0], + rerank_scores[0], + ) + + +def load_score_files(args): + if args.all_shards: + shard_ids = list(range(args.num_shards)) + else: + shard_ids = [args.shard_id] + + gen_output_lst = [] + bitext1_lst = [] + bitext2_lst = [] + lm_res1_lst = [] + + for shard_id in shard_ids: + using_nbest = args.nbest_list is not None + ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) = rerank_utils.get_directories( + args.data_dir_name, + args.num_rescore, + args.gen_subset, + args.gen_model_name, + shard_id, + args.num_shards, + args.sampling, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + + rerank1_is_gen = ( + args.gen_model == args.score_model1 and args.source_prefix_frac is None + ) + rerank2_is_gen = ( + args.gen_model == args.score_model2 and args.source_prefix_frac is None + ) + + score1_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model1_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards1, + ) + if args.score_model2 is not None: + score2_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model2_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards2, + ) + if args.language_model is not None: + lm_score_file = rerank_utils.rescore_file_name( + pre_gen, args.prefix_len, args.lm_name, lm_file=True + ) + + # get gen output + predictions_bpe_file = pre_gen + "/generate_output_bpe.txt" + if using_nbest: + print("Using predefined n-best list from interactive.py") + predictions_bpe_file = args.nbest_list + gen_output = rerank_utils.BitextOutputFromGen( + predictions_bpe_file, + bpe_symbol=args.remove_bpe, + nbest=using_nbest, + prefix_len=args.prefix_len, + target_prefix_frac=args.target_prefix_frac, + ) + + if rerank1_is_gen: + bitext1 = gen_output + else: + bitext1 = rerank_utils.BitextOutput( + score1_file, + args.backwards1, + args.right_to_left1, + args.remove_bpe, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + + if args.score_model2 is not None or args.nbest_list is not None: + if rerank2_is_gen: + bitext2 = gen_output + else: + bitext2 = rerank_utils.BitextOutput( + score2_file, + args.backwards2, + args.right_to_left2, + args.remove_bpe, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + + assert ( + bitext2.source_lengths == bitext1.source_lengths + ), "source lengths for rescoring models do not match" + assert ( + bitext2.target_lengths == bitext1.target_lengths + ), "target lengths for rescoring models do not match" + else: + if args.diff_bpe: + assert args.score_model2 is None + bitext2 = gen_output + else: + bitext2 = None + + if args.language_model is not None: + lm_res1 = rerank_utils.LMOutput( + lm_score_file, + args.lm_dict, + args.prefix_len, + args.remove_bpe, + args.target_prefix_frac, + ) + else: + lm_res1 = None + + gen_output_lst.append(gen_output) + bitext1_lst.append(bitext1) + bitext2_lst.append(bitext2) + lm_res1_lst.append(lm_res1) + return gen_output_lst, bitext1_lst, bitext2_lst, lm_res1_lst + + +def rerank(args): + if type(args.lenpen) is not list: + args.lenpen = [args.lenpen] + if type(args.weight1) is not list: + args.weight1 = [args.weight1] + if type(args.weight2) is not list: + args.weight2 = [args.weight2] + if type(args.weight3) is not list: + args.weight3 = [args.weight3] + if args.all_shards: + shard_ids = list(range(args.num_shards)) + else: + shard_ids = [args.shard_id] + + for shard_id in shard_ids: + ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) = rerank_utils.get_directories( + args.data_dir_name, + args.num_rescore, + args.gen_subset, + args.gen_model_name, + shard_id, + args.num_shards, + args.sampling, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + rerank_generate.gen_and_reprocess_nbest(args) + rerank_score_bw.score_bw(args) + rerank_score_lm.score_lm(args) + + if args.write_hypos is None: + write_targets = pre_gen + "/matched_targets" + write_hypos = pre_gen + "/matched_hypos" + else: + write_targets = args.write_hypos + "_targets" + args.gen_subset + write_hypos = args.write_hypos + "_hypos" + args.gen_subset + + if args.all_shards: + write_targets += "_all_shards" + write_hypos += "_all_shards" + + ( + best_lenpen, + best_weight1, + best_weight2, + best_weight3, + best_score, + ) = match_target_hypo(args, write_targets, write_hypos) + + return best_lenpen, best_weight1, best_weight2, best_weight3, best_score + + +def cli_main(): + parser = rerank_options.get_reranking_parser() + args = options.parse_args_and_arch(parser) + rerank(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_generate.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_generate.py new file mode 100644 index 00000000..4356b338 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_generate.py @@ -0,0 +1,397 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Generate n-best translations using a trained model. +""" + +import os +import subprocess +from contextlib import redirect_stdout + +from fairseq import options +from fairseq_cli import generate, preprocess + +from . import rerank_options, rerank_utils + + +def gen_and_reprocess_nbest(args): + if args.score_dict_dir is None: + args.score_dict_dir = args.data + if args.prefix_len is not None: + assert ( + args.right_to_left1 is False + ), "prefix length not compatible with right to left models" + assert ( + args.right_to_left2 is False + ), "prefix length not compatible with right to left models" + + if args.nbest_list is not None: + assert args.score_model2 is None + + if args.backwards1: + scorer1_src = args.target_lang + scorer1_tgt = args.source_lang + else: + scorer1_src = args.source_lang + scorer1_tgt = args.target_lang + + store_data = ( + os.path.join(os.path.dirname(__file__)) + "/rerank_data/" + args.data_dir_name + ) + if not os.path.exists(store_data): + os.makedirs(store_data) + + ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) = rerank_utils.get_directories( + args.data_dir_name, + args.num_rescore, + args.gen_subset, + args.gen_model_name, + args.shard_id, + args.num_shards, + args.sampling, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + assert not ( + args.right_to_left1 and args.backwards1 + ), "backwards right to left not supported" + assert not ( + args.right_to_left2 and args.backwards2 + ), "backwards right to left not supported" + assert not ( + args.prefix_len is not None and args.target_prefix_frac is not None + ), "target prefix frac and target prefix len incompatible" + + # make directory to store generation results + if not os.path.exists(pre_gen): + os.makedirs(pre_gen) + + rerank1_is_gen = ( + args.gen_model == args.score_model1 and args.source_prefix_frac is None + ) + rerank2_is_gen = ( + args.gen_model == args.score_model2 and args.source_prefix_frac is None + ) + + if args.nbest_list is not None: + rerank2_is_gen = True + + # make directories to store preprossed nbest list for reranking + if not os.path.exists(left_to_right_preprocessed_dir): + os.makedirs(left_to_right_preprocessed_dir) + if not os.path.exists(right_to_left_preprocessed_dir): + os.makedirs(right_to_left_preprocessed_dir) + if not os.path.exists(lm_preprocessed_dir): + os.makedirs(lm_preprocessed_dir) + if not os.path.exists(backwards_preprocessed_dir): + os.makedirs(backwards_preprocessed_dir) + + score1_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model1_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards1, + ) + if args.score_model2 is not None: + score2_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model2_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards2, + ) + + predictions_bpe_file = pre_gen + "/generate_output_bpe.txt" + + using_nbest = args.nbest_list is not None + + if using_nbest: + print("Using predefined n-best list from interactive.py") + predictions_bpe_file = args.nbest_list + + else: + if not os.path.isfile(predictions_bpe_file): + print("STEP 1: generate predictions using the p(T|S) model with bpe") + print(args.data) + param1 = [ + args.data, + "--path", + args.gen_model, + "--shard-id", + str(args.shard_id), + "--num-shards", + str(args.num_shards), + "--nbest", + str(args.num_rescore), + "--batch-size", + str(args.batch_size), + "--beam", + str(args.num_rescore), + "--batch-size", + str(args.num_rescore), + "--gen-subset", + args.gen_subset, + "--source-lang", + args.source_lang, + "--target-lang", + args.target_lang, + ] + if args.sampling: + param1 += ["--sampling"] + + gen_parser = options.get_generation_parser() + input_args = options.parse_args_and_arch(gen_parser, param1) + + print(input_args) + with open(predictions_bpe_file, "w") as f: + with redirect_stdout(f): + generate.main(input_args) + + gen_output = rerank_utils.BitextOutputFromGen( + predictions_bpe_file, + bpe_symbol=args.remove_bpe, + nbest=using_nbest, + prefix_len=args.prefix_len, + target_prefix_frac=args.target_prefix_frac, + ) + + if args.diff_bpe: + rerank_utils.write_reprocessed( + gen_output.no_bpe_source, + gen_output.no_bpe_hypo, + gen_output.no_bpe_target, + pre_gen + "/source_gen_bpe." + args.source_lang, + pre_gen + "/target_gen_bpe." + args.target_lang, + pre_gen + "/reference_gen_bpe." + args.target_lang, + ) + bitext_bpe = args.rescore_bpe_code + bpe_src_param = [ + "-c", + bitext_bpe, + "--input", + pre_gen + "/source_gen_bpe." + args.source_lang, + "--output", + pre_gen + "/rescore_data." + args.source_lang, + ] + bpe_tgt_param = [ + "-c", + bitext_bpe, + "--input", + pre_gen + "/target_gen_bpe." + args.target_lang, + "--output", + pre_gen + "/rescore_data." + args.target_lang, + ] + + subprocess.call( + [ + "python", + os.path.join( + os.path.dirname(__file__), "subword-nmt/subword_nmt/apply_bpe.py" + ), + ] + + bpe_src_param, + shell=False, + ) + + subprocess.call( + [ + "python", + os.path.join( + os.path.dirname(__file__), "subword-nmt/subword_nmt/apply_bpe.py" + ), + ] + + bpe_tgt_param, + shell=False, + ) + + if (not os.path.isfile(score1_file) and not rerank1_is_gen) or ( + args.score_model2 is not None + and not os.path.isfile(score2_file) + and not rerank2_is_gen + ): + print( + "STEP 2: process the output of generate.py so we have clean text files with the translations" + ) + + rescore_file = "/rescore_data" + if args.prefix_len is not None: + prefix_len_rescore_file = rescore_file + "prefix" + str(args.prefix_len) + if args.target_prefix_frac is not None: + target_prefix_frac_rescore_file = ( + rescore_file + "target_prefix_frac" + str(args.target_prefix_frac) + ) + if args.source_prefix_frac is not None: + source_prefix_frac_rescore_file = ( + rescore_file + "source_prefix_frac" + str(args.source_prefix_frac) + ) + + if not args.right_to_left1 or not args.right_to_left2: + if not args.diff_bpe: + rerank_utils.write_reprocessed( + gen_output.source, + gen_output.hypo, + gen_output.target, + pre_gen + rescore_file + "." + args.source_lang, + pre_gen + rescore_file + "." + args.target_lang, + pre_gen + "/reference_file", + bpe_symbol=args.remove_bpe, + ) + if args.prefix_len is not None: + bw_rescore_file = prefix_len_rescore_file + rerank_utils.write_reprocessed( + gen_output.source, + gen_output.hypo, + gen_output.target, + pre_gen + prefix_len_rescore_file + "." + args.source_lang, + pre_gen + prefix_len_rescore_file + "." + args.target_lang, + pre_gen + "/reference_file", + prefix_len=args.prefix_len, + bpe_symbol=args.remove_bpe, + ) + elif args.target_prefix_frac is not None: + bw_rescore_file = target_prefix_frac_rescore_file + rerank_utils.write_reprocessed( + gen_output.source, + gen_output.hypo, + gen_output.target, + pre_gen + + target_prefix_frac_rescore_file + + "." + + args.source_lang, + pre_gen + + target_prefix_frac_rescore_file + + "." + + args.target_lang, + pre_gen + "/reference_file", + bpe_symbol=args.remove_bpe, + target_prefix_frac=args.target_prefix_frac, + ) + else: + bw_rescore_file = rescore_file + + if args.source_prefix_frac is not None: + fw_rescore_file = source_prefix_frac_rescore_file + rerank_utils.write_reprocessed( + gen_output.source, + gen_output.hypo, + gen_output.target, + pre_gen + + source_prefix_frac_rescore_file + + "." + + args.source_lang, + pre_gen + + source_prefix_frac_rescore_file + + "." + + args.target_lang, + pre_gen + "/reference_file", + bpe_symbol=args.remove_bpe, + source_prefix_frac=args.source_prefix_frac, + ) + else: + fw_rescore_file = rescore_file + + if args.right_to_left1 or args.right_to_left2: + rerank_utils.write_reprocessed( + gen_output.source, + gen_output.hypo, + gen_output.target, + pre_gen + "/right_to_left_rescore_data." + args.source_lang, + pre_gen + "/right_to_left_rescore_data." + args.target_lang, + pre_gen + "/right_to_left_reference_file", + right_to_left=True, + bpe_symbol=args.remove_bpe, + ) + + print("STEP 3: binarize the translations") + if ( + not args.right_to_left1 + or args.score_model2 is not None + and not args.right_to_left2 + or not rerank1_is_gen + ): + + if args.backwards1 or args.backwards2: + if args.backwards_score_dict_dir is not None: + bw_dict = args.backwards_score_dict_dir + else: + bw_dict = args.score_dict_dir + bw_preprocess_param = [ + "--source-lang", + scorer1_src, + "--target-lang", + scorer1_tgt, + "--trainpref", + pre_gen + bw_rescore_file, + "--srcdict", + bw_dict + "/dict." + scorer1_src + ".txt", + "--tgtdict", + bw_dict + "/dict." + scorer1_tgt + ".txt", + "--destdir", + backwards_preprocessed_dir, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(bw_preprocess_param) + preprocess.main(input_args) + + preprocess_param = [ + "--source-lang", + scorer1_src, + "--target-lang", + scorer1_tgt, + "--trainpref", + pre_gen + fw_rescore_file, + "--srcdict", + args.score_dict_dir + "/dict." + scorer1_src + ".txt", + "--tgtdict", + args.score_dict_dir + "/dict." + scorer1_tgt + ".txt", + "--destdir", + left_to_right_preprocessed_dir, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(preprocess_param) + preprocess.main(input_args) + + if args.right_to_left1 or args.right_to_left2: + preprocess_param = [ + "--source-lang", + scorer1_src, + "--target-lang", + scorer1_tgt, + "--trainpref", + pre_gen + "/right_to_left_rescore_data", + "--srcdict", + args.score_dict_dir + "/dict." + scorer1_src + ".txt", + "--tgtdict", + args.score_dict_dir + "/dict." + scorer1_tgt + ".txt", + "--destdir", + right_to_left_preprocessed_dir, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(preprocess_param) + preprocess.main(input_args) + + return gen_output + + +def cli_main(): + parser = rerank_options.get_reranking_parser() + args = options.parse_args_and_arch(parser) + gen_and_reprocess_nbest(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_options.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_options.py new file mode 100644 index 00000000..ca7a2e0a --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_options.py @@ -0,0 +1,149 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import options + + +def get_reranking_parser(default_task="translation"): + parser = options.get_parser("Generation and reranking", default_task) + add_reranking_args(parser) + return parser + + +def get_tuning_parser(default_task="translation"): + parser = options.get_parser("Reranking tuning", default_task) + add_reranking_args(parser) + add_tuning_args(parser) + return parser + + +def add_reranking_args(parser): + group = parser.add_argument_group("Reranking") + # fmt: off + group.add_argument('--score-model1', '-s1', type=str, metavar='FILE', required=True, + help='path to first model or ensemble of models for rescoring') + group.add_argument('--score-model2', '-s2', type=str, metavar='FILE', required=False, + help='path to second model or ensemble of models for rescoring') + group.add_argument('--num-rescore', '-n', type=int, metavar='N', default=10, + help='the number of candidate hypothesis to rescore') + group.add_argument('-bz', '--batch-size', type=int, metavar='N', default=128, + help='batch size for generating the nbest list') + group.add_argument('--gen-subset', default='test', metavar='SET', choices=['test', 'train', 'valid'], + help='data subset to generate (train, valid, test)') + group.add_argument('--gen-model', default=None, metavar='FILE', + help='the model to generate translations') + group.add_argument('-b1', '--backwards1', action='store_true', + help='whether or not the first model group is backwards') + group.add_argument('-b2', '--backwards2', action='store_true', + help='whether or not the second model group is backwards') + group.add_argument('-a', '--weight1', default=1, nargs='+', type=float, + help='the weight(s) of the first model') + group.add_argument('-b', '--weight2', default=1, nargs='+', type=float, + help='the weight(s) of the second model, or the gen model if using nbest from interactive.py') + group.add_argument('-c', '--weight3', default=1, nargs='+', type=float, + help='the weight(s) of the third model') + + # lm arguments + group.add_argument('-lm', '--language-model', default=None, metavar='FILE', + help='language model for target language to rescore translations') + group.add_argument('--lm-dict', default=None, metavar='FILE', + help='the dict of the language model for the target language') + group.add_argument('--lm-name', default=None, + help='the name of the language model for the target language') + group.add_argument('--lm-bpe-code', default=None, metavar='FILE', + help='the bpe code for the language model for the target language') + group.add_argument('--data-dir-name', default=None, + help='name of data directory') + group.add_argument('--lenpen', default=1, nargs='+', type=float, + help='length penalty: <1.0 favors shorter, >1.0 favors longer sentences') + group.add_argument('--score-dict-dir', default=None, + help='the directory with dictionaries for the scoring models') + group.add_argument('--right-to-left1', action='store_true', + help='whether the first model group is a right to left model') + group.add_argument('--right-to-left2', action='store_true', + help='whether the second model group is a right to left model') + group.add_argument('--remove-bpe', '--post-process', default='@@ ', + help='the bpe symbol, used for the bitext and LM') + group.add_argument('--prefix-len', default=None, type=int, + help='the length of the target prefix to use in rescoring (in terms of words wo bpe)') + group.add_argument('--sampling', action='store_true', + help='use sampling instead of beam search for generating n best list') + group.add_argument('--diff-bpe', action='store_true', + help='bpe for rescoring and nbest list not the same') + group.add_argument('--rescore-bpe-code', default=None, + help='bpe code for rescoring models') + group.add_argument('--nbest-list', default=None, + help='use predefined nbest list in interactive.py format') + group.add_argument('--write-hypos', default=None, + help='filename prefix to write hypos to') + group.add_argument('--ref-translation', default=None, + help='reference translation to use with nbest list from interactive.py') + group.add_argument('--backwards-score-dict-dir', default=None, + help='the directory with dictionaries for the backwards model,' + 'if None then it is assumed the fw and backwards models share dictionaries') + + # extra scaling args + group.add_argument('--gen-model-name', default=None, + help='the name of the models that generated the nbest list') + group.add_argument('--model1-name', default=None, + help='the name of the set for model1 group ') + group.add_argument('--model2-name', default=None, + help='the name of the set for model2 group') + group.add_argument('--shard-id', default=0, type=int, + help='the id of the shard to generate') + group.add_argument('--num-shards', default=1, type=int, + help='the number of shards to generate across') + group.add_argument('--all-shards', action='store_true', + help='use all shards') + group.add_argument('--target-prefix-frac', default=None, type=float, + help='the fraction of the target prefix to use in rescoring (in terms of words wo bpe)') + group.add_argument('--source-prefix-frac', default=None, type=float, + help='the fraction of the source prefix to use in rescoring (in terms of words wo bpe)') + group.add_argument('--normalize', action='store_true', + help='whether to normalize by src and target len') + # fmt: on + return group + + +def add_tuning_args(parser): + group = parser.add_argument_group("Tuning") + + group.add_argument( + "--lower-bound", + default=[-0.7], + nargs="+", + type=float, + help="lower bound of search space", + ) + group.add_argument( + "--upper-bound", + default=[3], + nargs="+", + type=float, + help="upper bound of search space", + ) + group.add_argument( + "--tune-param", + default=["lenpen"], + nargs="+", + choices=["lenpen", "weight1", "weight2", "weight3"], + help="the parameter(s) to tune", + ) + group.add_argument( + "--tune-subset", + default="valid", + choices=["valid", "test", "train"], + help="the subset to tune on ", + ) + group.add_argument( + "--num-trials", + default=1000, + type=int, + help="number of trials to do for random search", + ) + group.add_argument( + "--share-weights", action="store_true", help="share weight2 and weight 3" + ) + return group diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_score_bw.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_score_bw.py new file mode 100644 index 00000000..895673b1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_score_bw.py @@ -0,0 +1,143 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +from contextlib import redirect_stdout + +from fairseq import options +from fairseq_cli import generate + +from . import rerank_options, rerank_utils + + +def score_bw(args): + if args.backwards1: + scorer1_src = args.target_lang + scorer1_tgt = args.source_lang + else: + scorer1_src = args.source_lang + scorer1_tgt = args.target_lang + + if args.score_model2 is not None: + if args.backwards2: + scorer2_src = args.target_lang + scorer2_tgt = args.source_lang + else: + scorer2_src = args.source_lang + scorer2_tgt = args.target_lang + + rerank1_is_gen = ( + args.gen_model == args.score_model1 and args.source_prefix_frac is None + ) + rerank2_is_gen = ( + args.gen_model == args.score_model2 and args.source_prefix_frac is None + ) + + ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) = rerank_utils.get_directories( + args.data_dir_name, + args.num_rescore, + args.gen_subset, + args.gen_model_name, + args.shard_id, + args.num_shards, + args.sampling, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + + score1_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model1_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards1, + ) + + if args.score_model2 is not None: + score2_file = rerank_utils.rescore_file_name( + pre_gen, + args.prefix_len, + args.model2_name, + target_prefix_frac=args.target_prefix_frac, + source_prefix_frac=args.source_prefix_frac, + backwards=args.backwards2, + ) + + if args.right_to_left1: + rerank_data1 = right_to_left_preprocessed_dir + elif args.backwards1: + rerank_data1 = backwards_preprocessed_dir + else: + rerank_data1 = left_to_right_preprocessed_dir + + gen_param = ["--batch-size", str(128), "--score-reference", "--gen-subset", "train"] + if not rerank1_is_gen and not os.path.isfile(score1_file): + print("STEP 4: score the translations for model 1") + + model_param1 = [ + "--path", + args.score_model1, + "--source-lang", + scorer1_src, + "--target-lang", + scorer1_tgt, + ] + gen_model1_param = [rerank_data1] + gen_param + model_param1 + + gen_parser = options.get_generation_parser() + input_args = options.parse_args_and_arch(gen_parser, gen_model1_param) + + with open(score1_file, "w") as f: + with redirect_stdout(f): + generate.main(input_args) + + if ( + args.score_model2 is not None + and not os.path.isfile(score2_file) + and not rerank2_is_gen + ): + print("STEP 4: score the translations for model 2") + + if args.right_to_left2: + rerank_data2 = right_to_left_preprocessed_dir + elif args.backwards2: + rerank_data2 = backwards_preprocessed_dir + else: + rerank_data2 = left_to_right_preprocessed_dir + + model_param2 = [ + "--path", + args.score_model2, + "--source-lang", + scorer2_src, + "--target-lang", + scorer2_tgt, + ] + gen_model2_param = [rerank_data2] + gen_param + model_param2 + + gen_parser = options.get_generation_parser() + input_args = options.parse_args_and_arch(gen_parser, gen_model2_param) + + with open(score2_file, "w") as f: + with redirect_stdout(f): + generate.main(input_args) + + +def cli_main(): + parser = rerank_options.get_reranking_parser() + args = options.parse_args_and_arch(parser) + score_bw(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_score_lm.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_score_lm.py new file mode 100644 index 00000000..fa3aa644 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_score_lm.py @@ -0,0 +1,81 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os + +from fairseq import options + +from . import rerank_options, rerank_utils + + +def score_lm(args): + using_nbest = args.nbest_list is not None + ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) = rerank_utils.get_directories( + args.data_dir_name, + args.num_rescore, + args.gen_subset, + args.gen_model_name, + args.shard_id, + args.num_shards, + args.sampling, + args.prefix_len, + args.target_prefix_frac, + args.source_prefix_frac, + ) + + predictions_bpe_file = pre_gen + "/generate_output_bpe.txt" + if using_nbest: + print("Using predefined n-best list from interactive.py") + predictions_bpe_file = args.nbest_list + + gen_output = rerank_utils.BitextOutputFromGen( + predictions_bpe_file, bpe_symbol=args.remove_bpe, nbest=using_nbest + ) + + if args.language_model is not None: + lm_score_file = rerank_utils.rescore_file_name( + pre_gen, args.prefix_len, args.lm_name, lm_file=True + ) + + if args.language_model is not None and not os.path.isfile(lm_score_file): + print("STEP 4.5: language modeling for P(T)") + if args.lm_bpe_code is None: + bpe_status = "no bpe" + elif args.lm_bpe_code == "shared": + bpe_status = "shared" + else: + bpe_status = "different" + + rerank_utils.lm_scoring( + lm_preprocessed_dir, + bpe_status, + gen_output, + pre_gen, + args.lm_dict, + args.lm_name, + args.language_model, + args.lm_bpe_code, + 128, + lm_score_file, + args.target_lang, + args.source_lang, + prefix_len=args.prefix_len, + ) + + +def cli_main(): + parser = rerank_options.get_reranking_parser() + args = options.parse_args_and_arch(parser) + score_lm(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_tune.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_tune.py new file mode 100644 index 00000000..1be71744 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_tune.py @@ -0,0 +1,102 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import random + +import numpy as np +from fairseq import options + +from . import rerank, rerank_options + + +def random_search(args): + param_values = [] + tuneable_parameters = ["lenpen", "weight1", "weight2", "weight3"] + initial_params = [args.lenpen, args.weight1, args.weight2, args.weight3] + for i, elem in enumerate(initial_params): + if type(elem) is not list: + initial_params[i] = [elem] + else: + initial_params[i] = elem + + tune_parameters = args.tune_param.copy() + for i in range(len(args.tune_param)): + assert args.upper_bound[i] >= args.lower_bound[i] + index = tuneable_parameters.index(args.tune_param[i]) + del tuneable_parameters[index] + del initial_params[index] + + tune_parameters += tuneable_parameters + param_values += initial_params + random.seed(args.seed) + + random_params = np.array( + [ + [ + random.uniform(args.lower_bound[i], args.upper_bound[i]) + for i in range(len(args.tune_param)) + ] + for k in range(args.num_trials) + ] + ) + set_params = np.array( + [ + [initial_params[i][0] for i in range(len(tuneable_parameters))] + for k in range(args.num_trials) + ] + ) + random_params = np.concatenate((random_params, set_params), 1) + + rerank_args = vars(args).copy() + if args.nbest_list: + rerank_args["gen_subset"] = "test" + else: + rerank_args["gen_subset"] = args.tune_subset + + for k in range(len(tune_parameters)): + rerank_args[tune_parameters[k]] = list(random_params[:, k]) + + if args.share_weights: + k = tune_parameters.index("weight2") + rerank_args["weight3"] = list(random_params[:, k]) + + rerank_args = argparse.Namespace(**rerank_args) + best_lenpen, best_weight1, best_weight2, best_weight3, best_score = rerank.rerank( + rerank_args + ) + rerank_args = vars(args).copy() + rerank_args["lenpen"] = [best_lenpen] + rerank_args["weight1"] = [best_weight1] + rerank_args["weight2"] = [best_weight2] + rerank_args["weight3"] = [best_weight3] + + # write the hypothesis from the valid set from the best trial + + if args.gen_subset != "valid": + rerank_args["gen_subset"] = "valid" + rerank_args = argparse.Namespace(**rerank_args) + rerank.rerank(rerank_args) + + # test with the best hyperparameters on gen subset + rerank_args = vars(args).copy() + rerank_args["gen_subset"] = args.gen_subset + rerank_args["lenpen"] = [best_lenpen] + rerank_args["weight1"] = [best_weight1] + rerank_args["weight2"] = [best_weight2] + rerank_args["weight3"] = [best_weight3] + rerank_args = argparse.Namespace(**rerank_args) + rerank.rerank(rerank_args) + + +def cli_main(): + parser = rerank_options.get_tuning_parser() + args = options.parse_args_and_arch(parser) + + random_search(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/noisychannel/rerank_utils.py b/fairseq-tools/fairseq/examples/noisychannel/rerank_utils.py new file mode 100644 index 00000000..2c6bf1b1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/noisychannel/rerank_utils.py @@ -0,0 +1,850 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +import os +import re +import subprocess +from contextlib import redirect_stdout + +from fairseq import options +from fairseq_cli import eval_lm, preprocess + + +def reprocess(fle): + # takes in a file of generate.py translation generate_output + # returns a source dict and hypothesis dict, where keys are the ID num (as a string) + # and values and the corresponding source and translation. There may be several translations + # per source, so the values for hypothesis_dict are lists. + # parses output of generate.py + + with open(fle, "r") as f: + txt = f.read() + + """reprocess generate.py output""" + p = re.compile(r"[STHP][-]\d+\s*") + hp = re.compile(r"(\s*[-]?\d+[.]?\d+\s*)|(\s*(-inf)\s*)") + source_dict = {} + hypothesis_dict = {} + score_dict = {} + target_dict = {} + pos_score_dict = {} + lines = txt.split("\n") + + for line in lines: + line += "\n" + prefix = re.search(p, line) + if prefix is not None: + assert len(prefix.group()) > 2, "prefix id not found" + _, j = prefix.span() + id_num = prefix.group()[2:] + id_num = int(id_num) + line_type = prefix.group()[0] + if line_type == "H": + h_txt = line[j:] + hypo = re.search(hp, h_txt) + assert ( + hypo is not None + ), "regular expression failed to find the hypothesis scoring" + _, i = hypo.span() + score = hypo.group() + if id_num in hypothesis_dict: + hypothesis_dict[id_num].append(h_txt[i:]) + score_dict[id_num].append(float(score)) + else: + hypothesis_dict[id_num] = [h_txt[i:]] + score_dict[id_num] = [float(score)] + + elif line_type == "S": + source_dict[id_num] = line[j:] + elif line_type == "T": + target_dict[id_num] = line[j:] + elif line_type == "P": + pos_scores = (line[j:]).split() + pos_scores = [float(x) for x in pos_scores] + if id_num in pos_score_dict: + pos_score_dict[id_num].append(pos_scores) + else: + pos_score_dict[id_num] = [pos_scores] + + return source_dict, hypothesis_dict, score_dict, target_dict, pos_score_dict + + +def reprocess_nbest(fle): + """reprocess interactive.py output""" + with open(fle, "r") as f: + txt = f.read() + + source_dict = {} + hypothesis_dict = {} + score_dict = {} + target_dict = {} + pos_score_dict = {} + lines = txt.split("\n") + + hp = re.compile(r"[-]?\d+[.]?\d+") + j = -1 + + for _i, line in enumerate(lines): + line += "\n" + line_type = line[0] + + if line_type == "H": + hypo = re.search(hp, line) + _, start_index = hypo.span() + score = hypo.group() + if j in score_dict: + score_dict[j].append(float(score)) + hypothesis_dict[j].append(line[start_index:].strip("\t")) + else: + score_dict[j] = [float(score)] + hypothesis_dict[j] = [line[start_index:].strip("\t")] + elif line_type == "O": + j += 1 + source_dict[j] = line[2:] + # we don't have the targets for interactive.py + target_dict[j] = "filler" + + elif line_type == "P": + pos_scores = [float(pos_score) for pos_score in line.split()[1:]] + if j in pos_score_dict: + pos_score_dict[j].append(pos_scores) + else: + pos_score_dict[j] = [pos_scores] + + assert source_dict.keys() == hypothesis_dict.keys() + assert source_dict.keys() == pos_score_dict.keys() + assert source_dict.keys() == score_dict.keys() + + return source_dict, hypothesis_dict, score_dict, target_dict, pos_score_dict + + +def write_reprocessed( + sources, + hypos, + targets, + source_outfile, + hypo_outfile, + target_outfile, + right_to_left=False, + prefix_len=None, + bpe_symbol=None, + target_prefix_frac=None, + source_prefix_frac=None, +): + + """writes nbest hypothesis for rescoring""" + assert not ( + prefix_len is not None and target_prefix_frac is not None + ), "in writing reprocessed, only one type of prefix may be used" + assert not ( + prefix_len is not None and source_prefix_frac is not None + ), "in writing reprocessed, only one type of prefix may be used" + assert not ( + target_prefix_frac is not None and source_prefix_frac is not None + ), "in writing reprocessed, only one type of prefix may be used" + + with open(source_outfile, "w") as source_file, open( + hypo_outfile, "w" + ) as hypo_file, open(target_outfile, "w") as target_file: + + assert len(sources) == len(hypos), "sources and hypos list length mismatch" + if right_to_left: + for i in range(len(sources)): + for j in range(len(hypos[i])): + if prefix_len is None: + hypo_file.write(make_right_to_left(hypos[i][j]) + "\n") + else: + raise NotImplementedError() + source_file.write(make_right_to_left(sources[i]) + "\n") + target_file.write(make_right_to_left(targets[i]) + "\n") + else: + for i in sorted(sources.keys()): + for j in range(len(hypos[i])): + if prefix_len is not None: + shortened = ( + get_prefix_no_bpe(hypos[i][j], bpe_symbol, prefix_len) + + "\n" + ) + hypo_file.write(shortened) + source_file.write(sources[i]) + target_file.write(targets[i]) + elif target_prefix_frac is not None: + num_words, shortened, num_bpe_tokens = calc_length_from_frac( + hypos[i][j], target_prefix_frac, bpe_symbol + ) + shortened += "\n" + hypo_file.write(shortened) + source_file.write(sources[i]) + target_file.write(targets[i]) + elif source_prefix_frac is not None: + num_words, shortened, num_bpe_tokensn = calc_length_from_frac( + sources[i], source_prefix_frac, bpe_symbol + ) + shortened += "\n" + hypo_file.write(hypos[i][j]) + source_file.write(shortened) + target_file.write(targets[i]) + else: + hypo_file.write(hypos[i][j]) + source_file.write(sources[i]) + target_file.write(targets[i]) + + +def calc_length_from_frac(bpe_sentence, prefix_frac, bpe_symbol): + # return number of words, (not bpe tokens) that we want + no_bpe_sen = remove_bpe(bpe_sentence, bpe_symbol) + len_sen = len(no_bpe_sen.split()) + + num_words = math.ceil(len_sen * prefix_frac) + prefix = get_prefix_no_bpe(bpe_sentence, bpe_symbol, num_words) + num_bpe_tokens = len(prefix.split()) + return num_words, prefix, num_bpe_tokens + + +def get_prefix(sentence, prefix_len): + """assuming no bpe, gets the prefix of the sentence with prefix_len words""" + tokens = sentence.strip("\n").split() + if prefix_len >= len(tokens): + return sentence.strip("\n") + else: + return " ".join(tokens[:prefix_len]) + + +def get_prefix_no_bpe(sentence, bpe_symbol, prefix_len): + if bpe_symbol is None: + return get_prefix(sentence, prefix_len) + else: + return " ".join(get_prefix_from_len(sentence.split(), bpe_symbol, prefix_len)) + + +def get_prefix_from_len(sentence, bpe_symbol, prefix_len): + """get the prefix of sentence with bpe, with prefix len in terms of words, not bpe tokens""" + bpe_count = sum([bpe_symbol.strip(" ") in t for t in sentence[:prefix_len]]) + if bpe_count == 0: + return sentence[:prefix_len] + else: + return sentence[:prefix_len] + get_prefix_from_len( + sentence[prefix_len:], bpe_symbol, bpe_count + ) + + +def get_num_bpe_tokens_from_len(sentence, bpe_symbol, prefix_len): + """given a prefix length in terms of words, return the number of bpe tokens""" + prefix = get_prefix_no_bpe(sentence, bpe_symbol, prefix_len) + assert len(remove_bpe(prefix, bpe_symbol).split()) <= prefix_len + return len(prefix.split(" ")) + + +def make_right_to_left(line): + tokens = line.split() + tokens.reverse() + new_line = " ".join(tokens) + return new_line + + +def remove_bpe(line, bpe_symbol): + line = line.replace("\n", "") + line = (line + " ").replace(bpe_symbol, "").rstrip() + return line + ("\n") + + +def remove_bpe_dict(pred_dict, bpe_symbol): + new_dict = {} + for i in pred_dict: + if type(pred_dict[i]) == list: + new_list = [remove_bpe(elem, bpe_symbol) for elem in pred_dict[i]] + new_dict[i] = new_list + else: + new_dict[i] = remove_bpe(pred_dict[i], bpe_symbol) + return new_dict + + +def parse_bleu_scoring(line): + p = re.compile(r"(BLEU4 = )\d+[.]\d+") + res = re.search(p, line) + assert res is not None, line + return float(res.group()[8:]) + + +def get_full_from_prefix(hypo_prefix, hypos): + """given a hypo prefix, recover the first hypo from the list of complete hypos beginning with that prefix""" + for hypo in hypos: + hypo_prefix = hypo_prefix.strip("\n") + len_prefix = len(hypo_prefix) + if hypo[:len_prefix] == hypo_prefix: + return hypo + # no match found + raise Exception() + + +def get_score( + a, + b, + c, + target_len, + bitext_score1, + bitext_score2=None, + lm_score=None, + lenpen=None, + src_len=None, + tgt_len=None, + bitext1_backwards=False, + bitext2_backwards=False, + normalize=False, +): + if bitext1_backwards: + bitext1_norm = src_len + else: + bitext1_norm = tgt_len + if bitext_score2 is not None: + if bitext2_backwards: + bitext2_norm = src_len + else: + bitext2_norm = tgt_len + else: + bitext2_norm = 1 + bitext_score2 = 0 + if normalize: + score = ( + a * bitext_score1 / bitext1_norm + + b * bitext_score2 / bitext2_norm + + c * lm_score / src_len + ) + else: + score = a * bitext_score1 + b * bitext_score2 + c * lm_score + + if lenpen is not None: + score /= (target_len) ** float(lenpen) + + return score + + +class BitextOutput(object): + def __init__( + self, + output_file, + backwards, + right_to_left, + bpe_symbol, + prefix_len=None, + target_prefix_frac=None, + source_prefix_frac=None, + ): + """process output from rescoring""" + source, hypo, score, target, pos_score = reprocess(output_file) + if backwards: + self.hypo_fracs = source_prefix_frac + else: + self.hypo_fracs = target_prefix_frac + + # remove length penalty so we can use raw scores + score, num_bpe_tokens = get_score_from_pos( + pos_score, prefix_len, hypo, bpe_symbol, self.hypo_fracs, backwards + ) + source_lengths = {} + target_lengths = {} + + assert hypo.keys() == source.keys(), "key mismatch" + if backwards: + tmp = hypo + hypo = source + source = tmp + for i in source: + # since we are reranking, there should only be one hypo per source sentence + if backwards: + len_src = len(source[i][0].split()) + # record length without + if len_src == num_bpe_tokens[i][0] - 1: + source_lengths[i] = num_bpe_tokens[i][0] - 1 + else: + source_lengths[i] = num_bpe_tokens[i][0] + + target_lengths[i] = len(hypo[i].split()) + + source[i] = remove_bpe(source[i][0], bpe_symbol) + target[i] = remove_bpe(target[i], bpe_symbol) + hypo[i] = remove_bpe(hypo[i], bpe_symbol) + + score[i] = float(score[i][0]) + pos_score[i] = pos_score[i][0] + + else: + len_tgt = len(hypo[i][0].split()) + # record length without + if len_tgt == num_bpe_tokens[i][0] - 1: + target_lengths[i] = num_bpe_tokens[i][0] - 1 + else: + target_lengths[i] = num_bpe_tokens[i][0] + + source_lengths[i] = len(source[i].split()) + + if right_to_left: + source[i] = remove_bpe(make_right_to_left(source[i]), bpe_symbol) + target[i] = remove_bpe(make_right_to_left(target[i]), bpe_symbol) + hypo[i] = remove_bpe(make_right_to_left(hypo[i][0]), bpe_symbol) + score[i] = float(score[i][0]) + pos_score[i] = pos_score[i][0] + else: + assert ( + len(hypo[i]) == 1 + ), "expected only one hypothesis per source sentence" + source[i] = remove_bpe(source[i], bpe_symbol) + target[i] = remove_bpe(target[i], bpe_symbol) + hypo[i] = remove_bpe(hypo[i][0], bpe_symbol) + score[i] = float(score[i][0]) + pos_score[i] = pos_score[i][0] + + self.rescore_source = source + self.rescore_hypo = hypo + self.rescore_score = score + self.rescore_target = target + self.rescore_pos_score = pos_score + self.backwards = backwards + self.right_to_left = right_to_left + self.target_lengths = target_lengths + self.source_lengths = source_lengths + + +class BitextOutputFromGen(object): + def __init__( + self, + predictions_bpe_file, + bpe_symbol=None, + nbest=False, + prefix_len=None, + target_prefix_frac=None, + ): + if nbest: + ( + pred_source, + pred_hypo, + pred_score, + pred_target, + pred_pos_score, + ) = reprocess_nbest(predictions_bpe_file) + else: + pred_source, pred_hypo, pred_score, pred_target, pred_pos_score = reprocess( + predictions_bpe_file + ) + + assert len(pred_source) == len(pred_hypo) + assert len(pred_source) == len(pred_score) + assert len(pred_source) == len(pred_target) + assert len(pred_source) == len(pred_pos_score) + + # remove length penalty so we can use raw scores + pred_score, num_bpe_tokens = get_score_from_pos( + pred_pos_score, prefix_len, pred_hypo, bpe_symbol, target_prefix_frac, False + ) + + self.source = pred_source + self.target = pred_target + self.score = pred_score + self.pos_score = pred_pos_score + self.hypo = pred_hypo + self.target_lengths = {} + self.source_lengths = {} + + self.no_bpe_source = remove_bpe_dict(pred_source.copy(), bpe_symbol) + self.no_bpe_hypo = remove_bpe_dict(pred_hypo.copy(), bpe_symbol) + self.no_bpe_target = remove_bpe_dict(pred_target.copy(), bpe_symbol) + + # indexes to match those from the rescoring models + self.rescore_source = {} + self.rescore_target = {} + self.rescore_pos_score = {} + self.rescore_hypo = {} + self.rescore_score = {} + self.num_hypos = {} + self.backwards = False + self.right_to_left = False + + index = 0 + + for i in sorted(pred_source.keys()): + for j in range(len(pred_hypo[i])): + + self.target_lengths[index] = len(self.hypo[i][j].split()) + self.source_lengths[index] = len(self.source[i].split()) + + self.rescore_source[index] = self.no_bpe_source[i] + self.rescore_target[index] = self.no_bpe_target[i] + self.rescore_hypo[index] = self.no_bpe_hypo[i][j] + self.rescore_score[index] = float(pred_score[i][j]) + self.rescore_pos_score[index] = pred_pos_score[i][j] + self.num_hypos[index] = len(pred_hypo[i]) + index += 1 + + +def get_score_from_pos( + pos_score_dict, prefix_len, hypo_dict, bpe_symbol, hypo_frac, backwards +): + score_dict = {} + num_bpe_tokens_dict = {} + assert prefix_len is None or hypo_frac is None + for key in pos_score_dict: + score_dict[key] = [] + num_bpe_tokens_dict[key] = [] + for i in range(len(pos_score_dict[key])): + if prefix_len is not None and not backwards: + num_bpe_tokens = get_num_bpe_tokens_from_len( + hypo_dict[key][i], bpe_symbol, prefix_len + ) + score_dict[key].append(sum(pos_score_dict[key][i][:num_bpe_tokens])) + num_bpe_tokens_dict[key].append(num_bpe_tokens) + elif hypo_frac is not None: + num_words, shortened, hypo_prefix_len = calc_length_from_frac( + hypo_dict[key][i], hypo_frac, bpe_symbol + ) + score_dict[key].append(sum(pos_score_dict[key][i][:hypo_prefix_len])) + num_bpe_tokens_dict[key].append(hypo_prefix_len) + else: + score_dict[key].append(sum(pos_score_dict[key][i])) + num_bpe_tokens_dict[key].append(len(pos_score_dict[key][i])) + return score_dict, num_bpe_tokens_dict + + +class LMOutput(object): + def __init__( + self, + lm_score_file, + lm_dict=None, + prefix_len=None, + bpe_symbol=None, + target_prefix_frac=None, + ): + ( + lm_sentences, + lm_sen_scores, + lm_sen_pos_scores, + lm_no_bpe_sentences, + lm_bpe_tokens, + ) = parse_lm( + lm_score_file, + prefix_len=prefix_len, + bpe_symbol=bpe_symbol, + target_prefix_frac=target_prefix_frac, + ) + + self.sentences = lm_sentences + self.score = lm_sen_scores + self.pos_score = lm_sen_pos_scores + self.lm_dict = lm_dict + self.no_bpe_sentences = lm_no_bpe_sentences + self.bpe_tokens = lm_bpe_tokens + + +def parse_lm(input_file, prefix_len=None, bpe_symbol=None, target_prefix_frac=None): + """parse output of eval_lm""" + with open(input_file, "r") as f: + text = f.readlines() + text = text[7:] + cleaned_text = text[:-2] + + sentences = {} + sen_scores = {} + sen_pos_scores = {} + no_bpe_sentences = {} + num_bpe_tokens_dict = {} + for _i, line in enumerate(cleaned_text): + tokens = line.split() + if tokens[0].isdigit(): + line_id = int(tokens[0]) + scores = [float(x[1:-1]) for x in tokens[2::2]] + sentences[line_id] = " ".join(tokens[1::2][:-1]) + "\n" + if bpe_symbol is not None: + # exclude symbol to match output from generate.py + bpe_sen = " ".join(tokens[1::2][:-1]) + "\n" + no_bpe_sen = remove_bpe(bpe_sen, bpe_symbol) + no_bpe_sentences[line_id] = no_bpe_sen + + if prefix_len is not None: + num_bpe_tokens = get_num_bpe_tokens_from_len( + bpe_sen, bpe_symbol, prefix_len + ) + sen_scores[line_id] = sum(scores[:num_bpe_tokens]) + num_bpe_tokens_dict[line_id] = num_bpe_tokens + elif target_prefix_frac is not None: + num_words, shortened, target_prefix_len = calc_length_from_frac( + bpe_sen, target_prefix_frac, bpe_symbol + ) + sen_scores[line_id] = sum(scores[:target_prefix_len]) + num_bpe_tokens_dict[line_id] = target_prefix_len + else: + sen_scores[line_id] = sum(scores) + num_bpe_tokens_dict[line_id] = len(scores) + + sen_pos_scores[line_id] = scores + + return sentences, sen_scores, sen_pos_scores, no_bpe_sentences, num_bpe_tokens_dict + + +def get_directories( + data_dir_name, + num_rescore, + gen_subset, + fw_name, + shard_id, + num_shards, + sampling=False, + prefix_len=None, + target_prefix_frac=None, + source_prefix_frac=None, +): + nbest_file_id = ( + "nbest_" + + str(num_rescore) + + "_subset_" + + gen_subset + + "_fw_name_" + + fw_name + + "_shard_" + + str(shard_id) + + "_of_" + + str(num_shards) + ) + + if sampling: + nbest_file_id += "_sampling" + + # the directory containing all information for this nbest list + pre_gen = ( + os.path.join(os.path.dirname(__file__)) + + "/rerank_data/" + + data_dir_name + + "/" + + nbest_file_id + ) + # the directory to store the preprocessed nbest list, for left to right rescoring + left_to_right_preprocessed_dir = pre_gen + "/left_to_right_preprocessed" + if source_prefix_frac is not None: + left_to_right_preprocessed_dir = ( + left_to_right_preprocessed_dir + "/prefix_frac" + str(source_prefix_frac) + ) + # the directory to store the preprocessed nbest list, for right to left rescoring + right_to_left_preprocessed_dir = pre_gen + "/right_to_left_preprocessed" + # the directory to store the preprocessed nbest list, for backwards rescoring + backwards_preprocessed_dir = pre_gen + "/backwards" + if target_prefix_frac is not None: + backwards_preprocessed_dir = ( + backwards_preprocessed_dir + "/prefix_frac" + str(target_prefix_frac) + ) + elif prefix_len is not None: + backwards_preprocessed_dir = ( + backwards_preprocessed_dir + "/prefix_" + str(prefix_len) + ) + + # the directory to store the preprocessed nbest list, for rescoring with P(T) + lm_preprocessed_dir = pre_gen + "/lm_preprocessed" + + return ( + pre_gen, + left_to_right_preprocessed_dir, + right_to_left_preprocessed_dir, + backwards_preprocessed_dir, + lm_preprocessed_dir, + ) + + +def lm_scoring( + preprocess_directory, + bpe_status, + gen_output, + pre_gen, + cur_lm_dict, + cur_lm_name, + cur_language_model, + cur_lm_bpe_code, + batch_size, + lm_score_file, + target_lang, + source_lang, + prefix_len=None, +): + if prefix_len is not None: + assert ( + bpe_status == "different" + ), "bpe status must be different to use prefix len" + if bpe_status == "no bpe": + # run lm on output without bpe + write_reprocessed( + gen_output.no_bpe_source, + gen_output.no_bpe_hypo, + gen_output.no_bpe_target, + pre_gen + "/rescore_data_no_bpe.de", + pre_gen + "/rescore_data_no_bpe.en", + pre_gen + "/reference_file_no_bpe", + ) + + preprocess_lm_param = [ + "--only-source", + "--trainpref", + pre_gen + "/rescore_data_no_bpe." + target_lang, + "--srcdict", + cur_lm_dict, + "--destdir", + preprocess_directory, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(preprocess_lm_param) + preprocess.main(input_args) + + eval_lm_param = [ + preprocess_directory, + "--path", + cur_language_model, + "--output-word-probs", + "--batch-size", + str(batch_size), + "--max-tokens", + "1024", + "--sample-break-mode", + "eos", + "--gen-subset", + "train", + ] + + eval_lm_parser = options.get_eval_lm_parser() + input_args = options.parse_args_and_arch(eval_lm_parser, eval_lm_param) + + with open(lm_score_file, "w") as f: + with redirect_stdout(f): + eval_lm.main(input_args) + + elif bpe_status == "shared": + preprocess_lm_param = [ + "--only-source", + "--trainpref", + pre_gen + "/rescore_data." + target_lang, + "--srcdict", + cur_lm_dict, + "--destdir", + preprocess_directory, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(preprocess_lm_param) + preprocess.main(input_args) + + eval_lm_param = [ + preprocess_directory, + "--path", + cur_language_model, + "--output-word-probs", + "--batch-size", + str(batch_size), + "--sample-break-mode", + "eos", + "--gen-subset", + "train", + ] + + eval_lm_parser = options.get_eval_lm_parser() + input_args = options.parse_args_and_arch(eval_lm_parser, eval_lm_param) + + with open(lm_score_file, "w") as f: + with redirect_stdout(f): + eval_lm.main(input_args) + + elif bpe_status == "different": + rescore_file = pre_gen + "/rescore_data_no_bpe" + rescore_bpe = pre_gen + "/rescore_data_new_bpe" + + rescore_file += "." + rescore_bpe += "." + + write_reprocessed( + gen_output.no_bpe_source, + gen_output.no_bpe_hypo, + gen_output.no_bpe_target, + rescore_file + source_lang, + rescore_file + target_lang, + pre_gen + "/reference_file_no_bpe", + bpe_symbol=None, + ) + + # apply LM bpe to nbest list + bpe_src_param = [ + "-c", + cur_lm_bpe_code, + "--input", + rescore_file + target_lang, + "--output", + rescore_bpe + target_lang, + ] + subprocess.call( + [ + "python", + os.path.join( + os.path.dirname(__file__), "subword-nmt/subword_nmt/apply_bpe.py" + ), + ] + + bpe_src_param, + shell=False, + ) + # uncomment to use fastbpe instead of subword-nmt bpe + # bpe_src_param = [rescore_bpe+target_lang, rescore_file+target_lang, cur_lm_bpe_code] + # subprocess.call(["/private/home/edunov/fastBPE/fast", "applybpe"] + bpe_src_param, shell=False) + + preprocess_dir = preprocess_directory + + preprocess_lm_param = [ + "--only-source", + "--trainpref", + rescore_bpe + target_lang, + "--srcdict", + cur_lm_dict, + "--destdir", + preprocess_dir, + ] + preprocess_parser = options.get_preprocessing_parser() + input_args = preprocess_parser.parse_args(preprocess_lm_param) + preprocess.main(input_args) + + eval_lm_param = [ + preprocess_dir, + "--path", + cur_language_model, + "--output-word-probs", + "--batch-size", + str(batch_size), + "--max-tokens", + "1024", + "--sample-break-mode", + "eos", + "--gen-subset", + "train", + ] + + eval_lm_parser = options.get_eval_lm_parser() + input_args = options.parse_args_and_arch(eval_lm_parser, eval_lm_param) + + with open(lm_score_file, "w") as f: + with redirect_stdout(f): + eval_lm.main(input_args) + + +def rescore_file_name( + nbest_dir, + prefix_len, + scorer_name, + lm_file=False, + target_prefix_frac=None, + source_prefix_frac=None, + backwards=None, +): + if lm_file: + score_file = nbest_dir + "/lm_score_translations_model_" + scorer_name + ".txt" + else: + score_file = nbest_dir + "/" + scorer_name + "_score_translations.txt" + if backwards: + if prefix_len is not None: + score_file += "prefix_len" + str(prefix_len) + elif target_prefix_frac is not None: + score_file += "target_prefix_frac" + str(target_prefix_frac) + else: + if source_prefix_frac is not None: + score_file += "source_prefix_frac" + str(source_prefix_frac) + return score_file diff --git a/fairseq-tools/fairseq/examples/nonautoregressive_translation/README.md b/fairseq-tools/fairseq/examples/nonautoregressive_translation/README.md new file mode 100644 index 00000000..dfc592f0 --- /dev/null +++ b/fairseq-tools/fairseq/examples/nonautoregressive_translation/README.md @@ -0,0 +1,146 @@ +# Non-autoregressive Neural Machine Translation (NAT) + +This page mainly includes instructions for reproducing results from the following papers +* [Levenshtein Transformer (Gu et al., 2019)](https://arxiv.org/abs/1905.11006). +* [Understanding Knowledge Distillation in Non-autoregressive Machine Translation (Zhou et al., 2019)](https://arxiv.org/abs/1911.02727). + +We also provided our own implementations for several popular non-autoregressive-based models as reference:
+* [Non-Autoregressive Neural Machine Translation (Gu et al., 2017)](https://arxiv.org/abs/1711.02281)
+* [Deterministic Non-Autoregressive Neural Sequence Modeling by Iterative Refinement (Lee et al., 2018)](https://arxiv.org/abs/1802.06901)
+* [Insertion Transformer: Flexible Sequence Generation via Insertion Operations (Stern et al., 2019)](https://arxiv.org/abs/1902.03249)
+* [Mask-Predict: Parallel Decoding of Conditional Masked Language Models (Ghazvininejad et al., 2019)](https://arxiv.org/abs/1904.09324v2)
+* [Fast Structured Decoding for Sequence Models (Sun et al., 2019)](https://arxiv.org/abs/1910.11555) + +## Dataset + +First, follow the [instructions to download and preprocess the WMT'14 En-De dataset](../translation#wmt14-english-to-german-convolutional). +Make sure to learn a joint vocabulary by passing the `--joined-dictionary` option to `fairseq-preprocess`. + +### Knowledge Distillation +Following [Gu et al. 2019](https://arxiv.org/abs/1905.11006), [knowledge distillation](https://arxiv.org/abs/1606.07947) from an autoregressive model can effectively simplify the training data distribution, which is sometimes essential for NAT-based models to learn good translations. +The easiest way of performing distillation is to follow the [instructions of training a standard transformer model](../translation) on the same data, and then decode the training set to produce a distillation dataset for NAT. + +### Download +We also provided the preprocessed [original](http://dl.fbaipublicfiles.com/nat/original_dataset.zip) and [distillation](http://dl.fbaipublicfiles.com/nat/distill_dataset.zip) datasets. Please build the binarized dataset on your own. + + +## Train a model + +Then we can train a nonautoregressive model using the `translation_lev` task and a new criterion `nat_loss`. +Use the `--noise` flag to specify the input noise used on the target sentences. +In default, we run the task for *Levenshtein Transformer*, with `--noise='random_delete'`. Full scripts to run other models can also be found [here](./scripts.md). + +The following command will train a *Levenshtein Transformer* on the binarized dataset. + +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch levenshtein_transformer \ + --noise random_delete \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + +## Translate + +Once a model is trained, we can generate translations using an `iterative_refinement_generator` which will based on the model's initial output and iteratively read and greedily refine the translation until (1) the model predicts the same translations for two consecutive iterations; or (2) the generator reaches the maximum iterations (`--iter-decode-max-iter`). Use `--print-step` to check the actual # of iteration for each sentence. + +For *Levenshtein Transformer*, it sometimes helps to apply a `--iter-decode-eos-penalty` (typically, 0~3) to penalize the model finishing generation too early and generating too short translations. + +For example, to generate with `--iter-decode-max-iter=9`: +```bash +fairseq-generate \ + data-bin/wmt14_en_de_distill \ + --gen-subset test \ + --task translation_lev \ + --path checkpoints/checkpoint_best.pt \ + --iter-decode-max-iter 9 \ + --iter-decode-eos-penalty 0 \ + --beam 1 --remove-bpe \ + --print-step \ + --batch-size 400 +``` +In the end of the generation, we can see the tokenized BLEU score for the translation. + +## Advanced Decoding Methods +### Ensemble +The NAT models use special implementations of [ensembling](https://github.com/fairinternal/fairseq-py/blob/b98d88da52f2f21f1b169bab8c70c1c4ca19a768/fairseq/sequence_generator.py#L522) to support iterative refinement and a variety of parallel operations in different models, while it shares the same API as standard autoregressive models as follows: +```bash +fairseq-generate \ + data-bin/wmt14_en_de_distill \ + --gen-subset test \ + --task translation_lev \ + --path checkpoint_1.pt:checkpoint_2.pt:checkpoint_3.pt \ + --iter-decode-max-iter 9 \ + --iter-decode-eos-penalty 0 \ + --beam 1 --remove-bpe \ + --print-step \ + --batch-size 400 +``` +We use ``:`` to split multiple models. Note that, not all NAT models support ensembling for now. + + +### Length-beam +For models that predict lengths before decoding (e.g. the vanilla NAT, Mask-Predict, etc), it is possible to improve the translation quality by varying the target lengths around the predicted value, and translating the same example multiple times in parallel. We can select the best translation with the highest scores defined by your model's output. + +Note that, not all models support length beams. For models which dynamically change the lengths (e.g. *Insertion Transformer*, *Levenshtein Transformer*), the same trick does not apply. + +### Re-ranking +If the model generates multiple translations with length beam, we can also introduce an autoregressive model to rerank the translations considering scoring from an autoregressive model is much faster than decoding from that. + +For example, to generate translations with length beam and reranking, +```bash +fairseq-generate \ + data-bin/wmt14_en_de_distill \ + --gen-subset test \ + --task translation_lev \ + --path checkpoints/checkpoint_best.pt:at_checkpoints/checkpoint_best.pt \ + --iter-decode-max-iter 9 \ + --iter-decode-eos-penalty 0 \ + --iter-decode-with-beam 9 \ + --iter-decode-with-external-reranker \ + --beam 1 --remove-bpe \ + --print-step \ + --batch-size 100 +``` +Note that we need to make sure the autoregressive model shares the same vocabulary as our target non-autoregressive model. + + +## Citation + +```bibtex +@incollection{NIPS2019_9297, + title = {Levenshtein Transformer}, + author = {Gu, Jiatao and Wang, Changhan and Zhao, Junbo}, + booktitle = {Advances in Neural Information Processing Systems 32}, + editor = {H. Wallach and H. Larochelle and A. Beygelzimer and F. d\textquotesingle Alch\'{e}-Buc and E. Fox and R. Garnett}, + pages = {11179--11189}, + year = {2019}, + publisher = {Curran Associates, Inc.}, + url = {http://papers.nips.cc/paper/9297-levenshtein-transformer.pdf} +} +``` +```bibtex +@article{zhou2019understanding, + title={Understanding Knowledge Distillation in Non-autoregressive Machine Translation}, + author={Zhou, Chunting and Neubig, Graham and Gu, Jiatao}, + journal={arXiv preprint arXiv:1911.02727}, + year={2019} +} +``` diff --git a/fairseq-tools/fairseq/examples/nonautoregressive_translation/scripts.md b/fairseq-tools/fairseq/examples/nonautoregressive_translation/scripts.md new file mode 100644 index 00000000..63b945c1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/nonautoregressive_translation/scripts.md @@ -0,0 +1,179 @@ +# Examples of Training scripts for Non-autoregressive Machine Translation models + +### Non-autoregressive Transformer (NAT, Gu et al., 2017) +Note that we need to have an additional module to perform "length prediction" (`--length-loss-factor`) before generating the whole sequence. +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch nonautoregressive_transformer \ + --noise full_mask \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --pred-length-offset \ + --length-loss-factor 0.1 \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + +### Fast Structured Decoding for Sequence Models (NAT-CRF, Sun et al., 2019) +Note that we implemented a low-rank appromixated CRF model by setting `--crf-lowrank-approx=32` and `--crf-beam-approx=64` as discribed in the original paper. All other settings are the same as the vanilla NAT model. +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch nacrf_transformer \ + --noise full_mask \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --pred-length-offset \ + --length-loss-factor 0.1 \ + --word-ins-loss-factor 0.5 \ + --crf-lowrank-approx 32 \ + --crf-beam-approx 64 \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + + +### Non-autoregressive Transformer with Iterative Refinement (iNAT, Lee et al., 2018) +Note that `--train-step` means how many iterations of refinement we used during training, and `--dae-ratio` controls the ratio of denoising auto-encoder training described in the original paper. +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch iterative_nonautoregressive_transformer \ + --noise full_mask \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --pred-length-offset \ + --length-loss-factor 0.1 \ + --train-step 4 \ + --dae-ratio 0.5 \ + --stochastic-approx \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + +### Insertion Transformer (InsT, Stern et al., 2019) +Note that we need to specify the "slot-loss" (uniform or balanced tree) described in the original paper. Here we use `--label-tau` to control the temperature. + +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch insertion_transformer \ + --noise random_delete \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + + +### Mask Predict (CMLM, Ghazvininejad et al., 2019) +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch cmlm_transformer \ + --noise random_mask \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` + + + + +### Levenshtein Transformer (LevT, Gu et al., 2019) +```bash +fairseq-train \ + data-bin/wmt14_en_de_distill \ + --save-dir checkpoints \ + --ddp-backend=no_c10d \ + --task translation_lev \ + --criterion nat_loss \ + --arch levenshtein_transformer \ + --noise random_delete \ + --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9,0.98)' \ + --lr 0.0005 --lr-scheduler inverse_sqrt \ + --min-lr '1e-09' --warmup-updates 10000 \ + --warmup-init-lr '1e-07' --label-smoothing 0.1 \ + --dropout 0.3 --weight-decay 0.01 \ + --decoder-learned-pos \ + --encoder-learned-pos \ + --apply-bert-init \ + --log-format 'simple' --log-interval 100 \ + --fixed-validation-seed 7 \ + --max-tokens 8000 \ + --save-interval-updates 10000 \ + --max-update 300000 +``` diff --git a/fairseq-tools/fairseq/examples/paraphraser/README.md b/fairseq-tools/fairseq/examples/paraphraser/README.md new file mode 100644 index 00000000..3810311f --- /dev/null +++ b/fairseq-tools/fairseq/examples/paraphraser/README.md @@ -0,0 +1,46 @@ +# Paraphrasing with round-trip translation and mixture of experts + +Machine translation models can be used to paraphrase text by translating it to +an intermediate language and back (round-trip translation). + +This example shows how to paraphrase text by first passing it to an +English-French translation model, followed by a French-English [mixture of +experts translation model](/examples/translation_moe). + +##### 0. Setup + +Clone fairseq from source and install necessary dependencies: +```bash +git clone https://github.com/pytorch/fairseq.git +cd fairseq +pip install --editable . +pip install sacremoses sentencepiece +``` + +##### 1. Download models +```bash +wget https://dl.fbaipublicfiles.com/fairseq/models/paraphraser.en-fr.tar.gz +wget https://dl.fbaipublicfiles.com/fairseq/models/paraphraser.fr-en.hMoEup.tar.gz +tar -xzvf paraphraser.en-fr.tar.gz +tar -xzvf paraphraser.fr-en.hMoEup.tar.gz +``` + +##### 2. Paraphrase +```bash +python examples/paraphraser/paraphrase.py \ + --en2fr paraphraser.en-fr \ + --fr2en paraphraser.fr-en.hMoEup +# Example input: +# The new date for the Games, postponed for a year in response to the coronavirus pandemic, gives athletes time to recalibrate their training schedules. +# Example outputs: +# Delayed one year in response to the coronavirus pandemic, the new date of the Games gives athletes time to rebalance their training schedule. +# The new date of the Games, which was rescheduled one year in response to the coronavirus (CV) pandemic, gives athletes time to rebalance their training schedule. +# The new date of the Games, postponed one year in response to the coronavirus pandemic, provides athletes with time to rebalance their training schedule. +# The Games' new date, postponed one year in response to the coronavirus pandemic, gives athletes time to rebalance their training schedule. +# The new Games date, postponed one year in response to the coronavirus pandemic, gives the athletes time to rebalance their training schedule. +# The new date of the Games, which was postponed one year in response to the coronavirus pandemic, gives the athletes time to rebalance their training schedule. +# The new date of the Games, postponed one year in response to the coronavirus pandemic, gives athletes time to rebalance their training schedule. +# The new date of the Games, postponed one year in response to the coronavirus pandemic, gives athletes time to re-balance their training schedule. +# The new date of the Games, postponed one year in response to the coronavirus pandemic, gives the athletes time to rebalance their schedule of training. +# The new date of the Games, postponed one year in response to the pandemic of coronavirus, gives the athletes time to rebalance their training schedule. +``` diff --git a/fairseq-tools/fairseq/examples/paraphraser/paraphrase.py b/fairseq-tools/fairseq/examples/paraphraser/paraphrase.py new file mode 100644 index 00000000..d3422fb3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/paraphraser/paraphrase.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 -u + +import argparse +import fileinput +import logging +import os +import sys + +from fairseq.models.transformer import TransformerModel + + +logging.getLogger().setLevel(logging.INFO) + + +def main(): + parser = argparse.ArgumentParser(description="") + parser.add_argument("--en2fr", required=True, help="path to en2fr model") + parser.add_argument( + "--fr2en", required=True, help="path to fr2en mixture of experts model" + ) + parser.add_argument( + "--user-dir", help="path to fairseq examples/translation_moe/src directory" + ) + parser.add_argument( + "--num-experts", + type=int, + default=10, + help="(keep at 10 unless using a different model)", + ) + parser.add_argument( + "files", + nargs="*", + default=["-"], + help='input files to paraphrase; "-" for stdin', + ) + args = parser.parse_args() + + if args.user_dir is None: + args.user_dir = os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), # examples/ + "translation_moe", + "src", + ) + if os.path.exists(args.user_dir): + logging.info("found user_dir:" + args.user_dir) + else: + raise RuntimeError( + "cannot find fairseq examples/translation_moe/src " + "(tried looking here: {})".format(args.user_dir) + ) + + logging.info("loading en2fr model from:" + args.en2fr) + en2fr = TransformerModel.from_pretrained( + model_name_or_path=args.en2fr, + tokenizer="moses", + bpe="sentencepiece", + ).eval() + + logging.info("loading fr2en model from:" + args.fr2en) + fr2en = TransformerModel.from_pretrained( + model_name_or_path=args.fr2en, + tokenizer="moses", + bpe="sentencepiece", + user_dir=args.user_dir, + task="translation_moe", + ).eval() + + def gen_paraphrases(en): + fr = en2fr.translate(en) + return [ + fr2en.translate(fr, inference_step_args={"expert": i}) + for i in range(args.num_experts) + ] + + logging.info("Type the input sentence and press return:") + for line in fileinput.input(args.files): + line = line.strip() + if len(line) == 0: + continue + for paraphrase in gen_paraphrases(line): + print(paraphrase) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/pay_less_attention_paper/README.md b/fairseq-tools/fairseq/examples/pay_less_attention_paper/README.md new file mode 100644 index 00000000..3fb93b23 --- /dev/null +++ b/fairseq-tools/fairseq/examples/pay_less_attention_paper/README.md @@ -0,0 +1,176 @@ +# Pay Less Attention with Lightweight and Dynamic Convolutions (Wu et al., 2019) + +This page contains pointers to pre-trained models as well as instructions on how to train new models for [our paper](https://arxiv.org/abs/1901.10430). + +## Citation: +```bibtex +@inproceedings{wu2018pay, + title = {Pay Less Attention with Lightweight and Dynamic Convolutions}, + author = {Felix Wu and Angela Fan and Alexei Baevski and Yann Dauphin and Michael Auli}, + booktitle = {International Conference on Learning Representations}, + year = {2019}, + url = {https://arxiv.org/abs/1901.10430}, +} +``` + +## Translation + +### Pre-trained models +For some datasets we release models without GLUs which are faster at inference. + +Model | Description | Dataset | Download +---|---|---|--- +`lightconv.no_glu.iwslt14.de-en` | LightConv (without GLUs) | [IWSLT14 German-English](https://wit3.fbk.eu/archive/2014-01/texts/de/en/de-en.tgz) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/iwslt14.de-en.lightconv.tar.gz)
IWSLT14 test:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/iwslt14.de-en.test.tar.bz2) +`dynamicconv.no_glu.iwslt14.de-en` | DynamicConv (without GLUs) | [IWSLT14 German-English](https://wit3.fbk.eu/archive/2014-01/texts/de/en/de-en.tgz) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/iwslt14.de-en.dynamicconv.tar.gz)
IWSLT14 test:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/iwslt14.de-en.test.tar.bz2) +`lightconv.no_glu.wmt16.en-de` | LightConv (without GLUs) | [WMT16 English-German](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.lightconv.tar.gz)
newstest2014 (shared vocab):
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt16.en-de.joined-dict.newstest2014.tar.bz2) +`dynamicconv.no_glu.wmt16.en-de` | DynamicConv (without GLUs) | [WMT16 English-German](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.dynamicconv.tar.gz)
newstest2014 (shared vocab):
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt16.en-de.joined-dict.newstest2014.tar.bz2) +`lightconv.glu.wmt16.en-de` | LightConv | [WMT16 English-German](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.lightconv-glu.tar.gz)
newstest2014 (shared vocab):
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt16.en-de.joined-dict.newstest2014.tar.bz2) +`dynamicconv.glu.wmt16.en-de` | DynamicConv | [WMT16 English-German](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.dynamicconv-glu.tar.gz)
newstest2014 (shared vocab):
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt16.en-de.joined-dict.newstest2014.tar.bz2) +`lightconv.glu.wmt14.en-fr` | LightConv | [WMT14 English-French](http://statmt.org/wmt14/translation-task.html#Download) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt14.en-fr.joined-dict.lightconv-glu.tar.gz)
newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.en-fr.joined-dict.newstest2014.tar.bz2) +`dynamicconv.glu.wmt14.en-fr` | DynamicConv | [WMT14 English-French](http://statmt.org/wmt14/translation-task.html#Download) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt14.en-fr.joined-dict.dynamicconv-glu.tar.gz)
newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.en-fr.joined-dict.newstest2014.tar.bz2) +`lightconv.glu.wmt17.zh-en` | LightConv | [WMT17 Chinese-English](http://statmt.org/wmt17/translation-task.html#Download) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt17.zh-en.lightconv-glu.tar.gz)
newstest2017:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt17.zh-en.newstest2017.tar.bz2) +`dynamicconv.glu.wmt17.zh-en` | DynamicConv | [WMT17 Chinese-English](http://statmt.org/wmt17/translation-task.html#Download) | model:
[download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt17.zh-en.dynamicconv-glu.tar.gz)
newstest2017:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt17.zh-en.newstest2017.tar.bz2) + +### Memory-Efficient CUDA Kernels + +Since the PyTorch implementations of Light/Dynamic conv are quite memory intensive, we have developed CUDA kernels that implement the light and dynamic convolution operator in a memory-efficient and performant manner. For large sequence lengths, these kernels save about 50% memory compared to the PyTorch equivalent. + +To install the kernels, use the commands below. Once installed, they will automatically be used in place of the PyTorch implementations whenever a light or dynamic convolution is used. + +```sh +# to install lightconv +cd fairseq/modules/lightconv_layer +python cuda_function_gen.py +python setup.py install + +# to install dynamicconv +cd fairseq/modules/dynamicconv_layer +python cuda_function_gen.py +python setup.py install +``` + +### Example usage (torch.hub) + +We require a few additional Python dependencies for preprocessing: +```bash +pip install sacremoses subword_nmt +``` + +Interactive translation via PyTorch Hub: +```python +import torch + +# List available models +torch.hub.list('pytorch/fairseq') # [..., 'lightconv.glu.wmt17.zh-en', ... ] + +# Load a transformer trained on WMT'16 En-De +zh2en = torch.hub.load('pytorch/fairseq', 'lightconv.glu.wmt17.zh-en', tokenizer='moses', bpe='subword_nmt') + +# The underlying model is available under the *models* attribute +assert isinstance(zh2en.models[0], fairseq.models.lightconv.LightConvModel) + +# Translate a sentence +zh2en.translate('你好 世界') +# 'Hello World' +``` + +Loading custom models: +```python +from fairseq.models.lightconv import LightConvModel +en2fr = LightConvModel.from_pretrained( + '/path/to/checkpoints', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='data-bin/wmt14_en_fr', + bpe='subword_nmt', + bpe_codes='data-bin/wmt14_en_fr/en.code' +) +en2fr.translate('Hello world!') +# 'Bonjour le monde' +``` + +### Preprocessing the training datasets + +Please follow the instructions in [`examples/translation/README.md`](../translation/README.md) to preprocess the data. + +### Training and evaluation options: +To use the model without GLU, please set `--encoder-glu 0 --decoder-glu 0`. +For LightConv, please use `--encoder-conv-type lightweight --decoder-conv-type lightweight`, otherwise the default is DynamicConv. +For best BLEU results, lenpen may need to be manually tuned. + +To use the CUDA kernels, first install the PyTorch modules using the commands +above. Once the CUDA modules are installed, they will automatically be used +instead of the PyTorch modules. + +### IWSLT14 De-En +Training and evaluating DynamicConv (without GLU) on a GPU: +```sh +# Training +SAVE="save/dynamic_conv_iwslt" +mkdir -p $SAVE +CUDA_VISIBLE_DEVICES=0 $(which fairseq-train) data-bin/iwslt14.tokenized.de-en \ + --clip-norm 0 --optimizer adam --lr 0.0005 \ + --source-lang de --target-lang en --max-tokens 4000 --no-progress-bar \ + --log-interval 100 --min-lr '1e-09' --weight-decay 0.0001 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --lr-scheduler inverse_sqrt \ + --ddp-backend=no_c10d \ + --max-update 50000 --warmup-updates 4000 --warmup-init-lr '1e-07' \ + --adam-betas '(0.9, 0.98)' --keep-last-epochs 10 \ + -a lightconv_iwslt_de_en --save-dir $SAVE \ + --dropout 0.3 --attention-dropout 0.1 --weight-dropout 0.1 \ + --encoder-glu 0 --decoder-glu 0 +python scripts/average_checkpoints.py --inputs $SAVE \ + --num-epoch-checkpoints 10 --output "${SAVE}/checkpoint_last10_avg.pt" + +# Evaluation +CUDA_VISIBLE_DEVICES=0 fairseq-generate data-bin/iwslt14.tokenized.de-en --path "${SAVE}/checkpoint_last10_avg.pt" --batch-size 128 --beam 4 --remove-bpe --lenpen 1 --gen-subset test --quiet +``` + +### WMT16 En-De +Training and evaluating DynamicConv (with GLU) on WMT16 En-De using cosine scheduler on one machine with 8 V100 GPUs: +```sh +# Training +SAVE="save/dynamic_conv_wmt16en2de" +mkdir -p $SAVE +python -m torch.distributed.launch --nproc_per_node 8 $(which fairseq-train) \ + data-bin/wmt16_en_de_bpe32k --fp16 --log-interval 100 --no-progress-bar \ + --max-update 30000 --share-all-embeddings --optimizer adam \ + --adam-betas '(0.9, 0.98)' --clip-norm 0.0 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --min-lr 1e-09 --update-freq 16 --attention-dropout 0.1 --keep-last-epochs 10 \ + --ddp-backend=no_c10d --max-tokens 3584 \ + --lr-scheduler cosine --warmup-init-lr 1e-7 --warmup-updates 10000 \ + --lr-shrink 1 --max-lr 0.001 --lr 1e-7 --min-lr 1e-9 --warmup-init-lr 1e-07 \ + --t-mult 1 --lr-period-updates 20000 \ + --arch lightconv_wmt_en_de_big --save-dir $SAVE \ + --dropout 0.3 --attention-dropout 0.1 --weight-dropout 0.1 \ + --encoder-glu 1 --decoder-glu 1 + +# Evaluation +CUDA_VISIBLE_DEVICES=0 fairseq-generate data-bin/wmt16.en-de.joined-dict.newstest2014 --path "${SAVE}/checkpoint_best.pt" --batch-size 128 --beam 5 --remove-bpe --lenpen 0.5 --gen-subset test > wmt16_gen.txt +bash scripts/compound_split_bleu.sh wmt16_gen.txt +``` + +### WMT14 En-Fr +Training DynamicConv (with GLU) on WMT14 En-Fr using cosine scheduler on one machine with 8 V100 GPUs: +```sh +# Training +SAVE="save/dynamic_conv_wmt14en2fr" +mkdir -p $SAVE +python -m torch.distributed.launch --nproc_per_node 8 $(which fairseq-train) \ + data-bin/wmt14_en_fr --fp16 --log-interval 100 --no-progress-bar \ + --max-update 30000 --share-all-embeddings --optimizer adam \ + --adam-betas '(0.9, 0.98)' --clip-norm 0.0 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --min-lr 1e-09 --update-freq 16 --attention-dropout 0.1 --keep-last-epochs 10 \ + --ddp-backend=no_c10d --max-tokens 3584 \ + --lr-scheduler cosine --warmup-init-lr 1e-7 --warmup-updates 10000 \ + --lr-shrink 1 --max-lr 0.001 --lr 1e-7 --min-lr 1e-9 --warmup-init-lr 1e-07 \ + --t-mult 1 --lr-period-updates 70000 \ + --arch lightconv_wmt_en_fr_big --save-dir $SAVE \ + --dropout 0.1 --attention-dropout 0.1 --weight-dropout 0.1 \ + --encoder-glu 1 --decoder-glu 1 + +# Evaluation +CUDA_VISIBLE_DEVICES=0 fairseq-generate data-bin/wmt14.en-fr.joined-dict.newstest2014 --path "${SAVE}/checkpoint_best.pt" --batch-size 128 --beam 5 --remove-bpe --lenpen 0.9 --gen-subset test +``` diff --git a/fairseq-tools/fairseq/examples/pointer_generator/README.md b/fairseq-tools/fairseq/examples/pointer_generator/README.md new file mode 100644 index 00000000..60965708 --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/README.md @@ -0,0 +1,82 @@ +# Transformer with Pointer-Generator Network + +This page describes the `transformer_pointer_generator` model that incorporates +a pointing mechanism in the Transformer model that facilitates copying of input +words to the output. This architecture is described in [Enarvi et al. (2020)](https://www.aclweb.org/anthology/2020.nlpmc-1.4/). + +## Background + +The pointer-generator network was introduced in [See et al. (2017)](https://arxiv.org/abs/1704.04368) +for RNN encoder-decoder attention models. A similar mechanism can be +incorporated in a Transformer model by reusing one of the many attention +distributions for pointing. The attention distribution over the input words is +interpolated with the normal output distribution over the vocabulary words. This +allows the model to generate words that appear in the input, even if they don't +appear in the vocabulary, helping especially with small vocabularies. + +## Implementation + +The mechanism for copying out-of-vocabulary words from the input has been +implemented differently to See et al. In their [implementation](https://github.com/abisee/pointer-generator) +they convey the word identities through the model in order to be able to produce +words that appear in the input sequence but not in the vocabulary. A different +approach was taken in the Fairseq implementation to keep it self-contained in +the model file, avoiding any changes to the rest of the code base. Copying +out-of-vocabulary words is possible by pre-processing the input and +post-processing the output. This is described in detail in the next section. + +## Usage + +The training and evaluation procedure is outlined below. You can also find a +more detailed example for the XSum dataset on [this page](README.xsum.md). + +##### 1. Create a vocabulary and extend it with source position markers + +The pointing mechanism is especially helpful with small vocabularies, if we are +able to recover the identities of any out-of-vocabulary words that are copied +from the input. For this purpose, the model allows extending the vocabulary with +special tokens that can be used in place of `` tokens to identify different +input positions. For example, the user may add ``, ``, ``, +etc. to the end of the vocabulary, after the normal words. Below is an example +of how to create a vocabulary of 10000 most common words and add 1000 input +position markers. + +```bash +vocab_size=10000 +position_markers=1000 +export LC_ALL=C +cat train.src train.tgt | + tr -s '[:space:]' '\n' | + sort | + uniq -c | + sort -k1,1bnr -k2 | + head -n "$((vocab_size - 4))" | + awk '{ print $2 " " $1 }' >dict.pg.txt +python3 -c "[print(' 0'.format(n)) for n in range($position_markers)]" >>dict.pg.txt +``` + +##### 2. Preprocess the text data + +The idea is that any `` tokens in the text are replaced with `` if +it appears in the first input position, `` if it appears in the second +input position, and so on. This can be achieved using the `preprocess.py` script +that is provided in this directory. + +##### 3. Train a model + +The number of these special tokens is given to the model with the +`--source-position-markers` argument—the model simply maps all of these to the +same word embedding as ``. + +The attention distribution that is used for pointing is selected using the +`--alignment-heads` and `--alignment-layer` command-line arguments in the same +way as with the `transformer_align` model. + +##### 4. Generate text and postprocess it + +When using the model to generate text, you want to preprocess the input text in +the same way that training data was processed, replacing out-of-vocabulary words +with `` tokens. If any of these tokens are copied to the output, the +actual words can be retrieved from the unprocessed input text. Any `` +token should be replaced with the word at position N in the original input +sequence. This can be achieved using the `postprocess.py` script. diff --git a/fairseq-tools/fairseq/examples/pointer_generator/README.xsum.md b/fairseq-tools/fairseq/examples/pointer_generator/README.xsum.md new file mode 100644 index 00000000..ac3a8c3d --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/README.xsum.md @@ -0,0 +1,180 @@ +## Training a pointer-generator model on the Extreme Summarization dataset + +##### 1. Download the Extreme Summarization data and preprocess it + +Follow the instructions [here](https://github.com/EdinburghNLP/XSum) to obtain +the original Extreme Summarization dataset. You should have six files, +{train,validation,test}.{document,summary}. + +##### 2. Create a vocabulary and extend it with source position markers + +```bash +vocab_size=10000 +position_markers=1000 +export LC_ALL=C +cat train.document train.summary | + tr -s '[:space:]' '\n' | + sort | + uniq -c | + sort -k1,1bnr -k2 | + head -n "$((vocab_size - 4))" | + awk '{ print $2 " " $1 }' >dict.pg.txt +python3 -c "[print(' 0'.format(n)) for n in range($position_markers)]" >>dict.pg.txt +``` + +This creates the file dict.pg.txt that contains the 10k most frequent words, +followed by 1k source position markers: + +``` +the 4954867 +. 4157552 +, 3439668 +to 2212159 +a 1916857 +of 1916820 +and 1823350 +... + 0 + 0 + 0 + 0 + 0 +... +``` + +##### 2. Preprocess the text data + +```bash +./preprocess.py --source train.document --target train.summary --vocab <(cut -d' ' -f1 dict.pg.txt) --source-out train.pg.src --target-out train.pg.tgt +./preprocess.py --source validation.document --target validation.summary --vocab <(cut -d' ' -f1 dict.pg.txt) --source-out valid.pg.src --target-out valid.pg.tgt +./preprocess.py --source test.document --vocab <(cut -d' ' -f1 dict.pg.txt) --source-out test.pg.src +``` + +The data should now contain `` tokens in place of out-of-vocabulary words. + +##### 3. Binarize the dataset: + +```bash +fairseq-preprocess \ + --source-lang src \ + --target-lang tgt \ + --trainpref train.pg \ + --validpref valid.pg \ + --destdir bin \ + --workers 60 \ + --srcdict dict.pg.txt \ + --joined-dictionary +``` + +##### 3. Train a model + +```bash +total_updates=20000 +warmup_updates=500 +lr=0.001 +max_tokens=4096 +update_freq=4 +pointer_layer=-2 + +CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 fairseq-train bin \ + --user-dir examples/pointer_generator/pointer_generator_src \ + --max-tokens "$max_tokens" \ + --task translation \ + --source-lang src --target-lang tgt \ + --truncate-source \ + --layernorm-embedding \ + --share-all-embeddings \ + --encoder-normalize-before \ + --decoder-normalize-before \ + --required-batch-size-multiple 1 \ + --arch transformer_pointer_generator \ + --alignment-layer "$pointer_layer" \ + --alignment-heads 1 \ + --source-position-markers 1000 \ + --criterion label_smoothed_cross_entropy \ + --label-smoothing 0.1 \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.01 --optimizer adam --adam-betas "(0.9, 0.999)" --adam-eps 1e-08 \ + --clip-norm 0.1 \ + --lr-scheduler inverse_sqrt --lr "$lr" --max-update "$total_updates" --warmup-updates "$warmup_updates" \ + --update-freq "$update_freq" \ + --skip-invalid-size-inputs-valid-test +``` + +Above we specify that our dictionary contains 1000 source position markers, and +that we want to use one attention head from the penultimate decoder layer for +pointing. It should run in 5.5 hours on one node with eight 32GB V100 GPUs. The +logged messages confirm that dictionary indices above 10000 will be mapped to +the `` embedding: + +``` +2020-09-24 20:43:53 | INFO | fairseq.tasks.translation | [src] dictionary: 11000 types +2020-09-24 20:43:53 | INFO | fairseq.tasks.translation | [tgt] dictionary: 11000 types +2020-09-24 20:43:53 | INFO | fairseq.data.data_utils | loaded 11332 examples from: bin/valid.src-tgt.src +2020-09-24 20:43:53 | INFO | fairseq.data.data_utils | loaded 11332 examples from: bin/valid.src-tgt.tgt +2020-09-24 20:43:53 | INFO | fairseq.tasks.translation | bin valid src-tgt 11332 examples +2020-09-24 20:43:53 | INFO | fairseq.models.transformer_pg | dictionary indices from 10000 to 10999 will be mapped to 3 +``` + +##### 4. Summarize the test sequences + +```bash +batch_size=32 +beam_size=6 +max_length=60 +length_penalty=1.0 + +fairseq-interactive bin \ + --user-dir examples/pointer_generator/pointer_generator_src \ + --batch-size "$batch_size" \ + --task translation \ + --source-lang src --target-lang tgt \ + --path checkpoints/checkpoint_last.pt \ + --input test.pg.src \ + --buffer-size 200 \ + --max-len-a 0 \ + --max-len-b "$max_length" \ + --lenpen "$length_penalty" \ + --beam "$beam_size" \ + --skip-invalid-size-inputs-valid-test | + tee generate.out +grep ^H generate.out | cut -f 3- >generate.hyp +``` + +Now you should have the generated sequences in `generate.hyp`. They contain +`` tokens that the model has copied from the source sequence. In order to +retrieve the original words, we need the unprocessed source sequences from +`test.document`. + +##### 5. Process the generated output + +Since we skipped too long inputs when producing `generate.hyp`, we also have to +skip too long sequences now that we read `test.document`. + +```bash +./postprocess.py \ + --source <(awk 'NF<1024' test.document) \ + --target generate.hyp \ + --target-out generate.hyp.processed +``` + +Now you'll find the final sequences from `generate.hyp.processed`, with +`` replaced with the original word from the source sequence. + +##### An example of a summarized sequence + +The original source document in `test.document`: + +> de roon moved to teesside in june 2016 for an initial # 8.8 m fee and played 33 premier league games last term . the netherlands international , 26 , scored five goals in 36 league and cup games during his spell at boro . meanwhile , manager garry monk confirmed the championship club 's interest in signing chelsea midfielder lewis baker . `` he 's a target and one of many that we 've had throughout the summer months , '' said monk . find all the latest football transfers on our dedicated page . + +The preprocessed source document in `test.src.pg`: + +> de \ moved to \ in june 2016 for an initial # \ m fee and played 33 premier league games last term . the netherlands international , 26 , scored five goals in 36 league and cup games during his spell at boro . meanwhile , manager garry monk confirmed the championship club 's interest in signing chelsea midfielder lewis baker . `` he 's a target and one of many that we 've had throughout the summer months , '' said monk . find all the latest football transfers on our dedicated page . + +The generated summary in `generate.hyp`: + +> middlesbrough striker \ de \ has joined spanish side \ on a season-long loan . + +The generated summary after postprocessing in `generate.hyp.processed`: + +> middlesbrough striker \ de roon has joined spanish side \ on a season-long loan . diff --git a/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/__init__.py b/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/__init__.py new file mode 100644 index 00000000..c361ff6b --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import transformer_pg # noqa diff --git a/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/transformer_pg.py b/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/transformer_pg.py new file mode 100644 index 00000000..079fdda5 --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/pointer_generator_src/transformer_pg.py @@ -0,0 +1,468 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from typing import Any, Dict, Optional + +import torch +import torch.nn as nn +from fairseq import metrics, utils +from fairseq.models import register_model, register_model_architecture +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.models.transformer import ( + DEFAULT_MAX_SOURCE_POSITIONS, + DEFAULT_MAX_TARGET_POSITIONS, + TransformerDecoder, + TransformerEncoder, + TransformerModel, + base_architecture, +) +from torch import Tensor + + +logger = logging.getLogger(__name__) + + +@register_model("transformer_pointer_generator") +class TransformerPointerGeneratorModel(TransformerModel): + """ + Transformer model from `"Attention Is All You Need" (Vaswani et al, 2017) + `_, augmented with a pointer-generator + network from `"Get To The Point: Summarization with Pointer-Generator + Networks" (See et al, 2017) `_. + + Args: + encoder (TransformerPointerGeneratorEncoder): the encoder + decoder (TransformerPointerGeneratorDecoder): the decoder + + The Transformer pointer-generator model provides the following named + architectures and command-line arguments: + + .. argparse:: + :ref: fairseq.models.transformer_pointer_generator_parser + :prog: + """ + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + TransformerModel.add_args(parser) + parser.add_argument('--alignment-heads', type=int, metavar='N', + help='number of attention heads to be used for ' + 'pointing') + parser.add_argument('--alignment-layer', type=int, metavar='I', + help='layer number to be used for pointing (0 ' + 'corresponding to the bottommost layer)') + parser.add_argument('--source-position-markers', type=int, metavar='N', + help='dictionary includes N additional items that ' + 'represent an OOV token at a particular input ' + 'position') + parser.add_argument('--force-generation', type=float, metavar='P', + default=None, + help='set the vocabulary distribution weight to P, ' + 'instead of predicting it from the input (1.0 ' + 'corresponding to generation, 0.0 to pointing)') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if args.encoder_layers_to_keep: + args.encoder_layers = len(args.encoder_layers_to_keep.split(",")) + if args.decoder_layers_to_keep: + args.decoder_layers = len(args.decoder_layers_to_keep.split(",")) + + if getattr(args, "max_source_positions", None) is None: + args.max_source_positions = DEFAULT_MAX_SOURCE_POSITIONS + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = DEFAULT_MAX_TARGET_POSITIONS + if getattr(args, "source_position_markers", None) is None: + args.source_position_markers = args.max_source_positions + + src_dict, tgt_dict = task.source_dictionary, task.target_dictionary + if src_dict != tgt_dict: + raise ValueError("Pointer-generator requires a joined dictionary") + + def build_embedding(dictionary, embed_dim, path=None): + # The dictionary may include additional items that can be used in + # place of the normal OOV token and that all map to the same + # embedding. Using a different token for each input position allows + # one to restore the word identities from the original source text. + num_embeddings = len(dictionary) - args.source_position_markers + padding_idx = dictionary.pad() + unk_idx = dictionary.unk() + logger.info( + "dictionary indices from {0} to {1} will be mapped to {2}".format( + num_embeddings, len(dictionary) - 1, unk_idx + ) + ) + emb = Embedding(num_embeddings, embed_dim, padding_idx, unk_idx) + # if provided, load from preloaded dictionaries + if path: + embed_dict = utils.parse_embedding(path) + utils.load_embedding(embed_dict, dictionary, emb) + return emb + + if args.share_all_embeddings: + if args.encoder_embed_dim != args.decoder_embed_dim: + raise ValueError( + "--share-all-embeddings requires --encoder-embed-dim to match --decoder-embed-dim" + ) + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise ValueError( + "--share-all-embeddings not compatible with --decoder-embed-path" + ) + encoder_embed_tokens = build_embedding( + src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = encoder_embed_tokens + args.share_decoder_input_output_embed = True + else: + encoder_embed_tokens = build_embedding( + src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = build_embedding( + tgt_dict, args.decoder_embed_dim, args.decoder_embed_path + ) + + encoder = cls.build_encoder(args, src_dict, encoder_embed_tokens) + decoder = cls.build_decoder(args, tgt_dict, decoder_embed_tokens) + return cls(args, encoder, decoder) + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerPointerGeneratorEncoder(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerPointerGeneratorDecoder(args, tgt_dict, embed_tokens) + + +class TransformerPointerGeneratorEncoder(TransformerEncoder): + """ + Transformer encoder consisting of *args.encoder_layers* layers. Each layer + is a :class:`TransformerEncoderLayer`. The pointer-generator variant adds + the source tokens to the encoder output as these are otherwise not passed + to the decoder. + """ + + def forward(self, src_tokens, src_lengths, **kwargs): + """ + Runs the `forward()` method of the parent Transformer class. Then adds + the source tokens into the encoder output tuple. + + While it might be more elegant that the model would pass the source + tokens to the `forward()` method of the decoder too, this would require + changes to `SequenceGenerator`. + + Args: + src_tokens (torch.LongTensor): tokens in the source language of + shape `(batch, src_len)` + src_lengths (torch.LongTensor): lengths of each source sentence of + shape `(batch)` + + Returns: + namedtuple: + - **encoder_out** (Tensor): the last encoder layer's output of + shape `(src_len, batch, embed_dim)` + - **encoder_padding_mask** (ByteTensor): the positions of + padding elements of shape `(batch, src_len)` + - **encoder_embedding** (Tensor): the (scaled) embedding lookup + of shape `(batch, src_len, embed_dim)` + - **encoder_states** (List[Tensor]): all intermediate + hidden states of shape `(src_len, batch, embed_dim)`. + Only populated if *return_all_hiddens* is True. + - **src_tokens** (Tensor): input token ids of shape + `(batch, src_len)` + """ + encoder_out = super().forward(src_tokens, src_lengths, **kwargs) + return EncoderOut( + encoder_out=encoder_out.encoder_out, # T x B x C + encoder_padding_mask=encoder_out.encoder_padding_mask, # B x T + encoder_embedding=encoder_out.encoder_embedding, # B x T x C + encoder_states=encoder_out.encoder_states, # List[T x B x C] + src_tokens=src_tokens, # B x T + src_lengths=None, + ) + + +class TransformerPointerGeneratorDecoder(TransformerDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. The pointer-generator variant mixes + the output probabilities with an attention distribution in the output layer. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + """ + + def __init__(self, args, dictionary, embed_tokens): + super().__init__(args, dictionary, embed_tokens, no_encoder_attn=False) + + # In the pointer-generator model these arguments define the decoder + # layer and the number of attention heads that will be averaged to + # create the alignment for pointing. + self.alignment_heads = args.alignment_heads + self.alignment_layer = args.alignment_layer + + input_embed_dim = embed_tokens.embedding_dim + + # Generation probabilities / interpolation coefficients are predicted + # from the current decoder input embedding and the decoder output, which + # is the size of output_embed_dim. + p_gen_input_size = input_embed_dim + self.output_embed_dim + self.project_p_gens = nn.Linear(p_gen_input_size, 1) + nn.init.zeros_(self.project_p_gens.bias) + + # The dictionary may include a separate entry for an OOV token in each + # input position, so that their identity can be restored from the + # original source text. + self.num_types = len(dictionary) + self.num_oov_types = args.source_position_markers + self.num_embeddings = self.num_types - self.num_oov_types + self.force_p_gen = args.force_generation + + def forward( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + features_only: bool = False, + alignment_layer: Optional[int] = 0, + alignment_heads: Optional[int] = 1, + src_lengths: Optional[Any] = None, + return_all_hiddens: bool = False, + ): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (EncoderOut, optional): output from the encoder, used + for encoder-side attention + incremental_state (dict, optional): dictionary used for storing + state during :ref:`Incremental decoding` + features_only (bool, optional): only return features without + applying output layer (default: False) + alignment_layer (int, optional): 0-based index of the layer to be + used for pointing (default: 0) + alignment_heads (int, optional): number of attention heads to be + used for pointing (default: 1) + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + # The normal Transformer model doesn't pass the alignment_layer and + # alignment_heads parameters correctly. We use our local variables. + x, extra = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + incremental_state=incremental_state, + alignment_layer=self.alignment_layer, + alignment_heads=self.alignment_heads, + ) + if not features_only: + # Embedding the tokens again for generation probability prediction, + # so that we don't have to reimplement the whole extract_features() + # method. + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + prev_output_embed = self.embed_tokens(prev_output_tokens) + prev_output_embed *= self.embed_scale + predictors = torch.cat((prev_output_embed, x), 2) + p_gens = self.project_p_gens(predictors) + p_gens = torch.sigmoid(p_gens) + x = self.output_layer(x, extra["attn"][0], encoder_out.src_tokens, p_gens) + return x, extra + + def output_layer(self, features, attn, src_tokens, p_gens, **kwargs): + """ + Project features to the vocabulary size and mix with the attention + distributions. + """ + if self.force_p_gen is not None: + p_gens = self.force_p_gen + + # project back to size of vocabulary + logits = super().output_layer(features, **kwargs) + + batch_size = logits.shape[0] + output_length = logits.shape[1] + assert logits.shape[2] == self.num_embeddings + assert src_tokens.shape[0] == batch_size + src_length = src_tokens.shape[1] + + # The final output distribution will be a mixture of the normal output + # distribution (softmax of logits) and attention weights. + gen_dists = super().get_normalized_probs( + (logits, None), log_probs=False, sample=None + ) + gen_dists = torch.mul(gen_dists, p_gens) + padding_size = (batch_size, output_length, self.num_oov_types) + padding = gen_dists.new_zeros(padding_size) + gen_dists = torch.cat((gen_dists, padding), 2) + assert gen_dists.shape[2] == self.num_types + + # Scatter attention distributions to distributions over the extended + # vocabulary in a tensor of shape [batch_size, output_length, + # vocab_size]. Each attention weight will be written into a location + # that is for other dimensions the same as in the index tensor, but for + # the third dimension it's the value of the index tensor (the token ID). + attn = torch.mul(attn, 1 - p_gens) + index = src_tokens[:, None, :] + index = index.expand(batch_size, output_length, src_length) + attn_dists_size = (batch_size, output_length, self.num_types) + attn_dists = attn.new_zeros(attn_dists_size) + attn_dists.scatter_add_(2, index, attn) + + # Final distributions, [batch_size, output_length, num_types]. + return gen_dists + attn_dists + + def get_normalized_probs(self, net_output, log_probs, sample): + """ + Get normalized probabilities (or log probs) from a net's output. + Pointer-generator network output is already normalized. + """ + probs = net_output[0] + # Make sure the probabilities are greater than zero when returning log + # probabilities. + return probs.clamp(1e-10, 1.0).log() if log_probs else probs + + +class Embedding(nn.Embedding): + r"""A simple lookup table that stores embeddings of a fixed dictionary and size. + This module is often used to store word embeddings and retrieve them using indices. + The input to the module is a list of indices, and the output is the corresponding + word embeddings. This subclass differs from the standard PyTorch Embedding class by + allowing additional vocabulary entries that will be mapped to the unknown token + embedding. + Args: + num_embeddings (int): size of the dictionary of embeddings + embedding_dim (int): the size of each embedding vector + padding_idx (int): Pads the output with the embedding vector at :attr:`padding_idx` + (initialized to zeros) whenever it encounters the index. + unk_idx (int): Maps all token indices that are greater than or equal to + num_embeddings to this index. + Attributes: + weight (Tensor): the learnable weights of the module of shape (num_embeddings, embedding_dim) + initialized from :math:`\mathcal{N}(0, 1)` + Shape: + - Input: :math:`(*)`, LongTensor of arbitrary shape containing the indices to extract + - Output: :math:`(*, H)`, where `*` is the input shape and :math:`H=\text{embedding\_dim}` + .. note:: + Keep in mind that only a limited number of optimizers support + sparse gradients: currently it's :class:`optim.SGD` (`CUDA` and `CPU`), + :class:`optim.SparseAdam` (`CUDA` and `CPU`) and :class:`optim.Adagrad` (`CPU`) + .. note:: + With :attr:`padding_idx` set, the embedding vector at + :attr:`padding_idx` is initialized to all zeros. However, note that this + vector can be modified afterwards, e.g., using a customized + initialization method, and thus changing the vector used to pad the + output. The gradient for this vector from :class:`~torch.nn.Embedding` + is always zero. + """ + __constants__ = ["unk_idx"] + + def __init__(self, num_embeddings, embedding_dim, padding_idx, unk_idx): + super().__init__(num_embeddings, embedding_dim, padding_idx=padding_idx) + self.unk_idx = unk_idx + nn.init.normal_(self.weight, mean=0, std=embedding_dim ** -0.5) + nn.init.constant_(self.weight[padding_idx], 0) + + def forward(self, input): + input = torch.where( + input >= self.num_embeddings, torch.ones_like(input) * self.unk_idx, input + ) + return super().forward(input) + + +@register_model_architecture( + "transformer_pointer_generator", "transformer_pointer_generator" +) +def transformer_pointer_generator(args): + args.alignment_heads = getattr(args, "alignment_heads", 1) + args.alignment_layer = getattr(args, "alignment_layer", -1) + base_architecture(args) + if args.alignment_layer < 0: + args.alignment_layer = args.decoder_layers + args.alignment_layer + + +@register_model_architecture( + "transformer_pointer_generator", "transformer_pointer_generator_iwslt_de_en" +) +def transformer_pointer_generator_iwslt_de_en(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 1024) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.decoder_layers = getattr(args, "decoder_layers", 6) + transformer_pointer_generator(args) + + +@register_model_architecture( + "transformer_pointer_generator", "transformer_pointer_generator_wmt_en_de" +) +def transformer_pointer_generator_wmt_en_de(args): + transformer_pointer_generator(args) + + +# Transformer pointer-generator with the base Transformer parameters as used in +# the "Attention Is All You Need" paper (Vaswani et al., 2017) +@register_model_architecture( + "transformer_pointer_generator", + "transformer_pointer_generator_vaswani_wmt_en_de_big", +) +def transformer_pointer_generator_vaswani_wmt_en_de_big(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.3) + transformer_pointer_generator(args) + + +@register_model_architecture( + "transformer_pointer_generator", + "transformer_pointer_generator_vaswani_wmt_en_fr_big", +) +def transformer_pointer_generator_vaswani_wmt_en_fr_big(args): + args.dropout = getattr(args, "dropout", 0.1) + transformer_pointer_generator_vaswani_wmt_en_de_big(args) + + +@register_model_architecture( + "transformer_pointer_generator", "transformer_pointer_generator_wmt_en_de_big" +) +def transformer_pointer_generator_wmt_en_de_big(args): + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + transformer_pointer_generator_vaswani_wmt_en_de_big(args) + + +# default parameters used in tensor2tensor implementation +@register_model_architecture( + "transformer_pointer_generator", "transformer_pointer_generator_wmt_en_de_big_t2t" +) +def transformer_pointer_generator_wmt_en_de_big_t2t(args): + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.1) + transformer_pointer_generator_vaswani_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/examples/pointer_generator/postprocess.py b/fairseq-tools/fairseq/examples/pointer_generator/postprocess.py new file mode 100644 index 00000000..b213aed8 --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/postprocess.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import re +import sys + + +class OOVIndexError(IndexError): + def __init__(self, pos, source_seq, target_seq): + super(OOVIndexError, self).__init__( + "A tag in the target sequence refers to a position that is " + "outside the source sequence. Most likely there was a mismatch in " + "provided source and target sequences. Otherwise this would mean that " + "the pointing mechanism somehow attended to a position that is past " + "the actual sequence end." + ) + self.source_pos = pos + self.source_seq = source_seq + self.target_seq = target_seq + + +def replace_oovs(source_in, target_in, target_out): + """Replaces tokens in the target text with the corresponding word in + the source text. + """ + + oov_re = re.compile("^$") + + for source_seq, target_seq in zip(source_in, target_in): + target_seq_out = [] + + pos_to_word = source_seq.strip().split() + for token in target_seq.strip().split(): + m = oov_re.match(token) + if m: + pos = int(m.group(1)) + if pos >= len(pos_to_word): + raise OOVIndexError(pos, source_seq, target_seq) + token_out = pos_to_word[pos] + else: + token_out = token + target_seq_out.append(token_out) + target_out.write(" ".join(target_seq_out) + "\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Replaces tokens in target sequences with words from " + "the corresponding position in the source sequence." + ) + parser.add_argument( + "--source", type=str, help="text file with source sequences", required=True + ) + parser.add_argument( + "--target", type=str, help="text file with target sequences", required=True + ) + parser.add_argument( + "--target-out", + type=str, + help="where to write target sequences without " "entries", + required=True, + ) + args = parser.parse_args() + + target_in = ( + open(args.target, "r", encoding="utf-8") if args.target is not None else None + ) + target_out = ( + open(args.target_out, "w", encoding="utf-8") + if args.target_out is not None + else None + ) + with open(args.source, "r", encoding="utf-8") as source_in, open( + args.target, "r", encoding="utf-8" + ) as target_in, open(args.target_out, "w", encoding="utf-8") as target_out: + replace_oovs(source_in, target_in, target_out) + + +if __name__ == "__main__": + try: + main() + except OOVIndexError as e: + print(e, file=sys.stderr) + print("Source sequence:", e.source_seq.strip(), file=sys.stderr) + print("Target sequence:", e.target_seq.strip(), file=sys.stderr) + print( + "Source sequence length:", + len(e.source_seq.strip().split()), + file=sys.stderr, + ) + print("The offending tag points to:", e.source_pos) + sys.exit(2) diff --git a/fairseq-tools/fairseq/examples/pointer_generator/preprocess.py b/fairseq-tools/fairseq/examples/pointer_generator/preprocess.py new file mode 100644 index 00000000..f72ca7d3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/pointer_generator/preprocess.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +from itertools import zip_longest + + +def replace_oovs(source_in, target_in, vocabulary, source_out, target_out): + """Replaces out-of-vocabulary words in source and target text with , + where N in is the position of the word in the source sequence. + """ + + def format_unk(pos): + return "".format(pos) + + if target_in is None: + target_in = [] + + for seq_num, (source_seq, target_seq) in enumerate( + zip_longest(source_in, target_in) + ): + source_seq_out = [] + target_seq_out = [] + + word_to_pos = dict() + for position, token in enumerate(source_seq.strip().split()): + if token in vocabulary: + token_out = token + else: + if token in word_to_pos: + oov_pos = word_to_pos[token] + else: + word_to_pos[token] = position + oov_pos = position + token_out = format_unk(oov_pos) + source_seq_out.append(token_out) + source_out.write(" ".join(source_seq_out) + "\n") + + if target_seq is not None: + for token in target_seq.strip().split(): + if token in word_to_pos: + token_out = format_unk(word_to_pos[token]) + else: + token_out = token + target_seq_out.append(token_out) + if target_out is not None: + target_out.write(" ".join(target_seq_out) + "\n") + + +def main(): + parser = argparse.ArgumentParser( + description="Replaces out-of-vocabulary words in both source and target " + "sequences with tokens that indicate the position of the word " + "in the source sequence." + ) + parser.add_argument( + "--source", type=str, help="text file with source sequences", required=True + ) + parser.add_argument( + "--target", type=str, help="text file with target sequences", default=None + ) + parser.add_argument("--vocab", type=str, help="vocabulary file", required=True) + parser.add_argument( + "--source-out", + type=str, + help="where to write source sequences with entries", + required=True, + ) + parser.add_argument( + "--target-out", + type=str, + help="where to write target sequences with entries", + default=None, + ) + args = parser.parse_args() + + with open(args.vocab, encoding="utf-8") as vocab: + vocabulary = vocab.read().splitlines() + + target_in = ( + open(args.target, "r", encoding="utf-8") if args.target is not None else None + ) + target_out = ( + open(args.target_out, "w", encoding="utf-8") + if args.target_out is not None + else None + ) + with open(args.source, "r", encoding="utf-8") as source_in, open( + args.source_out, "w", encoding="utf-8" + ) as source_out: + replace_oovs(source_in, target_in, vocabulary, source_out, target_out) + if target_in is not None: + target_in.close() + if target_out is not None: + target_out.close() + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/quant_noise/README.md b/fairseq-tools/fairseq/examples/quant_noise/README.md new file mode 100644 index 00000000..057ea620 --- /dev/null +++ b/fairseq-tools/fairseq/examples/quant_noise/README.md @@ -0,0 +1,298 @@ +# Training with Quantization Noise for Extreme Model Compression ({Fan\*, Stock\*} *et al.*, 2020) +This page contains information for how to train and quantize models with Quantization Noise, for both scalar quantization like `int8` and Iterative Product Quantization. +Check out our paper [here](https://arxiv.org/abs/2004.07320). + +Looking for pretrained models? They will be added shortly. +Looking for code to train vision models? We are working on open sourcing our code as part of ClassyVision. Please check back, but note that both the Scalar and Iterative Product Quantization counterparts of the `nn.Conv2d` module are already included in this release. + +**Contents**: +- [Walk through of code](#walk-through-the-code) +- [Reproduce NLP Results](#looking-to-reproduce-the-nlp-results-in-the-paper) +- [Reproduce Vision Results](#looking-to-reproduce-the-vision-results-in-the-paper) + + +## Citation +```bibtex +@article{fan2020training, + title={Training with Quantization Noise for Extreme Model Compression}, + author={Angela Fan* and Pierre Stock* and and Benjamin Graham and Edouard Grave and Remi Gribonval and Herve Jegou and Armand Joulin}, + year={2020}, + eprint={2004.07320}, + archivePrefix={arXiv}, + primaryClass={cs.ML} +} +``` + +## Walk through the code + +Training a model with Quant-Noise improves the performance in subsequent inference-time quantization by training models to be robust to quantization. This technique is useful for both scalar and product quantization methods, as well as multiple domains. We detail below our approach to train, quantize models and integrate our code to quantize your favorite models. + +### Scalar Quantization + +Unlike the section [Iterative Product Quantization](#iterative-product-quantization) which gives state-of-the-art compression, this section showcases the usefulness of our approach for simple scalar quantization baselines such as int8 using on-GPU Fake Quantization. + +#### Training + +Scalar quantization with Quant-Noise consists in randomly quantizing a proportion `p` of the weights during training. Scalar quantization is implemented [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quantization/scalar) under the form of Fake Quantization, meaning that we emulate int8 on GPU by quantizing and de-quantizing both the weights and the activations. We rely on PyTorch's [quantization primitives](https://github.com/pytorch/pytorch/tree/master/torch/quantization). + +To train a model with Quant-Noise, add the following flag: +``` +--quant-noise-scalar 0.5 +``` +Large values of noise make the network easier to quantize but may result in higher non-quantized test and validation perplexities. + +#### Quantization + +When evaluating a network, all quantized modules and activation hooks automatically switch to `p=1` so the validation accuracy reported by Fairseq is actually the quantized one, nothing more to do. + + +#### Integration with your own code + +Looking to quantize your own models with Quant-Noise + Scalar Quantization? +- Use the function `quantize_model_` implemented [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quantization/scalar/utils.py) to (1) replace all your modules by their quantized counterparts and (2) add hooks to those modules to quantize the activations. +- Then, perform your training as usual. Note that in `eval()` mode, the network is always fully quantized (weights and activations) by default (`p=1`). + + + +### Iterative Product Quantization + + +Iterative Product Quantization with Quant-Noise proceeds in two steps. First, a model must be trained uncompressed with Quant-Noise. Second, the model must be quantized with iPQ. Note that we implement here the simplest form of noise, which consists in randomly dropping a proportion `p` of blocks, and that worked as well as assigning those blocks to their current centroid. + +#### Training + +To train a model with Quant-Noise, add the following flags: +``` +--quant-noise-pq 0.1 --quant-noise-pq-block-size 8 +``` +`quant-noise-pq` controls how much dropout is applied to the blocks of the weight matrix. `quant-noise-pq-block-size` controls the size of the weight matrix blocks. +We recommend training with 0.05 to 0.2 Quant-Noise, a value that worked well in our experiments. For the block-size, we recommend training with block-size of 8. Note that the block size must be a multiple of `input_features`, see the size checks [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quant_noise.py). Large block sizes result in higher compression ratio but may induce a loss in accuracy. + +We currently support training Transformer based models, such as sequence-to-sequence, language models, and BERT architectures. The `quant_noise` function [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quant_noise.py) wraps a module. It splits a weight matrix into blocks and applies random dropout to these blocks. +In the Transformer architectures, quant-noise is applied to the input and output embeddings, the attention, and the FFN. + +Quant-Noise can also be combined with **LayerDrop** (see [here](https://github.com/pytorch/fairseq/tree/master/examples/layerdrop)) to add its pruning effect to the quantized model and make the model even smaller. We recommend training with LayerDrop 0.1 or 0.2. + +#### Quantization + +We implement an improved version of product quantization from Stock et al, **iPQ**, described [here](https://arxiv.org/abs/1907.05686), see code with old API [here](https://github.com/facebookresearch/kill-the-bits). Note that we improved the iPQ API in terms of both compute speed and usability as described below. + +For the particular case of PQ, quantization is made sequentially. We recommend first quantizing the FFNs, then the EMBs, and finally the ATTNs. Quantization is done in two sub-steps: +- First, perform `n` steps of Product Quantization (generally `n=20` is enough). +- Then, finetune the obtained centroids. + +#### Integration with your own code + +Looking to quantize your own models with Quant-Noise + iPQ? +- First wrap your modules with the `quant_noise` function [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quant_noise.py), which is module-agnostic and train your favorite model. +- Then, quantize your trained model using the code [here](https://github.com/pytorch/fairseq/tree/master/fairseq/modules/quantization/pq). This can be done *without any changes to your training loop*. Below is an example code for integration. +Note that we tried our approach only on Transformers and various Convolutional Models such as EfficientNets. + +```python +from fairseq.modules.quantization.pq import quantize_model_, SizeTracker + +# get configuration parameters +n_centroids_config = config["n_centroids"] +block_sizes_config = config["block_sizes"] +layers_to_quantize = config["layers_to_quantize"] + +# size tracker for keeping track of assignments, centroids and non-compressed sizes +size_tracker = SizeTracker(model) + +# Quantize model by stages +for step in range(len(layers_to_quantize)): + + # quantize model in-place + quantized_layers = quantize_model_( + model, + size_tracker, + layers_to_quantize, + block_sizes_config, + n_centroids_config, + step=step, + ) + logger.info(f"Finetuning stage {step}, quantized layers: {quantized_layers}") + logger.info(f"{size_tracker}") + + # Don't forget to re-create/update trainer/optimizer since model parameters have changed + optimizer = ... + + # Finetune the centroids with your usual training loop for a few epochs + trainer.train_epoch() +``` + + +## Looking to reproduce the NLP results in the paper? + +We detail below how to reproduce the state-of-the-art results in reported in the paper for Quant-Noise + Iterative Product Quantization. + +### Training with Quant-Noise + +To **train** RoBERTa + QuantNoise, we followed this setting [here](https://github.com/pytorch/fairseq/tree/master/examples/roberta). +The following command can be used to train a RoBERTa Base + QuantNoise model: + +```bash +TOTAL_UPDATES=125000 +WARMUP_UPDATES=10000 +PEAK_LR=0.0005 +TOKENS_PER_SAMPLE=512 +MAX_POSITIONS=512 +MAX_SENTENCES=16 +UPDATE_FREQ=2 +DATA_DIR=/path/to/data/here + +fairseq-train $DATA_DIR \ + --task masked_lm --criterion masked_lm --arch roberta_base \ + --sample-break-mode complete \ + --tokens-per-sample $TOKENS_PER_SAMPLE --max-positions $MAX_POSITIONS \ + --optimizer adam --adam-betas '(0.9, 0.98)' --adam-eps 1e-6 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $PEAK_LR \ + --warmup-updates $WARMUP_UPDATES --total-num-update $TOTAL_UPDATES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.01 \ + --batch-size $MAX_SENTENCES \ + --update-freq $UPDATE_FREQ --max-update $TOTAL_UPDATES \ + --save-dir checkpoint/roberta \ + --ddp-backend no_c10d --encoder-layerdrop 0.2 \ + --quant-noise-pq 0.2 --quant-noise-pq-block-size 8 --untie-weights-roberta +``` + +To **finetune** RoBERTa + QuantNoise, we followed this setting [here](https://github.com/pytorch/fairseq/blob/master/examples/roberta/README.glue.md). +The following command can be used to finetune a RoBERTa Base + QuantNoise model on the RTE dataset: + +```bash +TOTAL_NUM_UPDATES=2036 +WARMUP_UPDATES=122 +LR=2e-05 +NUM_CLASSES=2 +MAX_SENTENCES=16 +ROBERTA_PATH=/path/to/roberta_quantnoise/model.pt + +fairseq-train /path/to/rte/data/ \ + --restore-file $ROBERTA_PATH \ + --max-positions 512 \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --ddp-backend no_c10d \ + --quant-noise-pq 0.2 --quant-noise-pq-block-size 8 +``` + +To **train** Language Models on Wikitext-103, we followed this setting [here](https://github.com/pytorch/fairseq/tree/master/examples/language_model). +The following command can be used to train a Transformer + QuantNoise model on Wikitext-103: + +```bash +fairseq-train --task language_modeling /path/to/wikitext-103/data \ + --save-dir checkpoints/transformer_wikitext-103 \ + --adaptive-input --adaptive-input-cutoff 20000,60000 --adaptive-input-factor 4 \ + --adaptive-softmax-cutoff 20000,60000 --adaptive-softmax-dropout 0.2 --adaptive-softmax-factor 4.0 \ + --tie-adaptive-proj --tie-adaptive-weights \ + --arch transformer_lm_gbw \ + --attention-dropout 0.1 --dropout 0.2 --relu-dropout 0.1 \ + --clip-norm 0.1 --criterion adaptive_loss \ + --ddp-backend no_c10d \ + --decoder-attention-heads 8 --decoder-embed-dim 1024 --decoder-ffn-embed-dim 4096 --decoder-input-dim 1024 \ + --decoder-layers 16 --decoder-normalize-before --decoder-output-dim 1024 \ + --lr 0.0001 --lr-period-updates 270000 --lr-scheduler cosine --lr-shrink 0.75 --max-lr 1.0 --t-mult 2.0 \ + --max-tokens 3072 --tokens-per-sample 3072 --momentum 0.99 --optimizer nag \ + --sample-break-mode none --update-freq 3 \ + --warmup-init-lr 1e-07 --warmup-updates 16000 \ + --weight-decay 0 --seed 1 --min-lr 1e-09 \ + --quant-noise-pq 0.05 --quant-noise-pq-block-size 8 +``` + +To **evaluate** this model, note you need to use the `eval.py` script. The following command can be used to evaluate: + +```bash +fairseq-eval-lm /path/to/wikitext-103/data --path /path/to/model/checkpoint \ + --sample-break-mode complete \ + --max-tokens 3072 \ + --context-window 2560 \ + --softmax-batch 1024 \ + --gen-subset valid +``` +and change the `--gen-subset` to `test` if you would like to evaluate on the test set instead. + + +### Iterative Product Quantization + +To quantize the finetuned RoBERTa model, we use this command on 1 GPU. This should run in a day. +```bash +TOTAL_NUM_UPDATES=6108 # 2036 updates for each iteration +WARMUP_UPDATES=122 +LR=2e-05 +NUM_CLASSES=2 +MAX_SENTENCES=16 +fairseq-train --task sentence_prediction /path/to/data/ \ + --restore-file $ROBERTA_PATH \ + --save-dir checkpoints/roberta_finetuned \ + --max-positions 512 \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 --lr-scheduler polynomial_decay \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --no-progress-bar --skip-invalid-size-inputs-valid-test --ddp-backend no_c10d \ + --quantization-config-path /path/to/config/yaml +``` + +To quantize the trained Language Model, we use this command on 8 V100 23GB GPUs. This should run in a couple of hours. +```bash +fairseq-train --task language_modeling /path/to/wikitext-103/data \ + --save-dir checkpoints/transformer_wikitext-103 \ + --adaptive-input --adaptive-input-cutoff 20000,60000 --adaptive-input-factor 4 \ + --adaptive-softmax-cutoff 20000,60000 --adaptive-softmax-dropout 0.2 --adaptive-softmax-factor 4.0 \ + --arch transformer_lm_gbw \ + --attention-dropout 0.1 --dropout 0.2 --relu-dropout 0.1 \ + --bucket-cap-mb 25 --char-embedder-highway-layers 2 --character-embedding-dim 4 \ + --clip-norm 0.1 --criterion adaptive_loss \ + --ddp-backend no_c10d \ + --decoder-attention-heads 8 --decoder-embed-dim 1024 --decoder-ffn-embed-dim 4096 --decoder-input-dim 1024 --decoder-layers 16 --decoder-normalize-before --decoder-output-dim 1024 \ + --fp16 --keep-last-epochs -1 \ + --lr 0.0001 --lr-period-updates 270000 --lr-scheduler cosine --lr-shrink 0.75 --max-lr 0.05 --min-lr 1e-09 \ + --max-tokens 2944 --tokens-per-sample 2944\ + --momentum 0.99 --no-epoch-checkpoints --no-progress-bar --optimizer nag --required-batch-size-multiple 8 \ + --sample-break-mode none --t-mult 2.0 --skip-invalid-size-inputs-valid-test \ + --tie-adaptive-proj --tie-adaptive-weights --update-freq 3 --weight-decay 0 --seed 1 \ + --log-interval 100 --no-progress-bar --skip-invalid-size-inputs-valid-test \ + --restore-file path/to/trained/lm/with/quant/noise \ + --max-update 13500 --quantization-config-path /path/to/config/yaml +``` +If you have less capacity or if your distributed training freezes, try reducing `--max-tokens` and `--tokens-per-sample` (this may reduce the quantized accuracy a bit). + +### Remarks + +We try to keep the open-sourced code as readable and as easy-to-plug as possible. Therefore, we did not test it for the following cases: +- Scalar quantization with RoBERTa. +- Quantization with iPQ and `int8` combined. + +If you have trouble adapting it, we will be more than happy to help! + +## Looking to reproduce the Vision results in the paper? + +We are working on open sourcing our code as part of ClassyVision. Please check back. + + +## Having an issue or have a question? + +Please open an issue in this repository with the details of your question. Thanks! diff --git a/fairseq-tools/fairseq/examples/quant_noise/transformer_quantization_config.yaml b/fairseq-tools/fairseq/examples/quant_noise/transformer_quantization_config.yaml new file mode 100644 index 00000000..d4be14a9 --- /dev/null +++ b/fairseq-tools/fairseq/examples/quant_noise/transformer_quantization_config.yaml @@ -0,0 +1,33 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This file defines example configuration arguments for quantizing +# a transformer model with product quantization + +# Number of Centroids for Product Quantization, by default 256 (byte-aligned) +n_centroids: + Linear: + key: in_features + value: {"*": 256} + Embedding: + key: embedding_dim + value: {"*": 256} + +# Block Sizes for Product Quantization +# We suggest: 8 for FFN, 4 for ATTN, 4 for embedding projections, 8 for embeddings +block_sizes: + Linear: + key: fuzzy_name + value: {fc: 8, attn: 4, emb: 4} + Embedding: + key: fuzzy_name + value: {emb: 8} + +# Layers to Quantize Sequentially +# We suggest: first FFN, then EMB, then ATTN +layers_to_quantize: + - decoder\\.layers\\.\d+\\.fc[12] + - decoder\\.embed_tokens\\.embeddings\\.[012]\\.[01] + - decoder\\.layers\\.\d+\\.self_attn\\.(k_proj|v_proj|q_proj|out_proj) diff --git a/fairseq-tools/fairseq/examples/roberta/README.custom_classification.md b/fairseq-tools/fairseq/examples/roberta/README.custom_classification.md new file mode 100644 index 00000000..7254bb7d --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/README.custom_classification.md @@ -0,0 +1,168 @@ +# Finetuning RoBERTa on a custom classification task + +This example shows how to finetune RoBERTa on the IMDB dataset, but should illustrate the process for most classification tasks. + +### 1) Get the data + +```bash +wget http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz +tar zxvf aclImdb_v1.tar.gz +``` + + +### 2) Format data + +`IMDB` data has one data-sample in each file, below python code-snippet converts it one file for train and valid each for ease of processing. +```python +import argparse +import os +import random +from glob import glob + +random.seed(0) + +def main(args): + for split in ['train', 'test']: + samples = [] + for class_label in ['pos', 'neg']: + fnames = glob(os.path.join(args.datadir, split, class_label) + '/*.txt') + for fname in fnames: + with open(fname) as fin: + line = fin.readline() + samples.append((line, 1 if class_label == 'pos' else 0)) + random.shuffle(samples) + out_fname = 'train' if split == 'train' else 'dev' + f1 = open(os.path.join(args.datadir, out_fname + '.input0'), 'w') + f2 = open(os.path.join(args.datadir, out_fname + '.label'), 'w') + for sample in samples: + f1.write(sample[0] + '\n') + f2.write(str(sample[1]) + '\n') + f1.close() + f2.close() + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--datadir', default='aclImdb') + args = parser.parse_args() + main(args) +``` + + +### 3) BPE encode + +Run `multiprocessing_bpe_encoder`, you can also do this in previous step for each sample but that might be slower. +```bash +# Download encoder.json and vocab.bpe +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' + +for SPLIT in train dev; do + python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json encoder.json \ + --vocab-bpe vocab.bpe \ + --inputs "aclImdb/$SPLIT.input0" \ + --outputs "aclImdb/$SPLIT.input0.bpe" \ + --workers 60 \ + --keep-empty +done +``` + + +### 4) Preprocess data + +```bash +# Download fairseq dictionary. +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt' + +fairseq-preprocess \ + --only-source \ + --trainpref "aclImdb/train.input0.bpe" \ + --validpref "aclImdb/dev.input0.bpe" \ + --destdir "IMDB-bin/input0" \ + --workers 60 \ + --srcdict dict.txt + +fairseq-preprocess \ + --only-source \ + --trainpref "aclImdb/train.label" \ + --validpref "aclImdb/dev.label" \ + --destdir "IMDB-bin/label" \ + --workers 60 + +``` + + +### 5) Run training + +```bash +TOTAL_NUM_UPDATES=7812 # 10 epochs through IMDB for bsz 32 +WARMUP_UPDATES=469 # 6 percent of the number of updates +LR=1e-05 # Peak LR for polynomial LR scheduler. +HEAD_NAME=imdb_head # Custom name for the classification head. +NUM_CLASSES=2 # Number of classes for the classification task. +MAX_SENTENCES=8 # Batch size. +ROBERTA_PATH=/path/to/roberta.large/model.pt + +CUDA_VISIBLE_DEVICES=0 fairseq-train IMDB-bin/ \ + --restore-file $ROBERTA_PATH \ + --max-positions 512 \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction \ + --classification-head-name $HEAD_NAME \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --shorten-method "truncate" \ + --find-unused-parameters \ + --update-freq 4 +``` + +The above command will finetune RoBERTa-large with an effective batch-size of 32 +sentences (`--batch-size=8 --update-freq=4`). The expected +`best-validation-accuracy` after 10 epochs is ~96.5%. + +If you run out of GPU memory, try decreasing `--batch-size` and increase +`--update-freq` to compensate. + + +### 6) Load model using hub interface + +Now we can load the trained model checkpoint using the RoBERTa hub interface. + +Assuming your checkpoints are stored in `checkpoints/`: +```python +from fairseq.models.roberta import RobertaModel +roberta = RobertaModel.from_pretrained( + 'checkpoints', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='IMDB-bin' +) +roberta.eval() # disable dropout +``` + +Finally you can make predictions using the `imdb_head` (or whatever you set +`--classification-head-name` to during training): +```python +label_fn = lambda label: roberta.task.label_dictionary.string( + [label + roberta.task.label_dictionary.nspecial] +) + +tokens = roberta.encode('Best movie this year') +pred = label_fn(roberta.predict('imdb_head', tokens).argmax().item()) +assert pred == '1' # positive + +tokens = roberta.encode('Worst movie ever') +pred = label_fn(roberta.predict('imdb_head', tokens).argmax().item()) +assert pred == '0' # negative +``` diff --git a/fairseq-tools/fairseq/examples/roberta/README.glue.md b/fairseq-tools/fairseq/examples/roberta/README.glue.md new file mode 100644 index 00000000..77015d2e --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/README.glue.md @@ -0,0 +1,99 @@ +# Finetuning RoBERTa on GLUE tasks + +### 1) Download the data from GLUE website (https://gluebenchmark.com/tasks) using following commands: +```bash +wget https://gist.githubusercontent.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e/raw/17b8dd0d724281ed7c3b2aeeda662b92809aadd5/download_glue_data.py +python download_glue_data.py --data_dir glue_data --tasks all +``` + +### 2) Preprocess GLUE task data: +```bash +./examples/roberta/preprocess_GLUE_tasks.sh glue_data +``` +`glue_task_name` is one of the following: +`{ALL, QQP, MNLI, QNLI, MRPC, RTE, STS-B, SST-2, CoLA}` +Use `ALL` for preprocessing all the glue tasks. + +### 3) Fine-tuning on GLUE task: +Example fine-tuning cmd for `RTE` task +```bash +TOTAL_NUM_UPDATES=2036 # 10 epochs through RTE for bsz 16 +WARMUP_UPDATES=122 # 6 percent of the number of updates +LR=2e-05 # Peak LR for polynomial LR scheduler. +NUM_CLASSES=2 +MAX_SENTENCES=16 # Batch size. +ROBERTA_PATH=/path/to/roberta/model.pt + +CUDA_VISIBLE_DEVICES=0 fairseq-train RTE-bin/ \ + --restore-file $ROBERTA_PATH \ + --max-positions 512 \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric; +``` + +For each of the GLUE task, you will need to use following cmd-line arguments: + +Model | MNLI | QNLI | QQP | RTE | SST-2 | MRPC | CoLA | STS-B +---|---|---|---|---|---|---|---|--- +`--num-classes` | 3 | 2 | 2 | 2 | 2 | 2 | 2 | 1 +`--lr` | 1e-5 | 1e-5 | 1e-5 | 2e-5 | 1e-5 | 1e-5 | 1e-5 | 2e-5 +`--batch-size` | 32 | 32 | 32 | 16 | 32 | 16 | 16 | 16 +`--total-num-update` | 123873 | 33112 | 113272 | 2036 | 20935 | 2296 | 5336 | 3598 +`--warmup-updates` | 7432 | 1986 | 28318 | 122 | 1256 | 137 | 320 | 214 + +For `STS-B` additionally add `--regression-target --best-checkpoint-metric loss` and remove `--maximize-best-checkpoint-metric`. + +**Note:** + +a) `--total-num-updates` is used by `--polynomial_decay` scheduler and is calculated for `--max-epoch=10` and `--batch-size=16/32` depending on the task. + +b) Above cmd-args and hyperparams are tested on one Nvidia `V100` GPU with `32gb` of memory for each task. Depending on the GPU memory resources available to you, you can use increase `--update-freq` and reduce `--batch-size`. + +c) All the settings in above table are suggested settings based on our hyperparam search within a fixed search space (for careful comparison across models). You might be able to find better metrics with wider hyperparam search. + +### Inference on GLUE task +After training the model as mentioned in previous step, you can perform inference with checkpoints in `checkpoints/` directory using following python code snippet: + +```python +from fairseq.models.roberta import RobertaModel + +roberta = RobertaModel.from_pretrained( + 'checkpoints/', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='RTE-bin' +) + +label_fn = lambda label: roberta.task.label_dictionary.string( + [label + roberta.task.label_dictionary.nspecial] +) +ncorrect, nsamples = 0, 0 +roberta.cuda() +roberta.eval() +with open('glue_data/RTE/dev.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[1], tokens[2], tokens[3] + tokens = roberta.encode(sent1, sent2) + prediction = roberta.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_fn(prediction) + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) + +``` diff --git a/fairseq-tools/fairseq/examples/roberta/README.md b/fairseq-tools/fairseq/examples/roberta/README.md new file mode 100644 index 00000000..fdddd5b8 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/README.md @@ -0,0 +1,296 @@ +# RoBERTa: A Robustly Optimized BERT Pretraining Approach + +https://arxiv.org/abs/1907.11692 + +## Introduction + +RoBERTa iterates on BERT's pretraining procedure, including training the model longer, with bigger batches over more data; removing the next sentence prediction objective; training on longer sequences; and dynamically changing the masking pattern applied to the training data. See the associated paper for more details. + +### What's New: + +- January 2020: Italian model (UmBERTo) is available from Musixmatch Research: [UmBERTo](https://github.com/musixmatchresearch/umberto). +- November 2019: French model (CamemBERT) is available: [CamemBERT](https://github.com/pytorch/fairseq/tree/master/examples/camembert). +- November 2019: Multilingual encoder (XLM-RoBERTa) is available: [XLM-R](https://github.com/pytorch/fairseq/tree/master/examples/xlmr). +- September 2019: TensorFlow and TPU support via the [transformers library](https://github.com/huggingface/transformers). +- August 2019: RoBERTa is now supported in the [pytorch-transformers library](https://github.com/huggingface/pytorch-transformers). +- August 2019: Added [tutorial for finetuning on WinoGrande](https://github.com/pytorch/fairseq/tree/master/examples/roberta/wsc#roberta-training-on-winogrande-dataset). +- August 2019: Added [tutorial for pretraining RoBERTa using your own data](README.pretraining.md). + +## Pre-trained models + +Model | Description | # params | Download +---|---|---|--- +`roberta.base` | RoBERTa using the BERT-base architecture | 125M | [roberta.base.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta.base.tar.gz) +`roberta.large` | RoBERTa using the BERT-large architecture | 355M | [roberta.large.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta.large.tar.gz) +`roberta.large.mnli` | `roberta.large` finetuned on [MNLI](http://www.nyu.edu/projects/bowman/multinli) | 355M | [roberta.large.mnli.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta.large.mnli.tar.gz) +`roberta.large.wsc` | `roberta.large` finetuned on [WSC](wsc/README.md) | 355M | [roberta.large.wsc.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/roberta.large.wsc.tar.gz) + +## Results + +**[GLUE (Wang et al., 2019)](https://gluebenchmark.com/)** +_(dev set, single model, single-task finetuning)_ + +Model | MNLI | QNLI | QQP | RTE | SST-2 | MRPC | CoLA | STS-B +---|---|---|---|---|---|---|---|--- +`roberta.base` | 87.6 | 92.8 | 91.9 | 78.7 | 94.8 | 90.2 | 63.6 | 91.2 +`roberta.large` | 90.2 | 94.7 | 92.2 | 86.6 | 96.4 | 90.9 | 68.0 | 92.4 +`roberta.large.mnli` | 90.2 | - | - | - | - | - | - | - + +**[SuperGLUE (Wang et al., 2019)](https://super.gluebenchmark.com/)** +_(dev set, single model, single-task finetuning)_ + +Model | BoolQ | CB | COPA | MultiRC | RTE | WiC | WSC +---|---|---|---|---|---|---|--- +`roberta.large` | 86.9 | 98.2 | 94.0 | 85.7 | 89.5 | 75.6 | - +`roberta.large.wsc` | - | - | - | - | - | - | 91.3 + +**[SQuAD (Rajpurkar et al., 2018)](https://rajpurkar.github.io/SQuAD-explorer/)** +_(dev set, no additional data used)_ + +Model | SQuAD 1.1 EM/F1 | SQuAD 2.0 EM/F1 +---|---|--- +`roberta.large` | 88.9/94.6 | 86.5/89.4 + +**[RACE (Lai et al., 2017)](http://www.qizhexie.com/data/RACE_leaderboard.html)** +_(test set)_ + +Model | Accuracy | Middle | High +---|---|---|--- +`roberta.large` | 83.2 | 86.5 | 81.3 + +**[HellaSwag (Zellers et al., 2019)](https://rowanzellers.com/hellaswag/)** +_(test set)_ + +Model | Overall | In-domain | Zero-shot | ActivityNet | WikiHow +---|---|---|---|---|--- +`roberta.large` | 85.2 | 87.3 | 83.1 | 74.6 | 90.9 + +**[Commonsense QA (Talmor et al., 2019)](https://www.tau-nlp.org/commonsenseqa)** +_(test set)_ + +Model | Accuracy +---|--- +`roberta.large` (single model) | 72.1 +`roberta.large` (ensemble) | 72.5 + +**[Winogrande (Sakaguchi et al., 2019)](https://arxiv.org/abs/1907.10641)** +_(test set)_ + +Model | Accuracy +---|--- +`roberta.large` | 78.1 + +**[XNLI (Conneau et al., 2018)](https://arxiv.org/abs/1809.05053)** +_(TRANSLATE-TEST)_ + +Model | en | fr | es | de | el | bg | ru | tr | ar | vi | th | zh | hi | sw | ur +---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--- +`roberta.large.mnli` | 91.3 | 82.91 | 84.27 | 81.24 | 81.74 | 83.13 | 78.28 | 76.79 | 76.64 | 74.17 | 74.05 | 77.5 | 70.9 | 66.65 | 66.81 + +## Example usage + +##### Load RoBERTa from torch.hub (PyTorch >= 1.1): +```python +import torch +roberta = torch.hub.load('pytorch/fairseq', 'roberta.large') +roberta.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Load RoBERTa (for PyTorch 1.0 or custom models): +```python +# Download roberta.large model +wget https://dl.fbaipublicfiles.com/fairseq/models/roberta.large.tar.gz +tar -xzvf roberta.large.tar.gz + +# Load the model in fairseq +from fairseq.models.roberta import RobertaModel +roberta = RobertaModel.from_pretrained('/path/to/roberta.large', checkpoint_file='model.pt') +roberta.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Apply Byte-Pair Encoding (BPE) to input text: +```python +tokens = roberta.encode('Hello world!') +assert tokens.tolist() == [0, 31414, 232, 328, 2] +roberta.decode(tokens) # 'Hello world!' +``` + +##### Extract features from RoBERTa: +```python +# Extract the last layer's features +last_layer_features = roberta.extract_features(tokens) +assert last_layer_features.size() == torch.Size([1, 5, 1024]) + +# Extract all layer's features (layer 0 is the embedding layer) +all_layers = roberta.extract_features(tokens, return_all_hiddens=True) +assert len(all_layers) == 25 +assert torch.all(all_layers[-1] == last_layer_features) +``` + +##### Use RoBERTa for sentence-pair classification tasks: +```python +# Download RoBERTa already finetuned for MNLI +roberta = torch.hub.load('pytorch/fairseq', 'roberta.large.mnli') +roberta.eval() # disable dropout for evaluation + +# Encode a pair of sentences and make a prediction +tokens = roberta.encode('Roberta is a heavily optimized version of BERT.', 'Roberta is not very optimized.') +roberta.predict('mnli', tokens).argmax() # 0: contradiction + +# Encode another pair of sentences +tokens = roberta.encode('Roberta is a heavily optimized version of BERT.', 'Roberta is based on BERT.') +roberta.predict('mnli', tokens).argmax() # 2: entailment +``` + +##### Register a new (randomly initialized) classification head: +```python +roberta.register_classification_head('new_task', num_classes=3) +logprobs = roberta.predict('new_task', tokens) # tensor([[-1.1050, -1.0672, -1.1245]], grad_fn=) +``` + +##### Batched prediction: +```python +import torch +from fairseq.data.data_utils import collate_tokens + +roberta = torch.hub.load('pytorch/fairseq', 'roberta.large.mnli') +roberta.eval() + +batch_of_pairs = [ + ['Roberta is a heavily optimized version of BERT.', 'Roberta is not very optimized.'], + ['Roberta is a heavily optimized version of BERT.', 'Roberta is based on BERT.'], + ['potatoes are awesome.', 'I like to run.'], + ['Mars is very far from earth.', 'Mars is very close.'], +] + +batch = collate_tokens( + [roberta.encode(pair[0], pair[1]) for pair in batch_of_pairs], pad_idx=1 +) + +logprobs = roberta.predict('mnli', batch) +print(logprobs.argmax(dim=1)) +# tensor([0, 2, 1, 0]) +``` + +##### Using the GPU: +```python +roberta.cuda() +roberta.predict('new_task', tokens) # tensor([[-1.1050, -1.0672, -1.1245]], device='cuda:0', grad_fn=) +``` + +## Advanced usage + +#### Filling masks: + +RoBERTa can be used to fill `` tokens in the input. Some examples from the +[Natural Questions dataset](https://ai.google.com/research/NaturalQuestions/): +```python +roberta.fill_mask('The first Star wars movie came out in ', topk=3) +# [('The first Star wars movie came out in 1977', 0.9504708051681519, ' 1977'), ('The first Star wars movie came out in 1978', 0.009986862540245056, ' 1978'), ('The first Star wars movie came out in 1979', 0.009574787691235542, ' 1979')] + +roberta.fill_mask('Vikram samvat calender is official in ', topk=3) +# [('Vikram samvat calender is official in India', 0.21878819167613983, ' India'), ('Vikram samvat calender is official in Delhi', 0.08547237515449524, ' Delhi'), ('Vikram samvat calender is official in Gujarat', 0.07556215673685074, ' Gujarat')] + +roberta.fill_mask(' is the common currency of the European Union', topk=3) +# [('Euro is the common currency of the European Union', 0.9456493854522705, 'Euro'), ('euro is the common currency of the European Union', 0.025748178362846375, 'euro'), ('€ is the common currency of the European Union', 0.011183084920048714, '€')] +``` + +#### Pronoun disambiguation (Winograd Schema Challenge): + +RoBERTa can be used to disambiguate pronouns. First install spaCy and download the English-language model: +```bash +pip install spacy +python -m spacy download en_core_web_lg +``` + +Next load the `roberta.large.wsc` model and call the `disambiguate_pronoun` +function. The pronoun should be surrounded by square brackets (`[]`) and the +query referent surrounded by underscores (`_`), or left blank to return the +predicted candidate text directly: +```python +roberta = torch.hub.load('pytorch/fairseq', 'roberta.large.wsc', user_dir='examples/roberta/wsc') +roberta.cuda() # use the GPU (optional) + +roberta.disambiguate_pronoun('The _trophy_ would not fit in the brown suitcase because [it] was too big.') +# True +roberta.disambiguate_pronoun('The trophy would not fit in the brown _suitcase_ because [it] was too big.') +# False + +roberta.disambiguate_pronoun('The city councilmen refused the demonstrators a permit because [they] feared violence.') +# 'The city councilmen' +roberta.disambiguate_pronoun('The city councilmen refused the demonstrators a permit because [they] advocated violence.') +# 'demonstrators' +``` + +See the [RoBERTA Winograd Schema Challenge (WSC) README](wsc/README.md) for more details on how to train this model. + +#### Extract features aligned to words: + +By default RoBERTa outputs one feature vector per BPE token. You can instead +realign the features to match [spaCy's word-level tokenization](https://spacy.io/usage/linguistic-features#tokenization) +with the `extract_features_aligned_to_words` method. This will compute a +weighted average of the BPE-level features for each word and expose them in +spaCy's `Token.vector` attribute: +```python +doc = roberta.extract_features_aligned_to_words('I said, "hello RoBERTa."') +assert len(doc) == 10 +for tok in doc: + print('{:10}{} (...)'.format(str(tok), tok.vector[:5])) +# tensor([-0.1316, -0.0386, -0.0832, -0.0477, 0.1943], grad_fn=) (...) +# I tensor([ 0.0559, 0.1541, -0.4832, 0.0880, 0.0120], grad_fn=) (...) +# said tensor([-0.1565, -0.0069, -0.8915, 0.0501, -0.0647], grad_fn=) (...) +# , tensor([-0.1318, -0.0387, -0.0834, -0.0477, 0.1944], grad_fn=) (...) +# " tensor([-0.0486, 0.1818, -0.3946, -0.0553, 0.0981], grad_fn=) (...) +# hello tensor([ 0.0079, 0.1799, -0.6204, -0.0777, -0.0923], grad_fn=) (...) +# RoBERTa tensor([-0.2339, -0.1184, -0.7343, -0.0492, 0.5829], grad_fn=) (...) +# . tensor([-0.1341, -0.1203, -0.1012, -0.0621, 0.1892], grad_fn=) (...) +# " tensor([-0.1341, -0.1203, -0.1012, -0.0621, 0.1892], grad_fn=) (...) +# tensor([-0.0930, -0.0392, -0.0821, 0.0158, 0.0649], grad_fn=) (...) +``` + +#### Evaluating the `roberta.large.mnli` model: + +Example python code snippet to evaluate accuracy on the MNLI `dev_matched` set. +```python +label_map = {0: 'contradiction', 1: 'neutral', 2: 'entailment'} +ncorrect, nsamples = 0, 0 +roberta.cuda() +roberta.eval() +with open('glue_data/MNLI/dev_matched.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[8], tokens[9], tokens[-1] + tokens = roberta.encode(sent1, sent2) + prediction = roberta.predict('mnli', tokens).argmax().item() + prediction_label = label_map[prediction] + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) +# Expected output: 0.9060 +``` + +## Finetuning + +- [Finetuning on GLUE](README.glue.md) +- [Finetuning on custom classification tasks (e.g., IMDB)](README.custom_classification.md) +- [Finetuning on Winograd Schema Challenge (WSC)](wsc/README.md) +- [Finetuning on Commonsense QA (CQA)](commonsense_qa/README.md) +- Finetuning on SQuAD: coming soon + +## Pretraining using your own data + +See the [tutorial for pretraining RoBERTa using your own data](README.pretraining.md). + +## Citation + +```bibtex +@article{liu2019roberta, + title = {RoBERTa: A Robustly Optimized BERT Pretraining Approach}, + author = {Yinhan Liu and Myle Ott and Naman Goyal and Jingfei Du and + Mandar Joshi and Danqi Chen and Omer Levy and Mike Lewis and + Luke Zettlemoyer and Veselin Stoyanov}, + journal={arXiv preprint arXiv:1907.11692}, + year = {2019}, +} +``` diff --git a/fairseq-tools/fairseq/examples/roberta/README.pretraining.md b/fairseq-tools/fairseq/examples/roberta/README.pretraining.md new file mode 100644 index 00000000..8b6e10c0 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/README.pretraining.md @@ -0,0 +1,98 @@ +# Pretraining RoBERTa using your own data + +This tutorial will walk you through pretraining RoBERTa over your own data. + +### 1) Preprocess the data + +Data should be preprocessed following the [language modeling format](/examples/language_model), i.e. each document should be separated by an empty line (only useful with `--sample-break-mode complete_doc`). Lines will be concatenated as a 1D text stream during training. + +We'll use the [WikiText-103 dataset](https://www.salesforce.com/products/einstein/ai-research/the-wikitext-dependency-language-modeling-dataset/) +to demonstrate how to preprocess raw text data with the GPT-2 BPE. Of course +this dataset is quite small, so the resulting pretrained model will perform +poorly, but it gives the general idea. + +First download the dataset: +```bash +wget https://s3.amazonaws.com/research.metamind.io/wikitext/wikitext-103-raw-v1.zip +unzip wikitext-103-raw-v1.zip +``` + +Next encode it with the GPT-2 BPE: +```bash +mkdir -p gpt2_bpe +wget -O gpt2_bpe/encoder.json https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json +wget -O gpt2_bpe/vocab.bpe https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe +for SPLIT in train valid test; do \ + python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json gpt2_bpe/encoder.json \ + --vocab-bpe gpt2_bpe/vocab.bpe \ + --inputs wikitext-103-raw/wiki.${SPLIT}.raw \ + --outputs wikitext-103-raw/wiki.${SPLIT}.bpe \ + --keep-empty \ + --workers 60; \ +done +``` + +Finally preprocess/binarize the data using the GPT-2 fairseq dictionary: +```bash +wget -O gpt2_bpe/dict.txt https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt +fairseq-preprocess \ + --only-source \ + --srcdict gpt2_bpe/dict.txt \ + --trainpref wikitext-103-raw/wiki.train.bpe \ + --validpref wikitext-103-raw/wiki.valid.bpe \ + --testpref wikitext-103-raw/wiki.test.bpe \ + --destdir data-bin/wikitext-103 \ + --workers 60 +``` + +### 2) Train RoBERTa base +```bash +TOTAL_UPDATES=125000 # Total number of training steps +WARMUP_UPDATES=10000 # Warmup the learning rate over this many updates +PEAK_LR=0.0005 # Peak learning rate, adjust as needed +TOKENS_PER_SAMPLE=512 # Max sequence length +MAX_POSITIONS=512 # Num. positional embeddings (usually same as above) +MAX_SENTENCES=16 # Number of sequences per batch (batch size) +UPDATE_FREQ=16 # Increase the batch size 16x + +DATA_DIR=data-bin/wikitext-103 + +fairseq-train --fp16 $DATA_DIR \ + --task masked_lm --criterion masked_lm \ + --arch roberta_base --sample-break-mode complete --tokens-per-sample $TOKENS_PER_SAMPLE \ + --optimizer adam --adam-betas '(0.9,0.98)' --adam-eps 1e-6 --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $PEAK_LR --warmup-updates $WARMUP_UPDATES --total-num-update $TOTAL_UPDATES \ + --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ + --batch-size $MAX_SENTENCES --update-freq $UPDATE_FREQ \ + --max-update $TOTAL_UPDATES --log-format simple --log-interval 1 +``` + +**Note:** You can optionally resume training the released RoBERTa base model by +adding `--restore-file /path/to/roberta.base/model.pt`. + +**Note:** The above command assumes training on 8x32GB V100 GPUs. Each GPU uses +a batch size of 16 sequences (`$MAX_SENTENCES`) and accumulates gradients to +further increase the batch size by 16x (`$UPDATE_FREQ`), for a total batch size +of 2048 sequences. If you have fewer GPUs or GPUs with less memory you may need +to reduce `$MAX_SENTENCES` and increase `$UPDATE_FREQ` to compensate. +Alternatively if you have more GPUs you can decrease `$UPDATE_FREQ` accordingly +to increase training speed. + +**Note:** The learning rate and batch size are tightly connected and need to be +adjusted together. We generally recommend increasing the learning rate as you +increase the batch size according to the following table (although it's also +dataset dependent, so don't rely on the following values too closely): + +batch size | peak learning rate +---|--- +256 | 0.0001 +2048 | 0.0005 +8192 | 0.0007 + +### 3) Load your pretrained model +```python +from fairseq.models.roberta import RobertaModel +roberta = RobertaModel.from_pretrained('checkpoints', 'checkpoint_best.pt', 'path/to/data') +assert isinstance(roberta.model, torch.nn.Module) +``` diff --git a/fairseq-tools/fairseq/examples/roberta/README.race.md b/fairseq-tools/fairseq/examples/roberta/README.race.md new file mode 100644 index 00000000..527a0bce --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/README.race.md @@ -0,0 +1,68 @@ +# Finetuning RoBERTa on RACE tasks + +### 1) Download the data from RACE website (http://www.cs.cmu.edu/~glai1/data/race/) + +### 2) Preprocess RACE data: +```bash +python ./examples/roberta/preprocess_RACE.py --input-dir --output-dir +./examples/roberta/preprocess_RACE.sh +``` + +### 3) Fine-tuning on RACE: + +```bash +MAX_EPOCH=5 # Number of training epochs. +LR=1e-05 # Peak LR for fixed LR scheduler. +NUM_CLASSES=4 +MAX_SENTENCES=1 # Batch size per GPU. +UPDATE_FREQ=8 # Accumulate gradients to simulate training on 8 GPUs. +DATA_DIR=/path/to/race-output-dir +ROBERTA_PATH=/path/to/roberta/model.pt + +CUDA_VISIBLE_DEVICES=0,1 fairseq-train $DATA_DIR --ddp-backend=no_c10d \ + --restore-file $ROBERTA_PATH \ + --reset-optimizer --reset-dataloader --reset-meters \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --task sentence_ranking \ + --num-classes $NUM_CLASSES \ + --init-token 0 --separator-token 2 \ + --max-option-length 128 \ + --max-positions 512 \ + --shorten-method "truncate" \ + --arch roberta_large \ + --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ + --criterion sentence_ranking \ + --optimizer adam --adam-betas '(0.9, 0.98)' --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler fixed --lr $LR \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --batch-size $MAX_SENTENCES \ + --required-batch-size-multiple 1 \ + --update-freq $UPDATE_FREQ \ + --max-epoch $MAX_EPOCH +``` + +**Note:** + +a) As contexts in RACE are relatively long, we are using smaller batch size per GPU while increasing update-freq to achieve larger effective batch size. + +b) Above cmd-args and hyperparams are tested on one Nvidia `V100` GPU with `32gb` of memory for each task. Depending on the GPU memory resources available to you, you can use increase `--update-freq` and reduce `--batch-size`. + +c) The setting in above command is based on our hyperparam search within a fixed search space (for careful comparison across models). You might be able to find better metrics with wider hyperparam search. + +### 4) Evaluation: + +``` +DATA_DIR=/path/to/race-output-dir # data directory used during training +MODEL_PATH=/path/to/checkpoint_best.pt # path to the finetuned model checkpoint +PREDS_OUT=preds.tsv # output file path to save prediction +TEST_SPLIT=test # can be test (Middle) or test1 (High) +fairseq-validate \ + $DATA_DIR \ + --valid-subset $TEST_SPLIT \ + --path $MODEL_PATH \ + --batch-size 1 \ + --task sentence_ranking \ + --criterion sentence_ranking \ + --save-predictions $PREDS_OUT +``` diff --git a/fairseq-tools/fairseq/examples/roberta/commonsense_qa/README.md b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/README.md new file mode 100644 index 00000000..4f371f8b --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/README.md @@ -0,0 +1,99 @@ +# Finetuning RoBERTa on Commonsense QA + +We follow a similar approach to [finetuning RACE](../README.race.md). Specifically +for each question we construct five inputs, one for each of the five candidate +answer choices. Each input is constructed by concatenating the question and +candidate answer. We then encode each input and pass the resulting "[CLS]" +representations through a fully-connected layer to predict the correct answer. +We train with a standard cross-entropy loss. + +We also found it helpful to prepend a prefix of `Q:` to the question and `A:` to +the answer. The complete input format is: +``` + Q: Where would I not want a fox? A: hen house
+``` + +Our final submission is based on a hyperparameter search over the learning rate +(1e-5, 2e-5, 3e-5), batch size (8, 16), number of training steps (2000, 3000, +4000) and random seed. We selected the model with the best performance on the +development set after 100 trials. + +### 1) Download data from the Commonsense QA website (https://www.tau-nlp.org/commonsenseqa) +```bash +bash examples/roberta/commonsense_qa/download_cqa_data.sh +``` + +### 2) Finetune + +```bash +MAX_UPDATES=3000 # Number of training steps. +WARMUP_UPDATES=150 # Linearly increase LR over this many steps. +LR=1e-05 # Peak LR for polynomial LR scheduler. +MAX_SENTENCES=16 # Batch size. +SEED=1 # Random seed. +ROBERTA_PATH=/path/to/roberta/model.pt +DATA_DIR=data/CommonsenseQA + +# we use the --user-dir option to load the task from +# the examples/roberta/commonsense_qa directory: +FAIRSEQ_PATH=/path/to/fairseq +FAIRSEQ_USER_DIR=${FAIRSEQ_PATH}/examples/roberta/commonsense_qa + +CUDA_VISIBLE_DEVICES=0 fairseq-train --fp16 --ddp-backend=no_c10d \ + $DATA_DIR \ + --user-dir $FAIRSEQ_USER_DIR \ + --restore-file $ROBERTA_PATH \ + --reset-optimizer --reset-dataloader --reset-meters \ + --no-epoch-checkpoints --no-last-checkpoints --no-save-optimizer-state \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --task commonsense_qa --init-token 0 --bpe gpt2 \ + --arch roberta_large --max-positions 512 \ + --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ + --criterion sentence_ranking --num-classes 5 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --adam-eps 1e-06 --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR \ + --warmup-updates $WARMUP_UPDATES --total-num-update $MAX_UPDATES \ + --batch-size $MAX_SENTENCES \ + --max-update $MAX_UPDATES \ + --log-format simple --log-interval 25 \ + --seed $SEED +``` + +The above command assumes training on 1 GPU with 32GB of RAM. For GPUs with +less memory, decrease `--batch-size` and increase `--update-freq` +accordingly to compensate. + +### 3) Evaluate +```python +import json +import torch +from fairseq.models.roberta import RobertaModel +from examples.roberta import commonsense_qa # load the Commonsense QA task +roberta = RobertaModel.from_pretrained('checkpoints', 'checkpoint_best.pt', 'data/CommonsenseQA') +roberta.eval() # disable dropout +roberta.cuda() # use the GPU (optional) +nsamples, ncorrect = 0, 0 +with open('data/CommonsenseQA/valid.jsonl') as h: + for line in h: + example = json.loads(line) + scores = [] + for choice in example['question']['choices']: + input = roberta.encode( + 'Q: ' + example['question']['stem'], + 'A: ' + choice['text'], + no_separator=True + ) + score = roberta.predict('sentence_classification_head', input, return_logits=True) + scores.append(score) + pred = torch.cat(scores).argmax() + answer = ord(example['answerKey']) - ord('A') + nsamples += 1 + if pred == answer: + ncorrect += 1 + +print('Accuracy: ' + str(ncorrect / float(nsamples))) +# Accuracy: 0.7846027846027847 +``` + +The above snippet is not batched, which makes it quite slow. See [instructions +for batched prediction with RoBERTa](https://github.com/pytorch/fairseq/tree/master/examples/roberta#batched-prediction). diff --git a/fairseq-tools/fairseq/examples/roberta/commonsense_qa/__init__.py b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/__init__.py new file mode 100644 index 00000000..42d21f35 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import commonsense_qa_task # noqa diff --git a/fairseq-tools/fairseq/examples/roberta/commonsense_qa/commonsense_qa_task.py b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/commonsense_qa_task.py new file mode 100644 index 00000000..216093f7 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/commonsense_qa_task.py @@ -0,0 +1,190 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +import os + +import numpy as np +import torch +from fairseq.data import ( + Dictionary, + IdDataset, + ListDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + RawLabelDataset, + RightPadDataset, + SortDataset, + data_utils, + encoders, +) +from fairseq.tasks import LegacyFairseqTask, register_task + + +@register_task("commonsense_qa") +class CommonsenseQATask(LegacyFairseqTask): + """Task to finetune RoBERTa for Commonsense QA.""" + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", metavar="DIR", help="path to data directory; we load .jsonl" + ) + parser.add_argument( + "--init-token", + type=int, + default=None, + help="add token at the beginning of each batch item", + ) + parser.add_argument("--num-classes", type=int, default=5) + + def __init__(self, args, vocab): + super().__init__(args) + self.vocab = vocab + self.mask = vocab.add_symbol("") + + self.bpe = encoders.build_bpe(args) + + @classmethod + def load_dictionary(cls, filename): + """Load the dictionary from the filename + + Args: + filename (str): the filename + """ + dictionary = Dictionary.load(filename) + dictionary.add_symbol("") + return dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + assert ( + args.criterion == "sentence_ranking" + ), "Must set --criterion=sentence_ranking" + + # load data and label dictionaries + vocab = cls.load_dictionary(os.path.join(args.data, "dict.txt")) + print("| dictionary: {} types".format(len(vocab))) + + return cls(args, vocab) + + def load_dataset( + self, split, epoch=1, combine=False, data_path=None, return_only=False, **kwargs + ): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + + def binarize(s, append_bos=False): + if self.bpe is not None: + s = self.bpe.encode(s) + tokens = self.vocab.encode_line( + s, + append_eos=True, + add_if_not_exist=False, + ).long() + if append_bos and self.args.init_token is not None: + tokens = torch.cat([tokens.new([self.args.init_token]), tokens]) + return tokens + + if data_path is None: + data_path = os.path.join(self.args.data, split + ".jsonl") + if not os.path.exists(data_path): + raise FileNotFoundError("Cannot find data: {}".format(data_path)) + + src_tokens = [[] for i in range(self.args.num_classes)] + src_lengths = [[] for i in range(self.args.num_classes)] + labels = [] + + with open(data_path) as h: + for line in h: + example = json.loads(line.strip()) + if "answerKey" in example: + label = ord(example["answerKey"]) - ord("A") + labels.append(label) + question = example["question"]["stem"] + assert len(example["question"]["choices"]) == self.args.num_classes + # format: ` Q: Where would I not want a fox? A: hen house
` + question = "Q: " + question + question_toks = binarize(question, append_bos=True) + for i, choice in enumerate(example["question"]["choices"]): + src = "A: " + choice["text"] + src_bin = torch.cat([question_toks, binarize(src)]) + src_tokens[i].append(src_bin) + src_lengths[i].append(len(src_bin)) + assert all( + len(src_tokens[0]) == len(src_tokens[i]) + for i in range(self.args.num_classes) + ) + assert len(src_tokens[0]) == len(src_lengths[0]) + assert len(labels) == 0 or len(labels) == len(src_tokens[0]) + + for i in range(self.args.num_classes): + src_lengths[i] = np.array(src_lengths[i]) + src_tokens[i] = ListDataset(src_tokens[i], src_lengths[i]) + src_lengths[i] = ListDataset(src_lengths[i]) + + dataset = { + "id": IdDataset(), + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(src_tokens[0], reduce=True), + } + + for i in range(self.args.num_classes): + dataset.update( + { + "net_input{}".format(i + 1): { + "src_tokens": RightPadDataset( + src_tokens[i], + pad_idx=self.source_dictionary.pad(), + ), + "src_lengths": src_lengths[i], + } + } + ) + + if len(labels) > 0: + dataset.update({"target": RawLabelDataset(labels)}) + + dataset = NestedDictionaryDataset( + dataset, + sizes=[np.maximum.reduce([src_token.sizes for src_token in src_tokens])], + ) + + with data_utils.numpy_seed(self.args.seed): + dataset = SortDataset( + dataset, + # shuffle + sort_order=[np.random.permutation(len(dataset))], + ) + + print("| Loaded {} with {} samples".format(split, len(dataset))) + + self.datasets[split] = dataset + return self.datasets[split] + + def build_model(self, args): + from fairseq import models + + model = models.build_model(args, self) + + model.register_classification_head( + "sentence_classification_head", + num_classes=1, + ) + + return model + + @property + def source_dictionary(self): + return self.vocab + + @property + def target_dictionary(self): + return self.vocab diff --git a/fairseq-tools/fairseq/examples/roberta/commonsense_qa/download_cqa_data.sh b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/download_cqa_data.sh new file mode 100644 index 00000000..5f300093 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/commonsense_qa/download_cqa_data.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +OUTDIR=data/CommonsenseQA + +mkdir -p $OUTDIR + +wget -O $OUTDIR/train.jsonl https://s3.amazonaws.com/commensenseqa/train_rand_split.jsonl +wget -O $OUTDIR/valid.jsonl https://s3.amazonaws.com/commensenseqa/dev_rand_split.jsonl +wget -O $OUTDIR/test.jsonl https://s3.amazonaws.com/commensenseqa/test_rand_split_no_answers.jsonl +wget -O $OUTDIR/dict.txt https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt diff --git a/fairseq-tools/fairseq/examples/roberta/multiprocessing_bpe_encoder.py b/fairseq-tools/fairseq/examples/roberta/multiprocessing_bpe_encoder.py new file mode 100644 index 00000000..43fe0451 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/multiprocessing_bpe_encoder.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import contextlib +import sys +from collections import Counter +from multiprocessing import Pool + +from fairseq.data.encoders.gpt2_bpe import get_encoder + + +def main(): + """ + Helper script to encode raw text with the GPT-2 BPE using multiple processes. + + The encoder.json and vocab.bpe files can be obtained here: + - https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json + - https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "--encoder-json", + help="path to encoder.json", + ) + parser.add_argument( + "--vocab-bpe", + type=str, + help="path to vocab.bpe", + ) + parser.add_argument( + "--inputs", + nargs="+", + default=["-"], + help="input files to filter/encode", + ) + parser.add_argument( + "--outputs", + nargs="+", + default=["-"], + help="path to save encoded outputs", + ) + parser.add_argument( + "--keep-empty", + action="store_true", + help="keep empty lines", + ) + parser.add_argument("--workers", type=int, default=20) + args = parser.parse_args() + + assert len(args.inputs) == len( + args.outputs + ), "number of input and output paths should match" + + with contextlib.ExitStack() as stack: + inputs = [ + stack.enter_context(open(input, "r", encoding="utf-8")) + if input != "-" + else sys.stdin + for input in args.inputs + ] + outputs = [ + stack.enter_context(open(output, "w", encoding="utf-8")) + if output != "-" + else sys.stdout + for output in args.outputs + ] + + encoder = MultiprocessingEncoder(args) + pool = Pool(args.workers, initializer=encoder.initializer) + encoded_lines = pool.imap(encoder.encode_lines, zip(*inputs), 100) + + stats = Counter() + for i, (filt, enc_lines) in enumerate(encoded_lines, start=1): + if filt == "PASS": + for enc_line, output_h in zip(enc_lines, outputs): + print(enc_line, file=output_h) + else: + stats["num_filtered_" + filt] += 1 + if i % 10000 == 0: + print("processed {} lines".format(i), file=sys.stderr) + + for k, v in stats.most_common(): + print("[{}] filtered {} lines".format(k, v), file=sys.stderr) + + +class MultiprocessingEncoder(object): + def __init__(self, args): + self.args = args + + def initializer(self): + global bpe + bpe = get_encoder(self.args.encoder_json, self.args.vocab_bpe) + + def encode(self, line): + global bpe + ids = bpe.encode(line) + return list(map(str, ids)) + + def decode(self, tokens): + global bpe + return bpe.decode(tokens) + + def encode_lines(self, lines): + """ + Encode a set of lines. All lines will be encoded together. + """ + enc_lines = [] + for line in lines: + line = line.strip() + if len(line) == 0 and not self.args.keep_empty: + return ["EMPTY", None] + tokens = self.encode(line) + enc_lines.append(" ".join(tokens)) + return ["PASS", enc_lines] + + def decode_lines(self, lines): + dec_lines = [] + for line in lines: + tokens = map(int, line.strip().split()) + dec_lines.append(self.decode(tokens)) + return ["PASS", dec_lines] + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/roberta/preprocess_GLUE_tasks.sh b/fairseq-tools/fairseq/examples/roberta/preprocess_GLUE_tasks.sh new file mode 100644 index 00000000..7f215a3b --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/preprocess_GLUE_tasks.sh @@ -0,0 +1,185 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +# raw glue data as downloaded by glue download script (https://gist.github.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e) +if [[ $# -ne 2 ]]; then + echo "Run as following:" + echo "./examples/roberta/preprocess_GLUE_tasks.sh " + exit 1 +fi + +GLUE_DATA_FOLDER=$1 + +# download bpe encoder.json, vocabulary and fairseq dictionary +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt' + +TASKS=$2 # QQP + +if [ "$TASKS" = "ALL" ] +then + TASKS="QQP MNLI QNLI MRPC RTE STS-B SST-2 CoLA" +fi + +for TASK in $TASKS +do + echo "Preprocessing $TASK" + + TASK_DATA_FOLDER="$GLUE_DATA_FOLDER/$TASK" + echo "Raw data as downloaded from glue website: $TASK_DATA_FOLDER" + + SPLITS="train dev test" + INPUT_COUNT=2 + if [ "$TASK" = "QQP" ] + then + INPUT_COLUMNS=( 4 5 ) + TEST_INPUT_COLUMNS=( 2 3 ) + LABEL_COLUMN=6 + elif [ "$TASK" = "MNLI" ] + then + SPLITS="train dev_matched dev_mismatched test_matched test_mismatched" + INPUT_COLUMNS=( 9 10 ) + TEST_INPUT_COLUMNS=( 9 10 ) + DEV_LABEL_COLUMN=16 + LABEL_COLUMN=12 + elif [ "$TASK" = "QNLI" ] + then + INPUT_COLUMNS=( 2 3 ) + TEST_INPUT_COLUMNS=( 2 3 ) + LABEL_COLUMN=4 + elif [ "$TASK" = "MRPC" ] + then + INPUT_COLUMNS=( 4 5 ) + TEST_INPUT_COLUMNS=( 4 5 ) + LABEL_COLUMN=1 + elif [ "$TASK" = "RTE" ] + then + INPUT_COLUMNS=( 2 3 ) + TEST_INPUT_COLUMNS=( 2 3 ) + LABEL_COLUMN=4 + elif [ "$TASK" = "STS-B" ] + then + INPUT_COLUMNS=( 8 9 ) + TEST_INPUT_COLUMNS=( 8 9 ) + LABEL_COLUMN=10 + # Following are single sentence tasks. + elif [ "$TASK" = "SST-2" ] + then + INPUT_COLUMNS=( 1 ) + TEST_INPUT_COLUMNS=( 2 ) + LABEL_COLUMN=2 + INPUT_COUNT=1 + elif [ "$TASK" = "CoLA" ] + then + INPUT_COLUMNS=( 4 ) + TEST_INPUT_COLUMNS=( 2 ) + LABEL_COLUMN=2 + INPUT_COUNT=1 + fi + + # Strip out header and filter lines that don't have expected number of fields. + rm -rf "$TASK_DATA_FOLDER/processed" + mkdir -p "$TASK_DATA_FOLDER/processed" + for SPLIT in $SPLITS + do + # CoLA train and dev doesn't have header. + if [[ ( "$TASK" = "CoLA") && ( "$SPLIT" != "test" ) ]] + then + cp "$TASK_DATA_FOLDER/$SPLIT.tsv" "$TASK_DATA_FOLDER/processed/$SPLIT.tsv.temp"; + else + tail -n +2 "$TASK_DATA_FOLDER/$SPLIT.tsv" > "$TASK_DATA_FOLDER/processed/$SPLIT.tsv.temp"; + fi + + # Remove unformatted lines from train and dev files for QQP dataset. + if [[ ( "$TASK" = "QQP") && ( "$SPLIT" != "test" ) ]] + then + awk -F '\t' -v NUM_FIELDS=6 'NF==NUM_FIELDS{print}{}' "$TASK_DATA_FOLDER/processed/$SPLIT.tsv.temp" > "$TASK_DATA_FOLDER/processed/$SPLIT.tsv"; + else + cp "$TASK_DATA_FOLDER/processed/$SPLIT.tsv.temp" "$TASK_DATA_FOLDER/processed/$SPLIT.tsv"; + fi + rm "$TASK_DATA_FOLDER/processed/$SPLIT.tsv.temp"; + done + + # Split into input0, input1 and label + for SPLIT in $SPLITS + do + for INPUT_TYPE in $(seq 0 $((INPUT_COUNT-1))) + do + if [[ "$SPLIT" != test* ]] + then + COLUMN_NUMBER=${INPUT_COLUMNS[$INPUT_TYPE]} + else + COLUMN_NUMBER=${TEST_INPUT_COLUMNS[$INPUT_TYPE]} + fi + cut -f"$COLUMN_NUMBER" "$TASK_DATA_FOLDER/processed/$SPLIT.tsv" > "$TASK_DATA_FOLDER/processed/$SPLIT.raw.input$INPUT_TYPE"; + done + + if [[ "$SPLIT" != test* ]] + then + if [ "$TASK" = "MNLI" ] && [ "$SPLIT" != "train" ] + then + cut -f"$DEV_LABEL_COLUMN" "$TASK_DATA_FOLDER/processed/$SPLIT.tsv" > "$TASK_DATA_FOLDER/processed/$SPLIT.label"; + else + cut -f"$LABEL_COLUMN" "$TASK_DATA_FOLDER/processed/$SPLIT.tsv" > "$TASK_DATA_FOLDER/processed/$SPLIT.label"; + fi + fi + + # BPE encode. + for INPUT_TYPE in $(seq 0 $((INPUT_COUNT-1))) + do + LANG="input$INPUT_TYPE" + echo "BPE encoding $SPLIT/$LANG" + python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json encoder.json \ + --vocab-bpe vocab.bpe \ + --inputs "$TASK_DATA_FOLDER/processed/$SPLIT.raw.$LANG" \ + --outputs "$TASK_DATA_FOLDER/processed/$SPLIT.$LANG" \ + --workers 60 \ + --keep-empty; + done + done + + # Remove output directory. + rm -rf "$TASK-bin" + + DEVPREF="$TASK_DATA_FOLDER/processed/dev.LANG" + TESTPREF="$TASK_DATA_FOLDER/processed/test.LANG" + if [ "$TASK" = "MNLI" ] + then + DEVPREF="$TASK_DATA_FOLDER/processed/dev_matched.LANG,$TASK_DATA_FOLDER/processed/dev_mismatched.LANG" + TESTPREF="$TASK_DATA_FOLDER/processed/test_matched.LANG,$TASK_DATA_FOLDER/processed/test_mismatched.LANG" + fi + + # Run fairseq preprocessing: + for INPUT_TYPE in $(seq 0 $((INPUT_COUNT-1))) + do + LANG="input$INPUT_TYPE" + fairseq-preprocess \ + --only-source \ + --trainpref "$TASK_DATA_FOLDER/processed/train.$LANG" \ + --validpref "${DEVPREF//LANG/$LANG}" \ + --testpref "${TESTPREF//LANG/$LANG}" \ + --destdir "$TASK-bin/$LANG" \ + --workers 60 \ + --srcdict dict.txt; + done + if [[ "$TASK" != "STS-B" ]] + then + fairseq-preprocess \ + --only-source \ + --trainpref "$TASK_DATA_FOLDER/processed/train.label" \ + --validpref "${DEVPREF//LANG/label}" \ + --destdir "$TASK-bin/label" \ + --workers 60; + else + # For STS-B output range is converted to be between: [0.0, 1.0] + mkdir -p "$TASK-bin/label" + awk '{print $1 / 5.0 }' "$TASK_DATA_FOLDER/processed/train.label" > "$TASK-bin/label/train.label" + awk '{print $1 / 5.0 }' "$TASK_DATA_FOLDER/processed/dev.label" > "$TASK-bin/label/valid.label" + fi +done diff --git a/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.py b/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.py new file mode 100644 index 00000000..cdd66072 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import json +import os +import re + + +class InputExample: + def __init__(self, paragraph, qa_list, label): + self.paragraph = paragraph + self.qa_list = qa_list + self.label = label + + +def get_examples(data_dir, set_type): + """ + Extract paragraph and question-answer list from each json file + """ + examples = [] + + levels = ["middle", "high"] + set_type_c = set_type.split("-") + if len(set_type_c) == 2: + levels = [set_type_c[1]] + set_type = set_type_c[0] + for level in levels: + cur_dir = os.path.join(data_dir, set_type, level) + for filename in os.listdir(cur_dir): + cur_path = os.path.join(cur_dir, filename) + with open(cur_path, "r") as f: + cur_data = json.load(f) + answers = cur_data["answers"] + options = cur_data["options"] + questions = cur_data["questions"] + context = cur_data["article"].replace("\n", " ") + context = re.sub(r"\s+", " ", context) + for i in range(len(answers)): + label = ord(answers[i]) - ord("A") + qa_list = [] + question = questions[i] + for j in range(4): + option = options[i][j] + if "_" in question: + qa_cat = question.replace("_", option) + else: + qa_cat = " ".join([question, option]) + qa_cat = re.sub(r"\s+", " ", qa_cat) + qa_list.append(qa_cat) + examples.append(InputExample(context, qa_list, label)) + + return examples + + +def main(): + """ + Helper script to extract paragraphs questions and answers from RACE datasets. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + "--input-dir", + help="input directory for downloaded RACE dataset", + ) + parser.add_argument( + "--output-dir", + help="output directory for extracted data", + ) + args = parser.parse_args() + + if not os.path.exists(args.output_dir): + os.makedirs(args.output_dir, exist_ok=True) + + for set_type in ["train", "dev", "test-middle", "test-high"]: + examples = get_examples(args.input_dir, set_type) + qa_file_paths = [ + os.path.join(args.output_dir, set_type + ".input" + str(i + 1)) + for i in range(4) + ] + qa_files = [open(qa_file_path, "w") for qa_file_path in qa_file_paths] + outf_context_path = os.path.join(args.output_dir, set_type + ".input0") + outf_label_path = os.path.join(args.output_dir, set_type + ".label") + outf_context = open(outf_context_path, "w") + outf_label = open(outf_label_path, "w") + for example in examples: + outf_context.write(example.paragraph + "\n") + for i in range(4): + qa_files[i].write(example.qa_list[i] + "\n") + outf_label.write(str(example.label) + "\n") + + for f in qa_files: + f.close() + outf_label.close() + outf_context.close() + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.sh b/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.sh new file mode 100644 index 00000000..932d2ab6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/preprocess_RACE.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +# data should be downloaded and processed with reprocess_RACE.py +if [[ $# -ne 2 ]]; then + echo "Run as following:" + echo "./examples/roberta/preprocess_RACE.sh " + exit 1 +fi + +RACE_DATA_FOLDER=$1 +OUT_DATA_FOLDER=$2 + +# download bpe encoder.json, vocabulary and fairseq dictionary +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe' +wget -N 'https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt' + +SPLITS="train dev test-middle test-high" +INPUT_TYPES="input0 input1 input2 input3 input4" +for INPUT_TYPE in $INPUT_TYPES +do + for SPLIT in $SPLITS + do + echo "BPE encoding $SPLIT/$INPUT_TYPE" + python -m examples.roberta.multiprocessing_bpe_encoder \ + --encoder-json encoder.json \ + --vocab-bpe vocab.bpe \ + --inputs "$RACE_DATA_FOLDER/$SPLIT.$INPUT_TYPE" \ + --outputs "$RACE_DATA_FOLDER/$SPLIT.$INPUT_TYPE.bpe" \ + --workers 10 \ + --keep-empty; + + done +done + +for INPUT_TYPE in $INPUT_TYPES + do + LANG="input$INPUT_TYPE" + fairseq-preprocess \ + --only-source \ + --trainpref "$RACE_DATA_FOLDER/train.$INPUT_TYPE.bpe" \ + --validpref "$RACE_DATA_FOLDER/dev.$INPUT_TYPE.bpe" \ + --testpref "$RACE_DATA_FOLDER/test-middle.$INPUT_TYPE.bpe,$RACE_DATA_FOLDER/test-high.$INPUT_TYPE.bpe" \ + --destdir "$OUT_DATA_FOLDER/$INPUT_TYPE" \ + --workers 10 \ + --srcdict dict.txt; +done + +rm -rf "$OUT_DATA_FOLDER/label" +mkdir -p "$OUT_DATA_FOLDER/label" +cp "$RACE_DATA_FOLDER/train.label" "$OUT_DATA_FOLDER/label/" +cp "$RACE_DATA_FOLDER/dev.label" "$OUT_DATA_FOLDER/label/valid.label" +cp "$RACE_DATA_FOLDER/test-middle.label" "$OUT_DATA_FOLDER/label/test.label" +cp "$RACE_DATA_FOLDER/test-high.label" "$OUT_DATA_FOLDER/label/test1.label" diff --git a/fairseq-tools/fairseq/examples/roberta/wsc/README.md b/fairseq-tools/fairseq/examples/roberta/wsc/README.md new file mode 100644 index 00000000..d40da6a5 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/wsc/README.md @@ -0,0 +1,125 @@ +# Finetuning RoBERTa on Winograd Schema Challenge (WSC) data + +The following instructions can be used to finetune RoBERTa on the WSC training +data provided by [SuperGLUE](https://super.gluebenchmark.com/). + +Note that there is high variance in the results. For our GLUE/SuperGLUE +submission we swept over the learning rate (1e-5, 2e-5, 3e-5), batch size (16, +32, 64) and total number of updates (500, 1000, 2000, 3000), as well as the +random seed. Out of ~100 runs we chose the best 7 models and ensembled them. + +**Approach:** The instructions below use a slightly different loss function than +what's described in the original RoBERTa arXiv paper. In particular, +[Kocijan et al. (2019)](https://arxiv.org/abs/1905.06290) introduce a margin +ranking loss between `(query, candidate)` pairs with tunable hyperparameters +alpha and beta. This is supported in our code as well with the `--wsc-alpha` and +`--wsc-beta` arguments. However, we achieved slightly better (and more robust) +results on the development set by instead using a single cross entropy loss term +over the log-probabilities for the query and all mined candidates. **The +candidates are mined using spaCy from each input sentence in isolation, so the +approach remains strictly pointwise.** This reduces the number of +hyperparameters and our best model achieved 92.3% development set accuracy, +compared to ~90% accuracy for the margin loss. Later versions of the RoBERTa +arXiv paper will describe this updated formulation. + +### 1) Download the WSC data from the SuperGLUE website: +```bash +wget https://dl.fbaipublicfiles.com/glue/superglue/data/v2/WSC.zip +unzip WSC.zip + +# we also need to copy the RoBERTa dictionary into the same directory +wget -O WSC/dict.txt https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/dict.txt +``` + +### 2) Finetune over the provided training data: +```bash +TOTAL_NUM_UPDATES=2000 # Total number of training steps. +WARMUP_UPDATES=250 # Linearly increase LR over this many steps. +LR=2e-05 # Peak LR for polynomial LR scheduler. +MAX_SENTENCES=16 # Batch size per GPU. +SEED=1 # Random seed. +ROBERTA_PATH=/path/to/roberta/model.pt + +# we use the --user-dir option to load the task and criterion +# from the examples/roberta/wsc directory: +FAIRSEQ_PATH=/path/to/fairseq +FAIRSEQ_USER_DIR=${FAIRSEQ_PATH}/examples/roberta/wsc + +CUDA_VISIBLE_DEVICES=0,1,2,3 fairseq-train WSC/ \ + --restore-file $ROBERTA_PATH \ + --reset-optimizer --reset-dataloader --reset-meters \ + --no-epoch-checkpoints --no-last-checkpoints --no-save-optimizer-state \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --valid-subset val \ + --fp16 --ddp-backend no_c10d \ + --user-dir $FAIRSEQ_USER_DIR \ + --task wsc --criterion wsc --wsc-cross-entropy \ + --arch roberta_large --bpe gpt2 --max-positions 512 \ + --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --adam-eps 1e-06 \ + --lr-scheduler polynomial_decay --lr $LR \ + --warmup-updates $WARMUP_UPDATES --total-num-update $TOTAL_NUM_UPDATES \ + --batch-size $MAX_SENTENCES \ + --max-update $TOTAL_NUM_UPDATES \ + --log-format simple --log-interval 100 \ + --seed $SEED +``` + +The above command assumes training on 4 GPUs, but you can achieve the same +results on a single GPU by adding `--update-freq=4`. + +### 3) Evaluate +```python +from fairseq.models.roberta import RobertaModel +from examples.roberta.wsc import wsc_utils # also loads WSC task and criterion +roberta = RobertaModel.from_pretrained('checkpoints', 'checkpoint_best.pt', 'WSC/') +roberta.cuda() +nsamples, ncorrect = 0, 0 +for sentence, label in wsc_utils.jsonl_iterator('WSC/val.jsonl', eval=True): + pred = roberta.disambiguate_pronoun(sentence) + nsamples += 1 + if pred == label: + ncorrect += 1 +print('Accuracy: ' + str(ncorrect / float(nsamples))) +# Accuracy: 0.9230769230769231 +``` + +## RoBERTa training on WinoGrande dataset +We have also provided `winogrande` task and criterion for finetuning on the +[WinoGrande](https://mosaic.allenai.org/projects/winogrande) like datasets +where there are always two candidates and one is correct. +It's more efficient implementation for such subcases. + +```bash +TOTAL_NUM_UPDATES=23750 # Total number of training steps. +WARMUP_UPDATES=2375 # Linearly increase LR over this many steps. +LR=1e-05 # Peak LR for polynomial LR scheduler. +MAX_SENTENCES=32 # Batch size per GPU. +SEED=1 # Random seed. +ROBERTA_PATH=/path/to/roberta/model.pt + +# we use the --user-dir option to load the task and criterion +# from the examples/roberta/wsc directory: +FAIRSEQ_PATH=/path/to/fairseq +FAIRSEQ_USER_DIR=${FAIRSEQ_PATH}/examples/roberta/wsc + +cd fairseq +CUDA_VISIBLE_DEVICES=0 fairseq-train winogrande_1.0/ \ + --restore-file $ROBERTA_PATH \ + --reset-optimizer --reset-dataloader --reset-meters \ + --no-epoch-checkpoints --no-last-checkpoints --no-save-optimizer-state \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --valid-subset val \ + --fp16 --ddp-backend no_c10d \ + --user-dir $FAIRSEQ_USER_DIR \ + --task winogrande --criterion winogrande \ + --wsc-margin-alpha 5.0 --wsc-margin-beta 0.4 \ + --arch roberta_large --bpe gpt2 --max-positions 512 \ + --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ + --optimizer adam --adam-betas '(0.9, 0.98)' --adam-eps 1e-06 \ + --lr-scheduler polynomial_decay --lr $LR \ + --warmup-updates $WARMUP_UPDATES --total-num-update $TOTAL_NUM_UPDATES \ + --batch-size $MAX_SENTENCES \ + --max-update $TOTAL_NUM_UPDATES \ + --log-format simple --log-interval 100 +``` diff --git a/fairseq-tools/fairseq/examples/roberta/wsc/__init__.py b/fairseq-tools/fairseq/examples/roberta/wsc/__init__.py new file mode 100644 index 00000000..78afa472 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/wsc/__init__.py @@ -0,0 +1,7 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import wsc_criterion # noqa +from . import wsc_task # noqa diff --git a/fairseq-tools/fairseq/examples/roberta/wsc/wsc_criterion.py b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_criterion.py new file mode 100644 index 00000000..1a590123 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_criterion.py @@ -0,0 +1,167 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.criterions import LegacyFairseqCriterion, register_criterion +from fairseq.data import encoders + + +@register_criterion("wsc") +class WSCCriterion(LegacyFairseqCriterion): + def __init__(self, args, task): + super().__init__(args, task) + if self.args.save_predictions is not None: + self.prediction_h = open(self.args.save_predictions, "w") + else: + self.prediction_h = None + self.bpe = encoders.build_bpe(args) + self.tokenizer = encoders.build_tokenizer(args) + + def __del__(self): + if self.prediction_h is not None: + self.prediction_h.close() + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + parser.add_argument("--wsc-margin-alpha", type=float, metavar="A", default=1.0) + parser.add_argument("--wsc-margin-beta", type=float, metavar="B", default=0.0) + parser.add_argument( + "--wsc-cross-entropy", + action="store_true", + help="use cross entropy formulation instead of margin loss", + ) + parser.add_argument( + "--save-predictions", metavar="FILE", help="file to save predictions to" + ) + + def get_masked_input(self, tokens, mask): + masked_tokens = tokens.clone() + masked_tokens[mask] = self.task.mask + return masked_tokens + + def get_lprobs(self, model, tokens, mask): + logits, _ = model(src_tokens=self.get_masked_input(tokens, mask)) + lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float) + scores = lprobs.gather(2, tokens.unsqueeze(-1)).squeeze(-1) + mask = mask.type_as(scores) + scores = (scores * mask).sum(dim=-1) / mask.sum(dim=-1) + return scores + + def get_loss(self, query_lprobs, cand_lprobs): + if self.args.wsc_cross_entropy: + return F.cross_entropy( + torch.cat([query_lprobs, cand_lprobs]).unsqueeze(0), + query_lprobs.new([0]).long(), + ) + else: + return ( + -query_lprobs + + self.args.wsc_margin_alpha + * (cand_lprobs - query_lprobs + self.args.wsc_margin_beta).clamp(min=0) + ).sum() + + def forward(self, model, sample, reduce=True): + # compute loss and accuracy + loss, nloss = 0.0, 0 + ncorrect, nqueries = 0, 0 + + for i, label in enumerate(sample["labels"]): + query_lprobs = self.get_lprobs( + model, + sample["query_tokens"][i].unsqueeze(0), + sample["query_masks"][i].unsqueeze(0), + ) + cand_lprobs = self.get_lprobs( + model, + sample["candidate_tokens"][i], + sample["candidate_masks"][i], + ) + + pred = (query_lprobs >= cand_lprobs).all().item() + + if label is not None: + label = 1 if label else 0 + ncorrect += 1 if pred == label else 0 + nqueries += 1 + + if label: + # only compute a loss for positive instances + nloss += 1 + loss += self.get_loss(query_lprobs, cand_lprobs) + + id = sample["id"][i].item() + if self.prediction_h is not None: + print("{}\t{}\t{}".format(id, pred, label), file=self.prediction_h) + + if nloss == 0: + loss = torch.tensor(0.0, requires_grad=True) + + sample_size = nqueries if nqueries > 0 else 1 + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["nsentences"], + "sample_size": sample_size, + "ncorrect": ncorrect, + "nqueries": nqueries, + } + return loss, sample_size, logging_output + + @staticmethod + def aggregate_logging_outputs(logging_outputs): + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + agg_output = { + "loss": loss_sum / sample_size / math.log(2), + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + + ncorrect = sum(log.get("ncorrect", 0) for log in logging_outputs) + nqueries = sum(log.get("nqueries", 0) for log in logging_outputs) + if nqueries > 0: + agg_output["accuracy"] = ncorrect / float(nqueries) + + return agg_output + + +@register_criterion("winogrande") +class WinograndeCriterion(WSCCriterion): + def forward(self, model, sample, reduce=True): + # compute loss and accuracy + query_lprobs = self.get_lprobs( + model, + sample["query_tokens"], + sample["query_masks"], + ) + cand_lprobs = self.get_lprobs( + model, + sample["candidate_tokens"], + sample["candidate_masks"], + ) + pred = query_lprobs >= cand_lprobs + loss = self.get_loss(query_lprobs, cand_lprobs) + + sample_size = sample["query_tokens"].size(0) + ncorrect = pred.sum().item() + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["nsentences"], + "sample_size": sample_size, + "ncorrect": ncorrect, + "nqueries": sample_size, + } + return loss, sample_size, logging_output diff --git a/fairseq-tools/fairseq/examples/roberta/wsc/wsc_task.py b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_task.py new file mode 100644 index 00000000..602ea737 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_task.py @@ -0,0 +1,401 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +import os +import tempfile + +import numpy as np +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.data import ( + Dictionary, + IdDataset, + ListDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + PadDataset, + SortDataset, + data_utils, + encoders, +) +from fairseq.tasks import LegacyFairseqTask, register_task + +from . import wsc_utils + + +@register_task("wsc") +class WSCTask(LegacyFairseqTask): + """Task to finetune RoBERTa for Winograd Schemas.""" + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", metavar="DIR", help="path to data directory; we load .jsonl" + ) + parser.add_argument( + "--init-token", + type=int, + default=None, + help="add token at the beginning of each batch item", + ) + + def __init__(self, args, vocab): + super().__init__(args) + self.vocab = vocab + self.mask = vocab.add_symbol("") + + self.bpe = encoders.build_bpe(args) + self.tokenizer = encoders.build_tokenizer(args) + + # hack to handle GPT-2 BPE, which includes leading spaces + if args.bpe == "gpt2": + self.leading_space = True + self.trailing_space = False + else: + self.leading_space = False + self.trailing_space = True + + @classmethod + def load_dictionary(cls, filename): + """Load the dictionary from the filename + + Args: + filename (str): the filename + """ + dictionary = Dictionary.load(filename) + dictionary.add_symbol("") + return dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + assert args.criterion == "wsc", "Must set --criterion=wsc" + + # load data and label dictionaries + vocab = cls.load_dictionary(os.path.join(args.data, "dict.txt")) + print("| dictionary: {} types".format(len(vocab))) + + return cls(args, vocab) + + def binarize(self, s: str, append_eos: bool = False): + if self.tokenizer is not None: + s = self.tokenizer.encode(s) + if self.bpe is not None: + s = self.bpe.encode(s) + tokens = self.vocab.encode_line( + s, + append_eos=append_eos, + add_if_not_exist=False, + ).long() + if self.args.init_token is not None: + tokens = torch.cat([tokens.new([self.args.init_token]), tokens]) + return tokens + + def binarize_with_mask(self, txt, prefix, suffix, leading_space, trailing_space): + toks = self.binarize( + prefix + leading_space + txt + trailing_space + suffix, + append_eos=True, + ) + mask = torch.zeros_like(toks, dtype=torch.bool) + mask_start = len(self.binarize(prefix)) + mask_size = len(self.binarize(leading_space + txt)) + mask[mask_start : mask_start + mask_size] = 1 + return toks, mask + + def load_dataset( + self, split, epoch=1, combine=False, data_path=None, return_only=False, **kwargs + ): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + if data_path is None: + data_path = os.path.join(self.args.data, split + ".jsonl") + if not os.path.exists(data_path): + raise FileNotFoundError("Cannot find data: {}".format(data_path)) + + query_tokens = [] + query_masks = [] + query_lengths = [] + candidate_tokens = [] + candidate_masks = [] + candidate_lengths = [] + labels = [] + + for sentence, pronoun_span, query, label in wsc_utils.jsonl_iterator(data_path): + prefix = sentence[: pronoun_span.start].text + suffix = sentence[pronoun_span.end :].text_with_ws + + # spaCy spans include trailing spaces, but we need to know about + # leading spaces for the GPT-2 BPE + leading_space = ( + " " if sentence[: pronoun_span.start].text_with_ws.endswith(" ") else "" + ) + trailing_space = " " if pronoun_span.text_with_ws.endswith(" ") else "" + + # get noun phrases, excluding pronouns and anything overlapping with the query + cand_spans = wsc_utils.filter_noun_chunks( + wsc_utils.extended_noun_chunks(sentence), + exclude_pronouns=True, + exclude_query=query, + exact_match=False, + ) + + if query is not None: + query_toks, query_mask = self.binarize_with_mask( + query, prefix, suffix, leading_space, trailing_space + ) + query_len = len(query_toks) + else: + query_toks, query_mask, query_len = None, None, 0 + + query_tokens.append(query_toks) + query_masks.append(query_mask) + query_lengths.append(query_len) + + cand_toks, cand_masks = [], [] + for cand_span in cand_spans: + toks, mask = self.binarize_with_mask( + cand_span.text, + prefix, + suffix, + leading_space, + trailing_space, + ) + cand_toks.append(toks) + cand_masks.append(mask) + + # collate candidates + cand_toks = data_utils.collate_tokens(cand_toks, pad_idx=self.vocab.pad()) + cand_masks = data_utils.collate_tokens(cand_masks, pad_idx=0) + assert cand_toks.size() == cand_masks.size() + + candidate_tokens.append(cand_toks) + candidate_masks.append(cand_masks) + candidate_lengths.append(cand_toks.size(1)) + + labels.append(label) + + query_lengths = np.array(query_lengths) + query_tokens = ListDataset(query_tokens, query_lengths) + query_masks = ListDataset(query_masks, query_lengths) + + candidate_lengths = np.array(candidate_lengths) + candidate_tokens = ListDataset(candidate_tokens, candidate_lengths) + candidate_masks = ListDataset(candidate_masks, candidate_lengths) + + labels = ListDataset(labels, [1] * len(labels)) + + dataset = { + "id": IdDataset(), + "query_tokens": query_tokens, + "query_masks": query_masks, + "candidate_tokens": candidate_tokens, + "candidate_masks": candidate_masks, + "labels": labels, + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(query_tokens, reduce=True), + } + + nested_dataset = NestedDictionaryDataset( + dataset, + sizes=[query_lengths], + ) + + with data_utils.numpy_seed(self.args.seed): + shuffle = np.random.permutation(len(query_tokens)) + dataset = SortDataset( + nested_dataset, + # shuffle + sort_order=[shuffle], + ) + + if return_only: + return dataset + + self.datasets[split] = dataset + return self.datasets[split] + + def build_dataset_for_inference(self, sample_json): + with tempfile.NamedTemporaryFile(buffering=0) as h: + h.write((json.dumps(sample_json) + "\n").encode("utf-8")) + dataset = self.load_dataset( + "disambiguate_pronoun", + data_path=h.name, + return_only=True, + ) + return dataset + + def disambiguate_pronoun(self, model, sentence, use_cuda=False): + sample_json = wsc_utils.convert_sentence_to_json(sentence) + dataset = self.build_dataset_for_inference(sample_json) + sample = dataset.collater([dataset[0]]) + if use_cuda: + sample = utils.move_to_cuda(sample) + + def get_masked_input(tokens, mask): + masked_tokens = tokens.clone() + masked_tokens[mask.bool()] = self.mask + return masked_tokens + + def get_lprobs(tokens, mask): + logits, _ = model(src_tokens=get_masked_input(tokens, mask)) + lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float) + scores = lprobs.gather(2, tokens.unsqueeze(-1)).squeeze(-1) + mask = mask.type_as(scores) + scores = (scores * mask).sum(dim=-1) / mask.sum(dim=-1) + return scores + + cand_lprobs = get_lprobs( + sample["candidate_tokens"][0], + sample["candidate_masks"][0], + ) + if sample["query_tokens"][0] is not None: + query_lprobs = get_lprobs( + sample["query_tokens"][0].unsqueeze(0), + sample["query_masks"][0].unsqueeze(0), + ) + return (query_lprobs >= cand_lprobs).all().item() == 1 + else: + best_idx = cand_lprobs.argmax().item() + full_cand = sample["candidate_tokens"][0][best_idx] + mask = sample["candidate_masks"][0][best_idx] + toks = full_cand[mask.bool()] + return self.bpe.decode(self.source_dictionary.string(toks)).strip() + + @property + def source_dictionary(self): + return self.vocab + + @property + def target_dictionary(self): + return self.vocab + + +@register_task("winogrande") +class WinograndeTask(WSCTask): + """ + Task for WinoGrande dataset. Efficient implementation for Winograd schema + tasks with exactly two candidates, one of which is correct. + """ + + @classmethod + def setup_task(cls, args, **kwargs): + assert args.criterion == "winogrande", "Must set --criterion=winogrande" + + # load data and label dictionaries + vocab = cls.load_dictionary(os.path.join(args.data, "dict.txt")) + print("| dictionary: {} types".format(len(vocab))) + + return cls(args, vocab) + + def load_dataset( + self, split, epoch=1, combine=False, data_path=None, return_only=False, **kwargs + ): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + if data_path is None: + data_path = os.path.join(self.args.data, split + ".jsonl") + if not os.path.exists(data_path): + raise FileNotFoundError("Cannot find data: {}".format(data_path)) + + query_tokens = [] + query_masks = [] + query_lengths = [] + candidate_tokens = [] + candidate_masks = [] + candidate_lengths = [] + + itr = wsc_utils.winogrande_jsonl_iterator(data_path, eval=(split == "test")) + + for sample in itr: + sentence, pronoun_span, query, cand_text = sample + prefix = sentence[: pronoun_span[0]].rstrip() + suffix = sentence[pronoun_span[1] :] + + leading_space = " " if sentence[: pronoun_span[0]].endswith(" ") else "" + trailing_space = "" + + if query is not None: + query_toks, query_mask = self.binarize_with_mask( + query, + prefix, + suffix, + leading_space, + trailing_space, + ) + query_len = len(query_toks) + else: + query_toks, query_mask, query_len = None, None, 0 + + query_tokens.append(query_toks) + query_masks.append(query_mask) + query_lengths.append(query_len) + + cand_toks, cand_mask = self.binarize_with_mask( + cand_text, + prefix, + suffix, + leading_space, + trailing_space, + ) + + candidate_tokens.append(cand_toks) + candidate_masks.append(cand_mask) + candidate_lengths.append(cand_toks.size(0)) + + query_lengths = np.array(query_lengths) + + def get_pad_dataset_fn(tokens, length, pad_idx): + return PadDataset( + ListDataset(tokens, length), + pad_idx=pad_idx, + left_pad=False, + ) + + query_tokens = get_pad_dataset_fn(query_tokens, query_lengths, self.vocab.pad()) + query_masks = get_pad_dataset_fn(query_masks, query_lengths, 0) + + candidate_lengths = np.array(candidate_lengths) + candidate_tokens = get_pad_dataset_fn( + candidate_tokens, candidate_lengths, self.vocab.pad() + ) + candidate_masks = get_pad_dataset_fn(candidate_masks, candidate_lengths, 0) + + dataset = { + "id": IdDataset(), + "query_tokens": query_tokens, + "query_masks": query_masks, + "candidate_tokens": candidate_tokens, + "candidate_masks": candidate_masks, + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(query_tokens, reduce=True), + } + + nested_dataset = NestedDictionaryDataset( + dataset, + sizes=[query_lengths], + ) + + with data_utils.numpy_seed(self.args.seed): + shuffle = np.random.permutation(len(query_tokens)) + dataset = SortDataset( + nested_dataset, + # shuffle + sort_order=[shuffle], + ) + + if return_only: + return dataset + + self.datasets[split] = dataset + return self.datasets[split] diff --git a/fairseq-tools/fairseq/examples/roberta/wsc/wsc_utils.py b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_utils.py new file mode 100644 index 00000000..da6ba743 --- /dev/null +++ b/fairseq-tools/fairseq/examples/roberta/wsc/wsc_utils.py @@ -0,0 +1,241 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +from functools import lru_cache + + +def convert_sentence_to_json(sentence): + if "_" in sentence: + prefix, rest = sentence.split("_", 1) + query, rest = rest.split("_", 1) + query_index = len(prefix.rstrip().split(" ")) + else: + query, query_index = None, None + + prefix, rest = sentence.split("[", 1) + pronoun, rest = rest.split("]", 1) + pronoun_index = len(prefix.rstrip().split(" ")) + + sentence = sentence.replace("_", "").replace("[", "").replace("]", "") + + return { + "idx": 0, + "text": sentence, + "target": { + "span1_index": query_index, + "span1_text": query, + "span2_index": pronoun_index, + "span2_text": pronoun, + }, + } + + +def extended_noun_chunks(sentence): + noun_chunks = {(np.start, np.end) for np in sentence.noun_chunks} + np_start, cur_np = 0, "NONE" + for i, token in enumerate(sentence): + np_type = token.pos_ if token.pos_ in {"NOUN", "PROPN"} else "NONE" + if np_type != cur_np: + if cur_np != "NONE": + noun_chunks.add((np_start, i)) + if np_type != "NONE": + np_start = i + cur_np = np_type + if cur_np != "NONE": + noun_chunks.add((np_start, len(sentence))) + return [sentence[s:e] for (s, e) in sorted(noun_chunks)] + + +def find_token(sentence, start_pos): + found_tok = None + for tok in sentence: + if tok.idx == start_pos: + found_tok = tok + break + return found_tok + + +def find_span(sentence, search_text, start=0): + search_text = search_text.lower() + for tok in sentence[start:]: + remainder = sentence[tok.i :].text.lower() + if remainder.startswith(search_text): + len_to_consume = len(search_text) + start_idx = tok.idx + for next_tok in sentence[tok.i :]: + end_idx = next_tok.idx + len(next_tok.text) + if end_idx - start_idx == len_to_consume: + span = sentence[tok.i : next_tok.i + 1] + return span + return None + + +@lru_cache(maxsize=1) +def get_detokenizer(): + from sacremoses import MosesDetokenizer + + detok = MosesDetokenizer(lang="en") + return detok + + +@lru_cache(maxsize=1) +def get_spacy_nlp(): + import en_core_web_lg + + nlp = en_core_web_lg.load() + return nlp + + +def jsonl_iterator(input_fname, positive_only=False, ngram_order=3, eval=False): + detok = get_detokenizer() + nlp = get_spacy_nlp() + + with open(input_fname) as fin: + for line in fin: + sample = json.loads(line.strip()) + + if positive_only and "label" in sample and not sample["label"]: + # only consider examples where the query is correct + continue + + target = sample["target"] + + # clean up the query + query = target["span1_text"] + if query is not None: + if "\n" in query: + continue + if query.endswith(".") or query.endswith(","): + query = query[:-1] + + # split tokens + tokens = sample["text"].split(" ") + + def strip_pronoun(x): + return x.rstrip('.,"') + + # find the pronoun + pronoun_idx = target["span2_index"] + pronoun = strip_pronoun(target["span2_text"]) + if strip_pronoun(tokens[pronoun_idx]) != pronoun: + # hack: sometimes the index is misaligned + if strip_pronoun(tokens[pronoun_idx + 1]) == pronoun: + pronoun_idx += 1 + else: + raise Exception("Misaligned pronoun!") + assert strip_pronoun(tokens[pronoun_idx]) == pronoun + + # split tokens before and after the pronoun + before = tokens[:pronoun_idx] + after = tokens[pronoun_idx + 1 :] + + # the GPT BPE attaches leading spaces to tokens, so we keep track + # of whether we need spaces before or after the pronoun + leading_space = " " if pronoun_idx > 0 else "" + trailing_space = " " if len(after) > 0 else "" + + # detokenize + before = detok.detokenize(before, return_str=True) + pronoun = detok.detokenize([pronoun], return_str=True) + after = detok.detokenize(after, return_str=True) + + # hack: when the pronoun ends in a period (or comma), move the + # punctuation to the "after" part + if pronoun.endswith(".") or pronoun.endswith(","): + after = pronoun[-1] + trailing_space + after + pronoun = pronoun[:-1] + + # hack: when the "after" part begins with a comma or period, remove + # the trailing space + if after.startswith(".") or after.startswith(","): + trailing_space = "" + + # parse sentence with spacy + sentence = nlp(before + leading_space + pronoun + trailing_space + after) + + # find pronoun span + start = len(before + leading_space) + first_pronoun_tok = find_token(sentence, start_pos=start) + pronoun_span = find_span(sentence, pronoun, start=first_pronoun_tok.i) + assert pronoun_span.text == pronoun + + if eval: + # convert to format where pronoun is surrounded by "[]" and + # query is surrounded by "_" + query_span = find_span(sentence, query) + query_with_ws = "_{}_{}".format( + query_span.text, + (" " if query_span.text_with_ws.endswith(" ") else ""), + ) + pronoun_with_ws = "[{}]{}".format( + pronoun_span.text, + (" " if pronoun_span.text_with_ws.endswith(" ") else ""), + ) + if query_span.start < pronoun_span.start: + first = (query_span, query_with_ws) + second = (pronoun_span, pronoun_with_ws) + else: + first = (pronoun_span, pronoun_with_ws) + second = (query_span, query_with_ws) + sentence = ( + sentence[: first[0].start].text_with_ws + + first[1] + + sentence[first[0].end : second[0].start].text_with_ws + + second[1] + + sentence[second[0].end :].text + ) + yield sentence, sample.get("label", None) + else: + yield sentence, pronoun_span, query, sample.get("label", None) + + +def winogrande_jsonl_iterator(input_fname, eval=False): + with open(input_fname) as fin: + for line in fin: + sample = json.loads(line.strip()) + sentence, option1, option2 = ( + sample["sentence"], + sample["option1"], + sample["option2"], + ) + + pronoun_span = (sentence.index("_"), sentence.index("_") + 1) + + if eval: + query, cand = option1, option2 + else: + query = option1 if sample["answer"] == "1" else option2 + cand = option2 if sample["answer"] == "1" else option1 + yield sentence, pronoun_span, query, cand + + +def filter_noun_chunks( + chunks, exclude_pronouns=False, exclude_query=None, exact_match=False +): + if exclude_pronouns: + chunks = [ + np + for np in chunks + if (np.lemma_ != "-PRON-" and not all(tok.pos_ == "PRON" for tok in np)) + ] + + if exclude_query is not None: + excl_txt = [exclude_query.lower()] + filtered_chunks = [] + for chunk in chunks: + lower_chunk = chunk.text.lower() + found = False + for excl in excl_txt: + if ( + not exact_match and (lower_chunk in excl or excl in lower_chunk) + ) or lower_chunk == excl: + found = True + break + if not found: + filtered_chunks.append(chunk) + chunks = filtered_chunks + + return chunks diff --git a/fairseq-tools/fairseq/examples/rxf/README.md b/fairseq-tools/fairseq/examples/rxf/README.md new file mode 100644 index 00000000..22a1cc47 --- /dev/null +++ b/fairseq-tools/fairseq/examples/rxf/README.md @@ -0,0 +1,52 @@ +[Better Fine-Tuning by Reducing Representational Collapse](https://arxiv.org/abs/2008.03156) +===================== +This repo contains the code to replicate all experiments from the _Better Fine-Tuning by Reducing Representational Collapse_ paper excluding the probing results. + +The R3F sentence prediction criterion is registered as `sentence_prediction_r3f` while the label smoothing version of it is implemented as `label_smoothed_cross_entropy_r3f`. The R4F version of the sentence prediction criterion can be achieved by applying spectral norm to the classification head via the `--spectral-norm-classification-head` parameter. + +## Hyper-parameters +Our methods introduce 3 new hyper-parameters; `--eps` which sets the standard deviation or range of the distribution we're sampling from, `--r3f-lambda` which controls the combining of logistic loss and noisy KL loss and `--noise-type` which controls which parametric distribution we use ('normal', 'uniform'). + +For example to run R3F on RTE from GLUE + +``` +TOTAL_NUM_UPDATES=3120 +WARMUP_UPDATES=187 +LR=1e-05 +NUM_CLASSES=2 +MAX_SENTENCES=8 # Batch size. +ROBERTA_PATH=/path/to/roberta/model.pt + +CUDA_VISIBLE_DEVICES=0 fairseq-train RTE-bin \ + --restore-file $ROBERTA_PATH \ + --max-positions 512 \ + --max-sentences $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction_r3f \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric \ + --noise-type uniform --r3f-lambda 0.7 \ + --user-dir examples/rxf/rxf_src +``` + +## Citation +```bibtex +@article{aghajanyan2020better, + title={Better Fine-Tuning by Reducing Representational Collapse}, + author={Aghajanyan, Armen and Shrivastava, Akshat and Gupta, Anchit and Goyal, Naman and Zettlemoyer, Luke and Gupta, Sonal}, + journal={arXiv preprint arXiv:2008.03156}, + year={2020} +} +``` diff --git a/fairseq-tools/fairseq/examples/rxf/__init__.py b/fairseq-tools/fairseq/examples/rxf/__init__.py new file mode 100644 index 00000000..b24cb6b7 --- /dev/null +++ b/fairseq-tools/fairseq/examples/rxf/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import rxf_src # noqa diff --git a/fairseq-tools/fairseq/examples/rxf/rxf_src/__init__.py b/fairseq-tools/fairseq/examples/rxf/rxf_src/__init__.py new file mode 100644 index 00000000..306e232d --- /dev/null +++ b/fairseq-tools/fairseq/examples/rxf/rxf_src/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import label_smoothed_cross_entropy_r3f, sentence_prediction_r3f # noqa diff --git a/fairseq-tools/fairseq/examples/rxf/rxf_src/label_smoothed_cross_entropy_r3f.py b/fairseq-tools/fairseq/examples/rxf/rxf_src/label_smoothed_cross_entropy_r3f.py new file mode 100644 index 00000000..079db13e --- /dev/null +++ b/fairseq-tools/fairseq/examples/rxf/rxf_src/label_smoothed_cross_entropy_r3f.py @@ -0,0 +1,157 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from fairseq.criterions.label_smoothed_cross_entropy import label_smoothed_nll_loss + + +@register_criterion("label_smoothed_cross_entropy_r3f") +class LabelSmoothedCrossEntropyR3FCriterion(FairseqCriterion): + def __init__( + self, task, sentence_avg, label_smoothing, eps, r3f_lambda, noise_type + ): + super().__init__(task) + self.sentence_avg = sentence_avg + self.label_smoothing = label_smoothing + self.eps = eps + self.r3f_lambda = r3f_lambda + self.noise_type = noise_type + if self.noise_type in {"normal"}: + self.noise_sampler = torch.distributions.normal.Normal( + loc=0.0, scale=self.eps + ) + elif self.noise_type == "uniform": + self.noise_sampler = torch.distributions.uniform.Uniform( + low=-self.eps, high=self.eps + ) + else: + raise Exception(f"unrecognized noise type {self.noise_type}") + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--label-smoothing', default=0., type=float, metavar='D', + help='epsilon for label smoothing, 0 means no label smoothing') + parser.add_argument('--eps', type=float, default=1e-5, + help='noise eps') + parser.add_argument('--r3f-lambda', type=float, default=1.0, + help='lambda for combining logistic loss and noisy KL loss') + parser.add_argument('--noise-type', type=str, default='normal', + choices=['normal', 'uniform'], + help='type of noises') + # fmt: on + + def _get_symm_kl(self, noised_logits, input_logits): + return ( + F.kl_div( + F.log_softmax(noised_logits, dim=-1, dtype=torch.float32), + F.softmax(input_logits, dim=-1, dtype=torch.float32), + None, + None, + "sum", + ) + + F.kl_div( + F.log_softmax(input_logits, dim=-1, dtype=torch.float32), + F.softmax(noised_logits, dim=-1, dtype=torch.float32), + None, + None, + "sum", + ) + ) / noised_logits.size(0) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + token_embeddings = model.encoder.embed_tokens(sample["net_input"]["src_tokens"]) + input_logits, extra = model(**sample["net_input"]) + loss, nll_loss = self.compute_loss( + model, (input_logits, extra), sample, reduce=reduce + ) + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + + if model.training: + noise = self.noise_sampler.sample(sample_shape=token_embeddings.shape).to( + token_embeddings + ) + noised_embeddings = token_embeddings.clone() + noise + + noised_logits, _ = model( + **sample["net_input"], token_embeddings=noised_embeddings + ) + symm_kl = self._get_symm_kl(noised_logits, input_logits) + + if model.training: + symm_kl = symm_kl * sample_size + loss = loss + self.r3f_lambda * symm_kl + + logging_output = { + "loss": loss.data, + "nll_loss": nll_loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + + if model.training: + logging_output.update( + symm_kl=utils.item(symm_kl.data) if reduce else symm_kl.data + ) + + return loss, sample_size, logging_output + + def compute_loss(self, model, net_output, sample, reduce=True): + lprobs = model.get_normalized_probs(net_output, log_probs=True) + lprobs = lprobs.view(-1, lprobs.size(-1)) + target = model.get_targets(sample, net_output).view(-1, 1) + loss, nll_loss = label_smoothed_nll_loss( + lprobs, + target, + self.label_smoothing, + ignore_index=self.padding_idx, + reduce=reduce, + ) + return loss, nll_loss + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + nll_loss_sum = sum(log.get("nll_loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + symm_kl_sum = sum(log.get("symm_kl", 0) for log in logging_outputs) + + metrics.log_scalar("symm_kl", symm_kl_sum / sample_size, sample_size, round=3) + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar( + "nll_loss", nll_loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/examples/rxf/rxf_src/sentence_prediction_r3f.py b/fairseq-tools/fairseq/examples/rxf/rxf_src/sentence_prediction_r3f.py new file mode 100644 index 00000000..62dd6339 --- /dev/null +++ b/fairseq-tools/fairseq/examples/rxf/rxf_src/sentence_prediction_r3f.py @@ -0,0 +1,170 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("sentence_prediction_r3f") +class SentencePredictionR3F(FairseqCriterion): + def __init__( + self, + task, + eps, + r3f_lambda, + noise_type, + classification_head_name, + regression_target, + ): + super().__init__(task) + self.eps = eps + self.r3f_lambda = r3f_lambda + self.noise_type = noise_type + self.classification_head_name = classification_head_name + self.regression_target = regression_target + if self.noise_type in {"normal"}: + self.noise_sampler = torch.distributions.normal.Normal( + loc=0.0, scale=self.eps + ) + elif self.noise_type == "uniform": + self.noise_sampler = torch.distributions.uniform.Uniform( + low=-self.eps, high=self.eps + ) + else: + raise Exception(f"unrecognized noise type {self.noise_type}") + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--eps', type=float, default=1e-5, + help='noise eps') + parser.add_argument('--r3f-lambda', type=float, default=1.0, + help='lambda for combining logistic loss and noisy KL loss') + parser.add_argument('--noise-type', type=str, default='uniform', + choices=['normal', 'uniform'], + help='type of noises for RXF methods') + parser.add_argument('--classification-head-name', + default='sentence_classification_head', + help='name of the classification head to use') + # fmt: on + + def _get_symm_kl(self, noised_logits, input_logits): + return ( + F.kl_div( + F.log_softmax(noised_logits, dim=-1, dtype=torch.float32), + F.softmax(input_logits, dim=-1, dtype=torch.float32), + None, + None, + "sum", + ) + + F.kl_div( + F.log_softmax(input_logits, dim=-1, dtype=torch.float32), + F.softmax(noised_logits, dim=-1, dtype=torch.float32), + None, + None, + "sum", + ) + ) / noised_logits.size(0) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + assert ( + hasattr(model, "classification_heads") + and self.classification_head_name in model.classification_heads + ), "model must provide sentence classification head for --criterion=sentence_prediction" + + token_embeddings = model.encoder.sentence_encoder.embed_tokens( + sample["net_input"]["src_tokens"] + ) + input_logits, _ = model( + **sample["net_input"], + features_only=True, + classification_head_name=self.classification_head_name, + token_embeddings=token_embeddings, + ) + if model.training and self.noise_sampler: + noise = self.noise_sampler.sample(sample_shape=token_embeddings.shape).to( + token_embeddings + ) + noised_embeddings = token_embeddings.detach().clone() + noise + + noised_logits, _ = model( + **sample["net_input"], + features_only=True, + classification_head_name=self.classification_head_name, + token_embeddings=noised_embeddings, + ) + symm_kl = self._get_symm_kl(noised_logits, input_logits) + else: + symm_kl = 0 + + targets = model.get_targets(sample, [input_logits]).view(-1) + sample_size = targets.numel() + + if not self.regression_target: + loss = F.nll_loss( + F.log_softmax(input_logits, dim=-1, dtype=torch.float32), + targets, + reduction="sum", + ) + if model.training: + symm_kl = symm_kl * sample_size + loss = loss + self.r3f_lambda * symm_kl + else: + logits = input_logits.squeeze().float() + targets = targets.float() + loss = F.mse_loss(logits, targets, reduction="sum") + + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample_size, + "sample_size": sample_size, + } + + if not self.regression_target: + preds = input_logits.max(dim=1)[1] + logging_output.update(ncorrect=(preds == targets).sum().item()) + + if model.training and self.noise_sampler: + logging_output.update( + symm_kl=utils.item(symm_kl.data) if reduce else symm_kl.data + ) + return loss, sample_size, logging_output + + @staticmethod + def aggregate_logging_outputs(logging_outputs): + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + symm_kl_sum = sum(log.get("symm_kl", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + agg_output = { + "loss": loss_sum / sample_size / math.log(2), + "symm_kl": symm_kl_sum / sample_size, + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + + if len(logging_outputs) > 0 and "ncorrect" in logging_outputs[0]: + ncorrect = sum(log.get("ncorrect", 0) for log in logging_outputs) + agg_output.update(accuracy=ncorrect / nsentences) + + if sample_size != ntokens: + agg_output["nll_loss"] = loss_sum / ntokens / math.log(2) + return agg_output diff --git a/fairseq-tools/fairseq/examples/scaling_nmt/README.md b/fairseq-tools/fairseq/examples/scaling_nmt/README.md new file mode 100644 index 00000000..0cc3360c --- /dev/null +++ b/fairseq-tools/fairseq/examples/scaling_nmt/README.md @@ -0,0 +1,114 @@ +# Scaling Neural Machine Translation (Ott et al., 2018) + +This page includes instructions for reproducing results from the paper [Scaling Neural Machine Translation (Ott et al., 2018)](https://arxiv.org/abs/1806.00187). + +## Pre-trained models + +Model | Description | Dataset | Download +---|---|---|--- +`transformer.wmt14.en-fr` | Transformer
([Ott et al., 2018](https://arxiv.org/abs/1806.00187)) | [WMT14 English-French](http://statmt.org/wmt14/translation-task.html#Download) | model:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/wmt14.en-fr.joined-dict.transformer.tar.bz2)
newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt14.en-fr.joined-dict.newstest2014.tar.bz2) +`transformer.wmt16.en-de` | Transformer
([Ott et al., 2018](https://arxiv.org/abs/1806.00187)) | [WMT16 English-German](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8) | model:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/wmt16.en-de.joined-dict.transformer.tar.bz2)
newstest2014:
[download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/wmt16.en-de.joined-dict.newstest2014.tar.bz2) + +## Training a new model on WMT'16 En-De + +First download the [preprocessed WMT'16 En-De data provided by Google](https://drive.google.com/uc?export=download&id=0B_bZck-ksdkpM25jRUN2X2UxMm8). + +Then: + +##### 1. Extract the WMT'16 En-De data +```bash +TEXT=wmt16_en_de_bpe32k +mkdir -p $TEXT +tar -xzvf wmt16_en_de.tar.gz -C $TEXT +``` + +##### 2. Preprocess the dataset with a joined dictionary +```bash +fairseq-preprocess \ + --source-lang en --target-lang de \ + --trainpref $TEXT/train.tok.clean.bpe.32000 \ + --validpref $TEXT/newstest2013.tok.bpe.32000 \ + --testpref $TEXT/newstest2014.tok.bpe.32000 \ + --destdir data-bin/wmt16_en_de_bpe32k \ + --nwordssrc 32768 --nwordstgt 32768 \ + --joined-dictionary \ + --workers 20 +``` + +##### 3. Train a model +```bash +fairseq-train \ + data-bin/wmt16_en_de_bpe32k \ + --arch transformer_vaswani_wmt_en_de_big --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr 0.0005 --lr-scheduler inverse_sqrt --warmup-updates 4000 --warmup-init-lr 1e-07 \ + --dropout 0.3 --weight-decay 0.0 \ + --criterion label_smoothed_cross_entropy --label-smoothing 0.1 \ + --max-tokens 3584 \ + --fp16 +``` + +Note that the `--fp16` flag requires you have CUDA 9.1 or greater and a Volta GPU or newer. + +***IMPORTANT:*** You will get better performance by training with big batches and +increasing the learning rate. If you want to train the above model with big batches +(assuming your machine has 8 GPUs): +- add `--update-freq 16` to simulate training on 8x16=128 GPUs +- increase the learning rate; 0.001 works well for big batches + +##### 4. Evaluate + +Now we can evaluate our trained model. + +Note that the original [Attention Is All You Need](https://arxiv.org/abs/1706.03762) +paper used a couple tricks to achieve better BLEU scores. We use these same tricks in +the Scaling NMT paper, so it's important to apply them when reproducing our results. + +First, use the [average_checkpoints.py](/scripts/average_checkpoints.py) script to +average the last few checkpoints. Averaging the last 5-10 checkpoints is usually +good, but you may need to adjust this depending on how long you've trained: +```bash +python scripts/average_checkpoints \ + --inputs /path/to/checkpoints \ + --num-epoch-checkpoints 10 \ + --output checkpoint.avg10.pt +``` + +Next, generate translations using a beam width of 4 and length penalty of 0.6: +```bash +fairseq-generate \ + data-bin/wmt16_en_de_bpe32k \ + --path checkpoint.avg10.pt \ + --beam 4 --lenpen 0.6 --remove-bpe > gen.out +``` + +Finally, we apply the ["compound splitting" script](/scripts/compound_split_bleu.sh) to +add spaces around dashes. For example "Café-Liebhaber" would become three tokens: +"Café - Liebhaber". This typically results in larger BLEU scores, but it is not +appropriate to compare these inflated scores to work which does not include this trick. +This trick was used in the [original AIAYN code](https://github.com/tensorflow/tensor2tensor/blob/fc9335c0203685cbbfe2b30c92db4352d8f60779/tensor2tensor/utils/get_ende_bleu.sh), +so we used it in the Scaling NMT paper as well. That said, it's strongly advised to +report [sacrebleu](https://github.com/mjpost/sacrebleu) scores instead. + +To compute "compound split" tokenized BLEU (not recommended!): +```bash +bash scripts/compound_split_bleu.sh gen.out +# BLEU4 = 29.29, 60.3/35.0/22.8/15.3 (BP=1.000, ratio=1.004, syslen=64763, reflen=64496) +``` + +To compute detokenized BLEU with sacrebleu (preferred): +```bash +bash scripts/sacrebleu.sh wmt14/full en de gen.out +# BLEU+case.mixed+lang.en-de+numrefs.1+smooth.exp+test.wmt14/full+tok.13a+version.1.4.3 = 28.6 59.3/34.3/22.1/14.9 (BP = 1.000 ratio = 1.016 hyp_len = 63666 ref_len = 62688) +``` + +## Citation + +```bibtex +@inproceedings{ott2018scaling, + title = {Scaling Neural Machine Translation}, + author = {Ott, Myle and Edunov, Sergey and Grangier, David and Auli, Michael}, + booktitle = {Proceedings of the Third Conference on Machine Translation (WMT)}, + year = 2018, +} +``` diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/README.md b/fairseq-tools/fairseq/examples/simultaneous_translation/README.md new file mode 100644 index 00000000..e27b6528 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/README.md @@ -0,0 +1,106 @@ +# Simultaneous Machine Translation + +This directory contains the code for the paper [Monotonic Multihead Attention](https://openreview.net/forum?id=Hyg96gBKPS) + +## Prepare Data + +[Please follow the instructions to download and preprocess the WMT'15 En-De dataset.](https://github.com/pytorch/fairseq/tree/simulastsharedtask/examples/translation#prepare-wmt14en2desh) + +## Training + +- MMA-IL + +```shell +fairseq-train \ + data-bin/wmt15_en_de_32k \ + --simul-type infinite_lookback \ + --user-dir $FAIRSEQ/example/simultaneous_translation \ + --mass-preservation \ + --criterion latency_augmented_label_smoothed_cross_entropy \ + --latency-weight-avg 0.1 \ + --max-update 50000 \ + --arch transformer_monotonic_iwslt_de_en save_dir_key=lambda \ + --optimizer adam --adam-betas '(0.9, 0.98)' \ + --lr-scheduler 'inverse_sqrt' \ + --warmup-init-lr 1e-7 --warmup-updates 4000 \ + --lr 5e-4 --min-lr 1e-9 --clip-norm 0.0 --weight-decay 0.0001\ + --dropout 0.3 \ + --label-smoothing 0.1\ + --max-tokens 3584 +``` + +- MMA-H + +```shell +fairseq-train \ + data-bin/wmt15_en_de_32k \ + --simul-type hard_aligned \ + --user-dir $FAIRSEQ/example/simultaneous_translation \ + --mass-preservation \ + --criterion latency_augmented_label_smoothed_cross_entropy \ + --latency-weight-var 0.1 \ + --max-update 50000 \ + --arch transformer_monotonic_iwslt_de_en save_dir_key=lambda \ + --optimizer adam --adam-betas '(0.9, 0.98)' \ + --lr-scheduler 'inverse_sqrt' \ + --warmup-init-lr 1e-7 --warmup-updates 4000 \ + --lr 5e-4 --min-lr 1e-9 --clip-norm 0.0 --weight-decay 0.0001\ + --dropout 0.3 \ + --label-smoothing 0.1\ + --max-tokens 3584 +``` + +- wait-k + +```shell +fairseq-train \ + data-bin/wmt15_en_de_32k \ + --simul-type wait-k \ + --waitk-lagging 3 \ + --user-dir $FAIRSEQ/example/simultaneous_translation \ + --mass-preservation \ + --criterion latency_augmented_label_smoothed_cross_entropy \ + --max-update 50000 \ + --arch transformer_monotonic_iwslt_de_en save_dir_key=lambda \ + --optimizer adam --adam-betas '(0.9, 0.98)' \ + --lr-scheduler 'inverse_sqrt' \ + --warmup-init-lr 1e-7 --warmup-updates 4000 \ + --lr 5e-4 --min-lr 1e-9 --clip-norm 0.0 --weight-decay 0.0001\ + --dropout 0.3 \ + --label-smoothing 0.1\ + --max-tokens 3584 +``` + + +## Evaluation + +More details on evaluation can be found [here](https://github.com/pytorch/fairseq/blob/simulastsharedtask/examples/simultaneous_translation/docs/evaluation.md) + +### Start the server + +```shell +python ./eval/server.py \ + --src-file $SRC_FILE \ + --ref-file $TGT_FILE +``` + +### Run the client + +```shell +python ./evaluate.py \ + --data-bin data-bin/wmt15_en_de_32k \ + --model-path ./checkpoints/checkpoint_best.pt + --scores --output $RESULT_DIR +``` + +### Run evaluation locally without server + +```shell +python ./eval/evaluate.py + --local \ + --src-file $SRC_FILE \ + --tgt-file $TGT_FILE \ + --data-bin data-bin/wmt15_en_de_32k \ + --model-path ./checkpoints/checkpoint_best.pt \ + --scores --output $RESULT_DIR +``` diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/__init__.py new file mode 100644 index 00000000..446fc86c --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import criterions, eval, models # noqa diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/__init__.py new file mode 100644 index 00000000..08791bff --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + criterion_name = file[: file.find(".py")] + importlib.import_module( + "examples.simultaneous_translation.criterions." + criterion_name + ) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/label_smoothed_cross_entropy_latency_augmented.py b/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/label_smoothed_cross_entropy_latency_augmented.py new file mode 100644 index 00000000..b3c8f6d5 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/criterions/label_smoothed_cross_entropy_latency_augmented.py @@ -0,0 +1,73 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from examples.simultaneous_translation.utils.latency import LatencyTraining +from fairseq.criterions import register_criterion +from fairseq.criterions.label_smoothed_cross_entropy import ( + LabelSmoothedCrossEntropyCriterion, +) + + +@register_criterion("latency_augmented_label_smoothed_cross_entropy") +class LatencyAugmentedLabelSmoothedCrossEntropyCriterion( + LabelSmoothedCrossEntropyCriterion +): + def __init__(self, args, task): + super().__init__(args, task) + self.eps = args.label_smoothing + self.latency_weight_avg = args.latency_weight_avg + self.latency_weight_avg_type = args.latency_weight_avg_type + self.latency_weight_var = args.latency_weight_var + self.latency_weight_var_type = args.latency_weight_var_type + self.mass_preservation = args.mass_preservation + self.average_method = args.average_method + self.latency_train = LatencyTraining( + self.latency_weight_avg, + self.latency_weight_var, + self.latency_weight_avg_type, + self.latency_weight_var_type, + self.mass_preservation, + self.average_method, + ) + + @staticmethod + def add_args(parser): + super( + LatencyAugmentedLabelSmoothedCrossEntropyCriterion, + LatencyAugmentedLabelSmoothedCrossEntropyCriterion, + ).add_args(parser) + """Add criterion-specific arguments to the parser.""" + # fmt: off + parser.add_argument("--latency-weight-avg", default=0., type=float, metavar='D', + help="Average loss weight") + parser.add_argument("--latency-weight-var", default=0., type=float, metavar='D', + help="Variance loss weight") + parser.add_argument("--latency-weight-avg-type", default="differentiable_average_lagging", + help="Statistics for Average loss type") + parser.add_argument("--latency-weight-var-type", default="variance_delay", + help="Statistics for variance loss type") + parser.add_argument("--average-method", default="weighted_average", + help="Average loss type") + # fmt: on + + def compute_loss(self, model, net_output, sample, reduce=True): + # Compute cross entropy loss first + loss, nll_loss = super().compute_loss(model, net_output, sample, reduce) + + # Obtain the expected alignment + attn_list = [item["alpha"] for item in net_output[-1]["attn_list"]] + + target_padding_mask = model.get_targets(sample, net_output).eq(self.padding_idx) + + source_padding_mask = net_output[-1].get("encoder_padding_mask", None) + + # Get latency loss + latency_loss = self.latency_train.loss( + attn_list, source_padding_mask, target_padding_mask + ) + + loss += latency_loss + + return loss, nll_loss diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/docs/baseline.md b/fairseq-tools/fairseq/examples/simultaneous_translation/docs/baseline.md new file mode 100644 index 00000000..d9bf1a11 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/docs/baseline.md @@ -0,0 +1,178 @@ +# **Baseline Simultaneous Translation** +--- + +This is an instruction of training and evaluating a *wait-k* simultanoes LSTM model on MUST-C English-Gernam Dataset. + +[STACL: Simultaneous Translation with Implicit Anticipation and Controllable Latency using Prefix-to-Prefix Framework](https://https://www.aclweb.org/anthology/P19-1289/) + + +## **Requirements** +Install fairseq (make sure to use the correct branch): +``` +git clone --branch simulastsharedtask git@github.com:pytorch/fairseq.git +cd fairseq +pip install -e . +``` + +Assuming that fairseq is installed in a directory called `FAIRSEQ`. + +Install SentencePiece. One easy way is to use anaconda: + +``` +conda install -c powerai sentencepiece +``` + +Download the MuST-C data for English-German available at https://ict.fbk.eu/must-c/. +We will assume that the data is downloaded in a directory called `DATA_ROOT`. + + +## **Text-to-text Model** +--- +### Data Preparation +Train a SentencePiece model: +```shell +for lang in en de; do + python $FAIRSEQ/examples/simultaneous_translation/data/train_spm.py \ + --data-path $DATA_ROOT/data \ + --vocab-size 10000 \ + --max-frame 3000 \ + --model-type unigram \ + --lang $lang \ + --out-path . +``` + +Process the data with the SentencePiece model: +```shell +proc_dir=proc +mkdir -p $proc_dir +for split in train dev tst-COMMON tst-HE; do + for lang in en de; do + spm_encode \ + --model unigram-$lang-10000-3000/spm.model \ + < $DATA_ROOT/data/$split/txt/$split.$lang \ + > $proc_dir/$split.spm.$lang + done +done +``` + +Binarize the data: + +```shell +proc_dir=proc +fairseq-preprocess \ + --source-lang en --target-lang de \ + --trainpref $proc_dir/train.spm \ + --validpref $proc_dir/dev.spm \ + --testpref $proc_dir/tst-COMMON.spm \ + --thresholdtgt 0 \ + --thresholdsrc 0 \ + --workers 20 \ + --destdir ./data-bin/mustc_en_de \ +``` + +### Training + + +```shell +mkdir -p checkpoints +CUDA_VISIBLE_DEVICES=1 python $FAIRSEQ/train.py data-bin/mustc_en_de \ + --save-dir checkpoints \ + --arch berard_simul_text_iwslt \ + --simul-type waitk \ + --waitk-lagging 2 \ + --optimizer adam \ + --max-epoch 100 \ + --lr 0.001 \ + --clip-norm 5.0 \ + --batch-size 128 \ + --log-format json \ + --log-interval 10 \ + --criterion cross_entropy_acc \ + --user-dir $FAIRSEQ/examples/simultaneous_translation +``` + +## **Speech-to-text Model** +--- +### Data Preparation +First, segment wav files. +```shell +python $FAIRSEQ/examples/simultaneous_translation/data/segment_wav.py \ + --datapath $DATA_ROOT +``` +Similar to text-to-text model, train a Sentencepiecemodel, but only train on German +```Shell +python $FAIRSEQ/examples/simultaneous_translation/data/train_spm.py \ + --data-path $DATA_ROOT/data \ + --vocab-size 10000 \ + --max-frame 3000 \ + --model-type unigram \ + --lang $lang \ + --out-path . +``` +## Training +```shell +mkdir -p checkpoints +CUDA_VISIBLE_DEVICES=1 python $FAIRSEQ/train.py data-bin/mustc_en_de \ + --save-dir checkpoints \ + --arch berard_simul_text_iwslt \ + --waitk-lagging 2 \ + --waitk-stride 10 \ + --input-feat-per-channel 40 \ + --encoder-hidden-size 512 \ + --output-layer-dim 128 \ + --decoder-num-layers 3 \ + --task speech_translation \ + --user-dir $FAIRSEQ/examples/simultaneous_translation + --optimizer adam \ + --max-epoch 100 \ + --lr 0.001 \ + --clip-norm 5.0 \ + --batch-size 128 \ + --log-format json \ + --log-interval 10 \ + --criterion cross_entropy_acc \ + --user-dir $FAIRSEQ/examples/simultaneous_translation +``` + +## Evaluation +--- +### Evaluation Server +For text translation models, the server is set up as follow give input file and reference file. + +``` shell +python ./eval/server.py \ + --hostname localhost \ + --port 12321 \ + --src-file $DATA_ROOT/data/dev/txt/dev.en \ + --ref-file $DATA_ROOT/data/dev/txt/dev.de +``` +For speech translation models, the input is the data direcrory. +``` shell +python ./eval/server.py \ + --hostname localhost \ + --port 12321 \ + --ref-file $DATA_ROOT \ + --data-type speech +``` + +### Decode and Evaluate with Client +Once the server is set up, run client to evaluate translation quality and latency. +```shell +# TEXT +python $fairseq_dir/examples/simultaneous_translation/evaluate.py \ + data-bin/mustc_en_de \ + --user-dir $FAIRSEQ/examples/simultaneous_translation \ + --src-spm unigram-en-10000-3000/spm.model\ + --tgt-spm unigram-de-10000-3000/spm.model\ + -s en -t de \ + --path checkpoints/checkpoint_best.pt + +# SPEECH +python $fairseq_dir/examples/simultaneous_translation/evaluate.py \ + data-bin/mustc_en_de \ + --user-dir $FAIRSEQ/examples/simultaneous_translation \ + --data-type speech \ + --tgt-spm unigram-de-10000-3000/spm.model\ + -s en -t de \ + --path checkpoints/checkpoint_best.pt +``` diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/docs/evaluation.md b/fairseq-tools/fairseq/examples/simultaneous_translation/docs/evaluation.md new file mode 100644 index 00000000..c5340735 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/docs/evaluation.md @@ -0,0 +1,115 @@ +# Introduction to evaluation interface +The simultaneous translation models from sharedtask participents are evaluated under a server-client protocol. The participents are requisted to plug in their own model API in the protocol, and submit a docker file. + +## Server-Client Protocol +An server-client protocol that will be used in evaluation. For example, when a *wait-k* model (k=3) translate the English sentence "Alice and Bob are good friends" to Genman sentence "Alice und Bob sind gute Freunde." , the evaluation process is shown as following figure. + +While every time client needs to read a new state (word or speech utterence), a "GET" request is supposed to sent over to server. Whenever a new token is generated, a "SEND" request with the word predicted (untokenized word) will be sent to server immediately. The server can hence calculate both latency and BLEU score of the sentence. + +### Server +The server code is provided and can be set up directly locally for development purpose. For example, to evaluate a text simultaneous test set, + +```shell + + python fairseq/examples/simultaneous_translation/eval/server.py \ + --hostname local_host \ + --port 1234 \ + --src-file SRC_FILE \ + --ref-file REF_FILE \ + --data-type text \ +``` +The state that server sent to client is has the following format +```json +{ + 'sent_id': Int, + 'segment_id': Int, + 'segment': String +} +``` + +### Client +The client will handle the evaluation process mentioned above. It should be out-of-box as well. The client's protocol is as following table + +|Action|Content| +|:---:|:---:| +|Request new word / utterence| ```{key: "Get", value: None}```| +|Predict word "W"| ```{key: "SEND", value: "W"}```| + + + +The core of the client module is the agent, which needs to be modified to different models accordingly. The abstract class of agent is as follow, the evaluation process happens in the `decode()` function. +```python +class Agent(object): + "an agent needs to follow this pattern" + def __init__(self, *args, **kwargs): + ... + + def init_states(self): + # Initializing states + ... + + def update_states(self, states, new_state): + # Update states with given new state from server + # TODO (describe the states) + ... + + def finish_eval(self, states, new_state): + # Check if evaluation is finished + ... + + def policy(self, state: list) -> dict: + # Provide a action given current states + # The action can only be either + # {key: "GET", value: NONE} + # or + # {key: "SEND", value: W} + ... + + def reset(self): + # Reset agent + ... + + def decode(self, session): + + states = self.init_states() + self.reset() + + # Evaluataion protocol happens here + while True: + # Get action from the current states according to self.policy() + action = self.policy(states) + + if action['key'] == GET: + # Read a new state from server + new_state = session.get_src() + states = self.update_states(states, new_state) + + if self.finish_eval(states, new_state): + # End of document + break + + elif action['key'] == SEND: + # Send a new prediction to server + session.send_hypo(action['value']) + + # Clean the history, wait for next sentence + if action['value'] == DEFAULT_EOS: + states = self.init_states() + self.reset() + else: + raise NotImplementedError + + +``` +Here an implementation of agent of text [*wait-k* model](somelink). Notice that the tokenization is not considered. + +## Quality +The quality is measured by detokenized BLEU. So make sure that the predicted words sent to server are detokenized. An implementation is can be find [here](some link) + +## Latency +The latency metrics are +* Average Proportion +* Average Lagging +* Differentiable Average Lagging +Again Thery will also be evaluated on detokenized text. + diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/__init__.py new file mode 100644 index 00000000..62642369 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/__init__.py new file mode 100644 index 00000000..511e7b24 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/__init__.py @@ -0,0 +1,24 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + +from fairseq import registry + + +build_agent, register_agent, MONOTONIC_AGENT, _ = registry.setup_registry( + "--agent-type" +) + + +DEFAULT_EOS = "
" +GET = 0 +SEND = 1 + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("agents." + module) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/agent.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/agent.py new file mode 100644 index 00000000..997392cf --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/agent.py @@ -0,0 +1,67 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import time +from functools import partial +from multiprocessing.pool import ThreadPool as Pool + +from . import DEFAULT_EOS, GET, SEND + + +class Agent(object): + "an agent needs to follow this pattern" + + def __init__(self, *args, **kwargs): + pass + + def init_states(self, *args, **kwargs): + raise NotImplementedError + + def update_states(self, states, new_state): + raise NotImplementedError + + def finish_eval(self, states, new_state): + raise NotImplementedError + + def policy(self, state): + raise NotImplementedError + + def reset(self): + raise NotImplementedError + + def decode(self, session, low=0, high=100000, num_thread=10): + corpus_info = session.corpus_info() + high = min(corpus_info["num_sentences"] - 1, high) + if low >= high: + return + + t0 = time.time() + if num_thread > 1: + with Pool(10) as p: + p.map( + partial(self._decode_one, session), + [sent_id for sent_id in range(low, high + 1)], + ) + else: + for sent_id in range(low, high + 1): + self._decode_one(session, sent_id) + + print(f"Finished {low} to {high} in {time.time() - t0}s") + + def _decode_one(self, session, sent_id): + action = {} + self.reset() + states = self.init_states() + while action.get("value", None) != DEFAULT_EOS: + # take an action + action = self.policy(states) + + if action["key"] == GET: + new_states = session.get_src(sent_id, action["value"]) + states = self.update_states(states, new_states) + + elif action["key"] == SEND: + session.send_hypo(sent_id, action["value"]) + print(" ".join(states["tokens"]["tgt"])) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_agent.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_agent.py new file mode 100644 index 00000000..071b9e89 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_agent.py @@ -0,0 +1,167 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +import os + +from fairseq import checkpoint_utils, tasks, utils + +from . import DEFAULT_EOS, GET, SEND +from .agent import Agent + + +class SimulTransAgent(Agent): + def __init__(self, args): + # Load Model + self.load_model(args) + + # build word spliter + self.build_word_splitter(args) + + self.max_len = args.max_len + + self.eos = DEFAULT_EOS + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--model-path', type=str, required=True, + help='path to your pretrained model.') + parser.add_argument("--data-bin", type=str, required=True, + help="Path of data binary") + parser.add_argument("--user-dir", type=str, default="example/simultaneous_translation", + help="User directory for simultaneous translation") + parser.add_argument("--src-splitter-type", type=str, default=None, + help="Subword splitter type for source text") + parser.add_argument("--tgt-splitter-type", type=str, default=None, + help="Subword splitter type for target text") + parser.add_argument("--src-splitter-path", type=str, default=None, + help="Subword splitter model path for source text") + parser.add_argument("--tgt-splitter-path", type=str, default=None, + help="Subword splitter model path for target text") + parser.add_argument("--max-len", type=int, default=150, + help="Maximum length difference between source and target prediction") + parser.add_argument('--model-overrides', default="{}", type=str, metavar='DICT', + help='A dictionary used to override model args at generation ' + 'that were used during model training') + # fmt: on + return parser + + def load_dictionary(self, task): + raise NotImplementedError + + def load_model(self, args): + args.user_dir = os.path.join(os.path.dirname(__file__), "..", "..") + utils.import_user_module(args) + filename = args.model_path + if not os.path.exists(filename): + raise IOError("Model file not found: {}".format(filename)) + + state = checkpoint_utils.load_checkpoint_to_cpu( + filename, json.loads(args.model_overrides) + ) + + saved_args = state["args"] + saved_args.data = args.data_bin + + task = tasks.setup_task(saved_args) + + # build model for ensemble + self.model = task.build_model(saved_args) + self.model.load_state_dict(state["model"], strict=True) + + # Set dictionary + self.load_dictionary(task) + + def init_states(self): + return { + "indices": {"src": [], "tgt": []}, + "tokens": {"src": [], "tgt": []}, + "segments": {"src": [], "tgt": []}, + "steps": {"src": 0, "tgt": 0}, + "finished": False, + "finish_read": False, + "model_states": {}, + } + + def update_states(self, states, new_state): + raise NotImplementedError + + def policy(self, states): + # Read and Write policy + action = None + + while action is None: + if states["finished"]: + # Finish the hypo by sending eos to server + return self.finish_action() + + # Model make decision given current states + decision = self.model.decision_from_states(states) + + if decision == 0 and not self.finish_read(states): + # READ + action = self.read_action(states) + else: + # WRITE + action = self.write_action(states) + + # None means we make decision again but not sending server anything + # This happened when read a bufffered token + # Or predict a subword + return action + + def finish_read(self, states): + raise NotImplementedError + + def write_action(self, states): + token, index = self.model.predict_from_states(states) + + if ( + index == self.dict["tgt"].eos() + or len(states["tokens"]["tgt"]) > self.max_len + ): + # Finish this sentence is predict EOS + states["finished"] = True + end_idx_last_full_word = self._target_length(states) + + else: + states["tokens"]["tgt"] += [token] + end_idx_last_full_word = self.word_splitter["tgt"].end_idx_last_full_word( + states["tokens"]["tgt"] + ) + self._append_indices(states, [index], "tgt") + + if end_idx_last_full_word > states["steps"]["tgt"]: + # Only sent detokenized full words to the server + word = self.word_splitter["tgt"].merge( + states["tokens"]["tgt"][states["steps"]["tgt"] : end_idx_last_full_word] + ) + states["steps"]["tgt"] = end_idx_last_full_word + states["segments"]["tgt"] += [word] + + return {"key": SEND, "value": word} + else: + return None + + def read_action(self, states): + return {"key": GET, "value": None} + + def finish_action(self): + return {"key": SEND, "value": DEFAULT_EOS} + + def reset(self): + pass + + def finish_eval(self, states, new_state): + if len(new_state) == 0 and len(states["indices"]["src"]) == 0: + return True + return False + + def _append_indices(self, states, new_indices, key): + states["indices"][key] += new_indices + + def _target_length(self, states): + return len(states["tokens"]["tgt"]) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_text_agent.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_text_agent.py new file mode 100644 index 00000000..7c34817b --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/simul_trans_text_agent.py @@ -0,0 +1,81 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import DEFAULT_EOS, GET, register_agent +from .simul_trans_agent import SimulTransAgent +from .word_splitter import SPLITTER_DICT + + +@register_agent("simul_trans_text") +class SimulTransTextAgent(SimulTransAgent): + def build_word_splitter(self, args): + self.word_splitter = {} + + self.word_splitter["src"] = SPLITTER_DICT[args.src_splitter_type]( + getattr(args, f"src_splitter_path") + ) + self.word_splitter["tgt"] = SPLITTER_DICT[args.tgt_splitter_type]( + getattr(args, f"tgt_splitter_path") + ) + + def load_dictionary(self, task): + self.dict = {} + self.dict["tgt"] = task.target_dictionary + self.dict["src"] = task.source_dictionary + + def update_states(self, states, new_state): + if states["finish_read"]: + return states + + new_word = new_state["segment"] + + # Split words and index the token + if new_word not in [DEFAULT_EOS]: + tokens = self.word_splitter["src"].split(new_word) + # Get indices from dictionary + # You can change to you own dictionary + indices = ( + self.dict["src"] + .encode_line( + tokens, + line_tokenizer=lambda x: x, + add_if_not_exist=False, + append_eos=False, + ) + .tolist() + ) + else: + tokens = [new_word] + indices = [self.dict["src"].eos()] + states["finish_read"] = True + + # Update states + states["segments"]["src"] += [new_word] + states["tokens"]["src"] += tokens + self._append_indices(states, indices, "src") + + return states + + def read_action(self, states): + # Increase source step by one + states["steps"]["src"] += 1 + + # At leat one word is read + if len(states["tokens"]["src"]) == 0: + return {"key": GET, "value": None} + + # Only request new word if there is no buffered tokens + if len(states["tokens"]["src"]) <= states["steps"]["src"]: + return {"key": GET, "value": None} + + return None + + def finish_read(self, states): + # The first means all segments (full words) has been read from server + # The second means all tokens (subwords) has been read locally + return ( + states["finish_read"] + and len(states["tokens"]["src"]) == states["steps"]["src"] + ) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/word_splitter.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/word_splitter.py new file mode 100644 index 00000000..c3f71200 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/agents/word_splitter.py @@ -0,0 +1,91 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +class SubwordSplitter(object): + def process_line(self, string): + raise NotImplementedError + + def split(self, string): + raise NotImplementedError + + +class NoneWordSplitter(object): + def __init__(self, model): + pass + + def split(self, string): + return [string] + + def process_line(self, string): + return [string] + + def finished_word(self, string): + return True + + def merge(self, list_of_string): + return "".join(list_of_string) + + def last_full_word_step(self, tokens, step): + return len(tokens) + + def end_idx_last_full_word(self, tokens): + return len(tokens) + + +class BPEWordSplitter(object): + # TODO: lock back here + def __init__(self, model_path): + super().__init__() + from subword_nmt.apply_bpe import BPE + + with open(model_path) as f: + self.model = BPE(f) + + def split(self, string): + return self.model.process_line(string).split() + + def end_idx_last_full_word(self, tokens): + # Begin of word indices + bow_indices = [0] + [i + 1 for i, t in enumerate(tokens[1:]) if t[-2:] != "@@"] + + if len(bow_indices) < 2: + return 0 + else: + return bow_indices[-1] + + def merge(self, list_of_string): + return " ".join([item.replace("@@", "") for item in list_of_string]) + + +class SentencePieceModelWordSplitter(object): + def __init__(self, model_path): + super().__init__() + import sentencepiece as spm + + self.model = spm.SentencePieceProcessor() + self.model.Load(model_path) + + def split(self, string): + return self.model.EncodeAsPieces(string) + + def end_idx_last_full_word(self, tokens): + # Begin of word indices + bow_indices = [i for i, t in enumerate(tokens) if t[0] == "\u2581"] + + if len(bow_indices) < 2: + return 0 + else: + return bow_indices[-1] + + def merge(self, list_of_string): + return self.model.DecodePieces(list_of_string) + + +SPLITTER_DICT = { + None: NoneWordSplitter, + "BPE": BPEWordSplitter, + "SentencePieceModel": SentencePieceModelWordSplitter, +} diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/client.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/client.py new file mode 100644 index 00000000..3ca4ea73 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/client.py @@ -0,0 +1,100 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Optional + +import requests +from scorers import build_scorer + + +class SimulSTEvaluationService(object): + DEFAULT_HOSTNAME = "localhost" + DEFAULT_PORT = 12321 + + def __init__(self, hostname=DEFAULT_HOSTNAME, port=DEFAULT_PORT): + self.hostname = hostname + self.port = port + self.base_url = f"http://{self.hostname}:{self.port}" + + def __enter__(self): + self.new_session() + + def __exit__(self, exc_type, exc_val, exc_tb): + pass + + def new_session(self): + # start eval session + url = f"{self.base_url}" + + try: + _ = requests.post(url) + except Exception as e: + print(f"Failed to start an evaluation session: {e}") + + print("Evaluation session started.") + return self + + def get_scores(self): + # end eval session + url = f"{self.base_url}/result" + try: + r = requests.get(url) + print("Scores: {}".format(r.json())) + print("Evaluation session finished.") + except Exception as e: + print(f"Failed to end an evaluation session: {e}") + + def get_src(self, sent_id: int, extra_params: Optional[dict] = None) -> str: + url = f"{self.base_url}/src" + params = {"sent_id": sent_id} + if extra_params is not None: + for key in extra_params.keys(): + params[key] = extra_params[key] + try: + r = requests.get(url, params=params) + except Exception as e: + print(f"Failed to request a source segment: {e}") + return r.json() + + def send_hypo(self, sent_id: int, hypo: str) -> None: + url = f"{self.base_url}/hypo" + params = {"sent_id": sent_id} + + try: + requests.put(url, params=params, data=hypo.encode("utf-8")) + except Exception as e: + print(f"Failed to send a translated segment: {e}") + + def corpus_info(self): + url = f"{self.base_url}" + try: + r = requests.get(url) + except Exception as e: + print(f"Failed to request corpus information: {e}") + + return r.json() + + +class SimulSTLocalEvaluationService(object): + def __init__(self, args): + self.scorer = build_scorer(args) + + def get_scores(self): + return self.scorer.score() + + def get_src(self, sent_id: int, extra_params: Optional[dict] = None) -> str: + if extra_params is not None: + segment_size = extra_params.get("segment_size", None) + else: + segment_size = None + + return self.scorer.send_src(int(sent_id), segment_size) + + def send_hypo(self, sent_id: int, hypo: str) -> None: + list_of_tokens = hypo.strip().split() + self.scorer.recv_hyp(sent_id, list_of_tokens) + + def corpus_info(self): + return self.scorer.get_info() diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/eval_latency.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/eval_latency.py new file mode 100644 index 00000000..50021de4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/eval_latency.py @@ -0,0 +1,78 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import json + +import torch +from examples.simultaneous_translation.utils.latency import LatencyInference + + +LATENCY_METRICS = [ + "differentiable_average_lagging", + "average_lagging", + "average_proportion", +] + + +class LatencyScorer: + def __init__(self, start_from_zero=True): + self.recorder = [] + self.scores = {} + self.scorer = LatencyInference() + self.start_from_zero = start_from_zero + + def update_reorder(self, list_of_dict): + self.recorder = [] + for info in list_of_dict: + delays = [int(x) - int(not self.start_from_zero) for x in info["delays"]] + delays = torch.LongTensor(delays).unsqueeze(0) + src_len = torch.LongTensor([info["src_len"]]).unsqueeze(0) + + self.recorder.append(self.scorer(delays, src_len)) + + def cal_latency(self): + self.scores = {} + for metric in LATENCY_METRICS: + self.scores[metric] = sum( + [x[metric][0, 0].item() for x in self.recorder] + ) / len(self.recorder) + return self.scores + + @classmethod + def score(cls, list_of_dict, start_from_zero=True): + scorer_to_return = cls(start_from_zero) + scorer_to_return.update_reorder(list_of_dict) + scorer_to_return.cal_latency() + return scorer_to_return.scores + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--input", required=True) + parser.add_argument("--start-from-zero", action="store_true") + args = parser.parse_args() + + scorer = LatencyInference() + recorder = [] + with open(args.input, "r") as f: + for line in f: + info = json.loads(line) + + delays = [int(x) - int(not args.start_from_zero) for x in info["delays"]] + + delays = torch.LongTensor(delays).unsqueeze(0) + + src_len = torch.LongTensor([info["src_len"]]).unsqueeze(0) + + recorder.append(scorer(delays, src_len)) + + average_results = {} + + for metric in LATENCY_METRICS: + average_results[metric] = sum([x[metric][0, 0].item() for x in recorder]) / len( + recorder + ) + print(f"{metric}: {average_results[metric]}") diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/evaluate.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/evaluate.py new file mode 100644 index 00000000..2f747462 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/evaluate.py @@ -0,0 +1,81 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse + +from agents import build_agent +from client import SimulSTEvaluationService, SimulSTLocalEvaluationService +from fairseq.registry import REGISTRIES + + +DEFAULT_HOSTNAME = "localhost" +DEFAULT_PORT = 12321 + + +def get_args(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "--hostname", type=str, default=DEFAULT_HOSTNAME, help="server hostname" + ) + parser.add_argument( + "--port", type=int, default=DEFAULT_PORT, help="server port number" + ) + parser.add_argument("--agent-type", default="simul_trans_text", help="Agent type") + parser.add_argument("--scorer-type", default="text", help="Scorer type") + parser.add_argument( + "--start-idx", + type=int, + default=0, + help="Start index of the sentence to evaluate", + ) + parser.add_argument( + "--end-idx", + type=int, + default=float("inf"), + help="End index of the sentence to evaluate", + ) + parser.add_argument( + "--scores", action="store_true", help="Request scores from server" + ) + parser.add_argument("--reset-server", action="store_true", help="Reset the server") + parser.add_argument( + "--num-threads", type=int, default=10, help="Number of threads used by agent" + ) + parser.add_argument( + "--local", action="store_true", default=False, help="Local evaluation" + ) + + args, _ = parser.parse_known_args() + + for registry_name, REGISTRY in REGISTRIES.items(): + choice = getattr(args, registry_name, None) + if choice is not None: + cls = REGISTRY["registry"][choice] + if hasattr(cls, "add_args"): + cls.add_args(parser) + args = parser.parse_args() + + return args + + +if __name__ == "__main__": + args = get_args() + + if args.local: + session = SimulSTLocalEvaluationService(args) + else: + session = SimulSTEvaluationService(args.hostname, args.port) + + if args.reset_server: + session.new_session() + + if args.agent_type is not None: + agent = build_agent(args) + agent.decode(session, args.start_idx, args.end_idx, args.num_threads) + + if args.scores: + session.get_scores() + print(session.get_scores()) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/__init__.py new file mode 100644 index 00000000..0a0e0a05 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/__init__.py @@ -0,0 +1,19 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + +from fairseq import registry + + +(build_scorer, register_scorer, SCORER_REGISTRIES, _) = registry.setup_registry( + "--scorer-type" +) + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("scorers." + module) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/scorer.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/scorer.py new file mode 100644 index 00000000..d6d3e30a --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/scorer.py @@ -0,0 +1,175 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +import os +from collections import defaultdict + +from examples.simultaneous_translation.eval.eval_latency import LatencyScorer +from vizseq.scorers.bleu import BLEUScorer +from vizseq.scorers.meteor import METEORScorer +from vizseq.scorers.ter import TERScorer + + +DEFAULT_EOS = "
" + + +class SimulScorer(object): + def __init__(self, args): + self.tokenizer = args.tokenizer + self.output_dir = args.output + if args.output is not None: + self.output_files = { + "text": os.path.join(args.output, "text"), + "delay": os.path.join(args.output, "delay"), + "scores": os.path.join(args.output, "scores"), + } + else: + self.output_files = None + self.eos = DEFAULT_EOS + self.data = {"tgt": []} + self.reset() + + def get_info(self): + return {"num_sentences": len(self)} + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--src-file', type=str, required=True, + help='Source input file') + parser.add_argument('--tgt-file', type=str, required=True, + help='Target reference file') + parser.add_argument('--tokenizer', default="13a", choices=["none", "13a"], + help='Tokenizer used for sacrebleu') + parser.add_argument('--output', type=str, default=None, + help='Path for output directory') + # fmt: on + + def send_src(self, sent_id, *args): + raise NotImplementedError + + def recv_hyp(self, sent_id, list_of_tokens): + for token in list_of_tokens: + self.translations[sent_id].append((token, self.steps[sent_id])) + + def reset(self): + self.steps = defaultdict(int) + self.translations = defaultdict(list) + + def src_lengths(self): + raise NotImplementedError + + def score(self): + translations = [] + delays = [] + for i in range(1 + max(self.translations.keys())): + translations += [" ".join(t[0] for t in self.translations[i][:-1])] + delays += [[t[1] for t in self.translations[i]]] + + bleu_score = BLEUScorer( + sent_level=False, + corpus_level=True, + extra_args={"bleu_tokenizer": self.tokenizer}, + ).score(translations, [self.data["tgt"]]) + + ter_score = TERScorer(sent_level=False, corpus_level=True).score( + translations, [self.data["tgt"]] + ) + meteor_score = METEORScorer(sent_level=False, corpus_level=True).score( + translations, [self.data["tgt"]] + ) + + latency_score = LatencyScorer().score( + [ + {"src_len": src_len, "delays": delay} + for src_len, delay in zip(self.src_lengths(), delays) + ], + start_from_zero=False, + ) + + scores = { + "BLEU": bleu_score[0], + "TER": ter_score[0], + "METEOR": meteor_score[0], + "DAL": latency_score["differentiable_average_lagging"], + "AL": latency_score["average_lagging"], + "AP": latency_score["average_proportion"], + } + + if self.output_files is not None: + try: + os.makedirs(self.output_dir, exist_ok=True) + self.write_results_to_file(translations, delays, scores) + except BaseException as be: + print(f"Failed to write results to {self.output_dir}.") + print(be) + print("Skip writing predictions") + + return scores + + def write_results_to_file(self, translations, delays, scores): + if self.output_files["text"] is not None: + with open(self.output_files["text"], "w") as f: + for line in translations: + f.write(line + "\n") + + if self.output_files["delay"] is not None: + with open(self.output_files["delay"], "w") as f: + for i, delay in enumerate(delays): + f.write( + json.dumps({"src_len": self.src_lengths()[i], "delays": delay}) + + "\n" + ) + + with open(self.output_files["scores"], "w") as f: + for key, value in scores.items(): + f.write(f"{key}, {value}\n") + + @classmethod + def _load_text_file(cls, file, split=False): + with open(file) as f: + if split: + return [r.strip().split() for r in f] + else: + return [r.strip() for r in f] + + @classmethod + def _load_text_from_json(cls, file): + list_to_return = [] + with open(file) as f: + content = json.load(f) + for item in content["utts"].values(): + list_to_return.append(item["output"]["text"].strip()) + return list_to_return + + @classmethod + def _load_wav_info_from_json(cls, file): + list_to_return = [] + with open(file) as f: + content = json.load(f) + for item in content["utts"].values(): + list_to_return.append( + { + "path": item["input"]["path"].strip(), + "length": item["input"]["length_ms"], + } + ) + return list_to_return + + @classmethod + def _load_wav_info_from_list(cls, file): + list_to_return = [] + with open(file) as f: + for line in f: + list_to_return.append( + { + "path": line.strip(), + } + ) + return list_to_return + + def __len__(self): + return len(self.data["tgt"]) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/text_scorer.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/text_scorer.py new file mode 100644 index 00000000..649a2c7e --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/scorers/text_scorer.py @@ -0,0 +1,41 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import register_scorer +from .scorer import SimulScorer + + +@register_scorer("text") +class SimulTextScorer(SimulScorer): + def __init__(self, args): + super().__init__(args) + self.data = { + "src": self._load_text_file(args.src_file, split=True), + "tgt": self._load_text_file(args.tgt_file, split=False), + } + + def send_src(self, sent_id, *args): + if self.steps[sent_id] >= len(self.data["src"][sent_id]): + dict_to_return = { + "sent_id": sent_id, + "segment_id": self.steps[sent_id], + "segment": self.eos, + } + # Consider EOS + self.steps[sent_id] = len(self.data["src"][sent_id]) + 1 + else: + dict_to_return = { + "sent_id": sent_id, + "segment_id": self.steps[sent_id], + "segment": self.data["src"][sent_id][self.steps[sent_id]], + } + + self.steps[sent_id] += 1 + + return dict_to_return + + def src_lengths(self): + # +1 for eos + return [len(sent) + 1 for sent in self.data["src"]] diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/eval/server.py b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/server.py new file mode 100644 index 00000000..e44ceaff --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/eval/server.py @@ -0,0 +1,89 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +import argparse +import json +import sys + +from scorers import build_scorer +from tornado import ioloop, web + + +DEFAULT_HOSTNAME = "localhost" +DEFAULT_PORT = 12321 + + +class ScorerHandler(web.RequestHandler): + def initialize(self, scorer): + self.scorer = scorer + + +class EvalSessionHandler(ScorerHandler): + def post(self): + self.scorer.reset() + + def get(self): + r = json.dumps(self.scorer.get_info()) + self.write(r) + + +class ResultHandler(ScorerHandler): + def get(self): + r = json.dumps(self.scorer.score()) + self.write(r) + + +class SourceHandler(ScorerHandler): + def get(self): + sent_id = int(self.get_argument("sent_id")) + segment_size = None + if "segment_size" in self.request.arguments: + string = self.get_argument("segment_size") + if len(string) > 0: + segment_size = int(string) + + r = json.dumps(self.scorer.send_src(int(sent_id), segment_size)) + + self.write(r) + + +class HypothesisHandler(ScorerHandler): + def put(self): + sent_id = int(self.get_argument("sent_id")) + list_of_tokens = self.request.body.decode("utf-8").strip().split() + self.scorer.recv_hyp(sent_id, list_of_tokens) + + +def add_args(): + parser = argparse.ArgumentParser() + # fmt: off + parser.add_argument('--hostname', type=str, default=DEFAULT_HOSTNAME, + help='Server hostname') + parser.add_argument('--port', type=int, default=DEFAULT_PORT, + help='Server port number') + + args, _ = parser.parse_known_args() + # fmt: on + return args + + +def start_server(scorer, hostname=DEFAULT_HOSTNAME, port=DEFAULT_PORT, debug=False): + app = web.Application( + [ + (r"/result", ResultHandler, dict(scorer=scorer)), + (r"/src", SourceHandler, dict(scorer=scorer)), + (r"/hypo", HypothesisHandler, dict(scorer=scorer)), + (r"/", EvalSessionHandler, dict(scorer=scorer)), + ], + debug=debug, + ) + app.listen(port, max_buffer_size=1024 ** 3) + sys.stdout.write(f"Evaluation Server Started. Listening to port {port}\n") + ioloop.IOLoop.current().start() + + +if __name__ == "__main__": + args = add_args() + scorer = build_scorer(args) + start_server(scorer, args.hostname, args.port, args.debug) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/models/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/models/__init__.py new file mode 100644 index 00000000..083da437 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/models/__init__.py @@ -0,0 +1,15 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + model_name = file[: file.find(".py")] + importlib.import_module( + "examples.simultaneous_translation.models." + model_name + ) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/models/transformer_monotonic_attention.py b/fairseq-tools/fairseq/examples/simultaneous_translation/models/transformer_monotonic_attention.py new file mode 100644 index 00000000..ab8adf3a --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/models/transformer_monotonic_attention.py @@ -0,0 +1,322 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F +from examples.simultaneous_translation.modules.monotonic_transformer_layer import ( + TransformerMonotonicDecoderLayer, + TransformerMonotonicEncoderLayer, +) +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer import ( + TransformerDecoder, + TransformerEncoder, + TransformerModel, + base_architecture, + transformer_iwslt_de_en, + transformer_vaswani_wmt_en_de_big, +) + + +DEFAULT_MAX_SOURCE_POSITIONS = 1024 +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@register_model("transformer_unidirectional") +class TransformerUnidirectionalModel(TransformerModel): + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerMonotonicEncoder(args, src_dict, embed_tokens) + + +@register_model("transformer_monotonic") +class TransformerMonotonicModel(TransformerModel): + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerMonotonicEncoder(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerMonotonicDecoder(args, tgt_dict, embed_tokens) + + def _indices_from_states(self, states): + if type(states["indices"]["src"]) == list: + if next(self.parameters()).is_cuda: + tensor = torch.cuda.LongTensor + else: + tensor = torch.LongTensor + + src_indices = tensor( + [states["indices"]["src"][: 1 + states["steps"]["src"]]] + ) + + tgt_indices = tensor( + [[self.decoder.dictionary.eos()] + states["indices"]["tgt"]] + ) + else: + src_indices = states["indices"]["src"][: 1 + states["steps"]["src"]] + tgt_indices = states["indices"]["tgt"] + + return src_indices, None, tgt_indices + + def predict_from_states(self, states): + decoder_states = self.decoder.output_layer(states["decoder_features"]) + lprobs = self.get_normalized_probs([decoder_states[:, -1:]], log_probs=True) + + index = lprobs.argmax(dim=-1) + + token = self.decoder.dictionary.string(index) + + return token, index[0, 0].item() + + def decision_from_states(self, states): + """ + This funcion take states dictionary as input, and gives the agent + a decision of whether read a token from server. Moreover, the decoder + states are also calculated here so we can directly generate a target + token without recompute every thing + """ + + self.eval() + + if len(states["tokens"]["src"]) == 0: + return 0 + + src_indices, src_lengths, tgt_indices = self._indices_from_states(states) + + # Update encoder states if needed + if ( + "encoder_states" not in states + or states["encoder_states"][0].size(1) <= states["steps"]["src"] + ): + encoder_out_dict = self.encoder(src_indices, src_lengths) + states["encoder_states"] = encoder_out_dict + else: + encoder_out_dict = states["encoder_states"] + + # online means we still need tokens to feed the model + states["model_states"]["online"] = not ( + states["finish_read"] + and len(states["tokens"]["src"]) == states["steps"]["src"] + ) + + states["model_states"]["steps"] = states["steps"] + + x, outputs = self.decoder.forward( + prev_output_tokens=tgt_indices, + encoder_out=encoder_out_dict, + incremental_state=states["model_states"], + features_only=True, + ) + + states["decoder_features"] = x + + return outputs["action"] + + +class TransformerMonotonicEncoder(TransformerEncoder): + def __init__(self, args, dictionary, embed_tokens): + super().__init__(args, dictionary, embed_tokens) + + self.dictionary = dictionary + self.layers = nn.ModuleList([]) + self.layers.extend( + [TransformerMonotonicEncoderLayer(args) for i in range(args.encoder_layers)] + ) + + +class TransformerMonotonicDecoder(TransformerDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__(args, dictionary, embed_tokens, no_encoder_attn=False) + + self.dictionary = dictionary + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + TransformerMonotonicDecoderLayer(args, no_encoder_attn) + for _ in range(args.decoder_layers) + ] + ) + + def pre_attention( + self, prev_output_tokens, encoder_out_dict, incremental_state=None + ): + positions = ( + self.embed_positions( + prev_output_tokens, + incremental_state=incremental_state, + ) + if self.embed_positions is not None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + if positions is not None: + positions = positions[:, -1:] + + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + x = self.dropout_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + encoder_out = encoder_out_dict.encoder_out + encoder_padding_mask = encoder_out_dict.encoder_padding_mask + + return x, encoder_out, encoder_padding_mask + + def post_attention(self, x): + if self.layer_norm: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + + return x + + def extract_features( + self, prev_output_tokens, encoder_out, incremental_state=None, **unused + ): + """ + Similar to *forward* but only return features. + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + # incremental_state = None + (x, encoder_outs, encoder_padding_mask) = self.pre_attention( + prev_output_tokens, encoder_out, incremental_state + ) + attn = None + inner_states = [x] + attn_list = [] + step_list = [] + + for i, layer in enumerate(self.layers): + + x, attn, _ = layer( + x=x, + encoder_out=encoder_outs, + encoder_padding_mask=encoder_padding_mask, + incremental_state=incremental_state, + self_attn_mask=self.buffered_future_mask(x) + if incremental_state is None + else None, + ) + + inner_states.append(x) + attn_list.append(attn) + + if incremental_state is not None: + curr_steps = layer.get_steps(incremental_state) + step_list.append(curr_steps) + + if incremental_state.get("online", False): + p_choose = ( + attn["p_choose"].squeeze(0).squeeze(1).gather(1, curr_steps.t()) + ) + + new_steps = curr_steps + (p_choose < 0.5).t().type_as(curr_steps) + + if (new_steps >= incremental_state["steps"]["src"]).any(): + # We need to prune the last self_attn saved_state + # if model decide not to read + # otherwise there will be duplicated saved_state + for j in range(i + 1): + self.layers[j].prune_incremental_state(incremental_state) + + return x, {"action": 0} + + if incremental_state is not None and not incremental_state.get("online", False): + # Here is for fast evaluation + fastest_step = ( + torch.max(torch.cat(step_list, dim=1), dim=1, keepdim=True)[0] + 1 + ) + + if "fastest_step" in incremental_state: + incremental_state["fastest_step"] = torch.cat( + [incremental_state["fastest_step"], fastest_step], dim=1 + ) + else: + incremental_state["fastest_step"] = fastest_step + + x = self.post_attention(x) + + return x, { + "action": 1, + "attn_list": attn_list, + "step_list": step_list, + "encoder_out": encoder_out, + "encoder_padding_mask": encoder_padding_mask, + } + + def reorder_incremental_state(self, incremental_state, new_order): + super().reorder_incremental_state(incremental_state, new_order) + if "fastest_step" in incremental_state: + incremental_state["fastest_step"] = incremental_state[ + "fastest_step" + ].index_select(0, new_order) + + +@register_model_architecture("transformer_monotonic", "transformer_monotonic") +def base_monotonic_rchitecture(args): + base_architecture(args) + args.encoder_unidirectional = getattr(args, "encoder_unidirectional", False) + + +@register_model_architecture( + "transformer_monotonic", "transformer_monotonic_iwslt_de_en" +) +def transformer_monotonic_iwslt_de_en(args): + transformer_iwslt_de_en(args) + base_monotonic_rchitecture(args) + + +# parameters used in the "Attention Is All You Need" paper (Vaswani et al., 2017) +@register_model_architecture( + "transformer_monotonic", "transformer_monotonic_vaswani_wmt_en_de_big" +) +def transformer_monotonic_vaswani_wmt_en_de_big(args): + transformer_vaswani_wmt_en_de_big(args) + + +@register_model_architecture( + "transformer_monotonic", "transformer_monotonic_vaswani_wmt_en_fr_big" +) +def transformer_monotonic_vaswani_wmt_en_fr_big(args): + transformer_monotonic_vaswani_wmt_en_fr_big(args) + + +@register_model_architecture( + "transformer_unidirectional", "transformer_unidirectional_iwslt_de_en" +) +def transformer_unidirectional_iwslt_de_en(args): + transformer_iwslt_de_en(args) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/modules/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/__init__.py new file mode 100644 index 00000000..ad64774d --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/__init__.py @@ -0,0 +1,24 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + +from fairseq import registry + + +( + build_monotonic_attention, + register_monotonic_attention, + MONOTONIC_ATTENTION_REGISTRY, + _, +) = registry.setup_registry("--simul-type") + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + model_name = file[: file.find(".py")] + importlib.import_module( + "examples.simultaneous_translation.modules." + model_name + ) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_multihead_attention.py b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_multihead_attention.py new file mode 100644 index 00000000..c09725ac --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_multihead_attention.py @@ -0,0 +1,622 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F +from examples.simultaneous_translation.utils.functions import ( + exclusive_cumprod, + lengths_to_mask, +) +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules import MultiheadAttention +from fairseq.utils import convert_padding_direction + +from . import register_monotonic_attention + + +@with_incremental_state +class MonotonicAttention(nn.Module): + """ + Abstract class of monotonic attentions + """ + + def __init__(self, args): + self.eps = args.attention_eps + self.mass_preservation = args.mass_preservation + + self.noise_mean = args.noise_mean + self.noise_var = args.noise_var + + self.energy_bias_init = args.energy_bias_init + self.energy_bias = ( + nn.Parameter(self.energy_bias_init * torch.ones([1])) + if args.energy_bias is True + else 0 + ) + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--no-mass-preservation', action="store_false", dest="mass_preservation", + help='Do not stay on the last token when decoding') + parser.add_argument('--mass-preservation', action="store_true", dest="mass_preservation", + help='Stay on the last token when decoding') + parser.set_defaults(mass_preservation=True) + + parser.add_argument('--noise-var', type=float, default=1.0, + help='Variance of discretness noise') + parser.add_argument('--noise-mean', type=float, default=0.0, + help='Mean of discretness noise') + parser.add_argument('--energy-bias', action="store_true", default=False, + help='Bias for energy') + parser.add_argument('--energy-bias-init', type=float, default=-2.0, + help='Initial value of the bias for energy') + parser.add_argument('--attention-eps', type=float, default=1e-6, + help='Epsilon when calculating expected attention') + # fmt: on + + def p_choose(self, *args): + raise NotImplementedError + + def input_projections(self, *args): + raise NotImplementedError + + def attn_energy(self, q_proj, k_proj, key_padding_mask=None): + """ + Calculating monotonic energies + + ============================================================ + Expected input size + q_proj: bsz * num_heads, tgt_len, self.head_dim + k_proj: bsz * num_heads, src_len, self.head_dim + key_padding_mask: bsz, src_len + attn_mask: tgt_len, src_len + """ + bsz, tgt_len, embed_dim = q_proj.size() + bsz = bsz // self.num_heads + src_len = k_proj.size(1) + + attn_energy = torch.bmm(q_proj, k_proj.transpose(1, 2)) + self.energy_bias + + attn_energy = attn_energy.view(bsz, self.num_heads, tgt_len, src_len) + + if key_padding_mask is not None: + attn_energy = attn_energy.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2).bool(), + float("-inf"), + ) + + return attn_energy + + def expected_alignment_train(self, p_choose, key_padding_mask): + """ + Calculating expected alignment for MMA + Mask is not need because p_choose will be 0 if masked + + q_ij = (1 − p_{ij−1})q_{ij−1} + a+{i−1j} + a_ij = p_ij q_ij + + parellel solution: + ai = p_i * cumprod(1 − pi) * cumsum(a_i / cumprod(1 − pi)) + + ============================================================ + Expected input size + p_choose: bsz * num_heads, tgt_len, src_len + """ + + # p_choose: bsz * num_heads, tgt_len, src_len + bsz_num_heads, tgt_len, src_len = p_choose.size() + + # cumprod_1mp : bsz * num_heads, tgt_len, src_len + cumprod_1mp = exclusive_cumprod(1 - p_choose, dim=2, eps=self.eps) + cumprod_1mp_clamp = torch.clamp(cumprod_1mp, self.eps, 1.0) + + init_attention = p_choose.new_zeros([bsz_num_heads, 1, src_len]) + init_attention[:, :, 0] = 1.0 + + previous_attn = [init_attention] + + for i in range(tgt_len): + # p_choose: bsz * num_heads, tgt_len, src_len + # cumprod_1mp_clamp : bsz * num_heads, tgt_len, src_len + # previous_attn[i]: bsz * num_heads, 1, src_len + # alpha_i: bsz * num_heads, src_len + alpha_i = ( + p_choose[:, i] + * cumprod_1mp[:, i] + * torch.cumsum(previous_attn[i][:, 0] / cumprod_1mp_clamp[:, i], dim=1) + ).clamp(0, 1.0) + previous_attn.append(alpha_i.unsqueeze(1)) + + # alpha: bsz * num_heads, tgt_len, src_len + alpha = torch.cat(previous_attn[1:], dim=1) + + if self.mass_preservation: + # Last token has the residual probabilities + alpha[:, :, -1] = 1 - alpha[:, :, :-1].sum(dim=-1).clamp(0.0, 1.0) + + assert not torch.isnan(alpha).any(), "NaN detected in alpha." + + return alpha + + def expected_alignment_infer(self, p_choose, key_padding_mask, incremental_state): + """ + Calculating mo alignment for MMA during inference time + + ============================================================ + Expected input size + p_choose: bsz * num_heads, tgt_len, src_len + key_padding_mask: bsz * src_len + incremental_state: dict + """ + # p_choose: bsz * self.num_heads, src_len + bsz_num_heads, tgt_len, src_len = p_choose.size() + # One token at a time + assert tgt_len == 1 + p_choose = p_choose[:, 0, :] + + monotonic_cache = self._get_monotonic_buffer(incremental_state) + + # prev_monotonic_step: bsz, num_heads + bsz = bsz_num_heads // self.num_heads + prev_monotonic_step = monotonic_cache.get( + "step", p_choose.new_zeros([bsz, self.num_heads]).long() + ) + bsz, num_heads = prev_monotonic_step.size() + assert num_heads == self.num_heads + assert bsz * num_heads == bsz_num_heads + + # p_choose: bsz, num_heads, src_len + p_choose = p_choose.view(bsz, num_heads, src_len) + + if key_padding_mask is not None: + src_lengths = src_len - key_padding_mask.sum(dim=1, keepdim=True).long() + else: + src_lengths = prev_monotonic_step.new_ones(bsz, 1) * src_len + + # src_lengths: bsz, num_heads + src_lengths = src_lengths.expand_as(prev_monotonic_step) + # new_monotonic_step: bsz, num_heads + new_monotonic_step = prev_monotonic_step + + step_offset = 0 + if key_padding_mask is not None: + if key_padding_mask[:, 0].any(): + # left_pad_source = True: + step_offset = key_padding_mask.sum(dim=-1, keepdim=True) + + max_steps = src_lengths - 1 if self.mass_preservation else src_lengths + + # finish_read: bsz, num_heads + finish_read = new_monotonic_step.eq(max_steps) + + while finish_read.sum().item() < bsz * self.num_heads: + # p_choose: bsz * self.num_heads, src_len + # only choose the p at monotonic steps + # p_choose_i: bsz , self.num_heads + p_choose_i = ( + p_choose.gather( + 2, + (step_offset + new_monotonic_step) + .unsqueeze(2) + .clamp(0, src_len - 1), + ) + ).squeeze(2) + + action = ( + (p_choose_i < 0.5) + .type_as(prev_monotonic_step) + .masked_fill(finish_read, 0) + ) + # 1 x bsz + # sample actions on unfinished seq + # 1 means stay, finish reading + # 0 means leave, continue reading + # dist = torch.distributions.bernoulli.Bernoulli(p_choose) + # action = dist.sample().type_as(finish_read) * (1 - finish_read) + + new_monotonic_step += action + + finish_read = new_monotonic_step.eq(max_steps) | (action == 0) + # finish_read = (~ (finish_read.sum(dim=1, keepdim=True) < self.num_heads / 2)) | finish_read + + monotonic_cache["step"] = new_monotonic_step + + # alpha: bsz * num_heads, 1, src_len + # new_monotonic_step: bsz, num_heads + alpha = p_choose.new_zeros([bsz * self.num_heads, src_len]).scatter( + 1, + (step_offset + new_monotonic_step) + .view(bsz * self.num_heads, 1) + .clamp(0, src_len - 1), + 1, + ) + + if not self.mass_preservation: + alpha = alpha.masked_fill( + (new_monotonic_step == max_steps).view(bsz * self.num_heads, 1), 0 + ) + + alpha = alpha.unsqueeze(1) + + self._set_monotonic_buffer(incremental_state, monotonic_cache) + + return alpha + + def v_proj_output(self, value): + raise NotImplementedError + + def forward( + self, + query, + key, + value, + key_padding_mask=None, + incremental_state=None, + *args, + **kwargs, + ): + + tgt_len, bsz, embed_dim = query.size() + src_len = value.size(0) + + # stepwise prob + # p_choose: bsz * self.num_heads, tgt_len, src_len + p_choose = self.p_choose(query, key, key_padding_mask) + + # expected alignment alpha + # bsz * self.num_heads, tgt_len, src_len + if incremental_state is not None: + alpha = self.expected_alignment_infer( + p_choose, key_padding_mask, incremental_state + ) + else: + alpha = self.expected_alignment_train(p_choose, key_padding_mask) + + # expected attention beta + # bsz * self.num_heads, tgt_len, src_len + beta = self.expected_attention( + alpha, query, key, value, key_padding_mask, incremental_state + ) + + attn_weights = beta + + v_proj = self.v_proj_output(value) + attn = torch.bmm(attn_weights.type_as(v_proj), v_proj) + + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) + + attn = self.out_proj(attn) + + beta = beta.view(bsz, self.num_heads, tgt_len, src_len) + alpha = alpha.view(bsz, self.num_heads, tgt_len, src_len) + p_choose = p_choose.view(bsz, self.num_heads, tgt_len, src_len) + + return attn, {"alpha": alpha, "beta": beta, "p_choose": p_choose} + + def reorder_incremental_state(self, incremental_state, new_order): + """Reorder buffered internal state (for incremental generation).""" + super().reorder_incremental_state(incremental_state, new_order) + input_buffer = self._get_monotonic_buffer(incremental_state) + if input_buffer is not None: + for k in input_buffer.keys(): + input_buffer[k] = input_buffer[k].index_select(0, new_order) + self._set_monotonic_buffer(incremental_state, input_buffer) + + def _get_monotonic_buffer(self, incremental_state): + return ( + utils.get_incremental_state( + self, + incremental_state, + "monotonic", + ) + or {} + ) + + def _set_monotonic_buffer(self, incremental_state, buffer): + utils.set_incremental_state( + self, + incremental_state, + "monotonic", + buffer, + ) + + def get_pointer(self, incremental_state): + return ( + utils.get_incremental_state( + self, + incremental_state, + "monotonic", + ) + or {} + ) + + def get_fastest_pointer(self, incremental_state): + return self.get_pointer(incremental_state)["step"].max(0)[0] + + def set_pointer(self, incremental_state, p_choose): + curr_pointer = self.get_pointer(incremental_state) + if len(curr_pointer) == 0: + buffer = torch.zeros_like(p_choose) + else: + buffer = self.get_pointer(incremental_state)["step"] + + buffer += (p_choose < 0.5).type_as(buffer) + + utils.set_incremental_state( + self, + incremental_state, + "monotonic", + {"step": buffer}, + ) + + +@register_monotonic_attention("hard_aligned") +class MonotonicMultiheadAttentionHard(MonotonicAttention, MultiheadAttention): + def __init__(self, args): + MultiheadAttention.__init__( + self, + embed_dim=args.decoder_embed_dim, + num_heads=args.decoder_attention_heads, + kdim=getattr(args, "encoder_embed_dim", None), + vdim=getattr(args, "encoder_embed_dim", None), + dropout=args.attention_dropout, + encoder_decoder_attention=True, + ) + + MonotonicAttention.__init__(self, args) + + self.k_in_proj = {"monotonic": self.k_proj} + self.q_in_proj = {"monotonic": self.q_proj} + self.v_in_proj = {"output": self.v_proj} + + def input_projections(self, query, key, value, name): + """ + Prepare inputs for multihead attention + + ============================================================ + Expected input size + query: tgt_len, bsz, embed_dim + key: src_len, bsz, embed_dim + value: src_len, bsz, embed_dim + name: monotonic or soft + """ + + if query is not None: + bsz = query.size(1) + q = self.q_in_proj[name](query) + q *= self.scaling + q = ( + q.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + else: + q = None + + if key is not None: + bsz = key.size(1) + k = self.k_in_proj[name](key) + k = ( + k.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + else: + k = None + + if value is not None: + bsz = value.size(1) + v = self.v_in_proj[name](value) + v = ( + v.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + else: + v = None + + return q, k, v + + def p_choose(self, query, key, key_padding_mask=None): + """ + Calculating step wise prob for reading and writing + 1 to read, 0 to write + + ============================================================ + Expected input size + query: bsz, tgt_len, embed_dim + key: bsz, src_len, embed_dim + value: bsz, src_len, embed_dim + key_padding_mask: bsz, src_len + attn_mask: bsz, src_len + query: bsz, tgt_len, embed_dim + """ + + # prepare inputs + q_proj, k_proj, _ = self.input_projections(query, key, None, "monotonic") + + # attention energy + attn_energy = self.attn_energy(q_proj, k_proj, key_padding_mask) + + noise = 0 + + if self.training: + # add noise here to encourage discretness + noise = ( + torch.normal(self.noise_mean, self.noise_var, attn_energy.size()) + .type_as(attn_energy) + .to(attn_energy.device) + ) + + p_choose = torch.sigmoid(attn_energy + noise) + _, _, tgt_len, src_len = p_choose.size() + + # p_choose: bsz * self.num_heads, tgt_len, src_len + return p_choose.view(-1, tgt_len, src_len) + + def expected_attention(self, alpha, *args): + """ + For MMA-H, beta = alpha + """ + return alpha + + def v_proj_output(self, value): + _, _, v_proj = self.input_projections(None, None, value, "output") + return v_proj + + +@register_monotonic_attention("infinite_lookback") +class MonotonicMultiheadAttentionInfiniteLookback(MonotonicMultiheadAttentionHard): + def __init__(self, args): + super().__init__(args) + self.init_soft_attention() + + def init_soft_attention(self): + self.k_proj_soft = nn.Linear(self.kdim, self.embed_dim, bias=True) + self.q_proj_soft = nn.Linear(self.embed_dim, self.embed_dim, bias=True) + self.k_in_proj["soft"] = self.k_proj_soft + self.q_in_proj["soft"] = self.q_proj_soft + + if self.qkv_same_dim: + # Empirically observed the convergence to be much better with + # the scaled initialization + nn.init.xavier_uniform_( + self.k_in_proj["soft"].weight, gain=1 / math.sqrt(2) + ) + nn.init.xavier_uniform_( + self.q_in_proj["soft"].weight, gain=1 / math.sqrt(2) + ) + else: + nn.init.xavier_uniform_(self.k_in_proj["soft"].weight) + nn.init.xavier_uniform_(self.q_in_proj["soft"].weight) + + def expected_attention( + self, alpha, query, key, value, key_padding_mask, incremental_state + ): + # monotonic attention, we will calculate milk here + bsz_x_num_heads, tgt_len, src_len = alpha.size() + bsz = int(bsz_x_num_heads / self.num_heads) + + q, k, _ = self.input_projections(query, key, None, "soft") + soft_energy = self.attn_energy(q, k, key_padding_mask) + + assert list(soft_energy.size()) == [bsz, self.num_heads, tgt_len, src_len] + + soft_energy = soft_energy.view(bsz * self.num_heads, tgt_len, src_len) + + if incremental_state is not None: + monotonic_cache = self._get_monotonic_buffer(incremental_state) + monotonic_step = monotonic_cache["step"] + 1 + step_offset = 0 + if key_padding_mask is not None: + if key_padding_mask[:, 0].any(): + # left_pad_source = True: + step_offset = key_padding_mask.sum(dim=-1, keepdim=True) + monotonic_step += step_offset + mask = lengths_to_mask( + monotonic_step.view(-1), soft_energy.size(2), 1 + ).unsqueeze(1) + + soft_energy = soft_energy.masked_fill(~mask.bool(), float("-inf")) + soft_energy = soft_energy - soft_energy.max(dim=2, keepdim=True)[0] + exp_soft_energy = torch.exp(soft_energy) + exp_soft_energy_sum = exp_soft_energy.sum(dim=2) + beta = exp_soft_energy / exp_soft_energy_sum.unsqueeze(2) + + else: + # bsz * num_heads, tgt_len, src_len + soft_energy = soft_energy - soft_energy.max(dim=2, keepdim=True)[0] + exp_soft_energy = torch.exp(soft_energy) + exp_soft_energy_cumsum = torch.cumsum(exp_soft_energy, dim=2) + + if key_padding_mask is not None: + if key_padding_mask.any(): + exp_soft_energy_cumsum = ( + exp_soft_energy_cumsum.view( + -1, self.num_heads, tgt_len, src_len + ) + .masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(1), self.eps + ) + .view(-1, tgt_len, src_len) + ) + + inner_items = alpha / exp_soft_energy_cumsum + + beta = exp_soft_energy * torch.cumsum( + inner_items.flip(dims=[2]), dim=2 + ).flip(dims=[2]) + + beta = self.dropout_module(beta) + + assert not torch.isnan(beta).any(), "NaN detected in beta." + + return beta + + +@register_monotonic_attention("waitk") +class MonotonicMultiheadAttentionWaitk(MonotonicMultiheadAttentionInfiniteLookback): + def __init__(self, args): + super().__init__(args) + self.q_in_proj["soft"] = self.q_in_proj["monotonic"] + self.k_in_proj["soft"] = self.k_in_proj["monotonic"] + self.waitk_lagging = args.waitk_lagging + assert ( + self.waitk_lagging > 0 + ), f"Lagging has to been larger than 0, get {self.waitk_lagging}." + + @staticmethod + def add_args(parser): + super( + MonotonicMultiheadAttentionWaitk, + MonotonicMultiheadAttentionWaitk, + ).add_args(parser) + + parser.add_argument( + "--waitk-lagging", type=int, required=True, help="Wait k lagging" + ) + + def p_choose( + self, query, key, key_padding_mask=None, attn_mask=None, incremental_state=None + ): + """ + query: bsz, tgt_len + key: bsz, src_len + key_padding_mask: bsz, src_len + """ + src_len, bsz, _ = key.size() + tgt_len, bsz, _ = query.size() + p_choose = query.new_ones(bsz, tgt_len, src_len) + p_choose = torch.tril(p_choose, diagonal=self.waitk_lagging - 1) + p_choose = torch.triu(p_choose, diagonal=self.waitk_lagging - 1) + + if key_padding_mask is not None and key_padding_mask[:, 0].eq(1).any(): + # Left pad source + # add -1 to the end + p_choose = p_choose.masked_fill( + key_padding_mask.float().flip(1).unsqueeze(1).bool(), -1 + ) + p_choose = convert_padding_direction( + p_choose.view(-1, src_len).long(), padding_idx=-1, right_to_left=True + ) + p_choose = p_choose.view(bsz, tgt_len, src_len).type_as(query) + # remove -1 + p_choose[p_choose.eq(-1)] = 0 + + # Extend to each head + p_choose = ( + p_choose.contiguous() + .unsqueeze(1) + .expand(-1, self.num_heads, -1, -1) + .contiguous() + .view(-1, tgt_len, src_len) + ) + + return p_choose diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_transformer_layer.py b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_transformer_layer.py new file mode 100644 index 00000000..442b7d48 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/modules/monotonic_transformer_layer.py @@ -0,0 +1,48 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.modules import LayerNorm, TransformerDecoderLayer, TransformerEncoderLayer + +from . import build_monotonic_attention + + +class TransformerMonotonicEncoderLayer(TransformerEncoderLayer): + def forward(self, x, encoder_padding_mask): + seq_len, _, _ = x.size() + attn_mask = x.new_ones([seq_len, seq_len]).triu(1) + attn_mask = attn_mask.masked_fill(attn_mask.bool(), float("-inf")) + return super().forward(x, encoder_padding_mask, attn_mask) + + +class TransformerMonotonicDecoderLayer(TransformerDecoderLayer): + def __init__( + self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False + ): + super().__init__( + args, + no_encoder_attn=True, + add_bias_kv=add_bias_kv, + add_zero_attn=add_zero_attn, + ) + self.encoder_attn = build_monotonic_attention(args) + self.encoder_attn_layer_norm = LayerNorm( + self.embed_dim, export=getattr(args, "char_inputs", False) + ) + + def prune_incremental_state(self, incremental_state): + def prune(module): + input_buffer = module._get_input_buffer(incremental_state) + for key in ["prev_key", "prev_value"]: + if input_buffer[key].size(2) > 1: + input_buffer[key] = input_buffer[key][:, :, :-1, :] + else: + input_buffer = {} + break + module._set_input_buffer(incremental_state, input_buffer) + + prune(self.self_attn) + + def get_steps(self, incremental_state): + return self.encoder_attn._get_monotonic_buffer(incremental_state).get("step", 0) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/utils/__init__.py b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/__init__.py new file mode 100644 index 00000000..be0ba4d9 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +# automatically import any Python files in the criterions/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("examples.simultaneous_translation.utils." + module) diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/utils/functions.py b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/functions.py new file mode 100644 index 00000000..f795b5f3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/functions.py @@ -0,0 +1,149 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +def exclusive_cumprod(tensor, dim: int, eps: float = 1e-10): + """ + Implementing exclusive cumprod. + There is cumprod in pytorch, however there is no exclusive mode. + cumprod(x) = [x1, x1x2, x2x3x4, ..., prod_{i=1}^n x_i] + exclusive means cumprod(x) = [1, x1, x1x2, x1x2x3, ..., prod_{i=1}^{n-1} x_i] + """ + tensor_size = list(tensor.size()) + tensor_size[dim] = 1 + return_tensor = safe_cumprod( + torch.cat([torch.ones(tensor_size).type_as(tensor), tensor], dim=dim), + dim=dim, + eps=eps, + ) + + if dim == 0: + return return_tensor[:-1] + elif dim == 1: + return return_tensor[:, :-1] + elif dim == 2: + return return_tensor[:, :, :-1] + else: + raise RuntimeError("Cumprod on dimension 3 and more is not implemented") + + +def safe_cumprod(tensor, dim: int, eps: float = 1e-10): + """ + An implementation of cumprod to prevent precision issue. + cumprod(x) + = [x1, x1x2, x1x2x3, ....] + = [exp(log(x1)), exp(log(x1) + log(x2)), exp(log(x1) + log(x2) + log(x3)), ...] + = exp(cumsum(log(x))) + """ + + if (tensor + eps < 0).any().item(): + raise RuntimeError( + "Safe cumprod can only take non-negative tensors as input." + "Consider use torch.cumprod if you want to calculate negative values." + ) + + log_tensor = torch.log(tensor + eps) + cumsum_log_tensor = torch.cumsum(log_tensor, dim) + exp_cumsum_log_tensor = torch.exp(cumsum_log_tensor) + return exp_cumsum_log_tensor + + +def lengths_to_mask(lengths, max_len: int, dim: int = 0, negative_mask: bool = False): + """ + Convert a tensor of lengths to mask + For example, lengths = [[2, 3, 4]], max_len = 5 + mask = + [[1, 1, 1], + [1, 1, 1], + [0, 1, 1], + [0, 0, 1], + [0, 0, 0]] + """ + assert len(lengths.size()) <= 2 + if len(lengths) == 2: + if dim == 1: + lengths = lengths.t() + lengths = lengths + else: + lengths = lengths.unsqueeze(1) + + # lengths : batch_size, 1 + lengths = lengths.view(-1, 1) + + batch_size = lengths.size(0) + # batch_size, max_len + mask = torch.arange(max_len).expand(batch_size, max_len).type_as(lengths) < lengths + + if negative_mask: + mask = ~mask + + if dim == 0: + # max_len, batch_size + mask = mask.t() + + return mask + + +def moving_sum(x, start_idx: int, end_idx: int): + """ + From MONOTONIC CHUNKWISE ATTENTION + https://arxiv.org/pdf/1712.05382.pdf + Equation (18) + + x = [x_1, x_2, ..., x_N] + MovingSum(x, start_idx, end_idx)_n = Sigma_{m=n−(start_idx−1)}^{n+end_idx-1} x_m + for n in {1, 2, 3, ..., N} + + x : src_len, batch_size + start_idx : start idx + end_idx : end idx + + Example + src_len = 5 + batch_size = 3 + x = + [[ 0, 5, 10], + [ 1, 6, 11], + [ 2, 7, 12], + [ 3, 8, 13], + [ 4, 9, 14]] + + MovingSum(x, 3, 1) = + [[ 0, 5, 10], + [ 1, 11, 21], + [ 3, 18, 33], + [ 6, 21, 36], + [ 9, 24, 39]] + + MovingSum(x, 1, 3) = + [[ 3, 18, 33], + [ 6, 21, 36], + [ 9, 24, 39], + [ 7, 17, 27], + [ 4, 9, 14]] + """ + assert start_idx > 0 and end_idx > 0 + assert len(x.size()) == 2 + src_len, batch_size = x.size() + # batch_size, 1, src_len + x = x.t().unsqueeze(1) + # batch_size, 1, src_len + moving_sum_weight = x.new_ones([1, 1, end_idx + start_idx - 1]) + + moving_sum = ( + torch.nn.functional.conv1d( + x, moving_sum_weight, padding=start_idx + end_idx - 1 + ) + .squeeze(1) + .t() + ) + moving_sum = moving_sum[end_idx:-start_idx] + + assert src_len == moving_sum.size(0) + assert batch_size == moving_sum.size(1) + + return moving_sum diff --git a/fairseq-tools/fairseq/examples/simultaneous_translation/utils/latency.py b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/latency.py new file mode 100644 index 00000000..5d800a5d --- /dev/null +++ b/fairseq-tools/fairseq/examples/simultaneous_translation/utils/latency.py @@ -0,0 +1,451 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +class LatencyMetric(object): + @staticmethod + def length_from_padding_mask(padding_mask, batch_first: bool = False): + dim = 1 if batch_first else 0 + return padding_mask.size(dim) - padding_mask.sum(dim=dim, keepdim=True) + + def prepare_latency_metric( + self, + delays, + src_lens, + target_padding_mask=None, + batch_first: bool = False, + start_from_zero: bool = True, + ): + assert len(delays.size()) == 2 + assert len(src_lens.size()) == 2 + + if start_from_zero: + delays = delays + 1 + + if batch_first: + # convert to batch_last + delays = delays.t() + src_lens = src_lens.t() + tgt_len, bsz = delays.size() + _, bsz_1 = src_lens.size() + + if target_padding_mask is not None: + target_padding_mask = target_padding_mask.t() + tgt_len_1, bsz_2 = target_padding_mask.size() + assert tgt_len == tgt_len_1 + assert bsz == bsz_2 + + assert bsz == bsz_1 + + if target_padding_mask is None: + tgt_lens = tgt_len * delays.new_ones([1, bsz]).float() + else: + # 1, batch_size + tgt_lens = self.length_from_padding_mask(target_padding_mask, False).float() + delays = delays.masked_fill(target_padding_mask, 0) + + return delays, src_lens, tgt_lens, target_padding_mask + + def __call__( + self, + delays, + src_lens, + target_padding_mask=None, + batch_first: bool = False, + start_from_zero: bool = True, + ): + delays, src_lens, tgt_lens, target_padding_mask = self.prepare_latency_metric( + delays, src_lens, target_padding_mask, batch_first, start_from_zero + ) + return self.cal_metric(delays, src_lens, tgt_lens, target_padding_mask) + + @staticmethod + def cal_metric(delays, src_lens, tgt_lens, target_padding_mask): + """ + Expected sizes: + delays: tgt_len, batch_size + src_lens: 1, batch_size + target_padding_mask: tgt_len, batch_size + """ + raise NotImplementedError + + +class AverageProportion(LatencyMetric): + """ + Function to calculate Average Proportion from + Can neural machine translation do simultaneous translation? + (https://arxiv.org/abs/1606.02012) + + Delays are monotonic steps, range from 1 to src_len. + Give src x tgt y, AP is calculated as: + + AP = 1 / (|x||y]) sum_i^|Y| deleys_i + """ + + @staticmethod + def cal_metric(delays, src_lens, tgt_lens, target_padding_mask): + if target_padding_mask is not None: + AP = torch.sum( + delays.masked_fill(target_padding_mask, 0), dim=0, keepdim=True + ) + else: + AP = torch.sum(delays, dim=0, keepdim=True) + + AP = AP / (src_lens * tgt_lens) + return AP + + +class AverageLagging(LatencyMetric): + """ + Function to calculate Average Lagging from + STACL: Simultaneous Translation with Implicit Anticipation + and Controllable Latency using Prefix-to-Prefix Framework + (https://arxiv.org/abs/1810.08398) + + Delays are monotonic steps, range from 1 to src_len. + Give src x tgt y, AP is calculated as: + + AL = 1 / tau sum_i^tau delays_i - (i - 1) / gamma + + Where + gamma = |y| / |x| + tau = argmin_i(delays_i = |x|) + """ + + @staticmethod + def cal_metric(delays, src_lens, tgt_lens, target_padding_mask): + # tau = argmin_i(delays_i = |x|) + tgt_len, bsz = delays.size() + lagging_padding_mask = delays >= src_lens + lagging_padding_mask = torch.nn.functional.pad( + lagging_padding_mask.t(), (1, 0) + ).t()[:-1, :] + gamma = tgt_lens / src_lens + lagging = ( + delays + - torch.arange(delays.size(0)) + .unsqueeze(1) + .type_as(delays) + .expand_as(delays) + / gamma + ) + lagging.masked_fill_(lagging_padding_mask, 0) + tau = (1 - lagging_padding_mask.type_as(lagging)).sum(dim=0, keepdim=True) + AL = lagging.sum(dim=0, keepdim=True) / tau + + return AL + + +class DifferentiableAverageLagging(LatencyMetric): + """ + Function to calculate Differentiable Average Lagging from + Monotonic Infinite Lookback Attention for Simultaneous Machine Translation + (https://arxiv.org/abs/1906.05218) + + Delays are monotonic steps, range from 0 to src_len-1. + (In the original paper thery are from 1 to src_len) + Give src x tgt y, AP is calculated as: + + DAL = 1 / |Y| sum_i^|Y| delays'_i - (i - 1) / gamma + + Where + delays'_i = + 1. delays_i if i == 1 + 2. max(delays_i, delays'_{i-1} + 1 / gamma) + + """ + + @staticmethod + def cal_metric(delays, src_lens, tgt_lens, target_padding_mask): + tgt_len, bsz = delays.size() + + gamma = tgt_lens / src_lens + new_delays = torch.zeros_like(delays) + + for i in range(delays.size(0)): + if i == 0: + new_delays[i] = delays[i] + else: + new_delays[i] = torch.cat( + [ + new_delays[i - 1].unsqueeze(0) + 1 / gamma, + delays[i].unsqueeze(0), + ], + dim=0, + ).max(dim=0)[0] + + DAL = ( + new_delays + - torch.arange(delays.size(0)) + .unsqueeze(1) + .type_as(delays) + .expand_as(delays) + / gamma + ) + if target_padding_mask is not None: + DAL = DAL.masked_fill(target_padding_mask, 0) + + DAL = DAL.sum(dim=0, keepdim=True) / tgt_lens + + return DAL + + +class LatencyMetricVariance(LatencyMetric): + def prepare_latency_metric( + self, + delays, + src_lens, + target_padding_mask=None, + batch_first: bool = True, + start_from_zero: bool = True, + ): + assert batch_first + assert len(delays.size()) == 3 + assert len(src_lens.size()) == 2 + + if start_from_zero: + delays = delays + 1 + + # convert to batch_last + bsz, num_heads_x_layers, tgt_len = delays.size() + bsz_1, _ = src_lens.size() + assert bsz == bsz_1 + + if target_padding_mask is not None: + bsz_2, tgt_len_1 = target_padding_mask.size() + assert tgt_len == tgt_len_1 + assert bsz == bsz_2 + + if target_padding_mask is None: + tgt_lens = tgt_len * delays.new_ones([bsz, tgt_len]).float() + else: + # batch_size, 1 + tgt_lens = self.length_from_padding_mask(target_padding_mask, True).float() + delays = delays.masked_fill(target_padding_mask.unsqueeze(1), 0) + + return delays, src_lens, tgt_lens, target_padding_mask + + +class VarianceDelay(LatencyMetricVariance): + @staticmethod + def cal_metric(delays, src_lens, tgt_lens, target_padding_mask): + """ + delays : bsz, num_heads_x_layers, tgt_len + src_lens : bsz, 1 + target_lens : bsz, 1 + target_padding_mask: bsz, tgt_len or None + """ + if delays.size(1) == 1: + return delays.new_zeros([1]) + + variance_delays = delays.var(dim=1) + + if target_padding_mask is not None: + variance_delays.masked_fill_(target_padding_mask, 0) + + return variance_delays.sum(dim=1, keepdim=True) / tgt_lens + + +class LatencyInference(object): + def __init__(self, start_from_zero=True): + self.metric_calculator = { + "differentiable_average_lagging": DifferentiableAverageLagging(), + "average_lagging": AverageLagging(), + "average_proportion": AverageProportion(), + } + + self.start_from_zero = start_from_zero + + def __call__(self, monotonic_step, src_lens): + """ + monotonic_step range from 0 to src_len. src_len means eos + delays: bsz, tgt_len + src_lens: bsz, 1 + """ + if not self.start_from_zero: + monotonic_step -= 1 + + src_lens = src_lens + + delays = monotonic_step.view( + monotonic_step.size(0), -1, monotonic_step.size(-1) + ).max(dim=1)[0] + + delays = delays.masked_fill(delays >= src_lens, 0) + (src_lens - 1).expand_as( + delays + ).masked_fill(delays < src_lens, 0) + return_dict = {} + for key, func in self.metric_calculator.items(): + return_dict[key] = func( + delays.float(), + src_lens.float(), + target_padding_mask=None, + batch_first=True, + start_from_zero=True, + ).t() + + return return_dict + + +class LatencyTraining(object): + def __init__( + self, + avg_weight, + var_weight, + avg_type, + var_type, + stay_on_last_token, + average_method, + ): + self.avg_weight = avg_weight + self.var_weight = var_weight + self.avg_type = avg_type + self.var_type = var_type + self.stay_on_last_token = stay_on_last_token + self.average_method = average_method + + self.metric_calculator = { + "differentiable_average_lagging": DifferentiableAverageLagging(), + "average_lagging": AverageLagging(), + "average_proportion": AverageProportion(), + } + + self.variance_calculator = { + "variance_delay": VarianceDelay(), + } + + def expected_delays_from_attention( + self, attention, source_padding_mask=None, target_padding_mask=None + ): + if type(attention) == list: + # bsz, num_heads, tgt_len, src_len + bsz, num_heads, tgt_len, src_len = attention[0].size() + attention = torch.cat(attention, dim=1) + bsz, num_heads_x_layers, tgt_len, src_len = attention.size() + # bsz * num_heads * num_layers, tgt_len, src_len + attention = attention.view(-1, tgt_len, src_len) + else: + # bsz * num_heads * num_layers, tgt_len, src_len + bsz, tgt_len, src_len = attention.size() + num_heads_x_layers = 1 + attention = attention.view(-1, tgt_len, src_len) + + if not self.stay_on_last_token: + residual_attention = 1 - attention[:, :, :-1].sum(dim=2, keepdim=True) + attention = torch.cat([attention[:, :, :-1], residual_attention], dim=2) + + # bsz * num_heads_x_num_layers, tgt_len, src_len for MMA + steps = ( + torch.arange(1, 1 + src_len) + .unsqueeze(0) + .unsqueeze(1) + .expand_as(attention) + .type_as(attention) + ) + + if source_padding_mask is not None: + src_offset = ( + source_padding_mask.type_as(attention) + .sum(dim=1, keepdim=True) + .expand(bsz, num_heads_x_layers) + .contiguous() + .view(-1, 1) + ) + src_lens = src_len - src_offset + if source_padding_mask[:, 0].any(): + # Pad left + src_offset = src_offset.view(-1, 1, 1) + steps = steps - src_offset + steps = steps.masked_fill(steps <= 0, 0) + else: + src_lens = attention.new_ones([bsz, num_heads_x_layers]) * src_len + src_lens = src_lens.view(-1, 1) + + # bsz * num_heads_num_layers, tgt_len, src_len + expected_delays = ( + (steps * attention).sum(dim=2).view(bsz, num_heads_x_layers, tgt_len) + ) + + if target_padding_mask is not None: + expected_delays.masked_fill_(target_padding_mask.unsqueeze(1), 0) + + return expected_delays, src_lens + + def avg_loss(self, expected_delays, src_lens, target_padding_mask): + + bsz, num_heads_x_layers, tgt_len = expected_delays.size() + target_padding_mask = ( + target_padding_mask.unsqueeze(1) + .expand_as(expected_delays) + .contiguous() + .view(-1, tgt_len) + ) + + if self.average_method == "average": + # bsz * tgt_len + expected_delays = expected_delays.mean(dim=1) + elif self.average_method == "weighted_average": + weights = torch.nn.functional.softmax(expected_delays, dim=1) + expected_delays = torch.sum(expected_delays * weights, dim=1) + elif self.average_method == "max": + # bsz * num_heads_x_num_layers, tgt_len + expected_delays = expected_delays.max(dim=1)[0] + else: + raise RuntimeError(f"{self.average_method} is not supported") + + src_lens = src_lens.view(bsz, -1)[:, :1] + target_padding_mask = target_padding_mask.view(bsz, -1, tgt_len)[:, 0] + + if self.avg_weight > 0.0: + if self.avg_type in self.metric_calculator: + average_delays = self.metric_calculator[self.avg_type]( + expected_delays, + src_lens, + target_padding_mask, + batch_first=True, + start_from_zero=False, + ) + else: + raise RuntimeError(f"{self.avg_type} is not supported.") + + # bsz * num_heads_x_num_layers, 1 + return self.avg_weight * average_delays.sum() + else: + return 0.0 + + def var_loss(self, expected_delays, src_lens, target_padding_mask): + src_lens = src_lens.view(expected_delays.size(0), expected_delays.size(1))[ + :, :1 + ] + if self.var_weight > 0.0: + if self.var_type in self.variance_calculator: + variance_delays = self.variance_calculator[self.var_type]( + expected_delays, + src_lens, + target_padding_mask, + batch_first=True, + start_from_zero=False, + ) + else: + raise RuntimeError(f"{self.var_type} is not supported.") + + return self.var_weight * variance_delays.sum() + else: + return 0.0 + + def loss(self, attention, source_padding_mask=None, target_padding_mask=None): + expected_delays, src_lens = self.expected_delays_from_attention( + attention, source_padding_mask, target_padding_mask + ) + + latency_loss = 0 + + latency_loss += self.avg_loss(expected_delays, src_lens, target_padding_mask) + + latency_loss += self.var_loss(expected_delays, src_lens, target_padding_mask) + + return latency_loss diff --git a/fairseq-tools/fairseq/examples/speech_recognition/README.md b/fairseq-tools/fairseq/examples/speech_recognition/README.md new file mode 100644 index 00000000..19f7cc56 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/README.md @@ -0,0 +1,106 @@ +# Speech Recognition +`examples/speech_recognition` is implementing ASR task in Fairseq, along with needed features, datasets, models and loss functions to train and infer model described in [Transformers with convolutional context for ASR (Abdelrahman Mohamed et al., 2019)](https://arxiv.org/abs/1904.11660). + + +## Additional dependencies +On top of main fairseq dependencies there are couple more additional requirements. + +1) Please follow the instructions to install [torchaudio](https://github.com/pytorch/audio). This is required to compute audio fbank features. +2) [Sclite](http://www1.icsi.berkeley.edu/Speech/docs/sctk-1.2/sclite.htm#sclite_name_0) is used to measure WER. Sclite can be downloaded and installed from source from sctk package [here](http://www.openslr.org/4/). Training and inference doesn't require Sclite dependency. +3) [sentencepiece](https://github.com/google/sentencepiece) is required in order to create dataset with word-piece targets. + +## Preparing librispeech data +``` +./examples/speech_recognition/datasets/prepare-librispeech.sh $DIR_TO_SAVE_RAW_DATA $DIR_FOR_PREPROCESSED_DATA +``` + +## Training librispeech data +``` +python train.py $DIR_FOR_PREPROCESSED_DATA --save-dir $MODEL_PATH --max-epoch 80 --task speech_recognition --arch vggtransformer_2 --optimizer adadelta --lr 1.0 --adadelta-eps 1e-8 --adadelta-rho 0.95 --clip-norm 10.0 --max-tokens 5000 --log-format json --log-interval 1 --criterion cross_entropy_acc --user-dir examples/speech_recognition/ +``` + +## Inference for librispeech +`$SET` can be `test_clean` or `test_other` +Any checkpoint in `$MODEL_PATH` can be selected. In this example we are working with `checkpoint_last.pt` +``` +python examples/speech_recognition/infer.py $DIR_FOR_PREPROCESSED_DATA --task speech_recognition --max-tokens 25000 --nbest 1 --path $MODEL_PATH/checkpoint_last.pt --beam 20 --results-path $RES_DIR --batch-size 40 --gen-subset $SET --user-dir examples/speech_recognition/ +``` + +## Inference for librispeech +``` +sclite -r ${RES_DIR}/ref.word-checkpoint_last.pt-${SET}.txt -h ${RES_DIR}/hypo.word-checkpoint_last.pt-${SET}.txt -i rm -o all stdout > $RES_REPORT +``` +`Sum/Avg` row from first table of the report has WER + +## Using wav2letter components +[wav2letter](https://github.com/facebookresearch/wav2letter) now has integration with fairseq. Currently this includes: + +* AutoSegmentationCriterion (ASG) +* wav2letter-style Conv/GLU model +* wav2letter's beam search decoder + +To use these, follow the instructions on [this page](https://github.com/facebookresearch/wav2letter/tree/master/bindings/python) to install python bindings. Please note that python bindings are for a *subset* of wav2letter and don't require its full dependencies (notably, `flashlight` and `ArrayFire` are *not* required). + +To quickly summarize the instructions: first, install [CUDA](https://developer.nvidia.com/cuda-downloads). Then follow these steps: +``` +# additional prerequisites - use equivalents for your distro +sudo apt-get install build-essential cmake libatlas-base-dev libfftw3-dev liblzma-dev libbz2-dev libzstd-dev +# install KenLM from source +git clone https://github.com/kpu/kenlm.git +cd kenlm +mkdir -p build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON +make -j16 +cd .. +export KENLM_ROOT_DIR=$(pwd) +cd .. +# install wav2letter python bindings +git clone https://github.com/facebookresearch/wav2letter.git +cd wav2letter/bindings/python +# make sure your python environment is active at this point +pip install torch packaging +pip install -e . +# try some examples to verify installation succeeded +python ./examples/criterion_example.py +python ./examples/decoder_example.py ../../src/decoder/test +python ./examples/feature_example.py ../../src/feature/test/data +``` + +## Training librispeech data (wav2letter style, Conv/GLU + ASG loss) +Training command: +``` +python train.py $DIR_FOR_PREPROCESSED_DATA --save-dir $MODEL_PATH --max-epoch 100 --task speech_recognition --arch w2l_conv_glu_enc --batch-size 4 --optimizer sgd --lr 0.3,0.8 --momentum 0.8 --clip-norm 0.2 --max-tokens 50000 --log-format json --log-interval 100 --num-workers 0 --sentence-avg --criterion asg_loss --asg-transitions-init 5 --max-replabel 2 --linseg-updates 8789 --user-dir examples/speech_recognition +``` + +Note that ASG loss currently doesn't do well with word-pieces. You should prepare a dataset with character targets by setting `nbpe=31` in `prepare-librispeech.sh`. + +## Inference for librispeech (wav2letter decoder, n-gram LM) +Inference command: +``` +python examples/speech_recognition/infer.py $DIR_FOR_PREPROCESSED_DATA --task speech_recognition --seed 1 --nbest 1 --path $MODEL_PATH/checkpoint_last.pt --gen-subset $SET --results-path $RES_DIR --w2l-decoder kenlm --kenlm-model $KENLM_MODEL_PATH --lexicon $LEXICON_PATH --beam 200 --beam-threshold 15 --lm-weight 1.5 --word-score 1.5 --sil-weight -0.3 --criterion asg_loss --max-replabel 2 --user-dir examples/speech_recognition +``` + +`$KENLM_MODEL_PATH` should be a standard n-gram language model file. `$LEXICON_PATH` should be a wav2letter-style lexicon (list of known words and their spellings). For ASG inference, a lexicon line should look like this (note the repetition labels): +``` +doorbell D O 1 R B E L 1 ▁ +``` +For CTC inference with word-pieces, repetition labels are not used and the lexicon should have most common spellings for each word (one can use sentencepiece's `NBestEncodeAsPieces` for this): +``` +doorbell ▁DOOR BE LL +doorbell ▁DOOR B E LL +doorbell ▁DO OR BE LL +doorbell ▁DOOR B EL L +doorbell ▁DOOR BE L L +doorbell ▁DO OR B E LL +doorbell ▁DOOR B E L L +doorbell ▁DO OR B EL L +doorbell ▁DO O R BE LL +doorbell ▁DO OR BE L L +``` +Lowercase vs. uppercase matters: the *word* should match the case of the n-gram language model (i.e. `$KENLM_MODEL_PATH`), while the *spelling* should match the case of the token dictionary (i.e. `$DIR_FOR_PREPROCESSED_DATA/dict.txt`). + +## Inference for librispeech (wav2letter decoder, viterbi only) +Inference command: +``` +python examples/speech_recognition/infer.py $DIR_FOR_PREPROCESSED_DATA --task speech_recognition --seed 1 --nbest 1 --path $MODEL_PATH/checkpoint_last.pt --gen-subset $SET --results-path $RES_DIR --w2l-decoder viterbi --criterion asg_loss --max-replabel 2 --user-dir examples/speech_recognition +``` diff --git a/fairseq-tools/fairseq/examples/speech_recognition/__init__.py b/fairseq-tools/fairseq/examples/speech_recognition/__init__.py new file mode 100644 index 00000000..0278f6a2 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/__init__.py @@ -0,0 +1 @@ +from . import criterions, models, tasks # noqa diff --git a/fairseq-tools/fairseq/examples/speech_recognition/criterions/ASG_loss.py b/fairseq-tools/fairseq/examples/speech_recognition/criterions/ASG_loss.py new file mode 100644 index 00000000..7493654a --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/criterions/ASG_loss.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from examples.speech_recognition.data.replabels import pack_replabels +from fairseq import utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("asg_loss") +class ASGCriterion(FairseqCriterion): + @staticmethod + def add_args(parser): + group = parser.add_argument_group("ASG Loss") + group.add_argument( + "--asg-transitions-init", + help="initial diagonal value of transition matrix", + type=float, + default=0.0, + ) + group.add_argument( + "--max-replabel", help="maximum # of replabels", type=int, default=2 + ) + group.add_argument( + "--linseg-updates", + help="# of training updates to use LinSeg initialization", + type=int, + default=0, + ) + group.add_argument( + "--hide-linseg-messages", + help="hide messages about LinSeg initialization", + action="store_true", + ) + + def __init__( + self, + task, + silence_token, + asg_transitions_init, + max_replabel, + linseg_updates, + hide_linseg_messages, + ): + from wav2letter.criterion import ASGLoss, CriterionScaleMode + + super().__init__(task) + self.tgt_dict = task.target_dictionary + self.eos = self.tgt_dict.eos() + self.silence = ( + self.tgt_dict.index(silence_token) + if silence_token in self.tgt_dict + else None + ) + self.max_replabel = max_replabel + + num_labels = len(self.tgt_dict) + self.asg = ASGLoss(num_labels, scale_mode=CriterionScaleMode.TARGET_SZ_SQRT) + self.asg.trans = torch.nn.Parameter( + asg_transitions_init * torch.eye(num_labels), requires_grad=True + ) + + self.linseg_progress = torch.nn.Parameter( + torch.tensor([0], dtype=torch.int), requires_grad=False + ) + self.linseg_maximum = linseg_updates + self.linseg_message_state = "none" if hide_linseg_messages else "start" + + @classmethod + def build_criterion(cls, args, task): + return cls( + task, + args.silence_token, + args.asg_transitions_init, + args.max_replabel, + args.linseg_updates, + args.hide_linseg_messages, + ) + + def linseg_step(self): + if not self.training: + return False + if self.linseg_progress.item() < self.linseg_maximum: + if self.linseg_message_state == "start": + print("| using LinSeg to initialize ASG") + self.linseg_message_state = "finish" + self.linseg_progress.add_(1) + return True + elif self.linseg_message_state == "finish": + print("| finished LinSeg initialization") + self.linseg_message_state = "none" + return False + + def replace_eos_with_silence(self, tgt): + if tgt[-1] != self.eos: + return tgt + elif self.silence is None or (len(tgt) > 1 and tgt[-2] == self.silence): + return tgt[:-1] + else: + return tgt[:-1] + [self.silence] + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + + net_output = model(**sample["net_input"]) + emissions = net_output["encoder_out"].transpose(0, 1).contiguous() + B = emissions.size(0) + T = emissions.size(1) + device = emissions.device + + target = torch.IntTensor(B, T) + target_size = torch.IntTensor(B) + using_linseg = self.linseg_step() + + for b in range(B): + initial_target_size = sample["target_lengths"][b].item() + if initial_target_size == 0: + raise ValueError("target size cannot be zero") + + tgt = sample["target"][b, :initial_target_size].tolist() + tgt = self.replace_eos_with_silence(tgt) + tgt = pack_replabels(tgt, self.tgt_dict, self.max_replabel) + tgt = tgt[:T] + + if using_linseg: + tgt = [tgt[t * len(tgt) // T] for t in range(T)] + + target[b][: len(tgt)] = torch.IntTensor(tgt) + target_size[b] = len(tgt) + + loss = self.asg.forward(emissions, target.to(device), target_size.to(device)) + + if reduce: + loss = torch.sum(loss) + + sample_size = ( + sample["target"].size(0) if self.args.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + @staticmethod + def aggregate_logging_outputs(logging_outputs): + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + agg_output = { + "loss": loss_sum / nsentences, + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + return agg_output diff --git a/fairseq-tools/fairseq/examples/speech_recognition/criterions/__init__.py b/fairseq-tools/fairseq/examples/speech_recognition/criterions/__init__.py new file mode 100644 index 00000000..88af9f34 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/criterions/__init__.py @@ -0,0 +1,17 @@ +import importlib +import os + + +# ASG loss requires wav2letter +files_to_skip = set() +try: + import wav2letter +except ImportError: + files_to_skip.add("ASG_loss.py") + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_") and file not in files_to_skip: + criterion_name = file[: file.find(".py")] + importlib.import_module( + "examples.speech_recognition.criterions." + criterion_name + ) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/criterions/cross_entropy_acc.py b/fairseq-tools/fairseq/examples/speech_recognition/criterions/cross_entropy_acc.py new file mode 100644 index 00000000..7c4d8ba3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/criterions/cross_entropy_acc.py @@ -0,0 +1,130 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import logging +import math + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("cross_entropy_acc") +class CrossEntropyWithAccCriterion(FairseqCriterion): + def __init__(self, task, sentence_avg): + super().__init__(task) + self.sentence_avg = sentence_avg + + def compute_loss(self, model, net_output, target, reduction, log_probs): + # N, T -> N * T + target = target.view(-1) + lprobs = model.get_normalized_probs(net_output, log_probs=log_probs) + if not hasattr(lprobs, "batch_first"): + logging.warning( + "ERROR: we need to know whether " + "batch first for the net output; " + "you need to set batch_first attribute for the return value of " + "model.get_normalized_probs. Now, we assume this is true, but " + "in the future, we will raise exception instead. " + ) + batch_first = getattr(lprobs, "batch_first", True) + if not batch_first: + lprobs = lprobs.transpose(0, 1) + + # N, T, D -> N * T, D + lprobs = lprobs.view(-1, lprobs.size(-1)) + loss = F.nll_loss( + lprobs, target, ignore_index=self.padding_idx, reduction=reduction + ) + return lprobs, loss + + def get_logging_output(self, sample, target, lprobs, loss): + target = target.view(-1) + mask = target != self.padding_idx + correct = torch.sum( + lprobs.argmax(1).masked_select(mask) == target.masked_select(mask) + ) + total = torch.sum(mask) + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + + logging_output = { + "loss": utils.item(loss.data), # * sample['ntokens'], + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + "correct": utils.item(correct.data), + "total": utils.item(total.data), + "nframes": torch.sum(sample["net_input"]["src_lengths"]).item(), + } + + return sample_size, logging_output + + def forward(self, model, sample, reduction="sum", log_probs=True): + """Computes the cross entropy with accuracy metric for the given sample. + + This is similar to CrossEntropyCriterion in fairseq, but also + computes accuracy metrics as part of logging + + Args: + logprobs (Torch.tensor) of shape N, T, D i.e. + batchsize, timesteps, dimensions + targets (Torch.tensor) of shape N, T i.e batchsize, timesteps + + Returns: + tuple: With three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + + TODO: + * Currently this Criterion will only work with LSTMEncoderModels or + FairseqModels which have decoder, or Models which return TorchTensor + as net_output. + We need to make a change to support all FairseqEncoder models. + """ + net_output = model(**sample["net_input"]) + target = model.get_targets(sample, net_output) + lprobs, loss = self.compute_loss( + model, net_output, target, reduction, log_probs + ) + sample_size, logging_output = self.get_logging_output( + sample, target, lprobs, loss + ) + return loss, sample_size, logging_output + + @staticmethod + def aggregate_logging_outputs(logging_outputs): + """Aggregate logging outputs from data parallel training.""" + correct_sum = sum(log.get("correct", 0) for log in logging_outputs) + total_sum = sum(log.get("total", 0) for log in logging_outputs) + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + nframes = sum(log.get("nframes", 0) for log in logging_outputs) + agg_output = { + "loss": loss_sum / sample_size / math.log(2) if sample_size > 0 else 0.0, + # if args.sentence_avg, then sample_size is nsentences, then loss + # is per-sentence loss; else sample_size is ntokens, the loss + # becomes per-output token loss + "ntokens": ntokens, + "nsentences": nsentences, + "nframes": nframes, + "sample_size": sample_size, + "acc": correct_sum * 100.0 / total_sum if total_sum > 0 else 0.0, + "correct": correct_sum, + "total": total_sum, + # total is the number of validate tokens + } + if sample_size != ntokens: + agg_output["nll_loss"] = loss_sum / ntokens / math.log(2) + # loss: per output token loss + # nll_loss: per sentence loss + return agg_output diff --git a/fairseq-tools/fairseq/examples/speech_recognition/data/__init__.py b/fairseq-tools/fairseq/examples/speech_recognition/data/__init__.py new file mode 100644 index 00000000..47bb6e24 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/data/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .asr_dataset import AsrDataset + + +__all__ = [ + "AsrDataset", +] diff --git a/fairseq-tools/fairseq/examples/speech_recognition/data/asr_dataset.py b/fairseq-tools/fairseq/examples/speech_recognition/data/asr_dataset.py new file mode 100644 index 00000000..63a6fcac --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/data/asr_dataset.py @@ -0,0 +1,122 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os + +import numpy as np +from fairseq.data import FairseqDataset + +from . import data_utils +from .collaters import Seq2SeqCollater + + +class AsrDataset(FairseqDataset): + """ + A dataset representing speech and corresponding transcription. + + Args: + aud_paths: (List[str]): A list of str with paths to audio files. + aud_durations_ms (List[int]): A list of int containing the durations of + audio files. + tgt (List[torch.LongTensor]): A list of LongTensors containing the indices + of target transcriptions. + tgt_dict (~fairseq.data.Dictionary): target vocabulary. + ids (List[str]): A list of utterance IDs. + speakers (List[str]): A list of speakers corresponding to utterances. + num_mel_bins (int): Number of triangular mel-frequency bins (default: 80) + frame_length (float): Frame length in milliseconds (default: 25.0) + frame_shift (float): Frame shift in milliseconds (default: 10.0) + """ + + def __init__( + self, + aud_paths, + aud_durations_ms, + tgt, + tgt_dict, + ids, + speakers, + num_mel_bins=80, + frame_length=25.0, + frame_shift=10.0, + ): + assert frame_length > 0 + assert frame_shift > 0 + assert all(x > frame_length for x in aud_durations_ms) + self.frame_sizes = [ + int(1 + (d - frame_length) / frame_shift) for d in aud_durations_ms + ] + + assert len(aud_paths) > 0 + assert len(aud_paths) == len(aud_durations_ms) + assert len(aud_paths) == len(tgt) + assert len(aud_paths) == len(ids) + assert len(aud_paths) == len(speakers) + self.aud_paths = aud_paths + self.tgt_dict = tgt_dict + self.tgt = tgt + self.ids = ids + self.speakers = speakers + self.num_mel_bins = num_mel_bins + self.frame_length = frame_length + self.frame_shift = frame_shift + + self.s2s_collater = Seq2SeqCollater( + 0, + 1, + pad_index=self.tgt_dict.pad(), + eos_index=self.tgt_dict.eos(), + move_eos_to_beginning=True, + ) + + def __getitem__(self, index): + import torchaudio + import torchaudio.compliance.kaldi as kaldi + + tgt_item = self.tgt[index] if self.tgt is not None else None + + path = self.aud_paths[index] + if not os.path.exists(path): + raise FileNotFoundError("Audio file not found: {}".format(path)) + sound, sample_rate = torchaudio.load_wav(path) + output = kaldi.fbank( + sound, + num_mel_bins=self.num_mel_bins, + frame_length=self.frame_length, + frame_shift=self.frame_shift, + ) + output_cmvn = data_utils.apply_mv_norm(output) + + return {"id": index, "data": [output_cmvn.detach(), tgt_item]} + + def __len__(self): + return len(self.aud_paths) + + def collater(self, samples): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[int]): sample indices to collate + + Returns: + dict: a mini-batch suitable for forwarding with a Model + """ + return self.s2s_collater.collate(samples) + + def num_tokens(self, index): + return self.frame_sizes[index] + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + return ( + self.frame_sizes[index], + len(self.tgt[index]) if self.tgt is not None else 0, + ) + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + return np.arange(len(self)) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/data/collaters.py b/fairseq-tools/fairseq/examples/speech_recognition/data/collaters.py new file mode 100644 index 00000000..6acfec87 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/data/collaters.py @@ -0,0 +1,131 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" + This module contains collection of classes which implement + collate functionalities for various tasks. + + Collaters should know what data to expect for each sample + and they should pack / collate them into batches +""" + + +from __future__ import absolute_import, division, print_function, unicode_literals + +import numpy as np +import torch +from fairseq.data import data_utils as fairseq_data_utils + + +class Seq2SeqCollater(object): + """ + Implements collate function mainly for seq2seq tasks + This expects each sample to contain feature (src_tokens) and + targets. + This collator is also used for aligned training task. + """ + + def __init__( + self, + feature_index=0, + label_index=1, + pad_index=1, + eos_index=2, + move_eos_to_beginning=True, + ): + self.feature_index = feature_index + self.label_index = label_index + self.pad_index = pad_index + self.eos_index = eos_index + self.move_eos_to_beginning = move_eos_to_beginning + + def _collate_frames(self, frames): + """Convert a list of 2d frames into a padded 3d tensor + Args: + frames (list): list of 2d frames of size L[i]*f_dim. Where L[i] is + length of i-th frame and f_dim is static dimension of features + Returns: + 3d tensor of size len(frames)*len_max*f_dim where len_max is max of L[i] + """ + len_max = max(frame.size(0) for frame in frames) + f_dim = frames[0].size(1) + res = frames[0].new(len(frames), len_max, f_dim).fill_(0.0) + + for i, v in enumerate(frames): + res[i, : v.size(0)] = v + + return res + + def collate(self, samples): + """ + utility function to collate samples into batch for speech recognition. + """ + if len(samples) == 0: + return {} + + # parse samples into torch tensors + parsed_samples = [] + for s in samples: + # skip invalid samples + if s["data"][self.feature_index] is None: + continue + source = s["data"][self.feature_index] + if isinstance(source, (np.ndarray, np.generic)): + source = torch.from_numpy(source) + target = s["data"][self.label_index] + if isinstance(target, (np.ndarray, np.generic)): + target = torch.from_numpy(target).long() + elif isinstance(target, list): + target = torch.LongTensor(target) + + parsed_sample = {"id": s["id"], "source": source, "target": target} + parsed_samples.append(parsed_sample) + samples = parsed_samples + + id = torch.LongTensor([s["id"] for s in samples]) + frames = self._collate_frames([s["source"] for s in samples]) + # sort samples by descending number of frames + frames_lengths = torch.LongTensor([s["source"].size(0) for s in samples]) + frames_lengths, sort_order = frames_lengths.sort(descending=True) + id = id.index_select(0, sort_order) + frames = frames.index_select(0, sort_order) + + target = None + target_lengths = None + prev_output_tokens = None + if samples[0].get("target", None) is not None: + ntokens = sum(len(s["target"]) for s in samples) + target = fairseq_data_utils.collate_tokens( + [s["target"] for s in samples], + self.pad_index, + self.eos_index, + left_pad=False, + move_eos_to_beginning=False, + ) + target = target.index_select(0, sort_order) + target_lengths = torch.LongTensor( + [s["target"].size(0) for s in samples] + ).index_select(0, sort_order) + prev_output_tokens = fairseq_data_utils.collate_tokens( + [s["target"] for s in samples], + self.pad_index, + self.eos_index, + left_pad=False, + move_eos_to_beginning=self.move_eos_to_beginning, + ) + prev_output_tokens = prev_output_tokens.index_select(0, sort_order) + else: + ntokens = sum(len(s["source"]) for s in samples) + + batch = { + "id": id, + "ntokens": ntokens, + "net_input": {"src_tokens": frames, "src_lengths": frames_lengths}, + "target": target, + "target_lengths": target_lengths, + "nsentences": len(samples), + } + if prev_output_tokens is not None: + batch["net_input"]["prev_output_tokens"] = prev_output_tokens + return batch diff --git a/fairseq-tools/fairseq/examples/speech_recognition/data/data_utils.py b/fairseq-tools/fairseq/examples/speech_recognition/data/data_utils.py new file mode 100644 index 00000000..cc4729e6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/data/data_utils.py @@ -0,0 +1,100 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +def calc_mean_invstddev(feature): + if len(feature.size()) != 2: + raise ValueError("We expect the input feature to be 2-D tensor") + mean = feature.mean(0) + var = feature.var(0) + # avoid division by ~zero + eps = 1e-8 + if (var < eps).any(): + return mean, 1.0 / (torch.sqrt(var) + eps) + return mean, 1.0 / torch.sqrt(var) + + +def apply_mv_norm(features): + # If there is less than 2 spectrograms, the variance cannot be computed (is NaN) + # and normalization is not possible, so return the item as it is + if features.size(0) < 2: + return features + mean, invstddev = calc_mean_invstddev(features) + res = (features - mean) * invstddev + return res + + +def lengths_to_encoder_padding_mask(lengths, batch_first=False): + """ + convert lengths (a 1-D Long/Int tensor) to 2-D binary tensor + + Args: + lengths: a (B, )-shaped tensor + + Return: + max_length: maximum length of B sequences + encoder_padding_mask: a (max_length, B) binary mask, where + [t, b] = 0 for t < lengths[b] and 1 otherwise + + TODO: + kernelize this function if benchmarking shows this function is slow + """ + max_lengths = torch.max(lengths).item() + bsz = lengths.size(0) + encoder_padding_mask = torch.arange( + max_lengths + ).to( # a (T, ) tensor with [0, ..., T-1] + lengths.device + ).view( # move to the right device + 1, max_lengths + ).expand( # reshape to (1, T)-shaped tensor + bsz, -1 + ) >= lengths.view( # expand to (B, T)-shaped tensor + bsz, 1 + ).expand( + -1, max_lengths + ) + if not batch_first: + return encoder_padding_mask.t(), max_lengths + else: + return encoder_padding_mask, max_lengths + + +def encoder_padding_mask_to_lengths( + encoder_padding_mask, max_lengths, batch_size, device +): + """ + convert encoder_padding_mask (2-D binary tensor) to a 1-D tensor + + Conventionally, encoder output contains a encoder_padding_mask, which is + a 2-D mask in a shape (T, B), whose (t, b) element indicate whether + encoder_out[t, b] is a valid output (=0) or not (=1). Occasionally, we + need to convert this mask tensor to a 1-D tensor in shape (B, ), where + [b] denotes the valid length of b-th sequence + + Args: + encoder_padding_mask: a (T, B)-shaped binary tensor or None; if None, + indicating all are valid + Return: + seq_lengths: a (B,)-shaped tensor, where its (b, )-th element is the + number of valid elements of b-th sequence + + max_lengths: maximum length of all sequence, if encoder_padding_mask is + not None, max_lengths must equal to encoder_padding_mask.size(0) + + batch_size: batch size; if encoder_padding_mask is + not None, max_lengths must equal to encoder_padding_mask.size(1) + + device: which device to put the result on + """ + if encoder_padding_mask is None: + return torch.Tensor([max_lengths] * batch_size).to(torch.int32).to(device) + + assert encoder_padding_mask.size(0) == max_lengths, "max_lengths does not match" + assert encoder_padding_mask.size(1) == batch_size, "batch_size does not match" + + return max_lengths - torch.sum(encoder_padding_mask, dim=0) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/data/replabels.py b/fairseq-tools/fairseq/examples/speech_recognition/data/replabels.py new file mode 100644 index 00000000..d76bda7a --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/data/replabels.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Replabel transforms for use with wav2letter's ASG criterion. +""" + + +def replabel_symbol(i): + """ + Replabel symbols used in wav2letter, currently just "1", "2", ... + This prevents training with numeral tokens, so this might change in the future + """ + return str(i) + + +def pack_replabels(tokens, dictionary, max_reps): + """ + Pack a token sequence so that repeated symbols are replaced by replabels + """ + if len(tokens) == 0 or max_reps <= 0: + return tokens + + replabel_value_to_idx = [0] * (max_reps + 1) + for i in range(1, max_reps + 1): + replabel_value_to_idx[i] = dictionary.index(replabel_symbol(i)) + + result = [] + prev_token = -1 + num_reps = 0 + for token in tokens: + if token == prev_token and num_reps < max_reps: + num_reps += 1 + else: + if num_reps > 0: + result.append(replabel_value_to_idx[num_reps]) + num_reps = 0 + result.append(token) + prev_token = token + if num_reps > 0: + result.append(replabel_value_to_idx[num_reps]) + return result + + +def unpack_replabels(tokens, dictionary, max_reps): + """ + Unpack a token sequence so that replabels are replaced by repeated symbols + """ + if len(tokens) == 0 or max_reps <= 0: + return tokens + + replabel_idx_to_value = {} + for i in range(1, max_reps + 1): + replabel_idx_to_value[dictionary.index(replabel_symbol(i))] = i + + result = [] + prev_token = -1 + for token in tokens: + try: + for _ in range(replabel_idx_to_value[token]): + result.append(prev_token) + prev_token = -1 + except KeyError: + result.append(token) + prev_token = token + return result diff --git a/fairseq-tools/fairseq/examples/speech_recognition/datasets/asr_prep_json.py b/fairseq-tools/fairseq/examples/speech_recognition/datasets/asr_prep_json.py new file mode 100644 index 00000000..b8db8ff1 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/datasets/asr_prep_json.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import argparse +import concurrent.futures +import json +import multiprocessing +import os +from collections import namedtuple +from itertools import chain + +import sentencepiece as spm +from fairseq.data import Dictionary + + +MILLISECONDS_TO_SECONDS = 0.001 + + +def process_sample(aud_path, lable, utt_id, sp, tgt_dict): + import torchaudio + + input = {} + output = {} + si, ei = torchaudio.info(aud_path) + input["length_ms"] = int( + si.length / si.channels / si.rate / MILLISECONDS_TO_SECONDS + ) + input["path"] = aud_path + + token = " ".join(sp.EncodeAsPieces(lable)) + ids = tgt_dict.encode_line(token, append_eos=False) + output["text"] = lable + output["token"] = token + output["tokenid"] = ", ".join(map(str, [t.tolist() for t in ids])) + return {utt_id: {"input": input, "output": output}} + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--audio-dirs", + nargs="+", + default=["-"], + required=True, + help="input directories with audio files", + ) + parser.add_argument( + "--labels", + required=True, + help="aggregated input labels with format per line", + type=argparse.FileType("r", encoding="UTF-8"), + ) + parser.add_argument( + "--spm-model", + required=True, + help="sentencepiece model to use for encoding", + type=argparse.FileType("r", encoding="UTF-8"), + ) + parser.add_argument( + "--dictionary", + required=True, + help="file to load fairseq dictionary from", + type=argparse.FileType("r", encoding="UTF-8"), + ) + parser.add_argument("--audio-format", choices=["flac", "wav"], default="wav") + parser.add_argument( + "--output", + required=True, + type=argparse.FileType("w"), + help="path to save json output", + ) + args = parser.parse_args() + + sp = spm.SentencePieceProcessor() + sp.Load(args.spm_model.name) + + tgt_dict = Dictionary.load(args.dictionary) + + labels = {} + for line in args.labels: + (utt_id, label) = line.split(" ", 1) + labels[utt_id] = label + if len(labels) == 0: + raise Exception("No labels found in ", args.labels_path) + + Sample = namedtuple("Sample", "aud_path utt_id") + samples = [] + for path, _, files in chain.from_iterable( + os.walk(path) for path in args.audio_dirs + ): + for f in files: + if f.endswith(args.audio_format): + if len(os.path.splitext(f)) != 2: + raise Exception("Expect file name. Got: ", f) + utt_id = os.path.splitext(f)[0] + if utt_id not in labels: + continue + samples.append(Sample(os.path.join(path, f), utt_id)) + + utts = {} + num_cpu = multiprocessing.cpu_count() + with concurrent.futures.ThreadPoolExecutor(max_workers=num_cpu) as executor: + future_to_sample = { + executor.submit( + process_sample, s.aud_path, labels[s.utt_id], s.utt_id, sp, tgt_dict + ): s + for s in samples + } + for future in concurrent.futures.as_completed(future_to_sample): + try: + data = future.result() + except Exception as exc: + print("generated an exception: ", exc) + else: + utts.update(data) + json.dump({"utts": utts}, args.output, indent=4) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/speech_recognition/datasets/prepare-librispeech.sh b/fairseq-tools/fairseq/examples/speech_recognition/datasets/prepare-librispeech.sh new file mode 100644 index 00000000..9e9297f0 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/datasets/prepare-librispeech.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Prepare librispeech dataset + +base_url=www.openslr.org/resources/12 +train_dir=train_960 + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + echo "e.g.: $0 /tmp/librispeech_raw/ ~/data/librispeech_final" + exit 1 +fi + +download_dir=${1%/} +out_dir=${2%/} + +fairseq_root=~/fairseq-py/ +mkdir -p ${out_dir} +cd ${out_dir} || exit + +nbpe=5000 +bpemode=unigram + +if [ ! -d "$fairseq_root" ]; then + echo "$0: Please set correct fairseq_root" + exit 1 +fi + +echo "Data Download" +for part in dev-clean test-clean dev-other test-other train-clean-100 train-clean-360 train-other-500; do + url=$base_url/$part.tar.gz + if ! wget -P $download_dir $url; then + echo "$0: wget failed for $url" + exit 1 + fi + if ! tar -C $download_dir -xvzf $download_dir/$part.tar.gz; then + echo "$0: error un-tarring archive $download_dir/$part.tar.gz" + exit 1 + fi +done + +echo "Merge all train packs into one" +mkdir -p ${download_dir}/LibriSpeech/${train_dir}/ +for part in train-clean-100 train-clean-360 train-other-500; do + mv ${download_dir}/LibriSpeech/${part}/* $download_dir/LibriSpeech/${train_dir}/ +done +echo "Merge train text" +find ${download_dir}/LibriSpeech/${train_dir}/ -name '*.txt' -exec cat {} \; >> ${download_dir}/LibriSpeech/${train_dir}/text + +# Use combined dev-clean and dev-other as validation set +find ${download_dir}/LibriSpeech/dev-clean/ ${download_dir}/LibriSpeech/dev-other/ -name '*.txt' -exec cat {} \; >> ${download_dir}/LibriSpeech/valid_text +find ${download_dir}/LibriSpeech/test-clean/ -name '*.txt' -exec cat {} \; >> ${download_dir}/LibriSpeech/test-clean/text +find ${download_dir}/LibriSpeech/test-other/ -name '*.txt' -exec cat {} \; >> ${download_dir}/LibriSpeech/test-other/text + + +dict=data/lang_char/${train_dir}_${bpemode}${nbpe}_units.txt +encoded=data/lang_char/${train_dir}_${bpemode}${nbpe}_encoded.txt +fairseq_dict=data/lang_char/${train_dir}_${bpemode}${nbpe}_fairseq_dict.txt +bpemodel=data/lang_char/${train_dir}_${bpemode}${nbpe} +echo "dictionary: ${dict}" +echo "Dictionary preparation" +mkdir -p data/lang_char/ +echo " 3" > ${dict} +echo "
2" >> ${dict} +echo " 1" >> ${dict} +cut -f 2- -d" " ${download_dir}/LibriSpeech/${train_dir}/text > data/lang_char/input.txt +spm_train --input=data/lang_char/input.txt --vocab_size=${nbpe} --model_type=${bpemode} --model_prefix=${bpemodel} --input_sentence_size=100000000 --unk_id=3 --eos_id=2 --pad_id=1 --bos_id=-1 --character_coverage=1 +spm_encode --model=${bpemodel}.model --output_format=piece < data/lang_char/input.txt > ${encoded} +cat ${encoded} | tr ' ' '\n' | sort | uniq | awk '{print $0 " " NR+3}' >> ${dict} +cat ${encoded} | tr ' ' '\n' | sort | uniq -c | awk '{print $2 " " $1}' > ${fairseq_dict} +wc -l ${dict} + +echo "Prepare train and test jsons" +for part in train_960 test-other test-clean; do + python ${fairseq_root}/examples/speech_recognition/datasets/asr_prep_json.py --audio-dirs ${download_dir}/LibriSpeech/${part} --labels ${download_dir}/LibriSpeech/${part}/text --spm-model ${bpemodel}.model --audio-format flac --dictionary ${fairseq_dict} --output ${part}.json +done +# fairseq expects to find train.json and valid.json during training +mv train_960.json train.json + +echo "Prepare valid json" +python ${fairseq_root}/examples/speech_recognition/datasets/asr_prep_json.py --audio-dirs ${download_dir}/LibriSpeech/dev-clean ${download_dir}/LibriSpeech/dev-other --labels ${download_dir}/LibriSpeech/valid_text --spm-model ${bpemodel}.model --audio-format flac --dictionary ${fairseq_dict} --output valid.json + +cp ${fairseq_dict} ./dict.txt +cp ${bpemodel}.model ./spm.model diff --git a/fairseq-tools/fairseq/examples/speech_recognition/infer.py b/fairseq-tools/fairseq/examples/speech_recognition/infer.py new file mode 100644 index 00000000..a197ab5a --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/infer.py @@ -0,0 +1,464 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Run inference for pre-processed data with a trained model. +""" + +import logging +import math +import os +import sys + +import editdistance +import numpy as np +import torch +from fairseq import checkpoint_utils, options, progress_bar, tasks, utils +from fairseq.data.data_utils import post_process +from fairseq.logging.meters import StopwatchMeter, TimeMeter + + +logging.basicConfig() +logging.root.setLevel(logging.INFO) +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +def add_asr_eval_argument(parser): + parser.add_argument("--kspmodel", default=None, help="sentence piece model") + parser.add_argument( + "--wfstlm", default=None, help="wfstlm on dictonary output units" + ) + parser.add_argument( + "--rnnt_decoding_type", + default="greedy", + help="wfstlm on dictonary\ +output units", + ) + try: + parser.add_argument( + "--lm-weight", + "--lm_weight", + type=float, + default=0.2, + help="weight for lm while interpolating with neural score", + ) + except: + pass + parser.add_argument( + "--rnnt_len_penalty", default=-0.5, help="rnnt length penalty on word level" + ) + parser.add_argument( + "--w2l-decoder", + choices=["viterbi", "kenlm", "fairseqlm"], + help="use a w2l decoder", + ) + parser.add_argument("--lexicon", help="lexicon for w2l decoder") + parser.add_argument("--unit-lm", action="store_true", help="if using a unit lm") + parser.add_argument("--kenlm-model", "--lm-model", help="lm model for w2l decoder") + parser.add_argument("--beam-threshold", type=float, default=25.0) + parser.add_argument("--beam-size-token", type=float, default=100) + parser.add_argument("--word-score", type=float, default=1.0) + parser.add_argument("--unk-weight", type=float, default=-math.inf) + parser.add_argument("--sil-weight", type=float, default=0.0) + parser.add_argument( + "--dump-emissions", + type=str, + default=None, + help="if present, dumps emissions into this file and exits", + ) + parser.add_argument( + "--dump-features", + type=str, + default=None, + help="if present, dumps features into this file and exits", + ) + parser.add_argument( + "--load-emissions", + type=str, + default=None, + help="if present, loads emissions from this file", + ) + return parser + + +def check_args(args): + # assert args.path is not None, "--path required for generation!" + # assert args.results_path is not None, "--results_path required for generation!" + assert ( + not args.sampling or args.nbest == args.beam + ), "--sampling requires --nbest to be equal to --beam" + assert ( + args.replace_unk is None or args.raw_text + ), "--replace-unk requires a raw text dataset (--raw-text)" + + +def get_dataset_itr(args, task, models): + return task.get_batch_iterator( + dataset=task.dataset(args.gen_subset), + max_tokens=args.max_tokens, + max_sentences=args.batch_size, + max_positions=(sys.maxsize, sys.maxsize), + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=args.required_batch_size_multiple, + num_shards=args.num_shards, + shard_id=args.shard_id, + num_workers=args.num_workers, + data_buffer_size=args.data_buffer_size, + ).next_epoch_itr(shuffle=False) + + +def process_predictions( + args, hypos, sp, tgt_dict, target_tokens, res_files, speaker, id +): + for hypo in hypos[: min(len(hypos), args.nbest)]: + hyp_pieces = tgt_dict.string(hypo["tokens"].int().cpu()) + + if "words" in hypo: + hyp_words = " ".join(hypo["words"]) + else: + hyp_words = post_process(hyp_pieces, args.remove_bpe) + + if res_files is not None: + print( + "{} ({}-{})".format(hyp_pieces, speaker, id), + file=res_files["hypo.units"], + ) + print( + "{} ({}-{})".format(hyp_words, speaker, id), + file=res_files["hypo.words"], + ) + + tgt_pieces = tgt_dict.string(target_tokens) + tgt_words = post_process(tgt_pieces, args.remove_bpe) + + if res_files is not None: + print( + "{} ({}-{})".format(tgt_pieces, speaker, id), + file=res_files["ref.units"], + ) + print( + "{} ({}-{})".format(tgt_words, speaker, id), file=res_files["ref.words"] + ) + # only score top hypothesis + if not args.quiet: + logger.debug("HYPO:" + hyp_words) + logger.debug("TARGET:" + tgt_words) + logger.debug("___________________") + + hyp_words = hyp_words.split() + tgt_words = tgt_words.split() + return editdistance.eval(hyp_words, tgt_words), len(tgt_words) + + +def prepare_result_files(args): + def get_res_file(file_prefix): + if args.num_shards > 1: + file_prefix = f"{args.shard_id}_{file_prefix}" + path = os.path.join( + args.results_path, + "{}-{}-{}.txt".format( + file_prefix, os.path.basename(args.path), args.gen_subset + ), + ) + return open(path, "w", buffering=1) + + if not args.results_path: + return None + + return { + "hypo.words": get_res_file("hypo.word"), + "hypo.units": get_res_file("hypo.units"), + "ref.words": get_res_file("ref.word"), + "ref.units": get_res_file("ref.units"), + } + + +def load_models_and_criterions( + filenames, data_path, arg_overrides=None, task=None, model_state=None +): + models = [] + criterions = [] + + if arg_overrides is None: + arg_overrides = {} + + arg_overrides["wer_args"] = None + arg_overrides["data"] = data_path + + if filenames is None: + assert model_state is not None + filenames = [0] + else: + filenames = filenames.split(":") + + for filename in filenames: + if model_state is None: + if not os.path.exists(filename): + raise IOError("Model file not found: {}".format(filename)) + state = checkpoint_utils.load_checkpoint_to_cpu(filename, arg_overrides) + else: + state = model_state + + args = state["args"] + if task is None: + task = tasks.setup_task(args) + model = task.build_model(args) + model.load_state_dict(state["model"], strict=True) + models.append(model) + + criterion = task.build_criterion(args) + if "criterion" in state: + criterion.load_state_dict(state["criterion"], strict=True) + criterions.append(criterion) + return models, criterions, args + + +def optimize_models(args, use_cuda, models): + """Optimize ensemble for generation""" + for model in models: + model.make_generation_fast_( + beamable_mm_beam_size=None if args.no_beamable_mm else args.beam, + need_attn=args.print_alignment, + ) + if args.fp16: + model.half() + if use_cuda: + model.cuda() + + +class ExistingEmissionsDecoder(object): + def __init__(self, decoder, emissions): + self.decoder = decoder + self.emissions = emissions + + def generate(self, models, sample, **unused): + ids = sample["id"].cpu().numpy() + try: + emissions = np.stack(self.emissions[ids]) + except: + print([x.shape for x in self.emissions[ids]]) + raise Exception("invalid sizes") + emissions = torch.from_numpy(emissions) + return self.decoder.decode(emissions) + + +def main(args, task=None, model_state=None): + check_args(args) + + if args.max_tokens is None and args.batch_size is None: + args.max_tokens = 4000000 + logger.info(args) + + use_cuda = torch.cuda.is_available() and not args.cpu + + if task is None: + # Load dataset splits + task = tasks.setup_task(args) + task.load_dataset(args.gen_subset) + + logger.info( + "| {} {} {} examples".format( + args.data, args.gen_subset, len(task.dataset(args.gen_subset)) + ) + ) + + # Set dictionary + tgt_dict = task.target_dictionary + + logger.info("| decoding with criterion {}".format(args.criterion)) + + # Load ensemble + + if args.load_emissions: + models, criterions = [], [] + else: + logger.info("| loading model(s) from {}".format(args.path)) + models, criterions, _ = load_models_and_criterions( + args.path, + data_path=args.data, + arg_overrides=eval(args.model_overrides), # noqa + task=task, + model_state=model_state, + ) + optimize_models(args, use_cuda, models) + + # hack to pass transitions to W2lDecoder + if args.criterion == "asg_loss": + trans = criterions[0].asg.trans.data + args.asg_transitions = torch.flatten(trans).tolist() + + # Load dataset (possibly sharded) + itr = get_dataset_itr(args, task, models) + + # Initialize generator + gen_timer = StopwatchMeter() + + def build_generator(args): + w2l_decoder = getattr(args, "w2l_decoder", None) + if w2l_decoder == "viterbi": + from examples.speech_recognition.w2l_decoder import W2lViterbiDecoder + + return W2lViterbiDecoder(args, task.target_dictionary) + elif w2l_decoder == "kenlm": + from examples.speech_recognition.w2l_decoder import W2lKenLMDecoder + + return W2lKenLMDecoder(args, task.target_dictionary) + elif w2l_decoder == "fairseqlm": + from examples.speech_recognition.w2l_decoder import W2lFairseqLMDecoder + + return W2lFairseqLMDecoder(args, task.target_dictionary) + else: + print( + "only wav2letter decoders with (viterbi, kenlm, fairseqlm) options are supported at the moment" + ) + + # please do not touch this unless you test both generate.py and infer.py with audio_pretraining task + generator = build_generator(args) + + if args.load_emissions: + generator = ExistingEmissionsDecoder( + generator, np.load(args.load_emissions, allow_pickle=True) + ) + logger.info("loaded emissions from " + args.load_emissions) + + num_sentences = 0 + + if args.results_path is not None and not os.path.exists(args.results_path): + os.makedirs(args.results_path) + + max_source_pos = ( + utils.resolve_max_positions( + task.max_positions(), *[model.max_positions() for model in models] + ), + ) + + if max_source_pos is not None: + max_source_pos = max_source_pos[0] + if max_source_pos is not None: + max_source_pos = max_source_pos[0] - 1 + + if args.dump_emissions: + emissions = {} + if args.dump_features: + features = {} + models[0].bert.proj = None + else: + res_files = prepare_result_files(args) + errs_t = 0 + lengths_t = 0 + with progress_bar.build_progress_bar(args, itr) as t: + wps_meter = TimeMeter() + for sample in t: + sample = utils.move_to_cuda(sample) if use_cuda else sample + if "net_input" not in sample: + continue + + prefix_tokens = None + if args.prefix_size > 0: + prefix_tokens = sample["target"][:, : args.prefix_size] + + gen_timer.start() + if args.dump_emissions: + with torch.no_grad(): + encoder_out = models[0](**sample["net_input"]) + emm = models[0].get_normalized_probs(encoder_out, log_probs=True) + emm = emm.transpose(0, 1).cpu().numpy() + for i, id in enumerate(sample["id"]): + emissions[id.item()] = emm[i] + continue + elif args.dump_features: + with torch.no_grad(): + encoder_out = models[0](**sample["net_input"]) + feat = encoder_out["encoder_out"].transpose(0, 1).cpu().numpy() + for i, id in enumerate(sample["id"]): + padding = ( + encoder_out["encoder_padding_mask"][i].cpu().numpy() + if encoder_out["encoder_padding_mask"] is not None + else None + ) + features[id.item()] = (feat[i], padding) + continue + hypos = task.inference_step(generator, models, sample, prefix_tokens) + num_generated_tokens = sum(len(h[0]["tokens"]) for h in hypos) + gen_timer.stop(num_generated_tokens) + + for i, sample_id in enumerate(sample["id"].tolist()): + speaker = None + # id = task.dataset(args.gen_subset).ids[int(sample_id)] + id = sample_id + toks = ( + sample["target"][i, :] + if "target_label" not in sample + else sample["target_label"][i, :] + ) + target_tokens = utils.strip_pad(toks, tgt_dict.pad()).int().cpu() + # Process top predictions + errs, length = process_predictions( + args, + hypos[i], + None, + tgt_dict, + target_tokens, + res_files, + speaker, + id, + ) + errs_t += errs + lengths_t += length + + wps_meter.update(num_generated_tokens) + t.log({"wps": round(wps_meter.avg)}) + num_sentences += ( + sample["nsentences"] if "nsentences" in sample else sample["id"].numel() + ) + + wer = None + if args.dump_emissions: + emm_arr = [] + for i in range(len(emissions)): + emm_arr.append(emissions[i]) + np.save(args.dump_emissions, emm_arr) + logger.info(f"saved {len(emissions)} emissions to {args.dump_emissions}") + elif args.dump_features: + feat_arr = [] + for i in range(len(features)): + feat_arr.append(features[i]) + np.save(args.dump_features, feat_arr) + logger.info(f"saved {len(features)} emissions to {args.dump_features}") + else: + if lengths_t > 0: + wer = errs_t * 100.0 / lengths_t + logger.info(f"WER: {wer}") + + logger.info( + "| Processed {} sentences ({} tokens) in {:.1f}s ({:.2f}" + "sentences/s, {:.2f} tokens/s)".format( + num_sentences, + gen_timer.n, + gen_timer.sum, + num_sentences / gen_timer.sum, + 1.0 / gen_timer.avg, + ) + ) + logger.info("| Generate {} with beam={}".format(args.gen_subset, args.beam)) + return task, wer + + +def make_parser(): + parser = options.get_generation_parser() + parser = add_asr_eval_argument(parser) + return parser + + +def cli_main(): + parser = make_parser() + args = options.parse_args_and_arch(parser) + main(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/examples/speech_recognition/models/__init__.py b/fairseq-tools/fairseq/examples/speech_recognition/models/__init__.py new file mode 100644 index 00000000..0ad9663f --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/models/__init__.py @@ -0,0 +1,8 @@ +import importlib +import os + + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + model_name = file[: file.find(".py")] + importlib.import_module("examples.speech_recognition.models." + model_name) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/models/vggtransformer.py b/fairseq-tools/fairseq/examples/speech_recognition/models/vggtransformer.py new file mode 100644 index 00000000..97974360 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/models/vggtransformer.py @@ -0,0 +1,1019 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import math +from collections.abc import Iterable + +import torch +import torch.nn as nn +from examples.speech_recognition.data.data_utils import lengths_to_encoder_padding_mask +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqEncoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.modules import ( + LinearizedConvolution, + TransformerDecoderLayer, + TransformerEncoderLayer, + VGGBlock, +) + + +@register_model("asr_vggtransformer") +class VGGTransformerModel(FairseqEncoderDecoderModel): + """ + Transformers with convolutional context for ASR + https://arxiv.org/abs/1904.11660 + """ + + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--input-feat-per-channel", + type=int, + metavar="N", + help="encoder input dimension per input channel", + ) + parser.add_argument( + "--vggblock-enc-config", + type=str, + metavar="EXPR", + help=""" + an array of tuples each containing the configuration of one vggblock: + [(out_channels, + conv_kernel_size, + pooling_kernel_size, + num_conv_layers, + use_layer_norm), ...]) + """, + ) + parser.add_argument( + "--transformer-enc-config", + type=str, + metavar="EXPR", + help="""" + a tuple containing the configuration of the encoder transformer layers + configurations: + [(input_dim, + num_heads, + ffn_dim, + normalize_before, + dropout, + attention_dropout, + relu_dropout), ...]') + """, + ) + parser.add_argument( + "--enc-output-dim", + type=int, + metavar="N", + help=""" + encoder output dimension, can be None. If specified, projecting the + transformer output to the specified dimension""", + ) + parser.add_argument( + "--in-channels", + type=int, + metavar="N", + help="number of encoder input channels", + ) + parser.add_argument( + "--tgt-embed-dim", + type=int, + metavar="N", + help="embedding dimension of the decoder target tokens", + ) + parser.add_argument( + "--transformer-dec-config", + type=str, + metavar="EXPR", + help=""" + a tuple containing the configuration of the decoder transformer layers + configurations: + [(input_dim, + num_heads, + ffn_dim, + normalize_before, + dropout, + attention_dropout, + relu_dropout), ...] + """, + ) + parser.add_argument( + "--conv-dec-config", + type=str, + metavar="EXPR", + help=""" + an array of tuples for the decoder 1-D convolution config + [(out_channels, conv_kernel_size, use_layer_norm), ...]""", + ) + + @classmethod + def build_encoder(cls, args, task): + return VGGTransformerEncoder( + input_feat_per_channel=args.input_feat_per_channel, + vggblock_config=eval(args.vggblock_enc_config), + transformer_config=eval(args.transformer_enc_config), + encoder_output_dim=args.enc_output_dim, + in_channels=args.in_channels, + ) + + @classmethod + def build_decoder(cls, args, task): + return TransformerDecoder( + dictionary=task.target_dictionary, + embed_dim=args.tgt_embed_dim, + transformer_config=eval(args.transformer_dec_config), + conv_config=eval(args.conv_dec_config), + encoder_output_dim=args.enc_output_dim, + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + # make sure that all args are properly defaulted + # (in case there are any new ones) + base_architecture(args) + + encoder = cls.build_encoder(args, task) + decoder = cls.build_decoder(args, task) + return cls(encoder, decoder) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + # net_output['encoder_out'] is a (B, T, D) tensor + lprobs = super().get_normalized_probs(net_output, log_probs, sample) + lprobs.batch_first = True + return lprobs + + +DEFAULT_ENC_VGGBLOCK_CONFIG = ((32, 3, 2, 2, False),) * 2 +DEFAULT_ENC_TRANSFORMER_CONFIG = ((256, 4, 1024, True, 0.2, 0.2, 0.2),) * 2 +# 256: embedding dimension +# 4: number of heads +# 1024: FFN +# True: apply layerNorm before (dropout + resiaul) instead of after +# 0.2 (dropout): dropout after MultiheadAttention and second FC +# 0.2 (attention_dropout): dropout in MultiheadAttention +# 0.2 (relu_dropout): dropout after ReLu +DEFAULT_DEC_TRANSFORMER_CONFIG = ((256, 2, 1024, True, 0.2, 0.2, 0.2),) * 2 +DEFAULT_DEC_CONV_CONFIG = ((256, 3, True),) * 2 + + +# TODO: repace transformer encoder config from one liner +# to explicit args to get rid of this transformation +def prepare_transformer_encoder_params( + input_dim, + num_heads, + ffn_dim, + normalize_before, + dropout, + attention_dropout, + relu_dropout, +): + args = argparse.Namespace() + args.encoder_embed_dim = input_dim + args.encoder_attention_heads = num_heads + args.attention_dropout = attention_dropout + args.dropout = dropout + args.activation_dropout = relu_dropout + args.encoder_normalize_before = normalize_before + args.encoder_ffn_embed_dim = ffn_dim + return args + + +def prepare_transformer_decoder_params( + input_dim, + num_heads, + ffn_dim, + normalize_before, + dropout, + attention_dropout, + relu_dropout, +): + args = argparse.Namespace() + args.decoder_embed_dim = input_dim + args.decoder_attention_heads = num_heads + args.attention_dropout = attention_dropout + args.dropout = dropout + args.activation_dropout = relu_dropout + args.decoder_normalize_before = normalize_before + args.decoder_ffn_embed_dim = ffn_dim + return args + + +class VGGTransformerEncoder(FairseqEncoder): + """VGG + Transformer encoder""" + + def __init__( + self, + input_feat_per_channel, + vggblock_config=DEFAULT_ENC_VGGBLOCK_CONFIG, + transformer_config=DEFAULT_ENC_TRANSFORMER_CONFIG, + encoder_output_dim=512, + in_channels=1, + transformer_context=None, + transformer_sampling=None, + ): + """constructor for VGGTransformerEncoder + + Args: + - input_feat_per_channel: feature dim (not including stacked, + just base feature) + - in_channel: # input channels (e.g., if stack 8 feature vector + together, this is 8) + - vggblock_config: configuration of vggblock, see comments on + DEFAULT_ENC_VGGBLOCK_CONFIG + - transformer_config: configuration of transformer layer, see comments + on DEFAULT_ENC_TRANSFORMER_CONFIG + - encoder_output_dim: final transformer output embedding dimension + - transformer_context: (left, right) if set, self-attention will be focused + on (t-left, t+right) + - transformer_sampling: an iterable of int, must match with + len(transformer_config), transformer_sampling[i] indicates sampling + factor for i-th transformer layer, after multihead att and feedfoward + part + """ + super().__init__(None) + + self.num_vggblocks = 0 + if vggblock_config is not None: + if not isinstance(vggblock_config, Iterable): + raise ValueError("vggblock_config is not iterable") + self.num_vggblocks = len(vggblock_config) + + self.conv_layers = nn.ModuleList() + self.in_channels = in_channels + self.input_dim = input_feat_per_channel + self.pooling_kernel_sizes = [] + + if vggblock_config is not None: + for _, config in enumerate(vggblock_config): + ( + out_channels, + conv_kernel_size, + pooling_kernel_size, + num_conv_layers, + layer_norm, + ) = config + self.conv_layers.append( + VGGBlock( + in_channels, + out_channels, + conv_kernel_size, + pooling_kernel_size, + num_conv_layers, + input_dim=input_feat_per_channel, + layer_norm=layer_norm, + ) + ) + self.pooling_kernel_sizes.append(pooling_kernel_size) + in_channels = out_channels + input_feat_per_channel = self.conv_layers[-1].output_dim + + transformer_input_dim = self.infer_conv_output_dim( + self.in_channels, self.input_dim + ) + # transformer_input_dim is the output dimension of VGG part + + self.validate_transformer_config(transformer_config) + self.transformer_context = self.parse_transformer_context(transformer_context) + self.transformer_sampling = self.parse_transformer_sampling( + transformer_sampling, len(transformer_config) + ) + + self.transformer_layers = nn.ModuleList() + + if transformer_input_dim != transformer_config[0][0]: + self.transformer_layers.append( + Linear(transformer_input_dim, transformer_config[0][0]) + ) + self.transformer_layers.append( + TransformerEncoderLayer( + prepare_transformer_encoder_params(*transformer_config[0]) + ) + ) + + for i in range(1, len(transformer_config)): + if transformer_config[i - 1][0] != transformer_config[i][0]: + self.transformer_layers.append( + Linear(transformer_config[i - 1][0], transformer_config[i][0]) + ) + self.transformer_layers.append( + TransformerEncoderLayer( + prepare_transformer_encoder_params(*transformer_config[i]) + ) + ) + + self.encoder_output_dim = encoder_output_dim + self.transformer_layers.extend( + [ + Linear(transformer_config[-1][0], encoder_output_dim), + LayerNorm(encoder_output_dim), + ] + ) + + def forward(self, src_tokens, src_lengths, **kwargs): + """ + src_tokens: padded tensor (B, T, C * feat) + src_lengths: tensor of original lengths of input utterances (B,) + """ + bsz, max_seq_len, _ = src_tokens.size() + x = src_tokens.view(bsz, max_seq_len, self.in_channels, self.input_dim) + x = x.transpose(1, 2).contiguous() + # (B, C, T, feat) + + for layer_idx in range(len(self.conv_layers)): + x = self.conv_layers[layer_idx](x) + + bsz, _, output_seq_len, _ = x.size() + + # (B, C, T, feat) -> (B, T, C, feat) -> (T, B, C, feat) -> (T, B, C * feat) + x = x.transpose(1, 2).transpose(0, 1) + x = x.contiguous().view(output_seq_len, bsz, -1) + + input_lengths = src_lengths.clone() + for s in self.pooling_kernel_sizes: + input_lengths = (input_lengths.float() / s).ceil().long() + + encoder_padding_mask, _ = lengths_to_encoder_padding_mask( + input_lengths, batch_first=True + ) + if not encoder_padding_mask.any(): + encoder_padding_mask = None + + subsampling_factor = int(max_seq_len * 1.0 / output_seq_len + 0.5) + attn_mask = self.lengths_to_attn_mask(input_lengths, subsampling_factor) + + transformer_layer_idx = 0 + + for layer_idx in range(len(self.transformer_layers)): + + if isinstance(self.transformer_layers[layer_idx], TransformerEncoderLayer): + x = self.transformer_layers[layer_idx]( + x, encoder_padding_mask, attn_mask + ) + + if self.transformer_sampling[transformer_layer_idx] != 1: + sampling_factor = self.transformer_sampling[transformer_layer_idx] + x, encoder_padding_mask, attn_mask = self.slice( + x, encoder_padding_mask, attn_mask, sampling_factor + ) + + transformer_layer_idx += 1 + + else: + x = self.transformer_layers[layer_idx](x) + + # encoder_padding_maks is a (T x B) tensor, its [t, b] elements indicate + # whether encoder_output[t, b] is valid or not (valid=0, invalid=1) + + return { + "encoder_out": x, # (T, B, C) + "encoder_padding_mask": encoder_padding_mask.t() + if encoder_padding_mask is not None + else None, + # (B, T) --> (T, B) + } + + def infer_conv_output_dim(self, in_channels, input_dim): + sample_seq_len = 200 + sample_bsz = 10 + x = torch.randn(sample_bsz, in_channels, sample_seq_len, input_dim) + for i, _ in enumerate(self.conv_layers): + x = self.conv_layers[i](x) + x = x.transpose(1, 2) + mb, seq = x.size()[:2] + return x.contiguous().view(mb, seq, -1).size(-1) + + def validate_transformer_config(self, transformer_config): + for config in transformer_config: + input_dim, num_heads = config[:2] + if input_dim % num_heads != 0: + msg = ( + "ERROR in transformer config {}: ".format(config) + + "input dimension {} ".format(input_dim) + + "not dividable by number of heads {}".format(num_heads) + ) + raise ValueError(msg) + + def parse_transformer_context(self, transformer_context): + """ + transformer_context can be the following: + - None; indicates no context is used, i.e., + transformer can access full context + - a tuple/list of two int; indicates left and right context, + any number <0 indicates infinite context + * e.g., (5, 6) indicates that for query at x_t, transformer can + access [t-5, t+6] (inclusive) + * e.g., (-1, 6) indicates that for query at x_t, transformer can + access [0, t+6] (inclusive) + """ + if transformer_context is None: + return None + + if not isinstance(transformer_context, Iterable): + raise ValueError("transformer context must be Iterable if it is not None") + + if len(transformer_context) != 2: + raise ValueError("transformer context must have length 2") + + left_context = transformer_context[0] + if left_context < 0: + left_context = None + + right_context = transformer_context[1] + if right_context < 0: + right_context = None + + if left_context is None and right_context is None: + return None + + return (left_context, right_context) + + def parse_transformer_sampling(self, transformer_sampling, num_layers): + """ + parsing transformer sampling configuration + + Args: + - transformer_sampling, accepted input: + * None, indicating no sampling + * an Iterable with int (>0) as element + - num_layers, expected number of transformer layers, must match with + the length of transformer_sampling if it is not None + + Returns: + - A tuple with length num_layers + """ + if transformer_sampling is None: + return (1,) * num_layers + + if not isinstance(transformer_sampling, Iterable): + raise ValueError( + "transformer_sampling must be an iterable if it is not None" + ) + + if len(transformer_sampling) != num_layers: + raise ValueError( + "transformer_sampling {} does not match with the number " + "of layers {}".format(transformer_sampling, num_layers) + ) + + for layer, value in enumerate(transformer_sampling): + if not isinstance(value, int): + raise ValueError("Invalid value in transformer_sampling: ") + if value < 1: + raise ValueError( + "{} layer's subsampling is {}.".format(layer, value) + + " This is not allowed! " + ) + return transformer_sampling + + def slice(self, embedding, padding_mask, attn_mask, sampling_factor): + """ + embedding is a (T, B, D) tensor + padding_mask is a (B, T) tensor or None + attn_mask is a (T, T) tensor or None + """ + embedding = embedding[::sampling_factor, :, :] + if padding_mask is not None: + padding_mask = padding_mask[:, ::sampling_factor] + if attn_mask is not None: + attn_mask = attn_mask[::sampling_factor, ::sampling_factor] + + return embedding, padding_mask, attn_mask + + def lengths_to_attn_mask(self, input_lengths, subsampling_factor=1): + """ + create attention mask according to sequence lengths and transformer + context + + Args: + - input_lengths: (B, )-shape Int/Long tensor; input_lengths[b] is + the length of b-th sequence + - subsampling_factor: int + * Note that the left_context and right_context is specified in + the input frame-level while input to transformer may already + go through subsampling (e.g., the use of striding in vggblock) + we use subsampling_factor to scale the left/right context + + Return: + - a (T, T) binary tensor or None, where T is max(input_lengths) + * if self.transformer_context is None, None + * if left_context is None, + * attn_mask[t, t + right_context + 1:] = 1 + * others = 0 + * if right_context is None, + * attn_mask[t, 0:t - left_context] = 1 + * others = 0 + * elsif + * attn_mask[t, t - left_context: t + right_context + 1] = 0 + * others = 1 + """ + if self.transformer_context is None: + return None + + maxT = torch.max(input_lengths).item() + attn_mask = torch.zeros(maxT, maxT) + + left_context = self.transformer_context[0] + right_context = self.transformer_context[1] + if left_context is not None: + left_context = math.ceil(self.transformer_context[0] / subsampling_factor) + if right_context is not None: + right_context = math.ceil(self.transformer_context[1] / subsampling_factor) + + for t in range(maxT): + if left_context is not None: + st = 0 + en = max(st, t - left_context) + attn_mask[t, st:en] = 1 + if right_context is not None: + st = t + right_context + 1 + st = min(st, maxT - 1) + attn_mask[t, st:] = 1 + + return attn_mask.to(input_lengths.device) + + def reorder_encoder_out(self, encoder_out, new_order): + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(1, new_order) + return encoder_out + + +class TransformerDecoder(FairseqIncrementalDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs. + Default: ``False`` + left_pad (bool, optional): whether the input is left-padded. Default: + ``False`` + """ + + def __init__( + self, + dictionary, + embed_dim=512, + transformer_config=DEFAULT_ENC_TRANSFORMER_CONFIG, + conv_config=DEFAULT_DEC_CONV_CONFIG, + encoder_output_dim=512, + ): + + super().__init__(dictionary) + vocab_size = len(dictionary) + self.padding_idx = dictionary.pad() + self.embed_tokens = Embedding(vocab_size, embed_dim, self.padding_idx) + + self.conv_layers = nn.ModuleList() + for i in range(len(conv_config)): + out_channels, kernel_size, layer_norm = conv_config[i] + if i == 0: + conv_layer = LinearizedConv1d( + embed_dim, out_channels, kernel_size, padding=kernel_size - 1 + ) + else: + conv_layer = LinearizedConv1d( + conv_config[i - 1][0], + out_channels, + kernel_size, + padding=kernel_size - 1, + ) + self.conv_layers.append(conv_layer) + if layer_norm: + self.conv_layers.append(nn.LayerNorm(out_channels)) + self.conv_layers.append(nn.ReLU()) + + self.layers = nn.ModuleList() + if conv_config[-1][0] != transformer_config[0][0]: + self.layers.append(Linear(conv_config[-1][0], transformer_config[0][0])) + self.layers.append( + TransformerDecoderLayer( + prepare_transformer_decoder_params(*transformer_config[0]) + ) + ) + + for i in range(1, len(transformer_config)): + if transformer_config[i - 1][0] != transformer_config[i][0]: + self.layers.append( + Linear(transformer_config[i - 1][0], transformer_config[i][0]) + ) + self.layers.append( + TransformerDecoderLayer( + prepare_transformer_decoder_params(*transformer_config[i]) + ) + ) + self.fc_out = Linear(transformer_config[-1][0], vocab_size) + + def forward(self, prev_output_tokens, encoder_out=None, incremental_state=None): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for input feeding/teacher forcing + encoder_out (Tensor, optional): output from the encoder, used for + encoder-side attention + incremental_state (dict): dictionary used for storing state during + :ref:`Incremental decoding` + Returns: + tuple: + - the last decoder layer's output of shape `(batch, tgt_len, + vocab)` + - the last decoder layer's attention weights of shape `(batch, + tgt_len, src_len)` + """ + target_padding_mask = ( + (prev_output_tokens == self.padding_idx).to(prev_output_tokens.device) + if incremental_state is None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + + # embed tokens + x = self.embed_tokens(prev_output_tokens) + + # B x T x C -> T x B x C + x = self._transpose_if_training(x, incremental_state) + + for layer in self.conv_layers: + if isinstance(layer, LinearizedConvolution): + x = layer(x, incremental_state) + else: + x = layer(x) + + # B x T x C -> T x B x C + x = self._transpose_if_inference(x, incremental_state) + + # decoder layers + for layer in self.layers: + if isinstance(layer, TransformerDecoderLayer): + x, *_ = layer( + x, + (encoder_out["encoder_out"] if encoder_out is not None else None), + ( + encoder_out["encoder_padding_mask"].t() + if encoder_out["encoder_padding_mask"] is not None + else None + ), + incremental_state, + self_attn_mask=( + self.buffered_future_mask(x) + if incremental_state is None + else None + ), + self_attn_padding_mask=( + target_padding_mask if incremental_state is None else None + ), + ) + else: + x = layer(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + x = self.fc_out(x) + + return x, None + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + if ( + not hasattr(self, "_future_mask") + or self._future_mask is None + or self._future_mask.device != tensor.device + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(tensor.new(dim, dim)), 1 + ) + if self._future_mask.size(0) < dim: + self._future_mask = torch.triu( + utils.fill_with_neg_inf(self._future_mask.resize_(dim, dim)), 1 + ) + return self._future_mask[:dim, :dim] + + def _transpose_if_training(self, x, incremental_state): + if incremental_state is None: + x = x.transpose(0, 1) + return x + + def _transpose_if_inference(self, x, incremental_state): + if incremental_state: + x = x.transpose(0, 1) + return x + + +@register_model("asr_vggtransformer_encoder") +class VGGTransformerEncoderModel(FairseqEncoderModel): + def __init__(self, encoder): + super().__init__(encoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--input-feat-per-channel", + type=int, + metavar="N", + help="encoder input dimension per input channel", + ) + parser.add_argument( + "--vggblock-enc-config", + type=str, + metavar="EXPR", + help=""" + an array of tuples each containing the configuration of one vggblock + [(out_channels, conv_kernel_size, pooling_kernel_size,num_conv_layers), ...] + """, + ) + parser.add_argument( + "--transformer-enc-config", + type=str, + metavar="EXPR", + help=""" + a tuple containing the configuration of the Transformer layers + configurations: + [(input_dim, + num_heads, + ffn_dim, + normalize_before, + dropout, + attention_dropout, + relu_dropout), ]""", + ) + parser.add_argument( + "--enc-output-dim", + type=int, + metavar="N", + help="encoder output dimension, projecting the LSTM output", + ) + parser.add_argument( + "--in-channels", + type=int, + metavar="N", + help="number of encoder input channels", + ) + parser.add_argument( + "--transformer-context", + type=str, + metavar="EXPR", + help=""" + either None or a tuple of two ints, indicating left/right context a + transformer can have access to""", + ) + parser.add_argument( + "--transformer-sampling", + type=str, + metavar="EXPR", + help=""" + either None or a tuple of ints, indicating sampling factor in each layer""", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + base_architecture_enconly(args) + encoder = VGGTransformerEncoderOnly( + vocab_size=len(task.target_dictionary), + input_feat_per_channel=args.input_feat_per_channel, + vggblock_config=eval(args.vggblock_enc_config), + transformer_config=eval(args.transformer_enc_config), + encoder_output_dim=args.enc_output_dim, + in_channels=args.in_channels, + transformer_context=eval(args.transformer_context), + transformer_sampling=eval(args.transformer_sampling), + ) + return cls(encoder) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + # net_output['encoder_out'] is a (T, B, D) tensor + lprobs = super().get_normalized_probs(net_output, log_probs, sample) + # lprobs is a (T, B, D) tensor + # we need to transoose to get (B, T, D) tensor + lprobs = lprobs.transpose(0, 1).contiguous() + lprobs.batch_first = True + return lprobs + + +class VGGTransformerEncoderOnly(VGGTransformerEncoder): + def __init__( + self, + vocab_size, + input_feat_per_channel, + vggblock_config=DEFAULT_ENC_VGGBLOCK_CONFIG, + transformer_config=DEFAULT_ENC_TRANSFORMER_CONFIG, + encoder_output_dim=512, + in_channels=1, + transformer_context=None, + transformer_sampling=None, + ): + super().__init__( + input_feat_per_channel=input_feat_per_channel, + vggblock_config=vggblock_config, + transformer_config=transformer_config, + encoder_output_dim=encoder_output_dim, + in_channels=in_channels, + transformer_context=transformer_context, + transformer_sampling=transformer_sampling, + ) + self.fc_out = Linear(self.encoder_output_dim, vocab_size) + + def forward(self, src_tokens, src_lengths, **kwargs): + """ + src_tokens: padded tensor (B, T, C * feat) + src_lengths: tensor of original lengths of input utterances (B,) + """ + + enc_out = super().forward(src_tokens, src_lengths) + x = self.fc_out(enc_out["encoder_out"]) + # x = F.log_softmax(x, dim=-1) + # Note: no need this line, because model.get_normalized_prob will call + # log_softmax + return { + "encoder_out": x, # (T, B, C) + "encoder_padding_mask": enc_out["encoder_padding_mask"], # (T, B) + } + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return (1e6, 1e6) # an arbitrary large number + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + # nn.init.uniform_(m.weight, -0.1, 0.1) + # nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, bias=True, dropout=0): + """Linear layer (input: N x T x C)""" + m = nn.Linear(in_features, out_features, bias=bias) + # m.weight.data.uniform_(-0.1, 0.1) + # if bias: + # m.bias.data.uniform_(-0.1, 0.1) + return m + + +def LinearizedConv1d(in_channels, out_channels, kernel_size, dropout=0, **kwargs): + """Weight-normalized Conv1d layer optimized for decoding""" + m = LinearizedConvolution(in_channels, out_channels, kernel_size, **kwargs) + std = math.sqrt((4 * (1.0 - dropout)) / (m.kernel_size[0] * in_channels)) + nn.init.normal_(m.weight, mean=0, std=std) + nn.init.constant_(m.bias, 0) + return nn.utils.weight_norm(m, dim=2) + + +def LayerNorm(embedding_dim): + m = nn.LayerNorm(embedding_dim) + return m + + +# seq2seq models +def base_architecture(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 40) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", DEFAULT_ENC_VGGBLOCK_CONFIG + ) + args.transformer_enc_config = getattr( + args, "transformer_enc_config", DEFAULT_ENC_TRANSFORMER_CONFIG + ) + args.enc_output_dim = getattr(args, "enc_output_dim", 512) + args.in_channels = getattr(args, "in_channels", 1) + args.tgt_embed_dim = getattr(args, "tgt_embed_dim", 128) + args.transformer_dec_config = getattr( + args, "transformer_dec_config", DEFAULT_ENC_TRANSFORMER_CONFIG + ) + args.conv_dec_config = getattr(args, "conv_dec_config", DEFAULT_DEC_CONV_CONFIG) + args.transformer_context = getattr(args, "transformer_context", "None") + + +@register_model_architecture("asr_vggtransformer", "vggtransformer_1") +def vggtransformer_1(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", "[(64, 3, 2, 2, True), (128, 3, 2, 2, True)]" + ) + args.transformer_enc_config = getattr( + args, + "transformer_enc_config", + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 14", + ) + args.enc_output_dim = getattr(args, "enc_output_dim", 1024) + args.tgt_embed_dim = getattr(args, "tgt_embed_dim", 128) + args.conv_dec_config = getattr(args, "conv_dec_config", "((256, 3, True),) * 4") + args.transformer_dec_config = getattr( + args, + "transformer_dec_config", + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 4", + ) + + +@register_model_architecture("asr_vggtransformer", "vggtransformer_2") +def vggtransformer_2(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", "[(64, 3, 2, 2, True), (128, 3, 2, 2, True)]" + ) + args.transformer_enc_config = getattr( + args, + "transformer_enc_config", + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 16", + ) + args.enc_output_dim = getattr(args, "enc_output_dim", 1024) + args.tgt_embed_dim = getattr(args, "tgt_embed_dim", 512) + args.conv_dec_config = getattr(args, "conv_dec_config", "((256, 3, True),) * 4") + args.transformer_dec_config = getattr( + args, + "transformer_dec_config", + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 6", + ) + + +@register_model_architecture("asr_vggtransformer", "vggtransformer_base") +def vggtransformer_base(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", "[(64, 3, 2, 2, True), (128, 3, 2, 2, True)]" + ) + args.transformer_enc_config = getattr( + args, "transformer_enc_config", "((512, 8, 2048, True, 0.15, 0.15, 0.15),) * 12" + ) + + args.enc_output_dim = getattr(args, "enc_output_dim", 512) + args.tgt_embed_dim = getattr(args, "tgt_embed_dim", 512) + args.conv_dec_config = getattr(args, "conv_dec_config", "((256, 3, True),) * 4") + args.transformer_dec_config = getattr( + args, "transformer_dec_config", "((512, 8, 2048, True, 0.15, 0.15, 0.15),) * 6" + ) + # Size estimations: + # Encoder: + # - vggblock param: 64*1*3*3 + 64*64*3*3 + 128*64*3*3 + 128*128*3 = 258K + # Transformer: + # - input dimension adapter: 2560 x 512 -> 1.31M + # - transformer_layers (x12) --> 37.74M + # * MultiheadAttention: 512*512*3 (in_proj) + 512*512 (out_proj) = 1.048M + # * FFN weight: 512*2048*2 = 2.097M + # - output dimension adapter: 512 x 512 -> 0.26 M + # Decoder: + # - LinearizedConv1d: 512 * 256 * 3 + 256 * 256 * 3 * 3 + # - transformer_layer: (x6) --> 25.16M + # * MultiheadAttention (self-attention): 512*512*3 + 512*512 = 1.048M + # * MultiheadAttention (encoder-attention): 512*512*3 + 512*512 = 1.048M + # * FFN: 512*2048*2 = 2.097M + # Final FC: + # - FC: 512*5000 = 256K (assuming vocab size 5K) + # In total: + # ~65 M + + +# CTC models +def base_architecture_enconly(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 40) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", "[(32, 3, 2, 2, True)] * 2" + ) + args.transformer_enc_config = getattr( + args, "transformer_enc_config", "((256, 4, 1024, True, 0.2, 0.2, 0.2),) * 2" + ) + args.enc_output_dim = getattr(args, "enc_output_dim", 512) + args.in_channels = getattr(args, "in_channels", 1) + args.transformer_context = getattr(args, "transformer_context", "None") + args.transformer_sampling = getattr(args, "transformer_sampling", "None") + + +@register_model_architecture("asr_vggtransformer_encoder", "vggtransformer_enc_1") +def vggtransformer_enc_1(args): + # vggtransformer_1 is the same as vggtransformer_enc_big, except the number + # of layers is increased to 16 + # keep it here for backward compatiablity purpose + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80) + args.vggblock_enc_config = getattr( + args, "vggblock_enc_config", "[(64, 3, 2, 2, True), (128, 3, 2, 2, True)]" + ) + args.transformer_enc_config = getattr( + args, + "transformer_enc_config", + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 16", + ) + args.enc_output_dim = getattr(args, "enc_output_dim", 1024) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/models/w2l_conv_glu_enc.py b/fairseq-tools/fairseq/examples/speech_recognition/models/w2l_conv_glu_enc.py new file mode 100644 index 00000000..655a9b0d --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/models/w2l_conv_glu_enc.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderModel, + register_model, + register_model_architecture, +) +from fairseq.modules.fairseq_dropout import FairseqDropout + + +default_conv_enc_config = """[ + (400, 13, 170, 0.2), + (440, 14, 0, 0.214), + (484, 15, 0, 0.22898), + (532, 16, 0, 0.2450086), + (584, 17, 0, 0.262159202), + (642, 18, 0, 0.28051034614), + (706, 19, 0, 0.30014607037), + (776, 20, 0, 0.321156295296), + (852, 21, 0, 0.343637235966), + (936, 22, 0, 0.367691842484), + (1028, 23, 0, 0.393430271458), + (1130, 24, 0, 0.42097039046), + (1242, 25, 0, 0.450438317792), + (1366, 26, 0, 0.481969000038), + (1502, 27, 0, 0.51570683004), + (1652, 28, 0, 0.551806308143), + (1816, 29, 0, 0.590432749713), +]""" + + +@register_model("asr_w2l_conv_glu_encoder") +class W2lConvGluEncoderModel(FairseqEncoderModel): + def __init__(self, encoder): + super().__init__(encoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--input-feat-per-channel", + type=int, + metavar="N", + help="encoder input dimension per input channel", + ) + parser.add_argument( + "--in-channels", + type=int, + metavar="N", + help="number of encoder input channels", + ) + parser.add_argument( + "--conv-enc-config", + type=str, + metavar="EXPR", + help=""" + an array of tuples each containing the configuration of one conv layer + [(out_channels, kernel_size, padding, dropout), ...] + """, + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + conv_enc_config = getattr(args, "conv_enc_config", default_conv_enc_config) + encoder = W2lConvGluEncoder( + vocab_size=len(task.target_dictionary), + input_feat_per_channel=args.input_feat_per_channel, + in_channels=args.in_channels, + conv_enc_config=eval(conv_enc_config), + ) + return cls(encoder) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + lprobs = super().get_normalized_probs(net_output, log_probs, sample) + lprobs.batch_first = False + return lprobs + + +class W2lConvGluEncoder(FairseqEncoder): + def __init__( + self, vocab_size, input_feat_per_channel, in_channels, conv_enc_config + ): + super().__init__(None) + + self.input_dim = input_feat_per_channel + if in_channels != 1: + raise ValueError("only 1 input channel is currently supported") + + self.conv_layers = nn.ModuleList() + self.linear_layers = nn.ModuleList() + self.dropouts = [] + cur_channels = input_feat_per_channel + + for out_channels, kernel_size, padding, dropout in conv_enc_config: + layer = nn.Conv1d(cur_channels, out_channels, kernel_size, padding=padding) + layer.weight.data.mul_(math.sqrt(3)) # match wav2letter init + self.conv_layers.append(nn.utils.weight_norm(layer)) + self.dropouts.append( + FairseqDropout(dropout, module_name=self.__class__.__name__) + ) + if out_channels % 2 != 0: + raise ValueError("odd # of out_channels is incompatible with GLU") + cur_channels = out_channels // 2 # halved by GLU + + for out_channels in [2 * cur_channels, vocab_size]: + layer = nn.Linear(cur_channels, out_channels) + layer.weight.data.mul_(math.sqrt(3)) + self.linear_layers.append(nn.utils.weight_norm(layer)) + cur_channels = out_channels // 2 + + def forward(self, src_tokens, src_lengths, **kwargs): + + """ + src_tokens: padded tensor (B, T, C * feat) + src_lengths: tensor of original lengths of input utterances (B,) + """ + B, T, _ = src_tokens.size() + x = src_tokens.transpose(1, 2).contiguous() # (B, feat, T) assuming C == 1 + + for layer_idx in range(len(self.conv_layers)): + x = self.conv_layers[layer_idx](x) + x = F.glu(x, dim=1) + x = self.dropouts[layer_idx](x) + + x = x.transpose(1, 2).contiguous() # (B, T, 908) + x = self.linear_layers[0](x) + x = F.glu(x, dim=2) + x = self.dropouts[-1](x) + x = self.linear_layers[1](x) + + assert x.size(0) == B + assert x.size(1) == T + + encoder_out = x.transpose(0, 1) # (T, B, vocab_size) + + # need to debug this -- find a simpler/elegant way in pytorch APIs + encoder_padding_mask = ( + torch.arange(T).view(1, T).expand(B, -1).to(x.device) + >= src_lengths.view(B, 1).expand(-1, T) + ).t() # (B x T) -> (T x B) + + return { + "encoder_out": encoder_out, # (T, B, vocab_size) + "encoder_padding_mask": encoder_padding_mask, # (T, B) + } + + def reorder_encoder_out(self, encoder_out, new_order): + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(1, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return (1e6, 1e6) # an arbitrary large number + + +@register_model_architecture("asr_w2l_conv_glu_encoder", "w2l_conv_glu_enc") +def w2l_conv_glu_enc(args): + args.input_feat_per_channel = getattr(args, "input_feat_per_channel", 80) + args.in_channels = getattr(args, "in_channels", 1) + args.conv_enc_config = getattr(args, "conv_enc_config", default_conv_enc_config) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/tasks/__init__.py b/fairseq-tools/fairseq/examples/speech_recognition/tasks/__init__.py new file mode 100644 index 00000000..ffa5f3bd --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/tasks/__init__.py @@ -0,0 +1,8 @@ +import importlib +import os + + +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + task_name = file[: file.find(".py")] + importlib.import_module("examples.speech_recognition.tasks." + task_name) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/tasks/speech_recognition.py b/fairseq-tools/fairseq/examples/speech_recognition/tasks/speech_recognition.py new file mode 100644 index 00000000..d9f011d5 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/tasks/speech_recognition.py @@ -0,0 +1,157 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import json +import os +import re +import sys + +import torch +from examples.speech_recognition.data import AsrDataset +from examples.speech_recognition.data.replabels import replabel_symbol +from fairseq.data import Dictionary +from fairseq.tasks import LegacyFairseqTask, register_task + + +def get_asr_dataset_from_json(data_json_path, tgt_dict): + """ + Parse data json and create dataset. + See scripts/asr_prep_json.py which pack json from raw files + + Json example: + { + "utts": { + "4771-29403-0025": { + "input": { + "length_ms": 170, + "path": "/tmp/file1.flac" + }, + "output": { + "text": "HELLO \n", + "token": "HE LLO", + "tokenid": "4815, 861" + } + }, + "1564-142299-0096": { + ... + } + } + """ + if not os.path.isfile(data_json_path): + raise FileNotFoundError("Dataset not found: {}".format(data_json_path)) + with open(data_json_path, "rb") as f: + data_samples = json.load(f)["utts"] + assert len(data_samples) != 0 + sorted_samples = sorted( + data_samples.items(), + key=lambda sample: int(sample[1]["input"]["length_ms"]), + reverse=True, + ) + aud_paths = [s[1]["input"]["path"] for s in sorted_samples] + ids = [s[0] for s in sorted_samples] + speakers = [] + for s in sorted_samples: + m = re.search("(.+?)-(.+?)-(.+?)", s[0]) + speakers.append(m.group(1) + "_" + m.group(2)) + frame_sizes = [s[1]["input"]["length_ms"] for s in sorted_samples] + tgt = [ + [int(i) for i in s[1]["output"]["tokenid"].split(", ")] + for s in sorted_samples + ] + # append eos + tgt = [[*t, tgt_dict.eos()] for t in tgt] + return AsrDataset(aud_paths, frame_sizes, tgt, tgt_dict, ids, speakers) + + +@register_task("speech_recognition") +class SpeechRecognitionTask(LegacyFairseqTask): + """ + Task for training speech recognition model. + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("data", help="path to data directory") + parser.add_argument( + "--silence-token", default="\u2581", help="token for silence (used by w2l)" + ) + parser.add_argument( + "--max-source-positions", + default=sys.maxsize, + type=int, + metavar="N", + help="max number of frames in the source sequence", + ) + parser.add_argument( + "--max-target-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the target sequence", + ) + + def __init__(self, args, tgt_dict): + super().__init__(args) + self.tgt_dict = tgt_dict + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task (e.g., load dictionaries).""" + dict_path = os.path.join(args.data, "dict.txt") + if not os.path.isfile(dict_path): + raise FileNotFoundError("Dict not found: {}".format(dict_path)) + tgt_dict = Dictionary.load(dict_path) + + if args.criterion == "ctc_loss": + tgt_dict.add_symbol("") + elif args.criterion == "asg_loss": + for i in range(1, args.max_replabel + 1): + tgt_dict.add_symbol(replabel_symbol(i)) + + print("| dictionary: {} types".format(len(tgt_dict))) + return cls(args, tgt_dict) + + def load_dataset(self, split, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + data_json_path = os.path.join(self.args.data, "{}.json".format(split)) + self.datasets[split] = get_asr_dataset_from_json(data_json_path, self.tgt_dict) + + def build_generator(self, models, args, **unused): + w2l_decoder = getattr(args, "w2l_decoder", None) + if w2l_decoder == "viterbi": + from examples.speech_recognition.w2l_decoder import W2lViterbiDecoder + + return W2lViterbiDecoder(args, self.target_dictionary) + elif w2l_decoder == "kenlm": + from examples.speech_recognition.w2l_decoder import W2lKenLMDecoder + + return W2lKenLMDecoder(args, self.target_dictionary) + elif w2l_decoder == "fairseqlm": + from examples.speech_recognition.w2l_decoder import W2lFairseqLMDecoder + + return W2lFairseqLMDecoder(args, self.target_dictionary) + else: + return super().build_generator(models, args) + + @property + def target_dictionary(self): + """Return the :class:`~fairseq.data.Dictionary` for the language + model.""" + return self.tgt_dict + + @property + def source_dictionary(self): + """Return the source :class:`~fairseq.data.Dictionary` (if applicable + for this task).""" + return None + + def max_positions(self): + """Return the max speech and sentence length allowed by the task.""" + return (self.args.max_source_positions, self.args.max_target_positions) diff --git a/fairseq-tools/fairseq/examples/speech_recognition/utils/wer_utils.py b/fairseq-tools/fairseq/examples/speech_recognition/utils/wer_utils.py new file mode 100644 index 00000000..cf6f3d09 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/utils/wer_utils.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import re +from collections import deque +from enum import Enum + +import numpy as np + + +""" + Utility modules for computation of Word Error Rate, + Alignments, as well as more granular metrics like + deletion, insersion and substitutions. +""" + + +class Code(Enum): + match = 1 + substitution = 2 + insertion = 3 + deletion = 4 + + +class Token(object): + def __init__(self, lbl="", st=np.nan, en=np.nan): + if np.isnan(st): + self.label, self.start, self.end = "", 0.0, 0.0 + else: + self.label, self.start, self.end = lbl, st, en + + +class AlignmentResult(object): + def __init__(self, refs, hyps, codes, score): + self.refs = refs # std::deque + self.hyps = hyps # std::deque + self.codes = codes # std::deque + self.score = score # float + + +def coordinate_to_offset(row, col, ncols): + return int(row * ncols + col) + + +def offset_to_row(offset, ncols): + return int(offset / ncols) + + +def offset_to_col(offset, ncols): + return int(offset % ncols) + + +def trimWhitespace(str): + return re.sub(" +", " ", re.sub(" *$", "", re.sub("^ *", "", str))) + + +def str2toks(str): + pieces = trimWhitespace(str).split(" ") + toks = [] + for p in pieces: + toks.append(Token(p, 0.0, 0.0)) + return toks + + +class EditDistance(object): + def __init__(self, time_mediated): + self.time_mediated_ = time_mediated + self.scores_ = np.nan # Eigen::Matrix + self.backtraces_ = ( + np.nan + ) # Eigen::Matrix backtraces_; + self.confusion_pairs_ = {} + + def cost(self, ref, hyp, code): + if self.time_mediated_: + if code == Code.match: + return abs(ref.start - hyp.start) + abs(ref.end - hyp.end) + elif code == Code.insertion: + return hyp.end - hyp.start + elif code == Code.deletion: + return ref.end - ref.start + else: # substitution + return abs(ref.start - hyp.start) + abs(ref.end - hyp.end) + 0.1 + else: + if code == Code.match: + return 0 + elif code == Code.insertion or code == Code.deletion: + return 3 + else: # substitution + return 4 + + def get_result(self, refs, hyps): + res = AlignmentResult(refs=deque(), hyps=deque(), codes=deque(), score=np.nan) + + num_rows, num_cols = self.scores_.shape + res.score = self.scores_[num_rows - 1, num_cols - 1] + + curr_offset = coordinate_to_offset(num_rows - 1, num_cols - 1, num_cols) + + while curr_offset != 0: + curr_row = offset_to_row(curr_offset, num_cols) + curr_col = offset_to_col(curr_offset, num_cols) + + prev_offset = self.backtraces_[curr_row, curr_col] + + prev_row = offset_to_row(prev_offset, num_cols) + prev_col = offset_to_col(prev_offset, num_cols) + + res.refs.appendleft(curr_row - 1) # Note: this was .push_front() in C++ + res.hyps.appendleft(curr_col - 1) + if curr_row - 1 == prev_row and curr_col == prev_col: + res.codes.appendleft(Code.deletion) + elif curr_row == prev_row and curr_col - 1 == prev_col: + res.codes.appendleft(Code.insertion) + else: + # assert(curr_row - 1 == prev_row and curr_col - 1 == prev_col) + ref_str = refs[res.refs[0]].label + hyp_str = hyps[res.hyps[0]].label + + if ref_str == hyp_str: + res.codes.appendleft(Code.match) + else: + res.codes.appendleft(Code.substitution) + + confusion_pair = "%s -> %s" % (ref_str, hyp_str) + if confusion_pair not in self.confusion_pairs_: + self.confusion_pairs_[confusion_pair] = 1 + else: + self.confusion_pairs_[confusion_pair] += 1 + + curr_offset = prev_offset + + return res + + def align(self, refs, hyps): + if len(refs) == 0 and len(hyps) == 0: + return np.nan + + # NOTE: we're not resetting the values in these matrices because every value + # will be overridden in the loop below. If this assumption doesn't hold, + # be sure to set all entries in self.scores_ and self.backtraces_ to 0. + self.scores_ = np.zeros((len(refs) + 1, len(hyps) + 1)) + self.backtraces_ = np.zeros((len(refs) + 1, len(hyps) + 1)) + + num_rows, num_cols = self.scores_.shape + + for i in range(num_rows): + for j in range(num_cols): + if i == 0 and j == 0: + self.scores_[i, j] = 0.0 + self.backtraces_[i, j] = 0 + continue + + if i == 0: + self.scores_[i, j] = self.scores_[i, j - 1] + self.cost( + None, hyps[j - 1], Code.insertion + ) + self.backtraces_[i, j] = coordinate_to_offset(i, j - 1, num_cols) + continue + + if j == 0: + self.scores_[i, j] = self.scores_[i - 1, j] + self.cost( + refs[i - 1], None, Code.deletion + ) + self.backtraces_[i, j] = coordinate_to_offset(i - 1, j, num_cols) + continue + + # Below here both i and j are greater than 0 + ref = refs[i - 1] + hyp = hyps[j - 1] + best_score = self.scores_[i - 1, j - 1] + ( + self.cost(ref, hyp, Code.match) + if (ref.label == hyp.label) + else self.cost(ref, hyp, Code.substitution) + ) + + prev_row = i - 1 + prev_col = j - 1 + ins = self.scores_[i, j - 1] + self.cost(None, hyp, Code.insertion) + if ins < best_score: + best_score = ins + prev_row = i + prev_col = j - 1 + + delt = self.scores_[i - 1, j] + self.cost(ref, None, Code.deletion) + if delt < best_score: + best_score = delt + prev_row = i - 1 + prev_col = j + + self.scores_[i, j] = best_score + self.backtraces_[i, j] = coordinate_to_offset( + prev_row, prev_col, num_cols + ) + + return self.get_result(refs, hyps) + + +class WERTransformer(object): + def __init__(self, hyp_str, ref_str, verbose=True): + self.ed_ = EditDistance(False) + self.id2oracle_errs_ = {} + self.utts_ = 0 + self.words_ = 0 + self.insertions_ = 0 + self.deletions_ = 0 + self.substitutions_ = 0 + + self.process(["dummy_str", hyp_str, ref_str]) + + if verbose: + print("'%s' vs '%s'" % (hyp_str, ref_str)) + self.report_result() + + def process(self, input): # std::vector&& input + if len(input) < 3: + print( + "Input must be of the form ... , got ", + len(input), + " inputs:", + ) + return None + + # Align + # std::vector hyps; + # std::vector refs; + + hyps = str2toks(input[-2]) + refs = str2toks(input[-1]) + + alignment = self.ed_.align(refs, hyps) + if alignment is None: + print("Alignment is null") + return np.nan + + # Tally errors + ins = 0 + dels = 0 + subs = 0 + for code in alignment.codes: + if code == Code.substitution: + subs += 1 + elif code == Code.insertion: + ins += 1 + elif code == Code.deletion: + dels += 1 + + # Output + row = input + row.append(str(len(refs))) + row.append(str(ins)) + row.append(str(dels)) + row.append(str(subs)) + # print(row) + + # Accumulate + kIdIndex = 0 + kNBestSep = "/" + + pieces = input[kIdIndex].split(kNBestSep) + + if len(pieces) == 0: + print( + "Error splitting ", + input[kIdIndex], + " on '", + kNBestSep, + "', got empty list", + ) + return np.nan + + id = pieces[0] + if id not in self.id2oracle_errs_: + self.utts_ += 1 + self.words_ += len(refs) + self.insertions_ += ins + self.deletions_ += dels + self.substitutions_ += subs + self.id2oracle_errs_[id] = [ins, dels, subs] + else: + curr_err = ins + dels + subs + prev_err = np.sum(self.id2oracle_errs_[id]) + if curr_err < prev_err: + self.id2oracle_errs_[id] = [ins, dels, subs] + + return 0 + + def report_result(self): + # print("---------- Summary ---------------") + if self.words_ == 0: + print("No words counted") + return + + # 1-best + best_wer = ( + 100.0 + * (self.insertions_ + self.deletions_ + self.substitutions_) + / self.words_ + ) + + print( + "\tWER = %0.2f%% (%i utts, %i words, %0.2f%% ins, " + "%0.2f%% dels, %0.2f%% subs)" + % ( + best_wer, + self.utts_, + self.words_, + 100.0 * self.insertions_ / self.words_, + 100.0 * self.deletions_ / self.words_, + 100.0 * self.substitutions_ / self.words_, + ) + ) + + def wer(self): + if self.words_ == 0: + wer = np.nan + else: + wer = ( + 100.0 + * (self.insertions_ + self.deletions_ + self.substitutions_) + / self.words_ + ) + return wer + + def stats(self): + if self.words_ == 0: + stats = {} + else: + wer = ( + 100.0 + * (self.insertions_ + self.deletions_ + self.substitutions_) + / self.words_ + ) + stats = dict( + { + "wer": wer, + "utts": self.utts_, + "numwords": self.words_, + "ins": self.insertions_, + "dels": self.deletions_, + "subs": self.substitutions_, + "confusion_pairs": self.ed_.confusion_pairs_, + } + ) + return stats + + +def calc_wer(hyp_str, ref_str): + t = WERTransformer(hyp_str, ref_str, verbose=0) + return t.wer() + + +def calc_wer_stats(hyp_str, ref_str): + t = WERTransformer(hyp_str, ref_str, verbose=0) + return t.stats() + + +def get_wer_alignment_codes(hyp_str, ref_str): + """ + INPUT: hypothesis string, reference string + OUTPUT: List of alignment codes (intermediate results from WER computation) + """ + t = WERTransformer(hyp_str, ref_str, verbose=0) + return t.ed_.align(str2toks(ref_str), str2toks(hyp_str)).codes + + +def merge_counts(x, y): + # Merge two hashes which have 'counts' as their values + # This can be used for example to merge confusion pair counts + # conf_pairs = merge_counts(conf_pairs, stats['confusion_pairs']) + for k, v in y.items(): + if k not in x: + x[k] = 0 + x[k] += v + return x diff --git a/fairseq-tools/fairseq/examples/speech_recognition/w2l_decoder.py b/fairseq-tools/fairseq/examples/speech_recognition/w2l_decoder.py new file mode 100644 index 00000000..2a1d8a77 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_recognition/w2l_decoder.py @@ -0,0 +1,435 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Wav2letter decoders. +""" + +import gc +import itertools as it +import os.path as osp +import warnings +from collections import deque, namedtuple + +import numpy as np +import torch +from examples.speech_recognition.data.replabels import unpack_replabels +from fairseq import tasks +from fairseq.utils import apply_to_sample + + +try: + from wav2letter.common import create_word_dict, load_words + from wav2letter.criterion import CpuViterbiPath, get_data_ptr_as_bytes + from wav2letter.decoder import ( + CriterionType, + DecoderOptions, + KenLM, + LM, + LMState, + SmearingMode, + Trie, + LexiconDecoder, + LexiconFreeDecoder, + ) +except: + warnings.warn( + "wav2letter python bindings are required to use this functionality. Please install from https://github.com/facebookresearch/wav2letter/wiki/Python-bindings" + ) + LM = object + LMState = object + + +class W2lDecoder(object): + def __init__(self, args, tgt_dict): + self.tgt_dict = tgt_dict + self.vocab_size = len(tgt_dict) + self.nbest = args.nbest + + # criterion-specific init + if args.criterion == "ctc": + self.criterion_type = CriterionType.CTC + self.blank = ( + tgt_dict.index("") + if "" in tgt_dict.indices + else tgt_dict.bos() + ) + self.asg_transitions = None + elif args.criterion == "asg_loss": + self.criterion_type = CriterionType.ASG + self.blank = -1 + self.asg_transitions = args.asg_transitions + self.max_replabel = args.max_replabel + assert len(self.asg_transitions) == self.vocab_size ** 2 + else: + raise RuntimeError(f"unknown criterion: {args.criterion}") + + def generate(self, models, sample, **unused): + """Generate a batch of inferences.""" + # model.forward normally channels prev_output_tokens into the decoder + # separately, but SequenceGenerator directly calls model.encoder + encoder_input = { + k: v for k, v in sample["net_input"].items() if k != "prev_output_tokens" + } + emissions = self.get_emissions(models, encoder_input) + return self.decode(emissions) + + def get_emissions(self, models, encoder_input): + """Run encoder and normalize emissions""" + # encoder_out = models[0].encoder(**encoder_input) + encoder_out = models[0](**encoder_input) + if self.criterion_type == CriterionType.CTC: + emissions = models[0].get_normalized_probs(encoder_out, log_probs=True) + elif self.criterion_type == CriterionType.ASG: + emissions = encoder_out["encoder_out"] + return emissions.transpose(0, 1).float().cpu().contiguous() + + def get_tokens(self, idxs): + """Normalize tokens by handling CTC blank, ASG replabels, etc.""" + idxs = (g[0] for g in it.groupby(idxs)) + if self.criterion_type == CriterionType.CTC: + idxs = filter(lambda x: x != self.blank, idxs) + elif self.criterion_type == CriterionType.ASG: + idxs = filter(lambda x: x >= 0, idxs) + idxs = unpack_replabels(list(idxs), self.tgt_dict, self.max_replabel) + return torch.LongTensor(list(idxs)) + + +class W2lViterbiDecoder(W2lDecoder): + def __init__(self, args, tgt_dict): + super().__init__(args, tgt_dict) + + def decode(self, emissions): + B, T, N = emissions.size() + hypos = [] + if self.asg_transitions is None: + transitions = torch.FloatTensor(N, N).zero_() + else: + transitions = torch.FloatTensor(self.asg_transitions).view(N, N) + viterbi_path = torch.IntTensor(B, T) + workspace = torch.ByteTensor(CpuViterbiPath.get_workspace_size(B, T, N)) + CpuViterbiPath.compute( + B, + T, + N, + get_data_ptr_as_bytes(emissions), + get_data_ptr_as_bytes(transitions), + get_data_ptr_as_bytes(viterbi_path), + get_data_ptr_as_bytes(workspace), + ) + return [ + [{"tokens": self.get_tokens(viterbi_path[b].tolist()), "score": 0}] + for b in range(B) + ] + + +class W2lKenLMDecoder(W2lDecoder): + def __init__(self, args, tgt_dict): + super().__init__(args, tgt_dict) + + self.silence = ( + tgt_dict.index("") + if "" in tgt_dict.indices + else tgt_dict.bos() + ) + self.lexicon = load_words(args.lexicon) + self.word_dict = create_word_dict(self.lexicon) + self.unk_word = self.word_dict.get_index("") + + self.lm = KenLM(args.kenlm_model, self.word_dict) + self.trie = Trie(self.vocab_size, self.silence) + + start_state = self.lm.start(False) + for i, (word, spellings) in enumerate(self.lexicon.items()): + word_idx = self.word_dict.get_index(word) + _, score = self.lm.score(start_state, word_idx) + for spelling in spellings: + spelling_idxs = [tgt_dict.index(token) for token in spelling] + assert ( + tgt_dict.unk() not in spelling_idxs + ), f"{spelling} {spelling_idxs}" + self.trie.insert(spelling_idxs, word_idx, score) + self.trie.smear(SmearingMode.MAX) + + self.decoder_opts = DecoderOptions( + args.beam, + int(getattr(args, "beam_size_token", len(tgt_dict))), + args.beam_threshold, + args.lm_weight, + args.word_score, + args.unk_weight, + args.sil_weight, + 0, + False, + self.criterion_type, + ) + + if self.asg_transitions is None: + N = 768 + # self.asg_transitions = torch.FloatTensor(N, N).zero_() + self.asg_transitions = [] + + self.decoder = LexiconDecoder( + self.decoder_opts, + self.trie, + self.lm, + self.silence, + self.blank, + self.unk_word, + self.asg_transitions, + False, + ) + + def decode(self, emissions): + B, T, N = emissions.size() + hypos = [] + for b in range(B): + emissions_ptr = emissions.data_ptr() + 4 * b * emissions.stride(0) + results = self.decoder.decode(emissions_ptr, T, N) + + nbest_results = results[: self.nbest] + hypos.append( + [ + { + "tokens": self.get_tokens(result.tokens), + "score": result.score, + "words": [ + self.word_dict.get_entry(x) for x in result.words if x >= 0 + ], + } + for result in nbest_results + ] + ) + return hypos + + +FairseqLMState = namedtuple("FairseqLMState", ["prefix", "incremental_state", "probs"]) + + +class FairseqLM(LM): + def __init__(self, dictionary, model): + LM.__init__(self) + self.dictionary = dictionary + self.model = model + self.unk = self.dictionary.unk() + + self.save_incremental = False # this currently does not work properly + self.max_cache = 20_000 + + model.cuda() + model.eval() + model.make_generation_fast_() + + self.states = {} + self.stateq = deque() + + def start(self, start_with_nothing): + state = LMState() + prefix = torch.LongTensor([[self.dictionary.eos()]]) + incremental_state = {} if self.save_incremental else None + with torch.no_grad(): + res = self.model(prefix.cuda(), incremental_state=incremental_state) + probs = self.model.get_normalized_probs(res, log_probs=True, sample=None) + + if incremental_state is not None: + incremental_state = apply_to_sample(lambda x: x.cpu(), incremental_state) + self.states[state] = FairseqLMState( + prefix.numpy(), incremental_state, probs[0, -1].cpu().numpy() + ) + self.stateq.append(state) + + return state + + def score(self, state: LMState, token_index: int, no_cache: bool = False): + """ + Evaluate language model based on the current lm state and new word + Parameters: + ----------- + state: current lm state + token_index: index of the word + (can be lexicon index then you should store inside LM the + mapping between indices of lexicon and lm, or lm index of a word) + + Returns: + -------- + (LMState, float): pair of (new state, score for the current word) + """ + curr_state = self.states[state] + + def trim_cache(targ_size): + while len(self.stateq) > targ_size: + rem_k = self.stateq.popleft() + rem_st = self.states[rem_k] + rem_st = FairseqLMState(rem_st.prefix, None, None) + self.states[rem_k] = rem_st + + if curr_state.probs is None: + new_incremental_state = ( + curr_state.incremental_state.copy() + if curr_state.incremental_state is not None + else None + ) + with torch.no_grad(): + if new_incremental_state is not None: + new_incremental_state = apply_to_sample( + lambda x: x.cuda(), new_incremental_state + ) + elif self.save_incremental: + new_incremental_state = {} + + res = self.model( + torch.from_numpy(curr_state.prefix).cuda(), + incremental_state=new_incremental_state, + ) + probs = self.model.get_normalized_probs( + res, log_probs=True, sample=None + ) + + if new_incremental_state is not None: + new_incremental_state = apply_to_sample( + lambda x: x.cpu(), new_incremental_state + ) + + curr_state = FairseqLMState( + curr_state.prefix, new_incremental_state, probs[0, -1].cpu().numpy() + ) + + if not no_cache: + self.states[state] = curr_state + self.stateq.append(state) + + score = curr_state.probs[token_index].item() + + trim_cache(self.max_cache) + + outstate = state.child(token_index) + if outstate not in self.states and not no_cache: + prefix = np.concatenate( + [curr_state.prefix, torch.LongTensor([[token_index]])], -1 + ) + incr_state = curr_state.incremental_state + + self.states[outstate] = FairseqLMState(prefix, incr_state, None) + + if token_index == self.unk: + score = float("-inf") + + return outstate, score + + def finish(self, state: LMState): + """ + Evaluate eos for language model based on the current lm state + + Returns: + -------- + (LMState, float): pair of (new state, score for the current word) + """ + return self.score(state, self.dictionary.eos()) + + def empty_cache(self): + self.states = {} + self.stateq = deque() + gc.collect() + + +class W2lFairseqLMDecoder(W2lDecoder): + def __init__(self, args, tgt_dict): + super().__init__(args, tgt_dict) + + self.silence = tgt_dict.bos() + + self.unit_lm = getattr(args, "unit_lm", False) + + self.lexicon = load_words(args.lexicon) if args.lexicon else None + self.idx_to_wrd = {} + + checkpoint = torch.load(args.kenlm_model, map_location="cpu") + lm_args = checkpoint["args"] + lm_args.data = osp.dirname(args.kenlm_model) + print(lm_args) + task = tasks.setup_task(lm_args) + model = task.build_model(lm_args) + model.load_state_dict(checkpoint["model"], strict=False) + + self.trie = Trie(self.vocab_size, self.silence) + + self.word_dict = task.dictionary + self.unk_word = self.word_dict.unk() + self.lm = FairseqLM(self.word_dict, model) + + self.decoder_opts = DecoderOptions( + args.beam, + int(getattr(args, "beam_size_token", len(tgt_dict))), + args.beam_threshold, + args.lm_weight, + args.word_score, + args.unk_weight, + args.sil_weight, + 0, + False, + self.criterion_type, + ) + + if self.lexicon: + start_state = self.lm.start(False) + for i, (word, spellings) in enumerate(self.lexicon.items()): + if self.unit_lm: + word_idx = i + self.idx_to_wrd[i] = word + score = 0 + else: + word_idx = self.word_dict.index(word) + _, score = self.lm.score(start_state, word_idx, no_cache=True) + + for spelling in spellings: + spelling_idxs = [tgt_dict.index(token) for token in spelling] + assert ( + tgt_dict.unk() not in spelling_idxs + ), f"{spelling} {spelling_idxs}" + self.trie.insert(spelling_idxs, word_idx, score) + self.trie.smear(SmearingMode.MAX) + + self.decoder = LexiconDecoder( + self.decoder_opts, + self.trie, + self.lm, + self.silence, + self.blank, + self.unk_word, + [], + self.unit_lm, + ) + else: + self.decoder = LexiconFreeDecoder( + self.decoder_opts, self.lm, self.silence, self.blank, [] + ) + + def decode(self, emissions): + B, T, N = emissions.size() + hypos = [] + + def idx_to_word(idx): + if self.unit_lm: + return self.idx_to_wrd[idx] + else: + return self.word_dict[idx] + + def make_hypo(result): + hypo = {"tokens": self.get_tokens(result.tokens), "score": result.score} + if self.lexicon: + hypo["words"] = [idx_to_word(x) for x in result.words if x >= 0] + return hypo + + for b in range(B): + emissions_ptr = emissions.data_ptr() + 4 * b * emissions.stride(0) + results = self.decoder.decode(emissions_ptr, T, N) + + nbest_results = results[: self.nbest] + hypos.append([make_hypo(result) for result in nbest_results]) + self.lm.empty_cache() + + return hypos diff --git a/fairseq-tools/fairseq/examples/speech_to_text/README.md b/fairseq-tools/fairseq/examples/speech_to_text/README.md new file mode 100644 index 00000000..62fd2700 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_to_text/README.md @@ -0,0 +1,216 @@ +# Speech-to-Text (S2T) Modeling + +## Data Preparation +S2T modeling data consists of source speech features, target text and other optional information +(source text, speaker id, etc.). Fairseq S2T uses per-dataset-split TSV manifest files +to store these information. Each data field is represented by a column in the TSV file. + +Unlike text token embeddings, speech features (e.g. log mel-filter banks) are usually fixed +during model training and can be pre-computed. The manifest file contains the path to +either the feature file in NumPy format or the WAV/FLAC audio file. For the latter, +features will be extracted on-the-fly by fairseq S2T. Optionally, feature/audio files can be packed +into uncompressed ZIP files (then accessed via byte offset and length) to improve I/O performance. + +Fairseq S2T also employs a YAML file for data related configurations: tokenizer type and dictionary path +for the target text, feature transforms such as CMVN (cepstral mean and variance normalization) and SpecAugment, +temperature-based resampling, etc. + +## Model Training & Evaluation +Fairseq S2T uses the unified `fairseq-train`/`fairseq-generate` interface for model training and evaluation. +It requires arguments `--task speech_to_text` and `--arch `. + + +## Example 1: Speech Recognition (ASR) on LibriSpeech + +#### Data preparation +Download and preprocess LibriSpeech data with +```bash +python examples/speech_to_text/prep_librispeech_data.py \ + --output-root ${LS_ROOT} --vocab-type unigram --vocab-size 10000 +``` +where `LS_ROOT` is the root path for downloaded data as well as generated manifest and feature files. + +#### Training +```bash +fairseq-train ${LS_ROOT} --train-subset train --valid-subset dev --save-dir ${SAVE_DIR} --num-workers 4 \ + --max-tokens 40000 --task speech_to_text --criterion label_smoothed_cross_entropy --max-update 300000 \ + --arch s2t_transformer_s --optimizer adam --lr 2e-3 --lr-scheduler inverse_sqrt --warmup-updates 10000 \ + --clip-norm 10.0 --seed 1 --update-freq 8 +``` +where `SAVE_DIR` is the checkpoint root path. Here we use `--arch s2t_transformer_s` (31M parameters) as example. +You may switch to `s2t_transformer_m` (71M) or `s2t_transformer_l` (268M) for better performance. We set +`--update-freq 8` to simulate 8 GPUs with 1 GPU. You may want to update it accordingly when using more than 1 GPU. + +#### Inference & Evaluation +Average the last 10 checkpoints and evaluate on the 4 splits +(`dev-clean`, `dev-other`, `test-clean` and `test-other`): +```bash +CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt +python scripts/average_checkpoints.py \ + --inputs ${SAVE_DIR} --num-epoch-checkpoints 10 --output "${SAVE_DIR}/${CHECKPOINT_FILENAME}" +for SUBSET in dev-clean dev-other test-clean test-other; do + fairseq-generate ${LS_ROOT} --gen-subset ${SUBSET} --task speech_to_text \ + --path ${SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 --scoring wer +done +``` + +#### Result + +| --arch | Params | dev-clean | dev-other | test-clean | test-other | +|---|---|---|---|---|---| +| s2t_transformer_s | 30M | 4.1 | 9.3 | 4.4 | 9.2 | +| s2t_transformer_sp | 35M | 3.9 | 9.3 | 4.3 | 8.8 | +| s2t_transformer_m | 71M | 3.5 | 8.1 | 3.7 | 8.1 | +| s2t_transformer_mp | 84M | 3.3 | 7.8 | 3.7 | 8.2 | +| s2t_transformer_l | 268M | 3.3 | 7.7 | 3.5 | 7.8 | +| s2t_transformer_lp | 318M | 3.1 | 7.5 | 3.4 | 7.6 | + + +## Example 2: Speech Translation (ST) on MuST-C + +#### Data Preparation +[Download](https://ict.fbk.eu/must-c) and unpack MuST-C data to a path `MUSTC_ROOT`, then preprocess it with +```bash +python examples/speech_to_text/prep_mustc_data.py --data-root ${MUSTC_ROOT} \ + --asr-vocab-type unigram --asr-vocab-size 5000 \ + --st-vocab-type unigram --st-vocab-size 8000 +``` +The generated manifest and feature files will be available under `MUSTC_ROOT`. + +#### ASR +###### Training +```bash +fairseq-train ${MUSTC_ROOT} --train-subset train_asr --valid-subset dev_asr --save-dir ${ASR_SAVE_DIR} \ + --num-workers 4 --max-tokens 40000 --task speech_to_text --criterion label_smoothed_cross_entropy \ + --report-accuracy --max-update 100000 --arch s2t_transformer_s --optimizer adam --lr 1e-3 \ + --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 +``` +where `ASR_SAVE_DIR` is the checkpoint root path. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. +You may want to update it accordingly when using more than 1 GPU. + +###### Inference & Evaluation +```bash +CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt +python scripts/average_checkpoints.py \ + --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 --output "${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}" +fairseq-generate ${MUSTC_ROOT} --gen-subset tst-COMMON_asr --task speech_to_text \ + --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \ + --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct +``` +###### Result +| --arch | Params | En-De | En-Nl | En-Es | En-Fr | En-It | En-Pt | En-Ro | En-Ru | +|---|---|---|---|---|---|---|---|---|---| +| s2t_transformer_s | 31M | 18.2 | 17.6 | 17.7 | 17.2 | 17.9 | 19.1 | 18.1 | 17.7 | + +#### ST +###### Training +```bash +fairseq-train ${MUSTC_ROOT} --train-subset train_st --valid-subset dev_st --save-dir ${ST_SAVE_DIR} \ + --num-workers 4 --max-tokens 40000 --task speech_to_text --criterion label_smoothed_cross_entropy \ + --report-accuracy --max-update 100000 --arch s2t_transformer_s --optimizer adam --lr 2e-3 \ + --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \ + --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} +``` +where `ST_SAVE_DIR` is the checkpoint root path. The ST encoder is pre-trained by ASR for faster training and better +performance: `--load-pretrained-encoder-from `. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. +You may want to update it accordingly when using more than 1 GPU. + +###### Inference & Evaluation +Average the last 10 checkpoints and evaluate on the `tst-COMMON` split: +```bash +CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt +python scripts/average_checkpoints.py \ + --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 --output "${ST_SAVE_DIR}/${CHECKPOINT_FILENAME}" +fairseq-generate ${MUSTC_ROOT} --gen-subset tst-COMMON_st --task speech_to_text \ + --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 --scoring sacrebleu +``` + +###### Result +| --arch | Params | En-De | En-Nl | En-Es | En-Fr | En-It | En-Pt | En-Ro | En-Ru | +|---|---|---|---|---|---|---|---|---|---| +| s2t_transformer_s | 31M | 22.7 | 27.3 | 27.2 | 32.9 | 22.7 | 28.1 | 21.9 | 15.3 | + + +## Example 3: ST on CoVoST +#### Data Preparation +Download and preprocess CoVoST data with +```bash +# En ASR +python examples/speech_to_text/prep_covost_data.py --data-root ${COVOST_ROOT} \ + --vocab-type char --src-lang en +# ST +python examples/speech_to_text/prep_covost_data.py --data-root ${COVOST_ROOT} \ + --vocab-type char --src-lang fr --tgt-lang en +``` +where `COVOST_ROOT` is the root path for downloaded data as well as generated manifest and feature files. + +#### ASR +###### Training +```bash +fairseq-train ${COVOST_ROOT} --train-subset train_asr --valid-subset dev_asr --save-dir ${ASR_SAVE_DIR} \ + --num-workers 4 --max-tokens 40000 --task speech_to_text --criterion label_smoothed_cross_entropy \ + --report-accuracy --max-update 100000 --arch s2t_transformer_s --optimizer adam --lr 1e-3 \ + --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 +``` +where `ASR_SAVE_DIR` is the checkpoint root path. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. +You may want to update it accordingly when using more than 1 GPU. + +###### Inference & Evaluation +```bash +CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt +python scripts/average_checkpoints.py \ + --inputs ${ASR_SAVE_DIR} --num-epoch-checkpoints 10 --output "${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME}" +fairseq-generate ${COVOST_ROOT} --gen-subset test_asr_en --task speech_to_text \ + --path ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 \ + --scoring wer --wer-tokenizer 13a --wer-lowercase --wer-remove-punct +``` +###### Result +| --arch | Params | En | +|---|---|---| +| s2t_transformer_s | 31M | 25.6 | + +#### ST +###### Training +```bash +fairseq-train ${COVOST_ROOT} --train-subset train_st_fr_en --valid-subset dev_st_fr_en --save-dir ${ST_SAVE_DIR} \ + --num-workers 4 --max-tokens 40000 --task speech_to_text --criterion label_smoothed_cross_entropy \ + --report-accuracy --max-update 100000 --arch s2t_transformer_s --optimizer adam --lr 2e-3 \ + --lr-scheduler inverse_sqrt --warmup-updates 10000 --clip-norm 10.0 --seed 1 --update-freq 8 \ + --load-pretrained-encoder-from ${ASR_SAVE_DIR}/${CHECKPOINT_FILENAME} +``` +where `ST_SAVE_DIR` is the checkpoint root path. The ST encoder is pre-trained by En ASR for faster training and better +performance: `--load-pretrained-encoder-from `. We set `--update-freq 8` to simulate 8 GPUs with 1 GPU. +You may want to update it accordingly when using more than 1 GPU. + +###### Inference & Evaluation +Average the last 10 checkpoints and evaluate on test split: +```bash +CHECKPOINT_FILENAME=avg_last_10_checkpoint.pt +python scripts/average_checkpoints.py \ + --inputs ${ST_SAVE_DIR} --num-epoch-checkpoints 10 --output "${ST_SAVE_DIR}/${CHECKPOINT_FILENAME}" +fairseq-generate ${COVOST_ROOT} --gen-subset test_st_fr_en --task speech_to_text \ + --path ${ST_SAVE_DIR}/${CHECKPOINT_FILENAME} --max-tokens 50000 --beam 5 --scoring sacrebleu +``` + +###### Result +| --arch | Params | Fr-En | De-En | Es-En | Ca-En | En-De | En-Ca | En-Fa | En-Et | +|---|---|---|---|---|---|---|---|---|---| +| s2t_transformer_s | 31M | 26.3 | 17.1 | 23.0 | 18.8 | 16.3 | 21.8 | 13.1 | 13.2 | + +## Citation +Please cite as: +``` +@inproceedings{wang2020fairseqs2t, + title = {fairseq S2T: Fast Speech-to-Text Modeling with fairseq}, + author = {Changhan Wang and Yun Tang and Xutai Ma and Anne Wu and Dmytro Okhonko and Juan Pino}, + booktitle = {Proceedings of the 2020 Conference of the Asian Chapter of the Association for Computational Linguistics (AACL): System Demonstrations}, + year = {2020}, +} + +@inproceedings{ott2019fairseq, + title = {fairseq: A Fast, Extensible Toolkit for Sequence Modeling}, + author = {Myle Ott and Sergey Edunov and Alexei Baevski and Angela Fan and Sam Gross and Nathan Ng and David Grangier and Michael Auli}, + booktitle = {Proceedings of NAACL-HLT 2019: Demonstrations}, + year = {2019}, +} +``` diff --git a/fairseq-tools/fairseq/examples/speech_to_text/data_utils.py b/fairseq-tools/fairseq/examples/speech_to_text/data_utils.py new file mode 100644 index 00000000..1efeff4d --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_to_text/data_utils.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import csv +import os +import os.path as op +import zipfile +from functools import reduce +from glob import glob +from multiprocessing import cpu_count +from typing import Any, Dict, List + +import numpy as np +import sentencepiece as sp +from fairseq.data.audio.audio_utils import _get_kaldi_fbank, _get_torchaudio_fbank +from fairseq.data.audio.feature_transforms.utterance_cmvn import UtteranceCMVN +from tqdm import tqdm + + +UNK_TOKEN, UNK_TOKEN_ID = "", 3 +BOS_TOKEN, BOS_TOKEN_ID = "", 0 +EOS_TOKEN, EOS_TOKEN_ID = "", 2 +PAD_TOKEN, PAD_TOKEN_ID = "", 1 + + +def gen_vocab( + input_path: str, + output_path_prefix: str, + model_type="bpe", + vocab_size=1000, +): + # Train SentencePiece Model + arguments = [ + f"--input={input_path}", + f"--model_prefix={output_path_prefix}", + f"--model_type={model_type}", + f"--vocab_size={vocab_size}", + "--character_coverage=1.0", + f"--num_threads={cpu_count()}", + f"--unk_id={UNK_TOKEN_ID}", + f"--bos_id={BOS_TOKEN_ID}", + f"--eos_id={EOS_TOKEN_ID}", + f"--pad_id={PAD_TOKEN_ID}", + ] + sp.SentencePieceTrainer.Train(" ".join(arguments)) + # Export fairseq dictionary + spm = sp.SentencePieceProcessor() + spm.Load(output_path_prefix + ".model") + vocab = {i: spm.IdToPiece(i) for i in range(spm.GetPieceSize())} + assert ( + vocab.get(UNK_TOKEN_ID) == UNK_TOKEN + and vocab.get(PAD_TOKEN_ID) == PAD_TOKEN + and vocab.get(BOS_TOKEN_ID) == BOS_TOKEN + and vocab.get(EOS_TOKEN_ID) == EOS_TOKEN + ) + vocab = { + i: s + for i, s in vocab.items() + if s not in {UNK_TOKEN, BOS_TOKEN, EOS_TOKEN, PAD_TOKEN} + } + with open(output_path_prefix + ".txt", "w") as f_out: + for _, s in sorted(vocab.items(), key=lambda x: x[0]): + f_out.write(f"{s} 1\n") + + +def extract_fbank_features( + waveform, + sample_rate, + output_path=None, + n_mel_bins=80, + apply_utterance_cmvn=True, + overwrite=False, +): + if output_path is not None and op.exists(output_path) and not overwrite: + return + + _waveform = waveform * (2 ** 15) # Kaldi compliance: 16-bit signed integers + _waveform = _waveform.squeeze().numpy() + + features = _get_kaldi_fbank(_waveform, sample_rate, n_mel_bins) + if features is None: + features = _get_torchaudio_fbank(_waveform, sample_rate, n_mel_bins) + if features is None: + raise ImportError( + "Please install pyKaldi or torchaudio to enable " + "online filterbank feature extraction" + ) + + if apply_utterance_cmvn: + cmvn = UtteranceCMVN(norm_means=True, norm_vars=True) + features = cmvn(features) + if output_path is not None: + np.save(output_path, features) + else: + return features + + +def create_zip(data_root, zip_path): + cwd = os.path.abspath(os.curdir) + os.chdir(data_root) + with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_STORED) as f: + for filename in tqdm(glob("*.npy")): + f.write(filename) + os.chdir(cwd) + + +def is_npy_data(data: bytes) -> bool: + return data[0] == 147 and data[1] == 78 + + +def get_zip_manifest(zip_root, zip_filename): + zip_path = op.join(zip_root, zip_filename) + with zipfile.ZipFile(zip_path, mode="r") as f: + info = f.infolist() + manifest = {} + for i in tqdm(info): + utt_id = op.splitext(i.filename)[0] + offset, file_size = i.header_offset + 30 + len(i.filename), i.file_size + manifest[utt_id] = f"{zip_filename}:{offset}:{file_size}" + with open(zip_path, "rb") as f: + f.seek(offset) + data = f.read(file_size) + assert len(data) > 1 and is_npy_data(data) + return manifest + + +def gen_config_yaml( + data_root, spm_filename, yaml_filename="config.yaml", specaugment_policy="lb" +): + assert specaugment_policy in {"lb", "ld"} + data_root = op.abspath(data_root) + writer = S2TDataConfigWriter(op.join(data_root, yaml_filename)) + writer.set_audio_root(op.abspath(data_root)) + writer.set_vocab_filename(spm_filename.replace(".model", ".txt")) + writer.set_input_channels(1) + writer.set_input_feat_per_channel(80) + if specaugment_policy == "lb": + writer.set_specaugment_lb_policy() + else: + writer.set_specaugment_ld_policy() + writer.set_bpe_tokenizer( + { + "bpe": "sentencepiece", + "sentencepiece_model": op.join(data_root, spm_filename), + } + ) + writer.set_feature_transforms("_train", ["specaugment"]) + writer.flush() + + +def save_df_to_tsv(dataframe, path): + dataframe.to_csv( + path, + sep="\t", + header=True, + index=False, + encoding="utf-8", + escapechar="\\", + quoting=csv.QUOTE_NONE, + ) + + +def filter_manifest_df( + df, is_train_split=False, extra_filters=None, min_n_frames=5, max_n_frames=3000 +): + filters = { + "no speech": df["audio"] == "", + f"short speech (<{min_n_frames} frames)": df["n_frames"] < min_n_frames, + "empty sentence": df["tgt_text"] == "", + } + if is_train_split: + filters[f"long speech (>{max_n_frames} frames)"] = df["n_frames"] > max_n_frames + if extra_filters is not None: + filters.update(extra_filters) + invalid = reduce(lambda x, y: x | y, filters.values()) + valid = ~invalid + print( + "| " + + ", ".join(f"{n}: {f.sum()}" for n, f in filters.items()) + + f", total {invalid.sum()} filtered, {valid.sum()} remained." + ) + return df[valid] + + +class S2TDataConfigWriter(object): + DEFAULT_VOCAB_FILENAME = "dict.txt" + DEFAULT_INPUT_FEAT_PER_CHANNEL = 80 + DEFAULT_INPUT_CHANNELS = 1 + + def __init__(self, yaml_path): + try: + import yaml + except ImportError: + print("Please install PyYAML to load YAML files for S2T data config") + self.yaml = yaml + self.yaml_path = yaml_path + self.config = {} + + def flush(self): + with open(self.yaml_path, "w") as f: + self.yaml.dump(self.config, f) + + def set_audio_root(self, audio_root=""): + self.config["audio_root"] = audio_root + + def set_vocab_filename(self, vocab_filename="dict.txt"): + self.config["vocab_filename"] = vocab_filename + + def set_specaugment( + self, + time_wrap_w: int, + freq_mask_n: int, + freq_mask_f: int, + time_mask_n: int, + time_mask_t: int, + time_mask_p: float, + ): + self.config["specaugment"] = { + "time_wrap_W": time_wrap_w, + "freq_mask_N": freq_mask_n, + "freq_mask_F": freq_mask_f, + "time_mask_N": time_mask_n, + "time_mask_T": time_mask_t, + "time_mask_p": time_mask_p, + } + + def set_specaugment_lb_policy(self): + self.set_specaugment( + time_wrap_w=0, + freq_mask_n=1, + freq_mask_f=27, + time_mask_n=1, + time_mask_t=100, + time_mask_p=1.0, + ) + + def set_specaugment_ld_policy(self): + self.set_specaugment( + time_wrap_w=0, + freq_mask_n=2, + freq_mask_f=27, + time_mask_n=2, + time_mask_t=100, + time_mask_p=1.0, + ) + + def set_input_channels(self, input_channels=1): + self.config["input_channels"] = input_channels + + def set_input_feat_per_channel(self, input_feat_per_channel=80): + self.config["input_feat_per_channel"] = input_feat_per_channel + + def set_bpe_tokenizer(self, bpe_tokenizer: Dict[str, Any]): + self.config["bpe_tokenizer"] = bpe_tokenizer + + def set_feature_transforms(self, split, transforms: List[str]): + if "transforms" not in self.config: + self.config["transforms"] = {} + self.config["transforms"][split] = transforms diff --git a/fairseq-tools/fairseq/examples/speech_to_text/prep_covost_data.py b/fairseq-tools/fairseq/examples/speech_to_text/prep_covost_data.py new file mode 100644 index 00000000..e8a028b4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_to_text/prep_covost_data.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import csv +import logging +import os +import os.path as op +import shutil +from tempfile import NamedTemporaryFile +from typing import Optional, Tuple + +import pandas as pd +import torchaudio +from examples.speech_to_text.data_utils import ( + create_zip, + extract_fbank_features, + filter_manifest_df, + gen_config_yaml, + gen_vocab, + get_zip_manifest, + save_df_to_tsv, +) +from torch import Tensor +from torch.utils.data import Dataset +from torchaudio.datasets.utils import download_url, extract_archive +from tqdm import tqdm + + +log = logging.getLogger(__name__) + + +MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"] + + +class CoVoST(Dataset): + """Create a Dataset for CoVoST (https://github.com/facebookresearch/covost). + + Args: + root (str): root path to the dataset and generated manifests/features + source_language (str): source (audio) language + target_language (str, optional): target (text) language, + None for no translation (default: None) + version (int, optional): CoVoST version. (default: 2) + download (bool, optional): Whether to download the dataset if it is not + found at root path. (default: ``False``). + """ + + CV_URL_TEMPLATE = ( + "https://voice-prod-bundler-ee1969a6ce8178826482b88" + "e843c335139bd3fb4.s3.amazonaws.com/{ver}/{lang}.tar.gz" + ) + COVOST_URL_TEMPLATE = ( + "https://dl.fbaipublicfiles.com/covost/" + "covost_v2.{src_lang}_{tgt_lang}.tsv.tar.gz" + ) + + VERSIONS = {2} + SPLITS = ["train", "dev", "test"] + + CV_VERSION_ID = {1: "cv-corpus-3", 2: "cv-corpus-4-2019-12-10"} + + XX_EN_LANGUAGES = { + 1: ["fr", "de", "nl", "ru", "es", "it", "tr", "fa", "sv-SE", "mn", "zh-CN"], + 2: [ + "fr", + "de", + "es", + "ca", + "it", + "ru", + "zh-CN", + "pt", + "fa", + "et", + "mn", + "nl", + "tr", + "ar", + "sv-SE", + "lv", + "sl", + "ta", + "ja", + "id", + "cy", + ], + } + EN_XX_LANGUAGES = { + 1: [], + 2: [ + "de", + "tr", + "fa", + "sv-SE", + "mn", + "zh-CN", + "cy", + "ca", + "sl", + "et", + "id", + "ar", + "ta", + "lv", + "ja", + ], + } + + def __init__( + self, + root: str, + split: str, + source_language: str, + target_language: Optional[str] = None, + version: int = 2, + download: bool = False, + ) -> None: + assert version in self.VERSIONS and split in self.SPLITS + assert source_language is not None + self.no_translation = target_language is None + if not self.no_translation: + assert "en" in {source_language, target_language} + if source_language == "en": + assert target_language in self.EN_XX_LANGUAGES[version] + else: + assert source_language in self.XX_EN_LANGUAGES[version] + else: + # Hack here so that we can get "split" column from CoVoST TSV. + # Note that we use CoVoST train split for ASR which is an extension + # to Common Voice train split. + target_language = "de" if source_language == "en" else "en" + + self.root = os.path.join(root, "raw") + os.makedirs(self.root, exist_ok=True) + + cv_url = self.CV_URL_TEMPLATE.format( + ver=self.CV_VERSION_ID[version], lang=source_language + ) + cv_archive = os.path.join(self.root, os.path.basename(cv_url)) + if download: + if not os.path.isfile(cv_archive): + download_url(cv_url, self.root, hash_value=None) + extract_archive(cv_archive) + + covost_url = self.COVOST_URL_TEMPLATE.format( + src_lang=source_language, tgt_lang=target_language + ) + covost_archive = os.path.join(self.root, os.path.basename(covost_url)) + if download: + if not os.path.isfile(covost_archive): + download_url(covost_url, self.root, hash_value=None) + extract_archive(covost_archive) + + cv_tsv = self.load_from_tsv(os.path.join(self.root, "validated.tsv")) + covost_tsv = self.load_from_tsv( + os.path.join(self.root, os.path.basename(covost_url).replace(".tar.gz", "")) + ) + df = pd.merge( + left=cv_tsv[["path", "sentence", "client_id"]], + right=covost_tsv[["path", "translation", "split"]], + how="inner", + on="path", + ) + if split == "train": + df = df[(df["split"] == split) | (df["split"] == f"{split}_covost")] + else: + df = df[df["split"] == split] + self.data = df.to_dict(orient="index").items() + self.data = [v for k, v in sorted(self.data, key=lambda x: x[0])] + + @classmethod + def load_from_tsv(cls, path: str): + return pd.read_csv( + path, + sep="\t", + header=0, + encoding="utf-8", + escapechar="\\", + quoting=csv.QUOTE_NONE, + na_filter=False, + ) + + def __getitem__( + self, n: int + ) -> Tuple[Tensor, int, str, str, Optional[str], str, str]: + """Load the n-th sample from the dataset. + + Args: + n (int): The index of the sample to be loaded + + Returns: + tuple: ``(waveform, sample_rate, sentence, translation, speaker_id, + sample_id)`` + """ + data = self.data[n] + path = os.path.join(self.root, "clips", data["path"]) + waveform, sample_rate = torchaudio.load(path) + sentence = data["sentence"] + translation = None if self.no_translation else data["translation"] + speaker_id = data["client_id"] + _id = data["path"].replace(".mp3", "") + return waveform, sample_rate, sentence, translation, speaker_id, _id + + def __len__(self) -> int: + return len(self.data) + + +def process(args): + root = op.join(args.data_root, args.src_lang) + os.makedirs(root, exist_ok=True) + # Extract features + feature_root = op.join(root, "fbank80") + os.makedirs(feature_root, exist_ok=True) + for split in CoVoST.SPLITS: + print(f"Fetching split {split}...") + dataset = CoVoST(root, split, args.src_lang, args.tgt_lang, download=True) + print("Extracting log mel filter bank features...") + for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset): + extract_fbank_features( + waveform, sample_rate, op.join(feature_root, f"{utt_id}.npy") + ) + # Pack features into ZIP + zip_filename = "fbank80.zip" + zip_path = op.join(root, zip_filename) + print("ZIPing features...") + create_zip(feature_root, zip_path) + print("Fetching ZIP manifest...") + zip_manifest = get_zip_manifest(args.data_root, f"{args.src_lang}/{zip_filename}") + # Generate TSV manifest + print("Generating manifest...") + train_text = [] + task = f"asr_{args.src_lang}" + if args.tgt_lang is not None: + task = f"st_{args.src_lang}_{args.tgt_lang}" + for split in CoVoST.SPLITS: + manifest = {c: [] for c in MANIFEST_COLUMNS} + dataset = CoVoST(root, split, args.src_lang, args.tgt_lang) + for wav, sr, src_utt, tgt_utt, speaker_id, utt_id in tqdm(dataset): + manifest["id"].append(utt_id) + manifest["audio"].append(zip_manifest[utt_id]) + duration_ms = int(wav.size(1) / sr * 1000) + manifest["n_frames"].append(int(1 + (duration_ms - 25) / 10)) + manifest["tgt_text"].append(src_utt if args.tgt_lang is None else tgt_utt) + manifest["speaker"].append(speaker_id) + is_train_split = split.startswith("train") + if is_train_split: + train_text.extend(manifest["tgt_text"]) + df = pd.DataFrame.from_dict(manifest) + df = filter_manifest_df(df, is_train_split=is_train_split) + save_df_to_tsv(df, op.join(root, f"{split}_{task}.tsv")) + # Generate vocab + vocab_size_str = "" if args.vocab_type == "char" else str(args.vocab_size) + spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size_str}_{task}" + with NamedTemporaryFile(mode="w") as f: + for t in train_text: + f.write(t + "\n") + gen_vocab( + f.name, op.join(root, spm_filename_prefix), args.vocab_type, args.vocab_size + ) + # Generate config YAML + gen_config_yaml( + root, + spm_filename_prefix + ".model", + yaml_filename=f"config_{task}.yaml", + specaugment_policy="lb", + ) + # Clean up + shutil.rmtree(feature_root) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--data-root", "-d", required=True, type=str) + parser.add_argument( + "--vocab-type", + default="unigram", + required=True, + type=str, + choices=["bpe", "unigram", "char"], + ), + parser.add_argument("--vocab-size", default=1000, type=int) + parser.add_argument("--src-lang", "-s", required=True, type=str) + parser.add_argument("--tgt-lang", "-t", type=str) + args = parser.parse_args() + + process(args) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/speech_to_text/prep_librispeech_data.py b/fairseq-tools/fairseq/examples/speech_to_text/prep_librispeech_data.py new file mode 100644 index 00000000..95fcec8f --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_to_text/prep_librispeech_data.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import logging +import os +import os.path as op +import shutil +from tempfile import NamedTemporaryFile + +import pandas as pd +from examples.speech_to_text.data_utils import ( + create_zip, + extract_fbank_features, + gen_config_yaml, + gen_vocab, + get_zip_manifest, + save_df_to_tsv, +) +from torchaudio.datasets import LIBRISPEECH +from tqdm import tqdm + + +log = logging.getLogger(__name__) + +SPLITS = [ + "train-clean-100", + "train-clean-360", + "train-other-500", + "dev-clean", + "dev-other", + "test-clean", + "test-other", +] + +MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"] + + +def process(args): + os.makedirs(args.output_root, exist_ok=True) + # Extract features + feature_root = op.join(args.output_root, "fbank80") + os.makedirs(feature_root, exist_ok=True) + for split in SPLITS: + print(f"Fetching split {split}...") + dataset = LIBRISPEECH(args.output_root, url=split, download=True) + print("Extracting log mel filter bank features...") + for wav, sample_rate, _, spk_id, chapter_id, utt_id in tqdm(dataset): + sample_id = f"{spk_id}-{chapter_id}-{utt_id}" + extract_fbank_features( + wav, sample_rate, op.join(feature_root, f"{sample_id}.npy") + ) + # Pack features into ZIP + zip_filename = "fbank80.zip" + zip_path = op.join(args.output_root, zip_filename) + print("ZIPing features...") + create_zip(feature_root, zip_path) + print("Fetching ZIP manifest...") + zip_manifest = get_zip_manifest(args.output_root, zip_filename) + # Generate TSV manifest + print("Generating manifest...") + train_text = [] + for split in SPLITS: + manifest = {c: [] for c in MANIFEST_COLUMNS} + dataset = LIBRISPEECH(args.output_root, url=split) + for wav, sample_rate, utt, spk_id, chapter_id, utt_id in tqdm(dataset): + sample_id = f"{spk_id}-{chapter_id}-{utt_id}" + manifest["id"].append(sample_id) + manifest["audio"].append(zip_manifest[sample_id]) + duration_ms = int(wav.size(1) / sample_rate * 1000) + manifest["n_frames"].append(int(1 + (duration_ms - 25) / 10)) + manifest["tgt_text"].append(utt) + manifest["speaker"].append(spk_id) + save_df_to_tsv( + pd.DataFrame.from_dict(manifest), op.join(args.output_root, f"{split}.tsv") + ) + if split.startswith("train"): + train_text.extend(manifest["tgt_text"]) + # Generate vocab + vocab_size = "" if args.vocab_type == "char" else str(args.vocab_size) + spm_filename_prefix = f"spm_{args.vocab_type}{vocab_size}" + with NamedTemporaryFile(mode="w") as f: + for t in train_text: + f.write(t + "\n") + gen_vocab( + f.name, + op.join(args.output_root, spm_filename_prefix), + args.vocab_type, + args.vocab_size, + ) + # Generate config YAML + gen_config_yaml( + args.output_root, spm_filename_prefix + ".model", specaugment_policy="ld" + ) + # Clean up + shutil.rmtree(feature_root) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--output-root", "-o", required=True, type=str) + parser.add_argument( + "--vocab-type", + default="unigram", + required=True, + type=str, + choices=["bpe", "unigram", "char"], + ), + parser.add_argument("--vocab-size", default=10000, type=int) + args = parser.parse_args() + + process(args) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/speech_to_text/prep_mustc_data.py b/fairseq-tools/fairseq/examples/speech_to_text/prep_mustc_data.py new file mode 100644 index 00000000..5593d2e7 --- /dev/null +++ b/fairseq-tools/fairseq/examples/speech_to_text/prep_mustc_data.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import logging +import os +import os.path as op +import shutil +from itertools import groupby +from tempfile import NamedTemporaryFile +from typing import Tuple + +import pandas as pd +import torchaudio +from examples.speech_to_text.data_utils import ( + create_zip, + extract_fbank_features, + filter_manifest_df, + gen_config_yaml, + gen_vocab, + get_zip_manifest, + save_df_to_tsv, +) +from torch import Tensor +from torch.utils.data import Dataset +from tqdm import tqdm + + +log = logging.getLogger(__name__) + + +MANIFEST_COLUMNS = ["id", "audio", "n_frames", "tgt_text", "speaker"] +TASKS = ["asr", "st"] + + +class MUSTC(Dataset): + """ + Create a Dataset for MuST-C. Each item is a tuple of the form: + waveform, sample_rate, source utterance, target utterance, speaker_id, + utterance_id + """ + + SPLITS = ["train", "dev", "tst-COMMON", "tst-HE"] + LANGUAGES = ["de", "es", "fr", "it", "nl", "pt", "ro", "ru"] + + def __init__(self, root: str, lang: str, split: str) -> None: + assert split in self.SPLITS and lang in self.LANGUAGES + _root = op.join(root, f"en-{lang}", "data", split) + wav_root, txt_root = op.join(_root, "wav"), op.join(_root, "txt") + assert op.isdir(_root) and op.isdir(wav_root) and op.isdir(txt_root) + # Load audio segments + try: + import yaml + except ImportError: + print("Please install PyYAML to load YAML files for " "the MuST-C dataset") + with open(op.join(txt_root, f"{split}.yaml")) as f: + segments = yaml.load(f, Loader=yaml.BaseLoader) + # Load source and target utterances + for _lang in ["en", lang]: + with open(op.join(txt_root, f"{split}.{_lang}")) as f: + utterances = [r.strip() for r in f] + assert len(segments) == len(utterances) + for i, u in enumerate(utterances): + segments[i][_lang] = u + # Gather info + self.data = [] + for wav_filename, _seg_group in groupby(segments, lambda x: x["wav"]): + wav_path = op.join(wav_root, wav_filename) + sample_rate = torchaudio.info(wav_path)[0].rate + seg_group = sorted(_seg_group, key=lambda x: x["offset"]) + for i, segment in enumerate(seg_group): + offset = int(float(segment["offset"]) * sample_rate) + n_frames = int(float(segment["duration"]) * sample_rate) + _id = f"{op.splitext(wav_filename)[0]}_{i}" + self.data.append( + ( + wav_path, + offset, + n_frames, + sample_rate, + segment["en"], + segment[lang], + segment["speaker_id"], + _id, + ) + ) + + def __getitem__(self, n: int) -> Tuple[Tensor, int, str, str, str, str]: + wav_path, offset, n_frames, sr, src_utt, tgt_utt, spk_id, utt_id = self.data[n] + waveform, _ = torchaudio.load(wav_path, offset=offset, num_frames=n_frames) + return waveform, sr, src_utt, tgt_utt, spk_id, utt_id + + def __len__(self) -> int: + return len(self.data) + + +def process(args): + for lang in MUSTC.LANGUAGES: + cur_root = op.join(args.data_root, f"en-{lang}") + if not op.isdir(cur_root): + print(f"{cur_root} does not exist. Skipped.") + continue + # Extract features + feature_root = op.join(cur_root, "fbank80") + os.makedirs(feature_root, exist_ok=True) + for split in MUSTC.SPLITS: + print(f"Fetching split {split}...") + dataset = MUSTC(args.data_root, lang, split) + print("Extracting log mel filter bank features...") + for waveform, sample_rate, _, _, _, utt_id in tqdm(dataset): + extract_fbank_features( + waveform, sample_rate, op.join(feature_root, f"{utt_id}.npy") + ) + # Pack features into ZIP + zip_filename = "fbank80.zip" + zip_path = op.join(cur_root, zip_filename) + print("ZIPing features...") + create_zip(feature_root, zip_path) + print("Fetching ZIP manifest...") + zip_manifest = get_zip_manifest(args.data_root, f"en-{lang}/{zip_filename}") + # Generate TSV manifest + print("Generating manifest...") + train_text = {task: [] for task in TASKS} + for split in MUSTC.SPLITS: + is_train_split = split.startswith("train") + manifest = {c: [] for c in MANIFEST_COLUMNS} + text = {task: [] for task in TASKS} + dataset = MUSTC(args.data_root, lang, split) + for wav, sr, src_utt, tgt_utt, speaker_id, utt_id in tqdm(dataset): + manifest["id"].append(utt_id) + manifest["audio"].append(zip_manifest[utt_id]) + duration_ms = int(wav.size(1) / sr * 1000) + manifest["n_frames"].append(int(1 + (duration_ms - 25) / 10)) + text["asr"].append(src_utt) + text["st"].append(tgt_utt) + manifest["speaker"].append(speaker_id) + if is_train_split: + for task in TASKS: + train_text[task].extend(text[task]) + for task in TASKS: + manifest["tgt_text"] = text[task] + df = pd.DataFrame.from_dict(manifest) + df = filter_manifest_df(df, is_train_split=is_train_split) + save_df_to_tsv(df, op.join(cur_root, f"{split}_{task}.tsv")) + # Generate vocab + for task in TASKS: + vocab_type, vocab_size = args.asr_vocab_type, args.asr_vocab_size + if task == "st": + vocab_type, vocab_size = args.st_vocab_type, args.st_vocab_size + vocab_size_str = "" if vocab_type == "char" else str(vocab_size) + spm_filename_prefix = f"spm_{vocab_type}{vocab_size_str}_{task}" + with NamedTemporaryFile(mode="w") as f: + for t in train_text[task]: + f.write(t + "\n") + gen_vocab( + f.name, + op.join(cur_root, spm_filename_prefix), + vocab_type, + vocab_size, + ) + # Generate config YAML + gen_config_yaml( + cur_root, + spm_filename_prefix + ".model", + yaml_filename=f"config_{task}.yaml", + specaugment_policy="lb", + ) + # Clean up + shutil.rmtree(feature_root) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--data-root", "-d", required=True, type=str) + parser.add_argument( + "--asr-vocab-type", + default="unigram", + required=True, + type=str, + choices=["bpe", "unigram", "char"], + ), + parser.add_argument( + "--st-vocab-type", + default="unigram", + required=True, + type=str, + choices=["bpe", "unigram", "char"], + ), + parser.add_argument("--asr-vocab-size", default=5000, type=int) + parser.add_argument("--st-vocab-size", default=8000, type=int) + args = parser.parse_args() + + process(args) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/stories/README.md b/fairseq-tools/fairseq/examples/stories/README.md new file mode 100644 index 00000000..588941ed --- /dev/null +++ b/fairseq-tools/fairseq/examples/stories/README.md @@ -0,0 +1,66 @@ +# Hierarchical Neural Story Generation (Fan et al., 2018) + +The following commands provide an example of pre-processing data, training a model, and generating text for story generation with the WritingPrompts dataset. + +## Pre-trained models + +Description | Dataset | Model | Test set(s) +---|---|---|--- +Stories with Convolutional Model
([Fan et al., 2018](https://arxiv.org/abs/1805.04833)) | [WritingPrompts](https://dl.fbaipublicfiles.com/fairseq/data/writingPrompts.tar.gz) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/models/stories_checkpoint.tar.bz2) | [download (.tar.bz2)](https://dl.fbaipublicfiles.com/fairseq/data/stories_test.tar.bz2) + +We provide sample stories generated by the [convolutional seq2seq model](https://dl.fbaipublicfiles.com/fairseq/data/seq2seq_stories.txt) and [fusion model](https://dl.fbaipublicfiles.com/fairseq/data/fusion_stories.txt) from [Fan et al., 2018](https://arxiv.org/abs/1805.04833). The corresponding prompts for the fusion model can be found [here](https://dl.fbaipublicfiles.com/fairseq/data/fusion_prompts.txt). Note that there are unk in the file, as we modeled a small full vocabulary (no BPE or pre-training). We did not use these unk prompts for human evaluation. + +## Dataset + +The dataset can be downloaded like this: + +```bash +cd examples/stories +curl https://dl.fbaipublicfiles.com/fairseq/data/writingPrompts.tar.gz | tar xvzf - +``` + +and contains a train, test, and valid split. The dataset is described here: https://arxiv.org/abs/1805.04833. We model only the first 1000 words of each story, including one newLine token. + +## Example usage + +First we will preprocess the dataset. Note that the dataset release is the full data, but the paper models the first 1000 words of each story. Here is example code that trims the dataset to the first 1000 words of each story: +```python +data = ["train", "test", "valid"] +for name in data: + with open(name + ".wp_target") as f: + stories = f.readlines() + stories = [" ".join(i.split()[0:1000]) for i in stories] + with open(name + ".wp_target", "w") as o: + for line in stories: + o.write(line.strip() + "\n") +``` + +Once we've trimmed the data we can binarize it and train our model: +```bash +# Binarize the dataset: +export TEXT=examples/stories/writingPrompts +fairseq-preprocess --source-lang wp_source --target-lang wp_target \ + --trainpref $TEXT/train --validpref $TEXT/valid --testpref $TEXT/test \ + --destdir data-bin/writingPrompts --padding-factor 1 --thresholdtgt 10 --thresholdsrc 10 + +# Train the model: +fairseq-train data-bin/writingPrompts -a fconv_self_att_wp --lr 0.25 --optimizer nag --clip-norm 0.1 --max-tokens 1500 --lr-scheduler reduce_lr_on_plateau --decoder-attention True --encoder-attention False --criterion label_smoothed_cross_entropy --weight-decay .0000001 --label-smoothing 0 --source-lang wp_source --target-lang wp_target --gated-attention True --self-attention True --project-input True --pretrained False + +# Train a fusion model: +# add the arguments: --pretrained True --pretrained-checkpoint path/to/checkpoint + +# Generate: +# Note: to load the pretrained model at generation time, you need to pass in a model-override argument to communicate to the fusion model at generation time where you have placed the pretrained checkpoint. By default, it will load the exact path of the fusion model's pretrained model from training time. You should use model-override if you have moved the pretrained model (or are using our provided models). If you are generating from a non-fusion model, the model-override argument is not necessary. + +fairseq-generate data-bin/writingPrompts --path /path/to/trained/model/checkpoint_best.pt --batch-size 32 --beam 1 --sampling --sampling-topk 10 --temperature 0.8 --nbest 1 --model-overrides "{'pretrained_checkpoint':'/path/to/pretrained/model/checkpoint'}" +``` + +## Citation +```bibtex +@inproceedings{fan2018hierarchical, + title = {Hierarchical Neural Story Generation}, + author = {Fan, Angela and Lewis, Mike and Dauphin, Yann}, + booktitle = {Conference of the Association for Computational Linguistics (ACL)}, + year = 2018, +} +``` diff --git a/fairseq-tools/fairseq/examples/translation/prepare-iwslt14.sh b/fairseq-tools/fairseq/examples/translation/prepare-iwslt14.sh new file mode 100644 index 00000000..80192b02 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation/prepare-iwslt14.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +# +# Adapted from https://github.com/facebookresearch/MIXER/blob/master/prepareData.sh +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +echo 'Cloning Moses github repository (for tokenization scripts)...' +git clone https://github.com/moses-smt/mosesdecoder.git + +echo 'Cloning Subword NMT repository (for BPE pre-processing)...' +git clone https://github.com/rsennrich/subword-nmt.git + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +LC=$SCRIPTS/tokenizer/lowercase.perl +CLEAN=$SCRIPTS/training/clean-corpus-n.perl +BPEROOT=subword-nmt/subword_nmt +BPE_TOKENS=10000 + +URL="http://dl.fbaipublicfiles.com/fairseq/data/iwslt14/de-en.tgz" +GZ=de-en.tgz + +if [ ! -d "$SCRIPTS" ]; then + echo "Please set SCRIPTS variable correctly to point to Moses scripts." + exit +fi + +src=de +tgt=en +lang=de-en +prep=iwslt14.tokenized.de-en +tmp=$prep/tmp +orig=orig + +mkdir -p $orig $tmp $prep + +echo "Downloading data from ${URL}..." +cd $orig +wget "$URL" + +if [ -f $GZ ]; then + echo "Data successfully downloaded." +else + echo "Data not successfully downloaded." + exit +fi + +tar zxvf $GZ +cd .. + +echo "pre-processing train data..." +for l in $src $tgt; do + f=train.tags.$lang.$l + tok=train.tags.$lang.tok.$l + + cat $orig/$lang/$f | \ + grep -v '' | \ + grep -v '' | \ + grep -v '' | \ + sed -e 's///g' | \ + sed -e 's/<\/title>//g' | \ + sed -e 's/<description>//g' | \ + sed -e 's/<\/description>//g' | \ + perl $TOKENIZER -threads 8 -l $l > $tmp/$tok + echo "" +done +perl $CLEAN -ratio 1.5 $tmp/train.tags.$lang.tok $src $tgt $tmp/train.tags.$lang.clean 1 175 +for l in $src $tgt; do + perl $LC < $tmp/train.tags.$lang.clean.$l > $tmp/train.tags.$lang.$l +done + +echo "pre-processing valid/test data..." +for l in $src $tgt; do + for o in `ls $orig/$lang/IWSLT14.TED*.$l.xml`; do + fname=${o##*/} + f=$tmp/${fname%.*} + echo $o $f + grep '<seg id' $o | \ + sed -e 's/<seg id="[0-9]*">\s*//g' | \ + sed -e 's/\s*<\/seg>\s*//g' | \ + sed -e "s/\’/\'/g" | \ + perl $TOKENIZER -threads 8 -l $l | \ + perl $LC > $f + echo "" + done +done + + +echo "creating train, valid, test..." +for l in $src $tgt; do + awk '{if (NR%23 == 0) print $0; }' $tmp/train.tags.de-en.$l > $tmp/valid.$l + awk '{if (NR%23 != 0) print $0; }' $tmp/train.tags.de-en.$l > $tmp/train.$l + + cat $tmp/IWSLT14.TED.dev2010.de-en.$l \ + $tmp/IWSLT14.TEDX.dev2012.de-en.$l \ + $tmp/IWSLT14.TED.tst2010.de-en.$l \ + $tmp/IWSLT14.TED.tst2011.de-en.$l \ + $tmp/IWSLT14.TED.tst2012.de-en.$l \ + > $tmp/test.$l +done + +TRAIN=$tmp/train.en-de +BPE_CODE=$prep/code +rm -f $TRAIN +for l in $src $tgt; do + cat $tmp/train.$l >> $TRAIN +done + +echo "learn_bpe.py on ${TRAIN}..." +python3 $BPEROOT/learn_bpe.py -s $BPE_TOKENS < $TRAIN > $BPE_CODE + +for L in $src $tgt; do + for f in train.$L valid.$L test.$L; do + echo "apply_bpe.py to ${f}..." + python3 $BPEROOT/apply_bpe.py -c $BPE_CODE < $tmp/$f > $prep/$f + done +done diff --git a/fairseq-tools/fairseq/examples/translation/prepare-iwslt17-multilingual.sh b/fairseq-tools/fairseq/examples/translation/prepare-iwslt17-multilingual.sh new file mode 100644 index 00000000..23be8755 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation/prepare-iwslt17-multilingual.sh @@ -0,0 +1,133 @@ +#!/bin/bash +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +SRCS=( + "de" + "fr" +) +TGT=en + +ROOT=$(dirname "$0") +SCRIPTS=$ROOT/../../scripts +SPM_TRAIN=$SCRIPTS/spm_train.py +SPM_ENCODE=$SCRIPTS/spm_encode.py + +BPESIZE=16384 +ORIG=$ROOT/iwslt17_orig +DATA=$ROOT/iwslt17.de_fr.en.bpe16k +mkdir -p "$ORIG" "$DATA" + +TRAIN_MINLEN=1 # remove sentences with <1 BPE token +TRAIN_MAXLEN=250 # remove sentences with >250 BPE tokens + +URLS=( + "https://wit3.fbk.eu/archive/2017-01-trnted/texts/de/en/de-en.tgz" + "https://wit3.fbk.eu/archive/2017-01-trnted/texts/fr/en/fr-en.tgz" +) +ARCHIVES=( + "de-en.tgz" + "fr-en.tgz" +) +VALID_SETS=( + "IWSLT17.TED.dev2010.de-en IWSLT17.TED.tst2010.de-en IWSLT17.TED.tst2011.de-en IWSLT17.TED.tst2012.de-en IWSLT17.TED.tst2013.de-en IWSLT17.TED.tst2014.de-en IWSLT17.TED.tst2015.de-en" + "IWSLT17.TED.dev2010.fr-en IWSLT17.TED.tst2010.fr-en IWSLT17.TED.tst2011.fr-en IWSLT17.TED.tst2012.fr-en IWSLT17.TED.tst2013.fr-en IWSLT17.TED.tst2014.fr-en IWSLT17.TED.tst2015.fr-en" +) + +# download and extract data +for ((i=0;i<${#URLS[@]};++i)); do + ARCHIVE=$ORIG/${ARCHIVES[i]} + if [ -f "$ARCHIVE" ]; then + echo "$ARCHIVE already exists, skipping download" + else + URL=${URLS[i]} + wget -P "$ORIG" "$URL" + if [ -f "$ARCHIVE" ]; then + echo "$URL successfully downloaded." + else + echo "$URL not successfully downloaded." + exit 1 + fi + fi + FILE=${ARCHIVE: -4} + if [ -e "$FILE" ]; then + echo "$FILE already exists, skipping extraction" + else + tar -C "$ORIG" -xzvf "$ARCHIVE" + fi +done + +echo "pre-processing train data..." +for SRC in "${SRCS[@]}"; do + for LANG in "${SRC}" "${TGT}"; do + cat "$ORIG/${SRC}-${TGT}/train.tags.${SRC}-${TGT}.${LANG}" \ + | grep -v '<url>' \ + | grep -v '<talkid>' \ + | grep -v '<keywords>' \ + | grep -v '<speaker>' \ + | grep -v '<reviewer' \ + | grep -v '<translator' \ + | grep -v '<doc' \ + | grep -v '</doc>' \ + | sed -e 's/<title>//g' \ + | sed -e 's/<\/title>//g' \ + | sed -e 's/<description>//g' \ + | sed -e 's/<\/description>//g' \ + | sed 's/^\s*//g' \ + | sed 's/\s*$//g' \ + > "$DATA/train.${SRC}-${TGT}.${LANG}" + done +done + +echo "pre-processing valid data..." +for ((i=0;i<${#SRCS[@]};++i)); do + SRC=${SRCS[i]} + VALID_SET=(${VALID_SETS[i]}) + for ((j=0;j<${#VALID_SET[@]};++j)); do + FILE=${VALID_SET[j]} + for LANG in "$SRC" "$TGT"; do + grep '<seg id' "$ORIG/${SRC}-${TGT}/${FILE}.${LANG}.xml" \ + | sed -e 's/<seg id="[0-9]*">\s*//g' \ + | sed -e 's/\s*<\/seg>\s*//g' \ + | sed -e "s/\’/\'/g" \ + > "$DATA/valid${j}.${SRC}-${TGT}.${LANG}" + done + done +done + +# learn BPE with sentencepiece +TRAIN_FILES=$(for SRC in "${SRCS[@]}"; do echo $DATA/train.${SRC}-${TGT}.${SRC}; echo $DATA/train.${SRC}-${TGT}.${TGT}; done | tr "\n" ",") +echo "learning joint BPE over ${TRAIN_FILES}..." +python "$SPM_TRAIN" \ + --input=$TRAIN_FILES \ + --model_prefix=$DATA/sentencepiece.bpe \ + --vocab_size=$BPESIZE \ + --character_coverage=1.0 \ + --model_type=bpe + +# encode train/valid +echo "encoding train with learned BPE..." +for SRC in "${SRCS[@]}"; do + python "$SPM_ENCODE" \ + --model "$DATA/sentencepiece.bpe.model" \ + --output_format=piece \ + --inputs $DATA/train.${SRC}-${TGT}.${SRC} $DATA/train.${SRC}-${TGT}.${TGT} \ + --outputs $DATA/train.bpe.${SRC}-${TGT}.${SRC} $DATA/train.bpe.${SRC}-${TGT}.${TGT} \ + --min-len $TRAIN_MINLEN --max-len $TRAIN_MAXLEN +done + +echo "encoding valid with learned BPE..." +for ((i=0;i<${#SRCS[@]};++i)); do + SRC=${SRCS[i]} + VALID_SET=(${VALID_SETS[i]}) + for ((j=0;j<${#VALID_SET[@]};++j)); do + python "$SPM_ENCODE" \ + --model "$DATA/sentencepiece.bpe.model" \ + --output_format=piece \ + --inputs $DATA/valid${j}.${SRC}-${TGT}.${SRC} $DATA/valid${j}.${SRC}-${TGT}.${TGT} \ + --outputs $DATA/valid${j}.bpe.${SRC}-${TGT}.${SRC} $DATA/valid${j}.bpe.${SRC}-${TGT}.${TGT} + done +done diff --git a/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2de.sh b/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2de.sh new file mode 100644 index 00000000..7e4208f4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2de.sh @@ -0,0 +1,143 @@ +#!/bin/bash +# Adapted from https://github.com/facebookresearch/MIXER/blob/master/prepareData.sh +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +echo 'Cloning Moses github repository (for tokenization scripts)...' +git clone https://github.com/moses-smt/mosesdecoder.git + +echo 'Cloning Subword NMT repository (for BPE pre-processing)...' +git clone https://github.com/rsennrich/subword-nmt.git + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +CLEAN=$SCRIPTS/training/clean-corpus-n.perl +NORM_PUNC=$SCRIPTS/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$SCRIPTS/tokenizer/remove-non-printing-char.perl +BPEROOT=subword-nmt/subword_nmt +BPE_TOKENS=40000 + +URLS=( + "http://statmt.org/wmt13/training-parallel-europarl-v7.tgz" + "http://statmt.org/wmt13/training-parallel-commoncrawl.tgz" + "http://data.statmt.org/wmt17/translation-task/training-parallel-nc-v12.tgz" + "http://data.statmt.org/wmt17/translation-task/dev.tgz" + "http://statmt.org/wmt14/test-full.tgz" +) +FILES=( + "training-parallel-europarl-v7.tgz" + "training-parallel-commoncrawl.tgz" + "training-parallel-nc-v12.tgz" + "dev.tgz" + "test-full.tgz" +) +CORPORA=( + "training/europarl-v7.de-en" + "commoncrawl.de-en" + "training/news-commentary-v12.de-en" +) + +# This will make the dataset compatible to the one used in "Convolutional Sequence to Sequence Learning" +# https://arxiv.org/abs/1705.03122 +if [ "$1" == "--icml17" ]; then + URLS[2]="http://statmt.org/wmt14/training-parallel-nc-v9.tgz" + FILES[2]="training-parallel-nc-v9.tgz" + CORPORA[2]="training/news-commentary-v9.de-en" + OUTDIR=wmt14_en_de +else + OUTDIR=wmt17_en_de +fi + +if [ ! -d "$SCRIPTS" ]; then + echo "Please set SCRIPTS variable correctly to point to Moses scripts." + exit +fi + +src=en +tgt=de +lang=en-de +prep=$OUTDIR +tmp=$prep/tmp +orig=orig +dev=dev/newstest2013 + +mkdir -p $orig $tmp $prep + +cd $orig + +for ((i=0;i<${#URLS[@]};++i)); do + file=${FILES[i]} + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + url=${URLS[i]} + wget "$url" + if [ -f $file ]; then + echo "$url successfully downloaded." + else + echo "$url not successfully downloaded." + exit -1 + fi + if [ ${file: -4} == ".tgz" ]; then + tar zxvf $file + elif [ ${file: -4} == ".tar" ]; then + tar xvf $file + fi + fi +done +cd .. + +echo "pre-processing train data..." +for l in $src $tgt; do + rm $tmp/train.tags.$lang.tok.$l + for f in "${CORPORA[@]}"; do + cat $orig/$f.$l | \ + perl $NORM_PUNC $l | \ + perl $REM_NON_PRINT_CHAR | \ + perl $TOKENIZER -threads 8 -a -l $l >> $tmp/train.tags.$lang.tok.$l + done +done + +echo "pre-processing test data..." +for l in $src $tgt; do + if [ "$l" == "$src" ]; then + t="src" + else + t="ref" + fi + grep '<seg id' $orig/test-full/newstest2014-deen-$t.$l.sgm | \ + sed -e 's/<seg id="[0-9]*">\s*//g' | \ + sed -e 's/\s*<\/seg>\s*//g' | \ + sed -e "s/\’/\'/g" | \ + perl $TOKENIZER -threads 8 -a -l $l > $tmp/test.$l + echo "" +done + +echo "splitting train and valid..." +for l in $src $tgt; do + awk '{if (NR%100 == 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/valid.$l + awk '{if (NR%100 != 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/train.$l +done + +TRAIN=$tmp/train.de-en +BPE_CODE=$prep/code +rm -f $TRAIN +for l in $src $tgt; do + cat $tmp/train.$l >> $TRAIN +done + +echo "learn_bpe.py on ${TRAIN}..." +python3 $BPEROOT/learn_bpe.py -s $BPE_TOKENS < $TRAIN > $BPE_CODE + +for L in $src $tgt; do + for f in train.$L valid.$L test.$L; do + echo "apply_bpe.py to ${f}..." + python3 $BPEROOT/apply_bpe.py -c $BPE_CODE < $tmp/$f > $tmp/bpe.$f + done +done + +perl $CLEAN -ratio 1.5 $tmp/bpe.train $src $tgt $prep/train 1 250 +perl $CLEAN -ratio 1.5 $tmp/bpe.valid $src $tgt $prep/valid 1 250 + +for L in $src $tgt; do + cp $tmp/bpe.test.$L $prep/test.$L +done diff --git a/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2fr.sh b/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2fr.sh new file mode 100644 index 00000000..2ac97a5b --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation/prepare-wmt14en2fr.sh @@ -0,0 +1,136 @@ +#!/bin/bash +# Adapted from https://github.com/facebookresearch/MIXER/blob/master/prepareData.sh + +echo 'Cloning Moses github repository (for tokenization scripts)...' +git clone https://github.com/moses-smt/mosesdecoder.git + +echo 'Cloning Subword NMT repository (for BPE pre-processing)...' +git clone https://github.com/rsennrich/subword-nmt.git + +SCRIPTS=mosesdecoder/scripts +TOKENIZER=$SCRIPTS/tokenizer/tokenizer.perl +CLEAN=$SCRIPTS/training/clean-corpus-n.perl +NORM_PUNC=$SCRIPTS/tokenizer/normalize-punctuation.perl +REM_NON_PRINT_CHAR=$SCRIPTS/tokenizer/remove-non-printing-char.perl +BPEROOT=subword-nmt/subword_nmt +BPE_TOKENS=40000 + +URLS=( + "http://statmt.org/wmt13/training-parallel-europarl-v7.tgz" + "http://statmt.org/wmt13/training-parallel-commoncrawl.tgz" + "http://statmt.org/wmt13/training-parallel-un.tgz" + "http://statmt.org/wmt14/training-parallel-nc-v9.tgz" + "http://statmt.org/wmt10/training-giga-fren.tar" + "http://statmt.org/wmt14/test-full.tgz" +) +FILES=( + "training-parallel-europarl-v7.tgz" + "training-parallel-commoncrawl.tgz" + "training-parallel-un.tgz" + "training-parallel-nc-v9.tgz" + "training-giga-fren.tar" + "test-full.tgz" +) +CORPORA=( + "training/europarl-v7.fr-en" + "commoncrawl.fr-en" + "un/undoc.2000.fr-en" + "training/news-commentary-v9.fr-en" + "giga-fren.release2.fixed" +) + +if [ ! -d "$SCRIPTS" ]; then + echo "Please set SCRIPTS variable correctly to point to Moses scripts." + exit +fi + +src=en +tgt=fr +lang=en-fr +prep=wmt14_en_fr +tmp=$prep/tmp +orig=orig + +mkdir -p $orig $tmp $prep + +cd $orig + +for ((i=0;i<${#URLS[@]};++i)); do + file=${FILES[i]} + if [ -f $file ]; then + echo "$file already exists, skipping download" + else + url=${URLS[i]} + wget "$url" + if [ -f $file ]; then + echo "$url successfully downloaded." + else + echo "$url not successfully downloaded." + exit -1 + fi + if [ ${file: -4} == ".tgz" ]; then + tar zxvf $file + elif [ ${file: -4} == ".tar" ]; then + tar xvf $file + fi + fi +done + +gunzip giga-fren.release2.fixed.*.gz +cd .. + +echo "pre-processing train data..." +for l in $src $tgt; do + rm $tmp/train.tags.$lang.tok.$l + for f in "${CORPORA[@]}"; do + cat $orig/$f.$l | \ + perl $NORM_PUNC $l | \ + perl $REM_NON_PRINT_CHAR | \ + perl $TOKENIZER -threads 8 -a -l $l >> $tmp/train.tags.$lang.tok.$l + done +done + +echo "pre-processing test data..." +for l in $src $tgt; do + if [ "$l" == "$src" ]; then + t="src" + else + t="ref" + fi + grep '<seg id' $orig/test-full/newstest2014-fren-$t.$l.sgm | \ + sed -e 's/<seg id="[0-9]*">\s*//g' | \ + sed -e 's/\s*<\/seg>\s*//g' | \ + sed -e "s/\’/\'/g" | \ + perl $TOKENIZER -threads 8 -a -l $l > $tmp/test.$l + echo "" +done + +echo "splitting train and valid..." +for l in $src $tgt; do + awk '{if (NR%1333 == 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/valid.$l + awk '{if (NR%1333 != 0) print $0; }' $tmp/train.tags.$lang.tok.$l > $tmp/train.$l +done + +TRAIN=$tmp/train.fr-en +BPE_CODE=$prep/code +rm -f $TRAIN +for l in $src $tgt; do + cat $tmp/train.$l >> $TRAIN +done + +echo "learn_bpe.py on ${TRAIN}..." +python $BPEROOT/learn_bpe.py -s $BPE_TOKENS < $TRAIN > $BPE_CODE + +for L in $src $tgt; do + for f in train.$L valid.$L test.$L; do + echo "apply_bpe.py to ${f}..." + python $BPEROOT/apply_bpe.py -c $BPE_CODE < $tmp/$f > $tmp/bpe.$f + done +done + +perl $CLEAN -ratio 1.5 $tmp/bpe.train $src $tgt $prep/train 1 250 +perl $CLEAN -ratio 1.5 $tmp/bpe.valid $src $tgt $prep/valid 1 250 + +for L in $src $tgt; do + cp $tmp/bpe.test.$L $prep/test.$L +done diff --git a/fairseq-tools/fairseq/examples/translation_moe/README.md b/fairseq-tools/fairseq/examples/translation_moe/README.md new file mode 100644 index 00000000..ef7abdb4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/README.md @@ -0,0 +1,89 @@ +# Mixture Models for Diverse Machine Translation: Tricks of the Trade (Shen et al., 2019) + +This page includes instructions for reproducing results from the paper [Mixture Models for Diverse Machine Translation: Tricks of the Trade (Shen et al., 2019)](https://arxiv.org/abs/1902.07816). + +## Download data + +First, follow the [instructions to download and preprocess the WMT'17 En-De dataset](../translation#prepare-wmt14en2desh). +Make sure to learn a joint vocabulary by passing the `--joined-dictionary` option to `fairseq-preprocess`. + +## Train a model + +Then we can train a mixture of experts model using the `translation_moe` task. +Use the `--method` flag to choose the MoE variant; we support hard mixtures with a learned or uniform prior (`--method hMoElp` and `hMoEup`, respectively) and soft mixures (`--method sMoElp` and `sMoEup`). +The model is trained with online responsibility assignment and shared parameterization. + +The following command will train a `hMoElp` model with `3` experts: +```bash +fairseq-train --ddp-backend='no_c10d' \ + data-bin/wmt17_en_de \ + --max-update 100000 \ + --task translation_moe --user-dir examples/translation_moe/translation_moe_src \ + --method hMoElp --mean-pool-gating-network \ + --num-experts 3 \ + --arch transformer_wmt_en_de --share-all-embeddings \ + --optimizer adam --adam-betas '(0.9, 0.98)' --clip-norm 0.0 \ + --lr-scheduler inverse_sqrt --warmup-init-lr 1e-07 --warmup-updates 4000 \ + --lr 0.0007 --min-lr 1e-09 \ + --dropout 0.1 --weight-decay 0.0 --criterion cross_entropy \ + --max-tokens 3584 +``` + +## Translate + +Once a model is trained, we can generate translations from different experts using the `--gen-expert` option. +For example, to generate from expert 0: +```bash +fairseq-generate data-bin/wmt17_en_de \ + --path checkpoints/checkpoint_best.pt \ + --beam 1 --remove-bpe \ + --task translation_moe --user-dir examples/translation_moe/translation_moe_src \ + --method hMoElp --mean-pool-gating-network \ + --num-experts 3 \ + --gen-expert 0 +``` + +## Evaluate + +First download a tokenized version of the WMT'14 En-De test set with multiple references: +```bash +wget dl.fbaipublicfiles.com/fairseq/data/wmt14-en-de.extra_refs.tok +``` + +Next apply BPE on the fly and run generation for each expert: +```bash +BPE_CODE=examples/translation/wmt17_en_de/code +for EXPERT in $(seq 0 2); do \ + cat wmt14-en-de.extra_refs.tok \ + | grep ^S | cut -f 2 \ + | fairseq-interactive data-bin/wmt17_en_de \ + --path checkpoints/checkpoint_best.pt \ + --beam 1 \ + --bpe subword_nmt --bpe-codes $BPE_CODE \ + --buffer-size 500 --max-tokens 6000 \ + --task translation_moe --user-dir examples/translation_moe/translation_moe_src \ + --method hMoElp --mean-pool-gating-network \ + --num-experts 3 \ + --gen-expert $EXPERT ; \ +done > wmt14-en-de.extra_refs.tok.gen.3experts +``` + +Finally use `score_moe.py` to compute pairwise BLUE and average oracle BLEU: +```bash +python examples/translation_moe/score.py --sys wmt14-en-de.extra_refs.tok.gen.3experts --ref wmt14-en-de.extra_refs.tok +# pairwise BLEU: 48.26 +# #refs covered: 2.11 +# multi-reference BLEU (leave-one-out): 59.46 +``` +This matches row 3 from Table 7 in the paper. + +## Citation + +```bibtex +@article{shen2019mixture, + title = {Mixture Models for Diverse Machine Translation: Tricks of the Trade}, + author = {Tianxiao Shen and Myle Ott and Michael Auli and Marc'Aurelio Ranzato}, + journal = {International Conference on Machine Learning}, + year = 2019, +} +``` diff --git a/fairseq-tools/fairseq/examples/translation_moe/score.py b/fairseq-tools/fairseq/examples/translation_moe/score.py new file mode 100644 index 00000000..9a529a98 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/score.py @@ -0,0 +1,197 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Scoring script for computing pairwise BLEU and multi-ref BLEU over a set of +candidate hypotheses. + +See `"Mixture Models for Diverse Machine Translation: Tricks of the Trade" +(Shen et al., 2019) <https://arxiv.org/abs/1902.07816>`_. +""" + +import argparse +import random +import sys +from itertools import chain + +import numpy as np +from sacrebleu import compute_bleu, corpus_bleu as _corpus_bleu + + +def main(): + parser = argparse.ArgumentParser(sys.argv[0]) + parser.add_argument( + "--sys", nargs="*", default="", metavar="FILE", help="path to system output" + ) + parser.add_argument("--ref", default="", metavar="FILE", help="path to references") + parser.add_argument( + "--output", + default="", + metavar="FILE", + help="print outputs into a pretty format", + ) + args = parser.parse_args() + + if args.sys: + src, tgt, hypos, log_probs = load_sys(args.sys) + print("pairwise BLEU: %.2f" % pairwise(hypos)) + if args.output: + merge(src, tgt, hypos, log_probs, args.output) + + if args.ref: + _, _, refs = load_ref(args.ref) + if args.sys: + multi_ref(refs, hypos) + else: + intra_ref(refs) + + +def dictolist(d): + a = sorted(d.items(), key=lambda i: i[0]) + return [i[1] for i in a] + + +def load_sys(paths): + src, tgt, hypos, log_probs = {}, {}, {}, {} + for path in paths: + with open(path) as f: + for line in f: + line = line.rstrip() + # S: source + # T: target + # D: detokenized system output + if line.startswith(("S-", "T-", "D-")): + i = int(line[line.find("-") + 1 : line.find("\t")]) + if line.startswith("S-"): + src[i] = line.split("\t")[1] + if line.startswith("T-"): + tgt[i] = line.split("\t")[1] + if line.startswith("D-"): + if i not in hypos: + hypos[i] = [] + log_probs[i] = [] + hypos[i].append(line.split("\t")[2]) + log_probs[i].append(float(line.split("\t")[1])) + return dictolist(src), dictolist(tgt), dictolist(hypos), dictolist(log_probs) + + +def load_ref(path): + with open(path) as f: + lines = f.readlines() + src, tgt, refs = [], [], [] + i = 0 + while i < len(lines): + if lines[i].startswith("S-"): + src.append(lines[i].split("\t")[1].rstrip()) + i += 1 + elif lines[i].startswith("T-"): + tgt.append(lines[i].split("\t")[1].rstrip()) + i += 1 + else: + a = [] + while i < len(lines) and lines[i].startswith("R"): + a.append(lines[i].split("\t")[1].rstrip()) + i += 1 + refs.append(a) + return src, tgt, refs + + +def merge(src, tgt, hypos, log_probs, path): + with open(path, "w") as f: + for s, t, hs, lps in zip(src, tgt, hypos, log_probs): + f.write(s + "\n") + f.write(t + "\n") + f.write("\n") + for h, lp in zip(hs, lps): + f.write("\t%f\t%s\n" % (lp, h.strip())) + f.write("------------------------------------------------------\n") + + +def corpus_bleu(sys_stream, ref_streams): + bleu = _corpus_bleu(sys_stream, ref_streams, tokenize="none") + return bleu.score + + +def sentence_bleu(hypothesis, reference): + bleu = _corpus_bleu(hypothesis, reference) + for i in range(1, 4): + bleu.counts[i] += 1 + bleu.totals[i] += 1 + bleu = compute_bleu( + bleu.counts, + bleu.totals, + bleu.sys_len, + bleu.ref_len, + smooth_method="exp", + ) + return bleu.score + + +def pairwise(sents): + _ref, _hypo = [], [] + for s in sents: + for i in range(len(s)): + for j in range(len(s)): + if i != j: + _ref.append(s[i]) + _hypo.append(s[j]) + return corpus_bleu(_hypo, [_ref]) + + +def multi_ref(refs, hypos): + _ref, _hypo = [], [] + ref_cnt = 0 + assert len(refs) == len(hypos) + + # count number of refs covered + for rs, hs in zip(refs, hypos): + a = set() + for h in hs: + s = [sentence_bleu(h, r) for r in rs] + j = np.argmax(s) + _ref.append(rs[j]) + _hypo.append(h) + best = [k for k in range(len(rs)) if s[k] == s[j]] + a.add(random.choice(best)) + ref_cnt += len(a) + print("#refs covered: %.2f" % (ref_cnt / len(refs))) + + # transpose refs and hypos + refs = list(zip(*refs)) + hypos = list(zip(*hypos)) + + # compute multi-ref corpus BLEU (leave-one-out to be comparable to intra_ref) + k = len(hypos) + m = len(refs) + flat_hypos = [hypos[j][i] for i in range(len(hypos[0])) for j in range(k)] + duplicated_refs = [[ref for ref in refs_i for _ in range(k)] for refs_i in refs] + loo_bleus = [] + for held_out_ref in range(m): + remaining_refs = ( + duplicated_refs[:held_out_ref] + duplicated_refs[held_out_ref + 1 :] + ) + assert len(remaining_refs) == m - 1 + loo_bleus.append(corpus_bleu(flat_hypos, remaining_refs)) + print("average multi-reference BLEU (leave-one-out): %.2f" % np.mean(loo_bleus)) + + +def intra_ref(refs): + print("ref pairwise BLEU: %.2f" % pairwise(refs)) + refs = list(zip(*refs)) + m = len(refs) + concat_h = [] + concat_rest = [[] for j in range(m - 1)] + for i, h in enumerate(refs): + rest = refs[:i] + refs[i + 1 :] + concat_h.append(h) + for j in range(m - 1): + concat_rest[j].extend(rest[j]) + concat_h = list(chain.from_iterable(concat_h)) + bleu = corpus_bleu(concat_h, concat_rest) + print("multi-reference BLEU (leave-one-out): %.2f" % bleu) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/__init__.py b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/__init__.py new file mode 100644 index 00000000..c0abe53e --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import translation_moe # noqa diff --git a/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/logsumexp_moe.py b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/logsumexp_moe.py new file mode 100644 index 00000000..fb299dae --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/logsumexp_moe.py @@ -0,0 +1,26 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +class LogSumExpMoE(torch.autograd.Function): + """Standard LogSumExp forward pass, but use *posterior* for the backward. + + See `"Mixture Models for Diverse Machine Translation: Tricks of the Trade" + (Shen et al., 2019) <https://arxiv.org/abs/1902.07816>`_. + """ + + @staticmethod + def forward(ctx, logp, posterior, dim=-1): + ctx.save_for_backward(posterior) + ctx.dim = dim + return torch.logsumexp(logp, dim=dim) + + @staticmethod + def backward(ctx, grad_output): + (posterior,) = ctx.saved_tensors + grad_logp = grad_output.unsqueeze(ctx.dim) * posterior + return grad_logp, None, None diff --git a/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/mean_pool_gating_network.py b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/mean_pool_gating_network.py new file mode 100644 index 00000000..484b6ac9 --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/mean_pool_gating_network.py @@ -0,0 +1,50 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn.functional as F + + +class MeanPoolGatingNetwork(torch.nn.Module): + """A simple mean-pooling gating network for selecting experts. + + This module applies mean pooling over an encoder's output and returns + reponsibilities for each expert. The encoder format is expected to match + :class:`fairseq.models.transformer.TransformerEncoder`. + """ + + def __init__(self, embed_dim, num_experts, dropout=None): + super().__init__() + self.embed_dim = embed_dim + self.num_experts = num_experts + + self.fc1 = torch.nn.Linear(embed_dim, embed_dim) + self.dropout = torch.nn.Dropout(dropout) if dropout is not None else None + self.fc2 = torch.nn.Linear(embed_dim, num_experts) + + def forward(self, encoder_out): + if not ( + hasattr(encoder_out, "encoder_out") + and hasattr(encoder_out, "encoder_padding_mask") + and encoder_out.encoder_out.size(2) == self.embed_dim + ): + raise ValueError("Unexpected format for encoder_out") + + # mean pooling over time + encoder_padding_mask = encoder_out.encoder_padding_mask # B x T + encoder_out = encoder_out.encoder_out.transpose(0, 1) # B x T x C + if encoder_padding_mask is not None: + encoder_out = encoder_out.clone() # required because of transpose above + encoder_out[encoder_padding_mask] = 0 + ntokens = torch.sum(~encoder_padding_mask, dim=1, keepdim=True) + x = torch.sum(encoder_out, dim=1) / ntokens.type_as(encoder_out) + else: + x = torch.mean(encoder_out, dim=1) + + x = torch.tanh(self.fc1(x)) + if self.dropout is not None: + x = self.dropout(x) + x = self.fc2(x) + return F.log_softmax(x, dim=-1, dtype=torch.float32).type_as(x) diff --git a/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/translation_moe.py b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/translation_moe.py new file mode 100644 index 00000000..ae458aaa --- /dev/null +++ b/fairseq-tools/fairseq/examples/translation_moe/translation_moe_src/translation_moe.py @@ -0,0 +1,239 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq import metrics, utils +from fairseq.tasks import register_task +from fairseq.tasks.translation import TranslationTask + +from .logsumexp_moe import LogSumExpMoE +from .mean_pool_gating_network import MeanPoolGatingNetwork + + +@register_task("translation_moe") +class TranslationMoETask(TranslationTask): + """ + Translation task for Mixture of Experts (MoE) models. + + See `"Mixture Models for Diverse Machine Translation: Tricks of the Trade" + (Shen et al., 2019) <https://arxiv.org/abs/1902.07816>`_. + + Args: + src_dict (~fairseq.data.Dictionary): dictionary for the source language + tgt_dict (~fairseq.data.Dictionary): dictionary for the target language + + .. note:: + + The translation task is compatible with :mod:`fairseq-train`, + :mod:`fairseq-generate` and :mod:`fairseq-interactive`. + + The translation task provides the following additional command-line + arguments: + + .. argparse:: + :ref: fairseq.tasks.translation_parser + :prog: + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + TranslationTask.add_args(parser) + parser.add_argument('--method', default='hMoEup', + choices=['sMoElp', 'sMoEup', 'hMoElp', 'hMoEup']) + parser.add_argument('--num-experts', default=3, type=int, metavar='N', + help='number of experts') + parser.add_argument('--mean-pool-gating-network', action='store_true', + help='use a simple mean-pooling gating network') + parser.add_argument('--mean-pool-gating-network-dropout', type=float, + help='dropout for mean-pooling gating network') + parser.add_argument('--mean-pool-gating-network-encoder-dim', type=float, + help='encoder output dim for mean-pooling gating network') + parser.add_argument('--gen-expert', type=int, default=0, + help='which expert to use for generation') + # fmt: on + + def __init__(self, args, src_dict, tgt_dict): + if args.method == "sMoElp": + # soft MoE with learned prior + self.uniform_prior = False + self.hard_selection = False + elif args.method == "sMoEup": + # soft MoE with uniform prior + self.uniform_prior = True + self.hard_selection = False + elif args.method == "hMoElp": + # hard MoE with learned prior + self.uniform_prior = False + self.hard_selection = True + elif args.method == "hMoEup": + # hard MoE with uniform prior + self.uniform_prior = True + self.hard_selection = True + + # add indicator tokens for each expert + for i in range(args.num_experts): + # add to both dictionaries in case we're sharing embeddings + src_dict.add_symbol("<expert_{}>".format(i)) + tgt_dict.add_symbol("<expert_{}>".format(i)) + + super().__init__(args, src_dict, tgt_dict) + + def build_model(self, args): + from fairseq import models + + model = models.build_model(args, self) + if not self.uniform_prior and not hasattr(model, "gating_network"): + if self.args.mean_pool_gating_network: + if getattr(args, "mean_pool_gating_network_encoder_dim", None): + encoder_dim = args.mean_pool_gating_network_encoder_dim + elif getattr(args, "encoder_embed_dim", None): + # assume that encoder_embed_dim is the encoder's output dimension + encoder_dim = args.encoder_embed_dim + else: + raise ValueError( + "Must specify --mean-pool-gating-network-encoder-dim" + ) + + if getattr(args, "mean_pool_gating_network_dropout", None): + dropout = args.mean_pool_gating_network_dropout + elif getattr(args, "dropout", None): + dropout = args.dropout + else: + raise ValueError("Must specify --mean-pool-gating-network-dropout") + + model.gating_network = MeanPoolGatingNetwork( + encoder_dim, + args.num_experts, + dropout, + ) + else: + raise ValueError( + "translation_moe task with learned prior requires the model to " + "have a gating network; try using --mean-pool-gating-network" + ) + return model + + def expert_index(self, i): + return i + self.tgt_dict.index("<expert_0>") + + def _get_loss(self, sample, model, criterion): + assert hasattr( + criterion, "compute_loss" + ), "translation_moe task requires the criterion to implement the compute_loss() method" + + k = self.args.num_experts + bsz = sample["target"].size(0) + + def get_lprob_y(encoder_out, prev_output_tokens_k): + net_output = model.decoder( + prev_output_tokens=prev_output_tokens_k, + encoder_out=encoder_out, + ) + loss, _ = criterion.compute_loss(model, net_output, sample, reduce=False) + loss = loss.view(bsz, -1) + return -loss.sum(dim=1, keepdim=True) # -> B x 1 + + def get_lprob_yz(winners=None): + encoder_out = model.encoder( + src_tokens=sample["net_input"]["src_tokens"], + src_lengths=sample["net_input"]["src_lengths"], + ) + + if winners is None: + lprob_y = [] + for i in range(k): + prev_output_tokens_k = sample["net_input"][ + "prev_output_tokens" + ].clone() + assert not prev_output_tokens_k.requires_grad + prev_output_tokens_k[:, 0] = self.expert_index(i) + lprob_y.append(get_lprob_y(encoder_out, prev_output_tokens_k)) + lprob_y = torch.cat(lprob_y, dim=1) # -> B x K + else: + prev_output_tokens_k = sample["net_input"]["prev_output_tokens"].clone() + prev_output_tokens_k[:, 0] = self.expert_index(winners) + lprob_y = get_lprob_y(encoder_out, prev_output_tokens_k) # -> B + + if self.uniform_prior: + lprob_yz = lprob_y + else: + lprob_z = model.gating_network(encoder_out) # B x K + if winners is not None: + lprob_z = lprob_z.gather(dim=1, index=winners.unsqueeze(-1)) + lprob_yz = lprob_y + lprob_z.type_as(lprob_y) # B x K + + return lprob_yz + + # compute responsibilities without dropout + with utils.model_eval(model): # disable dropout + with torch.no_grad(): # disable autograd + lprob_yz = get_lprob_yz() # B x K + prob_z_xy = torch.nn.functional.softmax(lprob_yz, dim=1) + assert not prob_z_xy.requires_grad + + # compute loss with dropout + if self.hard_selection: + winners = prob_z_xy.max(dim=1)[1] + loss = -get_lprob_yz(winners) + else: + lprob_yz = get_lprob_yz() # B x K + loss = -LogSumExpMoE.apply(lprob_yz, prob_z_xy, 1) + + loss = loss.sum() + sample_size = ( + sample["target"].size(0) if self.args.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": utils.item(loss.data), + "ntokens": sample["ntokens"], + "nsentences": bsz, + "sample_size": sample_size, + "posterior": prob_z_xy.float().sum(dim=0).cpu(), + } + return loss, sample_size, logging_output + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + model.train() + loss, sample_size, logging_output = self._get_loss(sample, model, criterion) + if ignore_grad: + loss *= 0 + optimizer.backward(loss) + return loss, sample_size, logging_output + + def valid_step(self, sample, model, criterion): + model.eval() + with torch.no_grad(): + loss, sample_size, logging_output = self._get_loss(sample, model, criterion) + return loss, sample_size, logging_output + + def inference_step( + self, + generator, + models, + sample, + prefix_tokens=None, + expert=None, + constraints=None, + ): + expert = expert or self.args.gen_expert + with torch.no_grad(): + return generator.generate( + models, + sample, + prefix_tokens=prefix_tokens, + constraints=constraints, + bos_token=self.expert_index(expert), + ) + + def reduce_metrics(self, logging_outputs, criterion): + super().reduce_metrics(logging_outputs, criterion) + metrics.log_scalar( + "posterior", + sum(log["posterior"] for log in logging_outputs if "posterior" in log), + ) diff --git a/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/README.md b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/README.md new file mode 100644 index 00000000..809a58e4 --- /dev/null +++ b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/README.md @@ -0,0 +1,126 @@ +# Unsupervised Quality Estimation for Neural Machine Translation (Fomicheva et al., 2020) + +This page includes instructions for reproducing results from the paper [Unsupervised Quality Estimation for Neural +Machine Translation (Fomicheva et al., 2020)](https://arxiv.org/abs/2005.10608) + +## Requirements: + +* mosesdecoder: https://github.com/moses-smt/mosesdecoder +* subword-nmt: https://github.com/rsennrich/subword-nmt +* flores: https://github.com/facebookresearch/flores + +## Download Models and Test Data + +Download translation models and test data from [MLQE dataset repository](https://github.com/facebookresearch/mlqe). + +## Set up: + +Given a testset consisting of source sentences and reference translations: + +* `SRC_LANG`: source language +* `TGT_LANG`: target language +* `INPUT`: input prefix, such that the file `$INPUT.$SRC_LANG` contains source sentences and `$INPUT.$TGT_LANG` +contains the reference sentences +* `OUTPUT_DIR`: output path to store results +* `MOSES_DECODER`: path to mosesdecoder installation +* `BPE_ROOT`: path to subword-nmt installation +* `BPE`: path to BPE model +* `MODEL_DIR`: directory containing the NMT model `.pt` file as well as the source and target vocabularies. +* `TMP`: directory for intermediate temporary files +* `GPU`: if translating with GPU, id of the GPU to use for inference +* `DROPOUT_N`: number of stochastic forward passes + +`$DROPOUT_N` is set to 30 in the experiments reported in the paper. However, we observed that increasing it beyond 10 +does not bring substantial improvements. + +## Translate the data using standard decoding + +Preprocess the input data: +``` +for LANG in $SRC_LANG $TGT_LANG; do + perl $MOSES_DECODER/scripts/tokenizer/tokenizer.perl -threads 80 -a -l $LANG < $INPUT.$LANG > $TMP/preprocessed.tok.$LANG + python $BPE_ROOT/apply_bpe.py -c ${BPE} < $TMP/preprocessed.tok.$LANG > $TMP/preprocessed.tok.bpe.$LANG +done +``` + +Binarize the data for faster translation: + +``` +fairseq-preprocess --srcdict $MODEL_DIR/dict.$SRC_LANG.txt --tgtdict $MODEL_DIR/dict.$TGT_LANG.txt +--source-lang ${SRC_LANG} --target-lang ${TGT_LANG} --testpref $TMP/preprocessed.tok.bpe --destdir $TMP/bin --workers 4 +``` + +Translate + +``` +CUDA_VISIBLE_DEVICES=$GPU fairseq-generate $TMP/bin --path ${MODEL_DIR}/${SRC_LANG}-${TGT_LANG}.pt --beam 5 +--source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --unkpen 5 > $TMP/fairseq.out +grep ^H $TMP/fairseq.out | cut -f3- > $TMP/mt.out +``` + +Post-process + +``` +sed -r 's/(@@ )| (@@ ?$)//g' < $TMP/mt.out | perl $MOSES_DECODER/scripts/tokenizer/detokenizer.perl +-l $TGT_LANG > $OUTPUT_DIR/mt.out +``` + +## Produce uncertainty estimates + +### Scoring + +Make temporary files to store the translations repeated N times. + +``` +python ${SCRIPTS}/scripts/uncertainty/repeat_lines.py -i $TMP/preprocessed.tok.bpe.$SRC_LANG -n $DROPOUT_N +-o $TMP/repeated.$SRC_LANG +python ${SCRIPTS}/scripts/uncertainty/repeat_lines.py -i $TMP/mt.out -n $DROPOUT_N -o $TMP/repeated.$TGT_LANG + +fairseq-preprocess --srcdict ${MODEL_DIR}/dict.${SRC_LANG}.txt $TGT_DIC --source-lang ${SRC_LANG} +--target-lang ${TGT_LANG} --testpref ${TMP}/repeated --destdir ${TMP}/bin-repeated +``` + +Produce model scores for the generated translations using `--retain-dropout` option to apply dropout at inference time: + +``` +CUDA_VISIBLE_DEVICES=${GPU} fairseq-generate ${TMP}/bin-repeated --path ${MODEL_DIR}/${LP}.pt --beam 5 + --source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --unkpen 5 --score-reference --retain-dropout + --retain-dropout-modules TransformerModel TransformerEncoder TransformerDecoder TransformerEncoderLayer + TransformerDecoderLayer --seed 46 > $TMP/dropout.scoring.out + +grep ^H $TMP/dropout.scoring.out | cut -f2- > $TMP/dropout.scores + +``` + +Use `--retain-dropout-modules` to specify the modules. By default, dropout is applied in the same places +as for training. + +Compute the mean of the resulting output distribution: + +``` +python $SCRIPTS/scripts/uncertainty/aggregate_scores.py -i $TMP/dropout.scores -o $OUTPUT_DIR/dropout.scores.mean +-n $DROPOUT_N +``` + +### Generation + +Produce multiple translation hypotheses for the same source using `--retain-dropout` option: + +``` +CUDA_VISIBLE_DEVICES=${GPU} fairseq-generate ${TMP}/bin-repeated --path ${MODEL_DIR}/${LP}.pt + --beam 5 --source-lang $SRC_LANG --target-lang $TGT_LANG --no-progress-bar --retain-dropout + --unkpen 5 --retain-dropout-modules TransformerModel TransformerEncoder TransformerDecoder +TransformerEncoderLayer TransformerDecoderLayer --seed 46 > $TMP/dropout.generation.out + +grep ^H $TMP/dropout.generation.out | cut -f3- > $TMP/dropout.hypotheses_ + +sed -r 's/(@@ )| (@@ ?$)//g' < $TMP/dropout.hypotheses_ | perl $MOSES_DECODER/scripts/tokenizer/detokenizer.perl +-l $TGT_LANG > $TMP/dropout.hypotheses +``` + +Compute similarity between multiple hypotheses corresponding to the same source sentence using Meteor +evaluation metric: +``` +python meteor.py -i $TMP/dropout.hypotheses -m <path_to_meteor_installation> -n $DROPOUT_N -o +$OUTPUT_DIR/dropout.gen.sim.meteor +``` diff --git a/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/aggregate_scores.py b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/aggregate_scores.py new file mode 100644 index 00000000..66d50d07 --- /dev/null +++ b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/aggregate_scores.py @@ -0,0 +1,41 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import sys + +import numpy as np + + +aggregate_funcs = { + "std": np.std, + "var": np.var, + "median": np.median, + "mean": np.mean, + "min": np.min, + "max": np.max, +} + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--input_file", required=True, type=str) + parser.add_argument("-n", "--repeat_times", required=True, type=int) + parser.add_argument("-o", "--output_file", required=False) + parser.add_argument("-f", "--func", required=False, default="mean") + args = parser.parse_args() + + stream = open(args.output_file, "w") if args.output_file else sys.stdout + + segment_scores = [] + for line in open(args.input_file): + segment_scores.append(float(line.strip())) + if len(segment_scores) == args.repeat_times: + stream.write("{}\n".format(aggregate_funcs[args.func](segment_scores))) + segment_scores = [] + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/meteor.py b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/meteor.py new file mode 100644 index 00000000..4a214e79 --- /dev/null +++ b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/meteor.py @@ -0,0 +1,109 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import math +import os +import subprocess +import sys +import tempfile +from collections import defaultdict +from itertools import combinations + + +def read_translations(path, n_repeats): + segment_counter = 0 + segment_translations = [] + translations = defaultdict(list) + for line in open(path): + segment_translations.append(" ".join(line.split())) + if len(segment_translations) == n_repeats: + translations[segment_counter] = segment_translations + segment_translations = [] + segment_counter += 1 + return translations + + +def generate_input(translations, n_repeats): + _, ref_path = tempfile.mkstemp() + _, mt_path = tempfile.mkstemp() + ref_fh = open(ref_path, "w") + mt_fh = open(mt_path, "w") + for segid in sorted(translations.keys()): + assert len(translations[segid]) == n_repeats + indexes = combinations(range(n_repeats), 2) + for idx1, idx2 in indexes: + mt_fh.write(translations[segid][idx1].strip() + "\n") + ref_fh.write(translations[segid][idx2].strip() + "\n") + sys.stderr.write("\nSaved translations to %s and %s" % (ref_path, mt_path)) + return ref_path, mt_path + + +def run_meteor(ref_path, mt_path, metric_path, lang="en"): + _, out_path = tempfile.mkstemp() + subprocess.call( + [ + "java", + "-Xmx2G", + "-jar", + metric_path, + mt_path, + ref_path, + "-p", + "0.5 0.2 0.6 0.75", # default parameters, only changed alpha to give equal weight to P and R + "-norm", + "-l", + lang, + ], + stdout=open(out_path, "w"), + ) + os.remove(ref_path) + os.remove(mt_path) + sys.stderr.write("\nSaved Meteor output to %s" % out_path) + return out_path + + +def read_output(meteor_output_path, n_repeats): + n_combinations = math.factorial(n_repeats) / ( + math.factorial(2) * math.factorial(n_repeats - 2) + ) + raw_scores = [] + average_scores = [] + for line in open(meteor_output_path): + if not line.startswith("Segment "): + continue + score = float(line.strip().split("\t")[1]) + raw_scores.append(score) + if len(raw_scores) == n_combinations: + average_scores.append(sum(raw_scores) / n_combinations) + raw_scores = [] + os.remove(meteor_output_path) + return average_scores + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--input") + parser.add_argument("-n", "--repeat_times", type=int) + parser.add_argument("-m", "--meteor") + parser.add_argument("-o", "--output") + args = parser.parse_args() + + translations = read_translations(args.infile, args.repetitions) + sys.stderr.write("\nGenerating input for Meteor...") + ref_path, mt_path = generate_input(translations, args.repetitions) + sys.stderr.write("\nRunning Meteor...") + out_path = run_meteor(ref_path, mt_path, args.meteor) + sys.stderr.write("\nReading output...") + scores = read_output(out_path, args.repetitions) + sys.stderr.write("\nWriting results...") + with open(args.output, "w") as o: + for scr in scores: + o.write("{}\n".format(scr)) + o.close() + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/repeat_lines.py b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/repeat_lines.py new file mode 100644 index 00000000..5a04851a --- /dev/null +++ b/fairseq-tools/fairseq/examples/unsupervised_quality_estimation/repeat_lines.py @@ -0,0 +1,28 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import sys + + +def _normalize_spaces(line): + return " ".join(line.split()) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-i", "--input_file", required=True, type=str) + parser.add_argument("-n", "--repeat_times", required=True, type=int) + parser.add_argument("-o", "--output_file", required=False, type=str) + args = parser.parse_args() + stream = open(args.output_file, "w") if args.output_file else sys.stdout + + for line in open(args.input_file): + for _ in range(args.repeat_times): + stream.write(_normalize_spaces(line) + "\n") + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/wav2vec/README.md b/fairseq-tools/fairseq/examples/wav2vec/README.md new file mode 100644 index 00000000..518d8f86 --- /dev/null +++ b/fairseq-tools/fairseq/examples/wav2vec/README.md @@ -0,0 +1,260 @@ +# wav2vec 2.0 + +wav2vec 2.0 learns speech representations on unlabeled data as described in [wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations (Baevski et al., 2020)](https://arxiv.org/abs/2006.11477). + +## Pre-trained models + +Model | Finetuning split | Dataset | Model +|---|---|---|--- +Wav2Vec 2.0 Base | No finetuning | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_small.pt) +Wav2Vec 2.0 Base | 10 minutes | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_small_10m.pt) +Wav2Vec 2.0 Base | 100 hours | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_small_100h.pt) +Wav2Vec 2.0 Base | 960 hours | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_small_960h.pt) +Wav2Vec 2.0 Large | No finetuning | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/libri960_big.pt) +Wav2Vec 2.0 Large | 10 minutes | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_big_10m.pt) +Wav2Vec 2.0 Large | 100 hours | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_big_100h.pt) +Wav2Vec 2.0 Large | 960 hours | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_big_960h.pt) +Wav2Vec 2.0 Large (LV-60) | No finetuning | [Libri-Light](https://github.com/facebookresearch/libri-light) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox.pt) +Wav2Vec 2.0 Large (LV-60) | 10 minutes | [Libri-Light](https://github.com/facebookresearch/libri-light) + [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox_10m.pt) +Wav2Vec 2.0 Large (LV-60) | 100 hours | [Libri-Light](https://github.com/facebookresearch/libri-light) + [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_vox_100h.pt) +Wav2Vec 2.0 Large (LV-60) | 960 hours | [Libri-Light](https://github.com/facebookresearch/libri-light) + [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec2_vox_960h.pt) + +## Training a new model with the CLI tools + +Given a directory containing wav files to be used for pretraining (we recommend splitting each file into separate file 10 to 30 seconds in length) + +### Prepare training data manifest: + +First, install the `soundfile` library: +```shell script +pip install soundfile +``` + +Next, run: + +```shell script +$ python examples/wav2vec/wav2vec_manifest.py /path/to/waves --dest /manifest/path --ext $ext --valid-percent $valid +``` + +$ext should be set to flac, wav, or whatever format your dataset happens to use that soundfile can read. + +$valid should be set to some reasonable percentage (like 0.01) of training data to use for validation. +To use a pre-defined validation set (like dev-other from librispeech), set to it 0 and then overwrite valid.tsv with a +separately pre-processed manifest file. + +### Train a wav2vec 2.0 base model: + +This configuration was used for the base model trained on the Librispeech dataset in the wav2vec 2.0 paper + +Note that this was tested with pytorch 1.4.0 and the input is expected to be single channel, sampled at 16 kHz + +```shell script +$ python train.py --distributed-world-size 64 --distributed-port $PORT /manifest/path \ +--save-dir /model/path --fp16 --num-workers 6 --task audio_pretraining --criterion wav2vec --arch wav2vec2 \ +--log-keys '["prob_perplexity","code_perplexity","temp"]' --quantize-targets --extractor-mode default \ +--conv-feature-layers '[(512, 10, 5)] + [(512, 3, 2)] * 4 + [(512,2,2)] * 2' --final-dim 256 --latent-vars 320 \ +--latent-groups 2 --latent-temp '(2,0.5,0.999995)' --infonce --optimizer adam \ +--adam-betas '(0.9,0.98)' --adam-eps 1e-06 --lr-scheduler polynomial_decay --total-num-update 400000 \ +--lr 0.0005 --warmup-updates 32000 --mask-length 10 --mask-prob 0.65 --mask-selection static --mask-other 0 \ +--encoder-layerdrop 0.05 --dropout-input 0.1 --dropout-features 0.1 --feature-grad-mult 0.1 \ +--loss-weights '[0.1, 10]' --conv-pos 128 --conv-pos-groups 16 --num-negatives 100 --cross-sample-negatives 0 \ +--max-sample-size 250000 --min-sample-size 32000 --dropout 0.1 --attention-dropout 0.1 --weight-decay 0.01 \ +--max-tokens 1400000 --max-update 400000 --skip-invalid-size-inputs-valid-test --ddp-backend no_c10d +``` + +Note: you can simulate 64 GPUs by using k GPUs and setting --update-freq 64/k + +### Train a wav2vec 2.0 large model: + +This configuration was used for the large model trained on the Libri-light dataset in the wav2vec 2.0 paper + +```shell script +$ python train.py --distributed-world-size 128 --distributed-port $PORT /manifest/path \ +--save-dir /model/path --fp16 --num-workers 6 --task audio_pretraining --criterion wav2vec --arch wav2vec2 \ +--log-keys '["prob_perplexity","code_perplexity","temp"]' --quantize-targets --extractor-mode default \ +--conv-feature-layers '[(512, 10, 5)] + [(512, 3, 2)] * 4 + [(512,2,2)] * 2' --final-dim 768 --latent-vars 320 \ +--latent-groups 2 --latent-temp '(2.0,0.1,0.999995)' --infonce --optimizer adam \ +--adam-betas '(0.9,0.98)' --adam-eps 1e-06 --lr-scheduler polynomial_decay --total-num-update 600000 \ +--lr 0.0003 --warmup-updates 32000 --mask-length 10 --mask-prob 0.65 --mask-selection static --mask-other 0 \ +--encoder-layerdrop 0.0 --dropout-input 0.1 --dropout-features 0.1 --feature-grad-mult 0.03 \ +--loss-weights '[0.1, 10]' --conv-pos 128 --conv-pos-groups 16 --encoder-layers 24 --encoder-embed-dim 1024 \ +--encoder-ffn-embed-dim 4096 --encoder-attention-heads 16 --num-negatives 100 --cross-sample-negatives 0 \ +--max-sample-size 320000 --min-sample-size 32000 --dropout 0.0 --attention-dropout 0.1 --weight-decay 0.01 \ +--max-tokens 1200000 --max-update 600000 --skip-invalid-size-inputs-valid-test --ddp-backend no_c10d +``` + +Note: you can simulate 128 GPUs by using k GPUs and setting --update-freq 128/k + +### Fine-tune a pre-trained model with CTC: + +Fine-tuning a model requires parallel audio and labels file, as well as a vocabulary file in fairseq format. +A letter vocabulary can be downloaded [here](https://dl.fbaipublicfiles.com/fairseq/wav2vec/dict.ltr.txt). +An example [script](libri_labels.py) that generates labels for the Librispeech dataset from the tsv file produced by wav2vec_manifest.py can be used as follows: + +```shell script +split=train +$ python libri_labels.py /path/to/tsv --output-dir /output/dir --output-name $split +``` + +Fine-tuning on 100h of Librispeech with letter targets: +```shell script +valid_subset=dev_other +python train.py --distributed-world-size 24 --distributed-port $PORT /path/to/training_data --save-dir /model/path --fp16 \ +--wer-args '("/path/to/lm/4-gram.bin","/path/to/lexicon",2,-1)' \ +--post-process letter --valid-subset $valid_subset --no-epoch-checkpoints --best-checkpoint-metric wer --num-workers 4 \ +--max-update 80000 --sentence-avg --task audio_pretraining --arch wav2vec_ctc --w2v-path /path/to/pretrained/model \ +--labels ltr --apply-mask --mask-selection static --mask-other 0 --mask-length 10 --mask-prob 0.5 --layerdrop 0.1 \ +--mask-channel-selection static --mask-channel-other 0 --mask-channel-length 64 --mask-channel-prob 0.5 --zero-infinity \ +--feature-grad-mult 0.0 --freeze-finetune-updates 10000 --validate-after-updates 10000 --optimizer adam \ +--adam-betas '(0.9, 0.98)' --adam-eps 1e-08 --lr 2e-05 --lr-scheduler tri_stage --warmup-steps 8000 --hold-steps 32000 \ +--decay-steps 40000 --final-lr-scale 0.05 --final-dropout 0.0 --dropout 0.0 --activation-dropout 0.1 --criterion ctc \ +--attention-dropout 0.0 --max-tokens 1280000 --seed 2337 --log-format json --log-interval 500 --ddp-backend no_c10d +``` + +Note: you can simulate 24 GPUs by using k GPUs and setting --update-freq 24/k + +Decoding with a language model during training requires wav2letter [python bindings](https://github.com/facebookresearch/wav2letter/wiki/Building-Python-bindings). +Alternatively, simply omit the --wer-args flag. + +For hyper-parameters to fine-tune other Librispeech splits (10 minutes, 1 hour, etc) please refer to the table in Appendix B in the wav2vec 2.0 paper. +The main changes to make are adjusting --max-update, and then adjusting --warmup-steps, --hold-steps, and --decay steps so that they use 0.1/0.4/0.5 of max-update respectively. You then need to adjust --mask-prob and --mask-channel-prob. This should be set to the mask-length * x where x is the number in the table and mask-length is what you use for --mask-length (10 in this example. Use --mask-channel-length value for --mask-channel-prob). + +For example, for 10 hours, we see in the paper that timestep mask prob should be 0.065, so we set --mask-prob to 10* 0.065 = 0.65. channel mask prob is 0.004, so we set it to 64 * 0.004 = 0.256. then we set --max-updates to 20000 and change --warmup-steps to 20000 * 0.1 = 2000, --hold-steps to 8000 and --decay-steps to 10000. + +### Evaluating a CTC model: + +Evaluating a CTC model with a language model requires wav2letter [python bindings](https://github.com/facebookresearch/wav2letter/wiki/Building-Python-bindings) to be installed. + +Fairseq transformer language model used in the wav2vec 2.0 paper can be obtained from the [wav2letter model repository](https://github.com/facebookresearch/wav2letter/tree/master/recipes/sota/2019). +Be sure to upper-case the language model vocab after downloading it. + +Letter dictionary for pre-trained models can be found [here](https://dl.fbaipublicfiles.com/fairseq/wav2vec/dict.ltr.txt). + +Next, run the evaluation command: + +```shell script +$subset=dev_other +python examples/speech_recognition/infer.py /checkpoint/abaevski/data/speech/libri/10h/wav2vec/raw --task audio_pretraining \ +--nbest 1 --path /path/to/model --gen-subset $subset --results-path /path/to/save/results/for/sclite --w2l-decoder kenlm \ +--lm-model /path/to/kenlm.bin --lm-weight 2 --word-score -1 --sil-weight 0 --criterion ctc --labels ltr --max-tokens 4000000 \ +--post-process letter +``` + +To get raw numbers, use --w2l-decoder viterbi and omit the lexicon. To use the transformer language model, use --w2l-decoder fairseqlm. + +# wav2vec + +Example to train a wav2vec model as described in [wav2vec: Unsupervised Pre-training for Speech Recognition (Schneider et al., 2019)](https://arxiv.org/abs/1904.05862). + +## Pre-trained models + +Description | Dataset | Model +---|---|--- +Wav2Vec large | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/wav2vec_large.pt) + +#### Example usage: +```python +import torch +from fairseq.models.wav2vec import Wav2VecModel + +cp = torch.load('/path/to/wav2vec.pt') +model = Wav2VecModel.build_model(cp['args'], task=None) +model.load_state_dict(cp['model']) +model.eval() + +wav_input_16khz = torch.randn(1,10000) +z = model.feature_extractor(wav_input_16khz) +c = model.feature_aggregator(z) +``` + +## Training a new model with the CLI tools + +Given a directory containing wav files to be used for pretraining (we recommend splitting each file into separate files 10 to 30 seconds in length) + +### Prepare training data manifest: + +``` +$ python examples/wav2vec/wav2vec_manifest.py /path/to/waves --dest /manifest/path --ext wav +``` + +### Train a wav2vec model: + +``` +$ python train.py /manifest/path --save-dir /model/path --num-workers 6 --fp16 --max-update 400000 --save-interval 1 --no-epoch-checkpoints \ +--arch wav2vec --task audio_pretraining --lr 1e-06 --min-lr 1e-09 --optimizer adam --max-lr 0.005 --lr-scheduler cosine \ +--conv-feature-layers [(512, 10, 5), (512, 8, 4), (512, 4, 2), (512, 4, 2), (512, 4, 2), (512, 1, 1), (512, 1, 1)] \ +--conv-aggregator-layers [(512, 2, 1), (512, 3, 1), (512, 4, 1), (512, 5, 1), (512, 6, 1), (512, 7, 1), (512, 8, 1), (512, 9, 1), (512, 10, 1), (512, 11, 1), (512, 12, 1), (512, 13, 1)] \ +--skip-connections-agg --residual-scale 0.5 --log-compression --warmup-updates 500 --warmup-init-lr 1e-07 --criterion wav2vec --num-negatives 10 \ +--max-sample-size 150000 --max-tokens 1500000 --skip-invalid-size-inputs-valid-test +``` + +### Extract embeddings from the downstream task data: + +``` +$ PYTHONPATH=/path/to/fairseq python examples/wav2vec/wav2vec_featurize.py --input /path/to/task/waves --output /path/to/output \ +--model /model/path/checkpoint_best.pt --split train valid test +``` + +# vq-wav2vec + +Example to train a vq-wav2vec model as described in [vq-wav2vec: Self-Supervised Learning of Discrete Speech Representations (Baevski et al., 2019)](https://arxiv.org/abs/1910.05453). + +These models are also used in [Effectiveness of self-supervised pre-training for speech recognition (Baevski et al., 2019)](https://arxiv.org/abs/1911.03912). + +## Pre-trained models + +Description | Dataset | Model +---|---|--- +vq-wav2vec Gumbel | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/vq-wav2vec.pt) +vq-wav2vec K-means | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/vq-wav2vec_kmeans.pt) +Roberta on K-means codes | [Librispeech](http://www.openslr.org/12) | [download](https://dl.fbaipublicfiles.com/fairseq/wav2vec/bert_kmeans.tar) + +#### Example usage: +```python +import torch +from fairseq.models.wav2vec import Wav2VecModel + +cp = torch.load('/path/to/vq-wav2vec.pt') +model = Wav2VecModel.build_model(cp['args'], task=None) +model.load_state_dict(cp['model']) +model.eval() + +wav_input_16khz = torch.randn(1,10000) +z = model.feature_extractor(wav_input_16khz) +_, idxs = model.vector_quantizer.forward_idx(z) +print(idxs.shape) # output: torch.Size([1, 60, 2]), 60 timesteps with 2 indexes corresponding to 2 groups in the model +``` + +## Training a new model with the CLI tools + +Given a directory containing wav files to be used for pretraining (we recommend splitting each file into separate file 10 to 30 seconds in length) + +### Prepare training data manifest: + +``` +$ python examples/wav2vec/wav2vec_manifest.py /path/to/waves --dest /manifest/path --ext wav +``` + +### Train a gumbel vq-wav2vec model: + +``` +$ python train.py /manifest/path --save-dir /model/path --num-workers 6 --fp16 --max-update 400000 \ +--save-interval 1 --no-epoch-checkpoints --arch wav2vec --task audio_pretraining --lr 1e-06 --min-lr 1e-09 \ +--optimizer adam --max-lr 1e-05 --lr-scheduler cosine \ +--conv-feature-layers [(512, 10, 5), (512, 8, 4), (512, 4, 2), (512, 4, 2), (512, 4, 2), (512, 1, 1), (512, 1, 1), (512, 1, 1)] \ +--conv-aggregator-layers [(512, 2, 1), (512, 3, 1), (512, 4, 1), (512, 5, 1), (512, 6, 1), (512, 7, 1), (512, 8, 1), (512, 9, 1), (512, 10, 1), (512, 11, 1), (512, 12, 1), (512, 13, 1)] \ +--activation gelu --offset auto --skip-connections-agg --residual-scale 0.5 \ +--log-keys ["prob_perplexity","code_perplexity","temp"] --vq-type gumbel --vq-groups 2 --vq-depth 2 \ +--combine-groups --vq-vars 320 --vq-temp (2,0.5,0.999995) --prediction-steps 12 --warmup-updates 1000 \ +--warmup-init-lr 1e-07 --criterion wav2vec --num-negatives 10 --max-sample-size 150000 \ +--max-tokens 300000 --cross-sample-negatives 0 --update-freq 1 --seed 2 --skip-invalid-size-inputs-valid-test +``` + +for k-means training, set vq-type with "kmeans" and add --loss-weights [1] argument. Pre-trained models were trained on 16 GPUs. + +### Tokenize audio data (e.g. for BERT training): + +``` +$ PYTHONPATH=/path/to/fairseq python examples/wav2vec/vq-wav2vec_featurize.py --data-dir /manifest/path --output-dir /path/to/output \ +--checkpoint /model/path/checkpoint_best.pt --split train valid test --extension tsv +``` diff --git a/fairseq-tools/fairseq/examples/wav2vec/libri_labels.py b/fairseq-tools/fairseq/examples/wav2vec/libri_labels.py new file mode 100644 index 00000000..3fa1ec4c --- /dev/null +++ b/fairseq-tools/fairseq/examples/wav2vec/libri_labels.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Helper script to pre-compute embeddings for a wav2letter++ dataset +""" + +import argparse +import os + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("tsv") + parser.add_argument("--output-dir", required=True) + parser.add_argument("--output-name", required=True) + args = parser.parse_args() + + os.makedirs(args.output_dir, exist_ok=True) + + transcriptions = {} + + with open(args.tsv, "r") as tsv, open( + os.path.join(args.output_dir, args.output_name + ".ltr"), "w" + ) as ltr_out, open( + os.path.join(args.output_dir, args.output_name + ".wrd"), "w" + ) as wrd_out: + root = next(tsv).strip() + for line in tsv: + line = line.strip() + dir = os.path.dirname(line) + if dir not in transcriptions: + parts = dir.split(os.path.sep) + trans_path = f"{parts[-2]}-{parts[-1]}.trans.txt" + path = os.path.join(root, dir, trans_path) + assert os.path.exists(path) + texts = {} + with open(path, "r") as trans_f: + for tline in trans_f: + items = tline.strip().split() + texts[items[0]] = " ".join(items[1:]) + transcriptions[dir] = texts + part = os.path.basename(line).split(".")[0] + assert part in transcriptions[dir] + print(transcriptions[dir][part], file=wrd_out) + print( + " ".join(list(transcriptions[dir][part].replace(" ", "|"))) + " |", + file=ltr_out, + ) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/examples/wav2vec/vq-wav2vec_featurize.py b/fairseq-tools/fairseq/examples/wav2vec/vq-wav2vec_featurize.py new file mode 100644 index 00000000..baabc1d3 --- /dev/null +++ b/fairseq-tools/fairseq/examples/wav2vec/vq-wav2vec_featurize.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Helper script to pre-compute embeddings for a wav2letter++ dataset +""" + +import argparse +import glob +import os +import os.path as osp +import pprint + +import soundfile as sf +import torch +import tqdm +from fairseq.models.wav2vec.wav2vec import Wav2VecModel +from torch import nn +from torch.utils.data import DataLoader + + +try: + import tqdm +except: + print("Install tqdm to use --log-format=tqdm") + + +class FilesDataset: + def __init__(self, files, labels): + self.files = files + if labels and osp.exists(labels): + with open(labels, "r") as lbl_f: + self.labels = [line.rstrip() for line in lbl_f] + else: + self.labels = labels + + def __len__(self): + return len(self.files) + + def __getitem__(self, index): + fname = self.files[index] + + wav, sr = sf.read(fname) + assert sr == 16000 + + wav = torch.from_numpy(wav).float() + lbls = None + if self.labels: + if isinstance(self.labels, str): + lbl_file = osp.splitext(fname)[0] + "." + self.labels + with open(lbl_file, "r") as lblf: + lbls = lblf.readline() + assert lbls is not None + else: + lbls = self.labels[index] + return wav, lbls + + def collate(self, batch): + return batch + + +class ArgTypes: + @staticmethod + def existing_path(arg): + arg = str(arg) + assert osp.exists(arg), f"File {arg} does not exist" + return arg + + @staticmethod + def mkdir(arg): + arg = str(arg) + os.makedirs(arg, exist_ok=True) + return arg + + +class DatasetWriter: + def __init__(self): + + self.args = self.load_config() + pprint.pprint(self.args.__dict__) + + self.model = self.load_model() + + def __getattr__(self, attr): + return getattr(self.args, attr) + + def read_manifest(self, fname): + + with open(fname, "r") as fp: + lines = fp.read().split("\n") + root = lines.pop(0).strip() + fnames = [ + osp.join(root, line.split("\t")[0]) for line in lines if len(line) > 0 + ] + + return fnames + + def process_splits(self): + + if self.args.shard is not None or self.args.num_shards is not None: + assert self.args.shard is not None and self.args.num_shards is not None + + for split in self.splits: + print(split) + + if self.extension == "tsv": + datadir = osp.join(self.data_dir, f"{split}.{self.extension}") + print("Reading manifest file: ", datadir) + files = self.read_manifest(datadir) + else: + datadir = osp.join(self.data_dir, split, f"**/*.{self.extension}") + files = glob.glob(datadir, recursive=True) + + assert len(files) > 0 + + if self.args.shard is not None: + files = files[self.args.shard :: self.args.num_shards] + + lbls = [] + with open(self.data_file(split), "w") as srcf: + for line, lbl in self.iterate(files): + print(line, file=srcf) + if self.args.labels: + lbls.append(lbl + "\n") + + if self.args.labels: + assert all(a is not None for a in lbls) + with open(self.lbl_file(split), "w") as lblf: + lblf.writelines(lbls) + + def iterate(self, files): + + data = self.load_data(files) + for samples in tqdm.tqdm(data, total=len(files) // 32): + + for wav, lbl in samples: + x = wav.unsqueeze(0).float().cuda() + + div = 1 + while x.size(-1) // div > self.args.max_size: + div += 1 + + xs = x.chunk(div, dim=-1) + + result = [] + for x in xs: + torch.cuda.empty_cache() + x = self.model.feature_extractor(x) + if self.quantize_location == "encoder": + with torch.no_grad(): + _, idx = self.model.vector_quantizer.forward_idx(x) + idx = idx.squeeze(0).cpu() + else: + with torch.no_grad(): + z = self.model.feature_aggregator(x) + _, idx = self.model.vector_quantizer.forward_idx(z) + idx = idx.squeeze(0).cpu() + result.append(idx) + + idx = torch.cat(result, dim=0) + yield " ".join("-".join(map(str, a.tolist())) for a in idx), lbl + + def lbl_file(self, name): + shard_part = "" if self.args.shard is None else f".{self.args.shard}" + return osp.join(self.output_dir, f"{name}.lbl{shard_part}") + + def data_file(self, name): + shard_part = "" if self.args.shard is None else f".{self.args.shard}" + return osp.join(self.output_dir, f"{name}.src{shard_part}") + + def var_file(self): + return osp.join(self.output_dir, f"vars.pt") + + def load_config(self): + + parser = argparse.ArgumentParser("Vector Quantized wav2vec features") + + # Model Arguments + parser.add_argument("--checkpoint", type=ArgTypes.existing_path, required=True) + parser.add_argument("--data-parallel", action="store_true") + + # Output Arguments + parser.add_argument("--output-dir", type=ArgTypes.mkdir, required=True) + + # Data Arguments + parser.add_argument("--data-dir", type=ArgTypes.existing_path, required=True) + parser.add_argument("--splits", type=str, nargs="+", required=True) + parser.add_argument("--extension", type=str, required=True) + parser.add_argument("--labels", type=str, required=False) + + parser.add_argument("--shard", type=int, default=None) + parser.add_argument("--num-shards", type=int, default=None) + parser.add_argument("--max-size", type=int, default=1300000) + + # Logger Arguments + parser.add_argument( + "--log-format", type=str, choices=["none", "simple", "tqdm"] + ) + + return parser.parse_args() + + def load_data(self, fnames): + + dataset = FilesDataset(fnames, self.args.labels) + loader = DataLoader( + dataset, batch_size=32, collate_fn=dataset.collate, num_workers=8 + ) + return loader + + def load_model(self): + cp = torch.load(self.checkpoint, map_location=lambda x, _: x) + + model = Wav2VecModel.build_model(cp["args"], None) + + self.quantize_location = getattr(cp["args"], "vq", "encoder") + + model.load_state_dict(cp["model"]) + model.eval().float() + model.cuda() + + if self.data_parallel: + model = nn.DataParallel(model) + + return model + + def __call__(self): + + self.process_splits() + + if hasattr(self.model.feature_extractor, "vars") and ( + self.args.shard is None or self.args.shard == 0 + ): + vars = ( + self.model.feature_extractor.vars.view( + self.model.feature_extractor.banks, + self.model.feature_extractor.num_vars, + -1, + ) + .cpu() + .detach() + ) + print("writing learned latent variable embeddings: ", vars.shape) + torch.save(vars, self.var_file()) + + +if __name__ == "__main__": + write_data = DatasetWriter() + + write_data() + print("Done.") diff --git a/fairseq-tools/fairseq/examples/wav2vec/wav2vec_featurize.py b/fairseq-tools/fairseq/examples/wav2vec/wav2vec_featurize.py new file mode 100644 index 00000000..92839305 --- /dev/null +++ b/fairseq-tools/fairseq/examples/wav2vec/wav2vec_featurize.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Helper script to pre-compute embeddings for a wav2letter++ dataset +""" + +import argparse +import glob +import os +from shutil import copy + +import h5py +import numpy as np +import soundfile as sf +import torch +import tqdm +from fairseq.models.wav2vec.wav2vec import Wav2VecModel +from torch import nn + + +def read_audio(fname): + """ Load an audio file and return PCM along with the sample rate """ + + wav, sr = sf.read(fname) + assert sr == 16e3 + + return wav, 16e3 + + +class PretrainedWav2VecModel(nn.Module): + def __init__(self, fname): + super().__init__() + + checkpoint = torch.load(fname) + self.args = checkpoint["args"] + model = Wav2VecModel.build_model(self.args, None) + model.load_state_dict(checkpoint["model"]) + model.eval() + + self.model = model + + def forward(self, x): + with torch.no_grad(): + z = self.model.feature_extractor(x) + if isinstance(z, tuple): + z = z[0] + c = self.model.feature_aggregator(z) + return z, c + + +class EmbeddingWriterConfig(argparse.ArgumentParser): + def __init__(self): + super().__init__("Pre-compute embeddings for wav2letter++ datasets") + + kwargs = {"action": "store", "type": str, "required": True} + + self.add_argument("--input", "-i", help="Input Directory", **kwargs) + self.add_argument("--output", "-o", help="Output Directory", **kwargs) + self.add_argument("--model", help="Path to model checkpoint", **kwargs) + self.add_argument("--split", help="Dataset Splits", nargs="+", **kwargs) + self.add_argument( + "--ext", default="wav", required=False, help="Audio file extension" + ) + + self.add_argument( + "--no-copy-labels", + action="store_true", + help="Do not copy label files. Useful for large datasets, use --targetdir in wav2letter then.", + ) + self.add_argument( + "--use-feat", + action="store_true", + help="Use the feature vector ('z') instead of context vector ('c') for features", + ) + self.add_argument("--gpu", help="GPU to use", default=0, type=int) + + +class Prediction: + """ Lightweight wrapper around a fairspeech embedding model """ + + def __init__(self, fname, gpu=0): + self.gpu = gpu + self.model = PretrainedWav2VecModel(fname).cuda(gpu) + + def __call__(self, x): + x = torch.from_numpy(x).float().cuda(self.gpu) + with torch.no_grad(): + z, c = self.model(x.unsqueeze(0)) + + return z.squeeze(0).cpu().numpy(), c.squeeze(0).cpu().numpy() + + +class H5Writer: + """ Write features as hdf5 file in wav2letter++ compatible format """ + + def __init__(self, fname): + self.fname = fname + os.makedirs(os.path.dirname(self.fname), exist_ok=True) + + def write(self, data): + channel, T = data.shape + + with h5py.File(self.fname, "w") as out_ds: + data = data.T.flatten() + out_ds["features"] = data + out_ds["info"] = np.array([16e3 // 160, T, channel]) + + +class EmbeddingDatasetWriter(object): + """Given a model and a wav2letter++ dataset, pre-compute and store embeddings + + Args: + input_root, str : + Path to the wav2letter++ dataset + output_root, str : + Desired output directory. Will be created if non-existent + split, str : + Dataset split + """ + + def __init__( + self, + input_root, + output_root, + split, + model_fname, + extension="wav", + gpu=0, + verbose=False, + use_feat=False, + ): + + assert os.path.exists(model_fname) + + self.model_fname = model_fname + self.model = Prediction(self.model_fname, gpu) + + self.input_root = input_root + self.output_root = output_root + self.split = split + self.verbose = verbose + self.extension = extension + self.use_feat = use_feat + + assert os.path.exists(self.input_path), "Input path '{}' does not exist".format( + self.input_path + ) + + def _progress(self, iterable, **kwargs): + if self.verbose: + return tqdm.tqdm(iterable, **kwargs) + return iterable + + def require_output_path(self, fname=None): + path = self.get_output_path(fname) + os.makedirs(path, exist_ok=True) + + @property + def input_path(self): + return self.get_input_path() + + @property + def output_path(self): + return self.get_output_path() + + def get_input_path(self, fname=None): + if fname is None: + return os.path.join(self.input_root, self.split) + return os.path.join(self.get_input_path(), fname) + + def get_output_path(self, fname=None): + if fname is None: + return os.path.join(self.output_root, self.split) + return os.path.join(self.get_output_path(), fname) + + def copy_labels(self): + self.require_output_path() + + labels = list( + filter( + lambda x: self.extension not in x, glob.glob(self.get_input_path("*")) + ) + ) + for fname in tqdm.tqdm(labels): + copy(fname, self.output_path) + + @property + def input_fnames(self): + return sorted(glob.glob(self.get_input_path("*.{}".format(self.extension)))) + + def __len__(self): + return len(self.input_fnames) + + def write_features(self): + + paths = self.input_fnames + + fnames_context = map( + lambda x: os.path.join( + self.output_path, x.replace("." + self.extension, ".h5context") + ), + map(os.path.basename, paths), + ) + + for name, target_fname in self._progress( + zip(paths, fnames_context), total=len(self) + ): + wav, sr = read_audio(name) + z, c = self.model(wav) + feat = z if self.use_feat else c + writer = H5Writer(target_fname) + writer.write(feat) + + def __repr__(self): + + return "EmbeddingDatasetWriter ({n_files} files)\n\tinput:\t{input_root}\n\toutput:\t{output_root}\n\tsplit:\t{split})".format( + n_files=len(self), **self.__dict__ + ) + + +if __name__ == "__main__": + + args = EmbeddingWriterConfig().parse_args() + + for split in args.split: + + writer = EmbeddingDatasetWriter( + input_root=args.input, + output_root=args.output, + split=split, + model_fname=args.model, + gpu=args.gpu, + extension=args.ext, + use_feat=args.use_feat, + ) + + print(writer) + writer.require_output_path() + + print("Writing Features...") + writer.write_features() + print("Done.") + + if not args.no_copy_labels: + print("Copying label data...") + writer.copy_labels() + print("Done.") diff --git a/fairseq-tools/fairseq/examples/wav2vec/wav2vec_manifest.py b/fairseq-tools/fairseq/examples/wav2vec/wav2vec_manifest.py new file mode 100644 index 00000000..1d27f58a --- /dev/null +++ b/fairseq-tools/fairseq/examples/wav2vec/wav2vec_manifest.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Data pre-processing: build vocabularies and binarize training data. +""" + +import argparse +import glob +import os +import random + +import soundfile + + +def get_parser(): + parser = argparse.ArgumentParser() + parser.add_argument( + "root", metavar="DIR", help="root directory containing flac files to index" + ) + parser.add_argument( + "--valid-percent", + default=0.01, + type=float, + metavar="D", + help="percentage of data to use as validation set (between 0 and 1)", + ) + parser.add_argument( + "--dest", default=".", type=str, metavar="DIR", help="output directory" + ) + parser.add_argument( + "--ext", default="flac", type=str, metavar="EXT", help="extension to look for" + ) + parser.add_argument("--seed", default=42, type=int, metavar="N", help="random seed") + parser.add_argument( + "--path-must-contain", + default=None, + type=str, + metavar="FRAG", + help="if set, path must contain this substring for a file to be included in the manifest", + ) + return parser + + +def main(args): + assert args.valid_percent >= 0 and args.valid_percent <= 1.0 + + dir_path = os.path.realpath(args.root) + search_path = os.path.join(dir_path, "**/*." + args.ext) + rand = random.Random(args.seed) + + with open(os.path.join(args.dest, "train.tsv"), "w") as train_f, open( + os.path.join(args.dest, "valid.tsv"), "w" + ) as valid_f: + print(dir_path, file=train_f) + print(dir_path, file=valid_f) + + for fname in glob.iglob(search_path, recursive=True): + file_path = os.path.realpath(fname) + + if args.path_must_contain and args.path_must_contain not in file_path: + continue + + frames = soundfile.info(fname).frames + dest = train_f if rand.random() > args.valid_percent else valid_f + print( + "{}\t{}".format(os.path.relpath(file_path, dir_path), frames), file=dest + ) + + +if __name__ == "__main__": + parser = get_parser() + args = parser.parse_args() + main(args) diff --git a/fairseq-tools/fairseq/examples/wmt19/README.md b/fairseq-tools/fairseq/examples/wmt19/README.md new file mode 100644 index 00000000..5c90d0e6 --- /dev/null +++ b/fairseq-tools/fairseq/examples/wmt19/README.md @@ -0,0 +1,85 @@ +# WMT 19 + +This page provides pointers to the models of Facebook-FAIR's WMT'19 news translation task submission [(Ng et al., 2019)](https://arxiv.org/abs/1907.06616). + +## Pre-trained models + +Model | Description | Download +---|---|--- +`transformer.wmt19.en-de` | En->De Ensemble | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-de.joined-dict.ensemble.tar.gz) +`transformer.wmt19.de-en` | De->En Ensemble | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.de-en.joined-dict.ensemble.tar.gz) +`transformer.wmt19.en-ru` | En->Ru Ensemble | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-ru.ensemble.tar.gz) +`transformer.wmt19.ru-en` | Ru->En Ensemble | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.ru-en.ensemble.tar.gz) +`transformer_lm.wmt19.en` | En Language Model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.en.tar.gz) +`transformer_lm.wmt19.de` | De Language Model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.de.tar.gz) +`transformer_lm.wmt19.ru` | Ru Language Model | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.ru.tar.gz) + +## Pre-trained single models before finetuning + +Model | Description | Download +---|---|--- +`transformer.wmt19.en-de` | En->De Single, no finetuning | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-de.ffn8192.tar.gz) +`transformer.wmt19.de-en` | De->En Single, no finetuning | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.de-en.ffn8192.tar.gz) +`transformer.wmt19.en-ru` | En->Ru Single, no finetuning | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-ru.ffn8192.tar.gz) +`transformer.wmt19.ru-en` | Ru->En Single, no finetuning | [download (.tar.gz)](https://dl.fbaipublicfiles.com/fairseq/models/wmt19.ru-en.ffn8192.tar.gz) + +## Example usage (torch.hub) + +#### Requirements + +We require a few additional Python dependencies for preprocessing: +```bash +pip install fastBPE sacremoses +``` + +#### Translation + +```python +import torch + +# English to German translation +en2de = torch.hub.load('pytorch/fairseq', 'transformer.wmt19.en-de', checkpoint_file='model1.pt:model2.pt:model3.pt:model4.pt', + tokenizer='moses', bpe='fastbpe') +en2de.translate("Machine learning is great!") # 'Maschinelles Lernen ist großartig!' + +# German to English translation +de2en = torch.hub.load('pytorch/fairseq', 'transformer.wmt19.de-en', checkpoint_file='model1.pt:model2.pt:model3.pt:model4.pt', + tokenizer='moses', bpe='fastbpe') +de2en.translate("Maschinelles Lernen ist großartig!") # 'Machine learning is great!' + +# English to Russian translation +en2ru = torch.hub.load('pytorch/fairseq', 'transformer.wmt19.en-ru', checkpoint_file='model1.pt:model2.pt:model3.pt:model4.pt', + tokenizer='moses', bpe='fastbpe') +en2ru.translate("Machine learning is great!") # 'Машинное обучение - это здорово!' + +# Russian to English translation +ru2en = torch.hub.load('pytorch/fairseq', 'transformer.wmt19.ru-en', checkpoint_file='model1.pt:model2.pt:model3.pt:model4.pt', + tokenizer='moses', bpe='fastbpe') +ru2en.translate("Машинное обучение - это здорово!") # 'Machine learning is great!' +``` + +#### Language Modeling + +```python +# Sample from the English LM +en_lm = torch.hub.load('pytorch/fairseq', 'transformer_lm.wmt19.en', tokenizer='moses', bpe='fastbpe') +en_lm.sample("Machine learning is") # 'Machine learning is the future of computing, says Microsoft boss Satya Nadella ...' + +# Sample from the German LM +de_lm = torch.hub.load('pytorch/fairseq', 'transformer_lm.wmt19.de', tokenizer='moses', bpe='fastbpe') +de_lm.sample("Maschinelles lernen ist") # 'Maschinelles lernen ist das A und O (neues-deutschland.de) Die Arbeitsbedingungen für Lehrerinnen und Lehrer sind seit Jahren verbesserungswürdig ...' + +# Sample from the Russian LM +ru_lm = torch.hub.load('pytorch/fairseq', 'transformer_lm.wmt19.ru', tokenizer='moses', bpe='fastbpe') +ru_lm.sample("машинное обучение это") # 'машинное обучение это то, что мы называем "искусственным интеллектом".' +``` + +## Citation +```bibtex +@inproceedings{ng2019facebook}, + title = {Facebook FAIR's WMT19 News Translation Task Submission}, + author = {Ng, Nathan and Yee, Kyra and Baevski, Alexei and Ott, Myle and Auli, Michael and Edunov, Sergey}, + booktitle = {Proc. of WMT}, + year = 2019, +} +``` diff --git a/fairseq-tools/fairseq/examples/xlmr/README.md b/fairseq-tools/fairseq/examples/xlmr/README.md new file mode 100644 index 00000000..65d4be13 --- /dev/null +++ b/fairseq-tools/fairseq/examples/xlmr/README.md @@ -0,0 +1,123 @@ +# Unsupervised Cross-lingual Representation Learning at Scale (XLM-RoBERTa) +https://arxiv.org/pdf/1911.02116.pdf + +## Introduction + +XLM-R (XLM-RoBERTa) is a generic cross lingual sentence encoder that obtains state-of-the-art results on many cross-lingual understanding (XLU) benchmarks. It is trained on 2.5T of filtered CommonCrawl data in 100 languages (list below). + + Language | Language|Language |Language | Language +---|---|---|---|--- +Afrikaans | Albanian | Amharic | Arabic | Armenian +Assamese | Azerbaijani | Basque | Belarusian | Bengali +Bengali Romanize | Bosnian | Breton | Bulgarian | Burmese +Burmese zawgyi font | Catalan | Chinese (Simplified) | Chinese (Traditional) | Croatian +Czech | Danish | Dutch | English | Esperanto +Estonian | Filipino | Finnish | French | Galician +Georgian | German | Greek | Gujarati | Hausa +Hebrew | Hindi | Hindi Romanize | Hungarian | Icelandic +Indonesian | Irish | Italian | Japanese | Javanese +Kannada | Kazakh | Khmer | Korean | Kurdish (Kurmanji) +Kyrgyz | Lao | Latin | Latvian | Lithuanian +Macedonian | Malagasy | Malay | Malayalam | Marathi +Mongolian | Nepali | Norwegian | Oriya | Oromo +Pashto | Persian | Polish | Portuguese | Punjabi +Romanian | Russian | Sanskrit | Scottish Gaelic | Serbian +Sindhi | Sinhala | Slovak | Slovenian | Somali +Spanish | Sundanese | Swahili | Swedish | Tamil +Tamil Romanize | Telugu | Telugu Romanize | Thai | Turkish +Ukrainian | Urdu | Urdu Romanize | Uyghur | Uzbek +Vietnamese | Welsh | Western Frisian | Xhosa | Yiddish + +## Pre-trained models + +Model | Description | #params | vocab size | Download +---|---|---|---|--- +`xlmr.base` | XLM-R using the BERT-base architecture | 250M | 250k | [xlm.base.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/xlmr.base.tar.gz) +`xlmr.large` | XLM-R using the BERT-large architecture | 560M | 250k | [xlm.large.tar.gz](https://dl.fbaipublicfiles.com/fairseq/models/xlmr.large.tar.gz) + +(Note: Above are final model checkpoints. If you were using previously released `v0` version, we recommend using above. They have same architecture and dictionary.) + +## Results + +**[XNLI (Conneau et al., 2018)](https://arxiv.org/abs/1809.05053)** + +Model | average | en | fr | es | de | el | bg | ru | tr | ar | vi | th | zh | hi | sw | ur +---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|--- +`roberta.large.mnli` _(TRANSLATE-TEST)_ | 77.8 | 91.3 | 82.9 | 84.3 | 81.2 | 81.7 | 83.1 | 78.3 | 76.8 | 76.6 | 74.2 | 74.1 | 77.5 | 70.9 | 66.7 | 66.8 +`xlmr.large` _(TRANSLATE-TRAIN-ALL)_ | **83.6** | 89.1 | 85.1 | 86.6 | 85.7 | 85.3 | 85.9 | 83.5 | 83.2 | 83.1 | 83.7 | 81.5 | 83.7 | 81.6 | 78.0 | 78.1 + +**[MLQA (Lewis et al., 2018)](https://arxiv.org/abs/1910.07475)** + +Model | average | en | es | de | ar | hi | vi | zh +---|---|---|---|---|---|---|---|--- +`BERT-large` | - | 80.2/67.4 | - | - | - | - | - | - +`mBERT` | 57.7 / 41.6 | 77.7 / 65.2 | 64.3 / 46.6 | 57.9 / 44.3 | 45.7 / 29.8| 43.8 / 29.7 | 57.1 / 38.6 | 57.5 / 37.3 +`xlmr.large` | **70.7 / 52.7** | 80.6 / 67.8 | 74.1 / 56.0 | 68.5 / 53.6 | 63.1 / 43.5 | 69.2 / 51.6 | 71.3 / 50.9 | 68.0 / 45.4 + + +## Example usage + +##### Load XLM-R from torch.hub (PyTorch >= 1.1): +```python +import torch +xlmr = torch.hub.load('pytorch/fairseq', 'xlmr.large') +xlmr.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Load XLM-R (for PyTorch 1.0 or custom models): +```python +# Download xlmr.large model +wget https://dl.fbaipublicfiles.com/fairseq/models/xlmr.large.tar.gz +tar -xzvf xlmr.large.tar.gz + +# Load the model in fairseq +from fairseq.models.roberta import XLMRModel +xlmr = XLMRModel.from_pretrained('/path/to/xlmr.large', checkpoint_file='model.pt') +xlmr.eval() # disable dropout (or leave in train mode to finetune) +``` + +##### Apply sentence-piece-model (SPM) encoding to input text: +```python +en_tokens = xlmr.encode('Hello world!') +assert en_tokens.tolist() == [0, 35378, 8999, 38, 2] +xlmr.decode(en_tokens) # 'Hello world!' + +zh_tokens = xlmr.encode('你好,世界') +assert zh_tokens.tolist() == [0, 6, 124084, 4, 3221, 2] +xlmr.decode(zh_tokens) # '你好,世界' + +hi_tokens = xlmr.encode('नमस्ते दुनिया') +assert hi_tokens.tolist() == [0, 68700, 97883, 29405, 2] +xlmr.decode(hi_tokens) # 'नमस्ते दुनिया' + +ar_tokens = xlmr.encode('مرحبا بالعالم') +assert ar_tokens.tolist() == [0, 665, 193478, 258, 1705, 77796, 2] +xlmr.decode(ar_tokens) # 'مرحبا بالعالم' + +fr_tokens = xlmr.encode('Bonjour le monde') +assert fr_tokens.tolist() == [0, 84602, 95, 11146, 2] +xlmr.decode(fr_tokens) # 'Bonjour le monde' +``` + +##### Extract features from XLM-R: +```python +# Extract the last layer's features +last_layer_features = xlmr.extract_features(zh_tokens) +assert last_layer_features.size() == torch.Size([1, 6, 1024]) + +# Extract all layer's features (layer 0 is the embedding layer) +all_layers = xlmr.extract_features(zh_tokens, return_all_hiddens=True) +assert len(all_layers) == 25 +assert torch.all(all_layers[-1] == last_layer_features) +``` + +## Citation + +```bibtex +@article{conneau2019unsupervised, + title={Unsupervised Cross-lingual Representation Learning at Scale}, + author={Conneau, Alexis and Khandelwal, Kartikay and Goyal, Naman and Chaudhary, Vishrav and Wenzek, Guillaume and Guzm{\'a}n, Francisco and Grave, Edouard and Ott, Myle and Zettlemoyer, Luke and Stoyanov, Veselin}, + journal={arXiv preprint arXiv:1911.02116}, + year={2019} +} +``` diff --git a/fairseq-tools/fairseq/fairseq/__init__.py b/fairseq-tools/fairseq/fairseq/__init__.py new file mode 100644 index 00000000..9c1f7569 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/__init__.py @@ -0,0 +1,30 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +__all__ = ["pdb"] +__version__ = "0.10.2" + +import sys + +# backwards compatibility to support `from fairseq.meters import AverageMeter` +from fairseq.logging import meters, metrics, progress_bar # noqa + +sys.modules["fairseq.meters"] = meters +sys.modules["fairseq.metrics"] = metrics +sys.modules["fairseq.progress_bar"] = progress_bar + +import fairseq.criterions # noqa +import fairseq.models # noqa +import fairseq.modules # noqa +import fairseq.optim # noqa +import fairseq.optim.lr_scheduler # noqa +import fairseq.pdb # noqa +import fairseq.scoring # noqa +import fairseq.tasks # noqa +import fairseq.token_generation_constraints # noqa + +import fairseq.benchmark # noqa +import fairseq.model_parallel # noqa diff --git a/fairseq-tools/fairseq/fairseq/benchmark/__init__.py b/fairseq-tools/fairseq/fairseq/benchmark/__init__.py new file mode 100644 index 00000000..f6584661 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/benchmark/__init__.py @@ -0,0 +1,7 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# import models/tasks to register them +from . import dummy_lm, dummy_masked_lm, dummy_model, dummy_mt # noqa diff --git a/fairseq-tools/fairseq/fairseq/benchmark/dummy_lm.py b/fairseq-tools/fairseq/fairseq/benchmark/dummy_lm.py new file mode 100644 index 00000000..6429d04d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/benchmark/dummy_lm.py @@ -0,0 +1,119 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import numpy as np +import torch +from fairseq.data import Dictionary, FairseqDataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("dummy_lm") +class DummyLMTask(LegacyFairseqTask): + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("--dict-size", default=49996, type=int) + parser.add_argument("--dataset-size", default=100000, type=int) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments " + "per sample for BERT dataset", + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + dictionary.pad_to_multiple_(8) # often faster if divisible by 8 + + seq = torch.arange(args.tokens_per_sample + 1) + dictionary.pad() + 1 + + self.dummy_src = seq[:-1] + self.dummy_tgt = seq[1:] + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task. """ + dictionary = Dictionary() + for i in range(args.dict_size): + dictionary.add_symbol("word{}".format(i)) + logger.info("dictionary: {} types".format(len(dictionary))) + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + Args: + split (str): name of the split (e.g., train, valid, test) + """ + if self.args.batch_size is not None: + bsz = self.args.batch_size + else: + bsz = max(1, self.args.max_tokens // self.args.tokens_per_sample) + self.datasets[split] = DummyDataset( + { + "id": 1, + "net_input": { + "src_tokens": torch.stack([self.dummy_src for _ in range(bsz)]), + "src_lengths": torch.full( + (bsz,), self.args.tokens_per_sample, dtype=torch.long + ), + }, + "target": torch.stack([self.dummy_tgt for _ in range(bsz)]), + "nsentences": bsz, + "ntokens": bsz * self.args.tokens_per_sample, + }, + num_items=self.args.dataset_size, + item_size=self.args.tokens_per_sample, + ) + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary + + +class DummyDataset(FairseqDataset): + def __init__(self, batch, num_items, item_size): + super().__init__() + self.batch = batch + self.num_items = num_items + self.item_size = item_size + + def __getitem__(self, index): + return index + + def __len__(self): + return self.num_items + + def collater(self, samples): + return self.batch + + @property + def sizes(self): + return np.array([self.item_size] * self.num_items) + + def num_tokens(self, index): + return self.item_size + + def size(self, index): + return self.item_size + + def ordered_indices(self): + return np.arange(self.num_items) + + @property + def supports_prefetch(self): + return False diff --git a/fairseq-tools/fairseq/fairseq/benchmark/dummy_masked_lm.py b/fairseq-tools/fairseq/fairseq/benchmark/dummy_masked_lm.py new file mode 100644 index 00000000..ab506fe1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/benchmark/dummy_masked_lm.py @@ -0,0 +1,127 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import numpy as np +import torch +from fairseq.data import Dictionary, FairseqDataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("dummy_masked_lm") +class DummyMaskedLMTask(LegacyFairseqTask): + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("--dict-size", default=49995, type=int) + parser.add_argument("--dataset-size", default=100000, type=int) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments " + "per sample for BERT dataset", + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + + # add mask token + self.mask_idx = dictionary.add_symbol("<mask>") + dictionary.pad_to_multiple_(8) # often faster if divisible by 8 + + mask_idx = 0 + pad_idx = 1 + seq = torch.arange(args.tokens_per_sample) + pad_idx + 1 + mask = torch.arange(2, args.tokens_per_sample, 7) # ~15% + src = seq.clone() + src[mask] = mask_idx + tgt = torch.full_like(seq, pad_idx) + tgt[mask] = seq[mask] + + self.dummy_src = src + self.dummy_tgt = tgt + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task. """ + dictionary = Dictionary() + for i in range(args.dict_size): + dictionary.add_symbol("word{}".format(i)) + logger.info("dictionary: {} types".format(len(dictionary))) + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + Args: + split (str): name of the split (e.g., train, valid, test) + """ + if self.args.batch_size is not None: + bsz = self.args.batch_size + else: + bsz = max(1, self.args.max_tokens // self.args.tokens_per_sample) + self.datasets[split] = DummyDataset( + { + "id": 1, + "net_input": { + "src_tokens": torch.stack([self.dummy_src for _ in range(bsz)]), + "src_lengths": torch.full( + (bsz,), self.args.tokens_per_sample, dtype=torch.long + ), + }, + "target": torch.stack([self.dummy_tgt for _ in range(bsz)]), + "nsentences": bsz, + "ntokens": bsz * self.args.tokens_per_sample, + }, + num_items=self.args.dataset_size, + item_size=self.args.tokens_per_sample, + ) + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary + + +class DummyDataset(FairseqDataset): + def __init__(self, batch, num_items, item_size): + super().__init__() + self.batch = batch + self.num_items = num_items + self.item_size = item_size + + def __getitem__(self, index): + return index + + def __len__(self): + return self.num_items + + def collater(self, samples): + return self.batch + + @property + def sizes(self): + return np.array([self.item_size] * self.num_items) + + def num_tokens(self, index): + return self.item_size + + def size(self, index): + return self.item_size + + def ordered_indices(self): + return np.arange(self.num_items) + + @property + def supports_prefetch(self): + return False diff --git a/fairseq-tools/fairseq/fairseq/benchmark/dummy_model.py b/fairseq-tools/fairseq/fairseq/benchmark/dummy_model.py new file mode 100644 index 00000000..ff26e4fe --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/benchmark/dummy_model.py @@ -0,0 +1,96 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn as nn +import torch.nn.functional as F +from fairseq.data import Dictionary +from fairseq.models import ( + FairseqDecoder, + FairseqLanguageModel, + register_model, + register_model_architecture, +) + + +@register_model("dummy_model") +class DummyModel(FairseqLanguageModel): + def __init__(self, args, encoder): + super().__init__(encoder) + self.args = args + + @staticmethod + def add_args(parser): + parser.add_argument("--num-layers", type=int, default=24) + parser.add_argument("--embed-dim", type=int, default=1024) + + @classmethod + def build_model(cls, args, task): + encoder = DummyEncoder( + num_embed=len(task.target_dictionary), + embed_dim=args.embed_dim, + num_layers=args.num_layers, + ) + return cls(args, encoder) + + def forward(self, src_tokens, masked_tokens=None, **kwargs): + return self.decoder(src_tokens, masked_tokens=masked_tokens) + + +class DummyEncoder(FairseqDecoder): + def __init__(self, num_embed=50000, embed_dim=1024, num_layers=24): + super().__init__(Dictionary()) + self.embed = nn.Embedding( + num_embeddings=num_embed, embedding_dim=embed_dim, padding_idx=0 + ) + self.layers_a = nn.ModuleList( + [ + nn.Sequential( + nn.LayerNorm(embed_dim), + nn.Linear(embed_dim, 3 * embed_dim), # q, k, v input projection + nn.Linear(3 * embed_dim, embed_dim), # skip self-attention + nn.Linear(embed_dim, embed_dim), # output projection + nn.Dropout(), + ) + for i in range(num_layers) + ] + ) + self.layers_b = nn.ModuleList( + [ + nn.Sequential( + nn.LayerNorm(embed_dim), + nn.Linear(embed_dim, 4 * embed_dim), # FFN + nn.ReLU(), + nn.Linear(4 * embed_dim, embed_dim), # FFN + nn.Dropout(0.1), + ) + for i in range(num_layers) + ] + ) + self.out_proj = nn.Linear(embed_dim, num_embed) + + def forward(self, tokens, masked_tokens=None): + x = self.embed(tokens) + for layer_a, layer_b in zip(self.layers_a, self.layers_b): + x = x + layer_a(x) + x = x + layer_b(x) + x = self.out_proj(x) + if masked_tokens is not None: + x = x[masked_tokens] + return (x,) + + def max_positions(self): + return 1024 + + def get_normalized_probs(self, net_output, log_probs, sample=None): + logits = net_output[0].float() + if log_probs: + return F.log_softmax(logits, dim=-1) + else: + return F.softmax(logits, dim=-1) + + +@register_model_architecture("dummy_model", "dummy_model") +def base_architecture(args): + pass diff --git a/fairseq-tools/fairseq/fairseq/benchmark/dummy_mt.py b/fairseq-tools/fairseq/fairseq/benchmark/dummy_mt.py new file mode 100644 index 00000000..4ca7be93 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/benchmark/dummy_mt.py @@ -0,0 +1,119 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import numpy as np +import torch +from fairseq.data import Dictionary, FairseqDataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("dummy_mt") +class DummyMTTask(LegacyFairseqTask): + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("--dict-size", default=49996, type=int) + parser.add_argument("--dataset-size", default=100000, type=int) + parser.add_argument("--src-len", default=30, type=int) + parser.add_argument("--tgt-len", default=30, type=int) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + dictionary.pad_to_multiple_(8) # often faster if divisible by 8 + + self.dummy_src = torch.arange(args.src_len + 1) + dictionary.pad() + 1 + self.dummy_tgt = torch.arange(args.tgt_len + 1) + dictionary.pad() + 1 + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task. """ + dictionary = Dictionary() + for i in range(args.dict_size): + dictionary.add_symbol("word{}".format(i)) + logger.info("dictionary: {} types".format(len(dictionary))) + + args.max_source_positions = args.src_len + dictionary.pad() + 2 + args.max_target_positions = args.tgt_len + dictionary.pad() + 2 + + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + Args: + split (str): name of the split (e.g., train, valid, test) + """ + item_size = max(self.args.src_len, self.args.tgt_len) + if self.args.batch_size is not None: + bsz = self.args.batch_size + else: + bsz = max(1, self.args.max_tokens // item_size) + tgt = torch.stack([self.dummy_tgt for _ in range(bsz)]) + self.datasets[split] = DummyDataset( + { + "id": 1, + "net_input": { + "src_tokens": torch.stack([self.dummy_src for _ in range(bsz)]), + "src_lengths": torch.full( + (bsz,), self.args.src_len, dtype=torch.long + ), + "prev_output_tokens": tgt.clone(), + }, + "target": tgt, + "nsentences": bsz, + "ntokens": bsz * self.args.tgt_len, + }, + num_items=self.args.dataset_size, + item_size=item_size, + ) + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary + + +class DummyDataset(FairseqDataset): + def __init__(self, batch, num_items, item_size): + super().__init__() + self.batch = batch + self.num_items = num_items + self.item_size = item_size + + def __getitem__(self, index): + return index + + def __len__(self): + return self.num_items + + def collater(self, samples): + return self.batch + + @property + def sizes(self): + return np.array([self.item_size] * self.num_items) + + def num_tokens(self, index): + return self.item_size + + def size(self, index): + return self.item_size + + def ordered_indices(self): + return np.arange(self.num_items) + + @property + def supports_prefetch(self): + return False diff --git a/fairseq-tools/fairseq/fairseq/binarizer.py b/fairseq-tools/fairseq/fairseq/binarizer.py new file mode 100644 index 00000000..0255c084 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/binarizer.py @@ -0,0 +1,105 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +from collections import Counter + +import torch +from fairseq.file_io import PathManager +from fairseq.tokenizer import tokenize_line + + +def safe_readline(f): + pos = f.tell() + while True: + try: + return f.readline() + except UnicodeDecodeError: + pos -= 1 + f.seek(pos) # search where this character begins + + +class Binarizer: + @staticmethod + def binarize( + filename, + dict, + consumer, + tokenize=tokenize_line, + append_eos=True, + reverse_order=False, + offset=0, + end=-1, + already_numberized=False, + ): + nseq, ntok = 0, 0 + replaced = Counter() + + def replaced_consumer(word, idx): + if idx == dict.unk_index and word != dict.unk_word: + replaced.update([word]) + + with open(PathManager.get_local_path(filename), "r", encoding="utf-8") as f: + f.seek(offset) + # next(f) breaks f.tell(), hence readline() must be used + line = safe_readline(f) + while line: + if end > 0 and f.tell() > end: + break + if already_numberized: + id_strings = line.strip().split() + id_list = [int(id_string) for id_string in id_strings] + if reverse_order: + id_list.reverse() + if append_eos: + id_list.append(dict.eos()) + ids = torch.IntTensor(id_list) + else: + ids = dict.encode_line( + line=line, + line_tokenizer=tokenize, + add_if_not_exist=False, + consumer=replaced_consumer, + append_eos=append_eos, + reverse_order=reverse_order, + ) + nseq += 1 + ntok += len(ids) + consumer(ids) + line = f.readline() + return { + "nseq": nseq, + "nunk": sum(replaced.values()), + "ntok": ntok, + "replaced": replaced, + } + + @staticmethod + def binarize_alignments(filename, alignment_parser, consumer, offset=0, end=-1): + nseq = 0 + + with open(PathManager.get_local_path(filename), "r") as f: + f.seek(offset) + line = safe_readline(f) + while line: + if end > 0 and f.tell() > end: + break + ids = alignment_parser(line) + nseq += 1 + consumer(ids) + line = f.readline() + return {"nseq": nseq} + + @staticmethod + def find_offsets(filename, num_chunks): + with open(PathManager.get_local_path(filename), "r", encoding="utf-8") as f: + size = os.fstat(f.fileno()).st_size + chunk_size = size // num_chunks + offsets = [0 for _ in range(num_chunks + 1)] + for i in range(1, num_chunks): + f.seek(chunk_size * i) + safe_readline(f) + offsets[i] = f.tell() + return offsets diff --git a/fairseq-tools/fairseq/fairseq/checkpoint_utils.py b/fairseq-tools/fairseq/fairseq/checkpoint_utils.py new file mode 100644 index 00000000..75e2c68c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/checkpoint_utils.py @@ -0,0 +1,573 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import collections +import logging +import os +import re +import traceback +from collections import OrderedDict +from typing import Union + +import torch +from fairseq.file_io import PathManager +from fairseq.models import FairseqDecoder, FairseqEncoder +from torch.serialization import default_restore_location + + +logger = logging.getLogger(__name__) + + +def save_checkpoint(args, trainer, epoch_itr, val_loss): + from fairseq import distributed_utils, meters + + # only one worker should attempt to create the required dir + if args.distributed_rank == 0: + os.makedirs(args.save_dir, exist_ok=True) + + prev_best = getattr(save_checkpoint, "best", val_loss) + if val_loss is not None: + best_function = max if args.maximize_best_checkpoint_metric else min + save_checkpoint.best = best_function(val_loss, prev_best) + + if args.no_save: + return + + trainer.consolidate_optimizer() + + if not trainer.is_data_parallel_master: + return + + def is_better(a, b): + return a >= b if args.maximize_best_checkpoint_metric else a <= b + + write_timer = meters.StopwatchMeter() + write_timer.start() + + epoch = epoch_itr.epoch + end_of_epoch = epoch_itr.end_of_epoch() + updates = trainer.get_num_updates() + + suffix = getattr(args, "checkpoint_suffix", "") + checkpoint_conds = collections.OrderedDict() + checkpoint_conds["checkpoint{}{}.pt".format(epoch, suffix)] = ( + end_of_epoch + and not args.no_epoch_checkpoints + and epoch % args.save_interval == 0 + ) + checkpoint_conds["checkpoint_{}_{}{}.pt".format(epoch, updates, suffix)] = ( + not end_of_epoch + and args.save_interval_updates > 0 + and updates % args.save_interval_updates == 0 + ) + checkpoint_conds["checkpoint_best{}.pt".format(suffix)] = val_loss is not None and ( + not hasattr(save_checkpoint, "best") + or is_better(val_loss, save_checkpoint.best) + ) + if val_loss is not None and args.keep_best_checkpoints > 0: + checkpoint_conds[ + "checkpoint.best_{}_{:.2f}.pt".format(args.best_checkpoint_metric, val_loss) + ] = not hasattr(save_checkpoint, "best") or is_better( + val_loss, save_checkpoint.best + ) + checkpoint_conds[ + "checkpoint_last{}.pt".format(suffix) + ] = not args.no_last_checkpoints + + extra_state = {"train_iterator": epoch_itr.state_dict(), "val_loss": val_loss} + if hasattr(save_checkpoint, "best"): + extra_state.update({"best": save_checkpoint.best}) + + checkpoints = [ + os.path.join(args.save_dir, fn) for fn, cond in checkpoint_conds.items() if cond + ] + if len(checkpoints) > 0: + trainer.save_checkpoint(checkpoints[0], extra_state) + for cp in checkpoints[1:]: + PathManager.copy(checkpoints[0], cp, overwrite=True) + + write_timer.stop() + logger.info( + "saved checkpoint {} (epoch {} @ {} updates, score {}) (writing took {} seconds)".format( + checkpoints[0], epoch, updates, val_loss, write_timer.sum + ) + ) + + if not end_of_epoch and args.keep_interval_updates > 0: + # remove old checkpoints; checkpoints are sorted in descending order + checkpoints = checkpoint_paths( + args.save_dir, pattern=r"checkpoint_\d+_(\d+)\.pt" + ) + for old_chk in checkpoints[args.keep_interval_updates :]: + if os.path.lexists(old_chk): + os.remove(old_chk) + + if args.keep_last_epochs > 0: + # remove old epoch checkpoints; checkpoints are sorted in descending order + checkpoints = checkpoint_paths(args.save_dir, pattern=r"checkpoint(\d+)\.pt") + for old_chk in checkpoints[args.keep_last_epochs :]: + if os.path.lexists(old_chk): + os.remove(old_chk) + + if args.keep_best_checkpoints > 0: + # only keep the best N checkpoints according to validation metric + checkpoints = checkpoint_paths( + args.save_dir, + pattern=r"checkpoint\.best_{}_(\d+\.?\d*)\.pt".format( + args.best_checkpoint_metric + ), + ) + if not args.maximize_best_checkpoint_metric: + checkpoints = checkpoints[::-1] + for old_chk in checkpoints[args.keep_best_checkpoints :]: + if os.path.lexists(old_chk): + os.remove(old_chk) + + +def load_checkpoint(args, trainer, **passthrough_args): + """ + Load a checkpoint and restore the training iterator. + + *passthrough_args* will be passed through to + ``trainer.get_train_iterator``. + """ + reset_optimizer = args.reset_optimizer + reset_lr_scheduler = args.reset_lr_scheduler + optimizer_overrides = eval(args.optimizer_overrides) + reset_meters = args.reset_meters + reset_dataloader = args.reset_dataloader + + if getattr(args, "finetune_from_model", None) is not None and ( + reset_optimizer or reset_lr_scheduler or reset_meters or reset_dataloader + ): + raise ValueError( + "--finetune-from-model can not be set together with either --reset-optimizer" + " or reset_lr_scheduler or reset_meters or reset_dataloader" + ) + + suffix = getattr(args, "checkpoint_suffix", "") + if ( + args.restore_file == "checkpoint_last.pt" + ): # default value of restore_file is 'checkpoint_last.pt' + checkpoint_path = os.path.join( + args.save_dir, "checkpoint_last{}.pt".format(suffix) + ) + first_launch = not PathManager.exists(checkpoint_path) + if getattr(args, "finetune_from_model", None) is not None and first_launch: + # if there is no last checkpoint to restore, start the finetune from pretrained model + # else just use usual logic to load checkpoint, e.g. restart from last checkpoint and etc. + if PathManager.exists(args.finetune_from_model): + checkpoint_path = args.finetune_from_model + reset_optimizer = True + reset_lr_scheduler = True + reset_meters = True + reset_dataloader = True + logger.info( + f"loading pretrained model from {checkpoint_path}: " + "optimizer, lr scheduler, meters, dataloader will be reset" + ) + else: + raise ValueError( + f"--funetune-from-model {args.finetune_from_model} does not exist" + ) + elif getattr(args, "model_parallel_size", 1) > 1: + checkpoint_path = args.restore_file.replace(".pt", suffix + ".pt") + else: + checkpoint_path = args.restore_file + + if args.restore_file != "checkpoint_last.pt" and getattr( + args, "finetune_from_model", None + ): + raise ValueError( + "--finetune-from-model and --restore-file (non-default value) " + "can not be specified together: " + str(args) + ) + + extra_state = trainer.load_checkpoint( + checkpoint_path, + reset_optimizer, + reset_lr_scheduler, + optimizer_overrides, + reset_meters=reset_meters, + ) + + if ( + extra_state is not None + and "best" in extra_state + and not reset_optimizer + and not reset_meters + ): + save_checkpoint.best = extra_state["best"] + + if extra_state is not None and not reset_dataloader: + # restore iterator from checkpoint + itr_state = extra_state["train_iterator"] + epoch_itr = trainer.get_train_iterator( + epoch=itr_state["epoch"], load_dataset=True, **passthrough_args + ) + epoch_itr.load_state_dict(itr_state) + else: + epoch_itr = trainer.get_train_iterator( + epoch=1, load_dataset=True, **passthrough_args + ) + + trainer.lr_step(epoch_itr.epoch) + + return extra_state, epoch_itr + + +def load_checkpoint_to_cpu(path, arg_overrides=None): + """Loads a checkpoint to CPU (with upgrading for backward compatibility).""" + with open(PathManager.get_local_path(path), "rb") as f: + state = torch.load( + f, map_location=lambda s, l: default_restore_location(s, "cpu") + ) + + args = state["args"] + if arg_overrides is not None: + for arg_name, arg_val in arg_overrides.items(): + setattr(args, arg_name, arg_val) + state = _upgrade_state_dict(state) + return state + + +def load_model_ensemble( + filenames, arg_overrides=None, task=None, strict=True, suffix="", num_shards=1 +): + """Loads an ensemble of models. + + Args: + filenames (List[str]): checkpoint files to load + arg_overrides (Dict[str,Any], optional): override model args that + were used during model training + task (fairseq.tasks.FairseqTask, optional): task to use for loading + """ + assert not ( + strict and num_shards > 1 + ), "Cannot load state dict with strict=True and checkpoint shards > 1" + ensemble, args, _task = load_model_ensemble_and_task( + filenames, + arg_overrides, + task, + strict, + suffix, + num_shards, + ) + return ensemble, args + + +def load_model_ensemble_and_task( + filenames, arg_overrides=None, task=None, strict=True, suffix="", num_shards=1 +): + from fairseq import tasks + + assert not ( + strict and num_shards > 1 + ), "Cannot load state dict with strict=True and checkpoint shards > 1" + ensemble = [] + for filename in filenames: + orig_filename = filename + for shard_idx in range(num_shards): + if num_shards == 1: + filename = filename.replace(".pt", suffix + ".pt") + else: + filename = orig_filename[:-3] + f"_part{shard_idx}.pt" + if not PathManager.exists(filename): + raise IOError("Model file not found: {}".format(filename)) + state = load_checkpoint_to_cpu(filename, arg_overrides) + if shard_idx == 0: + args = state["args"] + if task is None: + task = tasks.setup_task(args) + + # build model for ensemble + model = task.build_model(args) + model.load_state_dict(state["model"], strict=strict, args=args) + ensemble.append(model) + return ensemble, args, task + + +def checkpoint_paths(path, pattern=r"checkpoint(\d+)\.pt"): + """Retrieves all checkpoints found in `path` directory. + + Checkpoints are identified by matching filename to the specified pattern. If + the pattern contains groups, the result will be sorted by the first group in + descending order. + """ + pt_regexp = re.compile(pattern) + files = os.listdir(path) + + entries = [] + for i, f in enumerate(files): + m = pt_regexp.fullmatch(f) + if m is not None: + idx = float(m.group(1)) if len(m.groups()) > 0 else i + entries.append((idx, m.group(0))) + return [os.path.join(path, x[1]) for x in sorted(entries, reverse=True)] + + +def torch_persistent_save(obj, f): + if isinstance(f, str): + with PathManager.open(f, "wb") as h: + torch_persistent_save(obj, h) + return + for i in range(3): + try: + return torch.save(obj, f) + except Exception: + if i == 2: + logger.error(traceback.format_exc()) + + +def save_state( + filename, + args, + model_state_dict, + criterion, + optimizer, + lr_scheduler, + num_updates, + optim_history=None, + extra_state=None, +): + from fairseq import utils + + if optim_history is None: + optim_history = [] + if extra_state is None: + extra_state = {} + state_dict = { + "args": args, + "model": model_state_dict or {}, + "optimizer_history": optim_history + + [ + { + "criterion_name": criterion.__class__.__name__, + "optimizer_name": optimizer.__class__.__name__, + "lr_scheduler_state": lr_scheduler.state_dict(), + "num_updates": num_updates, + } + ], + "extra_state": extra_state, + } + if utils.has_parameters(criterion): + state_dict["criterion"] = criterion.state_dict() + if not args.no_save_optimizer_state: + state_dict["last_optimizer_state"] = optimizer.state_dict() + + # convert all state to CPU + state_dict = utils.move_to_cpu(state_dict) + + with PathManager.open(filename, "wb") as f: + torch_persistent_save(state_dict, f) + + +def _upgrade_state_dict(state): + """Helper for upgrading old model checkpoints.""" + from fairseq import models, registry, tasks + + # add optimizer_history + if "optimizer_history" not in state: + state["optimizer_history"] = [ + {"criterion_name": "CrossEntropyCriterion", "best_loss": state["best_loss"]} + ] + state["last_optimizer_state"] = state["optimizer"] + del state["optimizer"] + del state["best_loss"] + # move extra_state into sub-dictionary + if "epoch" in state and "extra_state" not in state: + state["extra_state"] = { + "epoch": state["epoch"], + "batch_offset": state["batch_offset"], + "val_loss": state["val_loss"], + } + del state["epoch"] + del state["batch_offset"] + del state["val_loss"] + # reduce optimizer history's memory usage (only keep the last state) + if "optimizer" in state["optimizer_history"][-1]: + state["last_optimizer_state"] = state["optimizer_history"][-1]["optimizer"] + for optim_hist in state["optimizer_history"]: + del optim_hist["optimizer"] + # record the optimizer class name + if "optimizer_name" not in state["optimizer_history"][-1]: + state["optimizer_history"][-1]["optimizer_name"] = "FairseqNAG" + # move best_loss into lr_scheduler_state + if "lr_scheduler_state" not in state["optimizer_history"][-1]: + state["optimizer_history"][-1]["lr_scheduler_state"] = { + "best": state["optimizer_history"][-1]["best_loss"] + } + del state["optimizer_history"][-1]["best_loss"] + # keep track of number of updates + if "num_updates" not in state["optimizer_history"][-1]: + state["optimizer_history"][-1]["num_updates"] = 0 + # old model checkpoints may not have separate source/target positions + if hasattr(state["args"], "max_positions") and not hasattr( + state["args"], "max_source_positions" + ): + state["args"].max_source_positions = state["args"].max_positions + state["args"].max_target_positions = state["args"].max_positions + # use stateful training data iterator + if "train_iterator" not in state["extra_state"]: + state["extra_state"]["train_iterator"] = { + "epoch": state["extra_state"]["epoch"], + "iterations_in_epoch": state["extra_state"].get("batch_offset", 0), + } + # default to translation task + if not hasattr(state["args"], "task"): + state["args"].task = "translation" + # --raw-text and --lazy-load are deprecated + if getattr(state["args"], "raw_text", False): + state["args"].dataset_impl = "raw" + elif getattr(state["args"], "lazy_load", False): + state["args"].dataset_impl = "lazy" + # epochs start at 1 + if state["extra_state"]["train_iterator"] is not None: + state["extra_state"]["train_iterator"]["epoch"] = max( + state["extra_state"]["train_iterator"].get("epoch", 1), + 1, + ) + + # set any missing default values in the task, model or other registries + registry.set_defaults(state["args"], tasks.TASK_REGISTRY[state["args"].task]) + registry.set_defaults(state["args"], models.ARCH_MODEL_REGISTRY[state["args"].arch]) + for registry_name, REGISTRY in registry.REGISTRIES.items(): + choice = getattr(state["args"], registry_name, None) + if choice is not None: + cls = REGISTRY["registry"][choice] + registry.set_defaults(state["args"], cls) + + return state + + +def prune_state_dict(state_dict, args): + """Prune the given state_dict if desired for LayerDrop + (https://arxiv.org/abs/1909.11556). + + Training with LayerDrop allows models to be robust to pruning at inference + time. This function prunes state_dict to allow smaller models to be loaded + from a larger model and re-maps the existing state_dict for this to occur. + + It's called by functions that load models from checkpoints and does not + need to be called directly. + """ + if not args or args.arch == "ptt_transformer": + # args should not be none, but don't crash if it is. + return state_dict + + encoder_layers_to_keep = ( + args.encoder_layers_to_keep if "encoder_layers_to_keep" in vars(args) else None + ) + decoder_layers_to_keep = ( + args.decoder_layers_to_keep if "decoder_layers_to_keep" in vars(args) else None + ) + + if not encoder_layers_to_keep and not decoder_layers_to_keep: + return state_dict + + # apply pruning + logger.info( + "Pruning model to specified layer configuration - this works best if the model was trained with LayerDrop" + ) + + def create_pruning_pass(layers_to_keep, layer_name): + keep_layers = sorted( + [int(layer_string) for layer_string in layers_to_keep.split(",")] + ) + mapping_dict = {} + for i in range(len(keep_layers)): + mapping_dict[str(keep_layers[i])] = str(i) + + regex = re.compile(r"^{layer}.*\.layers\.(\d+)".format(layer=layer_name)) + return {"substitution_regex": regex, "mapping_dict": mapping_dict} + + pruning_passes = [] + if encoder_layers_to_keep: + pruning_passes.append(create_pruning_pass(encoder_layers_to_keep, "encoder")) + if decoder_layers_to_keep: + pruning_passes.append(create_pruning_pass(decoder_layers_to_keep, "decoder")) + + new_state_dict = {} + for layer_name in state_dict.keys(): + match = re.search(r"\.layers\.(\d+)\.", layer_name) + # if layer has no number in it, it is a supporting layer, such as an + # embedding + if not match: + new_state_dict[layer_name] = state_dict[layer_name] + continue + + # otherwise, layer should be pruned. + original_layer_number = match.group(1) + # figure out which mapping dict to replace from + for pruning_pass in pruning_passes: + if original_layer_number in pruning_pass["mapping_dict"] and pruning_pass[ + "substitution_regex" + ].search(layer_name): + new_layer_number = pruning_pass["mapping_dict"][original_layer_number] + substitution_match = pruning_pass["substitution_regex"].search( + layer_name + ) + new_state_key = ( + layer_name[: substitution_match.start(1)] + + new_layer_number + + layer_name[substitution_match.end(1) :] + ) + new_state_dict[new_state_key] = state_dict[layer_name] + + # Since layers are now pruned, *_layers_to_keep are no longer needed. + # This is more of "It would make it work fix" rather than a proper fix. + if "encoder_layers_to_keep" in vars(args): + args.encoder_layers_to_keep = None + if "decoder_layers_to_keep" in vars(args): + args.decoder_layers_to_keep = None + + return new_state_dict + + +def load_pretrained_component_from_model( + component: Union[FairseqEncoder, FairseqDecoder], checkpoint: str +): + """ + Load a pretrained FairseqEncoder or FairseqDecoder from checkpoint into the + provided `component` object. If state_dict fails to load, there may be a + mismatch in the architecture of the corresponding `component` found in the + `checkpoint` file. + """ + if not PathManager.exists(checkpoint): + raise IOError("Model file not found: {}".format(checkpoint)) + state = load_checkpoint_to_cpu(checkpoint) + if isinstance(component, FairseqEncoder): + component_type = "encoder" + elif isinstance(component, FairseqDecoder): + component_type = "decoder" + else: + raise ValueError( + "component to load must be either a FairseqEncoder or " + "FairseqDecoder. Loading other component types are not supported." + ) + component_state_dict = OrderedDict() + for key in state["model"].keys(): + if key.startswith(component_type): + # encoder.input_layers.0.0.weight --> input_layers.0.0.weight + component_subkey = key[len(component_type) + 1 :] + component_state_dict[component_subkey] = state["model"][key] + component.load_state_dict(component_state_dict, strict=True) + return component + + +def verify_checkpoint_directory(save_dir: str) -> None: + if not os.path.exists(save_dir): + os.makedirs(save_dir, exist_ok=True) + temp_file_path = os.path.join(save_dir, "dummy") + try: + with open(temp_file_path, "w"): + pass + except OSError as e: + logger.warning( + "Unable to access checkpoint save directory: {}".format(save_dir) + ) + raise e + else: + os.remove(temp_file_path) diff --git a/fairseq-tools/fairseq/fairseq/clib/libbleu/libbleu.cpp b/fairseq-tools/fairseq/fairseq/clib/libbleu/libbleu.cpp new file mode 100644 index 00000000..3cf2d65b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libbleu/libbleu.cpp @@ -0,0 +1,141 @@ +/** + * Copyright 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <map> +#include <array> +#include <cstring> +#include <cstdio> + +typedef struct +{ + size_t reflen; + size_t predlen; + size_t match1; + size_t count1; + size_t match2; + size_t count2; + size_t match3; + size_t count3; + size_t match4; + size_t count4; +} bleu_stat; + +// left trim (remove pad) +void bleu_ltrim(size_t* len, int** sent, int pad) { + size_t start = 0; + while(start < *len) { + if (*(*sent + start) != pad) { break; } + start++; + } + *sent += start; + *len -= start; +} + +// right trim remove (eos) +void bleu_rtrim(size_t* len, int** sent, int pad, int eos) { + size_t end = *len - 1; + while (end > 0) { + if (*(*sent + end) != eos && *(*sent + end) != pad) { break; } + end--; + } + *len = end + 1; +} + +// left and right trim +void bleu_trim(size_t* len, int** sent, int pad, int eos) { + bleu_ltrim(len, sent, pad); + bleu_rtrim(len, sent, pad, eos); +} + +size_t bleu_hash(int len, int* data) { + size_t h = 14695981039346656037ul; + size_t prime = 0x100000001b3; + char* b = (char*) data; + size_t blen = sizeof(int) * len; + + while (blen-- > 0) { + h ^= *b++; + h *= prime; + } + + return h; +} + +void bleu_addngram( + size_t *ntotal, size_t *nmatch, size_t n, + size_t reflen, int* ref, size_t predlen, int* pred) { + + if (predlen < n) { return; } + + predlen = predlen - n + 1; + (*ntotal) += predlen; + + if (reflen < n) { return; } + + reflen = reflen - n + 1; + + std::map<size_t, size_t> count; + while (predlen > 0) { + size_t w = bleu_hash(n, pred++); + count[w]++; + predlen--; + } + + while (reflen > 0) { + size_t w = bleu_hash(n, ref++); + if (count[w] > 0) { + (*nmatch)++; + count[w] -=1; + } + reflen--; + } +} + +extern "C" { + +#ifdef _WIN64 +__declspec(dllexport) +#endif +void bleu_zero_init(bleu_stat* stat) { + std::memset(stat, 0, sizeof(bleu_stat)); +} + +#ifdef _WIN64 +__declspec(dllexport) +#endif +void bleu_one_init(bleu_stat* stat) { + bleu_zero_init(stat); + stat->count1 = 0; + stat->count2 = 1; + stat->count3 = 1; + stat->count4 = 1; + stat->match1 = 0; + stat->match2 = 1; + stat->match3 = 1; + stat->match4 = 1; +} + +#ifdef _WIN64 +__declspec(dllexport) +#endif +void bleu_add( + bleu_stat* stat, + size_t reflen, int* ref, size_t predlen, int* pred, int pad, int eos) { + + bleu_trim(&reflen, &ref, pad, eos); + bleu_trim(&predlen, &pred, pad, eos); + stat->reflen += reflen; + stat->predlen += predlen; + + bleu_addngram(&stat->count1, &stat->match1, 1, reflen, ref, predlen, pred); + bleu_addngram(&stat->count2, &stat->match2, 2, reflen, ref, predlen, pred); + bleu_addngram(&stat->count3, &stat->match3, 3, reflen, ref, predlen, pred); + bleu_addngram(&stat->count4, &stat->match4, 4, reflen, ref, predlen, pred); +} + +} diff --git a/fairseq-tools/fairseq/fairseq/clib/libbleu/module.cpp b/fairseq-tools/fairseq/fairseq/clib/libbleu/module.cpp new file mode 100644 index 00000000..8ed9a84b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libbleu/module.cpp @@ -0,0 +1,37 @@ +/** + * Copyright 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <Python.h> + + +static PyMethodDef method_def[] = { + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef module_def = { + PyModuleDef_HEAD_INIT, + "libbleu", /* name of module */ + NULL, /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, + or -1 if the module keeps state in global variables. */ + method_def +}; + + +#if PY_MAJOR_VERSION == 2 +PyMODINIT_FUNC init_libbleu() +#else +PyMODINIT_FUNC PyInit_libbleu() +#endif +{ + PyObject *m = PyModule_Create(&module_def); + if (!m) { + return NULL; + } + return m; +} diff --git a/fairseq-tools/fairseq/fairseq/clib/libnat/edit_dist.cpp b/fairseq-tools/fairseq/fairseq/clib/libnat/edit_dist.cpp new file mode 100644 index 00000000..6bc6a937 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libnat/edit_dist.cpp @@ -0,0 +1,231 @@ +/** + * Copyright 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <torch/torch.h> // @manual=//caffe2:torch_extension +#include <pybind11/detail/common.h> +#include <pybind11/pybind11.h> +#include <vector> +#include <algorithm> +#include <cstdint> +#include <iosfwd> +#include <memory> +#include <new> +#include <string> +#include <utility> + +using namespace ::std; + +vector<vector<uint32_t>> edit_distance2_with_dp( + vector<uint32_t>& x, + vector<uint32_t>& y) { + uint32_t lx = x.size(); + uint32_t ly = y.size(); + vector<vector<uint32_t>> d(lx + 1, vector<uint32_t>(ly + 1)); + for (uint32_t i = 0; i < lx + 1; i++) { + d[i][0] = i; + } + for (uint32_t j = 0; j < ly + 1; j++) { + d[0][j] = j; + } + for (uint32_t i = 1; i < lx + 1; i++) { + for (uint32_t j = 1; j < ly + 1; j++) { + d[i][j] = + min(min(d[i - 1][j], d[i][j - 1]) + 1, + d[i - 1][j - 1] + 2 * (x.at(i - 1) == y.at(j - 1) ? 0 : 1)); + } + } + return d; +} + +vector<vector<uint32_t>> edit_distance2_backtracking( + vector<vector<uint32_t>>& d, + vector<uint32_t>& x, + vector<uint32_t>& y, + uint32_t terminal_symbol) { + vector<uint32_t> seq; + vector<vector<uint32_t>> edit_seqs(x.size() + 2, vector<uint32_t>()); + /* + edit_seqs: + 0~x.size() cell is the insertion sequences + last cell is the delete sequence + */ + + if (x.size() == 0) { + edit_seqs.at(0) = y; + return edit_seqs; + } + + uint32_t i = d.size() - 1; + uint32_t j = d.at(0).size() - 1; + + while ((i >= 0) && (j >= 0)) { + if ((i == 0) && (j == 0)) { + break; + } + + if ((j > 0) && (d.at(i).at(j - 1) < d.at(i).at(j))) { + seq.push_back(1); // insert + seq.push_back(y.at(j - 1)); + j--; + } else if ((i > 0) && (d.at(i - 1).at(j) < d.at(i).at(j))) { + seq.push_back(2); // delete + seq.push_back(x.at(i - 1)); + i--; + } else { + seq.push_back(3); // keep + seq.push_back(x.at(i - 1)); + i--; + j--; + } + } + + uint32_t prev_op, op, s, word; + prev_op = 0, s = 0; + for (uint32_t k = 0; k < seq.size() / 2; k++) { + op = seq.at(seq.size() - 2 * k - 2); + word = seq.at(seq.size() - 2 * k - 1); + if (prev_op != 1) { + s++; + } + if (op == 1) // insert + { + edit_seqs.at(s - 1).push_back(word); + } else if (op == 2) // delete + { + edit_seqs.at(x.size() + 1).push_back(1); + } else { + edit_seqs.at(x.size() + 1).push_back(0); + } + + prev_op = op; + } + + for (uint32_t k = 0; k < edit_seqs.size(); k++) { + if (edit_seqs[k].size() == 0) { + edit_seqs[k].push_back(terminal_symbol); + } + } + return edit_seqs; +} + +vector<vector<uint32_t>> edit_distance2_backtracking_with_delete( + vector<vector<uint32_t>>& d, + vector<uint32_t>& x, + vector<uint32_t>& y, + uint32_t terminal_symbol, + uint32_t deletion_symbol) { + vector<uint32_t> seq; + vector<vector<uint32_t>> edit_seqs(x.size() + 1, vector<uint32_t>()); + /* + edit_seqs: + 0~x.size() cell is the insertion sequences + last cell is the delete sequence + */ + + if (x.size() == 0) { + edit_seqs.at(0) = y; + return edit_seqs; + } + + uint32_t i = d.size() - 1; + uint32_t j = d.at(0).size() - 1; + + while ((i >= 0) && (j >= 0)) { + if ((i == 0) && (j == 0)) { + break; + } + + if ((j > 0) && (d.at(i).at(j - 1) < d.at(i).at(j))) { + seq.push_back(1); // insert + seq.push_back(y.at(j - 1)); + j--; + } else if ((i > 0) && (d.at(i - 1).at(j) < d.at(i).at(j))) { + seq.push_back(2); // delete + seq.push_back(x.at(i - 1)); + i--; + } else { + seq.push_back(3); // keep + seq.push_back(x.at(i - 1)); + i--; + j--; + } + } + + uint32_t prev_op, op, s, word; + prev_op = 0, s = 0; + for (uint32_t k = 0; k < seq.size() / 2; k++) { + op = seq.at(seq.size() - 2 * k - 2); + word = seq.at(seq.size() - 2 * k - 1); + if (prev_op != 1) { + s++; + } + if (op == 1) // insert + { + edit_seqs.at(s - 1).push_back(word); + } else if (op == 2) // delete + { + edit_seqs.at(s - 1).push_back(deletion_symbol); + } + + prev_op = op; + } + + for (uint32_t k = 0; k < edit_seqs.size(); k++) { + if (edit_seqs.at(k).size() == 0) { + edit_seqs.at(k).push_back(terminal_symbol); + } + } + return edit_seqs; +} + +vector<uint32_t> compute_ed2( + vector<vector<uint32_t>>& xs, + vector<vector<uint32_t>>& ys) { + vector<uint32_t> distances(xs.size()); + for (uint32_t i = 0; i < xs.size(); i++) { + vector<vector<uint32_t>> d = edit_distance2_with_dp(xs.at(i), ys.at(i)); + distances.at(i) = d.at(xs.at(i).size()).at(ys.at(i).size()); + } + return distances; +} + +vector<vector<vector<uint32_t>>> suggested_ed2_path( + vector<vector<uint32_t>>& xs, + vector<vector<uint32_t>>& ys, + uint32_t terminal_symbol) { + vector<vector<vector<uint32_t>>> seq(xs.size()); + for (uint32_t i = 0; i < xs.size(); i++) { + vector<vector<uint32_t>> d = edit_distance2_with_dp(xs.at(i), ys.at(i)); + seq.at(i) = + edit_distance2_backtracking(d, xs.at(i), ys.at(i), terminal_symbol); + } + return seq; +} + +vector<vector<vector<uint32_t>>> suggested_ed2_path_with_delete( + vector<vector<uint32_t>>& xs, + vector<vector<uint32_t>>& ys, + uint32_t terminal_symbol, + uint32_t deletion_symbol) { + vector<vector<vector<uint32_t>>> seq(xs.size()); + for (uint32_t i = 0; i < xs.size(); i++) { + vector<vector<uint32_t>> d = edit_distance2_with_dp(xs.at(i), ys.at(i)); + seq.at(i) = edit_distance2_backtracking_with_delete( + d, xs.at(i), ys.at(i), terminal_symbol, deletion_symbol); + } + return seq; +} + +PYBIND11_MODULE(libnat, m) { + m.def("compute_ed2", &compute_ed2, "compute_ed2"); + m.def("suggested_ed2_path", &suggested_ed2_path, "suggested_ed2_path"); + m.def( + "suggested_ed2_path_with_delete", + &suggested_ed2_path_with_delete, + "suggested_ed2_path_with_delete"); +} diff --git a/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/binding.cpp b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/binding.cpp new file mode 100644 index 00000000..aaa6244d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/binding.cpp @@ -0,0 +1,60 @@ +/** + * Copyright 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* + This code is partially adpoted from https://github.com/1ytic/pytorch-edit-distance + */ + +#include "edit_dist.h" +#include <torch/types.h> + +#ifndef TORCH_CHECK +#define TORCH_CHECK AT_CHECK +#endif + +#define CHECK_CUDA(x) TORCH_CHECK(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + + +torch::Tensor LevenshteinDistance( + torch::Tensor source, + torch::Tensor target, + torch::Tensor source_length, + torch::Tensor target_length) { + + CHECK_INPUT(source); + CHECK_INPUT(target); + CHECK_INPUT(source_length); + CHECK_INPUT(target_length); + return LevenshteinDistanceCuda(source, target, source_length, target_length); +} + +torch::Tensor GenerateDeletionLabel( + torch::Tensor source, + torch::Tensor operations) { + + CHECK_INPUT(source); + CHECK_INPUT(operations); + return GenerateDeletionLabelCuda(source, operations); +} + +std::pair<torch::Tensor, torch::Tensor> GenerateInsertionLabel( + torch::Tensor target, + torch::Tensor operations) { + + CHECK_INPUT(target); + CHECK_INPUT(operations); + return GenerateInsertionLabelCuda(target, operations); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("levenshtein_distance", &LevenshteinDistance, "Levenshtein distance"); + m.def("generate_deletion_labels", &GenerateDeletionLabel, "Generate Deletion Label"); + m.def("generate_insertion_labels", &GenerateInsertionLabel, "Generate Insertion Label"); +} diff --git a/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.cu b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.cu new file mode 100644 index 00000000..22de16b2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.cu @@ -0,0 +1,332 @@ +/** +* Copyright 2017-present, Facebook, Inc. +* All rights reserved. +* +* This source code is licensed under the license found in the +* LICENSE file in the root directory of this source tree. +*/ + +#include "edit_dist.h" +#include <THC/THC.h> +#include <cuda.h> +#include <cuda_runtime.h> +#include <device_launch_parameters.h> +#include <utility> // std::pair + +template <typename scalar_t> +__global__ void generate_deletion_label_kernel( + const scalar_t* __restrict__ source, + const size_t source_size, + const size_t operation_size, + int* __restrict__ operations, + int* __restrict__ labels) { + + const int index = blockIdx.x; + const int offset = index * operation_size; + const int offset_label = index * source_size; + + for (int i = 0; i < source_size; i++) { + labels[offset_label + i] = 0; + } + + int k = 0; + for (int i = 0; i < operation_size; i++){ + if (operations[offset + i] == 0){ + break; + } else if (operations[offset + i] == 1){ + continue; + } else { + labels[offset_label + k] = 3 - operations[offset + i]; + k++; + } + } +} + +template <typename scalar_t> +__global__ void generate_insertion_label_kernel( + const scalar_t* __restrict__ target, + const size_t target_size, + const size_t operation_size, + int* __restrict__ operations, + int* __restrict__ labels, + int* __restrict__ masks) { + + const int index = blockIdx.x; + const int offset = index * operation_size; + const int offset_label = index * target_size; + + int k = 0; + int u = 0; + int m = 0; + + for (int i = 0; i < target_size; i++) { + labels[offset_label + i] = 0; + masks[offset_label + i] = 0; + } + + for (int i = 0; i < operation_size-1; i++){ + if (operations[offset + i] == 0){ + break; + } else if (operations[offset + i] == 2){ + continue; + } else if (operations[offset + i] == 1){ + masks[offset_label + m] = 1; + u++; m++; + } else { + labels[offset_label + k] = u; + masks[offset_label + m] = 0; + k++; m++; + u = 0; + } + } +} + +template <typename scalar_t> +__global__ void levenshtein_distance_kernel( + const scalar_t* __restrict__ source, + const scalar_t* __restrict__ target, + const int* __restrict__ source_length, + const int* __restrict__ target_length, + const size_t source_size, + const size_t target_size, + int* __restrict__ operations, + int* __restrict__ errors_curr) { + + const int index = blockIdx.x; + const int offset = index * (source_size + target_size); + const int d = index * (source_size + 1) * (target_size + 1); + const int t = target_size + 1; + + auto err_idx = [d, t](int i, int j) { return d + i * t + j; }; + auto opt_idx = [offset](int k) { return offset + k; }; + + const int hyp_len = source_length[index]; + const int ref_len = target_length[index]; + const scalar_t* hyp_begin = source + index * source_size; + const scalar_t* ref_begin = target + index * target_size; + + // dynamic programming + for (int i = 0; i <= hyp_len; i++){ + errors_curr[err_idx(i, 0)] = i; + } + for (int j = 0; j <= ref_len; j++){ + errors_curr[err_idx(0, j)] = j; + } + for (int i = 1; i <= hyp_len; i++){ + for (int j = 1; j <= ref_len; j++){ + errors_curr[err_idx(i, j)] = min( + min( + errors_curr[err_idx(i-1, j)], + errors_curr[err_idx(i, j-1)] + ) + 1, + errors_curr[err_idx(i-1, j-1)] + 2 * ( + *(hyp_begin+i-1) == *(ref_begin+j-1) ? 0 : 1 + ) + ); + } + } + + // back-tracing + int i = hyp_len; + int j = ref_len; + int o = hyp_len + ref_len; + + for (int k = 0; k < source_size + target_size; k++) { + operations[opt_idx(k)] = 0; + } + + while ((i >= 0) && (j >= 0)) { + if ((i == 0) && (j == 0)) { + break; + } + + if ((j > 0) && (errors_curr[err_idx(i, j-1)] < errors_curr[err_idx(i, j)])) { + o--; operations[opt_idx(o)] = 1; j--; // insertion + } else if ((i > 0) && (errors_curr[err_idx(i-1, j)] < errors_curr[err_idx(i, j)])) { + o--; operations[opt_idx(o)] = 2; i--; // deletion + } else { + o--; operations[opt_idx(o)] = 3; i--; j--; // do nothing + } + } + + // moving to the left + for (int k = 0; k < hyp_len + ref_len; k++) { + if (k + o < hyp_len + ref_len){ + operations[opt_idx(k)] = operations[opt_idx(k+o)]; + } else{ + operations[opt_idx(k)] = 0; // padding + } + } + +} + +template <typename scalar_t> +__global__ void faster_levenshtein_distance_kernel( + const scalar_t* __restrict__ source, + const scalar_t* __restrict__ target, + const int* __restrict__ source_length, + const int* __restrict__ target_length, + const size_t source_size, + const size_t target_size, + int* __restrict__ operations) { + + extern __shared__ short errors[]; + auto errors_curr = errors; + + const int index = blockIdx.x; + const int offset = index * (source_size + target_size); + const int t = target_size + 1; + + auto err_idx = [t](int i, int j) { return i * t + j; }; + auto opt_idx = [offset](int k) { return offset + k; }; + + const int hyp_len = source_length[index]; + const int ref_len = target_length[index]; + const scalar_t* hyp_begin = source + index * source_size; + const scalar_t* ref_begin = target + index * target_size; + + // dynamic programming + for (int i = 0; i <= hyp_len; i++){ + errors_curr[err_idx(i, 0)] = i; + } + for (int j = 0; j <= ref_len; j++){ + errors_curr[err_idx(0, j)] = j; + } + for (int i = 1; i <= hyp_len; i++){ + for (int j = 1; j <= ref_len; j++){ + errors_curr[err_idx(i, j)] = min( + min( + errors_curr[err_idx(i-1, j)], + errors_curr[err_idx(i, j-1)] + ) + 1, + errors_curr[err_idx(i-1, j-1)] + 2 * ( + *(hyp_begin+i-1) == *(ref_begin+j-1) ? 0 : 1 + ) + ); + } + } + + // back-tracing + int i = hyp_len; + int j = ref_len; + int o = hyp_len + ref_len; + + for (int k = 0; k < source_size + target_size; k++) { + operations[opt_idx(k)] = 0; + } + + while ((i >= 0) && (j >= 0)) { + if ((i == 0) && (j == 0)) { + break; + } + + if ((j > 0) && (errors_curr[err_idx(i, j-1)] < errors_curr[err_idx(i, j)])) { + o--; operations[opt_idx(o)] = 1; j--; // insertion + } else if ((i > 0) && (errors_curr[err_idx(i-1, j)] < errors_curr[err_idx(i, j)])) { + o--; operations[opt_idx(o)] = 2; i--; // deletion + } else { + o--; operations[opt_idx(o)] = 3; i--; j--; // do nothing + } + } + + // moving to the left + for (int k = 0; k < hyp_len + ref_len; k++) { + if (k + o < hyp_len + ref_len){ + operations[opt_idx(k)] = operations[opt_idx(k+o)]; + } else{ + operations[opt_idx(k)] = 0; // padding + } + } + +} + + +torch::Tensor GenerateDeletionLabelCuda( + torch::Tensor source, + torch::Tensor operations) { + + const auto batch_size = source.size(0); + at::TensorOptions options(source.device()); + options = options.dtype(at::ScalarType::Int); + auto labels = torch::empty({batch_size, source.size(1)}, options); + auto stream = at::cuda::getCurrentCUDAStream(source.device().index()); + + AT_DISPATCH_ALL_TYPES(source.scalar_type(), "generate_deletion_labels", ([&] { + generate_deletion_label_kernel<scalar_t><<<batch_size, 1, 0, stream>>>( + source.data_ptr<scalar_t>(), + source.size(1), + operations.size(1), + operations.data_ptr<int>(), + labels.data_ptr<int>()); + })); + + return labels; +} + +std::pair<torch::Tensor, torch::Tensor> GenerateInsertionLabelCuda( + torch::Tensor target, + torch::Tensor operations) { + +const auto batch_size = target.size(0); +at::TensorOptions options(target.device()); +options = options.dtype(at::ScalarType::Int); +auto labels = torch::empty({batch_size, target.size(1)}, options); +auto masks = torch::empty({batch_size, target.size(1)}, options); +auto stream = at::cuda::getCurrentCUDAStream(target.device().index()); + +AT_DISPATCH_ALL_TYPES(target.scalar_type(), "generate_insertion_labels", ([&] { + generate_insertion_label_kernel<scalar_t><<<batch_size, 1, 0, stream>>>( + target.data_ptr<scalar_t>(), + target.size(1), + operations.size(1), + operations.data_ptr<int>(), + labels.data_ptr<int>(), + masks.data_ptr<int>()); +})); + +return std::make_pair(labels, masks); +} + + +torch::Tensor LevenshteinDistanceCuda( + torch::Tensor source, + torch::Tensor target, + torch::Tensor source_length, + torch::Tensor target_length) { + + const auto batch_size = source.size(0); + const auto shared_size = (source.size(1) + 1) * (target.size(1) + 1) * sizeof(short); + + at::TensorOptions options(source.device()); + options = options.dtype(at::ScalarType::Int); + auto operations = torch::empty({batch_size, source.size(1) + target.size(1)}, options); + auto stream = at::cuda::getCurrentCUDAStream(source.device().index()); + + if (shared_size > 40000) { + auto distances = torch::empty({batch_size, (source.size(1) + 1) * (target.size(1) + 1)}, options); + AT_DISPATCH_ALL_TYPES(source.scalar_type(), "levenshtein_distance", ([&] { + levenshtein_distance_kernel<scalar_t><<<batch_size, 1, 0, stream>>>( + source.data_ptr<scalar_t>(), + target.data_ptr<scalar_t>(), + source_length.data_ptr<int>(), + target_length.data_ptr<int>(), + source.size(1), + target.size(1), + operations.data_ptr<int>(), + distances.data_ptr<int>()); + })); + } else { + AT_DISPATCH_ALL_TYPES(source.scalar_type(), "faster_levenshtein_distance", ([&] { + faster_levenshtein_distance_kernel<scalar_t><<<batch_size, 1, shared_size, stream>>>( + source.data_ptr<scalar_t>(), + target.data_ptr<scalar_t>(), + source_length.data_ptr<int>(), + target_length.data_ptr<int>(), + source.size(1), + target.size(1), + operations.data_ptr<int>()); + })); + } + + return operations; +} diff --git a/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.h b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.h new file mode 100644 index 00000000..e3506cd3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/clib/libnat_cuda/edit_dist.h @@ -0,0 +1,25 @@ +/** + * Copyright 2017-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include <torch/extension.h> + +torch::Tensor LevenshteinDistanceCuda( + torch::Tensor source, + torch::Tensor target, + torch::Tensor source_length, + torch::Tensor target_length); + +torch::Tensor GenerateDeletionLabelCuda( + torch::Tensor source, + torch::Tensor operations); + +std::pair<torch::Tensor, torch::Tensor> GenerateInsertionLabelCuda( + torch::Tensor source, + torch::Tensor operations); diff --git a/fairseq-tools/fairseq/fairseq/criterions/__init__.py b/fairseq-tools/fairseq/fairseq/criterions/__init__.py new file mode 100644 index 00000000..a7eb5f6f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/__init__.py @@ -0,0 +1,38 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +import importlib +import os +from argparse import Namespace +from typing import Union + +from fairseq import registry +from fairseq.criterions.fairseq_criterion import ( # noqa + FairseqCriterion, + LegacyFairseqCriterion, +) +from omegaconf import DictConfig + + +( + build_criterion_, + register_criterion, + CRITERION_REGISTRY, + CRITERION_DATACLASS_REGISTRY, +) = registry.setup_registry( + "--criterion", base_class=FairseqCriterion, default="cross_entropy" +) + + +def build_criterion(criterion_cfg: Union[DictConfig, Namespace], task): + return build_criterion_(criterion_cfg, task) + + +# automatically import any Python files in the criterions/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + file_name = file[: file.find(".py")] + importlib.import_module("fairseq.criterions." + file_name) diff --git a/fairseq-tools/fairseq/fairseq/criterions/adaptive_loss.py b/fairseq-tools/fairseq/fairseq/criterions/adaptive_loss.py new file mode 100644 index 00000000..74ba37c3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/adaptive_loss.py @@ -0,0 +1,123 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from dataclasses import dataclass + +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from fairseq.dataclass import FairseqDataclass +from fairseq.dataclass.constants import DDP_BACKEND_CHOICES +from omegaconf import II + + +@dataclass +class AdaptiveLossConfig(FairseqDataclass): + sentence_avg: bool = II("params.optimization.sentence_avg") + ddp_backend: DDP_BACKEND_CHOICES = II("params.distributed_training.ddp_backend") + + +@register_criterion("adaptive_loss", dataclass=AdaptiveLossConfig) +class AdaptiveLoss(FairseqCriterion): + """This is an implementation of the loss function accompanying the adaptive softmax approximation for + graphical processing units (GPU), described in the paper "Efficient softmax approximation for GPUs" + (http://arxiv.org/abs/1609.04309).""" + + def __init__(self, task, sentence_avg): + super().__init__(task) + self.sentence_avg = sentence_avg + + @classmethod + def build_criterion(cls, args, task): + if getattr(args, "ddp_backend", None) == "c10d": + raise Exception( + "AdaptiveLoss is not compatible with the c10d " + "version of DistributedDataParallel. Please use " + "`--ddp-backend=no_c10d` instead." + ) + return cls(task, args.sentence_avg) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + + assert ( + hasattr(model.decoder, "adaptive_softmax") + and model.decoder.adaptive_softmax is not None + ) + adaptive_softmax = model.decoder.adaptive_softmax + + net_output = model(**sample["net_input"]) + orig_target = model.get_targets(sample, net_output) + + nsentences = orig_target.size(0) + orig_target = orig_target.view(-1) + + bsz = orig_target.size(0) + + logits, target = adaptive_softmax(net_output[0], orig_target) + assert len(target) == len(logits) + + loss = net_output[0].new(1 if reduce else bsz).zero_() + + for i in range(len(target)): + if target[i] is not None: + assert target[i].min() >= 0 and target[i].max() <= logits[i].size(1) + loss += F.cross_entropy( + logits[i], + target[i], + ignore_index=self.padding_idx, + reduction="sum" if reduce else "none", + ) + + orig = utils.strip_pad(orig_target, self.padding_idx) + ntokens = orig.numel() + sample_size = sample["target"].size(0) if self.sentence_avg else ntokens + logging_output = { + "loss": loss.data, + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = utils.item(sum(log.get("loss", 0) for log in logging_outputs)) + ntokens = utils.item(sum(log.get("ntokens", 0) for log in logging_outputs)) + sample_size = utils.item( + sum(log.get("sample_size", 0) for log in logging_outputs) + ) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + else: + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/composite_loss.py b/fairseq-tools/fairseq/fairseq/criterions/composite_loss.py new file mode 100644 index 00000000..98e835fa --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/composite_loss.py @@ -0,0 +1,100 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import utils +from fairseq.criterions import LegacyFairseqCriterion, register_criterion +from torch import nn + + +@register_criterion("composite_loss") +class CompositeLoss(LegacyFairseqCriterion): + """This is a composite loss that, given a list of model outputs and a list of targets, + computes an average of losses for each output-target pair""" + + def __init__(self, args, task): + super().__init__(args, task) + self.underlying_criterion = args.underlying_criterion + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--underlying-criterion', type=str, metavar='VAL', required=True, + help='underlying criterion to use for the composite loss') + # fmt: on + + @staticmethod + def build_underlying_criterion(args, task): + saved_criterion = args.criterion + args.criterion = args.underlying_criterion + assert saved_criterion != args.underlying_criterion + underlying_criterion = task.build_criterion(args) + args.criterion = saved_criterion + return underlying_criterion + + @classmethod + def build_criterion(cls, args, task): + underlying_criterion = CompositeLoss.build_underlying_criterion(args, task) + + class FakeModel(nn.Module): + def __init__(self, model, net_out, target): + super().__init__() + self.model = model + self.net_out = net_out + self.target = target + + def forward(self, **unused): + return self.net_out + + def get_normalized_probs(self, net_output, log_probs, sample=None): + return self.model.get_normalized_probs( + net_output, log_probs, sample=sample + ) + + def get_targets(self, *unused): + return self.target + + @property + def decoder(self): + return self.model.decoder + + class _CompositeLoss(LegacyFairseqCriterion): + def __init__(self, args, task, underlying_criterion): + super().__init__(args, task) + self.underlying_criterion = underlying_criterion + + def forward(self, model, sample, reduce=True): + net_outputs = model(**sample["net_input"]) + targets = sample["target"] + + bsz = targets[0].size(0) + loss = net_outputs[0][0].new(1 if reduce else bsz).float().zero_() + + sample_size = 0 + logging_output = {} + for o, t in zip(net_outputs[0], targets): + m = FakeModel(model, (o, net_outputs[1]), t) + sample["target"] = t + l, ss, logging_output = self.underlying_criterion(m, sample, reduce) + loss += l + sample_size += ss + + loss.div_(len(targets)) + sample_size /= len(targets) + + logging_output["loss"] = utils.item(loss.data) if reduce else loss.data + return loss, sample_size, logging_output + + @staticmethod + def aggregate_logging_outputs(logging_outputs): + return underlying_criterion.__class__.aggregate_logging_outputs( + logging_outputs + ) + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + underlying_criterion.__class__.reduce_metrics(logging_outputs) + + return _CompositeLoss(args, task, underlying_criterion) diff --git a/fairseq-tools/fairseq/fairseq/criterions/cross_entropy.py b/fairseq-tools/fairseq/fairseq/criterions/cross_entropy.py new file mode 100644 index 00000000..66500bf2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/cross_entropy.py @@ -0,0 +1,90 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from dataclasses import dataclass + +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from fairseq.dataclass import FairseqDataclass +from omegaconf import II + + +@dataclass +class CrossEntropyCriterionConfig(FairseqDataclass): + sentence_avg: bool = II("params.optimization.sentence_avg") + + +@register_criterion("cross_entropy", dataclass=CrossEntropyCriterionConfig) +class CrossEntropyCriterion(FairseqCriterion): + def __init__(self, task, sentence_avg): + super().__init__(task) + self.sentence_avg = sentence_avg + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"]) + loss, _ = self.compute_loss(model, net_output, sample, reduce=reduce) + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + def compute_loss(self, model, net_output, sample, reduce=True): + lprobs = model.get_normalized_probs(net_output, log_probs=True) + lprobs = lprobs.view(-1, lprobs.size(-1)) + target = model.get_targets(sample, net_output).view(-1) + loss = F.nll_loss( + lprobs, + target, + ignore_index=self.padding_idx, + reduction="sum" if reduce else "none", + ) + return loss, loss + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + # we divide by log(2) to convert the loss from base e to base 2 + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + else: + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/ctc.py b/fairseq-tools/fairseq/fairseq/criterions/ctc.py new file mode 100644 index 00000000..4f93b3cb --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/ctc.py @@ -0,0 +1,253 @@ +# All rights reserved. +# +# This source code is licensed under the license found in the LICENSE file in +# the root directory of this source tree. An additional grant of patent rights +# can be found in the PATENTS file in the same directory. + +import math +from argparse import Namespace + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from fairseq.data.data_utils import post_process +from fairseq.logging.meters import safe_round + + +@register_criterion("ctc") +class CtcCriterion(FairseqCriterion): + def __init__(self, task, wer_args, zero_infinity, sentence_avg, remove_bpe): + super().__init__(task) + self.blank_idx = task.target_dictionary.bos() + self.pad_idx = task.target_dictionary.pad() + self.eos_idx = task.target_dictionary.eos() + self.post_process = remove_bpe if remove_bpe else "letter" + + if wer_args is not None: + from examples.speech_recognition.w2l_decoder import W2lKenLMDecoder + + wer_compute_kenlm, wer_lexicon, lm_w, ws_w = eval(wer_args) + + dec_args = Namespace() + dec_args.nbest = 1 + dec_args.criterion = "ctc" + dec_args.kenlm_model = wer_compute_kenlm + dec_args.lexicon = wer_lexicon + dec_args.beam = 50 + dec_args.beam_size_token = min(50, len(task.target_dictionary)) + dec_args.beam_threshold = min(50, len(task.target_dictionary)) + dec_args.lm_weight = lm_w + dec_args.word_score = ws_w + dec_args.unk_weight = -math.inf + dec_args.sil_weight = 0 + + self.w2l_decoder = W2lKenLMDecoder(dec_args, task.target_dictionary) + else: + self.w2l_decoder = None + + self.zero_infinity = zero_infinity + self.sentence_avg = sentence_avg + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + parser.add_argument( + "--zero-infinity", action="store_true", help="zero inf loss" + ) + try: + parser.add_argument( + "--remove-bpe", + "--post-process", + default="letter", + help="remove BPE tokens before scoring (can be set to sentencepiece, letter, and more)", + ) + except: + pass # this option might have been added from eval args + parser.add_argument( + "--wer-args", + type=str, + default=None, + help="options for wer computation on valid set using 4 gram lm. this should be a tuple of 4 elements: path to 4-gram lm, \ + path to lexicon, lm score, word score", + ) + + def forward(self, model, sample, reduce=True): + net_output = model(**sample["net_input"]) + lprobs = model.get_normalized_probs( + net_output, log_probs=True + ).contiguous() # (T, B, C) from the encoder + + if "src_lengths" in sample["net_input"]: + input_lengths = sample["net_input"]["src_lengths"] + else: + non_padding_mask = ~net_output["padding_mask"] + input_lengths = non_padding_mask.long().sum(-1) + + pad_mask = (sample["target"] != self.pad_idx) & ( + sample["target"] != self.eos_idx + ) + targets_flat = sample["target"].masked_select(pad_mask) + target_lengths = sample["target_lengths"] + + with torch.backends.cudnn.flags(enabled=False): + loss = F.ctc_loss( + lprobs, + targets_flat, + input_lengths, + target_lengths, + blank=self.blank_idx, + reduction="sum", + zero_infinity=self.zero_infinity, + ) + + ntokens = ( + sample["ntokens"] if "ntokens" in sample else target_lengths.sum().item() + ) + + sample_size = sample["target"].size(0) if self.sentence_avg else ntokens + logging_output = { + "loss": utils.item(loss.data), # * sample['ntokens'], + "ntokens": ntokens, + "nsentences": sample["id"].numel(), + "sample_size": sample_size, + } + + if not model.training: + import editdistance + + with torch.no_grad(): + lprobs_t = lprobs.transpose(0, 1).float().contiguous().cpu() + + c_err = 0 + c_len = 0 + w_errs = 0 + w_len = 0 + wv_errs = 0 + for lp, t, inp_l in zip( + lprobs_t, + sample["target_label"] + if "target_label" in sample + else sample["target"], + input_lengths, + ): + lp = lp[:inp_l].unsqueeze(0) + + decoded = None + if self.w2l_decoder is not None: + decoded = self.w2l_decoder.decode(lp) + if len(decoded) < 1: + decoded = None + else: + decoded = decoded[0] + if len(decoded) < 1: + decoded = None + else: + decoded = decoded[0] + + p = (t != self.task.target_dictionary.pad()) & ( + t != self.task.target_dictionary.eos() + ) + targ = t[p] + targ_units = self.task.target_dictionary.string(targ) + targ_units_arr = targ.tolist() + + toks = lp.argmax(dim=-1).unique_consecutive() + pred_units_arr = toks[toks != self.blank_idx].tolist() + + c_err += editdistance.eval(pred_units_arr, targ_units_arr) + c_len += len(targ_units_arr) + + targ_words = post_process(targ_units, self.post_process).split() + + pred_units = self.task.target_dictionary.string(pred_units_arr) + pred_words_raw = post_process(pred_units, self.post_process).split() + + if decoded is not None and "words" in decoded: + pred_words = decoded["words"] + w_errs += editdistance.eval(pred_words, targ_words) + wv_errs += editdistance.eval(pred_words_raw, targ_words) + else: + dist = editdistance.eval(pred_words_raw, targ_words) + w_errs += dist + wv_errs += dist + + w_len += len(targ_words) + + logging_output["wv_errors"] = wv_errs + logging_output["w_errors"] = w_errs + logging_output["w_total"] = w_len + logging_output["c_errors"] = c_err + logging_output["c_total"] = c_len + + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + + loss_sum = utils.item(sum(log.get("loss", 0) for log in logging_outputs)) + ntokens = utils.item(sum(log.get("ntokens", 0) for log in logging_outputs)) + nsentences = utils.item( + sum(log.get("nsentences", 0) for log in logging_outputs) + ) + sample_size = utils.item( + sum(log.get("sample_size", 0) for log in logging_outputs) + ) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar("ntokens", ntokens) + metrics.log_scalar("nsentences", nsentences) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + + c_errors = sum(log.get("c_errors", 0) for log in logging_outputs) + metrics.log_scalar("_c_errors", c_errors) + c_total = sum(log.get("c_total", 0) for log in logging_outputs) + metrics.log_scalar("_c_total", c_total) + w_errors = sum(log.get("w_errors", 0) for log in logging_outputs) + metrics.log_scalar("_w_errors", w_errors) + wv_errors = sum(log.get("wv_errors", 0) for log in logging_outputs) + metrics.log_scalar("_wv_errors", wv_errors) + w_total = sum(log.get("w_total", 0) for log in logging_outputs) + metrics.log_scalar("_w_total", w_total) + + if c_total > 0: + metrics.log_derived( + "uer", + lambda meters: safe_round( + meters["_c_errors"].sum * 100.0 / meters["_c_total"].sum, 3 + ) + if meters["_c_total"].sum > 0 + else float("nan"), + ) + if w_total > 0: + metrics.log_derived( + "wer", + lambda meters: safe_round( + meters["_w_errors"].sum * 100.0 / meters["_w_total"].sum, 3 + ) + if meters["_w_total"].sum > 0 + else float("nan"), + ) + metrics.log_derived( + "raw_wer", + lambda meters: safe_round( + meters["_wv_errors"].sum * 100.0 / meters["_w_total"].sum, 3 + ) + if meters["_w_total"].sum > 0 + else float("nan"), + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/fairseq_criterion.py b/fairseq-tools/fairseq/fairseq/criterions/fairseq_criterion.py new file mode 100644 index 00000000..ef94a863 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/fairseq_criterion.py @@ -0,0 +1,119 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import inspect +from typing import Any, Dict, List + +from fairseq import metrics, utils +from fairseq.dataclass.utils import gen_parser_from_dataclass +from torch.nn.modules.loss import _Loss + + +class FairseqCriterion(_Loss): + def __init__(self, task): + super().__init__() + self.task = task + if hasattr(task, "target_dictionary"): + tgt_dict = task.target_dictionary + self.padding_idx = tgt_dict.pad() if tgt_dict is not None else -100 + + @classmethod + def add_args(cls, parser): + """Add criterion-specific arguments to the parser.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + gen_parser_from_dataclass(parser, dc()) + + @classmethod + def build_criterion(cls, args, task): + """Construct a criterion from command-line args.""" + # Criterions can override this, but for convenience we also try + # to automatically map argparse.Namespace keys to corresponding + # arguments in the __init__. + init_args = {} + for p in inspect.signature(cls).parameters.values(): + if ( + p.kind == p.POSITIONAL_ONLY + or p.kind == p.VAR_POSITIONAL + or p.kind == p.VAR_KEYWORD + ): + # we haven't implemented inference for these argument types, + # but PRs welcome :) + raise NotImplementedError("{} not supported".format(p.kind)) + + assert p.kind in {p.POSITIONAL_OR_KEYWORD, p.KEYWORD_ONLY} + + if p.name == "task": + init_args["task"] = task + elif hasattr(args, p.name): + init_args[p.name] = getattr(args, p.name) + elif p.default != p.empty: + pass # we'll use the default value + else: + raise NotImplementedError( + "Unable to infer Criterion arguments, please implement " + "{}.build_criterion".format(cls.__name__) + ) + return cls(**init_args) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + raise NotImplementedError + + @staticmethod + def aggregate_logging_outputs( + logging_outputs: List[Dict[str, Any]], + ) -> Dict[str, Any]: + """Aggregate logging outputs from data parallel training.""" + utils.deprecation_warning( + "The aggregate_logging_outputs API is deprecated. " + "Please use the reduce_metrics API instead." + ) + raise NotImplementedError + + @classmethod + def reduce_metrics(cls, logging_outputs: List[Dict[str, Any]]) -> None: + """Aggregate logging outputs from data parallel training.""" + utils.deprecation_warning( + "Criterions should implement the reduce_metrics API. " + "Falling back to deprecated aggregate_logging_outputs API." + ) + agg_logging_outputs = cls.aggregate_logging_outputs(logging_outputs) + for k, v in agg_logging_outputs.items(): + if k in {"nsentences", "ntokens", "sample_size"}: + continue + metrics.log_scalar(k, v) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return False + + +class LegacyFairseqCriterion(FairseqCriterion): + def __init__(self, args, task): + super().__init__(task=task) + self.args = args + + utils.deprecation_warning( + "Criterions should take explicit arguments instead of an " + "argparse.Namespace object, please update your criterion by " + "extending FairseqCriterion instead of LegacyFairseqCriterion." + ) + + @classmethod + def build_criterion(cls, args, task): + """Construct a criterion from command-line args.""" + return cls(args, task) diff --git a/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy.py b/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy.py new file mode 100644 index 00000000..2dc7f7a4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy.py @@ -0,0 +1,160 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +def label_smoothed_nll_loss(lprobs, target, epsilon, ignore_index=None, reduce=True): + if target.dim() == lprobs.dim() - 1: + target = target.unsqueeze(-1) + nll_loss = -lprobs.gather(dim=-1, index=target) + smooth_loss = -lprobs.sum(dim=-1, keepdim=True) + if ignore_index is not None: + pad_mask = target.eq(ignore_index) + nll_loss.masked_fill_(pad_mask, 0.0) + smooth_loss.masked_fill_(pad_mask, 0.0) + else: + nll_loss = nll_loss.squeeze(-1) + smooth_loss = smooth_loss.squeeze(-1) + if reduce: + nll_loss = nll_loss.sum() + smooth_loss = smooth_loss.sum() + eps_i = epsilon / lprobs.size(-1) + loss = (1.0 - epsilon) * nll_loss + eps_i * smooth_loss + return loss, nll_loss + + +@register_criterion("label_smoothed_cross_entropy") +class LabelSmoothedCrossEntropyCriterion(FairseqCriterion): + def __init__( + self, + task, + sentence_avg, + label_smoothing, + ignore_prefix_size=0, + report_accuracy=False, + ): + super().__init__(task) + self.sentence_avg = sentence_avg + self.eps = label_smoothing + self.ignore_prefix_size = ignore_prefix_size + self.report_accuracy = report_accuracy + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--label-smoothing', default=0., type=float, metavar='D', + help='epsilon for label smoothing, 0 means no label smoothing') + parser.add_argument('--report-accuracy', action='store_true', + help='report accuracy metric') + parser.add_argument('--ignore-prefix-size', default=0, type=int, + help='Ignore first N tokens') + # fmt: on + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"]) + loss, nll_loss = self.compute_loss(model, net_output, sample, reduce=reduce) + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": loss.data, + "nll_loss": nll_loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + if self.report_accuracy: + n_correct, total = self.compute_accuracy(model, net_output, sample) + logging_output["n_correct"] = utils.item(n_correct.data) + logging_output["total"] = utils.item(total.data) + return loss, sample_size, logging_output + + def get_lprobs_and_target(self, model, net_output, sample): + lprobs = model.get_normalized_probs(net_output, log_probs=True) + target = model.get_targets(sample, net_output) + if self.ignore_prefix_size > 0: + if getattr(lprobs, "batch_first", False): + lprobs = lprobs[:, self.ignore_prefix_size :, :].contiguous() + target = target[:, self.ignore_prefix_size :].contiguous() + else: + lprobs = lprobs[self.ignore_prefix_size :, :, :].contiguous() + target = target[self.ignore_prefix_size :, :].contiguous() + return lprobs.view(-1, lprobs.size(-1)), target.view(-1) + + def compute_loss(self, model, net_output, sample, reduce=True): + lprobs, target = self.get_lprobs_and_target(model, net_output, sample) + loss, nll_loss = label_smoothed_nll_loss( + lprobs, + target, + self.eps, + ignore_index=self.padding_idx, + reduce=reduce, + ) + return loss, nll_loss + + def compute_accuracy(self, model, net_output, sample): + lprobs, target = self.get_lprobs_and_target(model, net_output, sample) + mask = target.ne(self.padding_idx) + n_correct = torch.sum( + lprobs.argmax(1).masked_select(mask).eq(target.masked_select(mask)) + ) + total = torch.sum(mask) + return n_correct, total + + @classmethod + def reduce_metrics(cls, logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + nll_loss_sum = sum(log.get("nll_loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar( + "nll_loss", nll_loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + + total = utils.item(sum(log.get("total", 0) for log in logging_outputs)) + if total > 0: + metrics.log_scalar("total", total) + n_correct = utils.item( + sum(log.get("n_correct", 0) for log in logging_outputs) + ) + metrics.log_scalar("n_correct", n_correct) + metrics.log_derived( + "accuracy", + lambda meters: round( + meters["n_correct"].sum * 100.0 / meters["total"].sum, 3 + ) + if meters["total"].sum > 0 + else float("nan"), + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy_with_alignment.py b/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy_with_alignment.py new file mode 100644 index 00000000..73cfa053 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/label_smoothed_cross_entropy_with_alignment.py @@ -0,0 +1,125 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +from fairseq import metrics, utils +from fairseq.criterions import register_criterion + +from .label_smoothed_cross_entropy import LabelSmoothedCrossEntropyCriterion + + +@register_criterion("label_smoothed_cross_entropy_with_alignment") +class LabelSmoothedCrossEntropyCriterionWithAlignment( + LabelSmoothedCrossEntropyCriterion +): + def __init__(self, task, sentence_avg, label_smoothing, alignment_lambda): + super().__init__(task, sentence_avg, label_smoothing) + self.alignment_lambda = alignment_lambda + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + LabelSmoothedCrossEntropyCriterion.add_args(parser) + parser.add_argument( + "--alignment-lambda", + default=0.05, + type=float, + metavar="D", + help="weight for the alignment loss", + ) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"]) + loss, nll_loss = self.compute_loss(model, net_output, sample, reduce=reduce) + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "nll_loss": utils.item(nll_loss.data) if reduce else nll_loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + + alignment_loss = None + + # Compute alignment loss only for training set and non dummy batches. + if "alignments" in sample and sample["alignments"] is not None: + alignment_loss = self.compute_alignment_loss(sample, net_output) + + if alignment_loss is not None: + logging_output["alignment_loss"] = utils.item(alignment_loss.data) + loss += self.alignment_lambda * alignment_loss + + return loss, sample_size, logging_output + + def compute_alignment_loss(self, sample, net_output): + attn_prob = net_output[1]["attn"][0] + bsz, tgt_sz, src_sz = attn_prob.shape + attn = attn_prob.view(bsz * tgt_sz, src_sz) + + align = sample["alignments"] + align_weights = sample["align_weights"].float() + + if len(align) > 0: + # Alignment loss computation. align (shape [:, 2]) contains the src-tgt index pairs corresponding to + # the alignments. align_weights (shape [:]) contains the 1 / frequency of a tgt index for normalizing. + loss = -( + (attn[align[:, 1][:, None], align[:, 0][:, None]]).log() + * align_weights[:, None] + ).sum() + else: + return None + + return loss + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = utils.item(sum(log.get("loss", 0) for log in logging_outputs)) + nll_loss_sum = utils.item( + sum(log.get("nll_loss", 0) for log in logging_outputs) + ) + alignment_loss_sum = utils.item( + sum(log.get("alignment_loss", 0) for log in logging_outputs) + ) + ntokens = utils.item(sum(log.get("ntokens", 0) for log in logging_outputs)) + sample_size = utils.item( + sum(log.get("sample_size", 0) for log in logging_outputs) + ) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar( + "nll_loss", nll_loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_scalar( + "alignment_loss", + alignment_loss_sum / sample_size / math.log(2), + sample_size, + round=3, + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/legacy_masked_lm.py b/fairseq-tools/fairseq/fairseq/criterions/legacy_masked_lm.py new file mode 100644 index 00000000..c70608c5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/legacy_masked_lm.py @@ -0,0 +1,177 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +def compute_cross_entropy_loss(logits, targets, ignore_index=-100): + """ + Function to compute the cross entropy loss. The default value of + ignore_index is the same as the default value for F.cross_entropy in + pytorch. + """ + assert logits.size(0) == targets.size( + -1 + ), "Logits and Targets tensor shapes don't match up" + + loss = F.nll_loss( + F.log_softmax(logits, -1, dtype=torch.float32), + targets, + reduction="sum", + ignore_index=ignore_index, + ) + return loss + + +@register_criterion("legacy_masked_lm_loss") +class LegacyMaskedLmLoss(FairseqCriterion): + """ + Implementation for the loss used in masked language model (MLM) training. + This optionally also computes the next sentence prediction (NSP) loss and + adds it to the overall loss based on the specified args. There are three + cases to consider: + 1) Generic MLM training without NSP loss. In this case sentence_targets + and sentence_logits are both None. + 2) BERT training without NSP loss. In this case sentence_targets is + not None but sentence_logits is None and we should not be computing + a sentence level loss. + 3) BERT training with NSP loss. In this case both sentence_targets and + sentence_logits are not None and we should be computing a sentence + level loss. The weight of the sentence level loss is specified as + an argument. + """ + + def __init__(self, task, masked_lm_only, nsp_loss_weight): + super().__init__(task) + self.masked_lm_only = masked_lm_only + self.nsp_loss_weight = nsp_loss_weight + + @staticmethod + def add_args(parser): + """Args for MaskedLM Loss""" + # Default for masked_lm_only is False so as to not break BERT training + parser.add_argument( + "--masked-lm-only", + default=False, + action="store_true", + help="compute MLM loss only", + ) + parser.add_argument( + "--nsp-loss-weight", + default=1.0, + type=float, + help="weight for next sentence prediction" " loss (default 1)", + ) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + lm_logits, output_metadata = model(**sample["net_input"]) + + # reshape lm_logits from (N,T,C) to (N*T,C) + lm_logits = lm_logits.view(-1, lm_logits.size(-1)) + lm_targets = sample["lm_target"].view(-1) + lm_loss = compute_cross_entropy_loss(lm_logits, lm_targets, self.padding_idx) + + # compute the number of tokens for which loss is computed. This is used + # to normalize the loss + ntokens = utils.strip_pad(lm_targets, self.padding_idx).numel() + loss = lm_loss / ntokens + nsentences = sample["nsentences"] + # nsentences = 0 + + # Compute sentence loss if masked_lm_only is False + sentence_loss = None + if not self.masked_lm_only: + sentence_logits = output_metadata["sentence_logits"] + sentence_targets = sample["sentence_target"].view(-1) + # This needs to be recomputed due to some differences between + # TokenBlock and BlockPair dataset. This can be resolved with a + # refactor of BERTModel which we will do in the future. + # TODO: Remove this after refactor of BERTModel + nsentences = sentence_targets.size(0) + + # Check for logits being none which can happen when remove_heads + # is set to true in the BERT model. Ideally we should set + # masked_lm_only to true in this case, but that requires some + # refactor in the BERT model. + if sentence_logits is not None: + sentence_loss = compute_cross_entropy_loss( + sentence_logits, sentence_targets + ) + + loss += self.nsp_loss_weight * (sentence_loss / nsentences) + + # NOTE: as we are summing up per token mlm loss and per sentence nsp loss + # we don't need to use sample_size as denominator for the gradient + # here sample_size is just used for logging + sample_size = 1 + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "lm_loss": utils.item(lm_loss.data) if reduce else lm_loss.data, + # sentence loss is not always computed + "sentence_loss": ( + (utils.item(sentence_loss.data) if reduce else sentence_loss.data) + if sentence_loss is not None + else 0.0 + ), + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + lm_loss_sum = sum(log.get("lm_loss", 0) for log in logging_outputs) + sentence_loss_sum = sum(log.get("sentence_loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + agg_loss = sum(log.get("loss", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", + agg_loss / sample_size / math.log(2) if sample_size > 0 else 0.0, + sample_size, + round=3, + ) + metrics.log_scalar( + "lm_loss", + lm_loss_sum / ntokens / math.log(2) if ntokens > 0 else 0.0, + ntokens, + round=3, + ) + metrics.log_scalar( + "sentence_loss", + sentence_loss_sum / nsentences / math.log(2) if nsentences > 0 else 0.0, + nsentences, + round=3, + ) + metrics.log_scalar( + "nll_loss", + lm_loss_sum / ntokens / math.log(2) if ntokens > 0 else 0.0, + ntokens, + round=3, + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/masked_lm.py b/fairseq-tools/fairseq/fairseq/criterions/masked_lm.py new file mode 100644 index 00000000..b04cfbff --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/masked_lm.py @@ -0,0 +1,91 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, modules, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("masked_lm") +class MaskedLmLoss(FairseqCriterion): + """ + Implementation for the loss used in masked language model (MLM) training. + """ + + def __init__(self, task, tpu=False): + super().__init__(task) + self.tpu = tpu + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + masked_tokens = sample["target"].ne(self.padding_idx) + sample_size = masked_tokens.int().sum() + + # Rare: when all tokens are masked, project all tokens. + # We use torch.where to avoid device-to-host transfers, + # except on CPU where torch.where is not well supported + # (see github.com/pytorch/pytorch/issues/26247). + if self.tpu: + masked_tokens = None # always project all tokens on TPU + elif masked_tokens.device == torch.device("cpu"): + if not masked_tokens.any(): + masked_tokens = None + else: + masked_tokens = torch.where( + masked_tokens.any(), + masked_tokens, + masked_tokens.new([True]), + ) + + logits = model(**sample["net_input"], masked_tokens=masked_tokens)[0] + targets = model.get_targets(sample, [logits]) + if masked_tokens is not None: + targets = targets[masked_tokens] + + loss = modules.cross_entropy( + logits.view(-1, logits.size(-1)), + targets.view(-1), + reduction="sum", + ignore_index=self.padding_idx, + ) + + logging_output = { + "loss": loss if self.tpu else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["nsentences"], + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/nat_loss.py b/fairseq-tools/fairseq/fairseq/criterions/nat_loss.py new file mode 100644 index 00000000..cdc7da86 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/nat_loss.py @@ -0,0 +1,180 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from torch import Tensor + + +@register_criterion("nat_loss") +class LabelSmoothedDualImitationCriterion(FairseqCriterion): + def __init__(self, task, label_smoothing): + super().__init__(task) + self.label_smoothing = label_smoothing + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + parser.add_argument( + "--label-smoothing", + default=0.0, + type=float, + metavar="D", + help="epsilon for label smoothing, 0 means no label smoothing", + ) + + def _compute_loss( + self, outputs, targets, masks=None, label_smoothing=0.0, name="loss", factor=1.0 + ): + """ + outputs: batch x len x d_model + targets: batch x len + masks: batch x len + + policy_logprob: if there is some policy + depends on the likelihood score as rewards. + """ + + def mean_ds(x: Tensor, dim=None) -> Tensor: + return ( + x.float().mean().type_as(x) + if dim is None + else x.float().mean(dim).type_as(x) + ) + + if masks is not None: + outputs, targets = outputs[masks], targets[masks] + + if masks is not None and not masks.any(): + nll_loss = torch.tensor(0) + loss = nll_loss + else: + logits = F.log_softmax(outputs, dim=-1) + if targets.dim() == 1: + losses = F.nll_loss(logits, targets.to(logits.device), reduction="none") + + else: # soft-labels + losses = F.kl_div(logits, targets.to(logits.device), reduction="none") + losses = losses.sum(-1) + + nll_loss = mean_ds(losses) + if label_smoothing > 0: + loss = ( + nll_loss * (1 - label_smoothing) - mean_ds(logits) * label_smoothing + ) + else: + loss = nll_loss + + loss = loss * factor + return {"name": name, "loss": loss, "nll_loss": nll_loss, "factor": factor} + + def _custom_loss(self, loss, name="loss", factor=1.0): + return {"name": name, "loss": loss, "factor": factor} + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + nsentences, ntokens = sample["nsentences"], sample["ntokens"] + + # B x T + src_tokens, src_lengths = ( + sample["net_input"]["src_tokens"], + sample["net_input"]["src_lengths"], + ) + tgt_tokens, prev_output_tokens = sample["target"], sample["prev_target"] + + outputs = model(src_tokens, src_lengths, prev_output_tokens, tgt_tokens) + losses, nll_loss = [], [] + + for obj in outputs: + if outputs[obj].get("loss", None) is None: + _losses = self._compute_loss( + outputs[obj].get("out"), + outputs[obj].get("tgt"), + outputs[obj].get("mask", None), + outputs[obj].get("ls", 0.0), + name=obj + "-loss", + factor=outputs[obj].get("factor", 1.0), + ) + else: + _losses = self._custom_loss( + outputs[obj].get("loss"), + name=obj + "-loss", + factor=outputs[obj].get("factor", 1.0), + ) + + losses += [_losses] + if outputs[obj].get("nll_loss", False): + nll_loss += [_losses.get("nll_loss", 0.0)] + + loss = sum(l["loss"] for l in losses) + nll_loss = sum(l for l in nll_loss) if len(nll_loss) > 0 else loss.new_tensor(0) + + # NOTE: + # we don't need to use sample_size as denominator for the gradient + # here sample_size is just used for logging + sample_size = 1 + logging_output = { + "loss": loss.data, + "nll_loss": nll_loss.data, + "ntokens": ntokens, + "nsentences": nsentences, + "sample_size": sample_size, + } + + for l in losses: + logging_output[l["name"]] = ( + utils.item(l["loss"].data / l["factor"]) + if reduce + else l[["loss"]].data / l["factor"] + ) + + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + sample_size = utils.item( + sum(log.get("sample_size", 0) for log in logging_outputs) + ) + loss = utils.item(sum(log.get("loss", 0) for log in logging_outputs)) + nll_loss = utils.item(sum(log.get("nll_loss", 0) for log in logging_outputs)) + + metrics.log_scalar( + "loss", loss / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar( + "nll_loss", nll_loss / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["loss"].avg) + ) + + for key in logging_outputs[0]: + if key[-5:] == "-loss": + val = sum(log.get(key, 0) for log in logging_outputs) + metrics.log_scalar( + key[:-5], + val / sample_size / math.log(2) if sample_size > 0 else 0.0, + sample_size, + round=3, + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/sentence_prediction.py b/fairseq-tools/fairseq/fairseq/criterions/sentence_prediction.py new file mode 100644 index 00000000..9519fdc5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/sentence_prediction.py @@ -0,0 +1,99 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("sentence_prediction") +class SentencePredictionCriterion(FairseqCriterion): + def __init__(self, task, classification_head_name, regression_target): + super().__init__(task) + self.classification_head_name = classification_head_name + self.regression_target = regression_target + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--classification-head-name', + default='sentence_classification_head', + help='name of the classification head to use') + # fmt: on + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + assert ( + hasattr(model, "classification_heads") + and self.classification_head_name in model.classification_heads + ), "model must provide sentence classification head for --criterion=sentence_prediction" + + logits, _ = model( + **sample["net_input"], + features_only=True, + classification_head_name=self.classification_head_name, + ) + targets = model.get_targets(sample, [logits]).view(-1) + sample_size = targets.numel() + + if not self.regression_target: + lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float32) + loss = F.nll_loss(lprobs, targets, reduction="sum") + else: + logits = logits.view(-1).float() + targets = targets.float() + loss = F.mse_loss(logits, targets, reduction="sum") + + logging_output = { + "loss": loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample_size, + "sample_size": sample_size, + } + if not self.regression_target: + preds = logits.argmax(dim=1) + logging_output["ncorrect"] = (preds == targets).sum() + + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + + if len(logging_outputs) > 0 and "ncorrect" in logging_outputs[0]: + ncorrect = sum(log.get("ncorrect", 0) for log in logging_outputs) + metrics.log_scalar( + "accuracy", 100.0 * ncorrect / nsentences, nsentences, round=1 + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/sentence_ranking.py b/fairseq-tools/fairseq/fairseq/criterions/sentence_ranking.py new file mode 100644 index 00000000..d4c76341 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/sentence_ranking.py @@ -0,0 +1,120 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +@register_criterion("sentence_ranking") +class SentenceRankingCriterion(FairseqCriterion): + def __init__(self, task, ranking_head_name, save_predictions, num_classes): + super().__init__(task) + self.ranking_head_name = ranking_head_name + if save_predictions is not None: + self.prediction_h = open(save_predictions, "w") + else: + self.prediction_h = None + self.num_classes = num_classes + + def __del__(self): + if self.prediction_h is not None: + self.prediction_h.close() + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--save-predictions', metavar='FILE', + help='file to save predictions to') + parser.add_argument('--ranking-head-name', + default='sentence_classification_head', + help='name of the ranking head to use') + # fmt: on + + def forward(self, model, sample, reduce=True): + """Compute ranking loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + assert ( + hasattr(model, "classification_heads") + and self.ranking_head_name in model.classification_heads + ), "model must provide sentence ranking head for --criterion=sentence_ranking" + + scores = [] + for idx in range(self.num_classes): + score, _ = model( + **sample["net_input{idx}".format(idx=idx + 1)], + classification_head_name=self.ranking_head_name, + ) + scores.append(score) + + logits = torch.cat(scores, dim=1) + sample_size = logits.size(0) + + if "target" in sample: + targets = model.get_targets(sample, [logits]).view(-1) + lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float32) + loss = F.nll_loss(lprobs, targets, reduction="sum") + else: + targets = None + loss = torch.tensor(0.0, requires_grad=True) + + if self.prediction_h is not None: + preds = logits.argmax(dim=1) + for i, (id, pred) in enumerate(zip(sample["id"].tolist(), preds.tolist())): + if targets is not None: + label = targets[i].item() + print("{}\t{}\t{}".format(id, pred, label), file=self.prediction_h) + else: + print("{}\t{}".format(id, pred), file=self.prediction_h) + + logging_output = { + "loss": loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample_size, + "sample_size": sample_size, + } + if targets is not None: + logging_output["ncorrect"] = (logits.argmax(dim=1) == targets).sum() + + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + + if len(logging_outputs) > 0 and "ncorrect" in logging_outputs[0]: + ncorrect = sum(log.get("ncorrect", 0) for log in logging_outputs) + metrics.log_scalar( + "accuracy", 100.0 * ncorrect / nsentences, nsentences, round=1 + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/criterions/wav2vec_criterion.py b/fairseq-tools/fairseq/fairseq/criterions/wav2vec_criterion.py new file mode 100644 index 00000000..6ac7557d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/criterions/wav2vec_criterion.py @@ -0,0 +1,184 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion +from fairseq.logging.meters import safe_round + + +@register_criterion("wav2vec") +class Wav2vecCriterion(FairseqCriterion): + def __init__(self, task, infonce=False, loss_weights=None, log_keys=None): + super().__init__(task) + self.infonce = infonce + self.loss_weights = None if loss_weights is None else eval(loss_weights) + self.log_keys = [] if log_keys is None else eval(log_keys) + + @staticmethod + def add_args(parser): + """Add criterion-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--infonce', action='store_true', + help='if set, uses cross entropy instead of binary cross entropy (i.e. InfoNCE loss)') + parser.add_argument('--loss-weights', type=str, default=None, + help='weights for additional loss terms (not first one)') + parser.add_argument('--log-keys', type=str, default=None, + help='output keys to log') + # fmt: on + + def forward(self, model, sample, reduce=True, log_pred=False): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"]) + logits = model.get_logits(net_output).float() + target = model.get_targets(sample, net_output) + + weights = None + if hasattr(model, "get_target_weights") and not self.infonce: + weights = model.get_target_weights(target, net_output) + if torch.is_tensor(weights): + weights = weights.float() + + losses = [] + + if self.infonce: + loss = F.cross_entropy( + logits, + target, + reduction="sum" if reduce else "none", + ) + else: + loss = F.binary_cross_entropy_with_logits( + logits, + target.float(), + weights, + reduction="sum" if reduce else "none", + ) + + sample_size = target.numel() if self.infonce else target.long().sum().item() + losses.append(loss.detach().clone()) + + if self.loss_weights is not None: + assert hasattr(model, "get_extra_losses") + extra_losses = model.get_extra_losses(net_output) + if torch.is_tensor(extra_losses): + extra_losses = [extra_losses] + if len(self.loss_weights) == 1 and len(extra_losses) != 1: + self.loss_weights = [self.loss_weights[0]] * len(extra_losses) + assert len(extra_losses) == len( + self.loss_weights + ), f"{len(extra_losses)}, {len(self.loss_weights)}" + for p, coef in zip(extra_losses, self.loss_weights): + if coef != 0 and p is not None: + p = coef * p.float() * sample_size + loss += p + losses.append(p) + + logging_output = { + "loss": loss.item() if reduce else loss, + "ntokens": sample_size, + "nsentences": sample["id"].numel(), + "sample_size": sample_size, + } + + for lk in self.log_keys: + if lk in net_output: + logging_output[lk] = float((net_output[lk])) + + if len(losses) > 1: + for i, l in enumerate(losses): + logging_output[f"loss_{i}"] = l.item() + + if self.infonce: + with torch.no_grad(): + if logits.numel() == 0: + corr = 0 + count = 0 + else: + assert logits.dim() > 1, logits.shape + max = logits.argmax(-1) == 0 + min = logits.argmin(-1) == 0 + both = max & min + corr = max.long().sum().item() - both.long().sum().item() + count = max.numel() + + logging_output["correct"] = corr + logging_output["count"] = count + + if log_pred: + logging_output["logits"] = logits.cpu().numpy() + logging_output["target"] = target.cpu().numpy() + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = utils.item(sum(log.get("loss", 0) for log in logging_outputs)) + ntokens = utils.item(sum(log.get("ntokens", 0) for log in logging_outputs)) + nsentences = utils.item( + sum(log.get("nsentences", 0) for log in logging_outputs) + ) + sample_size = utils.item( + sum(log.get("sample_size", 0) for log in logging_outputs) + ) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + metrics.log_scalar("ntokens", ntokens) + metrics.log_scalar("nsentences", nsentences) + + correct = sum(log.get("correct", 0) for log in logging_outputs) + metrics.log_scalar("_correct", correct) + + total = sum(log.get("count", 0) for log in logging_outputs) + metrics.log_scalar("_total", total) + + if total > 0: + metrics.log_derived( + "accuracy", + lambda meters: safe_round( + meters["_correct"].sum / meters["_total"].sum, 5 + ) + if meters["_total"].sum > 0 + else float("nan"), + ) + + builtin_keys = { + "loss", + "ntokens", + "nsentences", + "sample_size", + "correct", + "count", + } + + for k in logging_outputs[0]: + if k not in builtin_keys: + val = sum(log.get(k, 0) for log in logging_outputs) / len( + logging_outputs + ) + if k.startswith("loss"): + metrics.log_scalar(k, val / sample_size / math.log(2), sample_size) + else: + metrics.log_scalar(k, val, round=3) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return False diff --git a/fairseq-tools/fairseq/fairseq/data/__init__.py b/fairseq-tools/fairseq/fairseq/data/__init__.py new file mode 100644 index 00000000..9b308139 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/__init__.py @@ -0,0 +1,124 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +from .dictionary import Dictionary, TruncatedDictionary + +from .fairseq_dataset import FairseqDataset, FairseqIterableDataset + +from .base_wrapper_dataset import BaseWrapperDataset + +from .add_target_dataset import AddTargetDataset +from .append_token_dataset import AppendTokenDataset +from .audio.raw_audio_dataset import FileAudioDataset +from .backtranslation_dataset import BacktranslationDataset +from .bucket_pad_length_dataset import BucketPadLengthDataset +from .colorize_dataset import ColorizeDataset +from .concat_dataset import ConcatDataset +from .concat_sentences_dataset import ConcatSentencesDataset +from .denoising_dataset import DenoisingDataset +from .id_dataset import IdDataset +from .indexed_dataset import ( + IndexedCachedDataset, + IndexedDataset, + IndexedRawTextDataset, + MMapIndexedDataset, +) +from .language_pair_dataset import LanguagePairDataset +from .list_dataset import ListDataset +from .lm_context_window_dataset import LMContextWindowDataset +from .lru_cache_dataset import LRUCacheDataset +from .mask_tokens_dataset import MaskTokensDataset +from .monolingual_dataset import MonolingualDataset +from .multi_corpus_sampled_dataset import MultiCorpusSampledDataset +from .nested_dictionary_dataset import NestedDictionaryDataset +from .noising import NoisingDataset +from .numel_dataset import NumelDataset +from .num_samples_dataset import NumSamplesDataset +from .offset_tokens_dataset import OffsetTokensDataset +from .pad_dataset import LeftPadDataset, PadDataset, RightPadDataset +from .prepend_dataset import PrependDataset +from .prepend_token_dataset import PrependTokenDataset +from .raw_label_dataset import RawLabelDataset +from .replace_dataset import ReplaceDataset +from .resampling_dataset import ResamplingDataset +from .roll_dataset import RollDataset +from .round_robin_zip_datasets import RoundRobinZipDatasets +from .sort_dataset import SortDataset +from .strip_token_dataset import StripTokenDataset +from .subsample_dataset import SubsampleDataset +from .token_block_dataset import TokenBlockDataset +from .transform_eos_dataset import TransformEosDataset +from .transform_eos_lang_pair_dataset import TransformEosLangPairDataset +from .shorten_dataset import TruncateDataset, RandomCropDataset +from .multilingual.sampled_multi_dataset import SampledMultiDataset +from .multilingual.sampled_multi_epoch_dataset import SampledMultiEpochDataset +from .fasta_dataset import FastaDataset, EncodedFastaDataset + +from .iterators import ( + CountingIterator, + EpochBatchIterator, + GroupedIterator, + ShardedIterator, +) + +__all__ = [ + "AddTargetDataset", + "AppendTokenDataset", + "BacktranslationDataset", + "BaseWrapperDataset", + "BucketPadLengthDataset", + "ColorizeDataset", + "ConcatDataset", + "ConcatSentencesDataset", + "CountingIterator", + "DenoisingDataset", + "Dictionary", + "EncodedFastaDataset", + "EpochBatchIterator", + "FairseqDataset", + "FairseqIterableDataset", + "FastaDataset", + "GroupedIterator", + "IdDataset", + "IndexedCachedDataset", + "IndexedDataset", + "IndexedRawTextDataset", + "LanguagePairDataset", + "LeftPadDataset", + "ListDataset", + "LMContextWindowDataset", + "LRUCacheDataset", + "MaskTokensDataset", + "MMapIndexedDataset", + "MonolingualDataset", + "MultiCorpusSampledDataset", + "NestedDictionaryDataset", + "NoisingDataset", + "NumelDataset", + "NumSamplesDataset", + "OffsetTokensDataset", + "PadDataset", + "PrependDataset", + "PrependTokenDataset", + "ReplaceDataset", + "RollDataset", + "FileAudioDataset", + "RawLabelDataset", + "ResamplingDataset", + "RightPadDataset", + "RoundRobinZipDatasets", + "SampledMultiDataset", + "SampledMultiEpochDataset", + "ShardedIterator", + "SortDataset", + "StripTokenDataset", + "SubsampleDataset", + "TokenBlockDataset", + "TransformEosDataset", + "TransformEosLangPairDataset", + "TruncateDataset", + "TruncatedDictionary", +] diff --git a/fairseq-tools/fairseq/fairseq/data/add_target_dataset.py b/fairseq-tools/fairseq/fairseq/data/add_target_dataset.py new file mode 100644 index 00000000..9ef46705 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/add_target_dataset.py @@ -0,0 +1,70 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import BaseWrapperDataset, data_utils + + +class AddTargetDataset(BaseWrapperDataset): + def __init__( + self, + dataset, + labels, + pad, + eos, + batch_targets, + process_label=None, + add_to_input=False, + ): + super().__init__(dataset) + self.labels = labels + self.batch_targets = batch_targets + self.pad = pad + self.eos = eos + self.process_label = process_label + self.add_to_input = add_to_input + + def get_label(self, index): + return ( + self.labels[index] + if self.process_label is None + else self.process_label(self.labels[index]) + ) + + def __getitem__(self, index): + item = self.dataset[index] + item["label"] = self.get_label(index) + return item + + def size(self, index): + sz = self.dataset.size(index) + own_sz = len(self.get_label(index)) + return (sz, own_sz) + + def collater(self, samples): + collated = self.dataset.collater(samples) + if len(collated) == 0: + return collated + indices = set(collated["id"].tolist()) + target = [s["label"] for s in samples if s["id"] in indices] + + if self.batch_targets: + collated["target_lengths"] = torch.LongTensor([len(t) for t in target]) + target = data_utils.collate_tokens(target, pad_idx=self.pad, left_pad=False) + collated["ntokens"] = collated["target_lengths"].sum().item() + else: + collated["ntokens"] = sum([len(t) for t in target]) + + collated["target"] = target + + if self.add_to_input: + eos = target.new_full((target.size(0), 1), self.eos) + collated["target"] = torch.cat([target, eos], dim=-1).long() + collated["net_input"]["prev_output_tokens"] = torch.cat( + [eos, target], dim=-1 + ).long() + collated["ntokens"] += target.size(0) + return collated diff --git a/fairseq-tools/fairseq/fairseq/data/append_token_dataset.py b/fairseq-tools/fairseq/fairseq/data/append_token_dataset.py new file mode 100644 index 00000000..87695bd0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/append_token_dataset.py @@ -0,0 +1,41 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch + +from . import BaseWrapperDataset + + +class AppendTokenDataset(BaseWrapperDataset): + def __init__(self, dataset, token=None): + super().__init__(dataset) + self.token = token + if token is not None: + self._sizes = np.array(dataset.sizes) + 1 + else: + self._sizes = dataset.sizes + + def __getitem__(self, idx): + item = self.dataset[idx] + if self.token is not None: + item = torch.cat([item, item.new([self.token])]) + return item + + @property + def sizes(self): + return self._sizes + + def num_tokens(self, index): + n = self.dataset.num_tokens(index) + if self.token is not None: + n += 1 + return n + + def size(self, index): + n = self.dataset.size(index) + if self.token is not None: + n += 1 + return n diff --git a/fairseq-tools/fairseq/fairseq/data/audio/__init__.py b/fairseq-tools/fairseq/fairseq/data/audio/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/fairseq/data/audio/audio_utils.py b/fairseq-tools/fairseq/fairseq/data/audio/audio_utils.py new file mode 100644 index 00000000..de086698 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/audio_utils.py @@ -0,0 +1,85 @@ +import os.path as op +from typing import BinaryIO, Optional, Tuple, Union + +import numpy as np + + +def get_waveform( + path_or_fp: Union[str, BinaryIO], normalization=True +) -> Tuple[np.ndarray, int]: + """Get the waveform and sample rate of a 16-bit mono-channel WAV or FLAC. + + Args: + path_or_fp (str or BinaryIO): the path or file-like object + normalization (bool): Normalize values to [-1, 1] (Default: True) + """ + if isinstance(path_or_fp, str): + ext = op.splitext(op.basename(path_or_fp))[1] + if ext not in {".flac", ".wav"}: + raise ValueError(f"Unsupported audio format: {ext}") + + try: + import soundfile as sf + except ImportError: + raise ImportError("Please install soundfile to load WAV/FLAC file") + + waveform, sample_rate = sf.read(path_or_fp, dtype="float32") + if not normalization: + waveform *= 2 ** 15 # denormalized to 16-bit signed integers + return waveform, sample_rate + + +def _get_kaldi_fbank(waveform, sample_rate, n_bins=80) -> Optional[np.ndarray]: + """Get mel-filter bank features via PyKaldi.""" + try: + from kaldi.feat.mel import MelBanksOptions + from kaldi.feat.fbank import FbankOptions, Fbank + from kaldi.feat.window import FrameExtractionOptions + from kaldi.matrix import Vector + + mel_opts = MelBanksOptions() + mel_opts.num_bins = n_bins + frame_opts = FrameExtractionOptions() + frame_opts.samp_freq = sample_rate + opts = FbankOptions() + opts.mel_opts = mel_opts + opts.frame_opts = frame_opts + fbank = Fbank(opts=opts) + features = fbank.compute(Vector(waveform), 1.0).numpy() + return features + except ImportError: + return None + + +def _get_torchaudio_fbank(waveform, sample_rate, n_bins=80) -> Optional[np.ndarray]: + """Get mel-filter bank features via TorchAudio.""" + try: + import torch + import torchaudio.compliance.kaldi as ta_kaldi + + waveform = torch.from_numpy(waveform).unsqueeze(0) + features = ta_kaldi.fbank( + waveform, num_mel_bins=n_bins, sample_frequency=sample_rate + ) + return features.numpy() + except ImportError: + return None + + +def get_fbank(path_or_fp: Union[str, BinaryIO], n_bins=80) -> np.ndarray: + """Get mel-filter bank features via PyKaldi or TorchAudio. Prefer PyKaldi + (faster CPP implementation) to TorchAudio (Python implementation). Note that + Kaldi/TorchAudio requires 16-bit signed integers as inputs and hence the + waveform should not be normalized.""" + sound, sample_rate = get_waveform(path_or_fp, normalization=False) + + features = _get_kaldi_fbank(sound, sample_rate, n_bins) + if features is None: + features = _get_torchaudio_fbank(sound, sample_rate, n_bins) + if features is None: + raise ImportError( + "Please install pyKaldi or torchaudio to enable " + "online filterbank feature extraction" + ) + + return features diff --git a/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/__init__.py b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/__init__.py new file mode 100644 index 00000000..359fa069 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/__init__.py @@ -0,0 +1,82 @@ +import importlib +import os +from abc import ABC, abstractmethod +from typing import Dict, Optional + + +class AudioFeatureTransform(ABC): + @classmethod + @abstractmethod + def from_config_dict(cls, config: Optional[Dict] = None): + pass + + +AUDIO_FEATURE_TRANSFORM_REGISTRY = {} +AUDIO_FEATURE_TRANSFORM_CLASS_NAMES = set() + + +def register_audio_feature_transform(name): + def register_audio_feature_transform_cls(cls): + if name in AUDIO_FEATURE_TRANSFORM_REGISTRY: + raise ValueError(f"Cannot register duplicate transform ({name})") + if not issubclass(cls, AudioFeatureTransform): + raise ValueError( + f"Transform ({name}: {cls.__name__}) must extend " + "AudioFeatureTransform" + ) + if cls.__name__ in AUDIO_FEATURE_TRANSFORM_CLASS_NAMES: + raise ValueError( + f"Cannot register audio feature transform with duplicate " + f"class name ({cls.__name__})" + ) + AUDIO_FEATURE_TRANSFORM_REGISTRY[name] = cls + AUDIO_FEATURE_TRANSFORM_CLASS_NAMES.add(cls.__name__) + return cls + + return register_audio_feature_transform_cls + + +def get_audio_feature_transform(name): + return AUDIO_FEATURE_TRANSFORM_REGISTRY[name] + + +transforms_dir = os.path.dirname(__file__) +for file in os.listdir(transforms_dir): + path = os.path.join(transforms_dir, file) + if ( + not file.startswith("_") + and not file.startswith(".") + and (file.endswith(".py") or os.path.isdir(path)) + ): + name = file[: file.find(".py")] if file.endswith(".py") else file + importlib.import_module("fairseq.data.audio.feature_transforms." + name) + + +class CompositeAudioFeatureTransform(AudioFeatureTransform): + @classmethod + def from_config_dict(cls, config=None): + _config = {} if config is None else config + _transforms = _config.get("transforms") + if _transforms is None: + return None + transforms = [ + get_audio_feature_transform(_t).from_config_dict(_config.get(_t)) + for _t in _transforms + ] + return CompositeAudioFeatureTransform(transforms) + + def __init__(self, transforms): + self.transforms = [t for t in transforms if t is not None] + + def __call__(self, x): + for t in self.transforms: + x = t(x) + return x + + def __repr__(self): + format_string = ( + [self.__class__.__name__ + "("] + + [f" {t.__repr__()}" for t in self.transforms] + + [")"] + ) + return "\n".join(format_string) diff --git a/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/global_cmvn.py b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/global_cmvn.py new file mode 100644 index 00000000..d512fed3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/global_cmvn.py @@ -0,0 +1,25 @@ +import numpy as np +from fairseq.data.audio.feature_transforms import ( + AudioFeatureTransform, + register_audio_feature_transform, +) + + +@register_audio_feature_transform("global_cmvn") +class GlobalCMVN(AudioFeatureTransform): + """Global CMVN (cepstral mean and variance normalization). The global mean + and variance need to be pre-computed and stored in NumPy format (.npz).""" + + @classmethod + def from_config_dict(cls, config=None): + _config = {} if config is None else config + return GlobalCMVN(_config.get("stats_npz_path")) + + def __init__(self, stats_npz_path): + stats = np.load(stats_npz_path) + self.mean, self.std = stats["mean"], stats["std"] + + def __call__(self, x): + x = np.subtract(x, self.mean) + x = np.divide(x, self.std) + return x diff --git a/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/specaugment.py b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/specaugment.py new file mode 100644 index 00000000..2ef4778b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/specaugment.py @@ -0,0 +1,131 @@ +import math +import numbers +from typing import Optional + +import numpy as np +from fairseq.data.audio.feature_transforms import ( + AudioFeatureTransform, + register_audio_feature_transform, +) + + +@register_audio_feature_transform("specaugment") +class SpecAugmentTransform(AudioFeatureTransform): + """SpecAugment (https://arxiv.org/abs/1904.08779)""" + + @classmethod + def from_config_dict(cls, config=None): + _config = {} if config is None else config + return SpecAugmentTransform( + _config.get("time_warp_W", 0), + _config.get("freq_mask_N", 0), + _config.get("freq_mask_F", 0), + _config.get("time_mask_N", 0), + _config.get("time_mask_T", 0), + _config.get("time_mask_p", 0.0), + _config.get("mask_value", None), + ) + + def __init__( + self, + time_warp_w: int = 0, + freq_mask_n: int = 0, + freq_mask_f: int = 0, + time_mask_n: int = 0, + time_mask_t: int = 0, + time_mask_p: float = 0.0, + mask_value: Optional[float] = 0.0, + ): + # Sanity checks + assert mask_value is None or isinstance( + mask_value, numbers.Number + ), f"mask_value (type: {type(mask_value)}) must be None or a number" + if freq_mask_n > 0: + assert freq_mask_f > 0, ( + f"freq_mask_F ({freq_mask_f}) " + f"must be larger than 0 when doing freq masking." + ) + if time_mask_n > 0: + assert time_mask_t > 0, ( + f"time_mask_T ({time_mask_t}) must be larger than 0 when " + f"doing time masking." + ) + + self.time_warp_w = time_warp_w + self.freq_mask_n = freq_mask_n + self.freq_mask_f = freq_mask_f + self.time_mask_n = time_mask_n + self.time_mask_t = time_mask_t + self.time_mask_p = time_mask_p + self.mask_value = mask_value + + def __repr__(self): + return ( + self.__class__.__name__ + + "(" + + ", ".join( + [ + f"time_warp_w={self.time_warp_w}", + f"freq_mask_n={self.freq_mask_n}", + f"freq_mask_f={self.freq_mask_f}", + f"time_mask_n={self.time_mask_n}", + f"time_mask_t={self.time_mask_t}", + f"time_mask_p={self.time_mask_p}", + ] + ) + + ")" + ) + + def __call__(self, spectrogram): + assert len(spectrogram.shape) == 2, "spectrogram must be a 2-D tensor." + + distorted = spectrogram.copy() # make a copy of input spectrogram. + num_frames = spectrogram.shape[0] # or 'tau' in the paper. + num_freqs = spectrogram.shape[1] # or 'miu' in the paper. + mask_value = self.mask_value + + if mask_value is None: # if no value was specified, use local mean. + mask_value = spectrogram.mean() + + if num_frames == 0: + return spectrogram + + if num_freqs < self.freq_mask_f: + return spectrogram + + if self.time_warp_w > 0: + if 2 * self.time_warp_w < num_frames: + import cv2 + + w0 = np.random.randint(self.time_warp_w, num_frames - self.time_warp_w) + w = np.random.randint(0, self.time_warp_w) + upper, lower = distorted[:w0, :], distorted[w0:, :] + upper = cv2.resize( + upper, dsize=(num_freqs, w0 + w), interpolation=cv2.INTER_LINEAR + ) + lower = cv2.resize( + lower, + dsize=(num_freqs, num_frames - w0 - w), + interpolation=cv2.INTER_LINEAR, + ) + distorted = np.concatenate((upper, lower), axis=0) + + for _i in range(self.freq_mask_n): + f = np.random.randint(0, self.freq_mask_f) + f0 = np.random.randint(0, num_freqs - f) + if f != 0: + distorted[:, f0 : f0 + f] = mask_value + + max_time_mask_t = min( + self.time_mask_t, math.floor(num_frames * self.time_mask_p) + ) + if max_time_mask_t < 1: + return distorted + + for _i in range(self.time_mask_n): + t = np.random.randint(0, max_time_mask_t) + t0 = np.random.randint(0, num_frames - t) + if t != 0: + distorted[t0 : t0 + t, :] = mask_value + + return distorted diff --git a/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/utterance_cmvn.py b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/utterance_cmvn.py new file mode 100644 index 00000000..6bbd0ae8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/feature_transforms/utterance_cmvn.py @@ -0,0 +1,40 @@ +import numpy as np +from fairseq.data.audio.feature_transforms import ( + AudioFeatureTransform, + register_audio_feature_transform, +) + + +@register_audio_feature_transform("utterance_cmvn") +class UtteranceCMVN(AudioFeatureTransform): + """Utterance-level CMVN (cepstral mean and variance normalization)""" + + @classmethod + def from_config_dict(cls, config=None): + _config = {} if config is None else config + return UtteranceCMVN( + _config.get("norm_means", True), + _config.get("norm_vars", True), + ) + + def __init__(self, norm_means=True, norm_vars=True): + self.norm_means, self.norm_vars = norm_means, norm_vars + + def __repr__(self): + return ( + self.__class__.__name__ + + f"(norm_means={self.norm_means}, norm_vars={self.norm_vars})" + ) + + def __call__(self, x): + mean = x.mean(axis=0) + square_sums = (x ** 2).sum(axis=0) + + if self.norm_means: + x = np.subtract(x, mean) + if self.norm_vars: + var = square_sums / x.shape[0] - mean ** 2 + std = np.sqrt(np.maximum(var, 1e-10)) + x = np.divide(x, std) + + return x diff --git a/fairseq-tools/fairseq/fairseq/data/audio/raw_audio_dataset.py b/fairseq-tools/fairseq/fairseq/data/audio/raw_audio_dataset.py new file mode 100644 index 00000000..8d6ce85e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/raw_audio_dataset.py @@ -0,0 +1,178 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +import logging +import os +import sys + +import numpy as np +import torch +import torch.nn.functional as F + +from .. import FairseqDataset + + +logger = logging.getLogger(__name__) + + +class RawAudioDataset(FairseqDataset): + def __init__( + self, + sample_rate, + max_sample_size=None, + min_sample_size=None, + shuffle=True, + min_length=0, + pad=False, + normalize=False, + ): + super().__init__() + + self.sample_rate = sample_rate + self.sizes = [] + self.max_sample_size = ( + max_sample_size if max_sample_size is not None else sys.maxsize + ) + self.min_sample_size = min_sample_size + self.min_length = min_length + self.pad = pad + self.shuffle = shuffle + self.normalize = normalize + + def __getitem__(self, index): + raise NotImplementedError() + + def __len__(self): + return len(self.sizes) + + def postprocess(self, feats, curr_sample_rate): + if feats.dim() == 2: + feats = feats.mean(-1) + + if curr_sample_rate != self.sample_rate: + raise Exception(f"sample rate: {curr_sample_rate}, need {self.sample_rate}") + + assert feats.dim() == 1, feats.dim() + + if self.normalize: + with torch.no_grad(): + feats = F.layer_norm(feats, feats.shape) + return feats + + def crop_to_max_size(self, wav, target_size): + size = len(wav) + diff = size - target_size + if diff <= 0: + return wav + + start = np.random.randint(0, diff + 1) + end = size - diff + start + return wav[start:end] + + def collater(self, samples): + samples = [s for s in samples if s["source"] is not None] + if len(samples) == 0: + return {} + + sources = [s["source"] for s in samples] + sizes = [len(s) for s in sources] + + if self.pad: + target_size = min(max(sizes), self.max_sample_size) + else: + target_size = min(min(sizes), self.max_sample_size) + + collated_sources = sources[0].new_zeros(len(sources), target_size) + padding_mask = ( + torch.BoolTensor(collated_sources.shape).fill_(False) if self.pad else None + ) + for i, (source, size) in enumerate(zip(sources, sizes)): + diff = size - target_size + if diff == 0: + collated_sources[i] = source + elif diff < 0: + assert self.pad + collated_sources[i] = torch.cat( + [source, source.new_full((-diff,), 0.0)] + ) + padding_mask[i, diff:] = True + else: + collated_sources[i] = self.crop_to_max_size(source, target_size) + + input = {"source": collated_sources} + if self.pad: + input["padding_mask"] = padding_mask + return {"id": torch.LongTensor([s["id"] for s in samples]), "net_input": input} + + def num_tokens(self, index): + return self.size(index) + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + if self.pad: + return self.sizes[index] + return min(self.sizes[index], self.max_sample_size) + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + + if self.shuffle: + order = [np.random.permutation(len(self))] + else: + order = [np.arange(len(self))] + + order.append(self.sizes) + return np.lexsort(order)[::-1] + + +class FileAudioDataset(RawAudioDataset): + def __init__( + self, + manifest_path, + sample_rate, + max_sample_size=None, + min_sample_size=None, + shuffle=True, + min_length=0, + pad=False, + normalize=False, + ): + super().__init__( + sample_rate=sample_rate, + max_sample_size=max_sample_size, + min_sample_size=min_sample_size, + shuffle=shuffle, + min_length=min_length, + pad=pad, + normalize=normalize, + ) + + self.fnames = [] + + skipped = 0 + with open(manifest_path, "r") as f: + self.root_dir = f.readline().strip() + for line in f: + items = line.strip().split("\t") + assert len(items) == 2, line + sz = int(items[1]) + if min_length is not None and sz < min_length: + skipped += 1 + continue + self.fnames.append(items[0]) + self.sizes.append(sz) + logger.info(f"loaded {len(self.fnames)}, skipped {skipped} samples") + + def __getitem__(self, index): + import soundfile as sf + + fname = os.path.join(self.root_dir, self.fnames[index]) + wav, curr_sample_rate = sf.read(fname) + feats = torch.from_numpy(wav).float() + feats = self.postprocess(feats, curr_sample_rate) + return {"id": index, "source": feats} diff --git a/fairseq-tools/fairseq/fairseq/data/audio/speech_to_text_dataset.py b/fairseq-tools/fairseq/fairseq/data/audio/speech_to_text_dataset.py new file mode 100644 index 00000000..6e5fd70e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/audio/speech_to_text_dataset.py @@ -0,0 +1,528 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import csv +import io +import logging +import os.path as op +import re +from typing import Dict, List, Optional, Tuple + +import numpy as np +import torch +from fairseq.data import ( + ConcatDataset, + Dictionary, + FairseqDataset, + ResamplingDataset, + data_utils as fairseq_data_utils, +) +from fairseq.data.audio.audio_utils import get_fbank, get_waveform +from fairseq.data.audio.feature_transforms import CompositeAudioFeatureTransform + + +logger = logging.getLogger(__name__) + + +class S2TDataConfig(object): + """Wrapper class for data config YAML""" + + def __init__(self, yaml_path): + try: + import yaml + except ImportError: + print("Please install PyYAML to load YAML files for " "S2T data config") + self.config = {} + if op.isfile(yaml_path): + try: + with open(yaml_path) as f: + self.config = yaml.load(f, Loader=yaml.FullLoader) + except Exception as e: + logger.info(f"Failed to load config from {yaml_path}: {e}") + else: + logger.info(f"Cannot find {yaml_path}") + + @property + def vocab_filename(self): + """fairseq vocabulary file under data root""" + return self.config.get("vocab_filename", "dict.txt") + + @property + def shuffle(self) -> bool: + """Shuffle dataset samples before batching""" + return self.config.get("shuffle", False) + + @property + def pre_tokenizer(self) -> Dict: + """Pre-tokenizer to apply before subword tokenization. Returning + a dictionary with `tokenizer` providing the tokenizer name and + the other items providing the tokenizer-specific arguments. + Tokenizers are defined in `fairseq.data.encoders.*`""" + return self.config.get("pre_tokenizer", {"tokenizer": None}) + + @property + def bpe_tokenizer(self) -> Dict: + """Subword tokenizer to apply after pre-tokenization. Returning + a dictionary with `bpe` providing the tokenizer name and + the other items providing the tokenizer-specific arguments. + Tokenizers are defined in `fairseq.data.encoders.*`""" + return self.config.get("bpe_tokenizer", None) + + @property + def prepend_tgt_lang_tag(self) -> bool: + """Prepend target lang ID token as the target BOS (e.g. for to-many + multilingual setting). During inference, this requires `--prefix-size 1` + to force BOS to be lang ID token.""" + return self.config.get("prepend_tgt_lang_tag", False) + + @property + def input_feat_per_channel(self): + """The dimension of input features (per audio channel)""" + return self.config.get("input_feat_per_channel", 80) + + @property + def input_channels(self): + """The number of channels in the input audio""" + return self.config.get("input_channels", 1) + + @property + def sampling_alpha(self): + """Hyper-parameter alpha = 1/T for temperature-based resampling. + (alpha = 1 for no resampling)""" + return self.config.get("sampling_alpha", 1.0) + + @property + def use_audio_input(self): + """Needed by the dataset loader to see if the model requires + raw audio as inputs.""" + return self.config.get("use_audio_input", False) + + @property + def audio_root(self): + """Audio paths in the manifest TSV can be relative and this provides + the root path. Set this to empty string when using absolute paths.""" + return self.config.get("audio_root", "") + + def get_feature_transforms(self, split, is_train): + """Split-specific feature transforms. Allowing train set wildcard `_train`, + evaluation set wildcard `_eval` and general wildcard `*` for matching.""" + from copy import deepcopy + + cfg = deepcopy(self.config) + _cur = cfg.get("transforms", {}) + cur = _cur.get(split) + cur = _cur.get("_train") if cur is None and is_train else cur + cur = _cur.get("_eval") if cur is None and not is_train else cur + cur = _cur.get("*") if cur is None else cur + cfg["transforms"] = cur + return cfg + + +def is_npy_data(data: bytes) -> bool: + return data[0] == 147 and data[1] == 78 + + +def is_flac_or_wav_data(data: bytes) -> bool: + is_flac = data[0] == 102 and data[1] == 76 + is_wav = data[0] == 82 and data[1] == 73 + return is_flac or is_wav + + +def read_from_uncompressed_zip(file_path, offset, file_size) -> bytes: + with open(file_path, "rb") as f: + f.seek(offset) + data = f.read(file_size) + return data + + +def get_features_from_npy_or_audio(path): + ext = op.splitext(op.basename(path))[1] + if ext not in {".npy", ".flac", ".wav"}: + raise ValueError(f'Unsupported file format for "{path}"') + return np.load(path) if ext == ".npy" else get_fbank(path) + + +def get_features_or_waveform_from_uncompressed_zip( + path, byte_offset, byte_size, need_waveform=False +): + assert path.endswith(".zip") + data = read_from_uncompressed_zip(path, byte_offset, byte_size) + f = io.BytesIO(data) + if is_npy_data(data): + features_or_waveform = np.load(f) + elif is_flac_or_wav_data(data): + features_or_waveform = get_waveform(f)[0] if need_waveform else get_fbank(f) + else: + raise ValueError(f'Unknown file format for "{path}"') + return features_or_waveform + + +def get_features_or_waveform(path: str, need_waveform=False): + """Get speech features from .npy file or waveform from .wav/.flac file. + The file may be inside an uncompressed ZIP file and is accessed via byte + offset and length. + + Args: + path (str): File path in the format of "<.npy/.wav/.flac path>" or + "<zip path>:<byte offset>:<byte length>". + need_waveform (bool): return waveform instead of features. + + Returns: + features_or_waveform (numpy.ndarray): speech features or waveform. + """ + _path, *extra = path.split(":") + if not op.exists(_path): + raise FileNotFoundError(f"File not found: {_path}") + + if len(extra) == 0: + if need_waveform: + return get_waveform(_path) + return get_features_from_npy_or_audio(_path) + elif len(extra) == 2: + extra = [int(i) for i in extra] + features_or_waveform = get_features_or_waveform_from_uncompressed_zip( + _path, extra[0], extra[1], need_waveform=need_waveform + ) + else: + raise ValueError(f"Invalid path: {path}") + + return features_or_waveform + + +def _collate_frames( + frames: List[torch.Tensor], is_audio_input: bool = False +) -> torch.Tensor: + """ + Convert a list of 2D frames into a padded 3D tensor + Args: + frames (list): list of 2D frames of size L[i]*f_dim. Where L[i] is + length of i-th frame and f_dim is static dimension of features + Returns: + 3D tensor of size len(frames)*len_max*f_dim where len_max is max of L[i] + """ + max_len = max(frame.size(0) for frame in frames) + if is_audio_input: + out = frames[0].new_zeros((len(frames), max_len)) + else: + out = frames[0].new_zeros((len(frames), max_len, frames[0].size(1))) + for i, v in enumerate(frames): + out[i, : v.size(0)] = v + return out + + +class SpeechToTextDataset(FairseqDataset): + LANG_TAG_TEMPLATE = "<lang:{}>" + + def __init__( + self, + split: str, + is_train_split: bool, + data_cfg: S2TDataConfig, + audio_paths: List[str], + n_frames: List[int], + src_texts: Optional[List[str]] = None, + tgt_texts: Optional[List[str]] = None, + speakers: Optional[List[str]] = None, + src_langs: Optional[List[str]] = None, + tgt_langs: Optional[List[str]] = None, + ids: Optional[List[str]] = None, + tgt_dict: Optional[Dictionary] = None, + pre_tokenizer=None, + bpe_tokenizer=None, + ): + self.split, self.is_train_split = split, is_train_split + self.data_cfg = data_cfg + self.audio_paths, self.n_frames = audio_paths, n_frames + self.n_samples = len(audio_paths) + assert len(n_frames) == self.n_samples > 0 + assert src_texts is None or len(src_texts) == self.n_samples + assert tgt_texts is None or len(tgt_texts) == self.n_samples + assert speakers is None or len(speakers) == self.n_samples + assert src_langs is None or len(src_langs) == self.n_samples + assert tgt_langs is None or len(tgt_langs) == self.n_samples + assert ids is None or len(ids) == self.n_samples + assert (tgt_dict is None and tgt_texts is None) or ( + tgt_dict is not None and tgt_texts is not None + ) + self.tgt_dict = tgt_dict + self.check_tgt_lang_tag() + self.src_texts, self.tgt_texts = src_texts, tgt_texts + self.src_langs, self.tgt_langs = src_langs, tgt_langs + self.ids = ids + self.shuffle = data_cfg.shuffle if is_train_split else False + + self.feature_transforms = CompositeAudioFeatureTransform.from_config_dict( + self.data_cfg.get_feature_transforms(split, is_train_split) + ) + + self.pre_tokenizer = pre_tokenizer + self.bpe_tokenizer = bpe_tokenizer + + logger.info(self.__repr__()) + + def __repr__(self): + return ( + self.__class__.__name__ + + f'(split="{self.split}", n_samples={self.n_samples}, ' + f"prepend_tgt_lang_tag={self.data_cfg.prepend_tgt_lang_tag}, " + f"shuffle={self.shuffle}, transforms={self.feature_transforms})" + ) + + @classmethod + def is_lang_tag(cls, token): + pattern = cls.LANG_TAG_TEMPLATE.replace("{}", "(.*)") + return re.match(pattern, token) + + def check_tgt_lang_tag(self): + if self.data_cfg.prepend_tgt_lang_tag: + assert self.tgt_langs is not None and self.tgt_dict is not None + tgt_lang_tags = [ + self.LANG_TAG_TEMPLATE.format(t) for t in set(self.tgt_langs) + ] + assert all(t in self.tgt_dict for t in tgt_lang_tags) + + def tokenize_text(self, text: str): + if self.pre_tokenizer is not None: + text = self.pre_tokenizer.encode(text) + if self.bpe_tokenizer is not None: + text = self.bpe_tokenizer.encode(text) + return text + + def __getitem__( + self, index: int + ) -> Tuple[int, torch.Tensor, Optional[torch.Tensor]]: + source = get_features_or_waveform( + self.audio_paths[index], need_waveform=self.data_cfg.use_audio_input + ) + if self.feature_transforms is not None: + assert not self.data_cfg.use_audio_input + source = self.feature_transforms(source) + source = torch.from_numpy(source).float() + + target = None + if self.tgt_texts is not None: + tokenized = self.tokenize_text(self.tgt_texts[index]) + target = self.tgt_dict.encode_line( + tokenized, add_if_not_exist=False, append_eos=True + ).long() + if self.data_cfg.prepend_tgt_lang_tag: + lang_tag = self.LANG_TAG_TEMPLATE.format(self.tgt_langs[index]) + lang_tag_idx = self.tgt_dict.index(lang_tag) + target = torch.cat((torch.LongTensor([lang_tag_idx]), target), 0) + return index, source, target + + def __len__(self): + return self.n_samples + + def collater(self, samples: List[Tuple[int, torch.Tensor, torch.Tensor]]) -> Dict: + if len(samples) == 0: + return {} + indices = torch.tensor([i for i, _, _ in samples], dtype=torch.long) + frames = _collate_frames( + [s for _, s, _ in samples], self.data_cfg.use_audio_input + ) + # sort samples by descending number of frames + n_frames = torch.tensor([s.size(0) for _, s, _ in samples], dtype=torch.long) + n_frames, order = n_frames.sort(descending=True) + indices = indices.index_select(0, order) + frames = frames.index_select(0, order) + + target, target_lengths = None, None + prev_output_tokens = None + ntokens = None + if self.tgt_texts is not None: + target = fairseq_data_utils.collate_tokens( + [t for _, _, t in samples], + self.tgt_dict.pad(), + self.tgt_dict.eos(), + left_pad=False, + move_eos_to_beginning=False, + ) + target = target.index_select(0, order) + target_lengths = torch.tensor( + [t.size(0) for _, _, t in samples], dtype=torch.long + ).index_select(0, order) + prev_output_tokens = fairseq_data_utils.collate_tokens( + [t for _, _, t in samples], + self.tgt_dict.pad(), + self.tgt_dict.eos(), + left_pad=False, + move_eos_to_beginning=True, + ) + prev_output_tokens = prev_output_tokens.index_select(0, order) + ntokens = sum(t.size(0) for _, _, t in samples) + + out = { + "id": indices, + "net_input": { + "src_tokens": frames, + "src_lengths": n_frames, + "prev_output_tokens": prev_output_tokens, + }, + "target": target, + "target_lengths": target_lengths, + "ntokens": ntokens, + "nsentences": len(samples), + } + return out + + def num_tokens(self, index): + return self.n_frames[index] + + def size(self, index): + t_len = 0 + if self.tgt_texts is not None: + tokenized = self.tokenize_text(self.tgt_texts[index]) + t_len = len(tokenized.split(" ")) + return self.n_frames[index], t_len + + @property + def sizes(self): + return np.array(self.n_frames) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return True + + def ordered_indices(self): + if self.shuffle: + order = [np.random.permutation(len(self))] + else: + order = [np.arange(len(self))] + # first by descending order of # of frames then by original/random order + order.append([-n for n in self.n_frames]) + return np.lexsort(order) + + def prefetch(self, indices): + raise False + + +class SpeechToTextDatasetCreator(object): + # mandatory columns + KEY_ID, KEY_AUDIO, KEY_N_FRAMES = "id", "audio", "n_frames" + KEY_TGT_TEXT = "tgt_text" + # optional columns + KEY_SPEAKER, KEY_SRC_TEXT = "speaker", "src_text" + KEY_SRC_LANG, KEY_TGT_LANG = "src_lang", "tgt_lang" + # default values + DEFAULT_SPEAKER = DEFAULT_SRC_TEXT = DEFAULT_LANG = "" + + @classmethod + def _from_list( + cls, + split_name: str, + is_train_split, + samples: List[List[Dict]], + data_cfg: S2TDataConfig, + tgt_dict, + pre_tokenizer, + bpe_tokenizer, + ) -> SpeechToTextDataset: + audio_paths, n_frames, src_texts, tgt_texts, ids = [], [], [], [], [] + speakers, src_langs, tgt_langs = [], [], [] + for s in samples: + ids.extend([ss[cls.KEY_ID] for ss in s]) + audio_paths.extend( + [op.join(data_cfg.audio_root, ss[cls.KEY_AUDIO]) for ss in s] + ) + n_frames.extend([int(ss[cls.KEY_N_FRAMES]) for ss in s]) + tgt_texts.extend([ss[cls.KEY_TGT_TEXT] for ss in s]) + src_texts.extend( + [ss.get(cls.KEY_SRC_TEXT, cls.DEFAULT_SRC_TEXT) for ss in s] + ) + speakers.extend([ss.get(cls.KEY_SPEAKER, cls.DEFAULT_SPEAKER) for ss in s]) + src_langs.extend([ss.get(cls.KEY_SRC_LANG, cls.DEFAULT_LANG) for ss in s]) + tgt_langs.extend([ss.get(cls.KEY_TGT_LANG, cls.DEFAULT_LANG) for ss in s]) + return SpeechToTextDataset( + split_name, + is_train_split, + data_cfg, + audio_paths, + n_frames, + src_texts, + tgt_texts, + speakers, + src_langs, + tgt_langs, + ids, + tgt_dict, + pre_tokenizer, + bpe_tokenizer, + ) + + @classmethod + def _get_size_ratios(cls, ids: List[str], sizes: List[int], alpha: float = 1.0): + """Size ratios for temperature-based sampling + (https://arxiv.org/abs/1907.05019)""" + _sizes = np.array(sizes) + prob = _sizes / _sizes.sum() + smoothed_prob = prob ** alpha + smoothed_prob = smoothed_prob / smoothed_prob.sum() + size_ratio = (smoothed_prob * _sizes.sum()) / _sizes + + o_str = str({_i: f"{prob[i]:.3f}" for i, _i in enumerate(ids)}) + logger.info(f"original sampling probability: {o_str}") + p_str = str({_i: f"{smoothed_prob[i]:.3f}" for i, _i in enumerate(ids)}) + logger.info(f"balanced sampling probability: {p_str}") + sr_str = str({_id: f"{size_ratio[i]:.3f}" for i, _id in enumerate(ids)}) + logger.info(f"balanced sampling size ratio: {sr_str}") + return size_ratio.tolist() + + @classmethod + def from_tsv( + cls, + root: str, + data_cfg: S2TDataConfig, + splits: str, + tgt_dict, + pre_tokenizer, + bpe_tokenizer, + is_train_split: bool, + epoch: int, + seed: int, + ) -> SpeechToTextDataset: + samples = [] + _splits = splits.split(",") + for split in _splits: + tsv_path = op.join(root, f"{split}.tsv") + if not op.isfile(tsv_path): + raise FileNotFoundError(f"Dataset not found: {tsv_path}") + with open(tsv_path) as f: + reader = csv.DictReader( + f, + delimiter="\t", + quotechar=None, + doublequote=False, + lineterminator="\n", + quoting=csv.QUOTE_NONE, + ) + samples.append([dict(e) for e in reader]) + assert len(samples) > 0 + + datasets = [ + cls._from_list( + name, + is_train_split, + [s], + data_cfg, + tgt_dict, + pre_tokenizer, + bpe_tokenizer, + ) + for name, s in zip(_splits, samples) + ] + + if is_train_split and len(_splits) > 1 and data_cfg.sampling_alpha != 1.0: + # temperature-based sampling + size_ratios = cls._get_size_ratios( + _splits, [len(s) for s in samples], alpha=data_cfg.sampling_alpha + ) + datasets = [ + ResamplingDataset( + d, size_ratio=r, seed=seed, epoch=epoch, replace=(r >= 1.0) + ) + for d, r in zip(datasets, size_ratios) + ] + return ConcatDataset(datasets) diff --git a/fairseq-tools/fairseq/fairseq/data/backtranslation_dataset.py b/fairseq-tools/fairseq/fairseq/data/backtranslation_dataset.py new file mode 100644 index 00000000..8f70c90d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/backtranslation_dataset.py @@ -0,0 +1,165 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq import utils + +from . import FairseqDataset + + +def backtranslate_samples(samples, collate_fn, generate_fn, cuda=True): + """Backtranslate a list of samples. + + Given an input (*samples*) of the form: + + [{'id': 1, 'source': 'hallo welt'}] + + this will return: + + [{'id': 1, 'source': 'hello world', 'target': 'hallo welt'}] + + Args: + samples (List[dict]): samples to backtranslate. Individual samples are + expected to have a 'source' key, which will become the 'target' + after backtranslation. + collate_fn (callable): function to collate samples into a mini-batch + generate_fn (callable): function to generate backtranslations + cuda (bool): use GPU for generation (default: ``True``) + + Returns: + List[dict]: an updated list of samples with a backtranslated source + """ + collated_samples = collate_fn(samples) + s = utils.move_to_cuda(collated_samples) if cuda else collated_samples + generated_sources = generate_fn(s) + + id_to_src = {sample["id"]: sample["source"] for sample in samples} + + # Go through each tgt sentence in batch and its corresponding best + # generated hypothesis and create a backtranslation data pair + # {id: id, source: generated backtranslation, target: original tgt} + return [ + { + "id": id.item(), + "target": id_to_src[id.item()], + "source": hypos[0]["tokens"].cpu(), + } + for id, hypos in zip(collated_samples["id"], generated_sources) + ] + + +class BacktranslationDataset(FairseqDataset): + """ + Sets up a backtranslation dataset which takes a tgt batch, generates + a src using a tgt-src backtranslation function (*backtranslation_fn*), + and returns the corresponding `{generated src, input tgt}` batch. + + Args: + tgt_dataset (~fairseq.data.FairseqDataset): the dataset to be + backtranslated. Only the source side of this dataset will be used. + After backtranslation, the source sentences in this dataset will be + returned as the targets. + src_dict (~fairseq.data.Dictionary): the dictionary of backtranslated + sentences. + tgt_dict (~fairseq.data.Dictionary, optional): the dictionary of + sentences to be backtranslated. + backtranslation_fn (callable, optional): function to call to generate + backtranslations. This is typically the `generate` method of a + :class:`~fairseq.sequence_generator.SequenceGenerator` object. + Pass in None when it is not available at initialization time, and + use set_backtranslation_fn function to set it when available. + output_collater (callable, optional): function to call on the + backtranslated samples to create the final batch + (default: ``tgt_dataset.collater``). + cuda: use GPU for generation + """ + + def __init__( + self, + tgt_dataset, + src_dict, + tgt_dict=None, + backtranslation_fn=None, + output_collater=None, + cuda=True, + **kwargs + ): + self.tgt_dataset = tgt_dataset + self.backtranslation_fn = backtranslation_fn + self.output_collater = ( + output_collater if output_collater is not None else tgt_dataset.collater + ) + self.cuda = cuda if torch.cuda.is_available() else False + self.src_dict = src_dict + self.tgt_dict = tgt_dict + + def __getitem__(self, index): + """ + Returns a single sample from *tgt_dataset*. Note that backtranslation is + not applied in this step; use :func:`collater` instead to backtranslate + a batch of samples. + """ + return self.tgt_dataset[index] + + def __len__(self): + return len(self.tgt_dataset) + + def set_backtranslation_fn(self, backtranslation_fn): + self.backtranslation_fn = backtranslation_fn + + def collater(self, samples): + """Merge and backtranslate a list of samples to form a mini-batch. + + Using the samples from *tgt_dataset*, load a collated target sample to + feed to the backtranslation model. Then take the backtranslation with + the best score as the source and the original input as the target. + + Note: we expect *tgt_dataset* to provide a function `collater()` that + will collate samples into the format expected by *backtranslation_fn*. + After backtranslation, we will feed the new list of samples (i.e., the + `(backtranslated source, original source)` pairs) to *output_collater* + and return the result. + + Args: + samples (List[dict]): samples to backtranslate and collate + + Returns: + dict: a mini-batch with keys coming from *output_collater* + """ + if samples[0].get("is_dummy", False): + return samples + samples = backtranslate_samples( + samples=samples, + collate_fn=self.tgt_dataset.collater, + generate_fn=(lambda net_input: self.backtranslation_fn(net_input)), + cuda=self.cuda, + ) + return self.output_collater(samples) + + def num_tokens(self, index): + """Just use the tgt dataset num_tokens""" + return self.tgt_dataset.num_tokens(index) + + def ordered_indices(self): + """Just use the tgt dataset ordered_indices""" + return self.tgt_dataset.ordered_indices() + + def size(self, index): + """Return an example's size as a float or tuple. This value is used + when filtering a dataset with ``--max-positions``. + + Note: we use *tgt_dataset* to approximate the length of the source + sentence, since we do not know the actual length until after + backtranslation. + """ + tgt_size = self.tgt_dataset.size(index)[0] + return (tgt_size, tgt_size) + + @property + def supports_prefetch(self): + return getattr(self.tgt_dataset, "supports_prefetch", False) + + def prefetch(self, indices): + return self.tgt_dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/base_wrapper_dataset.py b/fairseq-tools/fairseq/fairseq/data/base_wrapper_dataset.py new file mode 100644 index 00000000..134d398b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/base_wrapper_dataset.py @@ -0,0 +1,78 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from torch.utils.data.dataloader import default_collate + +from . import FairseqDataset + + +class BaseWrapperDataset(FairseqDataset): + def __init__(self, dataset): + super().__init__() + self.dataset = dataset + + def __getitem__(self, index): + return self.dataset[index] + + def __len__(self): + return len(self.dataset) + + def collater(self, samples): + if hasattr(self.dataset, "collater"): + return self.dataset.collater(samples) + else: + return default_collate(samples) + + @property + def sizes(self): + return self.dataset.sizes + + def num_tokens(self, index): + return self.dataset.num_tokens(index) + + def size(self, index): + return self.dataset.size(index) + + def ordered_indices(self): + return self.dataset.ordered_indices() + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def attr(self, attr: str, index: int): + return self.dataset.attr(attr, index) + + def prefetch(self, indices): + self.dataset.prefetch(indices) + + def get_batch_shapes(self): + return self.dataset.get_batch_shapes() + + def batch_by_size( + self, + indices, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + ): + return self.dataset.batch_by_size( + indices, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + ) + + def filter_indices_by_size(self, indices, max_sizes): + return self.dataset.filter_indices_by_size(indices, max_sizes) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return self.dataset.can_reuse_epoch_itr_across_epochs + + def set_epoch(self, epoch): + super().set_epoch(epoch) + if hasattr(self.dataset, "set_epoch"): + self.dataset.set_epoch(epoch) diff --git a/fairseq-tools/fairseq/fairseq/data/bucket_pad_length_dataset.py b/fairseq-tools/fairseq/fairseq/data/bucket_pad_length_dataset.py new file mode 100644 index 00000000..cda8834a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/bucket_pad_length_dataset.py @@ -0,0 +1,76 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch.nn.functional as F +from fairseq.data import BaseWrapperDataset + + +class BucketPadLengthDataset(BaseWrapperDataset): + """ + Bucket and pad item lengths to the nearest bucket size. This can be used to + reduce the number of unique batch shapes, which is important on TPUs since + each new batch shape requires a recompilation. + + Args: + dataset (FairseqDatset): dataset to bucket + sizes (List[int]): all item sizes + num_buckets (int): number of buckets to create + pad_idx (int): padding symbol + left_pad (bool): if True, pad on the left; otherwise right pad + """ + + def __init__( + self, + dataset, + sizes, + num_buckets, + pad_idx, + left_pad, + ): + super().__init__(dataset) + self.pad_idx = pad_idx + self.left_pad = left_pad + + assert num_buckets > 0 + self.buckets = np.unique( + np.percentile( + sizes, + np.linspace(0, 100, num_buckets + 1), + interpolation="lower", + )[1:] + ) + + def get_bucketed_sizes(orig_sizes, buckets): + sizes = np.copy(orig_sizes) + assert np.min(sizes) >= 0 + start_val = -1 + for end_val in buckets: + mask = (sizes > start_val) & (sizes <= end_val) + sizes[mask] = end_val + start_val = end_val + return sizes + + self._bucketed_sizes = get_bucketed_sizes(sizes, self.buckets) + + def __getitem__(self, index): + item = self.dataset[index] + bucket_size = self._bucketed_sizes[index] + num_pad = bucket_size - item.size(-1) + return F.pad( + item, + (num_pad if self.left_pad else 0, 0 if self.left_pad else num_pad), + value=self.pad_idx, + ) + + @property + def sizes(self): + return self._bucketed_sizes + + def num_tokens(self, index): + return self._bucketed_sizes[index] + + def size(self, index): + return self._bucketed_sizes[index] diff --git a/fairseq-tools/fairseq/fairseq/data/colorize_dataset.py b/fairseq-tools/fairseq/fairseq/data/colorize_dataset.py new file mode 100644 index 00000000..6ef097bf --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/colorize_dataset.py @@ -0,0 +1,25 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import BaseWrapperDataset + + +class ColorizeDataset(BaseWrapperDataset): + """ Adds 'colors' property to net input that is obtained from the provided color getter for use by models """ + + def __init__(self, dataset, color_getter): + super().__init__(dataset) + self.color_getter = color_getter + + def collater(self, samples): + base_collate = super().collater(samples) + if len(base_collate) > 0: + base_collate["net_input"]["colors"] = torch.tensor( + list(self.color_getter(self.dataset, s["id"]) for s in samples), + dtype=torch.long, + ) + return base_collate diff --git a/fairseq-tools/fairseq/fairseq/data/concat_dataset.py b/fairseq-tools/fairseq/fairseq/data/concat_dataset.py new file mode 100644 index 00000000..01a4078b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/concat_dataset.py @@ -0,0 +1,124 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import bisect + +import numpy as np +from torch.utils.data.dataloader import default_collate + +from . import FairseqDataset + + +class ConcatDataset(FairseqDataset): + @staticmethod + def cumsum(sequence, sample_ratios): + r, s = [], 0 + for e, ratio in zip(sequence, sample_ratios): + curr_len = int(ratio * len(e)) + r.append(curr_len + s) + s += curr_len + return r + + def __init__(self, datasets, sample_ratios=1): + super(ConcatDataset, self).__init__() + assert len(datasets) > 0, "datasets should not be an empty iterable" + self.datasets = list(datasets) + if isinstance(sample_ratios, int): + sample_ratios = [sample_ratios] * len(self.datasets) + self.sample_ratios = sample_ratios + self.cumulative_sizes = self.cumsum(self.datasets, sample_ratios) + self.real_sizes = [len(d) for d in self.datasets] + + def __len__(self): + return self.cumulative_sizes[-1] + + def __getitem__(self, idx): + dataset_idx, sample_idx = self._get_dataset_and_sample_index(idx) + return self.datasets[dataset_idx][sample_idx] + + def _get_dataset_and_sample_index(self, idx: int): + dataset_idx = bisect.bisect_right(self.cumulative_sizes, idx) + if dataset_idx == 0: + sample_idx = idx + else: + sample_idx = idx - self.cumulative_sizes[dataset_idx - 1] + sample_idx = sample_idx % self.real_sizes[dataset_idx] + return dataset_idx, sample_idx + + def collater(self, samples, **extra_args): + # For now only supports datasets with same underlying collater implementations + if hasattr(self.datasets[0], "collater"): + return self.datasets[0].collater(samples, **extra_args) + else: + return default_collate(samples, **extra_args) + + def size(self, idx: int): + """ + Return an example's size as a float or tuple. + """ + dataset_idx, sample_idx = self._get_dataset_and_sample_index(idx) + return self.datasets[dataset_idx].size(sample_idx) + + def num_tokens(self, index: int): + return np.max(self.size(index)) + + def attr(self, attr: str, index: int): + dataset_idx = bisect.bisect_right(self.cumulative_sizes, index) + return getattr(self.datasets[dataset_idx], attr, None) + + @property + def sizes(self): + _dataset_sizes = [] + for ds, sr in zip(self.datasets, self.sample_ratios): + if isinstance(ds.sizes, np.ndarray): + _dataset_sizes.append(np.tile(ds.sizes, sr)) + else: + # Only support underlying dataset with single size array. + assert isinstance(ds.sizes, list) + _dataset_sizes.append(np.tile(ds.sizes[0], sr)) + return np.concatenate(_dataset_sizes) + + @property + def supports_prefetch(self): + return all(d.supports_prefetch for d in self.datasets) + + def ordered_indices(self): + """ + Returns indices sorted by length. So less padding is needed. + """ + if isinstance(self.sizes, np.ndarray) and len(self.sizes.shape) > 1: + # special handling for concatenating lang_pair_datasets + indices = np.arange(len(self)) + sizes = self.sizes + tgt_sizes = ( + sizes[:, 1] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else None + ) + src_sizes = ( + sizes[:, 0] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else sizes + ) + # sort by target length, then source length + if tgt_sizes is not None: + indices = indices[np.argsort(tgt_sizes[indices], kind="mergesort")] + return indices[np.argsort(src_sizes[indices], kind="mergesort")] + else: + return np.argsort(self.sizes) + + def prefetch(self, indices): + frm = 0 + for to, ds in zip(self.cumulative_sizes, self.datasets): + real_size = len(ds) + if getattr(ds, "supports_prefetch", False): + ds.prefetch([(i - frm) % real_size for i in indices if frm <= i < to]) + frm = to + + @property + def can_reuse_epoch_itr_across_epochs(self): + return all(d.can_reuse_epoch_itr_across_epochs for d in self.datasets) + + def set_epoch(self, epoch): + super().set_epoch(epoch) + for ds in self.datasets: + if hasattr(ds, "set_epoch"): + ds.set_epoch(epoch) diff --git a/fairseq-tools/fairseq/fairseq/data/concat_sentences_dataset.py b/fairseq-tools/fairseq/fairseq/data/concat_sentences_dataset.py new file mode 100644 index 00000000..625a2937 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/concat_sentences_dataset.py @@ -0,0 +1,54 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import FairseqDataset + + +class ConcatSentencesDataset(FairseqDataset): + def __init__(self, *datasets): + super().__init__() + self.datasets = datasets + assert all( + len(ds) == len(datasets[0]) for ds in datasets + ), "datasets must have the same length" + + def __getitem__(self, index): + return torch.cat([ds[index] for ds in self.datasets]) + + def __len__(self): + return len(self.datasets[0]) + + def collater(self, samples): + return self.datasets[0].collater(samples) + + @property + def sizes(self): + return sum(ds.sizes for ds in self.datasets) + + def num_tokens(self, index): + return sum(ds.num_tokens(index) for ds in self.datasets) + + def size(self, index): + return sum(ds.size(index) for ds in self.datasets) + + def ordered_indices(self): + return self.datasets[0].ordered_indices() + + @property + def supports_prefetch(self): + return any(getattr(ds, "supports_prefetch", False) for ds in self.datasets) + + def prefetch(self, indices): + for ds in self.datasets: + if getattr(ds, "supports_prefetch", False): + ds.prefetch(indices) + + def set_epoch(self, epoch): + super().set_epoch(epoch) + for ds in self.datasets: + if hasattr(ds, "set_epoch"): + ds.set_epoch(epoch) diff --git a/fairseq-tools/fairseq/fairseq/data/data_utils.py b/fairseq-tools/fairseq/fairseq/data/data_utils.py new file mode 100644 index 00000000..81f45736 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/data_utils.py @@ -0,0 +1,499 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +try: + from collections.abc import Iterable +except ImportError: + from collections import Iterable +import contextlib +import itertools +import logging +import os +import warnings +from typing import Optional, Tuple + +import numpy as np +import torch + + +logger = logging.getLogger(__name__) + + +def infer_language_pair(path): + """Infer language pair from filename: <split>.<lang1>-<lang2>.(...).idx""" + src, dst = None, None + for filename in os.listdir(path): + parts = filename.split(".") + if len(parts) >= 3 and len(parts[1].split("-")) == 2: + return parts[1].split("-") + return src, dst + + +def collate_tokens( + values, + pad_idx, + eos_idx=None, + left_pad=False, + move_eos_to_beginning=False, + pad_to_length=None, + pad_to_multiple=1, +): + """Convert a list of 1d tensors into a padded 2d tensor.""" + size = max(v.size(0) for v in values) + size = size if pad_to_length is None else max(size, pad_to_length) + if pad_to_multiple != 1 and size % pad_to_multiple != 0: + size = int(((size - 0.1) // pad_to_multiple + 1) * pad_to_multiple) + res = values[0].new(len(values), size).fill_(pad_idx) + + def copy_tensor(src, dst): + assert dst.numel() == src.numel() + if move_eos_to_beginning: + if eos_idx is None: + # if no eos_idx is specified, then use the last token in src + dst[0] = src[-1] + else: + dst[0] = eos_idx + dst[1:] = src[:-1] + else: + dst.copy_(src) + + for i, v in enumerate(values): + copy_tensor(v, res[i][size - len(v) :] if left_pad else res[i][: len(v)]) + return res + + +def load_indexed_dataset( + path, dictionary=None, dataset_impl=None, combine=False, default="cached" +): + """A helper function for loading indexed datasets. + + Args: + path (str): path to indexed dataset (e.g., 'data-bin/train') + dictionary (~fairseq.data.Dictionary): data dictionary + dataset_impl (str, optional): which dataset implementation to use. If + not provided, it will be inferred automatically. For legacy indexed + data we use the 'cached' implementation by default. + combine (bool, optional): automatically load and combine multiple + datasets. For example, if *path* is 'data-bin/train', then we will + combine 'data-bin/train', 'data-bin/train1', ... and return a + single ConcatDataset instance. + """ + from fairseq.data.concat_dataset import ConcatDataset + import fairseq.data.indexed_dataset as indexed_dataset + + datasets = [] + for k in itertools.count(): + path_k = path + (str(k) if k > 0 else "") + path_k = indexed_dataset.get_indexed_dataset_to_local(path_k) + + dataset_impl_k = dataset_impl + if dataset_impl_k is None: + dataset_impl_k = indexed_dataset.infer_dataset_impl(path_k) + dataset = indexed_dataset.make_dataset( + path_k, + impl=dataset_impl_k or default, + fix_lua_indexing=True, + dictionary=dictionary, + ) + if dataset is None: + break + logger.info("loaded {} examples from: {}".format(len(dataset), path_k)) + datasets.append(dataset) + if not combine: + break + if len(datasets) == 0: + return None + elif len(datasets) == 1: + return datasets[0] + else: + return ConcatDataset(datasets) + + +@contextlib.contextmanager +def numpy_seed(seed, *addl_seeds): + """Context manager which seeds the NumPy PRNG with the specified seed and + restores the state afterward""" + if seed is None: + yield + return + if len(addl_seeds) > 0: + seed = int(hash((seed, *addl_seeds)) % 1e6) + state = np.random.get_state() + np.random.seed(seed) + try: + yield + finally: + np.random.set_state(state) + + +def collect_filtered(function, iterable, filtered): + """ + Similar to :func:`filter` but collects filtered elements in ``filtered``. + + Args: + function (callable): function that returns ``False`` for elements that + should be filtered + iterable (iterable): iterable to filter + filtered (list): list to store filtered elements + """ + for el in iterable: + if function(el): + yield el + else: + filtered.append(el) + + +def _filter_by_size_dynamic(indices, size_fn, max_positions, raise_exception=False): + def compare_leq(a, b): + return a <= b if not isinstance(a, tuple) else max(a) <= b + + def check_size(idx): + if isinstance(max_positions, float) or isinstance(max_positions, int): + return size_fn(idx) <= max_positions + elif isinstance(max_positions, dict): + idx_size = size_fn(idx) + assert isinstance(idx_size, dict) + intersect_keys = set(max_positions.keys()) & set(idx_size.keys()) + return all( + all( + a is None or b is None or a <= b + for a, b in zip(idx_size[key], max_positions[key]) + ) + for key in intersect_keys + ) + else: + # Hacky as heck, for the specific case of multilingual training with RoundRobin. + if isinstance(size_fn(idx), dict) and isinstance(max_positions, tuple): + return all( + a is None or b is None or compare_leq(a, b) + for a, b in zip(size_fn(idx).values(), max_positions) + ) + # For MultiCorpusSampledDataset, will generalize it later + if not isinstance(size_fn(idx), Iterable): + return all(size_fn(idx) <= b for b in max_positions) + return all( + a is None or b is None or a <= b + for a, b in zip(size_fn(idx), max_positions) + ) + + ignored = [] + itr = collect_filtered(check_size, indices, ignored) + indices = np.fromiter(itr, dtype=np.int64, count=-1) + return indices, ignored + + +def filter_by_size(indices, dataset, max_positions, raise_exception=False): + """ + [deprecated] Filter indices based on their size. + Use `FairseqDataset::filter_indices_by_size` instead. + + Args: + indices (List[int]): ordered list of dataset indices + dataset (FairseqDataset): fairseq dataset instance + max_positions (tuple): filter elements larger than this size. + Comparisons are done component-wise. + raise_exception (bool, optional): if ``True``, raise an exception if + any elements are filtered (default: False). + """ + warnings.warn( + "data_utils.filter_by_size is deprecated. " + "Use `FairseqDataset::filter_indices_by_size` instead.", + stacklevel=2, + ) + if isinstance(max_positions, float) or isinstance(max_positions, int): + if hasattr(dataset, "sizes") and isinstance(dataset.sizes, np.ndarray): + ignored = indices[dataset.sizes[indices] > max_positions].tolist() + indices = indices[dataset.sizes[indices] <= max_positions] + elif ( + hasattr(dataset, "sizes") + and isinstance(dataset.sizes, list) + and len(dataset.sizes) == 1 + ): + ignored = indices[dataset.sizes[0][indices] > max_positions].tolist() + indices = indices[dataset.sizes[0][indices] <= max_positions] + else: + indices, ignored = _filter_by_size_dynamic( + indices, dataset.size, max_positions + ) + else: + indices, ignored = _filter_by_size_dynamic(indices, dataset.size, max_positions) + + if len(ignored) > 0 and raise_exception: + raise Exception( + ( + "Size of sample #{} is invalid (={}) since max_positions={}, " + "skip this example with --skip-invalid-size-inputs-valid-test" + ).format(ignored[0], dataset.size(ignored[0]), max_positions) + ) + if len(ignored) > 0: + logger.warning( + ( + "{} samples have invalid sizes and will be skipped, " + "max_positions={}, first few sample ids={}" + ).format(len(ignored), max_positions, ignored[:10]) + ) + return indices + + +def filter_paired_dataset_indices_by_size(src_sizes, tgt_sizes, indices, max_sizes): + """Filter a list of sample indices. Remove those that are longer + than specified in max_sizes. + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + if max_sizes is None: + return indices, [] + if type(max_sizes) in (int, float): + max_src_size, max_tgt_size = max_sizes, max_sizes + else: + max_src_size, max_tgt_size = max_sizes + if tgt_sizes is None: + ignored = indices[src_sizes[indices] > max_src_size] + else: + ignored = indices[ + (src_sizes[indices] > max_src_size) | (tgt_sizes[indices] > max_tgt_size) + ] + if len(ignored) > 0: + if tgt_sizes is None: + indices = indices[src_sizes[indices] <= max_src_size] + else: + indices = indices[ + (src_sizes[indices] <= max_src_size) + & (tgt_sizes[indices] <= max_tgt_size) + ] + return indices, ignored.tolist() + + +def batch_by_size( + indices, + num_tokens_fn, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + fixed_shapes=None, +): + """ + Yield mini-batches of indices bucketed by size. Batches may contain + sequences of different lengths. + + Args: + indices (List[int]): ordered list of dataset indices + num_tokens_fn (callable): function that returns the number of tokens at + a given index + max_tokens (int, optional): max number of tokens in each batch + (default: None). + max_sentences (int, optional): max number of sentences in each + batch (default: None). + required_batch_size_multiple (int, optional): require batch size to + be less than N or a multiple of N (default: 1). + fixed_shapes (List[Tuple[int, int]], optional): if given, batches will + only be created with the given shapes. *max_sentences* and + *required_batch_size_multiple* will be ignored (default: None). + """ + try: + from fairseq.data.data_utils_fast import ( + batch_by_size_fast, + batch_fixed_shapes_fast, + ) + except ImportError: + raise ImportError( + "Please build Cython components with: `pip install --editable .` " + "or `python setup.py build_ext --inplace`" + ) + + max_tokens = max_tokens if max_tokens is not None else -1 + max_sentences = max_sentences if max_sentences is not None else -1 + bsz_mult = required_batch_size_multiple + + if not isinstance(indices, np.ndarray): + indices = np.fromiter(indices, dtype=np.int64, count=-1) + + if fixed_shapes is None: + return batch_by_size_fast( + indices, + num_tokens_fn, + max_tokens, + max_sentences, + bsz_mult, + ) + else: + fixed_shapes = np.array(fixed_shapes, dtype=np.int64) + sort_order = np.lexsort( + [ + fixed_shapes[:, 1].argsort(), # length + fixed_shapes[:, 0].argsort(), # bsz + ] + ) + fixed_shapes_sorted = fixed_shapes[sort_order] + return batch_fixed_shapes_fast(indices, num_tokens_fn, fixed_shapes_sorted) + + +def post_process(sentence: str, symbol: str): + if symbol == "sentencepiece": + sentence = sentence.replace(" ", "").replace("\u2581", " ").strip() + elif symbol == "wordpiece": + sentence = sentence.replace(" ", "").replace("_", " ").strip() + elif symbol == "letter": + sentence = sentence.replace(" ", "").replace("|", " ").strip() + elif symbol == "_EOW": + sentence = sentence.replace(" ", "").replace("_EOW", " ").strip() + elif symbol is not None and symbol != "none": + sentence = (sentence + " ").replace(symbol, "").rstrip() + return sentence + + +def compute_mask_indices( + shape: Tuple[int, int], + padding_mask: Optional[torch.Tensor], + mask_prob: float, + mask_length: int, + mask_type: str = "static", + mask_other: float = 0.0, + min_masks: int = 0, + no_overlap: bool = False, + min_space: int = 0, +) -> np.ndarray: + """ + Computes random mask spans for a given shape + + Args: + shape: the the shape for which to compute masks. + should be of size 2 where first element is batch size and 2nd is timesteps + padding_mask: optional padding mask of the same size as shape, which will prevent masking padded elements + mask_prob: probability for each token to be chosen as start of the span to be masked. this will be multiplied by + number of timesteps divided by length of mask span to mask approximately this percentage of all elements. + however due to overlaps, the actual number will be smaller (unless no_overlap is True) + mask_type: how to compute mask lengths + static = fixed size + uniform = sample from uniform distribution [mask_other, mask_length*2] + normal = sample from normal distribution with mean mask_length and stdev mask_other. mask is min 1 element + poisson = sample from possion distribution with lambda = mask length + min_masks: minimum number of masked spans + no_overlap: if false, will switch to an alternative recursive algorithm that prevents spans from overlapping + min_space: only used if no_overlap is True, this is how many elements to keep unmasked between spans + """ + + bsz, all_sz = shape + mask = np.full((bsz, all_sz), False) + + all_num_mask = int( + # add a random number for probabilistic rounding + mask_prob * all_sz / float(mask_length) + + np.random.rand() + ) + + all_num_mask = max(min_masks, all_num_mask) + + mask_idcs = [] + for i in range(bsz): + if padding_mask is not None: + sz = all_sz - padding_mask[i].long().sum().item() + num_mask = int( + # add a random number for probabilistic rounding + mask_prob * sz / float(mask_length) + + np.random.rand() + ) + num_mask = max(min_masks, num_mask) + else: + sz = all_sz + num_mask = all_num_mask + + if mask_type == "static": + lengths = np.full(num_mask, mask_length) + elif mask_type == "uniform": + lengths = np.random.randint(mask_other, mask_length * 2 + 1, size=num_mask) + elif mask_type == "normal": + lengths = np.random.normal(mask_length, mask_other, size=num_mask) + lengths = [max(1, int(round(x))) for x in lengths] + elif mask_type == "poisson": + lengths = np.random.poisson(mask_length, size=num_mask) + lengths = [int(round(x)) for x in lengths] + else: + raise Exception("unknown mask selection " + mask_type) + + if sum(lengths) == 0: + lengths[0] = min(mask_length, sz - 1) + + if no_overlap: + mask_idc = [] + + def arrange(s, e, length, keep_length): + span_start = np.random.randint(s, e - length) + mask_idc.extend(span_start + i for i in range(length)) + + new_parts = [] + if span_start - s - min_space >= keep_length: + new_parts.append((s, span_start - min_space + 1)) + if e - span_start - keep_length - min_space > keep_length: + new_parts.append((span_start + length + min_space, e)) + return new_parts + + parts = [(0, sz)] + min_length = min(lengths) + for length in sorted(lengths, reverse=True): + lens = np.fromiter( + (e - s if e - s >= length + min_space else 0 for s, e in parts), + np.int, + ) + l_sum = np.sum(lens) + if l_sum == 0: + break + probs = lens / np.sum(lens) + c = np.random.choice(len(parts), p=probs) + s, e = parts.pop(c) + parts.extend(arrange(s, e, length, min_length)) + mask_idc = np.asarray(mask_idc) + else: + min_len = min(lengths) + if sz - min_len <= num_mask: + min_len = sz - num_mask - 1 + + mask_idc = np.random.choice(sz - min_len, num_mask, replace=False) + + mask_idc = np.asarray( + [ + mask_idc[j] + offset + for j in range(len(mask_idc)) + for offset in range(lengths[j]) + ] + ) + + mask_idcs.append(np.unique(mask_idc[mask_idc < sz])) + + min_len = min([len(m) for m in mask_idcs]) + for i, mask_idc in enumerate(mask_idcs): + if len(mask_idc) > min_len: + mask_idc = np.random.choice(mask_idc, min_len, replace=False) + mask[i, mask_idc] = True + + return mask + + +def get_mem_usage(): + try: + import psutil + + mb = 1024 * 1024 + return f"used={psutil.virtual_memory().used / mb}Mb; avail={psutil.virtual_memory().available / mb}Mb" + except ImportError: + return "N/A" + + +def lengths_to_padding_mask(lens: torch.LongTensor) -> torch.BoolTensor: + bsz, max_lens = lens.size(0), torch.max(lens).item() + mask = torch.arange(max_lens).to(lens.device).view(1, max_lens) + mask = mask.expand(bsz, -1) >= lens.view(bsz, 1).expand(-1, max_lens) + return mask + + +def lengths_to_mask(lens: torch.LongTensor) -> torch.BoolTensor: + return ~lengths_to_padding_mask(lens) diff --git a/fairseq-tools/fairseq/fairseq/data/data_utils_fast.pyx b/fairseq-tools/fairseq/fairseq/data/data_utils_fast.pyx new file mode 100644 index 00000000..38b4aa67 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/data_utils_fast.pyx @@ -0,0 +1,123 @@ +# cython: language_level=3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np + +cimport cython +cimport numpy as np + +from libc.stdint cimport int32_t, int64_t + +ctypedef int64_t DTYPE_t + + +cdef _is_batch_full(int64_t num_sentences, int64_t num_tokens, int64_t max_tokens, int64_t max_sentences): + if num_sentences == 0: + return 0 + if max_sentences > 0 and num_sentences == max_sentences: + return 1 + if max_tokens > 0 and num_tokens > max_tokens: + return 1 + return 0 + + +@cython.cdivision(True) +cpdef list batch_by_size_fast( + np.ndarray[DTYPE_t, ndim=1] indices, + num_tokens_fn, + int64_t max_tokens, + int64_t max_sentences, + int32_t bsz_mult, +): + cdef int64_t sample_len = 0 + cdef list sample_lens = [] + cdef list batch = [] + cdef list batches = [] + cdef int64_t mod_len + cdef int64_t i + cdef int64_t idx + cdef int64_t num_tokens + cdef DTYPE_t[:] indices_view = indices + + for i in range(len(indices_view)): + idx = indices_view[i] + num_tokens = num_tokens_fn(idx) + sample_lens.append(num_tokens) + sample_len = max(sample_len, num_tokens) + + assert max_tokens <= 0 or sample_len <= max_tokens, ( + "sentence at index {} of size {} exceeds max_tokens " + "limit of {}!".format(idx, sample_len, max_tokens) + ) + num_tokens = (len(batch) + 1) * sample_len + + if _is_batch_full(len(batch), num_tokens, max_tokens, max_sentences): + mod_len = max( + bsz_mult * (len(batch) // bsz_mult), + len(batch) % bsz_mult, + ) + batches.append(batch[:mod_len]) + batch = batch[mod_len:] + sample_lens = sample_lens[mod_len:] + sample_len = max(sample_lens) if len(sample_lens) > 0 else 0 + batch.append(idx) + if len(batch) > 0: + batches.append(batch) + return batches + + +cdef _find_valid_shape( + DTYPE_t[:, :] shapes_view, + int64_t num_sentences, + int64_t num_tokens, +): + """Return index of first valid shape of -1 if none is found.""" + for i in range(shapes_view.shape[0]): + if num_sentences <= shapes_view[i][0] and num_tokens <= shapes_view[i][1]: + return i + return -1 + + +@cython.cdivision(True) +cpdef list batch_fixed_shapes_fast( + np.ndarray[DTYPE_t, ndim=1] indices, + num_tokens_fn, + np.ndarray[DTYPE_t, ndim=2] fixed_shapes_sorted, +): + cdef int64_t sample_len = 0 + cdef list sample_lens = [] + cdef list batch = [] + cdef list batches = [] + cdef int64_t mod_len + cdef int64_t i + cdef int64_t idx + cdef int64_t num_tokens + cdef DTYPE_t[:] indices_view = indices + cdef DTYPE_t[:, :] shapes_view = fixed_shapes_sorted + + for i in range(len(indices_view)): + idx = indices_view[i] + num_tokens = num_tokens_fn(idx) + sample_lens.append(num_tokens) + sample_len = max(sample_len, num_tokens) + + shape_idx = _find_valid_shape(shapes_view, len(batch) + 1, sample_len) + if shape_idx == -1: + batches.append(batch) + batch = [] + sample_lens = [] + sample_len = 0 + shapes_view = fixed_shapes_sorted + elif shape_idx > 0: + # small optimization for the next call to _find_valid_shape + shapes_view = shapes_view[shape_idx:] + + batch.append(idx) + + if len(batch) > 0: + batches.append(batch) + + return batches diff --git a/fairseq-tools/fairseq/fairseq/data/denoising_dataset.py b/fairseq-tools/fairseq/fairseq/data/denoising_dataset.py new file mode 100644 index 00000000..bdb62c8d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/denoising_dataset.py @@ -0,0 +1,436 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import numpy as np +import torch + +from . import FairseqDataset, data_utils + + +def collate( + samples, + pad_idx, + eos_idx, + vocab, + left_pad_source=False, + left_pad_target=False, + input_feeding=True, + pad_to_length=None, +): + assert input_feeding + if len(samples) == 0: + return {} + + def merge(key, left_pad, move_eos_to_beginning=False, pad_to_length=None): + return data_utils.collate_tokens( + [s[key] for s in samples], + pad_idx, + eos_idx=None, # use eos_idx of each sample instead of vocab.eos() + left_pad=left_pad, + move_eos_to_beginning=move_eos_to_beginning, + pad_to_length=pad_to_length, + ) + + id = torch.LongTensor([s["id"] for s in samples]) + src_tokens = merge( + "source", + left_pad=left_pad_source, + pad_to_length=pad_to_length["source"] if pad_to_length is not None else None, + ) + # sort by descending source length + src_lengths = torch.LongTensor([s["source"].numel() for s in samples]) + src_lengths, sort_order = src_lengths.sort(descending=True) + id = id.index_select(0, sort_order) + src_tokens = src_tokens.index_select(0, sort_order) + + prev_output_tokens = None + target = None + if samples[0].get("target", None) is not None: + target = merge( + "target", + left_pad=left_pad_target, + pad_to_length=pad_to_length["target"] + if pad_to_length is not None + else None, + ) + target = target.index_select(0, sort_order) + ntokens = sum(len(s["target"]) for s in samples) + + if input_feeding: + # we create a shifted version of targets for feeding the + # previous output token(s) into the next decoder step + prev_output_tokens = merge( + "target", + left_pad=left_pad_target, + move_eos_to_beginning=True, + pad_to_length=pad_to_length["target"] + if pad_to_length is not None + else None, + ) + prev_output_tokens = prev_output_tokens.index_select(0, sort_order) + else: + ntokens = sum(len(s["source"]) for s in samples) + + batch = { + "id": id, + "ntokens": ntokens, + "net_input": { + "src_tokens": src_tokens, + "src_lengths": src_lengths, + }, + "target": target, + "nsentences": samples[0]["source"].size(0), + "sort_order": sort_order, + } + if prev_output_tokens is not None: + batch["net_input"]["prev_output_tokens"] = prev_output_tokens + + return batch + + +class DenoisingDataset(FairseqDataset): + """ + A wrapper around TokenBlockDataset for BART dataset. + + Args: + dataset (TokenBlockDataset): dataset to wrap + sizes (List[int]): sentence lengths + vocab (~fairseq.data.Dictionary): vocabulary + mask_idx (int): dictionary index used for masked token + mask_whole_words: only mask whole words. This should be a byte mask + over vocab indices, indicating whether it is the beginning of a + word. We will extend any mask to encompass the whole word. + shuffle (bool, optional): shuffle the elements before batching. + Default: ``True`` + seed: Seed for random number generator for reproducibility. + args: argparse arguments. + """ + + def __init__( + self, + dataset, + sizes, + vocab, + mask_idx, + mask_whole_words, + shuffle, + seed, + args, + eos=None, + item_transform_func=None, + ): + self.dataset = dataset + + self.sizes = sizes + + self.vocab = vocab + self.shuffle = shuffle + self.seed = seed + self.mask_idx = mask_idx + self.mask_whole_word = mask_whole_words + self.mask_ratio = args.mask + self.random_ratio = args.mask_random + self.insert_ratio = args.insert + self.rotate_ratio = args.rotate + self.permute_sentence_ratio = args.permute_sentences + self.eos = eos if eos is not None else vocab.eos() + self.item_transform_func = item_transform_func + + if args.bpe != "gpt2": + self.full_stop_index = self.vocab.eos() + else: + assert args.bpe == "gpt2" + self.full_stop_index = self.vocab.index("13") + + self.replace_length = args.replace_length + if self.replace_length not in [-1, 0, 1]: + raise ValueError(f"invalid arg: replace_length={self.replace_length}") + if args.mask_length not in ["subword", "word", "span-poisson"]: + raise ValueError(f"invalid arg: mask-length={args.mask_length}") + if args.mask_length == "subword" and args.replace_length not in [0, 1]: + raise ValueError(f"if using subwords, use replace-length=1 or 0") + + self.mask_span_distribution = None + if args.mask_length == "span-poisson": + _lambda = args.poisson_lambda + + lambda_to_the_k = 1 + e_to_the_minus_lambda = math.exp(-_lambda) + k_factorial = 1 + ps = [] + for k in range(0, 128): + ps.append(e_to_the_minus_lambda * lambda_to_the_k / k_factorial) + lambda_to_the_k *= _lambda + k_factorial *= k + 1 + if ps[-1] < 0.0000001: + break + ps = torch.FloatTensor(ps) + self.mask_span_distribution = torch.distributions.Categorical(ps) + + self.epoch = 0 + + @property + def can_reuse_epoch_itr_across_epochs(self): + return True # only the noise changes, not item sizes + + def set_epoch(self, epoch, **unused): + self.epoch = epoch + + def __getitem__(self, index): + with data_utils.numpy_seed(self.seed, self.epoch, index): + tokens = self.dataset[index] + assert tokens[-1] == self.eos + source, target = tokens, tokens.clone() + + if self.permute_sentence_ratio > 0.0: + source = self.permute_sentences(source, self.permute_sentence_ratio) + + if self.mask_ratio > 0: + source = self.add_whole_word_mask(source, self.mask_ratio) + + if self.insert_ratio > 0: + source = self.add_insertion_noise(source, self.insert_ratio) + + if self.rotate_ratio > 0.0 and np.random.random() < self.rotate_ratio: + source = self.add_rolling_noise(source) + # there can additional changes to make: + if self.item_transform_func is not None: + source, target = self.item_transform_func(source, target) + + assert (source >= 0).all() + assert (source[1:-1] >= 1).all() + assert (source <= len(self.vocab)).all() + assert source[0] == self.vocab.bos() + assert source[-1] == self.eos + return { + "id": index, + "source": source, + "target": target, + } + + def __len__(self): + return len(self.dataset) + + def permute_sentences(self, source, p=1.0): + full_stops = source == self.full_stop_index + # Pretend it ends with a full stop so last span is a sentence + full_stops[-2] = 1 + + # Tokens that are full stops, where the previous token is not + sentence_ends = (full_stops[1:] * ~full_stops[:-1]).nonzero(as_tuple=False) + 2 + result = source.clone() + + num_sentences = sentence_ends.size(0) + num_to_permute = math.ceil((num_sentences * 2 * p) / 2.0) + substitutions = torch.randperm(num_sentences)[:num_to_permute] + ordering = torch.arange(0, num_sentences) + ordering[substitutions] = substitutions[torch.randperm(num_to_permute)] + + # Ignore <bos> at start + index = 1 + for i in ordering: + sentence = source[(sentence_ends[i - 1] if i > 0 else 1) : sentence_ends[i]] + result[index : index + sentence.size(0)] = sentence + index += sentence.size(0) + return result + + def word_starts(self, source): + if self.mask_whole_word is not None: + is_word_start = self.mask_whole_word.gather(0, source) + else: + is_word_start = torch.ones(source.size()) + is_word_start[0] = 0 + is_word_start[-1] = 0 + return is_word_start + + def add_whole_word_mask(self, source, p): + is_word_start = self.word_starts(source) + num_to_mask = int(math.ceil(is_word_start.float().sum() * p)) + num_inserts = 0 + if num_to_mask == 0: + return source + + if self.mask_span_distribution is not None: + lengths = self.mask_span_distribution.sample(sample_shape=(num_to_mask,)) + + # Make sure we have enough to mask + cum_length = torch.cumsum(lengths, 0) + while cum_length[-1] < num_to_mask: + lengths = torch.cat( + [ + lengths, + self.mask_span_distribution.sample(sample_shape=(num_to_mask,)), + ], + dim=0, + ) + cum_length = torch.cumsum(lengths, 0) + + # Trim to masking budget + i = 0 + while cum_length[i] < num_to_mask: + i += 1 + lengths[i] = num_to_mask - (0 if i == 0 else cum_length[i - 1]) + num_to_mask = i + 1 + lengths = lengths[:num_to_mask] + + # Handle 0-length mask (inserts) separately + lengths = lengths[lengths > 0] + num_inserts = num_to_mask - lengths.size(0) + num_to_mask -= num_inserts + if num_to_mask == 0: + return self.add_insertion_noise(source, num_inserts / source.size(0)) + + assert (lengths > 0).all() + else: + lengths = torch.ones((num_to_mask,)).long() + assert is_word_start[-1] == 0 + word_starts = is_word_start.nonzero(as_tuple=False) + indices = word_starts[ + torch.randperm(word_starts.size(0))[:num_to_mask] + ].squeeze(1) + mask_random = torch.FloatTensor(num_to_mask).uniform_() < self.random_ratio + + source_length = source.size(0) + assert source_length - 1 not in indices + to_keep = torch.ones(source_length, dtype=torch.bool) + is_word_start[ + -1 + ] = 255 # acts as a long length, so spans don't go over the end of doc + if self.replace_length == 0: + to_keep[indices] = 0 + else: + # keep index, but replace it with [MASK] + source[indices] = self.mask_idx + source[indices[mask_random]] = torch.randint( + 1, len(self.vocab), size=(mask_random.sum(),) + ) + + if self.mask_span_distribution is not None: + assert len(lengths.size()) == 1 + assert lengths.size() == indices.size() + lengths -= 1 + while indices.size(0) > 0: + assert lengths.size() == indices.size() + lengths -= is_word_start[indices + 1].long() + uncompleted = lengths >= 0 + indices = indices[uncompleted] + 1 + mask_random = mask_random[uncompleted] + lengths = lengths[uncompleted] + if self.replace_length != -1: + # delete token + to_keep[indices] = 0 + else: + # keep index, but replace it with [MASK] + source[indices] = self.mask_idx + source[indices[mask_random]] = torch.randint( + 1, len(self.vocab), size=(mask_random.sum(),) + ) + else: + # A bit faster when all lengths are 1 + while indices.size(0) > 0: + uncompleted = is_word_start[indices + 1] == 0 + indices = indices[uncompleted] + 1 + mask_random = mask_random[uncompleted] + if self.replace_length != -1: + # delete token + to_keep[indices] = 0 + else: + # keep index, but replace it with [MASK] + source[indices] = self.mask_idx + source[indices[mask_random]] = torch.randint( + 1, len(self.vocab), size=(mask_random.sum(),) + ) + + assert source_length - 1 not in indices + + source = source[to_keep] + + if num_inserts > 0: + source = self.add_insertion_noise(source, num_inserts / source.size(0)) + + return source + + def add_permuted_noise(self, tokens, p): + num_words = len(tokens) + num_to_permute = math.ceil(((num_words * 2) * p) / 2.0) + substitutions = torch.randperm(num_words - 2)[:num_to_permute] + 1 + tokens[substitutions] = tokens[substitutions[torch.randperm(num_to_permute)]] + return tokens + + def add_rolling_noise(self, tokens): + offset = np.random.randint(1, max(1, tokens.size(-1) - 1) + 1) + tokens = torch.cat( + (tokens[0:1], tokens[offset:-1], tokens[1:offset], tokens[-1:]), + dim=0, + ) + return tokens + + def add_insertion_noise(self, tokens, p): + if p == 0.0: + return tokens + + num_tokens = len(tokens) + n = int(math.ceil(num_tokens * p)) + + noise_indices = torch.randperm(num_tokens + n - 2)[:n] + 1 + noise_mask = torch.zeros(size=(num_tokens + n,), dtype=torch.bool) + noise_mask[noise_indices] = 1 + result = torch.LongTensor(n + len(tokens)).fill_(-1) + + num_random = int(math.ceil(n * self.random_ratio)) + result[noise_indices[num_random:]] = self.mask_idx + result[noise_indices[:num_random]] = torch.randint( + low=1, high=len(self.vocab), size=(num_random,) + ) + + result[~noise_mask] = tokens + + assert (result >= 0).all() + return result + + def collater(self, samples, pad_to_length=None): + """Merge a list of samples to form a mini-batch. + Args: + samples (List[dict]): samples to collate + Returns: + dict: a mini-batch of data + """ + return collate( + samples, self.vocab.pad(), self.eos, self.vocab, pad_to_length=pad_to_length + ) + + def num_tokens(self, index): + """Return the number of tokens in a sample. This value is used to + enforce ``--max-tokens`` during batching.""" + return self.sizes[index] + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + return self.sizes[index] + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + if self.shuffle: + indices = np.random.permutation(len(self)) + else: + indices = np.arange(len(self)) + return indices[np.argsort(self.sizes[indices], kind="mergesort")] + + def prefetch(self, indices): + self.src.prefetch(indices) + self.tgt.prefetch(indices) + + @property + def supports_prefetch(self): + return ( + hasattr(self.src, "supports_prefetch") + and self.src.supports_prefetch + and hasattr(self.tgt, "supports_prefetch") + and self.tgt.supports_prefetch + ) diff --git a/fairseq-tools/fairseq/fairseq/data/dictionary.py b/fairseq-tools/fairseq/fairseq/data/dictionary.py new file mode 100644 index 00000000..e2df08e0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/dictionary.py @@ -0,0 +1,387 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +from collections import Counter +from multiprocessing import Pool + +import torch +from fairseq import utils +from fairseq.binarizer import safe_readline +from fairseq.data import data_utils +from fairseq.file_io import PathManager +from fairseq.tokenizer import tokenize_line + + +class Dictionary(object): + """A mapping from symbols to consecutive integers""" + + def __init__( + self, + *, # begin keyword-only arguments + bos="<s>", + pad="<pad>", + eos="</s>", + unk="<unk>", + extra_special_symbols=None, + ): + self.bos_word, self.unk_word, self.pad_word, self.eos_word = bos, unk, pad, eos + self.symbols = [] + self.count = [] + self.indices = {} + self.bos_index = self.add_symbol(bos) + self.pad_index = self.add_symbol(pad) + self.eos_index = self.add_symbol(eos) + self.unk_index = self.add_symbol(unk) + if extra_special_symbols: + for s in extra_special_symbols: + self.add_symbol(s) + self.nspecial = len(self.symbols) + + def __eq__(self, other): + return self.indices == other.indices + + def __getitem__(self, idx): + if idx < len(self.symbols): + return self.symbols[idx] + return self.unk_word + + def __len__(self): + """Returns the number of symbols in the dictionary""" + return len(self.symbols) + + def __contains__(self, sym): + return sym in self.indices + + def index(self, sym): + """Returns the index of the specified symbol""" + assert isinstance(sym, str) + if sym in self.indices: + return self.indices[sym] + return self.unk_index + + def string( + self, + tensor, + bpe_symbol=None, + escape_unk=False, + extra_symbols_to_ignore=None, + unk_string=None, + ): + """Helper for converting a tensor of token indices to a string. + + Can optionally remove BPE symbols or escape <unk> words. + """ + if torch.is_tensor(tensor) and tensor.dim() == 2: + return "\n".join( + self.string(t, bpe_symbol, escape_unk, extra_symbols_to_ignore) + for t in tensor + ) + + extra_symbols_to_ignore = set(extra_symbols_to_ignore or []) + extra_symbols_to_ignore.add(self.eos()) + + def token_string(i): + if i == self.unk(): + if unk_string is not None: + return unk_string + else: + return self.unk_string(escape_unk) + else: + return self[i] + + if hasattr(self, "bos_index"): + extra_symbols_to_ignore.add(self.bos()) + + sent = " ".join( + token_string(i) + for i in tensor + if utils.item(i) not in extra_symbols_to_ignore + ) + + return data_utils.post_process(sent, bpe_symbol) + + def unk_string(self, escape=False): + """Return unknown string, optionally escaped as: <<unk>>""" + if escape: + return "<{}>".format(self.unk_word) + else: + return self.unk_word + + def add_symbol(self, word, n=1, overwrite=False): + """Adds a word to the dictionary""" + if word in self.indices and not overwrite: + idx = self.indices[word] + self.count[idx] = self.count[idx] + n + return idx + else: + idx = len(self.symbols) + self.indices[word] = idx + self.symbols.append(word) + self.count.append(n) + return idx + + def update(self, new_dict): + """Updates counts from new dictionary.""" + for word in new_dict.symbols: + idx2 = new_dict.indices[word] + if word in self.indices: + idx = self.indices[word] + self.count[idx] = self.count[idx] + new_dict.count[idx2] + else: + idx = len(self.symbols) + self.indices[word] = idx + self.symbols.append(word) + self.count.append(new_dict.count[idx2]) + + def finalize(self, threshold=-1, nwords=-1, padding_factor=8): + """Sort symbols by frequency in descending order, ignoring special ones. + + Args: + - threshold defines the minimum word count + - nwords defines the total number of words in the final dictionary, + including special symbols + - padding_factor can be used to pad the dictionary size to be a + multiple of 8, which is important on some hardware (e.g., Nvidia + Tensor Cores). + """ + if nwords <= 0: + nwords = len(self) + + new_indices = dict(zip(self.symbols[: self.nspecial], range(self.nspecial))) + new_symbols = self.symbols[: self.nspecial] + new_count = self.count[: self.nspecial] + + c = Counter( + dict( + sorted(zip(self.symbols[self.nspecial :], self.count[self.nspecial :])) + ) + ) + for symbol, count in c.most_common(nwords - self.nspecial): + if count >= threshold: + new_indices[symbol] = len(new_symbols) + new_symbols.append(symbol) + new_count.append(count) + else: + break + + assert len(new_symbols) == len(new_indices) + + self.count = list(new_count) + self.symbols = list(new_symbols) + self.indices = new_indices + + self.pad_to_multiple_(padding_factor) + + def pad_to_multiple_(self, padding_factor): + """Pad Dictionary size to be a multiple of *padding_factor*.""" + if padding_factor > 1: + i = 0 + while len(self) % padding_factor != 0: + symbol = "madeupword{:04d}".format(i) + self.add_symbol(symbol, n=0) + i += 1 + + def bos(self): + """Helper to get index of beginning-of-sentence symbol""" + return self.bos_index + + def pad(self): + """Helper to get index of pad symbol""" + return self.pad_index + + def eos(self): + """Helper to get index of end-of-sentence symbol""" + return self.eos_index + + def unk(self): + """Helper to get index of unk symbol""" + return self.unk_index + + @classmethod + def load(cls, f): + """Loads the dictionary from a text file with the format: + + ``` + <symbol0> <count0> + <symbol1> <count1> + ... + ``` + """ + d = cls() + d.add_from_file(f) + return d + + def add_from_file(self, f): + """ + Loads a pre-existing dictionary from a text file and adds its symbols + to this instance. + """ + if isinstance(f, str): + try: + with open(PathManager.get_local_path(f), "r", encoding="utf-8") as fd: + self.add_from_file(fd) + except FileNotFoundError as fnfe: + raise fnfe + except UnicodeError: + raise Exception( + "Incorrect encoding detected in {}, please " + "rebuild the dataset".format(f) + ) + return + + lines = f.readlines() + indices_start_line = self._load_meta(lines) + + for line in lines[indices_start_line:]: + try: + line, field = line.rstrip().rsplit(" ", 1) + if field == "#fairseq:overwrite": + overwrite = True + line, field = line.rsplit(" ", 1) + else: + overwrite = False + count = int(field) + word = line + if word in self and not overwrite: + raise RuntimeError( + "Duplicate word found when loading Dictionary: '{}'. " + "Duplicate words can overwrite earlier ones by adding the " + "#fairseq:overwrite flag at the end of the corresponding row " + "in the dictionary file. If using the Camembert model, please " + "download an updated copy of the model file.".format(word) + ) + self.add_symbol(word, n=count, overwrite=overwrite) + except ValueError: + raise ValueError( + "Incorrect dictionary format, expected '<token> <cnt> [flags]'" + ) + + def _save(self, f, kv_iterator): + if isinstance(f, str): + PathManager.mkdirs(os.path.dirname(f)) + with PathManager.open(f, "w", encoding="utf-8") as fd: + return self.save(fd) + for k, v in kv_iterator: + print("{} {}".format(k, v), file=f) + + def _get_meta(self): + return [], [] + + def _load_meta(self, lines): + return 0 + + def save(self, f): + """Stores dictionary into a text file""" + ex_keys, ex_vals = self._get_meta() + self._save( + f, + zip( + ex_keys + self.symbols[self.nspecial :], + ex_vals + self.count[self.nspecial :], + ), + ) + + def dummy_sentence(self, length): + t = torch.Tensor(length).uniform_(self.nspecial + 1, len(self)).long() + t[-1] = self.eos() + return t + + def encode_line( + self, + line, + line_tokenizer=tokenize_line, + add_if_not_exist=True, + consumer=None, + append_eos=True, + reverse_order=False, + ): + words = line_tokenizer(line) + if reverse_order: + words = list(reversed(words)) + nwords = len(words) + ids = torch.IntTensor(nwords + 1 if append_eos else nwords) + + for i, word in enumerate(words): + if add_if_not_exist: + idx = self.add_symbol(word) + else: + idx = self.index(word) + if consumer is not None: + consumer(word, idx) + ids[i] = idx + if append_eos: + ids[nwords] = self.eos_index + return ids + + @staticmethod + def _add_file_to_dictionary_single_worker( + filename, tokenize, eos_word, worker_id=0, num_workers=1 + ): + counter = Counter() + with open(PathManager.get_local_path(filename), "r", encoding="utf-8") as f: + size = os.fstat(f.fileno()).st_size + chunk_size = size // num_workers + offset = worker_id * chunk_size + end = offset + chunk_size + f.seek(offset) + if offset > 0: + safe_readline(f) # drop first incomplete line + line = f.readline() + while line: + for word in tokenize(line): + counter.update([word]) + counter.update([eos_word]) + if f.tell() > end: + break + line = f.readline() + return counter + + @staticmethod + def add_file_to_dictionary(filename, dict, tokenize, num_workers): + def merge_result(counter): + for w, c in sorted(counter.items()): + dict.add_symbol(w, c) + + if num_workers > 1: + pool = Pool(processes=num_workers) + results = [] + for worker_id in range(num_workers): + results.append( + pool.apply_async( + Dictionary._add_file_to_dictionary_single_worker, + (filename, tokenize, dict.eos_word, worker_id, num_workers), + ) + ) + pool.close() + pool.join() + for r in results: + merge_result(r.get()) + else: + merge_result( + Dictionary._add_file_to_dictionary_single_worker( + filename, tokenize, dict.eos_word + ) + ) + + +class TruncatedDictionary(object): + def __init__(self, wrapped_dict, length): + self.__class__ = type( + wrapped_dict.__class__.__name__, + (self.__class__, wrapped_dict.__class__), + {}, + ) + self.__dict__ = wrapped_dict.__dict__ + self.wrapped_dict = wrapped_dict + self.length = min(len(self.wrapped_dict), length) + + def __len__(self): + return self.length + + def __getitem__(self, i): + if i < self.length: + return self.wrapped_dict[i] + return self.wrapped_dict.unk() diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/__init__.py b/fairseq-tools/fairseq/fairseq/data/encoders/__init__.py new file mode 100644 index 00000000..2e807d8a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/__init__.py @@ -0,0 +1,29 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +import importlib +import os + +from fairseq import registry + + +build_tokenizer, register_tokenizer, TOKENIZER_REGISTRY, _ = registry.setup_registry( + "--tokenizer", + default=None, +) + + +build_bpe, register_bpe, BPE_REGISTRY, _ = registry.setup_registry( + "--bpe", + default=None, +) + + +# automatically import any Python files in the encoders/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("fairseq.data.encoders." + module) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/byte_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/byte_bpe.py new file mode 100644 index 00000000..0d2da3ea --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/byte_bpe.py @@ -0,0 +1,45 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from fairseq import file_utils +from fairseq.data.encoders import register_bpe +from fairseq.data.encoders.byte_utils import ( + SPACE, + SPACE_ESCAPE, + byte_encode, + smart_byte_decode, +) + + +@register_bpe("byte_bpe") +class ByteBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--sentencepiece-model-path', type=str, + help='path to sentencepiece model') + # fmt: on + + def __init__(self, args): + vocab = file_utils.cached_path(args.sentencepiece_model_path) + try: + import sentencepiece as spm + + self.sp = spm.SentencePieceProcessor() + self.sp.Load(vocab) + except ImportError: + raise ImportError( + "Please install sentencepiece with: pip install sentencepiece" + ) + + def encode(self, x: str) -> str: + byte_encoded = byte_encode(x) + return SPACE.join(self.sp.EncodeAsPieces(byte_encoded)) + + @staticmethod + def decode(x: str) -> str: + unescaped = x.replace(SPACE, "").replace(SPACE_ESCAPE, SPACE) + return smart_byte_decode(unescaped) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/byte_utils.py b/fairseq-tools/fairseq/fairseq/data/encoders/byte_utils.py new file mode 100644 index 00000000..a305c080 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/byte_utils.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import re + + +WHITESPACE_NORMALIZER = re.compile(r"\s+") +SPACE = chr(32) +SPACE_ESCAPE = chr(9601) +# excluding non-breaking space (160) here +PRINTABLE_LATIN = set( + list(range(32, 126 + 1)) + list(range(161, 172 + 1)) + list(range(174, 255 + 1)) +) +BYTE_TO_BCHAR = { + b: chr(b) if b in PRINTABLE_LATIN else chr(256 + b) for b in range(256) +} +BCHAR_TO_BYTE = {bc: b for b, bc in BYTE_TO_BCHAR.items()} + + +def byte_encode(x: str) -> str: + normalized = WHITESPACE_NORMALIZER.sub(SPACE, x) + return "".join([BYTE_TO_BCHAR[b] for b in normalized.encode("utf-8")]) + + +def byte_decode(x: str) -> str: + try: + return bytes([BCHAR_TO_BYTE[bc] for bc in x]).decode("utf-8") + except ValueError: + return "" + + +def smart_byte_decode(x: str) -> str: + output = byte_decode(x) + if output == "": + # DP the best recovery (max valid chars) if it's broken + n_bytes = len(x) + f = [0 for _ in range(n_bytes + 1)] + pt = [0 for _ in range(n_bytes + 1)] + for i in range(1, n_bytes + 1): + f[i], pt[i] = f[i - 1], i - 1 + for j in range(1, min(4, i) + 1): + if f[i - j] + 1 > f[i] and len(byte_decode(x[i - j : i])) > 0: + f[i], pt[i] = f[i - j] + 1, i - j + cur_pt = n_bytes + while cur_pt > 0: + if f[cur_pt] == f[pt[cur_pt]] + 1: + output = byte_decode(x[pt[cur_pt] : cur_pt]) + output + cur_pt = pt[cur_pt] + return output diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/bytes.py b/fairseq-tools/fairseq/fairseq/data/encoders/bytes.py new file mode 100644 index 00000000..bb9554ed --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/bytes.py @@ -0,0 +1,34 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from fairseq.data.encoders import register_bpe +from fairseq.data.encoders.byte_utils import ( + SPACE, + SPACE_ESCAPE, + byte_encode, + smart_byte_decode, +) + + +@register_bpe("bytes") +class Bytes(object): + def __init__(self, args): + pass + + @staticmethod + def add_args(parser): + pass + + @staticmethod + def encode(x: str) -> str: + encoded = byte_encode(x) + escaped = encoded.replace(SPACE, SPACE_ESCAPE) + return SPACE.join(list(escaped)) + + @staticmethod + def decode(x: str) -> str: + unescaped = x.replace(SPACE, "").replace(SPACE_ESCAPE, SPACE) + return smart_byte_decode(unescaped) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/characters.py b/fairseq-tools/fairseq/fairseq/data/encoders/characters.py new file mode 100644 index 00000000..cffc5751 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/characters.py @@ -0,0 +1,30 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from fairseq.data.encoders import register_bpe + + +SPACE = chr(32) +SPACE_ESCAPE = chr(9601) + + +@register_bpe("characters") +class Characters(object): + def __init__(self, args): + pass + + @staticmethod + def add_args(parser): + pass + + @staticmethod + def encode(x: str) -> str: + escaped = x.replace(SPACE, SPACE_ESCAPE) + return SPACE.join(list(escaped)) + + @staticmethod + def decode(x: str) -> str: + return x.replace(SPACE, "").replace(SPACE_ESCAPE, SPACE) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/fastbpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/fastbpe.py new file mode 100644 index 00000000..74d4ad85 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/fastbpe.py @@ -0,0 +1,35 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import file_utils +from fairseq.data.encoders import register_bpe + + +@register_bpe("fastbpe") +class fastBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--bpe-codes', type=str, + help='path to fastBPE BPE') + # fmt: on + + def __init__(self, args): + if args.bpe_codes is None: + raise ValueError("--bpe-codes is required for --bpe=fastbpe") + codes = file_utils.cached_path(args.bpe_codes) + try: + import fastBPE + + self.bpe = fastBPE.fastBPE(codes) + self.bpe_symbol = "@@ " + except ImportError: + raise ImportError("Please install fastBPE with: pip install fastBPE") + + def encode(self, x: str) -> str: + return self.bpe.apply([x])[0] + + def decode(self, x: str) -> str: + return (x + " ").replace(self.bpe_symbol, "").rstrip() diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe.py new file mode 100644 index 00000000..8ac099a6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe.py @@ -0,0 +1,47 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import file_utils +from fairseq.data.encoders import register_bpe + +from .gpt2_bpe_utils import get_encoder + + +DEFAULT_ENCODER_JSON = "https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/encoder.json" +DEFAULT_VOCAB_BPE = "https://dl.fbaipublicfiles.com/fairseq/gpt2_bpe/vocab.bpe" + + +@register_bpe("gpt2") +class GPT2BPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--gpt2-encoder-json', type=str, + default=DEFAULT_ENCODER_JSON, + help='path to encoder.json') + parser.add_argument('--gpt2-vocab-bpe', type=str, + default=DEFAULT_VOCAB_BPE, + help='path to vocab.bpe') + # fmt: on + + def __init__(self, args): + encoder_json = file_utils.cached_path( + getattr(args, "gpt2_encoder_json", DEFAULT_ENCODER_JSON) + ) + vocab_bpe = file_utils.cached_path( + getattr(args, "gpt2_vocab_bpe", DEFAULT_VOCAB_BPE) + ) + self.bpe = get_encoder(encoder_json, vocab_bpe) + + def encode(self, x: str) -> str: + return " ".join(map(str, self.bpe.encode(x))) + + def decode(self, x: str) -> str: + return self.bpe.decode( + [int(tok) if tok not in {"<unk>", "<mask>"} else tok for tok in x.split()] + ) + + def is_beginning_of_word(self, x: str) -> bool: + return self.decode(x).startswith(" ") diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe_utils.py b/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe_utils.py new file mode 100644 index 00000000..688d4e36 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/gpt2_bpe_utils.py @@ -0,0 +1,140 @@ +""" +Byte pair encoding utilities from GPT-2. + +Original source: https://github.com/openai/gpt-2/blob/master/src/encoder.py +Original license: MIT +""" + +import json +from functools import lru_cache + + +@lru_cache() +def bytes_to_unicode(): + """ + Returns list of utf-8 byte and a corresponding list of unicode strings. + The reversible bpe codes work on unicode strings. + This means you need a large # of unicode characters in your vocab if you want to avoid UNKs. + When you're at something like a 10B token dataset you end up needing around 5K for decent coverage. + This is a signficant percentage of your normal, say, 32K bpe vocab. + To avoid that, we want lookup tables between utf-8 bytes and unicode strings. + And avoids mapping to whitespace/control characters the bpe code barfs on. + """ + bs = ( + list(range(ord("!"), ord("~") + 1)) + + list(range(ord("¡"), ord("¬") + 1)) + + list(range(ord("®"), ord("ÿ") + 1)) + ) + cs = bs[:] + n = 0 + for b in range(2 ** 8): + if b not in bs: + bs.append(b) + cs.append(2 ** 8 + n) + n += 1 + cs = [chr(n) for n in cs] + return dict(zip(bs, cs)) + + +def get_pairs(word): + """Return set of symbol pairs in a word. + Word is represented as tuple of symbols (symbols being variable-length strings). + """ + pairs = set() + prev_char = word[0] + for char in word[1:]: + pairs.add((prev_char, char)) + prev_char = char + return pairs + + +class Encoder: + def __init__(self, encoder, bpe_merges, errors="replace"): + self.encoder = encoder + self.decoder = {v: k for k, v in self.encoder.items()} + self.errors = errors # how to handle errors in decoding + self.byte_encoder = bytes_to_unicode() + self.byte_decoder = {v: k for k, v in self.byte_encoder.items()} + self.bpe_ranks = dict(zip(bpe_merges, range(len(bpe_merges)))) + self.cache = {} + + try: + import regex as re + + self.re = re + except ImportError: + raise ImportError("Please install regex with: pip install regex") + + # Should haved added re.IGNORECASE so BPE merges can happen for capitalized versions of contractions + self.pat = self.re.compile( + r"""'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+""" + ) + + def bpe(self, token): + if token in self.cache: + return self.cache[token] + word = tuple(token) + pairs = get_pairs(word) + + if not pairs: + return token + + while True: + bigram = min(pairs, key=lambda pair: self.bpe_ranks.get(pair, float("inf"))) + if bigram not in self.bpe_ranks: + break + first, second = bigram + new_word = [] + i = 0 + while i < len(word): + try: + j = word.index(first, i) + new_word.extend(word[i:j]) + i = j + except: + new_word.extend(word[i:]) + break + + if word[i] == first and i < len(word) - 1 and word[i + 1] == second: + new_word.append(first + second) + i += 2 + else: + new_word.append(word[i]) + i += 1 + new_word = tuple(new_word) + word = new_word + if len(word) == 1: + break + else: + pairs = get_pairs(word) + word = " ".join(word) + self.cache[token] = word + return word + + def encode(self, text): + bpe_tokens = [] + for token in self.re.findall(self.pat, text): + token = "".join(self.byte_encoder[b] for b in token.encode("utf-8")) + bpe_tokens.extend( + self.encoder[bpe_token] for bpe_token in self.bpe(token).split(" ") + ) + return bpe_tokens + + def decode(self, tokens): + text = "".join([self.decoder.get(token, token) for token in tokens]) + text = bytearray([self.byte_decoder[c] for c in text]).decode( + "utf-8", errors=self.errors + ) + return text + + +def get_encoder(encoder_json_path, vocab_bpe_path): + with open(encoder_json_path, "r") as f: + encoder = json.load(f) + with open(vocab_bpe_path, "r", encoding="utf-8") as f: + bpe_data = f.read() + bpe_merges = [tuple(merge_str.split()) for merge_str in bpe_data.split("\n")[1:-1]] + return Encoder( + encoder=encoder, + bpe_merges=bpe_merges, + ) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/hf_bert_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/hf_bert_bpe.py new file mode 100644 index 00000000..a968fe88 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/hf_bert_bpe.py @@ -0,0 +1,48 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data.encoders import register_bpe + + +@register_bpe("bert") +class BertBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--bpe-cased', action='store_true', + help='set for cased BPE', + default=False) + parser.add_argument('--bpe-vocab-file', type=str, + help='bpe vocab file.') + # fmt: on + + def __init__(self, args): + try: + from transformers import BertTokenizer + except ImportError: + raise ImportError( + "Please install transformers with: pip install transformers" + ) + + if "bpe_vocab_file" in args: + self.bert_tokenizer = BertTokenizer( + args.bpe_vocab_file, do_lower_case=not args.bpe_cased + ) + else: + vocab_file_name = ( + "bert-base-cased" if args.bpe_cased else "bert-base-uncased" + ) + self.bert_tokenizer = BertTokenizer.from_pretrained(vocab_file_name) + + def encode(self, x: str) -> str: + return " ".join(self.bert_tokenizer.tokenize(x)) + + def decode(self, x: str) -> str: + return self.bert_tokenizer.clean_up_tokenization( + self.bert_tokenizer.convert_tokens_to_string(x.split(" ")) + ) + + def is_beginning_of_word(self, x: str) -> bool: + return not x.startswith("##") diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/hf_byte_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/hf_byte_bpe.py new file mode 100644 index 00000000..544d4082 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/hf_byte_bpe.py @@ -0,0 +1,43 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data.encoders import register_bpe + + +@register_bpe("hf_byte_bpe") +class HuggingFaceByteLevelBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--bpe-merges', help='path to merges.txt') + parser.add_argument('--bpe-vocab', help='path to vocab.json') + parser.add_argument('--bpe-add-prefix-space', action='store_true', + help='add prefix space before encoding') + # fmt: on + + def __init__(self, args): + try: + from tokenizers import ByteLevelBPETokenizer + except ImportError: + raise ImportError( + "Please install huggingface/tokenizers with: " "pip install tokenizers" + ) + + self.bpe = ByteLevelBPETokenizer( + args.bpe_vocab, + args.bpe_merges, + add_prefix_space=getattr(args, "bpe_add_prefix_space", False), + ) + + def encode(self, x: str) -> str: + return " ".join(map(str, self.bpe.encode(x).ids)) + + def decode(self, x: str) -> str: + return self.bpe.decode( + [int(tok) if tok not in {"<unk>", "<mask>"} else tok for tok in x.split()] + ) + + def is_beginning_of_word(self, x: str) -> bool: + return self.decode(x).startswith(" ") diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/moses_tokenizer.py b/fairseq-tools/fairseq/fairseq/data/encoders/moses_tokenizer.py new file mode 100644 index 00000000..8c248442 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/moses_tokenizer.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data.encoders import register_tokenizer + + +@register_tokenizer("moses") +class MosesTokenizer(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--moses-source-lang', metavar='SRC', + help='source language') + parser.add_argument('--moses-target-lang', metavar='TARGET', + help='target language') + parser.add_argument('--moses-no-dash-splits', action='store_true', default=False, + help='don\'t apply dash split rules') + parser.add_argument('--moses-no-escape', action='store_true', default=False, + help='don\'t perform HTML escaping on apostrophy, quotes, etc.') + # fmt: on + + def __init__(self, args): + self.args = args + + if getattr(args, "moses_source_lang", None) is None: + args.moses_source_lang = getattr(args, "source_lang", "en") + if getattr(args, "moses_target_lang", None) is None: + args.moses_target_lang = getattr(args, "target_lang", "en") + + try: + from sacremoses import MosesTokenizer, MosesDetokenizer + + self.tok = MosesTokenizer(args.moses_source_lang) + self.detok = MosesDetokenizer(args.moses_target_lang) + except ImportError: + raise ImportError( + "Please install Moses tokenizer with: pip install sacremoses" + ) + + def encode(self, x: str) -> str: + return self.tok.tokenize( + x, + aggressive_dash_splits=(not self.args.moses_no_dash_splits), + return_str=True, + escape=(not self.args.moses_no_escape), + ) + + def decode(self, x: str) -> str: + return self.detok.detokenize(x.split()) diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/nltk_tokenizer.py b/fairseq-tools/fairseq/fairseq/data/encoders/nltk_tokenizer.py new file mode 100644 index 00000000..3b617e73 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/nltk_tokenizer.py @@ -0,0 +1,23 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data.encoders import register_tokenizer + + +@register_tokenizer("nltk") +class NLTKTokenizer(object): + def __init__(self, source_lang=None, target_lang=None): + try: + from nltk.tokenize import word_tokenize + + self.word_tokenize = word_tokenize + except ImportError: + raise ImportError("Please install nltk with: pip install nltk") + + def encode(self, x: str) -> str: + return " ".join(self.word_tokenize(x)) + + def decode(self, x: str) -> str: + return x diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/sentencepiece_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/sentencepiece_bpe.py new file mode 100644 index 00000000..b25c6cae --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/sentencepiece_bpe.py @@ -0,0 +1,45 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import file_utils +from fairseq.data.encoders import register_bpe + + +@register_bpe("sentencepiece") +class SentencepieceBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--sentencepiece-model', type=str, + help='path to sentencepiece model') + # fmt: on + + def __init__(self, args): + sentencepiece_model = file_utils.cached_path(args.sentencepiece_model) + try: + import sentencepiece as spm + + self.sp = spm.SentencePieceProcessor() + self.sp.Load(sentencepiece_model) + except ImportError: + raise ImportError( + "Please install sentencepiece with: pip install sentencepiece" + ) + + def encode(self, x: str) -> str: + return " ".join(self.sp.EncodeAsPieces(x)) + + def decode(self, x: str) -> str: + return x.replace(" ", "").replace("\u2581", " ").strip() + + def is_beginning_of_word(self, x: str) -> bool: + if x in ["<unk>", "<s>", "</s>", "<pad>"]: + # special elements are always considered beginnings + # HACK: this logic is already present in fairseq/tasks/masked_lm.py + # but these special tokens are also contained in the sentencepiece + # vocabulary which causes duplicate special tokens. This hack makes + # sure that they are all taken into account. + return True + return x.startswith("\u2581") diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/space_tokenizer.py b/fairseq-tools/fairseq/fairseq/data/encoders/space_tokenizer.py new file mode 100644 index 00000000..3bc7ce49 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/space_tokenizer.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import re + +from fairseq.data.encoders import register_tokenizer + + +@register_tokenizer("space") +class SpaceTokenizer(object): + def __init__(self, source_lang=None, target_lang=None): + self.space_tok = re.compile(r"\s+") + + def encode(self, x: str) -> str: + return self.space_tok.sub(" ", x) + + def decode(self, x: str) -> str: + return x diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/subword_nmt_bpe.py b/fairseq-tools/fairseq/fairseq/data/encoders/subword_nmt_bpe.py new file mode 100644 index 00000000..e85f99af --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/subword_nmt_bpe.py @@ -0,0 +1,54 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import file_utils +from fairseq.data.encoders import register_bpe + + +@register_bpe("subword_nmt") +class SubwordNMTBPE(object): + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--bpe-codes', type=str, + help='path to subword NMT BPE') + parser.add_argument('--bpe-separator', default='@@', + help='BPE separator') + # fmt: on + + def __init__(self, args): + if args.bpe_codes is None: + raise ValueError("--bpe-codes is required for --bpe=subword_nmt") + codes = file_utils.cached_path(args.bpe_codes) + try: + from subword_nmt import apply_bpe + + bpe_parser = apply_bpe.create_parser() + bpe_args = bpe_parser.parse_args( + [ + "--codes", + codes, + "--separator", + args.bpe_separator, + ] + ) + self.bpe = apply_bpe.BPE( + bpe_args.codes, + bpe_args.merges, + bpe_args.separator, + None, + bpe_args.glossaries, + ) + self.bpe_symbol = bpe_args.separator + " " + except ImportError: + raise ImportError( + "Please install subword_nmt with: pip install subword-nmt" + ) + + def encode(self, x: str) -> str: + return self.bpe.process_line(x) + + def decode(self, x: str) -> str: + return (x + " ").replace(self.bpe_symbol, "").rstrip() diff --git a/fairseq-tools/fairseq/fairseq/data/encoders/utils.py b/fairseq-tools/fairseq/fairseq/data/encoders/utils.py new file mode 100644 index 00000000..d93eb532 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/encoders/utils.py @@ -0,0 +1,30 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq.data import encoders + + +def get_whole_word_mask(args, dictionary): + bpe = encoders.build_bpe(args) + if bpe is not None: + + def is_beginning_of_word(i): + if i < dictionary.nspecial: + # special elements are always considered beginnings + return True + tok = dictionary[i] + if tok.startswith("madeupword"): + return True + try: + return bpe.is_beginning_of_word(tok) + except ValueError: + return True + + mask_whole_words = torch.ByteTensor( + list(map(is_beginning_of_word, range(len(dictionary)))) + ) + return mask_whole_words + return None diff --git a/fairseq-tools/fairseq/fairseq/data/fairseq_dataset.py b/fairseq-tools/fairseq/fairseq/data/fairseq_dataset.py new file mode 100644 index 00000000..ed08c1ba --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/fairseq_dataset.py @@ -0,0 +1,191 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch.utils.data +from fairseq.data import data_utils + + +class EpochListening: + """Mixin for receiving updates whenever the epoch increments.""" + + @property + def can_reuse_epoch_itr_across_epochs(self): + """ + Whether we can reuse the :class:`fairseq.data.EpochBatchIterator` for + this dataset across epochs. + + This needs to return ``False`` if the sample sizes can change across + epochs, in which case we may need to regenerate batches at each epoch. + If your dataset relies in ``set_epoch`` then you should consider setting + this to ``False``. + """ + return True + + def set_epoch(self, epoch): + """Will receive the updated epoch number at the beginning of the epoch.""" + pass + + +class FairseqDataset(torch.utils.data.Dataset, EpochListening): + """A dataset that provides helpers for batching.""" + + def __getitem__(self, index): + raise NotImplementedError + + def __len__(self): + raise NotImplementedError + + def collater(self, samples): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[dict]): samples to collate + + Returns: + dict: a mini-batch suitable for forwarding with a Model + """ + raise NotImplementedError + + def num_tokens(self, index): + """Return the number of tokens in a sample. This value is used to + enforce ``--max-tokens`` during batching.""" + raise NotImplementedError + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + raise NotImplementedError + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + return np.arange(len(self), dtype=np.int64) + + @property + def supports_prefetch(self): + """Whether this dataset supports prefetching.""" + return False + + def attr(self, attr: str, index: int): + return getattr(self, attr, None) + + def prefetch(self, indices): + """Prefetch the data required for this epoch.""" + raise NotImplementedError + + def get_batch_shapes(self): + """ + Return a list of valid batch shapes, for example:: + + [(8, 512), (16, 256), (32, 128)] + + The first dimension of each tuple is the batch size and can be ``None`` + to automatically infer the max batch size based on ``--max-tokens``. + The second dimension of each tuple is the max supported length as given + by :func:`fairseq.data.FairseqDataset.num_tokens`. + + This will be used by :func:`fairseq.data.FairseqDataset.batch_by_size` + to restrict batch shapes. This is useful on TPUs to avoid too many + dynamic shapes (and recompilations). + """ + return None + + def batch_by_size( + self, + indices, + max_tokens=None, + max_sentences=None, + required_batch_size_multiple=1, + ): + """ + Given an ordered set of indices, return batches according to + *max_tokens*, *max_sentences* and *required_batch_size_multiple*. + """ + from fairseq.data import data_utils + + fixed_shapes = self.get_batch_shapes() + if fixed_shapes is not None: + + def adjust_bsz(bsz, num_tokens): + if bsz is None: + assert max_tokens is not None, "Must specify --max-tokens" + bsz = max_tokens // num_tokens + if max_sentences is not None: + bsz = min(bsz, max_sentences) + elif ( + bsz >= required_batch_size_multiple + and bsz % required_batch_size_multiple != 0 + ): + bsz -= bsz % required_batch_size_multiple + return bsz + + fixed_shapes = np.array( + [ + [adjust_bsz(bsz, num_tokens), num_tokens] + for (bsz, num_tokens) in fixed_shapes + ] + ) + + return data_utils.batch_by_size( + indices, + num_tokens_fn=self.num_tokens, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + fixed_shapes=fixed_shapes, + ) + + def filter_indices_by_size(self, indices, max_sizes): + """ + Filter a list of sample indices. Remove those that are longer than + specified in *max_sizes*. + + WARNING: don't update, override method in child classes + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + if isinstance(max_sizes, float) or isinstance(max_sizes, int): + if hasattr(self, "sizes") and isinstance(self.sizes, np.ndarray): + ignored = indices[self.sizes[indices] > max_sizes].tolist() + indices = indices[self.sizes[indices] <= max_sizes] + elif ( + hasattr(self, "sizes") + and isinstance(self.sizes, list) + and len(self.sizes) == 1 + ): + ignored = indices[self.sizes[0][indices] > max_sizes].tolist() + indices = indices[self.sizes[0][indices] <= max_sizes] + else: + indices, ignored = data_utils._filter_by_size_dynamic( + indices, self.size, max_sizes + ) + else: + indices, ignored = data_utils._filter_by_size_dynamic( + indices, self.size, max_sizes + ) + return indices, ignored + + @property + def supports_fetch_outside_dataloader(self): + """Whether this dataset supports fetching outside the workers of the dataloader.""" + return True + + +class FairseqIterableDataset(torch.utils.data.IterableDataset, EpochListening): + """ + For datasets that need to be read sequentially, usually because the data is + being streamed or otherwise can't be manipulated on a single machine. + """ + + def __iter__(self): + raise NotImplementedError diff --git a/fairseq-tools/fairseq/fairseq/data/fasta_dataset.py b/fairseq-tools/fairseq/fairseq/data/fasta_dataset.py new file mode 100644 index 00000000..00701197 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/fasta_dataset.py @@ -0,0 +1,107 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import subprocess +import threading +from pathlib import Path + +import numpy as np +import torch + + +def fasta_file_path(prefix_path): + return prefix_path + ".fasta" + + +class FastaDataset(torch.utils.data.Dataset): + """ + For loading protein sequence datasets in the common FASTA data format + """ + + def __init__(self, path: str, cache_indices=False): + self.fn = fasta_file_path(path) + self.threadlocal = threading.local() + self.cache = Path(f"{path}.fasta.idx.npy") + if cache_indices: + if self.cache.exists(): + self.offsets, self.sizes = np.load(self.cache) + else: + self.offsets, self.sizes = self._build_index(path) + np.save(self.cache, np.stack([self.offsets, self.sizes])) + else: + self.offsets, self.sizes = self._build_index(path) + + def _get_file(self): + if not hasattr(self.threadlocal, "f"): + self.threadlocal.f = open(self.fn, "r") + return self.threadlocal.f + + def __getitem__(self, idx): + f = self._get_file() + f.seek(self.offsets[idx]) + desc = f.readline().strip() + line = f.readline() + seq = "" + while line != "" and line[0] != ">": + seq += line.strip() + line = f.readline() + return desc, seq + + def __len__(self): + return self.offsets.size + + def _build_index(self, path: str): + # Use grep and awk to get 100M/s on local SSD. + # Should process your enormous 100G fasta in ~10 min single core... + path = fasta_file_path(path) + bytes_offsets = subprocess.check_output( + f"cat {path} | tqdm --bytes --total $(wc -c < {path})" + "| grep --byte-offset '^>' -o | cut -d: -f1", + shell=True, + ) + fasta_lengths = subprocess.check_output( + f"cat {path} | tqdm --bytes --total $(wc -c < {path})" + "| awk '/^>/ {print \"\";next;} { printf(\"%s\",$0);}' | tail -n+2 | awk '{print length($1)}'", + shell=True, + ) + bytes_np = np.fromstring(bytes_offsets, dtype=np.int64, sep=" ") + sizes_np = np.fromstring(fasta_lengths, dtype=np.int64, sep=" ") + return bytes_np, sizes_np + + def __setstate__(self, state): + self.__dict__ = state + self.threadlocal = threading.local() + + def __getstate__(self): + d = {} + for i, v in self.__dict__.items(): + if i != "threadlocal": + d[i] = v + return d + + def __del__(self): + if hasattr(self.threadlocal, "f"): + self.threadlocal.f.close() + del self.threadlocal.f + + @staticmethod + def exists(path): + return os.path.exists(fasta_file_path(path)) + + +class EncodedFastaDataset(FastaDataset): + """ + The FastaDataset returns raw sequences - this allows us to return + indices with a dictionary instead. + """ + + def __init__(self, path, dictionary): + super().__init__(path, cache_indices=True) + self.dictionary = dictionary + + def __getitem__(self, idx): + desc, seq = super().__getitem__(idx) + return self.dictionary.encode_line(seq, line_tokenizer=list).long() diff --git a/fairseq-tools/fairseq/fairseq/data/id_dataset.py b/fairseq-tools/fairseq/fairseq/data/id_dataset.py new file mode 100644 index 00000000..3e4d7969 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/id_dataset.py @@ -0,0 +1,19 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import FairseqDataset + + +class IdDataset(FairseqDataset): + def __getitem__(self, index): + return index + + def __len__(self): + return 0 + + def collater(self, samples): + return torch.tensor(samples) diff --git a/fairseq-tools/fairseq/fairseq/data/indexed_dataset.py b/fairseq-tools/fairseq/fairseq/data/indexed_dataset.py new file mode 100644 index 00000000..3efecab3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/indexed_dataset.py @@ -0,0 +1,561 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import shutil +import struct +from functools import lru_cache + +import numpy as np +import torch +from fairseq.data.fasta_dataset import FastaDataset +from fairseq.file_io import PathManager + +from . import FairseqDataset + + +def __best_fitting_dtype(vocab_size=None): + if vocab_size is not None and vocab_size < 65500: + return np.uint16 + else: + return np.int32 + + +def get_available_dataset_impl(): + return ["raw", "lazy", "cached", "mmap", "fasta"] + + +def infer_dataset_impl(path): + if IndexedRawTextDataset.exists(path): + return "raw" + elif IndexedDataset.exists(path): + with open(index_file_path(path), "rb") as f: + magic = f.read(8) + if magic == IndexedDataset._HDR_MAGIC: + return "cached" + elif magic == MMapIndexedDataset.Index._HDR_MAGIC[:8]: + return "mmap" + else: + return None + elif FastaDataset.exists(path): + return "fasta" + else: + return None + + +def make_builder(out_file, impl, vocab_size=None): + if impl == "mmap": + return MMapIndexedDatasetBuilder( + out_file, dtype=__best_fitting_dtype(vocab_size) + ) + elif impl == "fasta": + raise NotImplementedError + else: + return IndexedDatasetBuilder(out_file) + + +def make_dataset(path, impl, fix_lua_indexing=False, dictionary=None): + if impl == "raw" and IndexedRawTextDataset.exists(path): + assert dictionary is not None + return IndexedRawTextDataset(path, dictionary) + elif impl == "lazy" and IndexedDataset.exists(path): + return IndexedDataset(path, fix_lua_indexing=fix_lua_indexing) + elif impl == "cached" and IndexedDataset.exists(path): + return IndexedCachedDataset(path, fix_lua_indexing=fix_lua_indexing) + elif impl == "mmap" and MMapIndexedDataset.exists(path): + return MMapIndexedDataset(path) + elif impl == "fasta" and FastaDataset.exists(path): + from fairseq.data.fasta_dataset import EncodedFastaDataset + + return EncodedFastaDataset(path, dictionary) + return None + + +def dataset_exists(path, impl): + if impl == "raw": + return IndexedRawTextDataset.exists(path) + elif impl == "mmap": + return MMapIndexedDataset.exists(path) + else: + return IndexedDataset.exists(path) + + +def read_longs(f, n): + a = np.empty(n, dtype=np.int64) + f.readinto(a) + return a + + +def write_longs(f, a): + f.write(np.array(a, dtype=np.int64)) + + +dtypes = { + 1: np.uint8, + 2: np.int8, + 3: np.int16, + 4: np.int32, + 5: np.int64, + 6: np.float, + 7: np.double, + 8: np.uint16, +} + + +def code(dtype): + for k in dtypes.keys(): + if dtypes[k] == dtype: + return k + raise ValueError(dtype) + + +def index_file_path(prefix_path): + return prefix_path + ".idx" + + +def data_file_path(prefix_path): + return prefix_path + ".bin" + + +class IndexedDataset(FairseqDataset): + """Loader for TorchNet IndexedDataset""" + + _HDR_MAGIC = b"TNTIDX\x00\x00" + + def __init__(self, path, fix_lua_indexing=False): + super().__init__() + self.path = path + self.fix_lua_indexing = fix_lua_indexing + self.data_file = None + self.read_index(path) + + def read_index(self, path): + with open(index_file_path(path), "rb") as f: + magic = f.read(8) + assert magic == self._HDR_MAGIC, ( + "Index file doesn't match expected format. " + "Make sure that --dataset-impl is configured properly." + ) + version = f.read(8) + assert struct.unpack("<Q", version) == (1,) + code, self.element_size = struct.unpack("<QQ", f.read(16)) + self.dtype = dtypes[code] + self._len, self.s = struct.unpack("<QQ", f.read(16)) + self.dim_offsets = read_longs(f, self._len + 1) + self.data_offsets = read_longs(f, self._len + 1) + self.sizes = read_longs(f, self.s) + + def read_data(self, path): + self.data_file = open(data_file_path(path), "rb", buffering=0) + + def check_index(self, i): + if i < 0 or i >= self._len: + raise IndexError("index out of range") + + def __del__(self): + if self.data_file: + self.data_file.close() + + @lru_cache(maxsize=8) + def __getitem__(self, i): + if not self.data_file: + self.read_data(self.path) + self.check_index(i) + tensor_size = self.sizes[self.dim_offsets[i] : self.dim_offsets[i + 1]] + a = np.empty(tensor_size, dtype=self.dtype) + self.data_file.seek(self.data_offsets[i] * self.element_size) + self.data_file.readinto(a) + item = torch.from_numpy(a).long() + if self.fix_lua_indexing: + item -= 1 # subtract 1 for 0-based indexing + return item + + def __len__(self): + return self._len + + def num_tokens(self, index): + return self.sizes[index] + + def size(self, index): + return self.sizes[index] + + @staticmethod + def exists(path): + return PathManager.exists(index_file_path(path)) and PathManager.exists( + data_file_path(path) + ) + + @property + def supports_prefetch(self): + return False # avoid prefetching to save memory + + +class IndexedCachedDataset(IndexedDataset): + def __init__(self, path, fix_lua_indexing=False): + super().__init__(path, fix_lua_indexing=fix_lua_indexing) + self.cache = None + self.cache_index = {} + + @property + def supports_prefetch(self): + return True + + def prefetch(self, indices): + if all(i in self.cache_index for i in indices): + return + if not self.data_file: + self.read_data(self.path) + indices = sorted(set(indices)) + total_size = 0 + for i in indices: + total_size += self.data_offsets[i + 1] - self.data_offsets[i] + self.cache = np.empty(total_size, dtype=self.dtype) + ptx = 0 + self.cache_index.clear() + for i in indices: + self.cache_index[i] = ptx + size = self.data_offsets[i + 1] - self.data_offsets[i] + a = self.cache[ptx : ptx + size] + self.data_file.seek(self.data_offsets[i] * self.element_size) + self.data_file.readinto(a) + ptx += size + if self.data_file: + # close and delete data file after prefetch so we can pickle + self.data_file.close() + self.data_file = None + + @lru_cache(maxsize=8) + def __getitem__(self, i): + self.check_index(i) + tensor_size = self.sizes[self.dim_offsets[i] : self.dim_offsets[i + 1]] + a = np.empty(tensor_size, dtype=self.dtype) + ptx = self.cache_index[i] + np.copyto(a, self.cache[ptx : ptx + a.size]) + item = torch.from_numpy(a).long() + if self.fix_lua_indexing: + item -= 1 # subtract 1 for 0-based indexing + return item + + +class IndexedRawTextDataset(FairseqDataset): + """Takes a text file as input and binarizes it in memory at instantiation. + Original lines are also kept in memory""" + + def __init__(self, path, dictionary, append_eos=True, reverse_order=False): + self.tokens_list = [] + self.lines = [] + self.sizes = [] + self.append_eos = append_eos + self.reverse_order = reverse_order + self.read_data(path, dictionary) + self.size = len(self.tokens_list) + + def read_data(self, path, dictionary): + with open(path, "r", encoding="utf-8") as f: + for line in f: + self.lines.append(line.strip("\n")) + tokens = dictionary.encode_line( + line, + add_if_not_exist=False, + append_eos=self.append_eos, + reverse_order=self.reverse_order, + ).long() + self.tokens_list.append(tokens) + self.sizes.append(len(tokens)) + self.sizes = np.array(self.sizes) + + def check_index(self, i): + if i < 0 or i >= self.size: + raise IndexError("index out of range") + + @lru_cache(maxsize=8) + def __getitem__(self, i): + self.check_index(i) + return self.tokens_list[i] + + def get_original_text(self, i): + self.check_index(i) + return self.lines[i] + + def __del__(self): + pass + + def __len__(self): + return self.size + + def num_tokens(self, index): + return self.sizes[index] + + def size(self, index): + return self.sizes[index] + + @staticmethod + def exists(path): + return PathManager.exists(path) + + +class IndexedDatasetBuilder(object): + element_sizes = { + np.uint8: 1, + np.int8: 1, + np.int16: 2, + np.int32: 4, + np.int64: 8, + np.float: 4, + np.double: 8, + } + + def __init__(self, out_file, dtype=np.int32): + self.out_file = open(out_file, "wb") + self.dtype = dtype + self.data_offsets = [0] + self.dim_offsets = [0] + self.sizes = [] + self.element_size = self.element_sizes[self.dtype] + + def add_item(self, tensor): + # +1 for Lua compatibility + bytes = self.out_file.write(np.array(tensor.numpy() + 1, dtype=self.dtype)) + self.data_offsets.append(self.data_offsets[-1] + bytes / self.element_size) + for s in tensor.size(): + self.sizes.append(s) + self.dim_offsets.append(self.dim_offsets[-1] + len(tensor.size())) + + def merge_file_(self, another_file): + index = IndexedDataset(another_file) + assert index.dtype == self.dtype + + begin = self.data_offsets[-1] + for offset in index.data_offsets[1:]: + self.data_offsets.append(begin + offset) + self.sizes.extend(index.sizes) + begin = self.dim_offsets[-1] + for dim_offset in index.dim_offsets[1:]: + self.dim_offsets.append(begin + dim_offset) + + with open(data_file_path(another_file), "rb") as f: + while True: + data = f.read(1024) + if data: + self.out_file.write(data) + else: + break + + def finalize(self, index_file): + self.out_file.close() + index = open(index_file, "wb") + index.write(b"TNTIDX\x00\x00") + index.write(struct.pack("<Q", 1)) + index.write(struct.pack("<QQ", code(self.dtype), self.element_size)) + index.write(struct.pack("<QQ", len(self.data_offsets) - 1, len(self.sizes))) + write_longs(index, self.dim_offsets) + write_longs(index, self.data_offsets) + write_longs(index, self.sizes) + index.close() + + +def _warmup_mmap_file(path): + with open(path, "rb") as stream: + while stream.read(100 * 1024 * 1024): + pass + + +class MMapIndexedDataset(torch.utils.data.Dataset): + class Index(object): + _HDR_MAGIC = b"MMIDIDX\x00\x00" + + @classmethod + def writer(cls, path, dtype): + class _Writer(object): + def __enter__(self): + self._file = open(path, "wb") + + self._file.write(cls._HDR_MAGIC) + self._file.write(struct.pack("<Q", 1)) + self._file.write(struct.pack("<B", code(dtype))) + + return self + + @staticmethod + def _get_pointers(sizes): + dtype_size = dtype().itemsize + address = 0 + pointers = [] + + for size in sizes: + pointers.append(address) + address += size * dtype_size + + return pointers + + def write(self, sizes): + pointers = self._get_pointers(sizes) + + self._file.write(struct.pack("<Q", len(sizes))) + + sizes = np.array(sizes, dtype=np.int32) + self._file.write(sizes.tobytes(order="C")) + del sizes + + pointers = np.array(pointers, dtype=np.int64) + self._file.write(pointers.tobytes(order="C")) + del pointers + + def __exit__(self, exc_type, exc_val, exc_tb): + self._file.close() + + return _Writer() + + def __init__(self, path): + with open(path, "rb") as stream: + magic_test = stream.read(9) + assert self._HDR_MAGIC == magic_test, ( + "Index file doesn't match expected format. " + "Make sure that --dataset-impl is configured properly." + ) + version = struct.unpack("<Q", stream.read(8)) + assert (1,) == version + + (dtype_code,) = struct.unpack("<B", stream.read(1)) + self._dtype = dtypes[dtype_code] + self._dtype_size = self._dtype().itemsize + + self._len = struct.unpack("<Q", stream.read(8))[0] + offset = stream.tell() + + _warmup_mmap_file(path) + + self._bin_buffer_mmap = np.memmap(path, mode="r", order="C") + self._bin_buffer = memoryview(self._bin_buffer_mmap) + self._sizes = np.frombuffer( + self._bin_buffer, dtype=np.int32, count=self._len, offset=offset + ) + self._pointers = np.frombuffer( + self._bin_buffer, + dtype=np.int64, + count=self._len, + offset=offset + self._sizes.nbytes, + ) + + def __del__(self): + self._bin_buffer_mmap._mmap.close() + del self._bin_buffer_mmap + + @property + def dtype(self): + return self._dtype + + @property + def sizes(self): + return self._sizes + + @lru_cache(maxsize=8) + def __getitem__(self, i): + return self._pointers[i], self._sizes[i] + + def __len__(self): + return self._len + + def __init__(self, path): + super().__init__() + + self._path = None + self._index = None + self._bin_buffer = None + + self._do_init(path) + + def __getstate__(self): + return self._path + + def __setstate__(self, state): + self._do_init(state) + + def _do_init(self, path): + self._path = path + self._index = self.Index(index_file_path(self._path)) + + _warmup_mmap_file(data_file_path(self._path)) + self._bin_buffer_mmap = np.memmap( + data_file_path(self._path), mode="r", order="C" + ) + self._bin_buffer = memoryview(self._bin_buffer_mmap) + + def __del__(self): + self._bin_buffer_mmap._mmap.close() + del self._bin_buffer_mmap + del self._index + + def __len__(self): + return len(self._index) + + @lru_cache(maxsize=8) + def __getitem__(self, i): + ptr, size = self._index[i] + np_array = np.frombuffer( + self._bin_buffer, dtype=self._index.dtype, count=size, offset=ptr + ) + if self._index.dtype != np.int64: + np_array = np_array.astype(np.int64) + + return torch.from_numpy(np_array) + + @property + def sizes(self): + return self._index.sizes + + @property + def supports_prefetch(self): + return False + + @staticmethod + def exists(path): + return PathManager.exists(index_file_path(path)) and PathManager.exists( + data_file_path(path) + ) + + +def get_indexed_dataset_to_local(path): + local_index_path = PathManager.get_local_path(index_file_path(path)) + local_data_path = PathManager.get_local_path(data_file_path(path)) + + assert local_index_path.endswith(".idx") and local_data_path.endswith(".bin"), ( + "PathManager.get_local_path does not return files with expected patterns: " + f"{local_index_path} and {local_data_path}" + ) + + local_path = local_data_path[:-4] # stripping surfix ".bin" + assert local_path == local_index_path[:-4] # stripping surfix ".idx" + return local_path + + +class MMapIndexedDatasetBuilder(object): + def __init__(self, out_file, dtype=np.int64): + self._data_file = open(out_file, "wb") + self._dtype = dtype + self._sizes = [] + + def add_item(self, tensor): + np_array = np.array(tensor.numpy(), dtype=self._dtype) + self._data_file.write(np_array.tobytes(order="C")) + self._sizes.append(np_array.size) + + def merge_file_(self, another_file): + # Concatenate index + index = MMapIndexedDataset.Index(index_file_path(another_file)) + assert index.dtype == self._dtype + + for size in index.sizes: + self._sizes.append(size) + + # Concatenate data + with open(data_file_path(another_file), "rb") as f: + shutil.copyfileobj(f, self._data_file) + + def finalize(self, index_file): + self._data_file.close() + + with MMapIndexedDataset.Index.writer(index_file, self._dtype) as index: + index.write(self._sizes) diff --git a/fairseq-tools/fairseq/fairseq/data/iterators.py b/fairseq-tools/fairseq/fairseq/data/iterators.py new file mode 100644 index 00000000..ef41fed7 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/iterators.py @@ -0,0 +1,594 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import itertools +import logging +import math +import operator +import os +import queue +import time +from threading import Thread + +import numpy as np +import torch +from fairseq.data import data_utils + + +logger = logging.getLogger(__name__) + +# Object used by _background_consumer to signal the source is exhausted +# to the main thread. +_sentinel = object() + + +class CountingIterator(object): + """Wrapper around an iterable that maintains the iteration count. + + Args: + iterable (iterable): iterable to wrap + start (int): starting iteration count. Note that this doesn't + actually advance the iterator. + total (int): override the iterator length returned by + ``__len__``. This can be used to truncate *iterator*. + + Attributes: + n (int): number of elements consumed from this iterator + """ + + def __init__(self, iterable, start=None, total=None): + self.iterable = iterable + self.itr = iter(self) + + if start is None: + self.n = getattr(iterable, "n", 0) + else: + self.n = start + + if total is None: + self.total = self.n + len(iterable) + else: + self.total = total + + def __len__(self): + return self.total + + def __iter__(self): + for x in self.iterable: + if self.n >= self.total: + raise RuntimeError( + "Mismatch between actual and expected iterable length. " + "This may be caused by resuming training from a checkpoint using " + "a different number of GPUs, in which case you can try the " + "--reset-dataloader option. Alternatively you may have a train or " + "validation set that is smaller than the number of GPUs. If none " + "of these apply, please report this to the fairseq developers." + ) + self.n += 1 + yield x + + def __next__(self): + return next(self.itr) + + def has_next(self): + """Whether the iterator has been exhausted.""" + return self.n < len(self) + + def skip(self, num_to_skip): + """Fast-forward the iterator by skipping *num_to_skip* elements.""" + next(itertools.islice(self.itr, num_to_skip, num_to_skip), None) + return self + + def take(self, n): + """ + Truncates the iterator to n elements at most. + """ + self.total = min(self.total, n) + + # Propagate this change to the underlying iterator + # Only take after what we have already consumed (i.e. after restarting + # from checkpoint mid epoch, we have to subtract self.n which is the + # starting point) + # + # This to maintain the invariant self.total = self.n + len(iterable), + # before calling __next__ or __iter__ + propagated_take = max(n - self.n, 0) + if hasattr(self.iterable, "take"): + self.iterable.take(propagated_take) + else: + self.iterable = itertools.islice(self.iterable, propagated_take) + + +class EpochBatchIterating(object): + def __len__(self) -> int: + raise NotImplementedError + + @property + def next_epoch_idx(self): + raise NotImplementedError + + def next_epoch_itr(self, shuffle=True, fix_batches_to_gpus=False): + """Return a new iterator over the dataset. + + Args: + shuffle (bool, optional): shuffle batches before returning the + iterator (default: True). + fix_batches_to_gpus: ensure that batches are always + allocated to the same shards across epochs. Requires + that :attr:`dataset` supports prefetching (default: False). + """ + raise NotImplementedError + + def end_of_epoch(self) -> bool: + """Returns whether the most recent epoch iterator has been exhausted""" + raise NotImplementedError + + @property + def iterations_in_epoch(self) -> int: + """The number of consumed batches in the current epoch.""" + raise NotImplementedError + + def state_dict(self): + """Returns a dictionary containing a whole state of the iterator.""" + raise NotImplementedError + + def load_state_dict(self, state_dict): + """Copies the state of the iterator from the given *state_dict*.""" + raise NotImplementedError + + +class StreamingEpochBatchIterator(EpochBatchIterating): + def __init__( + self, + dataset, + epoch=1, + num_shards=1, + shard_id=0, + ): + assert isinstance(dataset, torch.utils.data.IterableDataset) + self.dataset = dataset + self.epoch = max(epoch, 1) # we use 1-based indexing for epochs + self._current_epoch_iterator = None + self.num_shards = num_shards + self.shard_id = shard_id + + @property + def next_epoch_idx(self): + """Return the epoch index after *next_epoch_itr* is called.""" + if self._current_epoch_iterator is not None and self.end_of_epoch(): + return self.epoch + 1 + else: + return self.epoch + + def next_epoch_itr(self, shuffle=True, fix_batches_to_gpus=False): + self.epoch = self.next_epoch_idx + if hasattr(self.dataset, "set_epoch"): + self.dataset.set_epoch(self.epoch) + self._current_epoch_iterator = CountingIterator( + iterable=ShardedIterator( + iterable=self.dataset, + num_shards=self.num_shards, + shard_id=self.shard_id, + ), + ) + return self._current_epoch_iterator + + def end_of_epoch(self) -> bool: + return not self._current_epoch_iterator.has_next() + + @property + def iterations_in_epoch(self) -> int: + if self._current_epoch_iterator is not None: + return self._current_epoch_iterator.n + return 0 + + def state_dict(self): + return { + "epoch": self.epoch, + } + + def load_state_dict(self, state_dict): + self.epoch = state_dict["epoch"] + + +class EpochBatchIterator(EpochBatchIterating): + """A multi-epoch iterator over a :class:`torch.utils.data.Dataset`. + + Compared to :class:`torch.utils.data.DataLoader`, this iterator: + + - can be reused across multiple epochs with the :func:`next_epoch_itr` + method (optionally shuffled between epochs) + - can be serialized/deserialized with the :func:`state_dict` and + :func:`load_state_dict` methods + - supports sharding with the *num_shards* and *shard_id* arguments + + Args: + dataset (~torch.utils.data.Dataset): dataset from which to load the data + collate_fn (callable): merges a list of samples to form a mini-batch + batch_sampler (~torch.utils.data.Sampler or a callable): an iterator over batches of + indices, or a callable to create such an iterator (~torch.utils.data.Sampler). + A callable batch_sampler will be called for each epoch to enable per epoch dynamic + batch iterators defined by this callable batch_sampler. + seed (int, optional): seed for random number generator for + reproducibility (default: 1). + num_shards (int, optional): shard the data iterator into N + shards (default: 1). + shard_id (int, optional): which shard of the data iterator to + return (default: 0). + num_workers (int, optional): how many subprocesses to use for data + loading. 0 means the data will be loaded in the main process + (default: 0). + epoch (int, optional): the epoch to start the iterator from + (default: 1). + buffer_size (int, optional): the number of batches to keep ready in the + queue. Helps speeding up dataloading. When buffer_size is zero, the + default torch.utils.data.DataLoader preloading is used. + timeout (int, optional): if positive, the timeout value for collecting a batch + from workers. Should always be non-negative (default: ``0``). + disable_shuffling (bool, optional): force disable shuffling + (default: ``False``). + """ + + def __init__( + self, + dataset, + collate_fn, + batch_sampler, + seed=1, + num_shards=1, + shard_id=0, + num_workers=0, + epoch=1, + buffer_size=0, + timeout=0, + disable_shuffling=False, + ): + assert isinstance(dataset, torch.utils.data.Dataset) + self.dataset = dataset + self.collate_fn = collate_fn + self.batch_sampler = batch_sampler + self._frozen_batches = ( + tuple(batch_sampler) if not callable(batch_sampler) else None + ) + self.seed = seed + self.num_shards = num_shards + self.shard_id = shard_id + self.num_workers = num_workers + # This upper limit here is to prevent people from abusing this feature + # in a shared computing environment. + self.buffer_size = min(buffer_size, 20) + self.timeout = timeout + self.disable_shuffling = disable_shuffling + + self.epoch = max(epoch, 1) # we use 1-based indexing for epochs + self.shuffle = not disable_shuffling + self._cur_epoch_itr = None + self._next_epoch_itr = None + self._supports_prefetch = getattr(dataset, "supports_prefetch", False) + + @property + def frozen_batches(self): + if self._frozen_batches is None: + self._frozen_batches = tuple(self.batch_sampler(self.dataset, self.epoch)) + return self._frozen_batches + + @property + def first_batch(self): + if len(self.frozen_batches) == 0: + raise Exception( + "The dataset is empty. This could indicate " + "that all elements in the dataset have been skipped. " + "Try increasing the max number of allowed tokens or using " + "a larger dataset." + ) + + if getattr(self.dataset, "supports_fetch_outside_dataloader", True): + return self.collate_fn([self.dataset[i] for i in self.frozen_batches[0]]) + else: + return "DUMMY" + + def __len__(self): + return int(math.ceil(len(self.frozen_batches) / float(self.num_shards))) + + @property + def n(self): + return self.iterations_in_epoch + + @property + def next_epoch_idx(self): + """Return the epoch index after *next_epoch_itr* is called.""" + if self._next_epoch_itr is not None: + return self.epoch + elif self._cur_epoch_itr is not None and self.end_of_epoch(): + return self.epoch + 1 + else: + return self.epoch + + def next_epoch_itr(self, shuffle=True, fix_batches_to_gpus=False): + """Return a new iterator over the dataset. + + Args: + shuffle (bool, optional): shuffle batches before returning the + iterator (default: True). + fix_batches_to_gpus: ensure that batches are always + allocated to the same shards across epochs. Requires + that :attr:`dataset` supports prefetching (default: False). + """ + if self.disable_shuffling: + shuffle = False + self.epoch = self.next_epoch_idx + if hasattr(self.dataset, "set_epoch"): + self.dataset.set_epoch(self.epoch) + if self._next_epoch_itr is not None: + self._cur_epoch_itr = self._next_epoch_itr + self._next_epoch_itr = None + else: + if callable(self.batch_sampler): + # reset _frozen_batches to refresh the next epoch + self._frozen_batches = None + self._cur_epoch_itr = self._get_iterator_for_epoch( + self.epoch, + shuffle, + fix_batches_to_gpus=fix_batches_to_gpus, + ) + self.shuffle = shuffle + return self._cur_epoch_itr + + def end_of_epoch(self) -> bool: + """Returns whether the most recent epoch iterator has been exhausted""" + return not self._cur_epoch_itr.has_next() + + @property + def iterations_in_epoch(self): + """The number of consumed batches in the current epoch.""" + if self._cur_epoch_itr is not None: + return self._cur_epoch_itr.n + elif self._next_epoch_itr is not None: + return self._next_epoch_itr.n + return 0 + + def state_dict(self): + """Returns a dictionary containing a whole state of the iterator.""" + if self.end_of_epoch(): + epoch = self.epoch + 1 + iter_in_epoch = 0 + else: + epoch = self.epoch + iter_in_epoch = self.iterations_in_epoch + return { + "version": 2, + "epoch": epoch, + "iterations_in_epoch": iter_in_epoch, + "shuffle": self.shuffle, + } + + def load_state_dict(self, state_dict): + """Copies the state of the iterator from the given *state_dict*.""" + self.epoch = state_dict["epoch"] + itr_pos = state_dict.get("iterations_in_epoch", 0) + version = state_dict.get("version", 1) + if itr_pos > 0: + # fast-forward epoch iterator + self._next_epoch_itr = self._get_iterator_for_epoch( + self.epoch, + shuffle=state_dict.get("shuffle", True), + offset=itr_pos, + ) + if self._next_epoch_itr is None: + if version == 1: + # legacy behavior: we finished the epoch, increment epoch counter + self.epoch += 1 + else: + raise RuntimeError( + "Cannot resume training due to dataloader mismatch, please " + "report this to the fairseq developers. You can relaunch " + "training with `--reset-dataloader` and it should work." + ) + else: + self._next_epoch_itr = None + + def _get_iterator_for_epoch( + self, epoch, shuffle, fix_batches_to_gpus=False, offset=0 + ): + def shuffle_batches(batches, seed): + with data_utils.numpy_seed(seed): + np.random.shuffle(batches) + return batches + + if self._supports_prefetch: + batches = self.frozen_batches + + if shuffle and not fix_batches_to_gpus: + batches = shuffle_batches(list(batches), self.seed + epoch) + + batches = list( + ShardedIterator(batches, self.num_shards, self.shard_id, fill_value=[]) + ) + self.dataset.prefetch([i for s in batches for i in s]) + + if shuffle and fix_batches_to_gpus: + batches = shuffle_batches(batches, self.seed + epoch + self.shard_id) + else: + if shuffle: + batches = shuffle_batches(list(self.frozen_batches), self.seed + epoch) + else: + batches = self.frozen_batches + batches = list( + ShardedIterator(batches, self.num_shards, self.shard_id, fill_value=[]) + ) + + if offset > 0 and offset >= len(batches): + return None + + if self.num_workers > 0: + os.environ["PYTHONWARNINGS"] = "ignore:semaphore_tracker:UserWarning" + + # Create data loader + itr = torch.utils.data.DataLoader( + self.dataset, + collate_fn=self.collate_fn, + batch_sampler=batches[offset:], + num_workers=self.num_workers, + timeout=self.timeout, + ) + + # Wrap with a BufferedIterator if needed + if self.buffer_size > 0: + itr = BufferedIterator(self.buffer_size, itr) + + # Wrap with CoutingIterator + itr = CountingIterator(itr, start=offset) + return itr + + +class GroupedIterator(CountingIterator): + """Wrapper around an iterable that returns groups (chunks) of items. + + Args: + iterable (iterable): iterable to wrap + chunk_size (int): size of each chunk + + Attributes: + n (int): number of elements consumed from this iterator + """ + + def __init__(self, iterable, chunk_size): + itr = _chunk_iterator(iterable, chunk_size) + super().__init__( + itr, + start=int(math.ceil(getattr(iterable, "n", 0) / float(chunk_size))), + total=int(math.ceil(len(iterable) / float(chunk_size))), + ) + self.chunk_size = chunk_size + + +def _chunk_iterator(itr, chunk_size): + chunk = [] + for x in itr: + chunk.append(x) + if len(chunk) == chunk_size: + yield chunk + chunk = [] + if len(chunk) > 0: + yield chunk + + +class ShardedIterator(CountingIterator): + """A sharded wrapper around an iterable, padded to length. + + Args: + iterable (iterable): iterable to wrap + num_shards (int): number of shards to split the iterable into + shard_id (int): which shard to iterator over + fill_value (Any, optional): padding value when the iterable doesn't + evenly divide *num_shards* (default: None). + + Attributes: + n (int): number of elements consumed from this iterator + """ + + def __init__(self, iterable, num_shards, shard_id, fill_value=None): + if shard_id < 0 or shard_id >= num_shards: + raise ValueError("shard_id must be between 0 and num_shards") + sharded_len = int(math.ceil(len(iterable) / float(num_shards))) + itr = map( + operator.itemgetter(1), + itertools.zip_longest( + range(sharded_len), + itertools.islice(iterable, shard_id, len(iterable), num_shards), + fillvalue=fill_value, + ), + ) + super().__init__( + itr, + start=int(math.ceil(getattr(iterable, "n", 0) / float(num_shards))), + total=sharded_len, + ) + + +class BackgroundConsumer(Thread): + def __init__(self, queue, source, max_len): + Thread.__init__(self) + + self._queue = queue + self._source = source + self._max_len = max_len + self.count = 0 + + def run(self): + try: + for item in self._source: + self._queue.put(item) + + # Stop if we reached the maximum length + self.count += 1 + if self._max_len is not None and self.count >= self._max_len: + break + + # Signal the consumer we are done. + self._queue.put(_sentinel) + except Exception as e: + self._queue.put(e) + + +class BufferedIterator(object): + def __init__(self, size, iterable): + self._queue = queue.Queue(size) + self._iterable = iterable + self._consumer = None + + self.start_time = time.time() + self.warning_time = None + + self.total = len(iterable) + + def _create_consumer(self): + self._consumer = BackgroundConsumer( + self._queue, + self._iterable, + self.total, + ) + self._consumer.daemon = True + self._consumer.start() + + def __iter__(self): + return self + + def __len__(self): + return self.total + + def take(self, n): + self.total = min(self.total, n) + + # Propagate this change to the underlying iterator + if hasattr(self._iterable, "take"): + self._iterable.take(n) + + def __next__(self): + # Create consumer if not created yet + if self._consumer is None: + self._create_consumer() + + # Notify the user if there is a data loading bottleneck + if self._queue.qsize() < min(2, max(1, self._queue.maxsize // 2)): + if time.time() - self.start_time > 5 * 60: + if ( + self.warning_time is None + or time.time() - self.warning_time > 15 * 60 + ): + logger.debug( + "Data loading buffer is empty or nearly empty. This may " + "indicate a data loading bottleneck, and increasing the " + "number of workers (--num-workers) may help." + ) + self.warning_time = time.time() + + # Get next example + item = self._queue.get(True) + if isinstance(item, Exception): + raise item + if item is _sentinel: + raise StopIteration() + return item diff --git a/fairseq-tools/fairseq/fairseq/data/language_pair_dataset.py b/fairseq-tools/fairseq/fairseq/data/language_pair_dataset.py new file mode 100644 index 00000000..62e7109b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/language_pair_dataset.py @@ -0,0 +1,469 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import numpy as np +import torch +from fairseq.data import FairseqDataset, data_utils + + +logger = logging.getLogger(__name__) + + +def collate( + samples, + pad_idx, + eos_idx, + left_pad_source=True, + left_pad_target=False, + input_feeding=True, + pad_to_length=None, + pad_to_multiple=1, +): + if len(samples) == 0: + return {} + + def merge(key, left_pad, move_eos_to_beginning=False, pad_to_length=None): + return data_utils.collate_tokens( + [s[key] for s in samples], + pad_idx, + eos_idx, + left_pad, + move_eos_to_beginning, + pad_to_length=pad_to_length, + pad_to_multiple=pad_to_multiple, + ) + + def check_alignment(alignment, src_len, tgt_len): + if alignment is None or len(alignment) == 0: + return False + if ( + alignment[:, 0].max().item() >= src_len - 1 + or alignment[:, 1].max().item() >= tgt_len - 1 + ): + logger.warning("alignment size mismatch found, skipping alignment!") + return False + return True + + def compute_alignment_weights(alignments): + """ + Given a tensor of shape [:, 2] containing the source-target indices + corresponding to the alignments, a weight vector containing the + inverse frequency of each target index is computed. + For e.g. if alignments = [[5, 7], [2, 3], [1, 3], [4, 2]], then + a tensor containing [1., 0.5, 0.5, 1] should be returned (since target + index 3 is repeated twice) + """ + align_tgt = alignments[:, 1] + _, align_tgt_i, align_tgt_c = torch.unique( + align_tgt, return_inverse=True, return_counts=True + ) + align_weights = align_tgt_c[align_tgt_i[np.arange(len(align_tgt))]] + return 1.0 / align_weights.float() + + id = torch.LongTensor([s["id"] for s in samples]) + src_tokens = merge( + "source", + left_pad=left_pad_source, + pad_to_length=pad_to_length["source"] if pad_to_length is not None else None, + ) + # sort by descending source length + src_lengths = torch.LongTensor( + [s["source"].ne(pad_idx).long().sum() for s in samples] + ) + src_lengths, sort_order = src_lengths.sort(descending=True) + id = id.index_select(0, sort_order) + src_tokens = src_tokens.index_select(0, sort_order) + + prev_output_tokens = None + target = None + if samples[0].get("target", None) is not None: + target = merge( + "target", + left_pad=left_pad_target, + pad_to_length=pad_to_length["target"] + if pad_to_length is not None + else None, + ) + target = target.index_select(0, sort_order) + tgt_lengths = torch.LongTensor( + [s["target"].ne(pad_idx).long().sum() for s in samples] + ).index_select(0, sort_order) + ntokens = tgt_lengths.sum().item() + + if samples[0].get("prev_output_tokens", None) is not None: + prev_output_tokens = merge("prev_output_tokens", left_pad=left_pad_target) + elif input_feeding: + # we create a shifted version of targets for feeding the + # previous output token(s) into the next decoder step + prev_output_tokens = merge( + "target", + left_pad=left_pad_target, + move_eos_to_beginning=True, + pad_to_length=pad_to_length["target"] + if pad_to_length is not None + else None, + ) + else: + ntokens = src_lengths.sum().item() + + batch = { + "id": id, + "nsentences": len(samples), + "ntokens": ntokens, + "net_input": { + "src_tokens": src_tokens, + "src_lengths": src_lengths, + }, + "target": target, + } + if prev_output_tokens is not None: + batch["net_input"]["prev_output_tokens"] = prev_output_tokens.index_select( + 0, sort_order + ) + + if samples[0].get("alignment", None) is not None: + bsz, tgt_sz = batch["target"].shape + src_sz = batch["net_input"]["src_tokens"].shape[1] + + offsets = torch.zeros((len(sort_order), 2), dtype=torch.long) + offsets[:, 1] += torch.arange(len(sort_order), dtype=torch.long) * tgt_sz + if left_pad_source: + offsets[:, 0] += src_sz - src_lengths + if left_pad_target: + offsets[:, 1] += tgt_sz - tgt_lengths + + alignments = [ + alignment + offset + for align_idx, offset, src_len, tgt_len in zip( + sort_order, offsets, src_lengths, tgt_lengths + ) + for alignment in [samples[align_idx]["alignment"].view(-1, 2)] + if check_alignment(alignment, src_len, tgt_len) + ] + + if len(alignments) > 0: + alignments = torch.cat(alignments, dim=0) + align_weights = compute_alignment_weights(alignments) + + batch["alignments"] = alignments + batch["align_weights"] = align_weights + + if samples[0].get("constraints", None) is not None: + # Collate the packed constraints across the samples, padding to + # the length of the longest sample. + lens = [sample.get("constraints").size(0) for sample in samples] + max_len = max(lens) + constraints = torch.zeros((len(samples), max(lens))).long() + for i, sample in enumerate(samples): + constraints[i, 0 : lens[i]] = samples[i].get("constraints") + batch["constraints"] = constraints + + return batch + + +class LanguagePairDataset(FairseqDataset): + """ + A pair of torch.utils.data.Datasets. + + Args: + src (torch.utils.data.Dataset): source dataset to wrap + src_sizes (List[int]): source sentence lengths + src_dict (~fairseq.data.Dictionary): source vocabulary + tgt (torch.utils.data.Dataset, optional): target dataset to wrap + tgt_sizes (List[int], optional): target sentence lengths + tgt_dict (~fairseq.data.Dictionary, optional): target vocabulary + left_pad_source (bool, optional): pad source tensors on the left side + (default: True). + left_pad_target (bool, optional): pad target tensors on the left side + (default: False). + shuffle (bool, optional): shuffle dataset elements before batching + (default: True). + input_feeding (bool, optional): create a shifted version of the targets + to be passed into the model for teacher forcing (default: True). + remove_eos_from_source (bool, optional): if set, removes eos from end + of source if it's present (default: False). + append_eos_to_target (bool, optional): if set, appends eos to end of + target if it's absent (default: False). + align_dataset (torch.utils.data.Dataset, optional): dataset + containing alignments. + constraints (Tensor, optional): 2d tensor with a concatenated, zero- + delimited list of constraints for each sentence. + append_bos (bool, optional): if set, appends bos to the beginning of + source/target sentence. + num_buckets (int, optional): if set to a value greater than 0, then + batches will be bucketed into the given number of batch shapes. + src_lang_id (int, optional): source language ID, if set, the collated batch + will contain a field 'src_lang_id' in 'net_input' which indicates the + source language of the samples. + tgt_lang_id (int, optional): target language ID, if set, the collated batch + will contain a field 'tgt_lang_id' which indicates the target language + of the samples. + """ + + def __init__( + self, + src, + src_sizes, + src_dict, + tgt=None, + tgt_sizes=None, + tgt_dict=None, + left_pad_source=True, + left_pad_target=False, + shuffle=True, + input_feeding=True, + remove_eos_from_source=False, + append_eos_to_target=False, + align_dataset=None, + constraints=None, + append_bos=False, + eos=None, + num_buckets=0, + src_lang_id=None, + tgt_lang_id=None, + pad_to_multiple=1, + ): + if tgt_dict is not None: + assert src_dict.pad() == tgt_dict.pad() + assert src_dict.eos() == tgt_dict.eos() + assert src_dict.unk() == tgt_dict.unk() + if tgt is not None: + assert len(src) == len( + tgt + ), "Source and target must contain the same number of examples" + self.src = src + self.tgt = tgt + self.src_sizes = np.array(src_sizes) + self.tgt_sizes = np.array(tgt_sizes) if tgt_sizes is not None else None + self.sizes = ( + np.vstack((self.src_sizes, self.tgt_sizes)).T + if self.tgt_sizes is not None + else self.src_sizes + ) + self.src_dict = src_dict + self.tgt_dict = tgt_dict + self.left_pad_source = left_pad_source + self.left_pad_target = left_pad_target + self.shuffle = shuffle + self.input_feeding = input_feeding + self.remove_eos_from_source = remove_eos_from_source + self.append_eos_to_target = append_eos_to_target + self.align_dataset = align_dataset + if self.align_dataset is not None: + assert ( + self.tgt_sizes is not None + ), "Both source and target needed when alignments are provided" + self.constraints = constraints + self.append_bos = append_bos + self.eos = eos if eos is not None else src_dict.eos() + self.src_lang_id = src_lang_id + self.tgt_lang_id = tgt_lang_id + if num_buckets > 0: + from fairseq.data import BucketPadLengthDataset + + self.src = BucketPadLengthDataset( + self.src, + sizes=self.src_sizes, + num_buckets=num_buckets, + pad_idx=self.src_dict.pad(), + left_pad=self.left_pad_source, + ) + self.src_sizes = self.src.sizes + logger.info("bucketing source lengths: {}".format(list(self.src.buckets))) + if self.tgt is not None: + self.tgt = BucketPadLengthDataset( + self.tgt, + sizes=self.tgt_sizes, + num_buckets=num_buckets, + pad_idx=self.tgt_dict.pad(), + left_pad=self.left_pad_target, + ) + self.tgt_sizes = self.tgt.sizes + logger.info( + "bucketing target lengths: {}".format(list(self.tgt.buckets)) + ) + + # determine bucket sizes using self.num_tokens, which will return + # the padded lengths (thanks to BucketPadLengthDataset) + num_tokens = np.vectorize(self.num_tokens, otypes=[np.long]) + self.bucketed_num_tokens = num_tokens(np.arange(len(self.src))) + self.buckets = [ + (None, num_tokens) for num_tokens in np.unique(self.bucketed_num_tokens) + ] + else: + self.buckets = None + self.pad_to_multiple = pad_to_multiple + + def get_batch_shapes(self): + return self.buckets + + def __getitem__(self, index): + tgt_item = self.tgt[index] if self.tgt is not None else None + src_item = self.src[index] + # Append EOS to end of tgt sentence if it does not have an EOS and remove + # EOS from end of src sentence if it exists. This is useful when we use + # use existing datasets for opposite directions i.e., when we want to + # use tgt_dataset as src_dataset and vice versa + if self.append_eos_to_target: + eos = self.tgt_dict.eos() if self.tgt_dict else self.src_dict.eos() + if self.tgt and self.tgt[index][-1] != eos: + tgt_item = torch.cat([self.tgt[index], torch.LongTensor([eos])]) + + if self.append_bos: + bos = self.tgt_dict.bos() if self.tgt_dict else self.src_dict.bos() + if self.tgt and self.tgt[index][0] != bos: + tgt_item = torch.cat([torch.LongTensor([bos]), self.tgt[index]]) + + bos = self.src_dict.bos() + if self.src[index][0] != bos: + src_item = torch.cat([torch.LongTensor([bos]), self.src[index]]) + + if self.remove_eos_from_source: + eos = self.src_dict.eos() + if self.src[index][-1] == eos: + src_item = self.src[index][:-1] + + example = { + "id": index, + "source": src_item, + "target": tgt_item, + } + if self.align_dataset is not None: + example["alignment"] = self.align_dataset[index] + if self.constraints is not None: + example["constraints"] = self.constraints[index] + return example + + def __len__(self): + return len(self.src) + + def collater(self, samples, pad_to_length=None): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[dict]): samples to collate + pad_to_length (dict, optional): a dictionary of + {'source': source_pad_to_length, 'target': target_pad_to_length} + to indicate the max length to pad to in source and target respectively. + + Returns: + dict: a mini-batch with the following keys: + + - `id` (LongTensor): example IDs in the original input order + - `ntokens` (int): total number of tokens in the batch + - `net_input` (dict): the input to the Model, containing keys: + + - `src_tokens` (LongTensor): a padded 2D Tensor of tokens in + the source sentence of shape `(bsz, src_len)`. Padding will + appear on the left if *left_pad_source* is ``True``. + - `src_lengths` (LongTensor): 1D Tensor of the unpadded + lengths of each source sentence of shape `(bsz)` + - `prev_output_tokens` (LongTensor): a padded 2D Tensor of + tokens in the target sentence, shifted right by one + position for teacher forcing, of shape `(bsz, tgt_len)`. + This key will not be present if *input_feeding* is + ``False``. Padding will appear on the left if + *left_pad_target* is ``True``. + - `src_lang_id` (LongTensor): a long Tensor which contains source + language IDs of each sample in the batch + + - `target` (LongTensor): a padded 2D Tensor of tokens in the + target sentence of shape `(bsz, tgt_len)`. Padding will appear + on the left if *left_pad_target* is ``True``. + - `tgt_lang_id` (LongTensor): a long Tensor which contains target language + IDs of each sample in the batch + """ + res = collate( + samples, + pad_idx=self.src_dict.pad(), + eos_idx=self.eos, + left_pad_source=self.left_pad_source, + left_pad_target=self.left_pad_target, + input_feeding=self.input_feeding, + pad_to_length=pad_to_length, + pad_to_multiple=self.pad_to_multiple, + ) + if self.src_lang_id is not None or self.tgt_lang_id is not None: + src_tokens = res["net_input"]["src_tokens"] + bsz = src_tokens.size(0) + if self.src_lang_id is not None: + res["net_input"]["src_lang_id"] = ( + torch.LongTensor([[self.src_lang_id]]).expand(bsz, 1).to(src_tokens) + ) + if self.tgt_lang_id is not None: + res["tgt_lang_id"] = ( + torch.LongTensor([[self.tgt_lang_id]]).expand(bsz, 1).to(src_tokens) + ) + return res + + def num_tokens(self, index): + """Return the number of tokens in a sample. This value is used to + enforce ``--max-tokens`` during batching.""" + return max( + self.src_sizes[index], + self.tgt_sizes[index] if self.tgt_sizes is not None else 0, + ) + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + return ( + self.src_sizes[index], + self.tgt_sizes[index] if self.tgt_sizes is not None else 0, + ) + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + if self.shuffle: + indices = np.random.permutation(len(self)).astype(np.int64) + else: + indices = np.arange(len(self), dtype=np.int64) + if self.buckets is None: + # sort by target length, then source length + if self.tgt_sizes is not None: + indices = indices[np.argsort(self.tgt_sizes[indices], kind="mergesort")] + return indices[np.argsort(self.src_sizes[indices], kind="mergesort")] + else: + # sort by bucketed_num_tokens, which is: + # max(padded_src_len, padded_tgt_len) + return indices[ + np.argsort(self.bucketed_num_tokens[indices], kind="mergesort") + ] + + @property + def supports_prefetch(self): + return getattr(self.src, "supports_prefetch", False) and ( + getattr(self.tgt, "supports_prefetch", False) or self.tgt is None + ) + + def prefetch(self, indices): + self.src.prefetch(indices) + if self.tgt is not None: + self.tgt.prefetch(indices) + if self.align_dataset is not None: + self.align_dataset.prefetch(indices) + + def filter_indices_by_size(self, indices, max_sizes): + """Filter a list of sample indices. Remove those that are longer + than specified in max_sizes. + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + return data_utils.filter_paired_dataset_indices_by_size( + self.src_sizes, + self.tgt_sizes, + indices, + max_sizes, + ) diff --git a/fairseq-tools/fairseq/fairseq/data/legacy/__init__.py b/fairseq-tools/fairseq/fairseq/data/legacy/__init__.py new file mode 100644 index 00000000..9bd5c72b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/legacy/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .block_pair_dataset import BlockPairDataset +from .masked_lm_dataset import MaskedLMDataset +from .masked_lm_dictionary import BertDictionary, MaskedLMDictionary + + +__all__ = [ + "BertDictionary", + "BlockPairDataset", + "MaskedLMDataset", + "MaskedLMDictionary", +] diff --git a/fairseq-tools/fairseq/fairseq/data/legacy/block_pair_dataset.py b/fairseq-tools/fairseq/fairseq/data/legacy/block_pair_dataset.py new file mode 100644 index 00000000..ba069b46 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/legacy/block_pair_dataset.py @@ -0,0 +1,311 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import numpy as np +import torch +from fairseq.data import FairseqDataset + + +class BlockPairDataset(FairseqDataset): + """Break a Dataset of tokens into sentence pair blocks for next sentence + prediction as well as masked language model. + + High-level logics are: + 1. break input tensor to tensor blocks + 2. pair the blocks with 50% next sentence and 50% random sentence + 3. return paired blocks as well as related segment labels + + Args: + dataset (~torch.utils.data.Dataset): dataset to break into blocks + sizes: array of sentence lengths + dictionary: dictionary for the task + block_size: maximum block size + break_mode: mode for breaking copurs into block pairs. currently we support + 2 modes + doc: respect document boundaries and each part of the pair should belong to on document + none: don't respect any boundary and cut tokens evenly + short_seq_prob: probability for generating shorter block pairs + doc_break_size: Size for empty line separating documents. Typically 1 if + the sentences have eos, 0 otherwise. + """ + + def __init__( + self, + dataset, + dictionary, + sizes, + block_size, + break_mode="doc", + short_seq_prob=0.1, + doc_break_size=1, + ): + super().__init__() + self.dataset = dataset + self.pad = dictionary.pad() + self.eos = dictionary.eos() + self.cls = dictionary.cls() + self.mask = dictionary.mask() + self.sep = dictionary.sep() + self.break_mode = break_mode + self.dictionary = dictionary + self.short_seq_prob = short_seq_prob + self.block_indices = [] + + assert len(dataset) == len(sizes) + + if break_mode == "doc": + cur_doc = [] + for sent_id, sz in enumerate(sizes): + assert doc_break_size == 0 or sz != 0, ( + "when doc_break_size is non-zero, we expect documents to be" + "separated by a blank line with a single eos." + ) + # empty line as document separator + if sz == doc_break_size: + if len(cur_doc) == 0: + continue + self.block_indices.append(cur_doc) + cur_doc = [] + else: + cur_doc.append(sent_id) + max_num_tokens = block_size - 3 # Account for [CLS], [SEP], [SEP] + self.sent_pairs = [] + self.sizes = [] + for doc_id, doc in enumerate(self.block_indices): + self._generate_sentence_pair(doc, doc_id, max_num_tokens, sizes) + elif break_mode is None or break_mode == "none": + # each block should have half of the block size since we are constructing block pair + sent_length = (block_size - 3) // 2 + total_len = sum(dataset.sizes) + length = math.ceil(total_len / sent_length) + + def block_at(i): + start = i * sent_length + end = min(start + sent_length, total_len) + return (start, end) + + sent_indices = np.array([block_at(i) for i in range(length)]) + sent_sizes = np.array([e - s for s, e in sent_indices]) + dataset_index = self._sent_to_dataset_index(sent_sizes) + + # pair sentences + self._pair_sentences(dataset_index) + else: + raise ValueError("Invalid break_mode: " + break_mode) + + def _pair_sentences(self, dataset_index): + """ + Give a list of evenly cut blocks/sentences, pair these sentences with 50% + consecutive sentences and 50% random sentences. + This is used for none break mode + """ + # pair sentences + for sent_id, sent in enumerate(dataset_index): + next_sent_label = ( + 1 if np.random.rand() > 0.5 and sent_id != len(dataset_index) - 1 else 0 + ) + if next_sent_label: + next_sent = dataset_index[sent_id + 1] + else: + next_sent = dataset_index[ + self._skip_sampling(len(dataset_index), [sent_id, sent_id + 1]) + ] + self.sent_pairs.append((sent, next_sent, next_sent_label)) + + # The current blocks don't include the special tokens but the + # sizes already account for this + self.sizes.append(3 + sent[3] + next_sent[3]) + + def _sent_to_dataset_index(self, sent_sizes): + """ + Build index mapping block indices to the underlying dataset indices + """ + dataset_index = [] + ds_idx, ds_remaining = -1, 0 + for to_consume in sent_sizes: + sent_size = to_consume + if ds_remaining == 0: + ds_idx += 1 + ds_remaining = sent_sizes[ds_idx] + start_ds_idx = ds_idx + start_offset = sent_sizes[ds_idx] - ds_remaining + while to_consume > ds_remaining: + to_consume -= ds_remaining + ds_idx += 1 + ds_remaining = sent_sizes[ds_idx] + ds_remaining -= to_consume + dataset_index.append( + ( + start_ds_idx, # starting index in dataset + start_offset, # starting offset within starting index + ds_idx, # ending index in dataset + sent_size, # sentence length + ) + ) + assert ds_remaining == 0 + assert ds_idx == len(self.dataset) - 1 + return dataset_index + + def _generate_sentence_pair(self, doc, doc_id, max_num_tokens, sizes): + """ + Go through a single document and genrate sentence paris from it + """ + current_chunk = [] + current_length = 0 + curr = 0 + # To provide more randomness, we decrease target seq length for parts of + # samples (10% by default). Note that max_num_tokens is the hard threshold + # for batching and will never be changed. + target_seq_length = max_num_tokens + if np.random.random() < self.short_seq_prob: + target_seq_length = np.random.randint(2, max_num_tokens) + # loop through all sentences in document + while curr < len(doc): + sent_id = doc[curr] + current_chunk.append(sent_id) + current_length = sum(sizes[current_chunk]) + # split chunk and generate pair when exceed target_seq_length or + # finish the loop + if curr == len(doc) - 1 or current_length >= target_seq_length: + # split the chunk into 2 parts + a_end = 1 + if len(current_chunk) > 2: + a_end = np.random.randint(1, len(current_chunk) - 1) + sent_a = current_chunk[:a_end] + len_a = sum(sizes[sent_a]) + # generate next sentence label, note that if there is only 1 sentence + # in current chunk, label is always 0 + next_sent_label = ( + 1 if np.random.rand() > 0.5 and len(current_chunk) != 1 else 0 + ) + if not next_sent_label: + # if next sentence label is 0, sample sent_b from a random doc + target_b_length = target_seq_length - len_a + rand_doc_id = self._skip_sampling(len(self.block_indices), [doc_id]) + random_doc = self.block_indices[rand_doc_id] + random_start = np.random.randint(0, len(random_doc)) + sent_b = [] + len_b = 0 + for j in range(random_start, len(random_doc)): + sent_b.append(random_doc[j]) + len_b = sum(sizes[sent_b]) + if len_b >= target_b_length: + break + # return the second part of the chunk since it's not used + num_unused_segments = len(current_chunk) - a_end + curr -= num_unused_segments + else: + # if next sentence label is 1, use the second part of chunk as sent_B + sent_b = current_chunk[a_end:] + len_b = sum(sizes[sent_b]) + # currently sent_a and sent_B may be longer than max_num_tokens, + # truncate them and return block idx and offsets for them + sent_a, sent_b = self._truncate_sentences( + sent_a, sent_b, max_num_tokens + ) + self.sent_pairs.append((sent_a, sent_b, next_sent_label)) + self.sizes.append(3 + sent_a[3] + sent_b[3]) + current_chunk = [] + curr += 1 + + def _skip_sampling(self, total, skip_ids): + """ + Generate a random integer which is not in skip_ids. Sample range is [0, total) + TODO: ids in skip_ids should be consecutive, we can extend it to more generic version later + """ + rand_id = np.random.randint(total - len(skip_ids)) + return rand_id if rand_id < min(skip_ids) else rand_id + len(skip_ids) + + def _truncate_sentences(self, sent_a, sent_b, max_num_tokens): + """ + Trancate a pair of sentence to limit total length under max_num_tokens + Logics: + 1. Truncate longer sentence + 2. Tokens to be truncated could be at the beginning or the end of the sentnce + Returns: + Truncated sentences represented by dataset idx + """ + len_a, len_b = sum(self.dataset.sizes[sent_a]), sum(self.dataset.sizes[sent_b]) + front_cut_a = front_cut_b = end_cut_a = end_cut_b = 0 + + while True: + total_length = ( + len_a + len_b - front_cut_a - front_cut_b - end_cut_a - end_cut_b + ) + if total_length <= max_num_tokens: + break + + if len_a - front_cut_a - end_cut_a > len_b - front_cut_b - end_cut_b: + if np.random.rand() < 0.5: + front_cut_a += 1 + else: + end_cut_a += 1 + else: + if np.random.rand() < 0.5: + front_cut_b += 1 + else: + end_cut_b += 1 + + # calculate ds indices as well as offsets and return + truncated_sent_a = self._cut_sentence(sent_a, front_cut_a, end_cut_a) + truncated_sent_b = self._cut_sentence(sent_b, front_cut_b, end_cut_b) + return truncated_sent_a, truncated_sent_b + + def _cut_sentence(self, sent, front_cut, end_cut): + """ + Cut a sentence based on the numbers of tokens to be cut from beginning and end + Represent the sentence as dataset idx and return + """ + start_ds_idx, end_ds_idx, offset = sent[0], sent[-1], 0 + target_len = sum(self.dataset.sizes[sent]) - front_cut - end_cut + while front_cut > 0: + if self.dataset.sizes[start_ds_idx] > front_cut: + offset += front_cut + break + else: + front_cut -= self.dataset.sizes[start_ds_idx] + start_ds_idx += 1 + while end_cut > 0: + if self.dataset.sizes[end_ds_idx] > end_cut: + break + else: + end_cut -= self.dataset.sizes[end_ds_idx] + end_ds_idx -= 1 + return start_ds_idx, offset, end_ds_idx, target_len + + def _fetch_block(self, start_ds_idx, offset, end_ds_idx, length): + """ + Fetch a block of tokens based on its dataset idx + """ + buffer = torch.cat( + [self.dataset[idx] for idx in range(start_ds_idx, end_ds_idx + 1)] + ) + s, e = offset, offset + length + return buffer[s:e] + + def __getitem__(self, index): + block1, block2, next_sent_label = self.sent_pairs[index] + block1 = self._fetch_block(*block1) + block2 = self._fetch_block(*block2) + return block1, block2, next_sent_label + + def __len__(self): + return len(self.sizes) + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + prefetch_idx = set() + for index in indices: + for block1, block2, _ in [self.sent_pairs[index]]: + for ds_idx in range(block1[0], block1[2] + 1): + prefetch_idx.add(ds_idx) + for ds_idx in range(block2[0], block2[2] + 1): + prefetch_idx.add(ds_idx) + self.dataset.prefetch(prefetch_idx) diff --git a/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dataset.py b/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dataset.py new file mode 100644 index 00000000..dd8ea2c6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dataset.py @@ -0,0 +1,303 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Dict, List, Tuple + +import numpy as np +import torch +from fairseq.data import Dictionary, FairseqDataset, data_utils +from fairseq.data.concat_dataset import ConcatDataset +from fairseq.data.legacy.block_pair_dataset import BlockPairDataset +from fairseq.data.token_block_dataset import TokenBlockDataset + + +class MaskedLMDataset(FairseqDataset): + """ + A wrapper Dataset for masked language modelling. The dataset + wraps around TokenBlockDataset or BlockedPairDataset and creates a batch + where the input blocks are masked according to the specified masking + probability. Additionally the batch can also contain sentence level targets + if this is specified. + + Args: + dataset: Dataset which generates blocks of data. Only BlockPairDataset + and TokenBlockDataset are supported. + sizes: Sentence lengths + vocab: Dictionary with the vocabulary and special tokens. + pad_idx: Id of padding token in dictionary + mask_idx: Id of mask token in dictionary + classif_token_idx: Id of classification token in dictionary. This is the + token associated with the sentence embedding (Eg: CLS for BERT) + sep_token_idx: Id of separator token in dictionary + (Eg: SEP in BERT) + seed: Seed for random number generator for reproducibility. + shuffle: Shuffle the elements before batching. + has_pairs: Specifies whether the underlying dataset + generates a pair of blocks along with a sentence_target or not. + Setting it to True assumes that the underlying dataset generates a + label for the pair of sentences which is surfaced as + sentence_target. The default value assumes a single block with no + sentence target. + segment_id: An optional segment id for filling in the segment labels + when we are in the single block setting (Eg: XLM). Default is 0. + masking_ratio: specifies what percentage of the blocks should be masked. + masking_prob: specifies the probability of a given token being + replaced with the "MASK" token. + random_token_prob: specifies the probability of a given token being + replaced by a random token from the vocabulary. + """ + + def __init__( + self, + dataset: FairseqDataset, + sizes: np.ndarray, + vocab: Dictionary, + pad_idx: int, + mask_idx: int, + classif_token_idx: int, + sep_token_idx: int, + seed: int = 1, + shuffle: bool = True, + has_pairs: bool = True, + segment_id: int = 0, + masking_ratio: float = 0.15, + masking_prob: float = 0.8, + random_token_prob: float = 0.1, + ): + # Make sure the input datasets are the ones supported + assert ( + isinstance(dataset, TokenBlockDataset) + or isinstance(dataset, BlockPairDataset) + or isinstance(dataset, ConcatDataset) + ), ( + "MaskedLMDataset only wraps TokenBlockDataset or BlockPairDataset or " + "ConcatDataset" + ) + + self.dataset = dataset + self.sizes = np.array(sizes) + self.vocab = vocab + self.pad_idx = pad_idx + self.mask_idx = mask_idx + self.classif_token_idx = classif_token_idx + self.sep_token_idx = sep_token_idx + self.shuffle = shuffle + self.seed = seed + self.has_pairs = has_pairs + self.segment_id = segment_id + self.masking_ratio = masking_ratio + self.masking_prob = masking_prob + self.random_token_prob = random_token_prob + + # If we have only one block then sizes needs to be updated to include + # the classification token + if not has_pairs: + self.sizes = self.sizes + 1 + + def __getitem__(self, index: int): + # if has_pairs, then expect 2 blocks and a sentence target + if self.has_pairs: + (block_one, block_two, sentence_target) = self.dataset[index] + else: + block_one = self.dataset[index] + + return { + "id": index, + "block_one": block_one, + "block_two": block_two if self.has_pairs else None, + "sentence_target": sentence_target if self.has_pairs else None, + } + + def __len__(self): + return len(self.dataset) + + def _mask_block( + self, + sentence: np.ndarray, + mask_idx: int, + pad_idx: int, + dictionary_token_range: Tuple, + ): + """ + Mask tokens for Masked Language Model training + Samples mask_ratio tokens that will be predicted by LM. + + Note:This function may not be efficient enough since we had multiple + conversions between np and torch, we can replace them with torch + operators later. + + Args: + sentence: 1d tensor to be masked + mask_idx: index to use for masking the sentence + pad_idx: index to use for masking the target for tokens we aren't + predicting + dictionary_token_range: range of indices in dictionary which can + be used for random word replacement + (e.g. without special characters) + Return: + masked_sent: masked sentence + target: target with words which we are not predicting replaced + by pad_idx + """ + masked_sent = np.copy(sentence) + sent_length = len(sentence) + mask_num = math.ceil(sent_length * self.masking_ratio) + mask = np.random.choice(sent_length, mask_num, replace=False) + target = np.copy(sentence) + + for i in range(sent_length): + if i in mask: + rand = np.random.random() + + # replace with mask if probability is less than masking_prob + # (Eg: 0.8) + if rand < self.masking_prob: + masked_sent[i] = mask_idx + + # replace with random token if probability is less than + # masking_prob + random_token_prob (Eg: 0.9) + elif rand < (self.masking_prob + self.random_token_prob): + # sample random token from dictionary + masked_sent[i] = np.random.randint( + dictionary_token_range[0], dictionary_token_range[1] + ) + else: + target[i] = pad_idx + + return masked_sent, target + + def _collate(self, samples: List[Dict], pad_idx: int, eos_idx: int): + """ + Does the heavy lifting for creating a batch from the input list of + examples. The logic is as follows: + 1. Mask the input blocks. In case has_pair is True then we have 2 + blocks to mask. + 2. Prepend the first masked block tensor with the special token + used as sentence embedding. Eg: CLS in BERT. This happens + irrespective of the value of has_pair. + 3. If has_pair is True, then append the first masked block with the + special separator token (eg: SEP for BERT) and compute segment + label accordingly. In this case, also append the second masked + block with this special separator token and compute its segment + label. + 4. For the targets tensor, prepend and append with padding index + accordingly. + 5. Concatenate all tensors. + """ + if len(samples) == 0: + return {} + # To ensure determinism, we reset the state of the PRNG after every + # batch based on the seed and the first id of the batch. This ensures + # that across epochs we get the same mask for the same example. This + # is needed for reproducibility and is how BERT does masking + # TODO: Can we add deteminism without this constraint? + with data_utils.numpy_seed(self.seed + samples[0]["id"]): + for s in samples: + + # token range is needed for replacing with random token during + # masking + token_range = (self.vocab.nspecial, len(self.vocab)) + + # mask according to specified probabilities. + masked_blk_one, masked_tgt_one = self._mask_block( + s["block_one"], + self.mask_idx, + self.pad_idx, + token_range, + ) + + tokens = np.concatenate([[self.classif_token_idx], masked_blk_one]) + targets = np.concatenate([[self.pad_idx], masked_tgt_one]) + segments = np.ones(len(tokens)) * self.segment_id + + # if has_pairs is True then we need to add the SEP token to both + # the blocks after masking and re-compute segments based on the new + # lengths. + if self.has_pairs: + tokens_one = np.concatenate([tokens, [self.sep_token_idx]]) + targets_one = np.concatenate([targets, [self.pad_idx]]) + + masked_blk_two, masked_tgt_two = self._mask_block( + s["block_two"], self.mask_idx, self.pad_idx, token_range + ) + tokens_two = np.concatenate([masked_blk_two, [self.sep_token_idx]]) + targets_two = np.concatenate([masked_tgt_two, [self.pad_idx]]) + + # block + 1 sep + 1 special (CLS) + segments_one = np.zeros(len(tokens_one)) + # block + 1 sep + segments_two = np.ones(len(tokens_two)) + + tokens = np.concatenate([tokens_one, tokens_two]) + targets = np.concatenate([targets_one, targets_two]) + segments = np.concatenate([segments_one, segments_two]) + + s["source"] = torch.LongTensor(tokens) + s["segment_labels"] = torch.LongTensor(segments) + s["lm_target"] = torch.LongTensor(targets) + + def merge(key): + return data_utils.collate_tokens( + [s[key] for s in samples], pad_idx, eos_idx, left_pad=False + ) + + return { + "id": torch.LongTensor([s["id"] for s in samples]), + "ntokens": sum(len(s["source"]) for s in samples), + "net_input": { + "src_tokens": merge("source"), + "segment_labels": merge("segment_labels"), + }, + "lm_target": merge("lm_target"), + "sentence_target": torch.LongTensor([s["sentence_target"] for s in samples]) + if self.has_pairs + else None, + "nsentences": len(samples), + } + + def collater(self, samples: List[Dict]): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[dict]): samples to collate + + Returns: + dict: a mini-batch of data + """ + return self._collate(samples, self.vocab.pad(), self.vocab.eos()) + + def num_tokens(self, index: int): + """ + Return the number of tokens in a sample. This value is used to + enforce max-tokens during batching. + """ + return self.sizes[index] + + def size(self, index: int): + """ + Return an example's size as a float or tuple. This value is used when + filtering a dataset with max-positions. + """ + return self.sizes[index] + + def ordered_indices(self): + """ + Return an ordered list of indices. Batches will be constructed based + on this order. + """ + if self.shuffle: + return np.random.permutation(len(self)) + else: + order = [np.arange(len(self))] + order.append(self.sizes) + return np.lexsort(order) + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + self.dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dictionary.py b/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dictionary.py new file mode 100644 index 00000000..dee88f7a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/legacy/masked_lm_dictionary.py @@ -0,0 +1,60 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data import Dictionary + + +class MaskedLMDictionary(Dictionary): + """ + Dictionary for Masked Language Modelling tasks. This extends Dictionary by + adding the mask symbol. + """ + + def __init__( + self, + pad="<pad>", + eos="</s>", + unk="<unk>", + mask="<mask>", + ): + super().__init__(pad=pad, eos=eos, unk=unk) + self.mask_word = mask + self.mask_index = self.add_symbol(mask) + self.nspecial = len(self.symbols) + + def mask(self): + """Helper to get index of mask symbol""" + return self.mask_index + + +class BertDictionary(MaskedLMDictionary): + """ + Dictionary for BERT task. This extends MaskedLMDictionary by adding support + for cls and sep symbols. + """ + + def __init__( + self, + pad="<pad>", + eos="</s>", + unk="<unk>", + mask="<mask>", + cls="<cls>", + sep="<sep>", + ): + super().__init__(pad=pad, eos=eos, unk=unk, mask=mask) + self.cls_word = cls + self.sep_word = sep + self.cls_index = self.add_symbol(cls) + self.sep_index = self.add_symbol(sep) + self.nspecial = len(self.symbols) + + def cls(self): + """Helper to get index of cls symbol""" + return self.cls_index + + def sep(self): + """Helper to get index of sep symbol""" + return self.sep_index diff --git a/fairseq-tools/fairseq/fairseq/data/list_dataset.py b/fairseq-tools/fairseq/fairseq/data/list_dataset.py new file mode 100644 index 00000000..12f00aa4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/list_dataset.py @@ -0,0 +1,32 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import BaseWrapperDataset + + +class ListDataset(BaseWrapperDataset): + def __init__(self, dataset, sizes=None): + super().__init__(dataset) + self._sizes = sizes + + def __iter__(self): + for x in self.dataset: + yield x + + def collater(self, samples): + return samples + + @property + def sizes(self): + return self._sizes + + def num_tokens(self, index): + return self.sizes[index] + + def size(self, index): + return self.sizes[index] + + def set_epoch(self, epoch): + pass diff --git a/fairseq-tools/fairseq/fairseq/data/lm_context_window_dataset.py b/fairseq-tools/fairseq/fairseq/data/lm_context_window_dataset.py new file mode 100644 index 00000000..29ad887b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/lm_context_window_dataset.py @@ -0,0 +1,79 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +from fairseq.data.monolingual_dataset import MonolingualDataset + +from . import FairseqDataset + + +class LMContextWindowDataset(FairseqDataset): + """Wraps a MonolingualDataset and provides more context for evaluation.""" + + def __init__(self, dataset, tokens_per_sample, context_window, pad_idx): + assert isinstance(dataset, MonolingualDataset) + assert context_window > 0 + self.dataset = dataset + self.tokens_per_sample = tokens_per_sample + self.context_window = context_window + self.pad_idx = pad_idx + self.prev_tokens = np.empty([0]) + + def __getitem__(self, index): + return self.dataset[index] + + def __len__(self): + return len(self.dataset) + + def collater(self, samples): + sample = self.dataset.collater(samples) + + pad = self.pad_idx + max_sample_len = self.tokens_per_sample + self.context_window + + bsz, tsz = sample["net_input"]["src_tokens"].shape + start_idxs = [0] * bsz + toks = sample["net_input"]["src_tokens"] + lengths = sample["net_input"]["src_lengths"] + tgt = sample["target"] + new_toks = np.empty([bsz, tsz + self.context_window], dtype=np.int64) + new_tgt = np.full([bsz, tsz + self.context_window], pad, dtype=np.int64) + sample_lens = toks.ne(pad).long().sum(dim=1).cpu() + for i in range(bsz): + sample_len = sample_lens[i] + extra = len(self.prev_tokens) + sample_len - max_sample_len + if extra > 0: + self.prev_tokens = self.prev_tokens[extra:] + pads = np.full(self.context_window - len(self.prev_tokens), pad) + new_toks[i] = np.concatenate([self.prev_tokens, toks[i].numpy(), pads]) + new_tgt[ + i, len(self.prev_tokens) : len(self.prev_tokens) + len(tgt[i]) + ] = tgt[i] + start_idxs[i] = len(self.prev_tokens) + lengths[i] += len(self.prev_tokens) + self.prev_tokens = new_toks[i][new_toks[i] != pad][-self.context_window :] + sample["net_input"]["src_tokens"] = torch.from_numpy(new_toks) + sample["target"] = torch.from_numpy(new_tgt) + sample["start_indices"] = start_idxs + + return sample + + def num_tokens(self, index): + return self.dataset.num_tokens(index) + + def size(self, index): + return self.dataset.size(index) + + def ordered_indices(self): + # NOTE we don't shuffle the data to retain access to the previous dataset elements + return np.arange(len(self.dataset)) + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + return self.dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/lru_cache_dataset.py b/fairseq-tools/fairseq/fairseq/data/lru_cache_dataset.py new file mode 100644 index 00000000..a7854ac1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/lru_cache_dataset.py @@ -0,0 +1,21 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from functools import lru_cache + +from . import BaseWrapperDataset + + +class LRUCacheDataset(BaseWrapperDataset): + def __init__(self, dataset, token=None): + super().__init__(dataset) + + @lru_cache(maxsize=8) + def __getitem__(self, index): + return self.dataset[index] + + @lru_cache(maxsize=8) + def collater(self, samples): + return self.dataset.collater(samples) diff --git a/fairseq-tools/fairseq/fairseq/data/mask_tokens_dataset.py b/fairseq-tools/fairseq/fairseq/data/mask_tokens_dataset.py new file mode 100644 index 00000000..8ea86245 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/mask_tokens_dataset.py @@ -0,0 +1,178 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from functools import lru_cache + +import numpy as np +import torch +from fairseq.data import Dictionary, data_utils + +from . import BaseWrapperDataset, LRUCacheDataset + + +class MaskTokensDataset(BaseWrapperDataset): + """ + A wrapper Dataset for masked language modeling. + + Input items are masked according to the specified masking probability. + + Args: + dataset: Dataset to wrap. + sizes: Sentence lengths + vocab: Dictionary with the vocabulary and special tokens. + pad_idx: Id of pad token in vocab + mask_idx: Id of mask token in vocab + return_masked_tokens: controls whether to return the non-masked tokens + (the default) or to return a tensor with the original masked token + IDs (and *pad_idx* elsewhere). The latter is useful as targets for + masked LM training. + seed: Seed for random number generator for reproducibility. + mask_prob: probability of replacing a token with *mask_idx*. + leave_unmasked_prob: probability that a masked token is unmasked. + random_token_prob: probability of replacing a masked token with a + random token from the vocabulary. + freq_weighted_replacement: sample random replacement words based on + word frequencies in the vocab. + mask_whole_words: only mask whole words. This should be a byte mask + over vocab indices, indicating whether it is the beginning of a + word. We will extend any mask to encompass the whole word. + bpe: BPE to use for whole-word masking. + """ + + @classmethod + def apply_mask(cls, dataset: torch.utils.data.Dataset, *args, **kwargs): + """Return the source and target datasets for masked LM training.""" + dataset = LRUCacheDataset(dataset) + return ( + LRUCacheDataset(cls(dataset, *args, **kwargs, return_masked_tokens=False)), + LRUCacheDataset(cls(dataset, *args, **kwargs, return_masked_tokens=True)), + ) + + def __init__( + self, + dataset: torch.utils.data.Dataset, + vocab: Dictionary, + pad_idx: int, + mask_idx: int, + return_masked_tokens: bool = False, + seed: int = 1, + mask_prob: float = 0.15, + leave_unmasked_prob: float = 0.1, + random_token_prob: float = 0.1, + freq_weighted_replacement: bool = False, + mask_whole_words: torch.Tensor = None, + ): + assert 0.0 < mask_prob < 1.0 + assert 0.0 <= random_token_prob <= 1.0 + assert 0.0 <= leave_unmasked_prob <= 1.0 + assert random_token_prob + leave_unmasked_prob <= 1.0 + + self.dataset = dataset + self.vocab = vocab + self.pad_idx = pad_idx + self.mask_idx = mask_idx + self.return_masked_tokens = return_masked_tokens + self.seed = seed + self.mask_prob = mask_prob + self.leave_unmasked_prob = leave_unmasked_prob + self.random_token_prob = random_token_prob + self.mask_whole_words = mask_whole_words + + if random_token_prob > 0.0: + if freq_weighted_replacement: + weights = np.array(self.vocab.count) + else: + weights = np.ones(len(self.vocab)) + weights[: self.vocab.nspecial] = 0 + self.weights = weights / weights.sum() + + self.epoch = 0 + + @property + def can_reuse_epoch_itr_across_epochs(self): + return True # only the noise changes, not item sizes + + def set_epoch(self, epoch, **unused): + super().set_epoch(epoch) + self.epoch = epoch + + @lru_cache(maxsize=8) + def __getitem__(self, index: int): + with data_utils.numpy_seed(self.seed, self.epoch, index): + item = self.dataset[index] + sz = len(item) + + assert ( + self.mask_idx not in item + ), "Dataset contains mask_idx (={}), this is not expected!".format( + self.mask_idx, + ) + + if self.mask_whole_words is not None: + word_begins_mask = self.mask_whole_words.gather(0, item) + word_begins_idx = word_begins_mask.nonzero().view(-1) + sz = len(word_begins_idx) + words = np.split(word_begins_mask, word_begins_idx)[1:] + assert len(words) == sz + word_lens = list(map(len, words)) + + # decide elements to mask + mask = np.full(sz, False) + num_mask = int( + # add a random number for probabilistic rounding + self.mask_prob * sz + + np.random.rand() + ) + mask[np.random.choice(sz, num_mask, replace=False)] = True + + if self.return_masked_tokens: + # exit early if we're just returning the masked tokens + # (i.e., the targets for masked LM training) + if self.mask_whole_words is not None: + mask = np.repeat(mask, word_lens) + new_item = np.full(len(mask), self.pad_idx) + new_item[mask] = item[torch.from_numpy(mask.astype(np.uint8)) == 1] + return torch.from_numpy(new_item) + + # decide unmasking and random replacement + rand_or_unmask_prob = self.random_token_prob + self.leave_unmasked_prob + if rand_or_unmask_prob > 0.0: + rand_or_unmask = mask & (np.random.rand(sz) < rand_or_unmask_prob) + if self.random_token_prob == 0.0: + unmask = rand_or_unmask + rand_mask = None + elif self.leave_unmasked_prob == 0.0: + unmask = None + rand_mask = rand_or_unmask + else: + unmask_prob = self.leave_unmasked_prob / rand_or_unmask_prob + decision = np.random.rand(sz) < unmask_prob + unmask = rand_or_unmask & decision + rand_mask = rand_or_unmask & (~decision) + else: + unmask = rand_mask = None + + if unmask is not None: + mask = mask ^ unmask + + if self.mask_whole_words is not None: + mask = np.repeat(mask, word_lens) + + new_item = np.copy(item) + new_item[mask] = self.mask_idx + if rand_mask is not None: + num_rand = rand_mask.sum() + if num_rand > 0: + if self.mask_whole_words is not None: + rand_mask = np.repeat(rand_mask, word_lens) + num_rand = rand_mask.sum() + + new_item[rand_mask] = np.random.choice( + len(self.vocab), + num_rand, + p=self.weights, + ) + + return torch.from_numpy(new_item) diff --git a/fairseq-tools/fairseq/fairseq/data/monolingual_dataset.py b/fairseq-tools/fairseq/fairseq/data/monolingual_dataset.py new file mode 100644 index 00000000..ec73f1fd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/monolingual_dataset.py @@ -0,0 +1,230 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch + +from . import FairseqDataset, data_utils + + +def collate(samples, pad_idx, eos_idx): + if len(samples) == 0: + return {} + + def merge(key, is_list=False): + if is_list: + res = [] + for i in range(len(samples[0][key])): + res.append( + data_utils.collate_tokens( + [s[key][i] for s in samples], + pad_idx, + eos_idx, + left_pad=False, + ) + ) + return res + else: + return data_utils.collate_tokens( + [s[key] for s in samples], + pad_idx, + eos_idx, + left_pad=False, + ) + + src_tokens = merge("source") + if samples[0]["target"] is not None: + is_target_list = isinstance(samples[0]["target"], list) + target = merge("target", is_target_list) + else: + target = src_tokens + + return { + "id": torch.LongTensor([s["id"] for s in samples]), + "nsentences": len(samples), + "ntokens": sum(len(s["source"]) for s in samples), + "net_input": { + "src_tokens": src_tokens, + "src_lengths": torch.LongTensor([s["source"].numel() for s in samples]), + }, + "target": target, + } + + +class MonolingualDataset(FairseqDataset): + """ + A wrapper around torch.utils.data.Dataset for monolingual data. + + Args: + dataset (torch.utils.data.Dataset): dataset to wrap + sizes (List[int]): sentence lengths + vocab (~fairseq.data.Dictionary): vocabulary + shuffle (bool, optional): shuffle the elements before batching + (default: True). + """ + + def __init__( + self, + dataset, + sizes, + src_vocab, + tgt_vocab, + add_eos_for_other_targets, + shuffle, + targets=None, + add_bos_token=False, + ): + self.dataset = dataset + self.sizes = np.array(sizes) + self.vocab = src_vocab + self.tgt_vocab = tgt_vocab + self.add_eos_for_other_targets = add_eos_for_other_targets + self.shuffle = shuffle + self.add_bos_token = add_bos_token + + assert targets is None or all( + t in {"self", "future", "past"} for t in targets + ), "targets must be none or one of 'self', 'future', 'past'" + if targets is not None and len(targets) == 0: + targets = None + self.targets = targets + + def __getitem__(self, index): + if self.targets is not None: + # *future_target* is the original sentence + # *source* is shifted right by 1 (maybe left-padded with eos) + # *past_target* is shifted right by 2 (left-padded as needed) + # + # Left-to-right language models should condition on *source* and + # predict *future_target*. + # Right-to-left language models should condition on *source* and + # predict *past_target*. + source, future_target, past_target = self.dataset[index] + source, target = self._make_source_target( + source, future_target, past_target + ) + else: + source = self.dataset[index] + target = None + source, target = self._maybe_add_bos(source, target) + return {"id": index, "source": source, "target": target} + + def __len__(self): + return len(self.dataset) + + def _make_source_target(self, source, future_target, past_target): + if self.targets is not None: + target = [] + + if ( + self.add_eos_for_other_targets + and (("self" in self.targets) or ("past" in self.targets)) + and source[-1] != self.vocab.eos() + ): + # append eos at the end of source + source = torch.cat([source, source.new([self.vocab.eos()])]) + + if "future" in self.targets: + future_target = torch.cat( + [future_target, future_target.new([self.vocab.pad()])] + ) + if "past" in self.targets: + # first token is before the start of sentence which is only used in "none" break mode when + # add_eos_for_other_targets is False + past_target = torch.cat( + [ + past_target.new([self.vocab.pad()]), + past_target[1:], + source[-2, None], + ] + ) + + for t in self.targets: + if t == "self": + target.append(source) + elif t == "future": + target.append(future_target) + elif t == "past": + target.append(past_target) + else: + raise Exception("invalid target " + t) + + if len(target) == 1: + target = target[0] + else: + target = future_target + + return source, self._filter_vocab(target) + + def _maybe_add_bos(self, source, target): + if self.add_bos_token: + source = torch.cat([source.new([self.vocab.bos()]), source]) + if target is not None: + target = torch.cat([target.new([self.tgt_vocab.bos()]), target]) + return source, target + + def _filter_vocab(self, target): + if len(self.tgt_vocab) != len(self.vocab): + + def _filter(target): + mask = target.ge(len(self.tgt_vocab)) + if mask.any(): + target[mask] = self.tgt_vocab.unk() + return target + + if isinstance(target, list): + return [_filter(t) for t in target] + return _filter(target) + return target + + def collater(self, samples): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[dict]): samples to collate + + Returns: + dict: a mini-batch with the following keys: + + - `id` (LongTensor): example IDs in the original input order + - `ntokens` (int): total number of tokens in the batch + - `net_input` (dict): the input to the Model, containing keys: + + - `src_tokens` (LongTensor): a padded 2D Tensor of tokens in + the source sentence of shape `(bsz, src_len)`. Padding will + appear on the right. + + - `target` (LongTensor): a padded 2D Tensor of tokens in the + target sentence of shape `(bsz, tgt_len)`. Padding will appear + on the right. + """ + return collate(samples, self.vocab.pad(), self.vocab.eos()) + + def num_tokens(self, index): + """Return the number of tokens in a sample. This value is used to + enforce ``--max-tokens`` during batching.""" + return self.sizes[index] + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + return self.sizes[index] + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + if self.shuffle: + order = [np.random.permutation(len(self))] + else: + order = [np.arange(len(self))] + order.append(self.sizes) + return np.lexsort(order) + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + self.dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/multi_corpus_dataset.py b/fairseq-tools/fairseq/fairseq/data/multi_corpus_dataset.py new file mode 100644 index 00000000..d2457666 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multi_corpus_dataset.py @@ -0,0 +1,159 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from collections import OrderedDict +from typing import Dict, List + +import numpy as np +from fairseq.data import data_utils + +from . import FairseqDataset + + +logger = logging.getLogger(__name__) + + +class MultiCorpusDataset(FairseqDataset): + """ + Stores multiple instances of FairseqDataset together. Requires each instance + to be the same dataset, as the collate method needs to work on batches with + samples from each dataset. + + Allows specifying a distribution over the datasets to use. Note that unlike + MultiCorpusSampledDataset, this distribution allows sampling for each item, + rather than on a batch level. + + Each time ordered_indices() is called, a new sample is generated with + the specified distribution. + + Args: + datasets: a OrderedDict of FairseqDataset instances. + distribution: a List containing the probability of getting an utterance from + corresponding dataset + seed: random seed for sampling the datsets + sort_indices: if true, will sort the ordered indices by size + """ + + def __init__( + self, + datasets: Dict[str, FairseqDataset], + distribution: List[float], + seed: int, + sort_indices: bool = False, + ): + super().__init__() + assert isinstance(datasets, OrderedDict) + assert len(datasets) == len(distribution) + self.datasets = datasets + self.distribution = distribution + self.seed = seed + self.sort_indices = sort_indices + + # Avoid repeated conversions to list later + self.dataset_list = list(datasets.values()) + self.total_num_instances = 0 + + first_dataset = list(self.datasets.values())[0] + + self.dataset_offsets = [] + for dataset in datasets.values(): + assert isinstance(dataset, FairseqDataset) + assert type(dataset) is type(first_dataset) + self.dataset_offsets.append(self.total_num_instances) + self.total_num_instances += len(dataset) + + def ordered_indices(self): + with data_utils.numpy_seed(self.seed, self.epoch): + # Used to store the order of indices of each dataset to use + indices = [ + np.random.permutation(len(dataset)) + for dataset in self.datasets.values() + ] + # Keep track of which samples we've used for each dataset + counters = [0 for _ in self.datasets] + + sampled_indices = [ + self._sample(indices, counters) for _ in range(self.total_num_instances) + ] + if self.sort_indices: + sampled_indices.sort(key=lambda i: self.num_tokens(i)) + return np.array(sampled_indices, dtype=np.int64) + + def _sample(self, indices, counters): + # First pick dataset + dataset_idx = np.random.choice(len(self.distribution), p=self.distribution) + + # Then get dataset internal index + idx = indices[dataset_idx][counters[dataset_idx]] + + # Convert to multi-datasets index + idx += self.dataset_offsets[dataset_idx] + + counters[dataset_idx] += 1 + + # Reset if we reach end + if counters[dataset_idx] == len(self.dataset_list[dataset_idx]): + counters[dataset_idx] = 0 + indices[dataset_idx] = np.random.permutation( + len(self.dataset_list[dataset_idx]) + ) + + return idx + + def _map_index(self, index: int): + """ + If dataset A has length N and dataset B has length M + then index 1 maps to index 1 of dataset A, and index N + 1 + maps to index 1 of B. + """ + counter = 0 + for key, dataset in self.datasets.items(): + if index < counter + len(dataset): + return index - counter, key + counter += len(dataset) + raise ValueError( + "Invalid index: {}, max: {}".format(index, self.total_num_instances) + ) + + def __len__(self): + """ + Length of this dataset is the sum of individual datasets + """ + return self.total_num_instances + + def __getitem__(self, index): + index, key = self._map_index(index) + return self.datasets[key][index] + + def collater(self, samples): + """ + Since we enforce all datsets to be the same, collating is just + picking the first one and doing collate. + """ + if len(samples) == 0: + return None + + return list(self.datasets.values())[0].collater(samples) + + def num_tokens(self, index: int): + index, key = self._map_index(index) + return self.datasets[key].num_tokens(index) + + def size(self, index: int): + index, key = self._map_index(index) + return self.datasets[key].size(index) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return False + + def set_epoch(self, epoch, **unused): + super().set_epoch(epoch) + self.epoch = epoch + + @property + def supports_prefetch(self): + return False diff --git a/fairseq-tools/fairseq/fairseq/data/multi_corpus_sampled_dataset.py b/fairseq-tools/fairseq/fairseq/data/multi_corpus_sampled_dataset.py new file mode 100644 index 00000000..ad8e951c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multi_corpus_sampled_dataset.py @@ -0,0 +1,145 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import OrderedDict +from typing import Callable, Dict, List + +import numpy as np + +from . import FairseqDataset + + +def uniform_sampler(x): + # Sample from uniform distribution + return np.random.choice(x, 1).item() + + +class MultiCorpusSampledDataset(FairseqDataset): + """ + Stores multiple instances of FairseqDataset together and in every iteration + creates a batch by first sampling a dataset according to a specified + probability distribution and then getting instances from that dataset. + + Args: + datasets: an OrderedDict of FairseqDataset instances. + sampling_func: A function for sampling over list of dataset keys. + The default strategy is to sample uniformly. + """ + + def __init__( + self, + datasets: Dict[str, FairseqDataset], + sampling_func: Callable[[List], int] = None, + ): + super().__init__() + assert isinstance(datasets, OrderedDict) + self.datasets = datasets + if sampling_func is None: + sampling_func = uniform_sampler + self.sampling_func = sampling_func + + self.total_num_instances = 0 + for _, dataset in datasets.items(): + assert isinstance(dataset, FairseqDataset) + self.total_num_instances += len(dataset) + + self._ordered_indices = None + + def __len__(self): + """ + Length of this dataset is the sum of individual datasets + """ + return self.total_num_instances + + def ordered_indices(self): + """ + Ordered indices for batching. Here we call the underlying + dataset's ordered_indices() so that we get the same random ordering + as we would have from using the underlying dataset directly. + """ + if self._ordered_indices is None: + self._ordered_indices = OrderedDict( + [ + (key, dataset.ordered_indices()) + for key, dataset in self.datasets.items() + ] + ) + return np.arange(len(self)) + + def _map_index_to_dataset(self, key: int, index: int): + """ + Different underlying datasets have different lengths. In order to ensure + we are not accessing an index outside the range of the current dataset + size, we wrap around. This function should be called after we have + created an ordering for this and all underlying datasets. + """ + assert ( + self._ordered_indices is not None + ), "Must call MultiCorpusSampledDataset.ordered_indices() first" + mapped_index = index % len(self.datasets[key]) + return self._ordered_indices[key][mapped_index] + + def __getitem__(self, index: int): + """ + Get the item associated with index from each underlying dataset. + Since index is in the range of [0, TotalNumInstances], we need to + map the index to the dataset before retrieving the item. + """ + return OrderedDict( + [ + (key, dataset[self._map_index_to_dataset(key, index)]) + for key, dataset in self.datasets.items() + ] + ) + + def collater(self, samples: List[Dict]): + """ + Generate a mini-batch for this dataset. + To convert this into a regular mini-batch we use the following + logic: + 1. Select a dataset using the specified probability distribution. + 2. Call the collater function of the selected dataset. + """ + if len(samples) == 0: + return None + + selected_key = self.sampling_func(list(self.datasets.keys())) + selected_samples = [sample[selected_key] for sample in samples] + return self.datasets[selected_key].collater(selected_samples) + + def num_tokens(self, index: int): + """ + Return an example's length (number of tokens), used for batching. Here + we return the max across all examples at index across all underlying + datasets. + """ + return max( + dataset.num_tokens(self._map_index_to_dataset(key, index)) + for key, dataset in self.datasets.items() + ) + + def size(self, index: int): + """ + Return an example's size as a float or tuple. Here we return the max + across all underlying datasets. This value is used when filtering a + dataset with max-positions. + """ + return max( + dataset.size(self._map_index_to_dataset(key, index)) + for key, dataset in self.datasets.items() + ) + + @property + def supports_prefetch(self): + return all( + getattr(dataset, "supports_prefetch", False) + for dataset in self.datasets.values() + ) + + def prefetch(self, indices): + for key, dataset in self.datasets.items(): + dataset.prefetch( + [self._map_index_to_dataset(key, index) for index in indices] + ) diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/__init__.py b/fairseq-tools/fairseq/fairseq/data/multilingual/__init__.py new file mode 100644 index 00000000..62642369 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_data_manager.py b/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_data_manager.py new file mode 100644 index 00000000..8c14f4e3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_data_manager.py @@ -0,0 +1,1042 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import itertools +import json +import logging +import math +import os +from collections import OrderedDict, defaultdict + +from fairseq import utils +from fairseq.data import ( + AppendTokenDataset, + ConcatDataset, + Dictionary, + LanguagePairDataset, + PrependTokenDataset, + SampledMultiDataset, + SampledMultiEpochDataset, + StripTokenDataset, + TransformEosLangPairDataset, + TruncateDataset, + data_utils, + indexed_dataset, +) +from fairseq.data.multilingual.multilingual_utils import ( + EncoderLangtok, + LangTokSpec, + LangTokStyle, + augment_dictionary, + get_lang_tok, +) +from fairseq.data.multilingual.sampled_multi_dataset import CollateFormat +from fairseq.file_io import PathManager +from fairseq.utils import FileContentsAction, csv_str_list, eval_str_dict + + +logger = logging.getLogger(__name__) + + +def _lang_id(dic: Dictionary, lang: str): + """Return language ID index.""" + idx = dic.index(lang) + assert idx != dic.unk_index, "cannot find language ID for lang {}".format(lang) + return idx + + +def load_sampling_weights(from_file): + with open(from_file) as f: + weights = json.load(f) + return weights + + +class MultilingualDatasetManager(object): + def __init__(self, args, lang_pairs, langs, dicts, sampling_method): + super().__init__() + self.args = args + self.seed = args.seed + self.lang_pairs = lang_pairs + self.langs = langs + self.dicts = dicts + self.lang_dict = self.create_lang_dictionary(self.langs) + self.sampling_method = sampling_method + self.sampling_scheduler = None + self._has_sharded_data = False + self._num_shards_dict = {} + self._training_data_sizes = defaultdict(lambda: {}) + + @classmethod + def setup_data_manager(cls, args, lang_pairs, langs, dicts, sampling_method): + return MultilingualDatasetManager( + args, lang_pairs, langs, dicts, sampling_method + ) + + @staticmethod + def add_args(parser): + parser.add_argument( + "data", + help="colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner", + action=FileContentsAction, + ) + parser.add_argument( + "--langs", + default=None, + type=csv_str_list, + help="a list of languages comma sperated languages which can appear in lang-pairs; " + "note that the ordering determines language token IDs", + ) + parser.add_argument( + "--lang-dict", + default=None, + type=str, + help="an external file which contains a list of " + "languages which can appear in lang-pairs; " + "note that the ordering determines language token IDs; " + "--langs and --lang-dict are two exclusive options", + ) + parser.add_argument( + "--lang-tok-style", + default=LangTokStyle.multilingual.value, + type=str, + choices=[LangTokStyle.multilingual.value, LangTokStyle.mbart.value], + help="language token styles", + ) + + parser.add_argument( + "--load-alignments", + action="store_true", + help="load the binarized alignments", + ) + parser.add_argument( + "--left-pad-source", + default="True", + type=str, + metavar="BOOL", + help="pad the source on the left", + ) + parser.add_argument( + "--left-pad-target", + default="False", + type=str, + metavar="BOOL", + help="pad the target on the left", + ) + parser.add_argument( + "--max-source-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the source sequence", + ) + parser.add_argument( + "--max-target-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the target sequence", + ) + parser.add_argument( + "--upsample-primary", + default=1, + type=int, + help="amount to upsample primary dataset", + ) + parser.add_argument( + "--truncate-source", + action="store_true", + default=False, + help="truncate source to max-source-positions", + ) + parser.add_argument( + "--encoder-langtok", + default=None, + type=str, + choices=[EncoderLangtok.src.value, EncoderLangtok.tgt.value], + metavar="SRCTGT", + help="prepend to the beginning of source sentence the source or target " + "language token. (src/tgt)", + ) + parser.add_argument( + "--decoder-langtok", + action="store_true", + help="prepend to the beginning of target sentence the target language token", + ) + parser.add_argument( + "--lang-tok-replacing-bos-eos", action="store_true", default=False + ) + parser.add_argument( + "--enable-lang-ids", + default=False, + action="store_true", + help="whether to include language IDs in samples", + ) + parser.add_argument( + "--enable-reservsed-directions-shared-datasets", + default=False, + action="store_true", + help="whether to allow datasets be used in reversed directions", + ) + + parser.add_argument( + "--extra-data", + help='a dictionary of data name to this path, \ + e.g. {"mined", path_to_mined_data, "denoised": path_to_denoised_data}', + type=lambda uf: eval_str_dict(uf, type=str), + default=None, + ) + parser.add_argument( + "--extra-lang-pairs", + help='a dictionary of data name to the language pairs they serve, \ + e.g. {"mined": comma-separated-lang-pairs, "denoised": comma-separated-lang-pairs}', + type=lambda uf: eval_str_dict(uf, type=str), + default=None, + ) + parser.add_argument( + "--fixed-dictionary", + help="Fixed dictionary to use with model path", + default=None, + type=str, + ) + parser.add_argument( + "--langtoks-specs", + help='a list of comma separated data types that a set of language tokens to be specialized for, \ + e.g. "main,dae,mined". There will be a set of language tokens added to the vocab to \ + distinguish languages in different training data types. If not specified, default language \ + tokens per languages will be added', + default=LangTokSpec.main.value, + type=csv_str_list, + ) + parser.add_argument( + "--langtoks", + help='a dictionary of how to add language tokens, \ + e.g. {"mined": (None, "tgt"), "mono_dae": ("src.dae", "tgt"), "main": \ + ("src", "tgt")}, or {"mined": ("src.mined", "tgt")}', + default=None, + type=lambda uf: eval_str_dict(uf, type=str), + ) + parser.add_argument( + "--sampling-weights-from-file", + help='a file contain a python dictionary of how to sample data sets, \ + e.g. { "main:en_XX-es_XX": 0.2, "mined:en_XX-pt_XX": 0.5, \ + "mono_dae:es_XX-es_XX: 0.3, "main:en_xx-fr_XX": 0.8 }', + default=None, + type=str, + ) + parser.add_argument( + "--sampling-weights", + help='a dictionary of how to sample data sets, \ + e.g. { "main:en_XX-es_XX": 0.2, "mined:en_XX-pt_XX": 0.5, \ + "mono_dae:es_XX-es_XX: 0.3, "main:en_xx-fr_XX": 0.8 }', + default=None, + type=lambda uf: eval_str_dict(uf, type=str), + ) + parser.add_argument( + "--virtual-epoch-size", + default=1000000, + type=int, + help="virtual epoch size to speed up data loading", + ) + parser.add_argument( + "--virtual-data-size", + default=None, + type=int, + help="virtual data size of the whole joint dataset to speed" + "up data loading and have specific dynamic sampling strategy interval", + ) + + @classmethod + def load_langs(cls, args, **kwargs): + if args.lang_dict and args.langs: + raise ValueError("--langs and --lang-dict can not both be specified") + if args.lang_dict is None and args.langs is None: + logger.warning( + "External language dictionary is not provided; " + "use lang-pairs to infer the set of supported languages. " + "The language ordering is not stable which might cause " + "misalignment in pretraining and finetuning." + ) + # infer from lang_pairs as it is + langs = list( + {x for lang_pair in args.lang_pairs for x in lang_pair.split("-")} + ) + langs = sorted(langs) + logger.info(f"inferred language list: {langs}") + elif args.lang_dict: + with open( + PathManager.get_local_path(args.lang_dict), "r", encoding="utf-8" + ) as f: + langs = [lang.strip() for lang in f.readlines() if lang.strip()] + logger.info( + f"loaded language list from {args.lang_dict} as they are ordered in file" + ) + elif args.langs: + langs = args.langs + logger.info( + f"parsed the language list as they are ordered in the option: {langs}" + ) + return langs + + def has_sharded_data(self, split): + return self._has_sharded_data and split == getattr( + self.args, "train_subset", None + ) + + def _shared_collater(self): + return not (self.args.extra_data and "mono_dae" in self.args.extra_data) and ( + not self.args.lang_tok_replacing_bos_eos + ) + + def estimate_global_pass_epoch(self, epoch): + if self.args.virtual_epoch_size is None or self.args.virtual_data_size is None: + return None + # one epoch more for remaining data in each shard + virtual_epochs_per_shard = math.ceil( + self.args.virtual_data_size / self.args.virtual_epoch_size + ) + # note that fairseq epoch / shard_epoch starts from 1 + shard_epoch = (epoch - 1) // virtual_epochs_per_shard + 1 + return shard_epoch + + @classmethod + def prepare(cls, load_dictionary, args, **kargs): + args.left_pad_source = utils.eval_bool(args.left_pad_source) + args.left_pad_target = utils.eval_bool(args.left_pad_target) + + if not hasattr(args, "shuffle_instance"): + args.shuffle_instance = False + if args.langtoks is None: + args.langtoks = {} + if "main" not in args.langtoks: + src_langtok_spec = args.encoder_langtok if args.encoder_langtok else None + tgt_langtok_spec = "tgt" if args.decoder_langtok else None + args.langtoks["main"] = (src_langtok_spec, tgt_langtok_spec) + + def check_langs(langs, pairs): + messages = [] + for src, tgt in pairs: + if src not in langs or tgt not in langs: + messages.append( + f"language pair {src}-{tgt} contains languages " + "that are not in the language dictionary" + ) + if len(messages) > 0: + raise ValueError(" ".join(messages) + f"; langs: {langs}") + + if args.lang_pairs is None: + raise ValueError( + "--lang-pairs is required. List all the language pairs in the training objective." + ) + if isinstance(args.lang_pairs, str): + args.lang_pairs = args.lang_pairs.split(",") + if args.source_lang is not None or args.target_lang is not None: + training = False + else: + training = True + language_list = cls.load_langs(args, **kargs) + check_langs( + language_list, + ( + [p.split("-") for p in args.lang_pairs] + if training + else [(args.source_lang, args.target_lang)] + ), + ) + + # load dictionaries + if training: + extra_lang_pairs = ( + list( + {p for _, v in args.extra_lang_pairs.items() for p in v.split(",")} + ) + if args.extra_lang_pairs + else [] + ) + langs_to_load_dicts = sorted( + {x for p in args.lang_pairs + extra_lang_pairs for x in p.split("-")} + ) + else: + langs_to_load_dicts = sorted([args.source_lang, args.target_lang]) + + dicts = OrderedDict() + paths = utils.split_paths(args.data) + assert len(paths) > 0 + for lang in langs_to_load_dicts: + if args.fixed_dictionary is not None: + dicts[lang] = load_dictionary(args.fixed_dictionary) + else: + dicts[lang] = load_dictionary( + os.path.join(paths[0], "dict.{}.txt".format(lang)) + ) + augment_dictionary( + dictionary=dicts[lang], + language_list=language_list, + lang_tok_style=args.lang_tok_style, + langtoks_specs=args.langtoks_specs, + extra_data=args.extra_data, + ) + if len(dicts) > 0: + assert dicts[lang].pad() == dicts[langs_to_load_dicts[0]].pad() + assert dicts[lang].eos() == dicts[langs_to_load_dicts[0]].eos() + assert dicts[lang].unk() == dicts[langs_to_load_dicts[0]].unk() + logger.info("[{}] dictionary: {} types".format(lang, len(dicts[lang]))) + return language_list, dicts, training + + @classmethod + def create_lang_dictionary(cls, langs): + unk = "<unk>" + # hack to remove symbols other than unk as they are not needed by lang dict + lang_dict = Dictionary(pad=unk, eos=unk, unk=unk, bos=unk) + for lang in langs: + lang_dict.add_symbol(lang) + return lang_dict + + @classmethod + def get_langtok_index(cls, lang_tok, dic): + idx = dic.index(lang_tok) + assert ( + idx != dic.unk_index + ), "cannot find language token {} in the dictionary".format(lang_tok) + return idx + + def get_encoder_langtok(self, src_lang, tgt_lang, spec=None): + if spec is None: + return None + if spec and spec.startswith("src"): + if src_lang is None: + return None + langtok = get_lang_tok( + lang=src_lang, lang_tok_style=self.args.lang_tok_style, spec=spec + ) + else: + if tgt_lang is None: + return None + langtok = get_lang_tok( + lang=tgt_lang, lang_tok_style=self.args.lang_tok_style, spec=spec + ) + return self.get_langtok_index( + langtok, self.dicts[src_lang if src_lang else tgt_lang] + ) + + def get_decoder_langtok(self, tgt_lang, spec=None): + if spec is None: + return None + langtok = get_lang_tok( + lang=tgt_lang, lang_tok_style=self.args.lang_tok_style, spec=spec + ) + return self.get_langtok_index(langtok, self.dicts[tgt_lang]) + + @classmethod + def load_data(cls, path, vdict, impl): + dataset = data_utils.load_indexed_dataset(path, vdict, impl) + return dataset + + @classmethod + def split_exists(cls, split, src, tgt, lang, data_path, dataset_impl): + filename = os.path.join(data_path, "{}.{}-{}.{}".format(split, src, tgt, lang)) + return indexed_dataset.dataset_exists(filename, impl=dataset_impl) + + def load_lang_dataset( + self, + data_path, + split, + src, + src_dict, + tgt, + tgt_dict, + combine, + dataset_impl, + upsample_primary, + max_source_positions, + prepend_bos=False, + load_alignments=False, + truncate_source=False, + ): + + src_datasets = [] + tgt_datasets = [] + + for k in itertools.count(): + split_k = split + (str(k) if k > 0 else "") + + # infer langcode + if self.split_exists(split_k, src, tgt, src, data_path, dataset_impl): + prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, src, tgt)) + elif self.split_exists(split_k, tgt, src, src, data_path, dataset_impl): + prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, tgt, src)) + else: + if k > 0: + break + else: + logger.error( + f"Dataset not found: {data_path}, {split_k}, {src}, {tgt}" + ) + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, data_path) + ) + + src_dataset = self.load_data(prefix + src, src_dict, dataset_impl) + if truncate_source: + src_dataset = AppendTokenDataset( + TruncateDataset( + StripTokenDataset(src_dataset, src_dict.eos()), + max_source_positions - 1, + ), + src_dict.eos(), + ) + src_datasets.append(src_dataset) + tgt_datasets.append(self.load_data(prefix + tgt, tgt_dict, dataset_impl)) + + logger.info( + "{} {} {}-{} {} examples".format( + data_path, split_k, src, tgt, len(src_datasets[-1]) + ) + ) + + if not combine: + break + + assert len(src_datasets) == len(tgt_datasets) + + if len(src_datasets) == 1: + src_dataset, tgt_dataset = src_datasets[0], tgt_datasets[0] + else: + sample_ratios = [1] * len(src_datasets) + sample_ratios[0] = upsample_primary + src_dataset = ConcatDataset(src_datasets, sample_ratios) + tgt_dataset = ConcatDataset(tgt_datasets, sample_ratios) + + if prepend_bos: + assert hasattr(src_dict, "bos_index") and hasattr(tgt_dict, "bos_index") + src_dataset = PrependTokenDataset(src_dataset, src_dict.bos()) + tgt_dataset = PrependTokenDataset(tgt_dataset, tgt_dict.bos()) + + align_dataset = None + if load_alignments: + align_path = os.path.join( + data_path, "{}.align.{}-{}".format(split, src, tgt) + ) + if indexed_dataset.dataset_exists(align_path, impl=dataset_impl): + align_dataset = data_utils.load_indexed_dataset( + align_path, None, dataset_impl + ) + + return src_dataset, tgt_dataset, align_dataset + + def load_langpair_dataset( + self, + data_path, + split, + src, + src_dict, + tgt, + tgt_dict, + combine, + dataset_impl, + upsample_primary, + left_pad_source, + left_pad_target, + max_source_positions, + max_target_positions, + prepend_bos=False, + load_alignments=False, + truncate_source=False, + src_dataset_transform_func=lambda dataset: dataset, + tgt_dataset_transform_func=lambda dataset: dataset, + src_lang_id=None, + tgt_lang_id=None, + langpairs_sharing_datasets=None, + ): + norm_direction = "-".join(sorted([src, tgt])) + if langpairs_sharing_datasets is not None: + src_dataset = langpairs_sharing_datasets.get( + (data_path, split, norm_direction, src), "NotInCache" + ) + tgt_dataset = langpairs_sharing_datasets.get( + (data_path, split, norm_direction, tgt), "NotInCache" + ) + align_dataset = langpairs_sharing_datasets.get( + (data_path, split, norm_direction, src, tgt), "NotInCache" + ) + + # a hack: any one is not in cache, we need to reload them + if ( + langpairs_sharing_datasets is None + or src_dataset == "NotInCache" + or tgt_dataset == "NotInCache" + or align_dataset == "NotInCache" + or split != getattr(self.args, "train_subset", None) + ): + # source and target datasets can be reused in reversed directions to save memory + # reversed directions of valid and test data will not share source and target datasets + src_dataset, tgt_dataset, align_dataset = self.load_lang_dataset( + data_path, + split, + src, + src_dict, + tgt, + tgt_dict, + combine, + dataset_impl, + upsample_primary, + max_source_positions=max_source_positions, + prepend_bos=prepend_bos, + load_alignments=load_alignments, + truncate_source=truncate_source, + ) + src_dataset = src_dataset_transform_func(src_dataset) + tgt_dataset = tgt_dataset_transform_func(tgt_dataset) + if langpairs_sharing_datasets is not None: + langpairs_sharing_datasets[ + (data_path, split, norm_direction, src) + ] = src_dataset + langpairs_sharing_datasets[ + (data_path, split, norm_direction, tgt) + ] = tgt_dataset + langpairs_sharing_datasets[ + (data_path, split, norm_direction, src, tgt) + ] = align_dataset + if align_dataset is None: + # no align data so flag the reverse direction as well in sharing + langpairs_sharing_datasets[ + (data_path, split, norm_direction, tgt, src) + ] = align_dataset + else: + logger.info( + f"Reusing source and target datasets of [{split}] {tgt}-{src} for reversed direction: " + f"[{split}] {src}-{tgt}: src length={len(src_dataset)}; tgt length={len(tgt_dataset)}" + ) + + return LanguagePairDataset( + src_dataset, + src_dataset.sizes, + src_dict, + tgt_dataset, + tgt_dataset.sizes if tgt_dataset is not None else None, + tgt_dict, + left_pad_source=left_pad_source, + left_pad_target=left_pad_target, + align_dataset=align_dataset, + src_lang_id=src_lang_id, + tgt_lang_id=tgt_lang_id, + ) + + def src_dataset_tranform_func(self, src_lang, tgt_lang, dataset, spec=None): + if self.args.lang_tok_replacing_bos_eos: + # it is handled by self.alter_dataset_langtok + # TODO: Unifiy with alter_dataset_langtok + return dataset + if spec is None: + return dataset + tok = self.get_encoder_langtok(src_lang, tgt_lang, spec) + if tok: + return PrependTokenDataset(dataset, tok) + return dataset + + def tgt_dataset_tranform_func(self, source_lang, target_lang, dataset, spec=None): + if dataset is None: + # note that target dataset can be None during inference time + return None + if self.args.lang_tok_replacing_bos_eos: + # TODO: Unifiy with alter_dataset_langtok + # It is handled by self.alter_dataset_langtok. + # The complication in self.alter_dataset_langtok + # makes a unified framework difficult. + return dataset + # if not self.args.decoder_langtok: + if not spec: + return dataset + tok = self.get_decoder_langtok(target_lang, spec) + if tok: + return PrependTokenDataset(dataset, tok) + return dataset + + def alter_dataset_langtok( + self, + lang_pair_dataset, + src_eos=None, + src_lang=None, + tgt_eos=None, + tgt_lang=None, + src_langtok_spec=None, + tgt_langtok_spec=None, + ): + if src_langtok_spec is None and tgt_langtok_spec is None: + return lang_pair_dataset + + new_src_eos = None + if ( + src_langtok_spec is not None + and src_eos is not None + and (src_lang is not None or tgt_lang is not None) + ): + new_src_eos = self.get_encoder_langtok(src_lang, tgt_lang, src_langtok_spec) + else: + src_eos = None + + new_tgt_bos = None + if tgt_langtok_spec and tgt_eos is not None and tgt_lang is not None: + new_tgt_bos = self.get_decoder_langtok(tgt_lang, tgt_langtok_spec) + else: + tgt_eos = None + + return TransformEosLangPairDataset( + lang_pair_dataset, + src_eos=src_eos, + new_src_eos=new_src_eos, + tgt_bos=tgt_eos, + new_tgt_bos=new_tgt_bos, + ) + + def load_a_dataset( + self, + split, + data_path, + src, + src_dict, + tgt, + tgt_dict, + combine, + prepend_bos=False, + langpairs_sharing_datasets=None, + data_category=None, + **extra_kwargs, + ): + dataset_impl = self.args.dataset_impl + upsample_primary = self.args.upsample_primary + left_pad_source = self.args.left_pad_source + left_pad_target = self.args.left_pad_target + max_source_positions = self.args.max_source_positions + max_target_positions = self.args.max_target_positions + load_alignments = self.args.load_alignments + truncate_source = self.args.truncate_source + src_dataset_transform_func = self.src_dataset_tranform_func + tgt_dataset_transform_func = self.tgt_dataset_tranform_func + enable_lang_ids = self.args.enable_lang_ids + lang_dictionary = self.lang_dict + src_langtok_spec, tgt_langtok_spec = extra_kwargs["langtok_spec"] + + src_langtok = self.get_encoder_langtok(src, tgt, src_langtok_spec) + tgt_langtok = self.get_decoder_langtok(tgt, tgt_langtok_spec) + logger.info( + f"{data_category}:{src}-{tgt} src_langtok: {src_langtok}; tgt_langtok: {tgt_langtok}" + ) + + langpair_ds = self.load_langpair_dataset( + data_path, + split, + src, + src_dict, + tgt, + tgt_dict, + combine, + dataset_impl, + upsample_primary, + left_pad_source, + left_pad_target, + max_source_positions, + max_target_positions, + prepend_bos, + load_alignments, + truncate_source, + src_dataset_transform_func=lambda dataset: src_dataset_transform_func( + src, tgt, dataset, src_langtok_spec + ), + tgt_dataset_transform_func=lambda dataset: tgt_dataset_transform_func( + src, tgt, dataset, tgt_langtok_spec + ), + src_lang_id=_lang_id(lang_dictionary, src) + if enable_lang_ids and lang_dictionary is not None + else None, + tgt_lang_id=_lang_id(lang_dictionary, tgt) + if enable_lang_ids and lang_dictionary is not None + else None, + langpairs_sharing_datasets=langpairs_sharing_datasets, + ) + # TODO: handle modified lang toks for mined data and dae data + if self.args.lang_tok_replacing_bos_eos: + ds = self.alter_dataset_langtok( + langpair_ds, + src_eos=self.dicts[src if src else tgt].eos(), + src_lang=src, + tgt_eos=self.dicts[tgt].eos(), + tgt_lang=tgt, + src_langtok_spec=src_langtok_spec, + tgt_langtok_spec=tgt_langtok_spec, + ) + else: + ds = langpair_ds + return ds + + def load_split_langpair_datasets(self, split, data_param_list): + datasets = [] + langpairs_sharing_datasets = ( + {} if self.args.enable_reservsed_directions_shared_datasets else None + ) + for param in data_param_list: + ds = self.load_a_dataset( + split=split, + langpairs_sharing_datasets=langpairs_sharing_datasets, + **param, + ) + datasets.append(ds) + return datasets + + def get_data_paths_and_lang_pairs(self, split): + datapaths = {"main": self.args.data} + lang_pairs = {"main": self.lang_pairs} + if split == getattr(self.args, "train_subset", None): + # only training data can have extra data and extra language pairs + if self.args.extra_data: + extra_datapaths = self.args.extra_data + datapaths.update(extra_datapaths) + if self.args.extra_lang_pairs: + extra_lang_pairs = { + k: v.split(",") for k, v in self.args.extra_lang_pairs.items() + } + lang_pairs.update(extra_lang_pairs) + return datapaths, lang_pairs + + @classmethod + def get_dataset_key(cls, data_category, src, tgt): + return f"{data_category}:{src}-{tgt}" + + @classmethod + def _get_shard_num_dict(cls, split, paths): + shards = defaultdict(int) + for path in paths: + files = PathManager.ls(path) + directions = set() + for f in files: + if f.startswith(split) and f.endswith(".idx"): + # idx files of the form "{split}.{src}-{tgt}.{lang}.idx" + direction = f.split(".")[-3] + directions.add(direction) + for direction in directions: + shards[direction] += 1 + return shards + + def get_split_num_data_shards(self, split): + if split in self._num_shards_dict: + return self._num_shards_dict[split] + num_shards_dict = {} + data_paths, lang_pairs = self.get_data_paths_and_lang_pairs(split) + + for data_category, paths in data_paths.items(): + if data_category not in lang_pairs: + continue + paths = utils.split_paths(paths) + shards_dict = self._get_shard_num_dict(split, paths) + lang_dirs = [ + lang_pair.split("-") for lang_pair in lang_pairs[data_category] + ] + lang_dirs = [x if len(x) > 1 else (x[0], x[0]) for x in lang_dirs] + for src, tgt in lang_dirs: + key = self.get_dataset_key(data_category, src, tgt) + if "mono_" in data_category: + # monolingual data requires tgt only + assert src is None or src == tgt, ( + f"error: src={src}, " + "tgt={tgt} for data_category={data_category}" + ) + num_shards_dict[key] = shards_dict[tgt] + else: + if f"{src}-{tgt}" in shards_dict: + num_shards_dict[key] = shards_dict[f"{src}-{tgt}"] + elif f"{tgt}-{src}" in shards_dict: + # follow the fairseq tradition to use reversed direction data if it is not available + num_shards_dict[key] = shards_dict[f"{tgt}-{src}"] + self._num_shards_dict[split] = num_shards_dict + logger.info(f"[{split}] num of shards: {num_shards_dict}") + return num_shards_dict + + @classmethod + def get_shard_id(cls, num_shards, epoch, shard_epoch=None): + shard = epoch if shard_epoch is None else shard_epoch + shard = (shard - 1) % num_shards + return shard + + def get_split_data_path(self, paths, epoch, shard_epoch, num_shards): + path = paths[self.get_shard_id(num_shards, epoch, shard_epoch)] + return path + + def get_split_data_param_list(self, split, epoch, shard_epoch=None): + # TODO: to extend with extra datasets and keys and loop over different shard data paths + param_list = [] + data_paths, lang_pairs = self.get_data_paths_and_lang_pairs(split) + logger.info(f"langtoks settings: {self.args.langtoks}") + split_num_shards_dict = self.get_split_num_data_shards(split) + for data_category, paths in data_paths.items(): + if data_category not in lang_pairs: + continue + paths = utils.split_paths(paths) + assert len(paths) > 0 + if len(paths) > 1: + self._has_sharded_data = True + if split != getattr(self.args, "train_subset", None): + # if not training data set, use the first shard for valid and test + paths = paths[:1] + + if data_category in self.args.langtoks: + lang_tok_spec = self.args.langtoks[data_category] + else: + # default to None + lang_tok_spec = (None, None) + + # infer langcode + lang_dirs = [ + lang_pair.split("-") for lang_pair in lang_pairs[data_category] + ] + lang_dirs = [x if len(x) > 1 else (x[0], x[0]) for x in lang_dirs] + for src, tgt in lang_dirs: + assert src is not None or data_category == "mono_dae", ( + f"error: src={src}, " "tgt={tgt} for data_category={data_category}" + ) + # logger.info(f"preparing param for {data_category}: {src} - {tgt}") + key = self.get_dataset_key(data_category, src, tgt) + data_path = self.get_split_data_path( + paths, epoch, shard_epoch, split_num_shards_dict[key] + ) + param_list.append( + { + "key": key, + "data_path": data_path, + "split": split, + "src": src, + "src_dict": self.dicts[src] + if src and data_category != "mono_dae" + else None, + "tgt": tgt, + "tgt_dict": self.dicts[tgt], + "data_category": data_category, + "langtok_spec": lang_tok_spec, + } + ) + return param_list + + def get_train_dataset_sizes( + self, data_param_list, datasets, epoch, shard_epoch=None + ): + num_shards = [ + self.get_split_num_data_shards(param["split"])[param["key"]] + for param in data_param_list + ] + data_sizes = [] + for (key, d), num_shard in zip(datasets, num_shards): + my_data_sizes = self._training_data_sizes[key] + shard_ind = self.get_shard_id(num_shard, epoch, shard_epoch) + if shard_ind not in my_data_sizes: + my_data_sizes[shard_ind] = len(d) + known_size = max(my_data_sizes.values()) + data_sizes.append( + # If we don't know the data size of the shard yet, + # use the the max known data size to approximate. + # Note that we preprocess shards by a designated shard size + # and put any remaining data at the end into the last shard so + # the max shard size approximation is almost correct before loading + # the last shard; after loading the last shard, it will have the + # exact data sizes of the whole data size. + (key, sum(my_data_sizes.get(i, known_size) for i in range(num_shard))) + ) + logger.info( + f"estimated total data sizes of all shards used in sampling ratios: {data_sizes}. " + "Note that if the data a shard has not been loaded yet, use the max known data size to approximate" + ) + return [s for _, s in data_sizes] + + def get_train_sampling_ratios( + self, data_param_list, datasets, epoch=1, shard_epoch=None + ): + data_sizes = self.get_train_dataset_sizes( + data_param_list, datasets, epoch, shard_epoch + ) + sampling_func = self.sampling_method.sampling_method_selector() + sample_ratios = sampling_func(data_sizes) if sampling_func is not None else None + return sample_ratios + + def get_sampling_ratios(self, data_param_list, datasets, epoch, shard_epoch=None): + if self.args.sampling_weights_from_file: + weights = load_sampling_weights(self.args.sampling_weights_from_file) + sample_ratios = [weights[k] for k, _ in datasets] + logger.info( + "| ignoring --sampling-weights when loadding sampling weights " + f"from file {self.args.sampling_weights_from_file}" + ) + elif self.args.sampling_weights: + sample_ratios = [self.args.sampling_weights[k] for k, _ in datasets] + else: + sample_ratios = self.get_train_sampling_ratios( + data_param_list, datasets, epoch, shard_epoch + ) + + if sample_ratios is not None: + logger.info( + "| Upsample ratios: {}".format( + list(zip(map(lambda x: x["key"], data_param_list), sample_ratios)) + ) + ) + assert len(sample_ratios) == len(datasets) + return sample_ratios + + def load_split_datasets( + self, split, training, epoch=1, combine=False, shard_epoch=None, **kwargs + ): + data_param_list = self.get_split_data_param_list( + split, epoch, shard_epoch=shard_epoch + ) + langpairs_sharing_datasets = ( + {} if self.args.enable_reservsed_directions_shared_datasets else None + ) + datasets = [ + ( + param["key"], + self.load_a_dataset( + combine=combine, + langpairs_sharing_datasets=langpairs_sharing_datasets, + **param, + ), + ) + for param in data_param_list + ] + return datasets, data_param_list + + def load_into_concat_dataset(self, split, datasets, data_param_list): + if self.args.lang_tok_replacing_bos_eos: + # TODO: to investigate why TransformEosLangPairDataset doesn't work with ConcatDataset + return SampledMultiDataset( + OrderedDict(datasets), + sampling_ratios=None, + eval_key=None, + collate_format=CollateFormat.single, + virtual_size=None, + split=split, + ) + return ConcatDataset([d for _, d in datasets]) + + def load_sampled_multi_epoch_dataset( + self, split, training, epoch=0, combine=False, shard_epoch=None, **kwargs + ): + datasets, data_param_list = self.load_split_datasets( + split, training, epoch, combine, shard_epoch=shard_epoch, **kwargs + ) + if training and split == getattr(self.args, "train_subset", None): + sample_ratios = self.get_sampling_ratios(data_param_list, datasets, epoch) + return SampledMultiEpochDataset( + OrderedDict(datasets), + epoch=epoch, + shard_epoch=shard_epoch, + # valid and test datasets will be degenerate to concating datasets: + sampling_ratios=sample_ratios, + eval_key=None, + collate_format=CollateFormat.single, + virtual_size=self.args.virtual_data_size, + split=split, + virtual_epoch_size=self.args.virtual_epoch_size, + # if not using lang_tok altering, simplified to use the same collater + shared_collater=self._shared_collater(), + ) + else: + return self.load_into_concat_dataset(split, datasets, data_param_list) diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_utils.py b/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_utils.py new file mode 100644 index 00000000..b4e0f982 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/multilingual_utils.py @@ -0,0 +1,63 @@ +from enum import Enum +from typing import Dict, List, Optional, Sequence + +import torch +from fairseq.data import Dictionary + + +class EncoderLangtok(Enum): + """ + Prepend to the beginning of source sentence either the + source or target language token. (src/tgt). + """ + + src = "src" + tgt = "tgt" + + +class LangTokSpec(Enum): + main = "main" + mono_dae = "mono_dae" + + +class LangTokStyle(Enum): + multilingual = "multilingual" + mbart = "mbart" + + +@torch.jit.export +def get_lang_tok( + lang: str, lang_tok_style: str, spec: str = LangTokSpec.main.value +) -> str: + # TOKEN_STYLES can't be defined outside this fn since it needs to be + # TorchScriptable. + TOKEN_STYLES: Dict[str, str] = { + LangTokStyle.mbart.value: "[{}]", + LangTokStyle.multilingual.value: "__{}__", + } + + if spec.endswith("dae"): + lang = f"{lang}_dae" + elif spec.endswith("mined"): + lang = f"{lang}_mined" + style = TOKEN_STYLES[lang_tok_style] + return style.format(lang) + + +def augment_dictionary( + dictionary: Dictionary, + language_list: List[str], + lang_tok_style: str, + langtoks_specs: Sequence[str] = (LangTokSpec.main.value,), + extra_data: Optional[Dict[str, str]] = None, +) -> None: + for spec in langtoks_specs: + for language in language_list: + dictionary.add_symbol( + get_lang_tok(lang=language, lang_tok_style=lang_tok_style, spec=spec) + ) + + if lang_tok_style == LangTokStyle.mbart.value or ( + extra_data is not None and LangTokSpec.mono_dae.value in extra_data + ): + dictionary.add_symbol("<mask>") diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_dataset.py b/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_dataset.py new file mode 100644 index 00000000..3f544b09 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_dataset.py @@ -0,0 +1,458 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import datetime +import hashlib +import logging +import time +from bisect import bisect_right +from collections import OrderedDict, defaultdict +from enum import Enum +from typing import List + +import numpy as np +import torch +from fairseq import distributed_utils +from fairseq.data import FairseqDataset, data_utils + + +def get_time_gap(s, e): + return ( + datetime.datetime.fromtimestamp(e) - datetime.datetime.fromtimestamp(s) + ).__str__() + + +logger = logging.getLogger(__name__) + + +def default_virtual_size_func(datasets, ratios, max_scale_up=1.5): + sizes = [len(d) for d in datasets] + if ratios is None: + return sum(sizes) + largest_idx = np.argmax(sizes) + largest_r = ratios[largest_idx] + largest_s = sizes[largest_idx] + # set virtual sizes relative to the largest dataset + virtual_sizes = [(r / largest_r) * largest_s for r in ratios] + vsize = sum(virtual_sizes) + max_size = sum(sizes) * max_scale_up + return int(vsize if vsize < max_size else max_size) + + +class CollateFormat(Enum): + single = 1 + ordered_dict = 2 + + +class SampledMultiDataset(FairseqDataset): + """Samples from multiple sub-datasets according to given sampling ratios. + Args: + datasets ( + List[~torch.utils.data.Dataset] + or OrderedDict[str, ~torch.utils.data.Dataset] + ): datasets + sampling_ratios (List[float]): list of probability of each dataset to be sampled + (default: None, which corresponds to concatenating all dataset together). + seed (int): RNG seed to use (default: 2). + epoch (int): starting epoch number (default: 1). + eval_key (str, optional): a key used at evaluation time that causes + this instance to pass-through batches from *datasets[eval_key]*. + collate_format (CollateFormat): collater output format, either CollateFormat.ordered_dict or + CollateFormat.single (default: CollateFormat.single) where CollateFormat.single configures + the collater to output batches of data mixed from all sub-datasets, + and CollateFormat.ordered_dict configures the collater to output a dictionary of batches indexed by keys + of sub-datasets. + Note that not all sub-datasets will present in a single batch in both formats. + virtual_size (int, or callable): the expected virtual size of the dataset (default: default_virtual_size_func). + split (str): the split of the data, e.g. 'train', 'valid' or 'test'. + shared_collater (bool): whether or not to all sub-datasets have the same collater. + shuffle (bool): whether or not to shuffle data (default: True). + """ + + def __init__( + self, + datasets, + sampling_ratios=None, + seed=2, + epoch=1, + eval_key=None, + collate_format=CollateFormat.single, + virtual_size=default_virtual_size_func, + split="", + shared_collater=False, + shuffle=True, + ): + super().__init__() + self.shared_collater = shared_collater + self.shuffle = shuffle + + if isinstance(datasets, OrderedDict): + self.keys = list(datasets.keys()) + datasets = list(datasets.values()) + elif isinstance(datasets, List): + self.keys = list(range(len(datasets))) + else: + raise AssertionError() + self.datasets = datasets + self.split = split + + self.eval_key = eval_key + if self.eval_key is not None: + self.collate_format = CollateFormat.single + else: + self.collate_format = collate_format + + self.seed = seed + self._cur_epoch = None + + self.cumulated_sizes = None + # self.datasets[k][self._cur_indices[i]] is the data item i in this sampled dataset + # namely, data item i is sampled from the kth sub-dataset self.datasets[k] + # where self.cumulated_sizes[k-1] <= i < self.cumulated_sizes[k] + self._cur_indices = None + + self._sizes = None + self.virtual_size_per_dataset = None + # caching properties + self._reset_cached_properties() + self.setup_sampling(sampling_ratios, virtual_size) + self.set_epoch(epoch) + + def _clean_if_not_none(self, var_list): + for v in var_list: + if v is not None: + del v + + def _reset_cached_properties(self): + self._clean_if_not_none([self._sizes, self._cur_indices]) + self._sizes = None + self._cur_indices = None + + def setup_sampling(self, sample_ratios, virtual_size): + sizes = [len(d) for d in self.datasets] + if sample_ratios is None: + # default back to concating datasets + self.sample_ratios = None + self.virtual_size = sum(sizes) + else: + if not isinstance(sample_ratios, np.ndarray): + sample_ratios = np.array(sample_ratios) + self.sample_ratios = sample_ratios + virtual_size = ( + default_virtual_size_func if virtual_size is None else virtual_size + ) + self.virtual_size = ( + virtual_size(self.datasets, self.sample_ratios) + if callable(virtual_size) + else virtual_size + ) + + def adjust_sampling(self, epoch, sampling_ratios, virtual_size): + if sampling_ratios is not None: + sampling_ratios = self._sync_sample_ratios(sampling_ratios) + self.setup_sampling(sampling_ratios, virtual_size) + + def _sync_sample_ratios(self, ratios): + # in case the ratios are not precisely the same across processes + # also to ensure every procresses update the ratios in the same pace + ratios = torch.DoubleTensor(ratios) + if torch.distributed.is_initialized(): + if torch.cuda.is_available(): + distributed_utils.all_reduce(ratios.cuda()) + else: + distributed_utils.all_reduce(ratios) + ret = ratios.cpu() + ret = ret.numpy() + return ret + + def random_choice_in_dataset(self, rng, dataset, choice_size): + if hasattr(dataset, "random_choice_in_dataset"): + return dataset.random_choice_in_dataset(rng, choice_size) + dataset_size = len(dataset) + return rng.choice( + dataset_size, choice_size, replace=(choice_size > dataset_size) + ) + + def get_virtual_indices(self, rng, datasets, sample_ratios, virtual_size): + def get_counts(sample_ratios): + counts = np.array([virtual_size * r for r in sample_ratios], dtype=np.int64) + diff = virtual_size - counts.sum() + assert diff >= 0 + # due to round-offs, the size might not match the desired sizes + if diff > 0: + dataset_indices = rng.choice( + len(sample_ratios), size=diff, p=sample_ratios + ) + for i in dataset_indices: + counts[i] += 1 + return counts + + def get_in_dataset_indices(datasets, sizes, sample_ratios): + counts = get_counts(sample_ratios) + # uniformally sample desired counts for each dataset + # if the desired counts are large, sample with replacement: + indices = [ + self.random_choice_in_dataset(rng, d, c) + for c, d in zip(counts, datasets) + ] + return indices + + sizes = [len(d) for d in datasets] + if sample_ratios is None: + # default back to concating datasets + in_dataset_indices = [list(range(s)) for s in sizes] + virtual_sizes_per_dataset = sizes + else: + ratios = sample_ratios / sample_ratios.sum() + in_dataset_indices = get_in_dataset_indices(datasets, sizes, ratios) + virtual_sizes_per_dataset = [len(d) for d in in_dataset_indices] + virtual_sizes_per_dataset = np.array(virtual_sizes_per_dataset, np.int64) + cumulative_sizes = np.cumsum(virtual_sizes_per_dataset) + assert sum(virtual_sizes_per_dataset) == virtual_size + assert cumulative_sizes[-1] == virtual_size + if virtual_size < sum(sizes): + logger.warning( + f"virtual data size ({virtual_size}) is less than real data size ({sum(sizes)})." + " If virtual size << real data size, there could be data coverage issue." + ) + in_dataset_indices = np.hstack(in_dataset_indices) + return in_dataset_indices, cumulative_sizes, virtual_sizes_per_dataset + + def _get_dataset_and_index(self, index): + i = bisect_right(self.cumulated_sizes, index) + return i, self._cur_indices[index] + + def __getitem__(self, index): + # self.__getitem__(index) returns self.datasets[k][self._cur_indices[index]] + # where k satisfies self.cumulated_sizes[k - 1] <= k < self.cumulated_sizes[k] + ds_idx, ds_sample_idx = self._get_dataset_and_index(index) + ret = (ds_idx, self.datasets[ds_idx][ds_sample_idx]) + return ret + + def num_tokens(self, index): + return self.sizes[index].max() + + def size(self, index): + return self.sizes[index] + + def __len__(self): + return self.virtual_size + + def collater(self, samples, **extra_args): + """Merge a list of samples to form a mini-batch.""" + if len(samples) == 0: + return None + if self.collate_format == "ordered_dict": + collect_samples = [[] for _ in range(len(self.datasets))] + for (i, sample) in samples: + collect_samples[i].append(sample) + batch = OrderedDict( + [ + (self.keys[i], dataset.collater(collect_samples[i])) + for i, (key, dataset) in enumerate(zip(self.keys, self.datasets)) + if len(collect_samples[i]) > 0 + ] + ) + elif self.shared_collater: + batch = self.datasets[0].collater([s for _, s in samples]) + else: + samples_dict = defaultdict(list) + pad_to_length = ( + defaultdict(int) + if "pad_to_length" not in extra_args + else extra_args["pad_to_length"] + ) + for ds_idx, s in samples: + pad_to_length["source"] = max( + pad_to_length["source"], s["source"].size(0) + ) + if s["target"] is not None: + pad_to_length["target"] = max( + pad_to_length["target"], s["target"].size(0) + ) + samples_dict[ds_idx].append(s) + batches = [ + self.datasets[i].collater(samples_dict[i], pad_to_length=pad_to_length) + for i in range(len(self.datasets)) + if len(samples_dict[i]) > 0 + ] + + def straight_data(tensors): + batch = torch.cat(tensors, dim=0) + return batch + + src_lengths = straight_data( + [b["net_input"]["src_lengths"] for b in batches] + ) + src_lengths, sort_order = src_lengths.sort(descending=True) + + def straight_order(tensors): + batch = straight_data(tensors) + return batch.index_select(0, sort_order) + + batch = { + "id": straight_order([b["id"] for b in batches]), + "nsentences": sum(b["nsentences"] for b in batches), + "ntokens": sum(b["ntokens"] for b in batches), + "net_input": { + "src_tokens": straight_order( + [b["net_input"]["src_tokens"] for b in batches] + ), + "src_lengths": src_lengths, + }, + "target": straight_order([b["target"] for b in batches]) + if batches[0]["target"] is not None + else None, + } + if "prev_output_tokens" in batches[0]["net_input"]: + batch["net_input"]["prev_output_tokens"] = straight_order( + [b["net_input"]["prev_output_tokens"] for b in batches] + ) + if "src_lang_id" in batches[0]["net_input"]: + batch["net_input"]["src_lang_id"] = straight_order( + [b["net_input"]["src_lang_id"] for b in batches] + ) + if "tgt_lang_id" in batches[0]: + batch["tgt_lang_id"] = straight_order( + [b["tgt_lang_id"] for b in batches] + ) + return batch + + @property + def sizes(self): + if self._sizes is not None: + return self._sizes + start_time = time.time() + in_sub_dataset_indices = [ + self._cur_indices[ + 0 if i == 0 else self.cumulated_sizes[i - 1] : self.cumulated_sizes[i] + ] + for i in range(len(self.datasets)) + ] + sub_dataset_sizes = [ + d.sizes[indices] + for d, indices in zip(self.datasets, in_sub_dataset_indices) + ] + self._sizes = np.vstack(sub_dataset_sizes) + logger.info(f"sizes() calling time: {get_time_gap(start_time, time.time())}") + return self._sizes + + def ordered_indices(self): + if self.shuffle: + indices = np.random.permutation(len(self)) + else: + indices = np.arange(len(self)) + + sizes = self.sizes + tgt_sizes = sizes[:, 1] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else None + src_sizes = ( + sizes[:, 0] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else sizes + ) + + # sort by target length, then source length + if tgt_sizes is not None: + indices = indices[np.argsort(tgt_sizes[indices], kind="mergesort")] + sort_indices = indices[np.argsort(src_sizes[indices], kind="mergesort")] + return sort_indices + + def prefetch(self, indices): + prefetch_indices = [[] for _ in range(len(self.datasets))] + for i in indices: + ds_idx, ds_sample_idx = self._get_dataset_and_index(i) + prefetch_indices[ds_idx].append(ds_sample_idx) + for i in range(len(prefetch_indices)): + self.datasets[i].prefetch(prefetch_indices[i]) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return False + + def set_epoch(self, epoch): + super().set_epoch(epoch) + if epoch == self._cur_epoch: + # re-enter so return + return + for d in self.datasets: + if hasattr(d, "set_epoch"): + d.set_epoch(epoch) + self._cur_epoch = epoch + self._establish_virtual_datasets() + + def _establish_virtual_datasets(self): + if self.sample_ratios is None and self._cur_indices is not None: + # not a samping dataset, no need to resample if indices are already established + return + self._reset_cached_properties() + + start_time = time.time() + # Generate a weighted sample of indices as a function of the + # random seed and the current epoch. + rng = np.random.RandomState( + [ + int( + hashlib.sha1( + str(self.__class__.__name__).encode("utf-8") + ).hexdigest(), + 16, + ) + % (2 ** 32), + self.seed % (2 ** 32), # global seed + self._cur_epoch, # epoch index, + ] + ) + self._clean_if_not_none( + [self.cumulated_sizes, self.virtual_size_per_dataset, self._sizes] + ) + self._sizes = None + + indices, cumulated_sizes, virtual_size_per_dataset = self.get_virtual_indices( + rng, self.datasets, self.sample_ratios, self.virtual_size + ) + self._cur_indices = indices + self.cumulated_sizes = cumulated_sizes + self.virtual_size_per_dataset = virtual_size_per_dataset + + raw_sizes = [len(d) for d in self.datasets] + sampled_sizes = self.virtual_size_per_dataset + logger.info( + f"[{self.split}] Raw sizes: {str(dict(zip(self.keys, raw_sizes)))}; " + f"raw total size: {sum(raw_sizes)}" + ) + logger.info( + f"[{self.split}] Resampled sizes: {str(dict(zip(self.keys, sampled_sizes)))}; " + f"resampled total size: {sum(sampled_sizes)}" + ) + if self.sample_ratios is not None: + logger.info( + f"[{self.split}] Upsampling ratios: {str(dict(zip(self.keys, self.sample_ratios)))}" + ) + else: + logger.info(f"[{self.split}] A concat dataset") + logger.info( + f"[{self.split}] virtual dataset established time: {get_time_gap(start_time, time.time())}" + ) + + def filter_indices_by_size(self, indices, max_sizes): + """Filter a list of sample indices. Remove those that are longer + than specified in max_sizes. + + Args: + indices (np.array): original array of sample indices + max_sizes (int or list[int] or tuple[int]): max sample size, + can be defined separately for src and tgt (then list or tuple) + + Returns: + np.array: filtered sample array + list: list of removed indices + """ + sizes = self.sizes + tgt_sizes = sizes[:, 1] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else None + src_sizes = ( + sizes[:, 0] if len(sizes.shape) > 0 and sizes.shape[1] > 1 else sizes + ) + + return data_utils.filter_paired_dataset_indices_by_size( + src_sizes, tgt_sizes, indices, max_sizes + ) diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_epoch_dataset.py b/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_epoch_dataset.py new file mode 100644 index 00000000..17387b2f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/sampled_multi_epoch_dataset.py @@ -0,0 +1,199 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import hashlib +import logging +import math + +import numpy as np +from fairseq.data import SampledMultiDataset + +from .sampled_multi_dataset import CollateFormat, default_virtual_size_func + + +logger = logging.getLogger(__name__) + + +class SampledMultiEpochDataset(SampledMultiDataset): + """Samples from multiple sub-datasets according to sampling ratios + using virtual epoch sizes to speed up dataloading. + Args: + datasets ( + List[~torch.utils.data.Dataset] + or OrderedDict[str, ~torch.utils.data.Dataset] + ): datasets + sampling_ratios (List[float]): list of probability of each dataset to be sampled + (default: None, which corresponds to concating all dataset together). + seed (int): RNG seed to use (default: 2). + epoch (int): starting epoch number (default: 1). + eval_key (str, optional): a key used at evaluation time that causes + this instance to pass-through batches from *datasets[eval_key]*. + collate_format (CollateFormat): collater output format, either CollateFormat.ordered_dict or + CollateFormat.single (default: CollateFormat.single) where CollateFormat.single configures + the collater to output batches of data mixed from all sub-datasets, + and CollateFormat.ordered_dict configures the collater to output a dictionary of batches indexed by keys + of sub-datasets. + Note that not all sub-datasets will present in a single batch in both formats. + virtual_size (int, or callable): the expected virtual size of the dataset (default: default_virtual_size_func). + split (str): the split of the data, e.g. 'train', 'valid' or 'test'. + virtual_epoch_size (int): virtual epoch size, the dataset will go through the data by + this virtual epoch size one by one to speed up data loading, e.g. indicing and filtering + can be performed whenever a virtual epoch is loaded without waiting for the whole dataset to be loaded. + shared_collater (bool): whether or not to all sub-datasets have the same collater. + shard_epoch (int): the real epoch number for shard selection. + shuffle (bool): whether or not to shuffle data (default: True). + """ + + def __init__( + self, + datasets, + sampling_ratios=None, + seed=2, + epoch=1, + eval_key=None, + collate_format=CollateFormat.single, + virtual_size=default_virtual_size_func, + split="", + virtual_epoch_size=None, + shared_collater=False, + shard_epoch=1, + shuffle=True, + ): + self.virtual_epoch_size = virtual_epoch_size + self._current_epoch_start_index = None + self._random_global_indices = None + self.shard_epoch = shard_epoch if shard_epoch is not None else 1 + self.load_next_shard = None + self._epoch_sizes = None + super().__init__( + datasets=datasets, + sampling_ratios=sampling_ratios, + seed=seed, + epoch=epoch, + eval_key=eval_key, + collate_format=collate_format, + virtual_size=virtual_size, + split=split, + shared_collater=shared_collater, + shuffle=shuffle, + ) + + def _setup(self, epoch): + self.virtual_epoch_size = ( + self.virtual_epoch_size + if self.virtual_epoch_size is not None + else self.virtual_size + ) + if self.virtual_epoch_size > self.virtual_size: + logger.warning( + f"virtual epoch size {self.virtual_epoch_size} " + f"is greater than virtual dataset size {self.virtual_size}" + ) + self.virtual_epoch_size = self.virtual_size + self.num_virtual_epochs = math.ceil(self.virtual_size / self.virtual_epoch_size) + self._current_epoch_start_index = self._get_epoch_start_index(epoch) + logger.info( + f"virtual epoch size {self.virtual_epoch_size}; virtual dataset size {self.virtual_size}" + ) + + def _map_epoch_index_to_global(self, index): + index = self._current_epoch_start_index + index + # add randomness + return self._random_global_indices[index] + + @property + def sizes(self): + if self._epoch_sizes is not None: + return self._epoch_sizes + _sizes = super().sizes + indices = self._random_global_indices[ + self._current_epoch_start_index : self._current_epoch_start_index + + len(self) + ] + self._epoch_sizes = _sizes[indices] + # del super()._sizes to save memory + del self._sizes + self._sizes = None + return self._epoch_sizes + + def _get_dataset_and_index(self, index): + i = self._map_epoch_index_to_global(index) + return super()._get_dataset_and_index(i) + + def __len__(self): + return ( + self.virtual_epoch_size + if self._current_epoch_start_index + self.virtual_epoch_size + < self.virtual_size + else self.virtual_size - self._current_epoch_start_index + ) + + def set_epoch(self, epoch): + if self._current_epoch_start_index is None: + # initializing epoch idnices of a virtual dataset + self._setup(epoch) + self._next_virtual_epoch(epoch) + else: + # working on already intialized epoch indices + if epoch == self._cur_epoch: + # re-enter so return + return + self._next_virtual_epoch(epoch) + + def _get_epoch_start_index(self, epoch): + assert epoch >= 1 # fairseq is using 1-based epoch everywhere + return ((epoch - 1) % self.num_virtual_epochs) * self.virtual_epoch_size + + def _next_global_indices(self, epoch): + rng = np.random.RandomState( + [ + int( + hashlib.sha1( + str(self.__class__.__name__).encode("utf-8") + ).hexdigest(), + 16, + ) + % (2 ** 32), + self.seed % (2 ** 32), # global seed + epoch, # epoch index, + ] + ) + del self._random_global_indices + self._random_global_indices = rng.choice( + self.virtual_size, self.virtual_size, replace=False + ) + if self.load_next_shard is None: + self.load_next_shard = False + else: + # increase shard epoch for next loading + self.shard_epoch += 1 + self.load_next_shard = True + logger.info( + "to load next epoch/shard in next load_dataset: " + f"epoch={epoch}/shard_epoch={self.shard_epoch}" + ) + + def _next_virtual_epoch(self, epoch): + index = self._get_epoch_start_index(epoch) + if index == 0 or self._random_global_indices is None: + # need to start from the beginning, + # so call super().set_epoch(epoch) to establish the global virtual indices + logger.info( + "establishing a new set of global virtual indices for " + f"epoch={epoch}/shard_epoch={self.shard_epoch}" + ) + super().set_epoch(epoch) + self._next_global_indices(epoch) + else: + self._cur_epoch = epoch + + # reset cache sizes and ordered_indices for the epoch after moving to a new epoch + self._clean_if_not_none( + [ + self._epoch_sizes, + ] + ) + self._epoch_sizes = None + self._current_epoch_start_index = index diff --git a/fairseq-tools/fairseq/fairseq/data/multilingual/sampling_method.py b/fairseq-tools/fairseq/fairseq/data/multilingual/sampling_method.py new file mode 100644 index 00000000..140c68f0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/multilingual/sampling_method.py @@ -0,0 +1,78 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from typing import List + + +logger = logging.getLogger(__name__) + + +def uniform(dataset_sizes: List[int]): + return [1.0] * len(dataset_sizes) + + +def temperature_sampling(dataset_sizes, temp): + total_size = sum(dataset_sizes) + return [(size / total_size) ** (1.0 / temp) for size in dataset_sizes] + + +def make_temperature_sampling(temp=1.0): + def sampling_func(dataset_sizes): + return temperature_sampling(dataset_sizes, temp) + + return sampling_func + + +def make_ratio_sampling(ratios): + def sampling_func(dataset_sizes): + return ratios + + return sampling_func + + +class SamplingMethod: + @staticmethod + def add_arguments(parser): + parser.add_argument( + "--sampling-method", + choices=[ + "uniform", + "temperature", + "concat", + "RoundRobin", + ], + type=str, + default="concat", + help="The method to sample data per language pairs", + ) + parser.add_argument( + "--sampling-temperature", + default=1.5, + type=float, + help="only work with --sampling-method temperature", + ) + + @staticmethod + def build_sampler(args, task): + return SamplingMethod(args, task) + + def __init__(self, args, task): + self.args = args + self.task = task + + def is_adaptive(self): + return False + + def sampling_method_selector(self): + args = self.args + logger.info(f"selected sampler: {args.sampling_method}") + if args.sampling_method == "uniform": + return uniform + elif args.sampling_method == "temperature" or self.is_adaptive(): + return make_temperature_sampling(float(args.sampling_temperature)) + else: + # default to concating all data set together + return None diff --git a/fairseq-tools/fairseq/fairseq/data/nested_dictionary_dataset.py b/fairseq-tools/fairseq/fairseq/data/nested_dictionary_dataset.py new file mode 100644 index 00000000..52e74abd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/nested_dictionary_dataset.py @@ -0,0 +1,125 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import OrderedDict + +import torch +from torch.utils.data.dataloader import default_collate + +from . import FairseqDataset + + +def _flatten(dico, prefix=None): + """Flatten a nested dictionary.""" + new_dico = OrderedDict() + if isinstance(dico, dict): + prefix = prefix + "." if prefix is not None else "" + for k, v in dico.items(): + if v is None: + continue + new_dico.update(_flatten(v, prefix + k)) + elif isinstance(dico, list): + for i, v in enumerate(dico): + new_dico.update(_flatten(v, prefix + ".[" + str(i) + "]")) + else: + new_dico = OrderedDict({prefix: dico}) + return new_dico + + +def _unflatten(dico): + """Unflatten a flattened dictionary into a nested dictionary.""" + new_dico = OrderedDict() + for full_k, v in dico.items(): + full_k = full_k.split(".") + node = new_dico + for k in full_k[:-1]: + if k.startswith("[") and k.endswith("]"): + k = int(k[1:-1]) + if k not in node: + node[k] = OrderedDict() + node = node[k] + node[full_k[-1]] = v + return new_dico + + +class NestedDictionaryDataset(FairseqDataset): + def __init__(self, defn, sizes=None): + super().__init__() + self.defn = _flatten(defn) + self.sizes = [sizes] if not isinstance(sizes, (list, tuple)) else sizes + + first = None + for v in self.defn.values(): + if not isinstance( + v, + ( + FairseqDataset, + torch.utils.data.Dataset, + ), + ): + raise ValueError("Expected Dataset but found: {}".format(v.__class__)) + first = first or v + if len(v) > 0: + assert len(v) == len(first), "dataset lengths must match" + + self._len = len(first) + + def __getitem__(self, index): + return OrderedDict((k, ds[index]) for k, ds in self.defn.items()) + + def __len__(self): + return self._len + + def collater(self, samples): + """Merge a list of samples to form a mini-batch. + + Args: + samples (List[dict]): samples to collate + + Returns: + dict: a mini-batch suitable for forwarding with a Model + """ + if len(samples) == 0: + return {} + sample = OrderedDict() + for k, ds in self.defn.items(): + try: + sample[k] = ds.collater([s[k] for s in samples]) + except NotImplementedError: + sample[k] = default_collate([s[k] for s in samples]) + return _unflatten(sample) + + def num_tokens(self, index): + """Return the number of tokens in a sample. This value is used to + enforce ``--max-tokens`` during batching.""" + return max(s[index] for s in self.sizes) + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + if len(self.sizes) == 1: + return self.sizes[0][index] + else: + return (s[index] for s in self.sizes) + + @property + def supports_prefetch(self): + """Whether this dataset supports prefetching.""" + return any(ds.supports_prefetch for ds in self.defn.values()) + + def prefetch(self, indices): + """Prefetch the data required for this epoch.""" + for ds in self.defn.values(): + if getattr(ds, "supports_prefetch", False): + ds.prefetch(indices) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return all(ds.can_reuse_epoch_itr_across_epochs for ds in self.defn.values()) + + def set_epoch(self, epoch): + super().set_epoch(epoch) + for ds in self.defn.values(): + ds.set_epoch(epoch) diff --git a/fairseq-tools/fairseq/fairseq/data/noising.py b/fairseq-tools/fairseq/fairseq/data/noising.py new file mode 100644 index 00000000..9643d1aa --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/noising.py @@ -0,0 +1,333 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +from fairseq.data import data_utils + + +class WordNoising(object): + """Generate a noisy version of a sentence, without changing words themselves.""" + + def __init__(self, dictionary, bpe_cont_marker="@@", bpe_end_marker=None): + self.dictionary = dictionary + self.bpe_end = None + if bpe_cont_marker: + self.bpe_end = np.array( + [ + not self.dictionary[i].endswith(bpe_cont_marker) + for i in range(len(self.dictionary)) + ] + ) + elif bpe_end_marker: + self.bpe_end = np.array( + [ + self.dictionary[i].endswith(bpe_end_marker) + for i in range(len(self.dictionary)) + ] + ) + + self.get_word_idx = ( + self._get_bpe_word_idx if self.bpe_end is not None else self._get_token_idx + ) + + def noising(self, x, lengths, noising_prob=0.0): + raise NotImplementedError() + + def _get_bpe_word_idx(self, x): + """ + Given a list of BPE tokens, for every index in the tokens list, + return the index of the word grouping that it belongs to. + For example, for input x corresponding to ["how", "are", "y@@", "ou"], + return [[0], [1], [2], [2]]. + """ + # x: (T x B) + bpe_end = self.bpe_end[x] + + if x.size(0) == 1 and x.size(1) == 1: + # Special case when we only have one word in x. If x = [[N]], + # bpe_end is a scalar (bool) instead of a 2-dim array of bools, + # which makes the sum operation below fail. + return np.array([[0]]) + + # do a reduce front sum to generate word ids + word_idx = bpe_end[::-1].cumsum(0)[::-1] + word_idx = word_idx.max(0)[None, :] - word_idx + return word_idx + + def _get_token_idx(self, x): + """ + This is to extend noising functions to be able to apply to non-bpe + tokens, e.g. word or characters. + """ + x = torch.t(x) + word_idx = np.array([range(len(x_i)) for x_i in x]) + return np.transpose(word_idx) + + +class WordDropout(WordNoising): + """Randomly drop input words. If not passing blank_idx (default is None), + then dropped words will be removed. Otherwise, it will be replaced by the + blank_idx.""" + + def __init__( + self, + dictionary, + default_dropout_prob=0.1, + bpe_cont_marker="@@", + bpe_end_marker=None, + ): + super().__init__(dictionary, bpe_cont_marker, bpe_end_marker) + self.default_dropout_prob = default_dropout_prob + + def noising(self, x, lengths, dropout_prob=None, blank_idx=None): + if dropout_prob is None: + dropout_prob = self.default_dropout_prob + # x: (T x B), lengths: B + if dropout_prob == 0: + return x, lengths + + assert 0 < dropout_prob < 1 + + # be sure to drop entire words + word_idx = self.get_word_idx(x) + sentences = [] + modified_lengths = [] + for i in range(lengths.size(0)): + # Since dropout probabilities need to apply over non-pad tokens, + # it is not trivial to generate the keep mask without consider + # input lengths; otherwise, this could be done outside the loop + + # We want to drop whole words based on word_idx grouping + num_words = max(word_idx[:, i]) + 1 + + # ith example: [x0, x1, ..., eos, pad, ..., pad] + # We should only generate keep probs for non-EOS tokens. Thus if the + # input sentence ends in EOS, the last word idx is not included in + # the dropout mask generation and we append True to always keep EOS. + # Otherwise, just generate the dropout mask for all word idx + # positions. + has_eos = x[lengths[i] - 1, i] == self.dictionary.eos() + if has_eos: # has eos? + keep = np.random.rand(num_words - 1) >= dropout_prob + keep = np.append(keep, [True]) # keep EOS symbol + else: + keep = np.random.rand(num_words) >= dropout_prob + + words = x[: lengths[i], i].tolist() + + # TODO: speed up the following loop + # drop words from the input according to keep + new_s = [ + w if keep[word_idx[j, i]] else blank_idx for j, w in enumerate(words) + ] + new_s = [w for w in new_s if w is not None] + # we need to have at least one word in the sentence (more than the + # start / end sentence symbols) + if len(new_s) <= 1: + # insert at beginning in case the only token left is EOS + # EOS should be at end of list. + new_s.insert(0, words[np.random.randint(0, len(words))]) + assert len(new_s) >= 1 and ( + not has_eos # Either don't have EOS at end or last token is EOS + or (len(new_s) >= 2 and new_s[-1] == self.dictionary.eos()) + ), "New sentence is invalid." + sentences.append(new_s) + modified_lengths.append(len(new_s)) + # re-construct input + modified_lengths = torch.LongTensor(modified_lengths) + modified_x = torch.LongTensor( + modified_lengths.max(), modified_lengths.size(0) + ).fill_(self.dictionary.pad()) + for i in range(modified_lengths.size(0)): + modified_x[: modified_lengths[i], i].copy_(torch.LongTensor(sentences[i])) + + return modified_x, modified_lengths + + +class WordShuffle(WordNoising): + """Shuffle words by no more than k positions.""" + + def __init__( + self, + dictionary, + default_max_shuffle_distance=3, + bpe_cont_marker="@@", + bpe_end_marker=None, + ): + super().__init__(dictionary, bpe_cont_marker, bpe_end_marker) + self.default_max_shuffle_distance = 3 + + def noising(self, x, lengths, max_shuffle_distance=None): + if max_shuffle_distance is None: + max_shuffle_distance = self.default_max_shuffle_distance + # x: (T x B), lengths: B + if max_shuffle_distance == 0: + return x, lengths + + # max_shuffle_distance < 1 will return the same sequence + assert max_shuffle_distance > 1 + + # define noise word scores + noise = np.random.uniform( + 0, + max_shuffle_distance, + size=(x.size(0), x.size(1)), + ) + noise[0] = -1 # do not move start sentence symbol + # be sure to shuffle entire words + word_idx = self.get_word_idx(x) + x2 = x.clone() + for i in range(lengths.size(0)): + length_no_eos = lengths[i] + if x[lengths[i] - 1, i] == self.dictionary.eos(): + length_no_eos = lengths[i] - 1 + # generate a random permutation + scores = word_idx[:length_no_eos, i] + noise[word_idx[:length_no_eos, i], i] + # ensure no reordering inside a word + scores += 1e-6 * np.arange(length_no_eos.item()) + permutation = scores.argsort() + # shuffle words + x2[:length_no_eos, i].copy_( + x2[:length_no_eos, i][torch.from_numpy(permutation)] + ) + return x2, lengths + + +class UnsupervisedMTNoising(WordNoising): + """ + Implements the default configuration for noising in UnsupervisedMT + (github.com/facebookresearch/UnsupervisedMT) + """ + + def __init__( + self, + dictionary, + max_word_shuffle_distance, + word_dropout_prob, + word_blanking_prob, + bpe_cont_marker="@@", + bpe_end_marker=None, + ): + super().__init__(dictionary) + self.max_word_shuffle_distance = max_word_shuffle_distance + self.word_dropout_prob = word_dropout_prob + self.word_blanking_prob = word_blanking_prob + + self.word_dropout = WordDropout( + dictionary=dictionary, + bpe_cont_marker=bpe_cont_marker, + bpe_end_marker=bpe_end_marker, + ) + self.word_shuffle = WordShuffle( + dictionary=dictionary, + bpe_cont_marker=bpe_cont_marker, + bpe_end_marker=bpe_end_marker, + ) + + def noising(self, x, lengths): + # 1. Word Shuffle + noisy_src_tokens, noisy_src_lengths = self.word_shuffle.noising( + x=x, + lengths=lengths, + max_shuffle_distance=self.max_word_shuffle_distance, + ) + # 2. Word Dropout + noisy_src_tokens, noisy_src_lengths = self.word_dropout.noising( + x=noisy_src_tokens, + lengths=noisy_src_lengths, + dropout_prob=self.word_dropout_prob, + ) + # 3. Word Blanking + noisy_src_tokens, noisy_src_lengths = self.word_dropout.noising( + x=noisy_src_tokens, + lengths=noisy_src_lengths, + dropout_prob=self.word_blanking_prob, + blank_idx=self.dictionary.unk(), + ) + + return noisy_src_tokens + + +class NoisingDataset(torch.utils.data.Dataset): + def __init__( + self, + src_dataset, + src_dict, + seed, + noiser=None, + noising_class=UnsupervisedMTNoising, + **kwargs + ): + """ + Wrap a :class:`~torch.utils.data.Dataset` and apply noise to the + samples based on the supplied noising configuration. + + Args: + src_dataset (~torch.utils.data.Dataset): dataset to wrap. + to build self.src_dataset -- + a LanguagePairDataset with src dataset as the source dataset and + None as the target dataset. Should NOT have padding so that + src_lengths are accurately calculated by language_pair_dataset + collate function. + We use language_pair_dataset here to encapsulate the tgt_dataset + so we can re-use the LanguagePairDataset collater to format the + batches in the structure that SequenceGenerator expects. + src_dict (~fairseq.data.Dictionary): source dictionary + seed (int): seed to use when generating random noise + noiser (WordNoising): a pre-initialized :class:`WordNoising` + instance. If this is None, a new instance will be created using + *noising_class* and *kwargs*. + noising_class (class, optional): class to use to initialize a + default :class:`WordNoising` instance. + kwargs (dict, optional): arguments to initialize the default + :class:`WordNoising` instance given by *noiser*. + """ + self.src_dataset = src_dataset + self.src_dict = src_dict + self.seed = seed + self.noiser = ( + noiser + if noiser is not None + else noising_class( + dictionary=src_dict, + **kwargs, + ) + ) + + def __getitem__(self, index): + """ + Returns a single noisy sample. Multiple samples are fed to the collater + create a noising dataset batch. + """ + src_tokens = self.src_dataset[index] + src_lengths = torch.LongTensor([len(src_tokens)]) + src_tokens = src_tokens.unsqueeze(0) + + # Transpose src tokens to fit expected shape of x in noising function + # (batch size, sequence length) -> (sequence length, batch size) + src_tokens_t = torch.t(src_tokens) + + with data_utils.numpy_seed(self.seed + index): + noisy_src_tokens = self.noiser.noising(src_tokens_t, src_lengths) + + # Transpose back to expected src_tokens format + # (sequence length, 1) -> (1, sequence length) + noisy_src_tokens = torch.t(noisy_src_tokens) + return noisy_src_tokens[0] + + def __len__(self): + """ + The length of the noising dataset is the length of src. + """ + return len(self.src_dataset) + + @property + def supports_prefetch(self): + return self.src_dataset.supports_prefetch + + def prefetch(self, indices): + if self.src_dataset.supports_prefetch: + self.src_dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/num_samples_dataset.py b/fairseq-tools/fairseq/fairseq/data/num_samples_dataset.py new file mode 100644 index 00000000..99a17495 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/num_samples_dataset.py @@ -0,0 +1,17 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import FairseqDataset + + +class NumSamplesDataset(FairseqDataset): + def __getitem__(self, index): + return 1 + + def __len__(self): + return 0 + + def collater(self, samples): + return sum(samples) diff --git a/fairseq-tools/fairseq/fairseq/data/numel_dataset.py b/fairseq-tools/fairseq/fairseq/data/numel_dataset.py new file mode 100644 index 00000000..ac86dfd2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/numel_dataset.py @@ -0,0 +1,31 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch + +from . import BaseWrapperDataset + + +class NumelDataset(BaseWrapperDataset): + def __init__(self, dataset, reduce=False): + super().__init__(dataset) + self.reduce = reduce + + def __getitem__(self, index): + item = self.dataset[index] + if torch.is_tensor(item): + return torch.numel(item) + else: + return np.size(item) + + def __len__(self): + return len(self.dataset) + + def collater(self, samples): + if self.reduce: + return sum(samples) + else: + return torch.tensor(samples) diff --git a/fairseq-tools/fairseq/fairseq/data/offset_tokens_dataset.py b/fairseq-tools/fairseq/fairseq/data/offset_tokens_dataset.py new file mode 100644 index 00000000..6fabbdcd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/offset_tokens_dataset.py @@ -0,0 +1,15 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import BaseWrapperDataset + + +class OffsetTokensDataset(BaseWrapperDataset): + def __init__(self, dataset, offset): + super().__init__(dataset) + self.offset = offset + + def __getitem__(self, idx): + return self.dataset[idx] + self.offset diff --git a/fairseq-tools/fairseq/fairseq/data/pad_dataset.py b/fairseq-tools/fairseq/fairseq/data/pad_dataset.py new file mode 100644 index 00000000..8075bba6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/pad_dataset.py @@ -0,0 +1,28 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data import data_utils + +from . import BaseWrapperDataset + + +class PadDataset(BaseWrapperDataset): + def __init__(self, dataset, pad_idx, left_pad): + super().__init__(dataset) + self.pad_idx = pad_idx + self.left_pad = left_pad + + def collater(self, samples): + return data_utils.collate_tokens(samples, self.pad_idx, left_pad=self.left_pad) + + +class LeftPadDataset(PadDataset): + def __init__(self, dataset, pad_idx): + super().__init__(dataset, pad_idx, left_pad=True) + + +class RightPadDataset(PadDataset): + def __init__(self, dataset, pad_idx): + super().__init__(dataset, pad_idx, left_pad=False) diff --git a/fairseq-tools/fairseq/fairseq/data/plasma_utils.py b/fairseq-tools/fairseq/fairseq/data/plasma_utils.py new file mode 100644 index 00000000..2b126467 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/plasma_utils.py @@ -0,0 +1,91 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import subprocess +import tempfile + + +class PlasmaArray(object): + """ + Wrapper around numpy arrays that automatically moves the data to shared + memory upon serialization. This is particularly helpful when passing numpy + arrays through multiprocessing, so that data is not unnecessarily + duplicated or pickled. + """ + + def __init__(self, array): + super().__init__() + self.array = array + self.disable = array.nbytes < 134217728 # disable for arrays <128MB + self.object_id = None + self.path = None + + # variables with underscores shouldn't be pickled + self._client = None + self._server = None + self._server_tmp = None + self._plasma = None + + @property + def plasma(self): + if self._plasma is None and not self.disable: + try: + import pyarrow.plasma as plasma + + self._plasma = plasma + except ImportError: + self._plasma = None + return self._plasma + + def start_server(self): + if self.plasma is None or self._server is not None: + return + assert self.object_id is None + assert self.path is None + self._server_tmp = tempfile.NamedTemporaryFile() + self.path = self._server_tmp.name + self._server = subprocess.Popen( + [ + "plasma_store", + "-m", + str(int(1.05 * self.array.nbytes)), + "-s", + self.path, + ] + ) + + @property + def client(self): + if self._client is None: + assert self.path is not None + self._client = self.plasma.connect(self.path) + return self._client + + def __getstate__(self): + if self.plasma is None: + return self.__dict__ + if self.object_id is None: + self.start_server() + self.object_id = self.client.put(self.array) + state = self.__dict__.copy() + del state["array"] + state["_client"] = None + state["_server"] = None + state["_server_tmp"] = None + state["_plasma"] = None + return state + + def __setstate__(self, state): + self.__dict__.update(state) + if self.plasma is None: + return + self.array = self.client.get(self.object_id) + + def __del__(self): + if self._server is not None: + self._server.kill() + self._server = None + self._server_tmp.close() + self._server_tmp = None diff --git a/fairseq-tools/fairseq/fairseq/data/prepend_dataset.py b/fairseq-tools/fairseq/fairseq/data/prepend_dataset.py new file mode 100644 index 00000000..ad74784d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/prepend_dataset.py @@ -0,0 +1,28 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch + +from . import BaseWrapperDataset + + +class PrependDataset(BaseWrapperDataset): + def __init__(self, dataset, prepend_getter, ensure_first_token_is=None): + super().__init__(dataset) + self.prepend_getter = prepend_getter + self.ensure_first_token = ensure_first_token_is + + def __getitem__(self, idx): + item = self.dataset[idx] + is_tuple = isinstance(item, tuple) + src = item[0] if is_tuple else item + + assert self.ensure_first_token is None or src[0] == self.ensure_first_token + prepend_idx = self.prepend_getter(self.dataset, idx) + assert isinstance(prepend_idx, int) + src[0] = prepend_idx + item = tuple((src,) + item[1:]) if is_tuple else src + return item diff --git a/fairseq-tools/fairseq/fairseq/data/prepend_token_dataset.py b/fairseq-tools/fairseq/fairseq/data/prepend_token_dataset.py new file mode 100644 index 00000000..fd1331f4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/prepend_token_dataset.py @@ -0,0 +1,41 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch + +from . import BaseWrapperDataset + + +class PrependTokenDataset(BaseWrapperDataset): + def __init__(self, dataset, token=None): + super().__init__(dataset) + self.token = token + if token is not None: + self._sizes = np.array(dataset.sizes) + 1 + else: + self._sizes = dataset.sizes + + def __getitem__(self, idx): + item = self.dataset[idx] + if self.token is not None: + item = torch.cat([item.new([self.token]), item]) + return item + + @property + def sizes(self): + return self._sizes + + def num_tokens(self, index): + n = self.dataset.num_tokens(index) + if self.token is not None: + n += 1 + return n + + def size(self, index): + n = self.dataset.size(index) + if self.token is not None: + n += 1 + return n diff --git a/fairseq-tools/fairseq/fairseq/data/raw_label_dataset.py b/fairseq-tools/fairseq/fairseq/data/raw_label_dataset.py new file mode 100644 index 00000000..d054904f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/raw_label_dataset.py @@ -0,0 +1,23 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import FairseqDataset + + +class RawLabelDataset(FairseqDataset): + def __init__(self, labels): + super().__init__() + self.labels = labels + + def __getitem__(self, index): + return self.labels[index] + + def __len__(self): + return len(self.labels) + + def collater(self, samples): + return torch.tensor(samples) diff --git a/fairseq-tools/fairseq/fairseq/data/replace_dataset.py b/fairseq-tools/fairseq/fairseq/data/replace_dataset.py new file mode 100644 index 00000000..5aac2ba9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/replace_dataset.py @@ -0,0 +1,36 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import BaseWrapperDataset + + +class ReplaceDataset(BaseWrapperDataset): + """Replaces tokens found in the dataset by a specified replacement token + + Args: + dataset (~torch.utils.data.Dataset): dataset to replace tokens in + replace_map(Dictionary[int,int]): map of token to replace -> replacement token + offsets (List[int]): do not replace tokens before (from left if pos, right if neg) this offset. should be + as many as the number of objects returned by the underlying dataset __getitem__ method. + """ + + def __init__(self, dataset, replace_map, offsets): + super().__init__(dataset) + assert len(replace_map) > 0 + self.replace_map = replace_map + self.offsets = offsets + + def __getitem__(self, index): + item = self.dataset[index] + is_tuple = isinstance(item, tuple) + srcs = item if is_tuple else [item] + + for offset, src in zip(self.offsets, srcs): + for k, v in self.replace_map.items(): + src_off = src[offset:] if offset >= 0 else src[:offset] + src_off.masked_fill_(src_off == k, v) + + item = srcs if is_tuple else srcs[0] + return item diff --git a/fairseq-tools/fairseq/fairseq/data/resampling_dataset.py b/fairseq-tools/fairseq/fairseq/data/resampling_dataset.py new file mode 100644 index 00000000..fdafda3c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/resampling_dataset.py @@ -0,0 +1,140 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +import logging + +import numpy as np +from fairseq.data import BaseWrapperDataset, plasma_utils + + +logger = logging.getLogger(__name__) + + +class ResamplingDataset(BaseWrapperDataset): + """Randomly samples from a given dataset at each epoch. + + Sampling is done with or without replacement, depending on the "replace" + parameter. + + Optionally, the epoch size can be rescaled. This is potentially desirable + to increase per-epoch coverage of the base dataset (since sampling with + replacement means that many items in the dataset will be left out). In the + case of sampling without replacement, size_ratio should be strictly less + than 1. + + Args: + dataset (~torch.utils.data.Dataset): dataset on which to sample. + weights (List[float]): list of probability weights + (default: None, which corresponds to uniform sampling). + replace (bool): sampling mode; True for "with replacement", or False + for "without replacement" (default: True) + size_ratio (float): the ratio to subsample to; must be positive + (default: 1.0). + batch_by_size (bool): whether or not to batch by sequence length + (default: True). + seed (int): RNG seed to use (default: 0). + epoch (int): starting epoch number (default: 1). + """ + + def __init__( + self, + dataset, + weights=None, + replace=True, + size_ratio=1.0, + batch_by_size=True, + seed=0, + epoch=1, + ): + super().__init__(dataset) + + if weights is None: + self.weights = None + + else: + assert len(weights) == len(dataset) + weights_arr = np.array(weights, dtype=np.float32) + weights_arr /= weights_arr.sum() + self.weights = plasma_utils.PlasmaArray(weights_arr) + + self.replace = replace + + assert size_ratio > 0.0 + if not self.replace: + assert size_ratio < 1.0 + self.size_ratio = float(size_ratio) + self.actual_size = np.ceil(len(dataset) * self.size_ratio).astype(int) + + self.batch_by_size = batch_by_size + self.seed = seed + + self._cur_epoch = None + self._cur_indices = None + + self.set_epoch(epoch) + + def __getitem__(self, index): + return self.dataset[self._cur_indices.array[index]] + + def __len__(self): + return self.actual_size + + @property + def sizes(self): + if isinstance(self.dataset.sizes, list): + return [s[self._cur_indices.array] for s in self.dataset.sizes] + return self.dataset.sizes[self._cur_indices.array] + + def num_tokens(self, index): + return self.dataset.num_tokens(self._cur_indices.array[index]) + + def size(self, index): + return self.dataset.size(self._cur_indices.array[index]) + + def ordered_indices(self): + if self.batch_by_size: + order = [ + np.arange(len(self)), + self.sizes, + ] # No need to handle `self.shuffle == True` + return np.lexsort(order) + else: + return np.arange(len(self)) + + def prefetch(self, indices): + self.dataset.prefetch(self._cur_indices.array[indices]) + + @property + def can_reuse_epoch_itr_across_epochs(self): + return False + + def set_epoch(self, epoch): + logger.debug("ResamplingDataset.set_epoch: {}".format(epoch)) + super().set_epoch(epoch) + + if epoch == self._cur_epoch: + return + + self._cur_epoch = epoch + + # Generate a weighted sample of indices as a function of the + # random seed and the current epoch. + + rng = np.random.RandomState( + [ + 42, # magic number + self.seed % (2 ** 32), # global seed + self._cur_epoch, # epoch index + ] + ) + self._cur_indices = plasma_utils.PlasmaArray( + rng.choice( + len(self.dataset), + self.actual_size, + replace=self.replace, + p=(None if self.weights is None else self.weights.array), + ) + ) diff --git a/fairseq-tools/fairseq/fairseq/data/roll_dataset.py b/fairseq-tools/fairseq/fairseq/data/roll_dataset.py new file mode 100644 index 00000000..a2915eeb --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/roll_dataset.py @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import BaseWrapperDataset + + +class RollDataset(BaseWrapperDataset): + def __init__(self, dataset, shifts): + super().__init__(dataset) + self.shifts = shifts + + def __getitem__(self, index): + item = self.dataset[index] + return torch.roll(item, self.shifts) diff --git a/fairseq-tools/fairseq/fairseq/data/round_robin_zip_datasets.py b/fairseq-tools/fairseq/fairseq/data/round_robin_zip_datasets.py new file mode 100644 index 00000000..690823fc --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/round_robin_zip_datasets.py @@ -0,0 +1,117 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import OrderedDict + +import numpy as np + +from . import FairseqDataset + + +class RoundRobinZipDatasets(FairseqDataset): + """Zip multiple :class:`~fairseq.data.FairseqDataset` instances together. + + Shorter datasets are repeated in a round-robin fashion to match the length + of the longest one. + + Args: + datasets (Dict[~fairseq.data.FairseqDataset]): a dictionary of + :class:`~fairseq.data.FairseqDataset` instances. + eval_key (str, optional): a key used at evaluation time that causes + this instance to pass-through batches from *datasets[eval_key]*. + """ + + def __init__(self, datasets, eval_key=None): + super().__init__() + assert isinstance(datasets, OrderedDict) + self.datasets = datasets + self.eval_key = eval_key + + self.longest_dataset = None + self.longest_dataset_key = None + for key, dataset in datasets.items(): + assert isinstance(dataset, FairseqDataset) + if self.longest_dataset is None or len(dataset) > len(self.longest_dataset): + self.longest_dataset = dataset + self.longest_dataset_key = key + + self._ordered_indices = None + + def _map_index(self, key, index): + assert ( + self._ordered_indices is not None + ), "Must call RoundRobinZipDatasets.ordered_indices() first" + return self._ordered_indices[key][index % len(self.datasets[key])] + + def __getitem__(self, index): + if self.eval_key is None: + return OrderedDict( + [ + (key, dataset[self._map_index(key, index)]) + for key, dataset in self.datasets.items() + ] + ) + else: + # at evaluation time it's useful to pass-through batches from a single key + return self.datasets[self.eval_key][self._map_index(self.eval_key, index)] + + def __len__(self): + return len(self.longest_dataset) + + def collater(self, samples): + """Merge a list of samples to form a mini-batch.""" + if len(samples) == 0: + return None + if self.eval_key is None: + return OrderedDict( + [ + (key, dataset.collater([sample[key] for sample in samples])) + for key, dataset in self.datasets.items() + ] + ) + else: + # at evaluation time it's useful to pass-through batches from a single key + return self.datasets[self.eval_key].collater(samples) + + def num_tokens(self, index): + """Return an example's length (number of tokens), used for batching.""" + # TODO make it configurable whether to use max() or sum() here + return max( + dataset.num_tokens(self._map_index(key, index)) + for key, dataset in self.datasets.items() + ) + + def size(self, index): + """Return an example's size as a float or tuple. This value is used when + filtering a dataset with ``--max-positions``.""" + return { + key: dataset.size(self._map_index(key, index)) + for key, dataset in self.datasets.items() + } + + def ordered_indices(self): + """Ordered indices for batching.""" + if self._ordered_indices is None: + # Call the underlying dataset's ordered_indices() here, so that we + # get the same random ordering as we would have from using the + # underlying dataset directly. + self._ordered_indices = OrderedDict( + [ + (key, dataset.ordered_indices()) + for key, dataset in self.datasets.items() + ] + ) + return np.arange(len(self)) + + @property + def supports_prefetch(self): + return all( + getattr(dataset, "supports_prefetch", False) + for dataset in self.datasets.values() + ) + + def prefetch(self, indices): + for key, dataset in self.datasets.items(): + dataset.prefetch([self._map_index(key, index) for index in indices]) diff --git a/fairseq-tools/fairseq/fairseq/data/shorten_dataset.py b/fairseq-tools/fairseq/fairseq/data/shorten_dataset.py new file mode 100644 index 00000000..6ebb5d88 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/shorten_dataset.py @@ -0,0 +1,78 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +from fairseq.data import data_utils + +from . import BaseWrapperDataset + + +class TruncateDataset(BaseWrapperDataset): + """Truncate a sequence by returning the first truncation_length tokens""" + + def __init__(self, dataset, truncation_length): + super().__init__(dataset) + assert truncation_length is not None + self.truncation_length = truncation_length + self.dataset = dataset + + def __getitem__(self, index): + item = self.dataset[index] + item_len = item.size(0) + if item_len > self.truncation_length: + item = item[: self.truncation_length] + return item + + @property + def sizes(self): + return np.minimum(self.dataset.sizes, self.truncation_length) + + def __len__(self): + return len(self.dataset) + + +class RandomCropDataset(TruncateDataset): + """Truncate a sequence by returning a random crop of truncation_length tokens""" + + def __init__(self, dataset, truncation_length, seed=1): + super().__init__(dataset, truncation_length) + self.seed = seed + self.epoch = 0 + + @property + def can_reuse_epoch_itr_across_epochs(self): + return True # only the crop changes, not item sizes + + def set_epoch(self, epoch, **unused): + super().set_epoch(epoch) + self.epoch = epoch + + def __getitem__(self, index): + with data_utils.numpy_seed(self.seed, self.epoch, index): + item = self.dataset[index] + item_len = item.size(0) + excess = item_len - self.truncation_length + if excess > 0: + start_idx = np.random.randint(0, excess) + item = item[start_idx : start_idx + self.truncation_length] + return item + + +def maybe_shorten_dataset( + dataset, + split, + shorten_data_split_list, + shorten_method, + tokens_per_sample, + seed, +): + truncate_split = ( + split in shorten_data_split_list.split(",") or len(shorten_data_split_list) == 0 + ) + if shorten_method == "truncate" and truncate_split: + dataset = TruncateDataset(dataset, tokens_per_sample) + elif shorten_method == "random_crop" and truncate_split: + dataset = RandomCropDataset(dataset, tokens_per_sample, seed) + return dataset diff --git a/fairseq-tools/fairseq/fairseq/data/sort_dataset.py b/fairseq-tools/fairseq/fairseq/data/sort_dataset.py new file mode 100644 index 00000000..b3890e72 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/sort_dataset.py @@ -0,0 +1,21 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np + +from . import BaseWrapperDataset + + +class SortDataset(BaseWrapperDataset): + def __init__(self, dataset, sort_order): + super().__init__(dataset) + if not isinstance(sort_order, (list, tuple)): + sort_order = [sort_order] + self.sort_order = sort_order + + assert all(len(so) == len(dataset) for so in sort_order) + + def ordered_indices(self): + return np.lexsort(self.sort_order) diff --git a/fairseq-tools/fairseq/fairseq/data/strip_token_dataset.py b/fairseq-tools/fairseq/fairseq/data/strip_token_dataset.py new file mode 100644 index 00000000..cae39ba4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/strip_token_dataset.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import BaseWrapperDataset + + +class StripTokenDataset(BaseWrapperDataset): + def __init__(self, dataset, id_to_strip): + super().__init__(dataset) + self.id_to_strip = id_to_strip + + def __getitem__(self, index): + item = self.dataset[index] + while len(item) > 0 and item[-1] == self.id_to_strip: + item = item[:-1] + while len(item) > 0 and item[0] == self.id_to_strip: + item = item[1:] + return item diff --git a/fairseq-tools/fairseq/fairseq/data/subsample_dataset.py b/fairseq-tools/fairseq/fairseq/data/subsample_dataset.py new file mode 100644 index 00000000..48feaf88 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/subsample_dataset.py @@ -0,0 +1,72 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import numpy as np + +from . import BaseWrapperDataset + + +logger = logging.getLogger(__name__) + + +class SubsampleDataset(BaseWrapperDataset): + """Subsamples a given dataset by a specified ratio. Subsampling is done on the number of examples + + Args: + dataset (~torch.utils.data.Dataset): dataset to subsample + size_ratio(float): the ratio to subsample to. must be between 0 and 1 (exclusive) + """ + + def __init__(self, dataset, size_ratio, shuffle=False): + super().__init__(dataset) + assert size_ratio < 1 + self.actual_size = np.ceil(len(dataset) * size_ratio).astype(int) + self.indices = np.random.choice( + list(range(len(self.dataset))), self.actual_size, replace=False + ) + self.shuffle = shuffle + logger.info( + "subsampled dataset from {} to {} (ratio={})".format( + len(self.dataset), self.actual_size, size_ratio + ) + ) + + def __getitem__(self, index): + return self.dataset[self.indices[index]] + + def __len__(self): + return self.actual_size + + def collater(self, samples): + return self.dataset.collater(samples) + + @property + def sizes(self): + return self.dataset.sizes[self.indices] + + @property + def name(self): + return self.dataset.name + + def num_tokens(self, index): + return self.dataset.num_tokens(self.indices[index]) + + def size(self, index): + return self.dataset.size(self.indices[index]) + + def ordered_indices(self): + """Return an ordered list of indices. Batches will be constructed based + on this order.""" + if self.shuffle: + order = [np.random.permutation(len(self))] + else: + order = [np.arange(len(self))] + order.append(self.sizes) + return np.lexsort(order) + + def prefetch(self, indices): + self.dataset.prefetch(self.indices[indices]) diff --git a/fairseq-tools/fairseq/fairseq/data/token_block_dataset.py b/fairseq-tools/fairseq/fairseq/data/token_block_dataset.py new file mode 100644 index 00000000..aa33f9d0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/token_block_dataset.py @@ -0,0 +1,168 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +from fairseq.data import FairseqDataset, plasma_utils + + +class TokenBlockDataset(FairseqDataset): + """Break a Dataset of tokens into blocks. + + Args: + dataset (~torch.utils.data.Dataset): dataset to break into blocks + sizes (List[int]): sentence lengths (required for 'complete' and 'eos') + block_size (int): maximum block size (ignored in 'eos' break mode) + break_mode (str, optional): Mode used for breaking tokens. Values can + be one of: + - 'none': break tokens into equally sized blocks (up to block_size) + - 'complete': break tokens into blocks (up to block_size) such that + blocks contains complete sentences, although block_size may be + exceeded if some sentences exceed block_size + - 'complete_doc': similar to 'complete' mode, but do not + cross document boundaries + - 'eos': each block contains one sentence (block_size is ignored) + include_targets (bool, optional): return next tokens as targets + (default: False). + document_sep_len (int, optional): document separator size (required for + 'complete_doc' break mode). Typically 1 if the sentences have eos + and 0 otherwise. + """ + + def __init__( + self, + dataset, + sizes, + block_size, + pad, + eos, + break_mode=None, + include_targets=False, + document_sep_len=1, + ): + try: + from fairseq.data.token_block_utils_fast import ( + _get_slice_indices_fast, + _get_block_to_dataset_index_fast, + ) + except ImportError: + raise ImportError( + "Please build Cython components with: `pip install --editable .` " + "or `python setup.py build_ext --inplace`" + ) + + super().__init__() + self.dataset = dataset + self.pad = pad + self.eos = eos + self.include_targets = include_targets + + assert len(dataset) == len(sizes) + assert len(dataset) > 0 + + if isinstance(sizes, list): + sizes = np.array(sizes, dtype=np.int64) + else: + if torch.is_tensor(sizes): + sizes = sizes.numpy() + sizes = sizes.astype(np.int64) + + break_mode = break_mode if break_mode is not None else "none" + + # For "eos" break-mode, block_size is not required parameters. + if break_mode == "eos" and block_size is None: + block_size = 0 + + slice_indices = _get_slice_indices_fast( + sizes, str(break_mode), block_size, document_sep_len + ) + self._sizes = slice_indices[:, 1] - slice_indices[:, 0] + + # build index mapping block indices to the underlying dataset indices + if break_mode == "eos": + # much faster version for eos break mode + block_to_dataset_index = np.stack( + [ + np.arange(len(sizes)), # starting index in dataset + np.zeros( + len(sizes), dtype=np.long + ), # starting offset within starting index + np.arange(len(sizes)), # ending index in dataset + ], + 1, + ) + else: + block_to_dataset_index = _get_block_to_dataset_index_fast( + sizes, + slice_indices, + ) + self._slice_indices = plasma_utils.PlasmaArray(slice_indices) + self._sizes = plasma_utils.PlasmaArray(self._sizes) + self._block_to_dataset_index = plasma_utils.PlasmaArray(block_to_dataset_index) + + @property + def slice_indices(self): + return self._slice_indices.array + + @property + def sizes(self): + return self._sizes.array + + @property + def block_to_dataset_index(self): + return self._block_to_dataset_index.array + + def attr(self, attr: str, index: int): + start_ds_idx, _, _ = self.block_to_dataset_index[index] + return self.dataset.attr(attr, start_ds_idx) + + def __getitem__(self, index): + start_ds_idx, start_offset, end_ds_idx = self.block_to_dataset_index[index] + + buffer = torch.cat( + [self.dataset[idx] for idx in range(start_ds_idx, end_ds_idx + 1)] + ) + + slice_s, slice_e = self.slice_indices[index] + length = slice_e - slice_s + s, e = start_offset, start_offset + length + item = buffer[s:e] + + if self.include_targets: + # *target* is the original sentence (=item) + # *source* is shifted right by 1 (maybe left-padded with eos) + # *past_target* is shifted right by 2 (left-padded as needed) + if s == 0: + source = torch.cat([item.new([self.eos]), buffer[0 : e - 1]]) + past_target = torch.cat( + [item.new([self.pad, self.eos]), buffer[0 : e - 2]] + ) + else: + source = buffer[s - 1 : e - 1] + if s == 1: + past_target = torch.cat([item.new([self.eos]), buffer[0 : e - 2]]) + else: + past_target = buffer[s - 2 : e - 2] + + return source, item, past_target + + return item + + def __len__(self): + return len(self.slice_indices) + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + self.dataset.prefetch( + { + ds_idx + for index in indices + for start_ds_idx, _, end_ds_idx in [self.block_to_dataset_index[index]] + for ds_idx in range(start_ds_idx, end_ds_idx + 1) + } + ) diff --git a/fairseq-tools/fairseq/fairseq/data/token_block_utils_fast.pyx b/fairseq-tools/fairseq/fairseq/data/token_block_utils_fast.pyx new file mode 100644 index 00000000..08af4f30 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/token_block_utils_fast.pyx @@ -0,0 +1,187 @@ +# cython: language_level=3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +from itertools import chain +from libc.math cimport ceil + +cimport cython +cimport numpy as np + +from libc.stdint cimport int32_t, int64_t + +DTYPE = np.int64 +ctypedef int64_t DTYPE_t + + +@cython.boundscheck(False) +@cython.wraparound(False) +@cython.nonecheck(False) +cdef np.ndarray[DTYPE_t, ndim=2] _get_slice_indices_none_mode(np.ndarray[DTYPE_t, ndim=1] sizes, int block_size): + cdef DTYPE_t total_size = sizes.sum() + cdef DTYPE_t length = <DTYPE_t> ceil(total_size / <double> block_size) + cdef np.ndarray[DTYPE_t, ndim=2] slice_indices = np.zeros([length, 2], dtype=DTYPE) + cdef DTYPE_t[:, :] slice_indices_view = slice_indices + cdef DTYPE_t i + cdef DTYPE_t start + cdef DTYPE_t end + for i in range(length): + start = i * block_size + end = min(start + block_size, total_size) + slice_indices_view[i][0] = start + slice_indices_view[i][1] = end + return slice_indices + + +cdef np.ndarray[DTYPE_t, ndim=2] _fast_convert_to_np_array(list list_of_list): + """ + Faster function to convert DTYPE_t list of list. + Only fast when there are huge number of rows and low number of columns. + """ + cdef np.ndarray[DTYPE_t, ndim=1] flat = np.fromiter(chain.from_iterable(list_of_list), DTYPE, -1) + return flat.reshape((len(list_of_list), -1)) + + +@cython.boundscheck(False) +@cython.wraparound(False) +@cython.nonecheck(False) +cpdef np.ndarray[DTYPE_t, ndim=2] _get_slice_indices_fast(np.ndarray[DTYPE_t, ndim=1] sizes, str break_mode, int block_size, int document_sep_len): + cdef DTYPE_t tok_idx = 0 + cdef DTYPE_t sz_idx = 0 + cdef DTYPE_t curr_size = 0 + cdef DTYPE_t i = 0 + cdef DTYPE_t length + cdef DTYPE_t total_size + cdef DTYPE_t[:] sizes_view = sizes + cdef np.ndarray[DTYPE_t, ndim=2] slice_indices + cdef list slice_indices_list = [] + + if break_mode is None or break_mode == 'none': + slice_indices = _get_slice_indices_none_mode(sizes, block_size) + elif break_mode == 'complete': + while sz_idx < len(sizes_view): + if curr_size + sizes_view[sz_idx] <= block_size or curr_size == 0: + curr_size += sizes_view[sz_idx] + sz_idx += 1 + else: + slice_indices_list.append((tok_idx, tok_idx + curr_size)) + tok_idx += curr_size + curr_size = 0 + if curr_size > 0: + slice_indices_list.append((tok_idx, tok_idx + curr_size)) + slice_indices = _fast_convert_to_np_array(slice_indices_list) + elif break_mode == 'complete_doc': + while sz_idx < len(sizes_view): + if ( + (curr_size + sizes_view[sz_idx] <= block_size or curr_size == 0) + # an empty sentence indicates end-of-document: + and sizes_view[sz_idx] != document_sep_len + ): + curr_size += sizes_view[sz_idx] + sz_idx += 1 + else: + # Only keep non-empty documents. + if curr_size > 1: + slice_indices_list.append((tok_idx, tok_idx + curr_size)) + tok_idx += curr_size + curr_size = 0 + if sizes_view[sz_idx] == document_sep_len: + tok_idx += sizes_view[sz_idx] + sz_idx += 1 + if curr_size > 1: + slice_indices_list.append((tok_idx, tok_idx + curr_size)) + slice_indices = _fast_convert_to_np_array(slice_indices_list) + elif break_mode == 'eos': + slice_indices = np.zeros((len(sizes), 2), dtype=DTYPE) + cumsum = sizes.cumsum(axis=0) + slice_indices[1:, 0] = cumsum[:cumsum.shape[0] - 1] + slice_indices[:, 1] = cumsum + else: + raise ValueError('Invalid break_mode: ' + break_mode) + return slice_indices + + +@cython.boundscheck(False) +@cython.wraparound(False) +@cython.nonecheck(False) +cpdef np.ndarray[DTYPE_t, ndim=2] _get_block_to_dataset_index_fast(np.ndarray[DTYPE_t, ndim=1] sizes, np.ndarray[DTYPE_t, ndim=2] slice_indices): + cdef DTYPE_t start_ds_idx + cdef DTYPE_t start_offset + cdef DTYPE_t end_ds_idx + cdef DTYPE_t i + cdef DTYPE_t s + cdef DTYPE_t e + cdef DatasetSearcher ds = DatasetSearcher(sizes) + cdef np.ndarray[DTYPE_t, ndim=2] block_to_dataset_index = np.zeros([len(slice_indices), 3], dtype=DTYPE) + cdef DTYPE_t[:, :] block_to_dataset_index_view = block_to_dataset_index + cdef DTYPE_t[:, :] slice_indices_view = slice_indices + cdef Py_ssize_t x_max = slice_indices.shape[0] + + for i in range(x_max): + s = slice_indices_view[i][0] + e = slice_indices_view[i][1] + ds.seek(s) + start_ds_idx = ds.current_index + start_offset = ds.current_offset + if e <= s: + end_ds_idx = start_ds_idx + else: + ds.seek(e - 1) + end_ds_idx = ds.current_index + block_to_dataset_index_view[i][0] = start_ds_idx # starting index in dataset + block_to_dataset_index_view[i][1] = start_offset # starting offset within starting index + block_to_dataset_index_view[i][2] = end_ds_idx # ending index in dataset + return block_to_dataset_index + + +cdef class DatasetSearcher(object): + """Helper for mapping "flat" indices to indices and offsets in an + underlying dataset.""" + cdef DTYPE_t current_i + cdef DTYPE_t current_offset + cdef DTYPE_t current_index + cdef DTYPE_t[:] sizes + + def __init__(self, DTYPE_t[:] sizes): + self.sizes = sizes + self.reset() + + cdef reset(self): + self.current_offset = 0 # offset within current index in underlying dataset + self.current_i = 0 # "flat" index + self.current_index = 0 # index in underlying dataset + + @cython.boundscheck(False) + @cython.wraparound(False) + @cython.nonecheck(False) + cdef int step(self, DTYPE_t i): + cdef DTYPE_t to_consume + cdef DTYPE_t remaining + if i < self.current_i: + self.reset() + if i > self.current_i: + to_consume = i - self.current_i + remaining = self.sizes[self.current_index] - self.current_offset + if remaining > to_consume: + self.current_offset += to_consume + self.current_i += to_consume + else: + assert remaining >= 0 + self.current_i += remaining + self.current_index += 1 + self.current_offset = 0 + return 1 + return 0 + + @cython.boundscheck(False) + @cython.wraparound(False) + @cython.nonecheck(False) + cdef seek(self, DTYPE_t i): + cdef int not_done = 1 + while not_done == 1: + not_done = self.step(i) + assert self.current_i == i diff --git a/fairseq-tools/fairseq/fairseq/data/transform_eos_dataset.py b/fairseq-tools/fairseq/fairseq/data/transform_eos_dataset.py new file mode 100644 index 00000000..fb14ff01 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/transform_eos_dataset.py @@ -0,0 +1,120 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from . import FairseqDataset + + +class TransformEosDataset(FairseqDataset): + """A :class:`~fairseq.data.FairseqDataset` wrapper that appends/prepends/strips EOS. + + Note that the transformation is applied in :func:`collater`. + + Args: + dataset (~fairseq.data.FairseqDataset): dataset to wrap + eos (int): index of the end-of-sentence symbol + append_eos_to_src (bool, optional): append EOS to the end of src + remove_eos_from_src (bool, optional): remove EOS from the end of src + append_eos_to_tgt (bool, optional): append EOS to the end of tgt + remove_eos_from_tgt (bool, optional): remove EOS from the end of tgt + """ + + def __init__( + self, + dataset, + eos, + append_eos_to_src=False, + remove_eos_from_src=False, + append_eos_to_tgt=False, + remove_eos_from_tgt=False, + has_target=True, + ): + if not isinstance(dataset, FairseqDataset): + raise ValueError("dataset must be an instance of FairseqDataset") + if append_eos_to_src and remove_eos_from_src: + raise ValueError("cannot combine append_eos_to_src and remove_eos_from_src") + if append_eos_to_tgt and remove_eos_from_tgt: + raise ValueError("cannot combine append_eos_to_tgt and remove_eos_from_tgt") + + self.dataset = dataset + self.eos = torch.LongTensor([eos]) + self.append_eos_to_src = append_eos_to_src + self.remove_eos_from_src = remove_eos_from_src + self.append_eos_to_tgt = append_eos_to_tgt + self.remove_eos_from_tgt = remove_eos_from_tgt + self.has_target = has_target + + # precompute how we should adjust the reported sizes + self._src_delta = 0 + self._src_delta += 1 if append_eos_to_src else 0 + self._src_delta -= 1 if remove_eos_from_src else 0 + self._tgt_delta = 0 + self._tgt_delta += 1 if append_eos_to_tgt else 0 + self._tgt_delta -= 1 if remove_eos_from_tgt else 0 + + self._checked_src = False + self._checked_tgt = False + + def _check_src(self, src, expect_eos): + if not self._checked_src: + assert (src[-1] == self.eos[0]) == expect_eos + self._checked_src = True + + def _check_tgt(self, tgt, expect_eos): + if self.has_target and not self._checked_tgt: + assert (tgt[-1] == self.eos[0]) == expect_eos + self._checked_tgt = True + + def __getitem__(self, index): + return self.dataset[index] + + def __len__(self): + return len(self.dataset) + + def collater(self, samples): + def transform(item): + if self.append_eos_to_src: + self.eos = self.eos.to(device=item["source"].device) + self._check_src(item["source"], expect_eos=False) + item["source"] = torch.cat([item["source"], self.eos]) + if self.remove_eos_from_src: + self.eos = self.eos.to(device=item["source"].device) + self._check_src(item["source"], expect_eos=True) + item["source"] = item["source"][:-1] + if self.append_eos_to_tgt: + self.eos = self.eos.to(device=item["target"].device) + self._check_tgt(item["target"], expect_eos=False) + item["target"] = torch.cat([item["target"], self.eos]) + if self.remove_eos_from_tgt: + self.eos = self.eos.to(device=item["target"].device) + self._check_tgt(item["target"], expect_eos=True) + item["target"] = item["target"][:-1] + return item + + samples = list(map(transform, samples)) + return self.dataset.collater(samples) + + def num_tokens(self, index): + return self.dataset.num_tokens(index) + + def size(self, index): + if self.has_target: + src_len, tgt_len = self.dataset.size(index) + return (src_len + self._src_delta, tgt_len + self._tgt_delta) + else: + return self.dataset.size(index) + + def ordered_indices(self): + # NOTE: we assume that the ordering does not change based on the + # addition or removal of eos + return self.dataset.ordered_indices() + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + return self.dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/data/transform_eos_lang_pair_dataset.py b/fairseq-tools/fairseq/fairseq/data/transform_eos_lang_pair_dataset.py new file mode 100644 index 00000000..1dd3d93d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/data/transform_eos_lang_pair_dataset.py @@ -0,0 +1,108 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from typing import Optional + +import torch + +from . import FairseqDataset + + +class TransformEosLangPairDataset(FairseqDataset): + """A :class:`~fairseq.data.FairseqDataset` wrapper that transform bos on + collated samples of language pair dataset. + + Note that the transformation is applied in :func:`collater`. + + Args: + dataset (~fairseq.data.FairseqDataset): dataset that collates sample into + LanguagePairDataset schema + src_eos (int): original source end-of-sentence symbol index to be replaced + new_src_eos (int, optional): new end-of-sentence symbol index to replace source eos symbol + tgt_bos (int, optional): original target beginning-of-sentence symbol index to be replaced + new_tgt_bos (int, optional): new beginning-of-sentence symbol index to replace at the + beginning of 'prev_output_tokens' + """ + + def __init__( + self, + dataset: FairseqDataset, + src_eos: int, + new_src_eos: Optional[int] = None, + tgt_bos: Optional[int] = None, + new_tgt_bos: Optional[int] = None, + ): + self.dataset = dataset + self.src_eos = src_eos + self.new_src_eos = new_src_eos + self.tgt_bos = tgt_bos + self.new_tgt_bos = new_tgt_bos + + def __getitem__(self, index): + return self.dataset[index] + + def __len__(self): + return len(self.dataset) + + def collater(self, samples, **extra_args): + samples = self.dataset.collater(samples, **extra_args) + + if self.new_src_eos is not None: + if self.dataset.left_pad_source: + assert ( + samples["net_input"]["src_tokens"][:, -1] != self.src_eos + ).sum() == 0 + samples["net_input"]["src_tokens"][:, -1] = self.new_src_eos + else: + eos_idx = samples["net_input"]["src_lengths"] - 1 + assert ( + samples["net_input"]["src_tokens"][ + torch.arange(eos_idx.size(0)), eos_idx + ] + != self.src_eos + ).sum() == 0 + eos_idx = eos_idx.resize_(len(samples["net_input"]["src_lengths"]), 1) + samples["net_input"]["src_tokens"].scatter_( + 1, eos_idx, self.new_src_eos + ) + + if ( + self.new_tgt_bos is not None + and "prev_output_tokens" in samples["net_input"] + ): + if self.dataset.left_pad_target: + # TODO: support different padding direction on target side + raise NotImplementedError( + "TransformEosLangPairDataset does not implement --left-pad-target True option" + ) + else: + assert ( + samples["net_input"]["prev_output_tokens"][:, 0] != self.tgt_bos + ).sum() == 0 + samples["net_input"]["prev_output_tokens"][:, 0] = self.new_tgt_bos + + return samples + + def num_tokens(self, index): + return self.dataset.num_tokens(index) + + def size(self, index): + return self.dataset.size(index) + + @property + def sizes(self): + # dataset.sizes can be a dynamically computed sizes: + return self.dataset.sizes + + def ordered_indices(self): + return self.dataset.ordered_indices() + + @property + def supports_prefetch(self): + return getattr(self.dataset, "supports_prefetch", False) + + def prefetch(self, indices): + return self.dataset.prefetch(indices) diff --git a/fairseq-tools/fairseq/fairseq/dataclass/__init__.py b/fairseq-tools/fairseq/fairseq/dataclass/__init__.py new file mode 100644 index 00000000..32870814 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/dataclass/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .utils import ChoiceEnum, FairseqDataclass + + +__all__ = ["FairseqDataclass", "ChoiceEnum"] diff --git a/fairseq-tools/fairseq/fairseq/dataclass/constants.py b/fairseq-tools/fairseq/fairseq/dataclass/constants.py new file mode 100644 index 00000000..21b36450 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/dataclass/constants.py @@ -0,0 +1,13 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.dataclass.utils import ChoiceEnum + + +LOG_FORMAT_CHOICES = ChoiceEnum(["json", "none", "simple", "tqdm"]) +DDP_BACKEND_CHOICES = ChoiceEnum(["c10d", "no_c10d"]) +DISTRIBUTED_WRAPPER_CHOICES = ChoiceEnum(["DDP", "SlowMo"]) +ZERO_SHARDING_CHOICES = ChoiceEnum(["none", "os"]) +PIPELINE_CHECKPOINT_CHOICES = ChoiceEnum(["always", "never", "except_last"]) diff --git a/fairseq-tools/fairseq/fairseq/dataclass/data_class.py b/fairseq-tools/fairseq/fairseq/dataclass/data_class.py new file mode 100644 index 00000000..1d25c19f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/dataclass/data_class.py @@ -0,0 +1,773 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys +from argparse import Namespace +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Tuple, Type + +import torch +from fairseq.criterions import CRITERION_DATACLASS_REGISTRY +from fairseq.data.indexed_dataset import get_available_dataset_impl +from fairseq.dataclass.constants import ( + DDP_BACKEND_CHOICES, + DISTRIBUTED_WRAPPER_CHOICES, + LOG_FORMAT_CHOICES, + PIPELINE_CHECKPOINT_CHOICES, + ZERO_SHARDING_CHOICES, +) +from fairseq.dataclass.utils import ChoiceEnum, FairseqDataclass +from fairseq.models import ARCH_MODEL_REGISTRY, MODEL_DATACLASS_REGISTRY +from fairseq.optim import OPTIMIZER_DATACLASS_REGISTRY +from fairseq.optim.bmuf import FairseqBMUFConfig +from fairseq.optim.lr_scheduler import LR_SCHEDULER_DATACLASS_REGISTRY +from fairseq.tasks import TASK_DATACLASS_REGISTRY +from hydra.core.config_store import ConfigStore + + +@dataclass +class CommonParams(FairseqDataclass): + # This is the core dataclass including common parameters shared by all different jobs. Please append your params to other dataclasses if they were + # used for a particular purpose or task, such as those dedicated for `distributed training`, `optimization`, etc. + no_progress_bar: bool = field( + default=False, metadata={"help": "disable progress bar"} + ) + log_interval: int = field( + default=100, + metadata={ + "help": "log progress every N batches (when progress bar is disabled)" + }, + ) + log_format: Optional[LOG_FORMAT_CHOICES] = field( + default=None, metadata={"help": "log format to use"} + ) + tensorboard_logdir: Optional[str] = field( + default=None, + metadata={ + "help": "path to save logs for tensorboard, should match --logdir " + "of running tensorboard (default: no tensorboard logging)" + }, + ) + seed: int = field( + default=1, metadata={"help": "pseudo random number generator seed"} + ) + cpu: bool = field(default=False, metadata={"help": "use CPU instead of CUDA"}) + tpu: bool = field(default=False, metadata={"help": "use TPU instead of CUDA"}) + bf16: bool = field(default=False, metadata={"help": "use bfloat16; implies --tpu"}) + memory_efficient_bf16: bool = field( + default=False, + metadata={ + "help": "use a memory-efficient version of BF16 training; implies --bf16" + }, + ) + fp16: bool = field(default=False, metadata={"help": "use FP16"}) + memory_efficient_fp16: bool = field( + default=False, + metadata={ + "help": "use a memory-efficient version of FP16 training; implies --fp16" + }, + ) + fp16_no_flatten_grads: bool = field( + default=False, metadata={"help": "don't flatten FP16 grads tensor"} + ) + fp16_init_scale: int = field( + default=2 ** 7, metadata={"help": "default FP16 loss scale"} + ) + fp16_scale_window: Optional[int] = field( + default=None, + metadata={"help": "number of updates before increasing loss scale"}, + ) + fp16_scale_tolerance: float = field( + default=0.0, + metadata={ + "help": "pct of updates that can overflow before decreasing the loss scale" + }, + ) + min_loss_scale: float = field( + default=1e-4, + metadata={"help": "minimum FP16 loss scale, after which training is stopped"}, + ) + threshold_loss_scale: Optional[float] = field( + default=None, metadata={"help": "threshold FP16 loss scale from below"} + ) + user_dir: Optional[str] = field( + default=None, + metadata={ + "help": "path to a python module containing custom extensions (tasks and/or architectures)" + }, + ) + empty_cache_freq: int = field( + default=0, + metadata={"help": "how often to clear the PyTorch CUDA cache (0 to disable)"}, + ) + all_gather_list_size: int = field( + default=16384, + metadata={"help": "number of bytes reserved for gathering stats from workers"}, + ) + model_parallel_size: int = field( + default=1, metadata={"help": "total number of GPUs to parallelize model over"} + ) + checkpoint_suffix: str = field( + default="", metadata={"help": "suffix to add to the checkpoint file name"} + ) + checkpoint_shard_count: int = field( + default=1, + metadata={ + "help": "Number of shards containing the checkpoint - " + "if the checkpoint is over 300GB, it is preferable " + "to split it into shards to prevent OOM on CPU while loading " + "the checkpoint" + }, + ) + quantization_config_path: Optional[str] = field( + default=None, metadata={"help": "path to quantization config file"} + ) + profile: bool = field( + default=False, metadata={"help": "enable autograd profiler emit_nvtx"} + ) + + +@dataclass +class DistributedTrainingParams(FairseqDataclass): + distributed_world_size: int = field( + default=max(1, torch.cuda.device_count()), + metadata={ + "help": "total number of GPUs across all nodes (default: all visible GPUs)" + }, + ) + distributed_rank: Optional[int] = field( + default=0, metadata={"help": "rank of the current worker"} + ) + distributed_backend: str = field( + default="nccl", metadata={"help": "distributed backend"} + ) + distributed_init_method: Optional[str] = field( + default=None, + metadata={ + "help": "typically tcp://hostname:port that will be used to " + "establish initial connetion" + }, + ) + distributed_port: int = field( + default=-1, + metadata={ + "help": "port number (not required if using --distributed-init-method)" + }, + ) + device_id: int = field( + default=0, + metadata={ + "help": "which GPU to use (usually configured automatically)", + "argparse_alias": "--local_rank", + }, + ) + distributed_no_spawn: bool = field( + default=False, + metadata={ + "help": "do not spawn multiple processes even if multiple GPUs are visible" + }, + ) + ddp_backend: DDP_BACKEND_CHOICES = field( + default="c10d", metadata={"help": "DistributedDataParallel backend"} + ) + bucket_cap_mb: int = field( + default=25, metadata={"help": "bucket size for reduction"} + ) + fix_batches_to_gpus: bool = field( + default=False, + metadata={ + "help": "don't shuffle batches between GPUs; this reduces overall " + "randomness and may affect precision but avoids the cost of re-reading the data" + }, + ) + find_unused_parameters: bool = field( + default=False, + metadata={ + "help": "disable unused parameter detection (not applicable to " + "no_c10d ddp-backend" + }, + ) + fast_stat_sync: bool = field( + default=False, + metadata={"help": "[deprecated] this is now defined per Criterion"}, + ) + broadcast_buffers: bool = field( + default=False, + metadata={ + "help": "Copy non-trainable parameters between GPUs, such as " + "batchnorm population statistics" + }, + ) + distributed_wrapper: DISTRIBUTED_WRAPPER_CHOICES = field( + default="DDP", metadata={"help": "DistributedDataParallel backend"} + ) + slowmo_momentum: Optional[float] = field( + default=None, + metadata={ + "help": "SlowMo momentum term; by default use 0.0 for 16 GPUs, " + "0.2 for 32 GPUs; 0.5 for 64 GPUs, 0.6 for > 64 GPUs" + }, + ) + slowmo_algorithm: str = field( + default="LocalSGD", metadata={"help": "whether to use LocalSGD or SGP"} + ) + localsgd_frequency: int = field( + default=3, metadata={"help": "Local SGD allreduce frequency"} + ) + nprocs_per_node: int = field( + default=max(1, torch.cuda.device_count()), + metadata={ + "help": "number of GPUs in each node. An allreduce operation across GPUs in " + "a node is very fast. Hence, we do allreduce across GPUs in a node, " + "and gossip across different nodes" + }, + ) + pipeline_model_parallel: bool = field( + default=False, + metadata={"help": "if set, use pipeline model parallelism across GPUs"}, + ) + pipeline_balance: str = field( + default=None, + metadata={ + "help": "partition the model into N_K pieces, where each piece " + "contains N_i layers. The sum(args.pipeline_balance) " + "should equal the total number of layers in the model" + }, + ) + pipeline_devices: str = field( + default=None, + metadata={ + "help": "a list of device indices indicating which device to place " + "each of the N_K partitions. The length of this list should " + "equal the length of the --pipeline-balance argument" + }, + ) + pipeline_chunks: int = field( + default=0, metadata={"help": "microbatch count for pipeline model parallelism"} + ) + pipeline_encoder_balance: str = field( + default=None, + metadata={ + "help": "partition the pipeline parallel encoder into N_K pieces, where each piece " + "contains N_i layers. The sum(args.pipeline_encoder_balance) " + "should equal the total number of encoder layers in the model" + }, + ) + pipeline_encoder_devices: str = field( + default=None, + metadata={ + "help": "a list of device indices indicating which device to place " + "each of the N_K partitions. The length of this list should " + "equal the length of the --pipeline-encoder-balance argument" + }, + ) + pipeline_decoder_balance: str = field( + default=None, + metadata={ + "help": "partition the pipeline parallel decoder into N_K pieces, where each piece " + "contains N_i layers. The sum(args.pipeline_decoder_balance) " + "should equal the total number of decoder layers in the model" + }, + ) + pipeline_decoder_devices: str = field( + default=None, + metadata={ + "help": "a list of device indices indicating which device to place " + "each of the N_K partitions. The length of this list should " + "equal the length of the --pipeline-decoder-balance argument" + }, + ) + pipeline_checkpoint: PIPELINE_CHECKPOINT_CHOICES = field( + default="never", + metadata={"help": "checkpointing mode for pipeline model parallelism"}, + ) + zero_sharding: ZERO_SHARDING_CHOICES = field( + default="none", metadata={"help": "ZeRO sharding"} + ) + + +@dataclass +class DatasetParams(FairseqDataclass): + num_workers: int = field( + default=1, metadata={"help": "how many subprocesses to use for data loading"} + ) + skip_invalid_size_inputs_valid_test: bool = field( + default=False, + metadata={"help": "ignore too long or too short lines in valid and test set"}, + ) + max_tokens: Optional[int] = field( + default=None, metadata={"help": "maximum number of tokens in a batch"} + ) + batch_size: Optional[int] = field( + default=None, metadata={"help": "number of examples in a batch"} + ) + required_batch_size_multiple: int = field( + default=8, metadata={"help": "batch size will be a multiplier of this value"} + ) + required_seq_len_multiple: int = field( + default=1, + metadata={ + "help": "maximum sequence length in batch will be a multiplier of this value" + }, + ) + dataset_impl: Optional[ChoiceEnum(get_available_dataset_impl())] = field( + default=None, metadata={"help": "output dataset implementation"} + ) + data_buffer_size: int = field( + default=10, metadata={"help": "Number of batches to preload"} + ) + train_subset: str = field( + default="train", + metadata={"help": "data subset to use for training (e.g. train, valid, test)"}, + ) + valid_subset: str = field( + default="valid", + metadata={ + "help": "comma separated list of data subsets to use for validation" + " (e.g. train, valid, test)" + }, + ) + validate_interval: int = field( + default=1, metadata={"help": "validate every N epochs"} + ) + validate_interval_updates: int = field( + default=0, metadata={"help": "validate every N updates"} + ) + validate_after_updates: int = field( + default=0, metadata={"help": "dont validate until reaching this many updates"} + ) + fixed_validation_seed: Optional[int] = field( + default=None, metadata={"help": "specified random seed for validation"} + ) + disable_validation: bool = field( + default=False, metadata={"help": "disable validation"} + ) + max_tokens_valid: Optional[int] = field( + default=None, + metadata={ + "help": "maximum number of tokens in a validation batch" + " (defaults to --max-tokens)" + }, + ) + batch_size_valid: Optional[int] = field( + default=None, + metadata={ + "help": "batch size of the validation batch" " (defaults to --batch-size)" + }, + ) + curriculum: int = field( + default=0, metadata={"help": "don't shuffle batches for first N epochs"} + ) + gen_subset: str = field( + default="test", + metadata={"help": "data subset to generate (train, valid, test)"}, + ) + num_shards: int = field( + default=1, metadata={"help": "shard generation over N shards"} + ) + shard_id: int = field( + default=0, metadata={"help": "id of the shard to generate (id < num_shards)"} + ) + + +@dataclass +class OptimizationParams(FairseqDataclass): + max_epoch: int = field( + default=0, metadata={"help": "force stop training at specified epoch"} + ) + max_update: int = field( + default=0, metadata={"help": "force stop training at specified update"} + ) + stop_time_hours: float = field( + default=0, + metadata={ + "help": "force stop training after specified cumulative time (if >0)" + }, + ) + clip_norm: float = field( + default=0.0, metadata={"help": "clip threshold of gradients"} + ) + sentence_avg: bool = field( + default=False, + metadata={ + "help": "normalize gradients by the number of sentences in a batch" + " (default is to normalize by number of tokens)" + }, + ) + update_freq: List[int] = field( + default_factory=lambda: [1], + metadata={"help": "update parameters every N_i batches, when in epoch i"}, + ) + lr: List[float] = field( + default_factory=lambda: [0.25], + metadata={ + "help": "learning rate for the first N epochs; all epochs >N using LR_N" + " (note: this may be interpreted differently depending on --lr-scheduler)" + }, + ) + min_lr: float = field( + default=-1.0, + metadata={"help": "stop training when the learning rate reaches this minimum"}, + ) + use_bmuf: bool = field( + default=False, + metadata={ + "help": "specify global optimizer for syncing models on different GPUs/shards" + }, + ) + + +@dataclass +class CheckpointParams(FairseqDataclass): + save_dir: str = field( + default="checkpoints", metadata={"help": "path to save checkpoints"} + ) + restore_file: str = field( + default="checkpoint_last.pt", + metadata={ + "help": "filename from which to load checkpoint " + "(default: <save-dir>/checkpoint_last.pt" + }, + ) + finetune_from_model: Optional[str] = field( + default=None, + metadata={ + "help": "finetune from a pretrained model; note that meters and lr scheduler will be reset" + }, + ) + reset_dataloader: bool = field( + default=False, + metadata={ + "help": "if set, does not reload dataloader state from the checkpoint" + }, + ) + reset_lr_scheduler: bool = field( + default=False, + metadata={ + "help": "if set, does not load lr scheduler state from the checkpoint" + }, + ) + reset_meters: bool = field( + default=False, + metadata={"help": "if set, does not load meters from the checkpoint"}, + ) + reset_optimizer: bool = field( + default=False, + metadata={"help": "if set, does not load optimizer state from the checkpoint"}, + ) + optimizer_overrides: str = field( + default="{}", + metadata={ + "help": "a dictionary used to override optimizer args when loading a checkpoint" + }, + ) + save_interval: int = field( + default=1, metadata={"help": "save a checkpoint every N epochs"} + ) + save_interval_updates: int = field( + default=0, metadata={"help": "save a checkpoint (and validate) every N updates"} + ) + keep_interval_updates: int = field( + default=-1, + metadata={ + "help": "keep the last N checkpoints saved with --save-interval-updates" + }, + ) + keep_last_epochs: int = field( + default=-1, metadata={"help": "keep last N epoch checkpoints"} + ) + keep_best_checkpoints: int = field( + default=-1, metadata={"help": "keep best N checkpoints based on scores"} + ) + no_save: bool = field( + default=False, metadata={"help": "don't save models or checkpoints"} + ) + no_epoch_checkpoints: bool = field( + default=False, metadata={"help": "only store last and best checkpoints"} + ) + no_last_checkpoints: bool = field( + default=False, metadata={"help": "don't store last checkpoints"} + ) + no_save_optimizer_state: bool = field( + default=False, + metadata={"help": "don't save optimizer-state as part of checkpoint"}, + ) + best_checkpoint_metric: str = field( + default="loss", metadata={"help": 'metric to use for saving "best" checkpoints'} + ) + maximize_best_checkpoint_metric: bool = field( + default=False, + metadata={ + "help": 'select the largest metric value for saving "best" checkpoints' + }, + ) + patience: int = field( + default=-1, + metadata={ + "help": ( + "early stop training if valid performance doesn't " + "improve for N consecutive validation runs; note " + "that this is influenced by --validate-interval" + ) + }, + ) + + +@dataclass +class CommonEvalParams(FairseqDataclass): + path: Optional[str] = field( + default=None, metadata={"help": "path(s) to model file(s), colon separated"} + ) + remove_bpe: Optional[str] = field( + default=None, + metadata={ + "help": "remove BPE tokens before scoring (can be set to sentencepiece)", + "argparse_const": "@@ ", + }, + ) + quiet: bool = field(default=False, metadata={"help": "only print final scores"}) + model_overrides: str = field( + default="{}", + metadata={ + "help": "a dictionary used to override model args at generation that were used during model training" + }, + ) + results_path: Optional[str] = field( + default=None, metadata={"help": "path to save eval results (optional)"} + ) + + +@dataclass +class EvalLMParams(FairseqDataclass): + output_word_probs: bool = field( + default=False, + metadata={ + "help": "if set, outputs words and their predicted log probabilities to standard output" + }, + ) + output_word_stats: bool = field( + default=False, + metadata={ + "help": "if set, outputs word statistics such as word count, average probability, etc" + }, + ) + context_window: int = field( + default=0, + metadata={ + "help": "ensures that every evaluated token has access to a context of at least this size, if possible" + }, + ) + softmax_batch: int = field( + default=sys.maxsize, + metadata={ + "help": "if BxT is more than this, will batch the softmax over vocab to this amount of tokens, in order to fit into GPU memory" + }, + ) + + +@dataclass +class TrainingConfig(FairseqDataclass): + """Config for training, a composition of training params""" + + common: CommonParams = CommonParams() + distributed_training: DistributedTrainingParams = DistributedTrainingParams() + dataset: DatasetParams = DatasetParams() + optimization: OptimizationParams = OptimizationParams() + checkpoint: CheckpointParams = CheckpointParams() + bmuf: FairseqBMUFConfig = FairseqBMUFConfig() + + +@dataclass +class EvalLMConfig(FairseqDataclass): + """Config for eval lm, a composition of eval_lm params""" + + common: CommonParams = CommonParams() + distributed_training: DistributedTrainingParams = DistributedTrainingParams() + dataset: DatasetParams = DatasetParams() + optimization: OptimizationParams = OptimizationParams() + checkpoint: CheckpointParams = CheckpointParams() + bmuf: FairseqBMUFConfig = FairseqBMUFConfig() + common_eval: CommonEvalParams = CommonEvalParams() + eval_lm: EvalLMParams = EvalLMParams() + + +def register_params_dataclass( + cs: ConfigStore, name: str, group: str, data_class: Type[FairseqDataclass] +) -> None: + """register params dataclass in config store""" + node_ = data_class(_name=data_class.name()) + cs.store(name=name, group=group, node=node_) + + +def register_module_dataclass( + cs: ConfigStore, registry: Dict[str, Any], group: str +) -> None: + """register dataclasses defined in modules in config store, for example, in migrated tasks, models, etc.""" + # note that if `group == model`, we register all model archs, not the model name. + for k, v in registry.items(): + if v is not None: + node_ = v(_name=k) + cs.store(name=k, group=group, node=node_) + + +def register_training_hydra_cfg(cs: ConfigStore, name: str = "default") -> None: + """cs: config store instance, register common training configs""" + + register_params_dataclass( + cs, name="training_params", group="params", data_class=TrainingConfig + ) + + register_module_dataclass(cs, TASK_DATACLASS_REGISTRY, "task") + register_module_dataclass(cs, MODEL_DATACLASS_REGISTRY, "model") + register_module_dataclass(cs, CRITERION_DATACLASS_REGISTRY, "criterion") + register_module_dataclass(cs, OPTIMIZER_DATACLASS_REGISTRY, "optimizer") + register_module_dataclass(cs, LR_SCHEDULER_DATACLASS_REGISTRY, "lr_scheduler") + + +def register_eval_lm_hydra_cfg(cs: ConfigStore, name: str = "default") -> None: + """cs: config store instance, register common training configs""" + + register_params_dataclass( + cs, name="eval_lm_params", group="params", data_class=EvalLMConfig + ) + + register_module_dataclass(cs, TASK_DATACLASS_REGISTRY, "task") + register_module_dataclass(cs, CRITERION_DATACLASS_REGISTRY, "criterion") + register_module_dataclass(cs, OPTIMIZER_DATACLASS_REGISTRY, "optimizer") + register_module_dataclass(cs, LR_SCHEDULER_DATACLASS_REGISTRY, "lr_scheduler") + + +def _override_attr( + sub_node: str, data_class: Type[FairseqDataclass], args: Namespace +) -> List[str]: + overrides = [] + for k in data_class.__dataclass_fields__.keys(): + if k == "_name": + # private member, skip + continue + if not hasattr(args, k): + # print(f"cannot override {sub_node}.{k} since args does not have attribute {k}") + continue + if getattr(args, k) is None: + overrides.append("{}.{}=null".format(sub_node, k)) + elif getattr(args, k) == "": + overrides.append("{}.{}=''".format(sub_node, k)) + elif isinstance(getattr(args, k), str): + if ( + getattr(args, k).startswith("[") + or getattr(args, k).startswith("(") + or getattr(args, k).startswith("{") + or ("," in getattr(args, k)) + ): + overrides.append("{}.{}='{}'".format(sub_node, k, getattr(args, k))) + else: + overrides.append("{}.{}={}".format(sub_node, k, getattr(args, k))) + else: + overrides.append("{}.{}={}".format(sub_node, k, getattr(args, k))) + return overrides + + +def override_training_args(args: Namespace) -> Tuple[List[str], List[str]]: + overrides = [] + + overrides.extend(_override_attr("params.common", CommonParams, args)) + overrides.extend(_override_attr("params.dataset", DatasetParams, args)) + overrides.extend( + _override_attr("params.distributed_training", DistributedTrainingParams, args) + ) + overrides.extend(_override_attr("params.optimization", OptimizationParams, args)) + overrides.extend(_override_attr("params.checkpoint", CheckpointParams, args)) + overrides.extend(_override_attr("params.bmuf", FairseqBMUFConfig, args)) + module_overrides, module_deletes = override_module_args(args) + overrides.extend(module_overrides) + + return overrides, module_deletes + + +def override_eval_lm_args(args: Namespace) -> Tuple[List[str], List[str]]: + overrides = [] + + overrides.extend(_override_attr("params.common", CommonParams, args)) + overrides.extend(_override_attr("params.dataset", DatasetParams, args)) + overrides.extend( + _override_attr("params.distributed_training", DistributedTrainingParams, args) + ) + overrides.extend(_override_attr("params.common_eval", CommonEvalParams, args)) + overrides.extend(_override_attr("params.eval_lm", EvalLMParams, args)) + overrides.extend(_override_attr("params.bmuf", FairseqBMUFConfig, args)) + module_overrides, module_deletes = override_module_args(args) + overrides.extend(module_overrides) + + return overrides, module_deletes + + +def override_module_args(args: Namespace) -> Tuple[List[str], List[str]]: + """use the field in args to overrides those in cfg""" + overrides = [] + deletes = [] + + if args is not None: + assert ( + hasattr(args, "task") + and hasattr(args, "criterion") + and hasattr(args, "optimizer") + and hasattr(args, "lr_scheduler") + ) + if args.task in TASK_DATACLASS_REGISTRY: + overrides.append("task={}".format(args.task)) + overrides.append("task._name={}".format(args.task)) + overrides.extend( + _override_attr("task", TASK_DATACLASS_REGISTRY[args.task], args) + ) + else: + deletes.append("task") + if args.criterion in CRITERION_DATACLASS_REGISTRY: + overrides.append("criterion={}".format(args.criterion)) + overrides.append("criterion._name={}".format(args.criterion)) + overrides.extend( + _override_attr( + "criterion", CRITERION_DATACLASS_REGISTRY[args.criterion], args + ) + ) + else: + deletes.append("criterion") + if args.optimizer in OPTIMIZER_DATACLASS_REGISTRY: + overrides.append("optimizer={}".format(args.optimizer)) + overrides.append("optimizer._name={}".format(args.optimizer)) + overrides.extend( + _override_attr( + "optimizer", OPTIMIZER_DATACLASS_REGISTRY[args.optimizer], args + ) + ) + else: + deletes.append("optimizer") + if args.lr_scheduler in LR_SCHEDULER_DATACLASS_REGISTRY: + overrides.append("lr_scheduler={}".format(args.lr_scheduler)) + overrides.append("lr_scheduler._name={}".format(args.lr_scheduler)) + overrides.extend( + _override_attr( + "lr_scheduler", + LR_SCHEDULER_DATACLASS_REGISTRY[args.lr_scheduler], + args, + ) + ) + else: + deletes.append("lr_scheduler") + + no_dc = True + if hasattr(args, "arch"): + if args.arch in ARCH_MODEL_REGISTRY: + m_cls = ARCH_MODEL_REGISTRY[args.arch] + dc = getattr(m_cls, "__dataclass", None) + if dc is not None: + overrides.append("model={}".format(args.arch)) + overrides.append("model._name={}".format(args.arch)) + # override model params with those exist in args + overrides.extend(_override_attr("model", dc, args)) + no_dc = False + if no_dc: + deletes.append("model") + + return overrides, deletes diff --git a/fairseq-tools/fairseq/fairseq/dataclass/utils.py b/fairseq-tools/fairseq/fairseq/dataclass/utils.py new file mode 100644 index 00000000..836a0777 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/dataclass/utils.py @@ -0,0 +1,221 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from argparse import ArgumentParser +from dataclasses import MISSING, dataclass +from enum import Enum +from typing import Any, Dict, List, Optional + + +def eval_str_list(x, x_type=float): + if x is None: + return None + if isinstance(x, str): + x = eval(x) + try: + return list(map(x_type, x)) + except TypeError: + return [x_type(x)] + + +class StrEnum(Enum): + def __str__(self): + return self.value + + def __eq__(self, other: str): + return self.value == other + + def __repr__(self): + return self.value + + +def ChoiceEnum(choices: List[str]): + """return the Enum class used to enforce list of choices""" + return StrEnum("Choices", {k: k for k in choices}) + + +@dataclass +class FairseqDataclass: + """fairseq base dataclass that supported fetching attributes and metas""" + + _name: Optional[str] = None + + @staticmethod + def name(): + return None + + def _get_all_attributes(self) -> List[str]: + return [k for k in self.__dataclass_fields__.keys()] + + def _get_meta( + self, attribute_name: str, meta: str, default: Optional[Any] = None + ) -> Any: + return self.__dataclass_fields__[attribute_name].metadata.get(meta, default) + + def _get_name(self, attribute_name: str) -> str: + return self.__dataclass_fields__[attribute_name].name + + def _get_default(self, attribute_name: str) -> Any: + if hasattr(self, attribute_name): + if str(getattr(self, attribute_name)).startswith("${"): + return str(getattr(self, attribute_name)) + elif str(self.__dataclass_fields__[attribute_name].default).startswith( + "${" + ): + return str(self.__dataclass_fields__[attribute_name].default) + elif ( + getattr(self, attribute_name) + != self.__dataclass_fields__[attribute_name].default + ): + return getattr(self, attribute_name) + return self.__dataclass_fields__[attribute_name].default + + def _get_default_factory(self, attribute_name: str) -> Any: + if hasattr(self, attribute_name): + if str(getattr(self, attribute_name)).startswith("${"): + return str(getattr(self, attribute_name)) + elif str(self.__dataclass_fields__[attribute_name].default).startswith( + "${" + ): + return str(self.__dataclass_fields__[attribute_name].default) + elif ( + getattr(self, attribute_name) + != self.__dataclass_fields__[attribute_name].default_factory() + ): + return getattr(self, attribute_name) + return self.__dataclass_fields__[attribute_name].default_factory() + + def _get_type(self, attribute_name: str) -> Any: + return self.__dataclass_fields__[attribute_name].type + + def _get_help(self, attribute_name: str) -> Any: + return self._get_meta(attribute_name, "help") + + def _get_argparse_const(self, attribute_name: str) -> Any: + return self._get_meta(attribute_name, "argparse_const") + + def _get_argparse_alias(self, attribute_name: str) -> Any: + return self._get_meta(attribute_name, "argparse_alias") + + def _get_choices(self, attribute_name: str) -> Any: + return self._get_meta(attribute_name, "choices") + + +def gen_parser_from_dataclass( + parser: ArgumentParser, + dataclass_instance: FairseqDataclass, + delete_default: bool = False, +) -> None: + """convert a dataclass instance to tailing parser arguments""" + import re + + def argparse_name(name: str): + if name == "data": + # normally data is positional args + return name + if name == "_name": + # private member, skip + return None + return "--" + name.replace("_", "-") + + def interpret_dc_type(field_type): + if isinstance(field_type, str): + raise RuntimeError() + typestring = str(field_type) + if re.match(r"(typing.|^)Union\[(.*), NoneType\]$", typestring): + return field_type.__args__[0] + return field_type + + def get_kwargs_from_dc( + dataclass_instance: FairseqDataclass, k: str + ) -> Dict[str, Any]: + """k: dataclass attributes""" + field_type = dataclass_instance._get_type(k) + inter_type = interpret_dc_type(field_type) + if isinstance(inter_type, type) and issubclass(inter_type, List): + field_default = dataclass_instance._get_default_factory(k) + else: + field_default = dataclass_instance._get_default(k) + + if isinstance(inter_type, type) and issubclass(inter_type, Enum): + field_choices = [t.value for t in list(inter_type)] + else: + field_choices = None + + field_help = dataclass_instance._get_help(k) + field_const = dataclass_instance._get_argparse_const(k) + kwargs = {} + if isinstance(field_default, str) and field_default.startswith("${"): + kwargs["default"] = field_default + else: + if field_default is MISSING: + kwargs["required"] = True + if field_choices is not None: + kwargs["choices"] = field_choices + if (isinstance(inter_type, type) and issubclass(inter_type, List)) or ( + "List" in str(inter_type) + ): + if "int" in str(inter_type): + kwargs["type"] = lambda x: eval_str_list(x, int) + elif "float" in str(inter_type): + kwargs["type"] = lambda x: eval_str_list(x, float) + elif "str" in str(inter_type): + kwargs["type"] = lambda x: eval_str_list(x, str) + else: + raise NotImplementedError() + if field_default is not MISSING: + kwargs["default"] = ",".join(map(str, field_default)) + elif ( + isinstance(inter_type, type) and issubclass(inter_type, Enum) + ) or "Enum" in str(inter_type): + kwargs["type"] = str + if field_default is not MISSING: + if isinstance(field_default, Enum): + kwargs["default"] = field_default.value + else: + kwargs["default"] = field_default + elif inter_type is bool: + kwargs["action"] = ( + "store_false" if field_default is True else "store_true" + ) + kwargs["default"] = field_default + else: + kwargs["type"] = inter_type + if field_default is not MISSING: + kwargs["default"] = field_default + + kwargs["help"] = field_help + if field_const is not None: + kwargs["const"] = field_const + kwargs["nargs"] = "?" + return kwargs + + for k in dataclass_instance._get_all_attributes(): + field_name = argparse_name(dataclass_instance._get_name(k)) + if field_name is None: + continue + + kwargs = get_kwargs_from_dc(dataclass_instance, k) + + field_args = [field_name] + alias = dataclass_instance._get_argparse_alias(k) + if alias is not None: + field_args.append(alias) + + if "default" in kwargs: + if isinstance(kwargs["default"], str) and kwargs["default"].startswith( + "${" + ): + if kwargs["help"] is None: + # this is a field with a name that will be added elsewhere + continue + else: + del kwargs["default"] + if delete_default: + del kwargs["default"] + try: + parser.add_argument(*field_args, **kwargs) + except ArgumentError: + pass diff --git a/fairseq-tools/fairseq/fairseq/distributed_utils.py b/fairseq-tools/fairseq/fairseq/distributed_utils.py new file mode 100644 index 00000000..bf66d05d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/distributed_utils.py @@ -0,0 +1,446 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +import logging +import os +import pickle +import random +import socket +import struct +import subprocess +import warnings +from collections import OrderedDict +from typing import Any, Dict, Mapping + +import torch +import torch.distributed as dist +from fairseq import utils + + +logger = logging.getLogger(__name__) + + +def is_master(args): + return args.distributed_rank == 0 + + +def infer_init_method(args, force_distributed=False): + if args.distributed_init_method is not None or getattr(args, "tpu", False): + return + + if args.pipeline_model_parallel: + balance_exists = ( + args.pipeline_balance is not None + or args.pipeline_encoder_balance is not None + or args.pipeline_decoder_balance is not None + ) + devices_exist = ( + args.pipeline_devices is not None + or args.pipeline_encoder_devices is not None + or args.pipeline_decoder_devices is not None + ) + if not balance_exists: + raise ValueError( + "--pipeline-balance is currently required for pipeline model parallelism" + ) + if not devices_exist: + raise ValueError( + "--pipeline-devices is currently required for pipeline model parallelism" + ) + + args.pipeline_balance = utils.eval_str_list(args.pipeline_balance, type=int) + if args.pipeline_devices is not None: + args.pipeline_devices = utils.eval_str_list(args.pipeline_devices, type=int) + num_pipeline_devices = len(set(args.pipeline_devices)) + else: + args.pipeline_encoder_devices = utils.eval_str_list( + args.pipeline_encoder_devices, type=int + ) + args.pipeline_decoder_devices = utils.eval_str_list( + args.pipeline_decoder_devices, type=int + ) + num_pipeline_devices = len( + set(args.pipeline_encoder_devices + args.pipeline_decoder_devices) + ) + gpus_per_node = torch.cuda.device_count() + assert ( + gpus_per_node >= num_pipeline_devices + and gpus_per_node % num_pipeline_devices == 0 + ), ( + "the number of unique device IDs in --pipeline-devices must evenly divide " + "the number of GPUs per node (multi-node pipelining is not yet supported)" + ) + num_pipelines_per_node = gpus_per_node // num_pipeline_devices + + # support torch.distributed.launch + if all( + key in os.environ + for key in ["MASTER_ADDR", "MASTER_PORT", "WORLD_SIZE", "RANK"] + ): + args.distributed_init_method = "env://" + args.distributed_world_size = int(os.environ["WORLD_SIZE"]) + args.distributed_rank = int(os.environ["RANK"]) + # processes are created by torch.distributed.launch + args.distributed_no_spawn = True + + # we can determine the init method automatically for Slurm + elif args.distributed_port > 0: + node_list = os.environ.get("SLURM_STEP_NODELIST") + if node_list is None: + node_list = os.environ.get("SLURM_JOB_NODELIST") + if node_list is not None: + try: + hostnames = subprocess.check_output( + ["scontrol", "show", "hostnames", node_list] + ) + args.distributed_init_method = "tcp://{host}:{port}".format( + host=hostnames.split()[0].decode("utf-8"), + port=args.distributed_port, + ) + nnodes = int(os.environ.get("SLURM_NNODES")) + ntasks_per_node = os.environ.get("SLURM_NTASKS_PER_NODE") + if ntasks_per_node is not None: + ntasks_per_node = int(ntasks_per_node) + else: + ntasks = int(os.environ.get("SLURM_NTASKS")) + nnodes = int(os.environ.get("SLURM_NNODES")) + assert ntasks % nnodes == 0 + ntasks_per_node = int(ntasks / nnodes) + if ntasks_per_node == 1: + gpus_per_node = torch.cuda.device_count() + node_id = int(os.environ.get("SLURM_NODEID")) + args.distributed_rank = node_id * gpus_per_node + args.distributed_world_size = nnodes * gpus_per_node + elif args.pipeline_model_parallel: + assert ntasks_per_node == num_pipelines_per_node, ( + "SLURM --ntasks-per-node must match number of pipelines per " + "node (={})".format(num_pipelines_per_node) + ) + args.distributed_no_spawn = True + # For 4-way MP on nodes with 8 GPUs, ranks will be [0, 1] on + # the first node, [1, 2] on the second node, etc. This + # matches torch.distributed.launch. + node_id = int(os.environ.get("SLURM_NODEID")) + local_id = int(os.environ.get("SLURM_LOCALID")) + args.distributed_rank = node_id * num_pipelines_per_node + local_id + # In the above example, device_id will always be in [0, 1], + # which also matches torch.distributed.launch. + args.device_id = local_id + # We also want to set distributed_world_size to be the total + # number of pipelines across all nodes. + args.distributed_world_size = nnodes * num_pipelines_per_node + else: + assert ntasks_per_node == args.distributed_world_size // nnodes + args.distributed_no_spawn = True + args.distributed_rank = int(os.environ.get("SLURM_PROCID")) + args.device_id = int(os.environ.get("SLURM_LOCALID")) + except subprocess.CalledProcessError as e: # scontrol failed + raise e + except FileNotFoundError: # Slurm is not installed + pass + + elif args.distributed_world_size > 1 or force_distributed: + # fallback for single node with multiple GPUs + assert args.distributed_world_size <= torch.cuda.device_count() + port = random.randint(10000, 20000) + args.distributed_init_method = "tcp://localhost:{port}".format(port=port) + + if args.pipeline_model_parallel: + if not args.distributed_no_spawn: + # When distributed_no_spawn is False, we expect distributed_rank and + # distributed_world_size to be based on the total number of GPUs, so + # we need to correct them to be based on the number of pipelines. + assert args.distributed_world_size % num_pipeline_devices == 0 + args.distributed_world_size = ( + args.distributed_world_size // num_pipeline_devices + ) + # In the case of 4-way MP on nodes with 8 GPUs, we want + # distributed_rank to be the starting GPU index for each pipeline + # i.e., 0, 2, ... + assert args.distributed_rank % gpus_per_node == 0 + assert args.distributed_rank % num_pipeline_devices == 0 + args.distributed_rank = args.distributed_rank // num_pipeline_devices + # launch one process per pipeline + args.distributed_num_procs = num_pipelines_per_node + + # if we have 4-way MP on a node with 8 GPUs, we want device_ids to be 0 + # and 4, indicating the starting device IDs for each pipeline + args.device_id *= num_pipeline_devices + + if args.device_id > 0: + # if there's multiple pipelines on a node (e.g., 4-way MP on an 8 + # GPU node), we need to adjust pipeline_devices accordingly + logger.debug( + "setting CUDA device={} on rank {}".format( + args.device_id, args.distributed_rank + ) + ) + torch.cuda.set_device(args.device_id) + args.pipeline_devices = [args.device_id + d for d in args.pipeline_devices] + logger.info( + "setting pipeline_devices={} on rank {}".format( + args.pipeline_devices, args.distributed_rank + ), + ) + elif not args.distributed_no_spawn: + args.distributed_num_procs = min( + torch.cuda.device_count(), + args.distributed_world_size, + ) + + +def distributed_init(args): + if not getattr(args, "tpu", False): + if torch.distributed.is_initialized(): + warnings.warn( + "Distributed is already initialized, cannot initialize twice!" + ) + else: + logger.info( + "distributed init (rank {}): {}".format( + args.distributed_rank, + args.distributed_init_method, + ) + ) + dist.init_process_group( + backend=args.distributed_backend, + init_method=args.distributed_init_method, + world_size=args.distributed_world_size, + rank=args.distributed_rank, + ) + logger.info( + "initialized host {} as rank {}".format( + socket.gethostname(), + args.distributed_rank, + ) + ) + + # perform a dummy all-reduce to initialize the NCCL communicator + if torch.cuda.is_available(): + dist.all_reduce(torch.zeros(1).cuda()) + + args.distributed_rank = torch.distributed.get_rank() + else: + import torch_xla.core.xla_model as xm + + assert xm.xrt_world_size() == args.distributed_world_size + args.device_id = xm.get_local_ordinal() + args.distributed_rank = xm.get_ordinal() + xm.rendezvous("distributed_init") # wait for all workers + xm.mark_step() + + if not is_master(args): + logging.getLogger().setLevel(logging.WARNING) + + if args.model_parallel_size > 1: + try: + from fairseq.model_parallel.megatron.mpu import ( + get_model_parallel_rank, + initialize_model_parallel, + model_parallel_cuda_manual_seed, + ) + except ImportError: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + initialize_model_parallel(args.model_parallel_size) + model_parallel_cuda_manual_seed(args.seed) + model_part_number = get_model_parallel_rank() + args.checkpoint_suffix += "-model_part-{0}".format(model_part_number) + return args.distributed_rank + + +def distributed_main(i, main, args, kwargs): + args.device_id = i + if torch.cuda.is_available() and not args.cpu and not getattr(args, "tpu", False): + torch.cuda.set_device(args.device_id) + if args.distributed_rank is None: # torch.multiprocessing.spawn + args.distributed_rank = kwargs.pop("start_rank", 0) + i + + args.distributed_rank = distributed_init(args) + + after_distributed_init_fn = kwargs.pop("after_distributed_init_fn", None) + if after_distributed_init_fn: + args = after_distributed_init_fn(args) + + main(args, **kwargs) + + +def call_main(args, main, **kwargs): + if args.distributed_init_method is None: + infer_init_method(args) + + if args.distributed_init_method is not None: + # distributed training + if not args.distributed_no_spawn: + start_rank = args.distributed_rank + args.distributed_rank = None # assign automatically + kwargs["start_rank"] = start_rank + torch.multiprocessing.spawn( + fn=distributed_main, + args=(main, args, kwargs), + nprocs=args.distributed_num_procs, + ) + else: + distributed_main(args.device_id, main, args, kwargs) + elif getattr(args, "tpu", False) and args.distributed_world_size > 1: + import torch_xla.distributed.xla_multiprocessing as xmp + + torch.multiprocessing.set_sharing_strategy("file_system") + xmp.spawn( + fn=distributed_main, + args=(main, args, kwargs), + nprocs=8, # use all 8 TPU cores + ) + else: + # single GPU main + main(args, **kwargs) + + +def get_rank(): + return dist.get_rank() + + +def get_world_size(): + return dist.get_world_size() + + +def get_default_group(): + return dist.group.WORLD + + +def all_reduce(tensor, group=None): + if isinstance(group, tuple) and group[0] == "tpu": + import torch_xla.core.xla_model as xm + + return xm.all_reduce("sum", [tensor], groups=group[1]) + else: + if group is None: + group = get_default_group() + return dist.all_reduce(tensor, group=group) + + +def all_gather_list(data, group=None, max_size=16384): + """Gathers arbitrary data from all nodes into a list. + + Similar to :func:`~torch.distributed.all_gather` but for arbitrary Python + data. Note that *data* must be picklable. + + Args: + data (Any): data from the local worker to be gathered on other workers + group (optional): group of the collective + max_size (int, optional): maximum size of the data to be gathered + across workers + """ + rank = get_rank() + world_size = get_world_size() + + buffer_size = max_size * world_size + if ( + not hasattr(all_gather_list, "_buffer") + or all_gather_list._buffer.numel() < buffer_size + ): + all_gather_list._buffer = torch.cuda.ByteTensor(buffer_size) + all_gather_list._cpu_buffer = torch.ByteTensor(max_size).pin_memory() + buffer = all_gather_list._buffer + buffer.zero_() + cpu_buffer = all_gather_list._cpu_buffer + + data = utils.move_to_cpu(data) + enc = pickle.dumps(data) + enc_size = len(enc) + header_size = 4 # size of header that contains the length of the encoded data + size = header_size + enc_size + if size > max_size: + raise ValueError( + "encoded data size ({}) exceeds max_size ({})".format(size, max_size) + ) + + header = struct.pack(">I", enc_size) + cpu_buffer[:size] = torch.ByteTensor(list(header + enc)) + start = rank * max_size + buffer[start : start + size].copy_(cpu_buffer[:size]) + + all_reduce(buffer, group=group) + + buffer = buffer.cpu() + try: + result = [] + for i in range(world_size): + out_buffer = buffer[i * max_size : (i + 1) * max_size] + (enc_size,) = struct.unpack(">I", bytes(out_buffer[:header_size].tolist())) + if enc_size > 0: + result.append( + pickle.loads( + bytes(out_buffer[header_size : header_size + enc_size].tolist()) + ) + ) + return result + except pickle.UnpicklingError: + raise Exception( + "Unable to unpickle data from other workers. all_gather_list requires all " + "workers to enter the function together, so this error usually indicates " + "that the workers have fallen out of sync somehow. Workers can fall out of " + "sync if one of them runs out of memory, or if there are other conditions " + "in your training script that can cause one worker to finish an epoch " + "while other workers are still iterating over their portions of the data. " + "Try rerunning with --ddp-backend=no_c10d and see if that helps." + ) + + +def all_reduce_dict( + data: Mapping[str, Any], + device, + group=None, +) -> Dict[str, Any]: + """ + AllReduce a dictionary of values across workers. We separately + reduce items that are already on the device and items on CPU for + better performance. + + Args: + data (Mapping[str, Any]): dictionary of data to all-reduce, but + cannot be a nested dictionary + device (torch.device): device for the reduction + group (optional): group of the collective + """ + data_keys = list(data.keys()) + + # We want to separately reduce items that are already on the + # device and items on CPU for performance reasons. + cpu_data = OrderedDict() + device_data = OrderedDict() + for k in data_keys: + t = data[k] + if not torch.is_tensor(t): + cpu_data[k] = torch.tensor(t, dtype=torch.float32) + elif t.device.type != device.type: + cpu_data[k] = t.to(dtype=torch.float32) + else: + device_data[k] = t.to(dtype=torch.float32) + + def _all_reduce_dict(data: OrderedDict): + if len(data) == 0: + return data + buf = torch.cat([t.view(-1) for t in data.values()]).to(device=device) + all_reduce(buf, group=group) + split_buf = torch.split(buf, [t.numel() for t in data.values()]) + reduced_data = [t.view_as(orig) for t, orig in zip(split_buf, data.values())] + return OrderedDict(zip(data.keys(), reduced_data)) + + cpu_data = _all_reduce_dict(cpu_data) + device_data = _all_reduce_dict(device_data) + + def get_from_stack(key): + if key in cpu_data: + return cpu_data[key] + elif key in device_data: + return device_data[key] + raise KeyError + + return OrderedDict([(key, get_from_stack(key)) for key in data_keys]) diff --git a/fairseq-tools/fairseq/fairseq/file_io.py b/fairseq-tools/fairseq/fairseq/file_io.py new file mode 100644 index 00000000..d6672569 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/file_io.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import shutil +from typing import List, Optional + + +try: + from fvcore.common.file_io import PathManager as FVCorePathManager + +except ImportError: + FVCorePathManager = None + + +class PathManager: + """ + Wrapper for insulating OSS I/O (using Python builtin operations) from + fvcore's PathManager abstraction (for transparently handling various + internal backends). + """ + + @staticmethod + def open( + path: str, + mode: str = "r", + buffering: int = -1, + encoding: Optional[str] = None, + errors: Optional[str] = None, + newline: Optional[str] = None, + ): + if FVCorePathManager: + return FVCorePathManager.open( + path=path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + ) + return open( + path, + mode=mode, + buffering=buffering, + encoding=encoding, + errors=errors, + newline=newline, + ) + + @staticmethod + def copy(src_path: str, dst_path: str, overwrite: bool = False) -> bool: + if FVCorePathManager: + return FVCorePathManager.copy( + src_path=src_path, dst_path=dst_path, overwrite=overwrite + ) + return shutil.copyfile(src_path, dst_path) + + @staticmethod + def get_local_path(path: str, **kwargs) -> str: + if FVCorePathManager: + return FVCorePathManager.get_local_path(path, **kwargs) + return path + + @staticmethod + def exists(path: str) -> bool: + if FVCorePathManager: + return FVCorePathManager.exists(path) + return os.path.exists(path) + + @staticmethod + def isfile(path: str) -> bool: + if FVCorePathManager: + return FVCorePathManager.isfile(path) + return os.path.isfile(path) + + @staticmethod + def ls(path: str) -> List[str]: + if FVCorePathManager: + return FVCorePathManager.ls(path) + return os.listdir(path) + + @staticmethod + def mkdirs(path: str) -> None: + if FVCorePathManager: + return FVCorePathManager.mkdirs(path) + os.makedirs(path, exist_ok=True) + + @staticmethod + def rm(path: str) -> None: + if FVCorePathManager: + return FVCorePathManager.rm(path) + os.remove(path) + + @staticmethod + def chmod(path: str, mode: int) -> None: + if "manifold" not in path: + os.chmod(path, mode) + + @staticmethod + def register_handler(handler) -> None: + if FVCorePathManager: + return FVCorePathManager.register_handler(handler=handler) + + @staticmethod + def copy_from_local( + local_path: str, dst_path: str, overwrite: bool = False, **kwargs + ) -> None: + if FVCorePathManager: + return FVCorePathManager.copy_from_local( + local_path=local_path, dst_path=dst_path, overwrite=overwrite, **kwargs + ) + return shutil.copyfile(local_path, dst_path) diff --git a/fairseq-tools/fairseq/fairseq/file_utils.py b/fairseq-tools/fairseq/fairseq/file_utils.py new file mode 100644 index 00000000..0a94ac71 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/file_utils.py @@ -0,0 +1,353 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Utilities for working with the local dataset cache. +This file is adapted from `AllenNLP <https://github.com/allenai/allennlp>`_. +and `huggingface <https://github.com/huggingface>`_. +""" + +import fnmatch +import json +import logging +import os +import shutil +import tarfile +import tempfile +from functools import partial, wraps +from hashlib import sha256 +from io import open + + +try: + from torch.hub import _get_torch_home + + torch_cache_home = _get_torch_home() +except ImportError: + torch_cache_home = os.path.expanduser( + os.getenv( + "TORCH_HOME", os.path.join(os.getenv("XDG_CACHE_HOME", "~/.cache"), "torch") + ) + ) +default_cache_path = os.path.join(torch_cache_home, "pytorch_fairseq") + +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + +try: + from pathlib import Path + + PYTORCH_FAIRSEQ_CACHE = Path(os.getenv("PYTORCH_FAIRSEQ_CACHE", default_cache_path)) +except (AttributeError, ImportError): + PYTORCH_FAIRSEQ_CACHE = os.getenv("PYTORCH_FAIRSEQ_CACHE", default_cache_path) + +CONFIG_NAME = "config.json" +WEIGHTS_NAME = "pytorch_model.bin" + +logger = logging.getLogger(__name__) # pylint: disable=invalid-name + + +def load_archive_file(archive_file): + # redirect to the cache, if necessary + try: + resolved_archive_file = cached_path(archive_file, cache_dir=None) + except EnvironmentError: + logger.info( + "Archive name '{}' was not found in archive name list. " + "We assumed '{}' was a path or URL but couldn't find any file " + "associated to this path or URL.".format( + archive_file, + archive_file, + ) + ) + return None + + if resolved_archive_file == archive_file: + logger.info("loading archive file {}".format(archive_file)) + else: + logger.info( + "loading archive file {} from cache at {}".format( + archive_file, resolved_archive_file + ) + ) + + # Extract archive to temp dir and replace .tar.bz2 if necessary + tempdir = None + if not os.path.isdir(resolved_archive_file): + tempdir = tempfile.mkdtemp() + logger.info( + "extracting archive file {} to temp dir {}".format( + resolved_archive_file, tempdir + ) + ) + ext = os.path.splitext(archive_file)[1][1:] + with tarfile.open(resolved_archive_file, "r:" + ext) as archive: + top_dir = os.path.commonprefix(archive.getnames()) + archive.extractall(tempdir) + os.remove(resolved_archive_file) + shutil.move(os.path.join(tempdir, top_dir), resolved_archive_file) + shutil.rmtree(tempdir) + + return resolved_archive_file + + +def url_to_filename(url, etag=None): + """ + Convert `url` into a hashed filename in a repeatable way. + If `etag` is specified, append its hash to the URL's, delimited + by a period. + """ + url_bytes = url.encode("utf-8") + url_hash = sha256(url_bytes) + filename = url_hash.hexdigest() + + if etag: + etag_bytes = etag.encode("utf-8") + etag_hash = sha256(etag_bytes) + filename += "." + etag_hash.hexdigest() + + return filename + + +def filename_to_url(filename, cache_dir=None): + """ + Return the url and etag (which may be ``None``) stored for `filename`. + Raise ``EnvironmentError`` if `filename` or its stored metadata do not exist. + """ + if cache_dir is None: + cache_dir = PYTORCH_FAIRSEQ_CACHE + if isinstance(cache_dir, Path): + cache_dir = str(cache_dir) + + cache_path = os.path.join(cache_dir, filename) + if not os.path.exists(cache_path): + raise EnvironmentError("file {} not found".format(cache_path)) + + meta_path = cache_path + ".json" + if not os.path.exists(meta_path): + raise EnvironmentError("file {} not found".format(meta_path)) + + with open(meta_path, encoding="utf-8") as meta_file: + metadata = json.load(meta_file) + url = metadata["url"] + etag = metadata["etag"] + + return url, etag + + +def cached_path(url_or_filename, cache_dir=None): + """ + Given something that might be a URL (or might be a local path), + determine which. If it's a URL, download the file and cache it, and + return the path to the cached file. If it's already a local path, + make sure the file exists and then return the path. + """ + if cache_dir is None: + cache_dir = PYTORCH_FAIRSEQ_CACHE + if isinstance(url_or_filename, Path): + url_or_filename = str(url_or_filename) + if isinstance(cache_dir, Path): + cache_dir = str(cache_dir) + + parsed = urlparse(url_or_filename) + + if parsed.scheme in ("http", "https", "s3"): + # URL, so get it from the cache (downloading if necessary) + return get_from_cache(url_or_filename, cache_dir) + elif os.path.exists(url_or_filename): + # File, and it exists. + return url_or_filename + elif parsed.scheme == "": + # File, but it doesn't exist. + raise EnvironmentError("file {} not found".format(url_or_filename)) + else: + # Something unknown + raise ValueError( + "unable to parse {} as a URL or as a local path".format(url_or_filename) + ) + + +def split_s3_path(url): + """Split a full s3 path into the bucket name and path.""" + parsed = urlparse(url) + if not parsed.netloc or not parsed.path: + raise ValueError("bad s3 path {}".format(url)) + bucket_name = parsed.netloc + s3_path = parsed.path + # Remove '/' at beginning of path. + if s3_path.startswith("/"): + s3_path = s3_path[1:] + return bucket_name, s3_path + + +def s3_request(func): + """ + Wrapper function for s3 requests in order to create more helpful error + messages. + """ + + @wraps(func) + def wrapper(url, *args, **kwargs): + from botocore.exceptions import ClientError + + try: + return func(url, *args, **kwargs) + except ClientError as exc: + if int(exc.response["Error"]["Code"]) == 404: + raise EnvironmentError("file {} not found".format(url)) + else: + raise + + return wrapper + + +@s3_request +def s3_etag(url): + """Check ETag on S3 object.""" + import boto3 + + s3_resource = boto3.resource("s3") + bucket_name, s3_path = split_s3_path(url) + s3_object = s3_resource.Object(bucket_name, s3_path) + return s3_object.e_tag + + +@s3_request +def s3_get(url, temp_file): + """Pull a file directly from S3.""" + import boto3 + + s3_resource = boto3.resource("s3") + bucket_name, s3_path = split_s3_path(url) + s3_resource.Bucket(bucket_name).download_fileobj(s3_path, temp_file) + + +def request_wrap_timeout(func, url): + import requests + + for attempt, timeout in enumerate([10, 20, 40, 60, 60]): + try: + return func(timeout=timeout) + except requests.exceptions.Timeout as e: + logger.warning( + "Request for %s timed-out (attempt %d). Retrying with a timeout of %d secs", + url, + attempt, + timeout, + exc_info=e, + ) + continue + raise RuntimeError(f"Unable to fetch file {url}") + + +def http_get(url, temp_file): + import requests + from tqdm import tqdm + + req = request_wrap_timeout(partial(requests.get, url, stream=True), url) + content_length = req.headers.get("Content-Length") + total = int(content_length) if content_length is not None else None + progress = tqdm(unit="B", total=total) + for chunk in req.iter_content(chunk_size=1024): + if chunk: # filter out keep-alive new chunks + progress.update(len(chunk)) + temp_file.write(chunk) + progress.close() + + +def get_from_cache(url, cache_dir=None): + """ + Given a URL, look for the corresponding dataset in the local cache. + If it's not there, download it. Then return the path to the cached file. + """ + if cache_dir is None: + cache_dir = PYTORCH_FAIRSEQ_CACHE + if isinstance(cache_dir, Path): + cache_dir = str(cache_dir) + + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + # Get eTag to add to filename, if it exists. + if url.startswith("s3://"): + etag = s3_etag(url) + else: + try: + import requests + + response = request_wrap_timeout( + partial(requests.head, url, allow_redirects=True), url + ) + if response.status_code != 200: + etag = None + else: + etag = response.headers.get("ETag") + except EnvironmentError: + etag = None + + filename = url_to_filename(url, etag) + + # get cache path to put the file + cache_path = os.path.join(cache_dir, filename) + + # If we don't have a connection (etag is None) and can't identify the file + # try to get the last downloaded one + if not os.path.exists(cache_path) and etag is None: + matching_files = fnmatch.filter(os.listdir(cache_dir), filename + ".*") + matching_files = list(filter(lambda s: not s.endswith(".json"), matching_files)) + if matching_files: + cache_path = os.path.join(cache_dir, matching_files[-1]) + + if not os.path.exists(cache_path): + # Download to temporary file, then copy to cache dir once finished. + # Otherwise you get corrupt cache entries if the download gets interrupted. + with tempfile.NamedTemporaryFile() as temp_file: + logger.info("%s not found in cache, downloading to %s", url, temp_file.name) + + # GET file object + if url.startswith("s3://"): + s3_get(url, temp_file) + else: + http_get(url, temp_file) + + # we are copying the file before closing it, so flush to avoid truncation + temp_file.flush() + # shutil.copyfileobj() starts at the current position, so go to the start + temp_file.seek(0) + + logger.info("copying %s to cache at %s", temp_file.name, cache_path) + with open(cache_path, "wb") as cache_file: + shutil.copyfileobj(temp_file, cache_file) + + logger.info("creating metadata file for %s", cache_path) + meta = {"url": url, "etag": etag} + meta_path = cache_path + ".json" + with open(meta_path, "w") as meta_file: + output_string = json.dumps(meta) + meta_file.write(output_string) + + logger.info("removing temp file %s", temp_file.name) + + return cache_path + + +def read_set_from_file(filename): + """ + Extract a de-duped collection (set) of text from a file. + Expected file format is one item per line. + """ + collection = set() + with open(filename, "r", encoding="utf-8") as file_: + for line in file_: + collection.add(line.rstrip()) + return collection + + +def get_file_extension(path, dot=True, lower=True): + ext = os.path.splitext(path)[1] + ext = ext if dot else ext[1:] + return ext.lower() if lower else ext diff --git a/fairseq-tools/fairseq/fairseq/hub_utils.py b/fairseq-tools/fairseq/fairseq/hub_utils.py new file mode 100644 index 00000000..b293e54e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/hub_utils.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import copy +import logging +import os +from typing import Any, Dict, Iterator, List, Tuple + +import torch +from fairseq import utils +from fairseq.data import encoders +from torch import nn + + +logger = logging.getLogger(__name__) + + +def from_pretrained( + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + archive_map=None, + **kwargs +): + from fairseq import checkpoint_utils, file_utils + + if archive_map is not None: + if model_name_or_path in archive_map: + model_name_or_path = archive_map[model_name_or_path] + if data_name_or_path is not None and data_name_or_path in archive_map: + data_name_or_path = archive_map[data_name_or_path] + + # allow archive_map to set default arg_overrides (e.g., tokenizer, bpe) + # for each model + if isinstance(model_name_or_path, dict): + for k, v in model_name_or_path.items(): + if k == "checkpoint_file": + checkpoint_file = v + elif ( + k != "path" + # only set kwargs that don't already have overrides + and k not in kwargs + ): + kwargs[k] = v + model_name_or_path = model_name_or_path["path"] + + model_path = file_utils.load_archive_file(model_name_or_path) + + # convenience hack for loading data and BPE codes from model archive + if data_name_or_path.startswith("."): + kwargs["data"] = os.path.abspath(os.path.join(model_path, data_name_or_path)) + else: + kwargs["data"] = file_utils.load_archive_file(data_name_or_path) + for file, arg in { + "code": "bpe_codes", + "bpecodes": "bpe_codes", + "sentencepiece.bpe.model": "sentencepiece_model", + }.items(): + path = os.path.join(model_path, file) + if os.path.exists(path): + kwargs[arg] = path + + if "user_dir" in kwargs: + utils.import_user_module(argparse.Namespace(user_dir=kwargs["user_dir"])) + + models, args, task = checkpoint_utils.load_model_ensemble_and_task( + [os.path.join(model_path, cpt) for cpt in checkpoint_file.split(os.pathsep)], + arg_overrides=kwargs, + ) + + return { + "args": args, + "task": task, + "models": models, + } + + +class GeneratorHubInterface(nn.Module): + """ + PyTorch Hub interface for generating sequences from a pre-trained + translation or language model. + """ + + def __init__(self, args, task, models): + super().__init__() + self.args = args + self.task = task + self.models = nn.ModuleList(models) + self.src_dict = task.source_dictionary + self.tgt_dict = task.target_dictionary + + # optimize model for generation + for model in self.models: + model.prepare_for_inference_(args) + + # Load alignment dictionary for unknown word replacement + # (None if no unknown word replacement, empty if no path to align dictionary) + self.align_dict = utils.load_align_dict(getattr(args, "replace_unk", None)) + + self.tokenizer = encoders.build_tokenizer(args) + self.bpe = encoders.build_bpe(args) + + self.max_positions = utils.resolve_max_positions( + self.task.max_positions(), *[model.max_positions() for model in models] + ) + + # this is useful for determining the device + self.register_buffer("_float_tensor", torch.tensor([0], dtype=torch.float)) + + @property + def device(self): + return self._float_tensor.device + + def translate( + self, sentences: List[str], beam: int = 5, verbose: bool = False, **kwargs + ) -> List[str]: + return self.sample(sentences, beam, verbose, **kwargs) + + def sample( + self, sentences: List[str], beam: int = 1, verbose: bool = False, **kwargs + ) -> List[str]: + if isinstance(sentences, str): + return self.sample([sentences], beam=beam, verbose=verbose, **kwargs)[0] + tokenized_sentences = [self.encode(sentence) for sentence in sentences] + batched_hypos = self.generate(tokenized_sentences, beam, verbose, **kwargs) + return [self.decode(hypos[0]["tokens"]) for hypos in batched_hypos] + + def score(self, sentences: List[str], **kwargs): + if isinstance(sentences, str): + return self.score([sentences], **kwargs)[0] + # NOTE: this doesn't support translation tasks currently + tokenized_sentences = [self.encode(sentence) for sentence in sentences] + return [ + hypos[0] + for hypos in self.generate( + tokenized_sentences, score_reference=True, **kwargs + ) + ] + + def generate( + self, + tokenized_sentences: List[torch.LongTensor], + beam: int = 5, + verbose: bool = False, + skip_invalid_size_inputs=False, + inference_step_args=None, + **kwargs + ) -> List[List[Dict[str, torch.Tensor]]]: + if torch.is_tensor(tokenized_sentences) and tokenized_sentences.dim() == 1: + return self.generate( + tokenized_sentences.unsqueeze(0), beam=beam, verbose=verbose, **kwargs + )[0] + + # build generator using current args as well as any kwargs + gen_args = copy.copy(self.args) + gen_args.beam = beam + for k, v in kwargs.items(): + setattr(gen_args, k, v) + generator = self.task.build_generator(self.models, gen_args) + + inference_step_args = inference_step_args or {} + results = [] + for batch in self._build_batches(tokenized_sentences, skip_invalid_size_inputs): + batch = utils.apply_to_sample(lambda t: t.to(self.device), batch) + translations = self.task.inference_step( + generator, self.models, batch, **inference_step_args + ) + for id, hypos in zip(batch["id"].tolist(), translations): + results.append((id, hypos)) + + # sort output to match input order + outputs = [hypos for _, hypos in sorted(results, key=lambda x: x[0])] + + if verbose: + + def getarg(name, default): + return getattr(gen_args, name, getattr(self.args, name, default)) + + for source_tokens, target_hypotheses in zip(tokenized_sentences, outputs): + src_str_with_unk = self.string(source_tokens) + logger.info("S\t{}".format(src_str_with_unk)) + for hypo in target_hypotheses: + hypo_str = self.decode(hypo["tokens"]) + logger.info("H\t{}\t{}".format(hypo["score"], hypo_str)) + logger.info( + "P\t{}".format( + " ".join( + map( + lambda x: "{:.4f}".format(x), + hypo["positional_scores"].tolist(), + ) + ) + ) + ) + if hypo["alignment"] is not None and getarg( + "print_alignment", False + ): + logger.info( + "A\t{}".format( + " ".join( + [ + "{}-{}".format(src_idx, tgt_idx) + for src_idx, tgt_idx in hypo["alignment"] + ] + ) + ) + ) + return outputs + + def encode(self, sentence: str) -> torch.LongTensor: + sentence = self.tokenize(sentence) + sentence = self.apply_bpe(sentence) + return self.binarize(sentence) + + def decode(self, tokens: torch.LongTensor) -> str: + sentence = self.string(tokens) + sentence = self.remove_bpe(sentence) + return self.detokenize(sentence) + + def tokenize(self, sentence: str) -> str: + if self.tokenizer is not None: + sentence = self.tokenizer.encode(sentence) + return sentence + + def detokenize(self, sentence: str) -> str: + if self.tokenizer is not None: + sentence = self.tokenizer.decode(sentence) + return sentence + + def apply_bpe(self, sentence: str) -> str: + if self.bpe is not None: + sentence = self.bpe.encode(sentence) + return sentence + + def remove_bpe(self, sentence: str) -> str: + if self.bpe is not None: + sentence = self.bpe.decode(sentence) + return sentence + + def binarize(self, sentence: str) -> torch.LongTensor: + return self.src_dict.encode_line(sentence, add_if_not_exist=False).long() + + def string(self, tokens: torch.LongTensor) -> str: + return self.tgt_dict.string(tokens) + + def _build_batches( + self, tokens: List[List[int]], skip_invalid_size_inputs: bool + ) -> Iterator[Dict[str, Any]]: + lengths = torch.LongTensor([t.numel() for t in tokens]) + batch_iterator = self.task.get_batch_iterator( + dataset=self.task.build_dataset_for_inference(tokens, lengths), + max_tokens=self.args.max_tokens, + max_sentences=self.args.batch_size, + max_positions=self.max_positions, + ignore_invalid_inputs=skip_invalid_size_inputs, + disable_iterator_cache=True, + ).next_epoch_itr(shuffle=False) + return batch_iterator + + +class BPEHubInterface(object): + """PyTorch Hub interface for Byte-Pair Encoding (BPE).""" + + def __init__(self, bpe, **kwargs): + super().__init__() + args = argparse.Namespace(bpe=bpe, **kwargs) + self.bpe = encoders.build_bpe(args) + assert self.bpe is not None + + def encode(self, sentence: str) -> str: + return self.bpe.encode(sentence) + + def decode(self, sentence: str) -> str: + return self.bpe.decode(sentence) + + +class TokenizerHubInterface(object): + """PyTorch Hub interface for tokenization.""" + + def __init__(self, tokenizer, **kwargs): + super().__init__() + args = argparse.Namespace(tokenizer=tokenizer, **kwargs) + self.tokenizer = encoders.build_tokenizer(args) + assert self.tokenizer is not None + + def encode(self, sentence: str) -> str: + return self.tokenizer.encode(sentence) + + def decode(self, sentence: str) -> str: + return self.tokenizer.decode(sentence) diff --git a/fairseq-tools/fairseq/fairseq/incremental_decoding_utils.py b/fairseq-tools/fairseq/fairseq/incremental_decoding_utils.py new file mode 100644 index 00000000..b26e6cd0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/incremental_decoding_utils.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import uuid +from typing import Dict, Optional + +from torch import Tensor + + +class FairseqIncrementalState(object): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.init_incremental_state() + + def init_incremental_state(self): + self._incremental_state_id = str(uuid.uuid4()) + + def _get_full_incremental_state_key(self, key: str) -> str: + return "{}.{}".format(self._incremental_state_id, key) + + def get_incremental_state( + self, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, + ) -> Optional[Dict[str, Optional[Tensor]]]: + """Helper for getting incremental state for an nn.Module.""" + full_key = self._get_full_incremental_state_key(key) + if incremental_state is None or full_key not in incremental_state: + return None + return incremental_state[full_key] + + def set_incremental_state( + self, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, + value: Dict[str, Optional[Tensor]], + ) -> Optional[Dict[str, Dict[str, Optional[Tensor]]]]: + """Helper for setting incremental state for an nn.Module.""" + if incremental_state is not None: + full_key = self._get_full_incremental_state_key(key) + incremental_state[full_key] = value + return incremental_state + + +def with_incremental_state(cls): + cls.__bases__ = (FairseqIncrementalState,) + tuple( + b for b in cls.__bases__ if b != FairseqIncrementalState + ) + return cls diff --git a/fairseq-tools/fairseq/fairseq/iterative_refinement_generator.py b/fairseq-tools/fairseq/fairseq/iterative_refinement_generator.py new file mode 100644 index 00000000..4fb0946f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/iterative_refinement_generator.py @@ -0,0 +1,359 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import namedtuple + +import numpy as np +import torch +from fairseq import utils + + +DecoderOut = namedtuple( + "IterativeRefinementDecoderOut", + ["output_tokens", "output_scores", "attn", "step", "max_step", "history"], +) + + +class IterativeRefinementGenerator(object): + def __init__( + self, + tgt_dict, + models=None, + eos_penalty=0.0, + max_iter=10, + max_ratio=2, + beam_size=1, + decoding_format=None, + retain_dropout=False, + adaptive=True, + retain_history=False, + reranking=False, + ): + """ + Generates translations based on iterative refinement. + + Args: + tgt_dict: target dictionary + eos_penalty: if > 0.0, it penalized early-stopping in decoding + max_iter: maximum number of refinement iterations + max_ratio: generate sequences of maximum length ax, where x is the source length + decoding_format: decoding mode in {'unigram', 'ensemble', 'vote', 'dp', 'bs'} + retain_dropout: retaining dropout in the inference + adaptive: decoding with early stop + """ + self.bos = tgt_dict.bos() + self.pad = tgt_dict.pad() + self.unk = tgt_dict.unk() + self.eos = tgt_dict.eos() + self.vocab_size = len(tgt_dict) + self.eos_penalty = eos_penalty + self.max_iter = max_iter + self.max_ratio = max_ratio + self.beam_size = beam_size + self.reranking = reranking + self.decoding_format = decoding_format + self.retain_dropout = retain_dropout + self.retain_history = retain_history + self.adaptive = adaptive + self.models = models + + def generate_batched_itr( + self, + data_itr, + maxlen_a=None, + maxlen_b=None, + cuda=False, + timer=None, + prefix_size=0, + ): + """Iterate over a batched dataset and yield individual translations. + + Args: + maxlen_a/b: generate sequences of maximum length ax + b, + where x is the source sentence length. + cuda: use GPU for generation + timer: StopwatchMeter for timing generations. + """ + + for sample in data_itr: + if "net_input" not in sample: + continue + if timer is not None: + timer.start() + with torch.no_grad(): + hypos = self.generate( + self.models, + sample, + prefix_tokens=sample["target"][:, :prefix_size] + if prefix_size > 0 + else None, + ) + if timer is not None: + timer.stop(sample["ntokens"]) + for i, id in enumerate(sample["id"]): + # remove padding + src = utils.strip_pad(sample["net_input"]["src_tokens"][i, :], self.pad) + ref = utils.strip_pad(sample["target"][i, :], self.pad) + yield id, src, ref, hypos[i] + + @torch.no_grad() + def generate(self, models, sample, prefix_tokens=None, constraints=None): + if constraints is not None: + raise NotImplementedError( + "Constrained decoding with the IterativeRefinementGenerator is not supported" + ) + + # TODO: iterative refinement generator does not support ensemble for now. + if not self.retain_dropout: + for model in models: + model.eval() + + model, reranker = models[0], None + if self.reranking: + assert len(models) > 1, "Assuming the last checkpoint is the reranker" + assert ( + self.beam_size > 1 + ), "Reranking requires multiple translation for each example" + + reranker = models[-1] + models = models[:-1] + + if len(models) > 1 and hasattr(model, "enable_ensemble"): + assert model.allow_ensemble, "{} does not support ensembling".format( + model.__class__.__name__ + ) + model.enable_ensemble(models) + + # TODO: better encoder inputs? + src_tokens = sample["net_input"]["src_tokens"] + src_lengths = sample["net_input"]["src_lengths"] + bsz, src_len = src_tokens.size() + + # initialize + encoder_out = model.forward_encoder([src_tokens, src_lengths]) + prev_decoder_out = model.initialize_output_tokens(encoder_out, src_tokens) + + if self.beam_size > 1: + assert ( + model.allow_length_beam + ), "{} does not support decoding with length beam.".format( + model.__class__.__name__ + ) + + # regenerate data based on length-beam + length_beam_order = ( + utils.new_arange(src_tokens, self.beam_size, bsz).t().reshape(-1) + ) + encoder_out = model.encoder.reorder_encoder_out( + encoder_out, length_beam_order + ) + prev_decoder_out = model.regenerate_length_beam( + prev_decoder_out, self.beam_size + ) + bsz = bsz * self.beam_size + + sent_idxs = torch.arange(bsz) + prev_output_tokens = prev_decoder_out.output_tokens.clone() + + if self.retain_history: + prev_decoder_out = prev_decoder_out._replace(history=[prev_output_tokens]) + + finalized = [[] for _ in range(bsz)] + + def is_a_loop(x, y, s, a): + b, l_x, l_y = x.size(0), x.size(1), y.size(1) + if l_x > l_y: + y = torch.cat([y, x.new_zeros(b, l_x - l_y).fill_(self.pad)], 1) + s = torch.cat([s, s.new_zeros(b, l_x - l_y)], 1) + if a is not None: + a = torch.cat([a, a.new_zeros(b, l_x - l_y, a.size(2))], 1) + elif l_x < l_y: + x = torch.cat([x, y.new_zeros(b, l_y - l_x).fill_(self.pad)], 1) + return (x == y).all(1), y, s, a + + def finalized_hypos(step, prev_out_token, prev_out_score, prev_out_attn): + cutoff = prev_out_token.ne(self.pad) + tokens = prev_out_token[cutoff] + if prev_out_score is None: + scores, score = None, None + else: + scores = prev_out_score[cutoff] + score = scores.mean() + + if prev_out_attn is None: + hypo_attn, alignment = None, None + else: + hypo_attn = prev_out_attn[cutoff] + alignment = hypo_attn.max(dim=1)[1] + return { + "steps": step, + "tokens": tokens, + "positional_scores": scores, + "score": score, + "hypo_attn": hypo_attn, + "alignment": alignment, + } + + for step in range(self.max_iter + 1): + + decoder_options = { + "eos_penalty": self.eos_penalty, + "max_ratio": self.max_ratio, + "decoding_format": self.decoding_format, + } + prev_decoder_out = prev_decoder_out._replace( + step=step, + max_step=self.max_iter + 1, + ) + + decoder_out = model.forward_decoder( + prev_decoder_out, encoder_out, **decoder_options + ) + + if self.adaptive: + # terminate if there is a loop + terminated, out_tokens, out_scores, out_attn = is_a_loop( + prev_output_tokens, + decoder_out.output_tokens, + decoder_out.output_scores, + decoder_out.attn, + ) + decoder_out = decoder_out._replace( + output_tokens=out_tokens, + output_scores=out_scores, + attn=out_attn, + ) + + else: + terminated = decoder_out.output_tokens.new_zeros( + decoder_out.output_tokens.size(0) + ).bool() + + if step == self.max_iter: # reach last iteration, terminate + terminated.fill_(1) + + # collect finalized sentences + finalized_idxs = sent_idxs[terminated] + finalized_tokens = decoder_out.output_tokens[terminated] + finalized_scores = decoder_out.output_scores[terminated] + finalized_attn = ( + None + if (decoder_out.attn is None or decoder_out.attn.size(0) == 0) + else decoder_out.attn[terminated] + ) + + if self.retain_history: + finalized_history_tokens = [h[terminated] for h in decoder_out.history] + + for i in range(finalized_idxs.size(0)): + finalized[finalized_idxs[i]] = [ + finalized_hypos( + step, + finalized_tokens[i], + finalized_scores[i], + None if finalized_attn is None else finalized_attn[i], + ) + ] + + if self.retain_history: + finalized[finalized_idxs[i]][0]["history"] = [] + for j in range(len(finalized_history_tokens)): + finalized[finalized_idxs[i]][0]["history"].append( + finalized_hypos( + step, finalized_history_tokens[j][i], None, None + ) + ) + + # check if all terminated + if terminated.sum() == terminated.size(0): + break + + # for next step + not_terminated = ~terminated + prev_decoder_out = decoder_out._replace( + output_tokens=decoder_out.output_tokens[not_terminated], + output_scores=decoder_out.output_scores[not_terminated], + attn=decoder_out.attn[not_terminated] + if (decoder_out.attn is not None and decoder_out.attn.size(0) > 0) + else None, + history=[h[not_terminated] for h in decoder_out.history] + if decoder_out.history is not None + else None, + ) + encoder_out = model.encoder.reorder_encoder_out( + encoder_out, not_terminated.nonzero(as_tuple=False).squeeze() + ) + sent_idxs = sent_idxs[not_terminated] + prev_output_tokens = prev_decoder_out.output_tokens.clone() + + if self.beam_size > 1: + if reranker is not None: + finalized = self.rerank( + reranker, finalized, [src_tokens, src_lengths], self.beam_size + ) + + # aggregate information from length beam + finalized = [ + finalized[ + np.argmax( + [ + finalized[self.beam_size * i + j][0]["score"] + for j in range(self.beam_size) + ] + ) + + self.beam_size * i + ] + for i in range(len(finalized) // self.beam_size) + ] + + return finalized + + def rerank(self, reranker, finalized, encoder_input, beam_size): + def rebuild_batch(finalized): + finalized_tokens = [f[0]["tokens"] for f in finalized] + finalized_maxlen = max(f.size(0) for f in finalized_tokens) + final_output_tokens = ( + finalized_tokens[0] + .new_zeros(len(finalized_tokens), finalized_maxlen) + .fill_(self.pad) + ) + for i, f in enumerate(finalized_tokens): + final_output_tokens[i, : f.size(0)] = f + return final_output_tokens + + final_output_tokens = rebuild_batch(finalized) + final_output_tokens[ + :, 0 + ] = self.eos # autoregressive model assumes starting with EOS + + reranker_encoder_out = reranker.encoder(*encoder_input) + length_beam_order = ( + utils.new_arange( + final_output_tokens, beam_size, reranker_encoder_out.encoder_out.size(1) + ) + .t() + .reshape(-1) + ) + reranker_encoder_out = reranker.encoder.reorder_encoder_out( + reranker_encoder_out, length_beam_order + ) + reranking_scores = reranker.get_normalized_probs( + reranker.decoder(final_output_tokens[:, :-1], reranker_encoder_out), + True, + None, + ) + reranking_scores = reranking_scores.gather(2, final_output_tokens[:, 1:, None]) + reranking_masks = final_output_tokens[:, 1:].ne(self.pad) + reranking_scores = ( + reranking_scores[:, :, 0].masked_fill_(~reranking_masks, 0).sum(1) + ) + reranking_scores = reranking_scores / reranking_masks.sum(1).type_as( + reranking_scores + ) + + for i in range(len(finalized)): + finalized[i][0]["score"] = reranking_scores[i] + + return finalized diff --git a/fairseq-tools/fairseq/fairseq/legacy_distributed_data_parallel.py b/fairseq-tools/fairseq/fairseq/legacy_distributed_data_parallel.py new file mode 100644 index 00000000..44f87c7c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/legacy_distributed_data_parallel.py @@ -0,0 +1,171 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +A modified version of the legacy DistributedDataParallel module that uses c10d +communication primitives. This version is simpler than the latest PyTorch +version and is useful for debugging. Notably it does not overlap gradient +communication with the backward pass, which makes it slower but more robust +than the PyTorch version. + +This version also supports the *no_sync* context manager, which allows faster +training with `--update-freq`. +""" + +import copy +from collections import OrderedDict +from contextlib import contextmanager + +import torch +from torch import nn +from torch.autograd import Variable + +from . import distributed_utils + + +class LegacyDistributedDataParallel(nn.Module): + """Implements distributed data parallelism at the module level. + + A simplified version of :class:`torch.nn.parallel.DistributedDataParallel`. + This version uses a c10d process group for communication and does not + broadcast buffers. + + Args: + module (~torch.nn.Module): module to be parallelized + world_size (int): number of parallel workers + process_group (optional): the c10d process group to be used for + distributed data all-reduction. If None, the default process group + will be used. + buffer_size (int, optional): number of elements to buffer before + performing all-reduce (default: 256M). + """ + + def __init__(self, module, world_size, process_group=None, buffer_size=2 ** 28): + super().__init__() + + self.module = module + self.world_size = world_size + self.process_group = process_group + + # Never use a bigger buffer than the number of model params + self.buffer_size = min(buffer_size, sum(p.numel() for p in module.parameters())) + self.buffer = None + + # We can also forcibly accumulate grads locally and only do the + # all-reduce at some later time + self.accumulate_grads = False + + # make per-device lists of parameters + paramlists = OrderedDict() + for param in self.module.parameters(): + device = param.device + if paramlists.get(device) is None: + paramlists[device] = [] + paramlists[device] += [param] + self.per_device_params = list(paramlists.values()) + + def __getstate__(self): + attrs = copy.copy(self.__dict__) + return attrs + + def __setstate__(self, state): + super().__setstate__(state) + + @contextmanager + def no_sync(self): + """A context manager to disable gradient synchronization.""" + old_accumulate_grads = self.accumulate_grads + self.accumulate_grads = True + yield + self.accumulate_grads = old_accumulate_grads + + def forward(self, *inputs, **kwargs): + return self.module(*inputs, **kwargs) + + def all_reduce(self): + """ + This function must be called explicitly after backward to reduce + gradients. There is no automatic hook like c10d. + """ + + def all_reduce_params(params): + buffer = self.buffer + nonzero_buffer = False + if len(params) > 1: + offset = 0 + for p in params: + sz = p.numel() + if p.grad is not None: + buffer[offset : offset + sz].copy_(p.grad.data.view(-1)) + nonzero_buffer = True + else: + buffer[offset : offset + sz].zero_() + offset += sz + else: + # we only have a single grad to all-reduce + p = params[0] + if p.grad is not None: + buffer = p.grad.data + nonzero_buffer = True + elif p.numel() <= self.buffer.numel(): + buffer = buffer[: p.numel()] + buffer.zero_() + else: + buffer = torch.zeros_like(p) + + if nonzero_buffer: + buffer.div_(self.world_size) + + distributed_utils.all_reduce(buffer, self.process_group) + + # copy all-reduced grads back into their original place + offset = 0 + for p in params: + sz = p.numel() + if p.grad is not None: + p.grad.data.copy_(buffer[offset : offset + sz].view_as(p)) + else: + p.grad = buffer[offset : offset + sz].view_as(p).clone() + offset += sz + + def reduction_fn(): + # This function only needs to be called once + if self.accumulate_grads: + return + + if self.buffer is None: + self.buffer = next(self.module.parameters()).new(self.buffer_size) + + for params in self.per_device_params: + # All-reduce the gradients in buckets + offset = 0 + buffered_params = [] + for param in params: + if not param.requires_grad: + continue + if param.grad is None: + param.grad = torch.zeros_like(param) + if param.grad.requires_grad: + raise RuntimeError( + "DistributedDataParallel only works " + "with gradients that don't require " + "grad" + ) + sz = param.numel() + if sz > self.buffer.numel(): + # all-reduce big params directly + all_reduce_params([param]) + else: + if offset + sz > self.buffer.numel(): + all_reduce_params(buffered_params) + offset = 0 + buffered_params.clear() + buffered_params.append(param) + offset += sz + + if len(buffered_params) > 0: + all_reduce_params(buffered_params) + + reduction_fn() diff --git a/fairseq-tools/fairseq/fairseq/logging/__init__.py b/fairseq-tools/fairseq/fairseq/logging/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/fairseq/logging/meters.py b/fairseq-tools/fairseq/fairseq/logging/meters.py new file mode 100644 index 00000000..6793ef54 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/logging/meters.py @@ -0,0 +1,291 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import bisect +import time +from collections import OrderedDict +from typing import Dict, Optional + + +try: + import torch + + def type_as(a, b): + if torch.is_tensor(a) and torch.is_tensor(b): + return a.to(b) + else: + return a + + +except ImportError: + torch = None + + def type_as(a, b): + return a + + +try: + import numpy as np +except ImportError: + np = None + + +class Meter(object): + """Base class for Meters.""" + + def __init__(self): + pass + + def state_dict(self): + return {} + + def load_state_dict(self, state_dict): + pass + + def reset(self): + raise NotImplementedError + + @property + def smoothed_value(self) -> float: + """Smoothed value used for logging.""" + raise NotImplementedError + + +def safe_round(number, ndigits): + if hasattr(number, "__round__"): + return round(number, ndigits) + elif torch is not None and torch.is_tensor(number) and number.numel() == 1: + return safe_round(number.item(), ndigits) + elif np is not None and np.ndim(number) == 0 and hasattr(number, "item"): + return safe_round(number.item(), ndigits) + else: + return number + + +class AverageMeter(Meter): + """Computes and stores the average and current value""" + + def __init__(self, round: Optional[int] = None): + self.round = round + self.reset() + + def reset(self): + self.val = None # most recent update + self.sum = 0 # sum from all updates + self.count = 0 # total n from all updates + + def update(self, val, n=1): + if val is not None: + self.val = val + if n > 0: + self.sum = type_as(self.sum, val) + (val * n) + self.count = type_as(self.count, n) + n + + def state_dict(self): + return { + "val": self.val, + "sum": self.sum, + "count": self.count, + "round": self.round, + } + + def load_state_dict(self, state_dict): + self.val = state_dict["val"] + self.sum = state_dict["sum"] + self.count = state_dict["count"] + self.round = state_dict.get("round", None) + + @property + def avg(self): + return self.sum / self.count if self.count > 0 else self.val + + @property + def smoothed_value(self) -> float: + val = self.avg + if self.round is not None and val is not None: + val = safe_round(val, self.round) + return val + + +class TimeMeter(Meter): + """Computes the average occurrence of some event per second""" + + def __init__( + self, + init: int = 0, + n: int = 0, + round: Optional[int] = None, + ): + self.round = round + self.reset(init, n) + + def reset(self, init=0, n=0): + self.init = init + self.start = time.perf_counter() + self.n = n + self.i = 0 + + def update(self, val=1): + self.n = type_as(self.n, val) + val + self.i += 1 + + def state_dict(self): + return { + "init": self.elapsed_time, + "n": self.n, + "round": self.round, + } + + def load_state_dict(self, state_dict): + if "start" in state_dict: + # backwards compatibility for old state_dicts + self.reset(init=state_dict["init"]) + else: + self.reset(init=state_dict["init"], n=state_dict["n"]) + self.round = state_dict.get("round", None) + + @property + def avg(self): + return self.n / self.elapsed_time + + @property + def elapsed_time(self): + return self.init + (time.perf_counter() - self.start) + + @property + def smoothed_value(self) -> float: + val = self.avg + if self.round is not None and val is not None: + val = safe_round(val, self.round) + return val + + +class StopwatchMeter(Meter): + """Computes the sum/avg duration of some event in seconds""" + + def __init__(self, round: Optional[int] = None): + self.round = round + self.sum = 0 + self.n = 0 + self.start_time = None + + def start(self): + self.start_time = time.perf_counter() + + def stop(self, n=1, prehook=None): + if self.start_time is not None: + if prehook is not None: + prehook() + delta = time.perf_counter() - self.start_time + self.sum = self.sum + delta + self.n = type_as(self.n, n) + n + + def reset(self): + self.sum = 0 # cumulative time during which stopwatch was active + self.n = 0 # total n across all start/stop + self.start() + + def state_dict(self): + return { + "sum": self.sum, + "n": self.n, + "round": self.round, + } + + def load_state_dict(self, state_dict): + self.sum = state_dict["sum"] + self.n = state_dict["n"] + self.start_time = None + self.round = state_dict.get("round", None) + + @property + def avg(self): + return self.sum / self.n if self.n > 0 else self.sum + + @property + def elapsed_time(self): + if self.start_time is None: + return 0.0 + return time.perf_counter() - self.start_time + + @property + def smoothed_value(self) -> float: + val = self.avg if self.sum > 0 else self.elapsed_time + if self.round is not None and val is not None: + val = safe_round(val, self.round) + return val + + +class MetersDict(OrderedDict): + """A sorted dictionary of :class:`Meters`. + + Meters are sorted according to a priority that is given when the + meter is first added to the dictionary. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.priorities = [] + + def __setitem__(self, key, value): + assert key not in self, "MetersDict doesn't support reassignment" + priority, value = value + bisect.insort(self.priorities, (priority, len(self.priorities), key)) + super().__setitem__(key, value) + for _, _, key in self.priorities: # reorder dict to match priorities + self.move_to_end(key) + + def add_meter(self, key, meter, priority): + self.__setitem__(key, (priority, meter)) + + def state_dict(self): + return [ + (pri, key, self[key].__class__.__name__, self[key].state_dict()) + for pri, _, key in self.priorities + # can't serialize DerivedMeter instances + if not isinstance(self[key], MetersDict._DerivedMeter) + ] + + def load_state_dict(self, state_dict): + self.clear() + self.priorities.clear() + for pri, key, meter_cls, meter_state in state_dict: + meter = globals()[meter_cls]() + meter.load_state_dict(meter_state) + self.add_meter(key, meter, pri) + + def get_smoothed_value(self, key: str) -> float: + """Get a single smoothed value.""" + meter = self[key] + if isinstance(meter, MetersDict._DerivedMeter): + return meter.fn(self) + else: + return meter.smoothed_value + + def get_smoothed_values(self) -> Dict[str, float]: + """Get all smoothed values.""" + return OrderedDict( + [ + (key, self.get_smoothed_value(key)) + for key in self.keys() + if not key.startswith("_") + ] + ) + + def reset(self): + """Reset Meter instances.""" + for meter in self.values(): + if isinstance(meter, MetersDict._DerivedMeter): + continue + meter.reset() + + class _DerivedMeter(Meter): + """A Meter whose values are derived from other Meters.""" + + def __init__(self, fn): + self.fn = fn + + def reset(self): + pass diff --git a/fairseq-tools/fairseq/fairseq/logging/metrics.py b/fairseq-tools/fairseq/fairseq/logging/metrics.py new file mode 100644 index 00000000..7b56e315 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/logging/metrics.py @@ -0,0 +1,288 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +A standalone module for aggregating metrics. + +Metrics can be logged from anywhere using the `log_*` functions defined +in this module. The logged values will be aggregated dynamically based +on the aggregation context in which the logging occurs. See the +:func:`aggregate` context manager for more details. +""" + +import contextlib +import time +import uuid +from collections import OrderedDict, defaultdict +from typing import Callable, Dict, List, Optional + +from .meters import * + + +# Aggregation contexts are considered "active" when inside the scope +# created by the :func:`aggregate` context manager. +_aggregators = OrderedDict() +_active_aggregators = OrderedDict() +_active_aggregators_cnt = defaultdict(lambda: 0) + + +def reset() -> None: + """Reset all metrics aggregators.""" + _aggregators.clear() + _active_aggregators.clear() + _active_aggregators_cnt.clear() + + # The "default" aggregator observes all logged values. + _aggregators["default"] = MetersDict() + _active_aggregators["default"] = _aggregators["default"] + _active_aggregators_cnt["default"] = 1 + + +reset() + + +@contextlib.contextmanager +def aggregate(name: Optional[str] = None, new_root: bool = False): + """Context manager to aggregate metrics under a given name. + + Aggregations can be nested. If *new_root* is ``False``, then logged + metrics will be recorded along the entire stack of nested + aggregators, including a global "default" aggregator. If *new_root* + is ``True``, then this aggregator will be the root of a new + aggregation stack, thus bypassing any parent aggregators. + + Note that aggregation contexts are uniquely identified by their + *name* (e.g., train, valid). Creating a context with an existing + name will reuse the corresponding :class:`MetersDict` instance. + If no name is given, then a temporary aggregator will be created. + + Usage:: + + with metrics.aggregate("train"): + for step, batch in enumerate(epoch): + with metrics.aggregate("train_inner") as agg: + metrics.log_scalar("loss", get_loss(batch)) + if step % log_interval == 0: + print(agg.get_smoothed_value("loss")) + agg.reset() + print(metrics.get_smoothed_values("train")["loss"]) + + Args: + name (str): name of the aggregation. Defaults to a + random/temporary name if not given explicitly. + new_root (bool): make this aggregation the root of a new + aggregation stack. + """ + if name is None: + # generate a temporary name + name = str(uuid.uuid4()) + assert name not in _aggregators + agg = MetersDict() + else: + assert name != "default" + agg = _aggregators.setdefault(name, MetersDict()) + + if new_root: + backup_aggregators = _active_aggregators.copy() + _active_aggregators.clear() + backup_aggregators_cnt = _active_aggregators_cnt.copy() + _active_aggregators_cnt.clear() + + _active_aggregators[name] = agg + _active_aggregators_cnt[name] += 1 + + yield agg + + _active_aggregators_cnt[name] -= 1 + if _active_aggregators_cnt[name] == 0 and name in _active_aggregators: + del _active_aggregators[name] + + if new_root: + _active_aggregators.clear() + _active_aggregators.update(backup_aggregators) + _active_aggregators_cnt.clear() + _active_aggregators_cnt.update(backup_aggregators_cnt) + + +def get_active_aggregators() -> List[MetersDict]: + return list(_active_aggregators.values()) + + +def log_scalar( + key: str, + value: float, + weight: float = 1, + priority: int = 10, + round: Optional[int] = None, +): + """Log a scalar value. + + Args: + key (str): name of the field to log + value (float): value to log + weight (float): weight that this value contributes to the average. + A weight of 0 will always log the latest value. + priority (int): smaller values are logged earlier in the output + round (Optional[int]): number of digits to round to when displaying + """ + for agg in get_active_aggregators(): + if key not in agg: + agg.add_meter(key, AverageMeter(round=round), priority) + agg[key].update(value, weight) + + +def log_derived(key: str, fn: Callable[[MetersDict], float], priority: int = 20): + """Log a scalar value derived from other meters. + + Args: + key (str): name of the field to log + fn (Callable[[MetersDict], float]): function that takes a single + argument *meters* and returns the derived value + priority (int): smaller values are logged earlier in the output + """ + for agg in get_active_aggregators(): + if key not in agg: + agg.add_meter(key, MetersDict._DerivedMeter(fn), priority) + + +def log_speed( + key: str, + value: float, + priority: int = 30, + round: Optional[int] = None, +): + """Log the rate of some quantity per second. + + Args: + key (str): name of the field to log + value (float): value to log + priority (int): smaller values are logged earlier in the output + round (Optional[int]): number of digits to round to when displaying + """ + for agg in get_active_aggregators(): + if key not in agg: + agg.add_meter(key, TimeMeter(round=round), priority) + agg[key].reset() # reset meter on the first call + else: + agg[key].update(value) + + +def log_start_time(key: str, priority: int = 40, round: Optional[int] = None): + """Log the duration of some event in seconds. + + The duration will be computed once :func:`log_stop_time` is called. + + Args: + key (str): name of the field to log + priority (int): smaller values are logged earlier in the output + round (Optional[int]): number of digits to round to when displaying + """ + for agg in get_active_aggregators(): + if key not in agg: + agg.add_meter(key, StopwatchMeter(round=round), priority) + agg[key].start() + + +def log_stop_time(key: str, weight: float = 0.0, prehook=None): + """Log the duration of some event in seconds. + + The duration will be computed since :func:`log_start_time` was called. + Set weight > 0 to report the average time instead of the sum. + + Args: + key (str): name of the field to log + weight (float): weight that this time contributes to the average + prehook (function, no arguments): will be called before the timer + is stopped. For example, use prehook=torch.cuda.synchronize to + make sure all gpu operations are done before timer is stopped. + """ + for agg in get_active_aggregators(): + if key in agg: + agg[key].stop(weight, prehook) + + +def log_custom( + new_meter_fn: Callable[[], Meter], + key: str, + *args, + priority: int = 50, + **kwargs, +): + """Log using a custom Meter. + + Any extra *args* or *kwargs* will be passed through to the Meter's + *update* method. + + Args: + new_meter_fn (Callable[[], Meter]): function that returns a new + Meter instance + key (str): name of the field to log + priority (int): smaller values are logged earlier in the output + """ + for agg in get_active_aggregators(): + if key not in agg: + agg.add_meter(key, new_meter_fn(), priority) + agg[key].update(*args, **kwargs) + + +def reset_meter(name: str, key: str) -> None: + """Reset Meter instance aggregated under a given *name* and *key*.""" + meter = get_meter(name, key) + if meter is not None: + meter.reset() + + +def reset_meters(name: str) -> None: + """Reset Meter instances aggregated under a given *name*.""" + meters = get_meters(name) + if meters is not None: + meters.reset() + + +def get_meter(name: str, key: str) -> Meter: + """Get a single Meter instance aggregated under *name* and *key*. + + Returns: + Meter or None if no metrics have been logged under *name* and *key*. + """ + if name not in _aggregators: + return None + return _aggregators[name].get(key, None) + + +def get_meters(name: str) -> MetersDict: + """Get Meter instances aggregated under a given *name*. + + Returns: + MetersDict or None if no metrics have been logged under *name*. + """ + return _aggregators.get(name, None) + + +def get_smoothed_value(name: str, key: str) -> float: + """Get a single smoothed value. + + Raises: + KeyError: if no metrics have been logged under *name* and *key*. + """ + return _aggregators[name].get_smoothed_value(key) + + +def get_smoothed_values(name: str) -> Dict[str, float]: + """Get smoothed values aggregated under a given *name*. + + Raises: + KeyError: if no metrics have been logged under *name*. + """ + return _aggregators[name].get_smoothed_values() + + +def state_dict(): + return OrderedDict([(name, agg.state_dict()) for name, agg in _aggregators.items()]) + + +def load_state_dict(state_dict): + for name, agg_state in state_dict.items(): + _aggregators[name] = MetersDict() + _aggregators[name].load_state_dict(agg_state) diff --git a/fairseq-tools/fairseq/fairseq/logging/progress_bar.py b/fairseq-tools/fairseq/fairseq/logging/progress_bar.py new file mode 100644 index 00000000..63e53948 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/logging/progress_bar.py @@ -0,0 +1,355 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Wrapper around various loggers and progress bars (e.g., tqdm). +""" + +import atexit +import json +import logging +import os +import sys +from collections import OrderedDict +from contextlib import contextmanager +from numbers import Number +from typing import Optional + +import torch + +from .meters import AverageMeter, StopwatchMeter, TimeMeter + + +logger = logging.getLogger(__name__) + + +def progress_bar( + iterator, + log_format: Optional[str] = None, + log_interval: int = 100, + epoch: Optional[int] = None, + prefix: Optional[str] = None, + tensorboard_logdir: Optional[str] = None, + default_log_format: str = "tqdm", +): + if log_format is None: + log_format = default_log_format + if log_format == "tqdm" and not sys.stderr.isatty(): + log_format = "simple" + + if log_format == "json": + bar = JsonProgressBar(iterator, epoch, prefix, log_interval) + elif log_format == "none": + bar = NoopProgressBar(iterator, epoch, prefix) + elif log_format == "simple": + bar = SimpleProgressBar(iterator, epoch, prefix, log_interval) + elif log_format == "tqdm": + bar = TqdmProgressBar(iterator, epoch, prefix) + else: + raise ValueError("Unknown log format: {}".format(log_format)) + + if tensorboard_logdir: + try: + # [FB only] custom wrapper for TensorBoard + import palaas # noqa + from .fb_tbmf_wrapper import FbTbmfWrapper + + bar = FbTbmfWrapper(bar, log_interval) + except ImportError: + bar = TensorboardProgressBarWrapper(bar, tensorboard_logdir) + + return bar + + +def build_progress_bar( + args, + iterator, + epoch: Optional[int] = None, + prefix: Optional[str] = None, + default: str = "tqdm", + no_progress_bar: str = "none", +): + """Legacy wrapper that takes an argparse.Namespace.""" + if getattr(args, "no_progress_bar", False): + default = no_progress_bar + if getattr(args, "distributed_rank", 0) == 0: + tensorboard_logdir = getattr(args, "tensorboard_logdir", None) + else: + tensorboard_logdir = None + return progress_bar( + iterator, + log_format=args.log_format, + log_interval=args.log_interval, + epoch=epoch, + prefix=prefix, + tensorboard_logdir=tensorboard_logdir, + default_log_format=default, + ) + + +def format_stat(stat): + if isinstance(stat, Number): + stat = "{:g}".format(stat) + elif isinstance(stat, AverageMeter): + stat = "{:.3f}".format(stat.avg) + elif isinstance(stat, TimeMeter): + stat = "{:g}".format(round(stat.avg)) + elif isinstance(stat, StopwatchMeter): + stat = "{:g}".format(round(stat.sum)) + elif torch.is_tensor(stat): + stat = stat.tolist() + return stat + + +class BaseProgressBar(object): + """Abstract class for progress bars.""" + + def __init__(self, iterable, epoch=None, prefix=None): + self.iterable = iterable + self.n = getattr(iterable, "n", 0) + self.epoch = epoch + self.prefix = "" + if epoch is not None: + self.prefix += "epoch {:03d}".format(epoch) + if prefix is not None: + self.prefix += " | {}".format(prefix) + + def __len__(self): + return len(self.iterable) + + def __enter__(self): + return self + + def __exit__(self, *exc): + return False + + def __iter__(self): + raise NotImplementedError + + def log(self, stats, tag=None, step=None): + """Log intermediate stats according to log_interval.""" + raise NotImplementedError + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + raise NotImplementedError + + def _str_commas(self, stats): + return ", ".join(key + "=" + stats[key].strip() for key in stats.keys()) + + def _str_pipes(self, stats): + return " | ".join(key + " " + stats[key].strip() for key in stats.keys()) + + def _format_stats(self, stats): + postfix = OrderedDict(stats) + # Preprocess stats according to datatype + for key in postfix.keys(): + postfix[key] = str(format_stat(postfix[key])) + return postfix + + +@contextmanager +def rename_logger(logger, new_name): + old_name = logger.name + if new_name is not None: + logger.name = new_name + yield logger + logger.name = old_name + + +class JsonProgressBar(BaseProgressBar): + """Log output in JSON format.""" + + def __init__(self, iterable, epoch=None, prefix=None, log_interval=1000): + super().__init__(iterable, epoch, prefix) + self.log_interval = log_interval + self.i = None + self.size = None + + def __iter__(self): + self.size = len(self.iterable) + for i, obj in enumerate(self.iterable, start=self.n): + self.i = i + yield obj + + def log(self, stats, tag=None, step=None): + """Log intermediate stats according to log_interval.""" + step = step or self.i or 0 + if step > 0 and self.log_interval is not None and step % self.log_interval == 0: + update = ( + self.epoch - 1 + (self.i + 1) / float(self.size) + if self.epoch is not None + else None + ) + stats = self._format_stats(stats, epoch=self.epoch, update=update) + with rename_logger(logger, tag): + logger.info(json.dumps(stats)) + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + self.stats = stats + if tag is not None: + self.stats = OrderedDict( + [(tag + "_" + k, v) for k, v in self.stats.items()] + ) + stats = self._format_stats(self.stats, epoch=self.epoch) + with rename_logger(logger, tag): + logger.info(json.dumps(stats)) + + def _format_stats(self, stats, epoch=None, update=None): + postfix = OrderedDict() + if epoch is not None: + postfix["epoch"] = epoch + if update is not None: + postfix["update"] = round(update, 3) + # Preprocess stats according to datatype + for key in stats.keys(): + postfix[key] = format_stat(stats[key]) + return postfix + + +class NoopProgressBar(BaseProgressBar): + """No logging.""" + + def __init__(self, iterable, epoch=None, prefix=None): + super().__init__(iterable, epoch, prefix) + + def __iter__(self): + for obj in self.iterable: + yield obj + + def log(self, stats, tag=None, step=None): + """Log intermediate stats according to log_interval.""" + pass + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + pass + + +class SimpleProgressBar(BaseProgressBar): + """A minimal logger for non-TTY environments.""" + + def __init__(self, iterable, epoch=None, prefix=None, log_interval=1000): + super().__init__(iterable, epoch, prefix) + self.log_interval = log_interval + self.i = None + self.size = None + + def __iter__(self): + self.size = len(self.iterable) + for i, obj in enumerate(self.iterable, start=self.n): + self.i = i + yield obj + + def log(self, stats, tag=None, step=None): + """Log intermediate stats according to log_interval.""" + step = step or self.i or 0 + if step > 0 and self.log_interval is not None and step % self.log_interval == 0: + stats = self._format_stats(stats) + postfix = self._str_commas(stats) + with rename_logger(logger, tag): + logger.info( + "{}: {:5d} / {:d} {}".format( + self.prefix, self.i + 1, self.size, postfix + ) + ) + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + postfix = self._str_pipes(self._format_stats(stats)) + with rename_logger(logger, tag): + logger.info("{} | {}".format(self.prefix, postfix)) + + +class TqdmProgressBar(BaseProgressBar): + """Log to tqdm.""" + + def __init__(self, iterable, epoch=None, prefix=None): + super().__init__(iterable, epoch, prefix) + from tqdm import tqdm + + self.tqdm = tqdm( + iterable, + self.prefix, + leave=False, + disable=(logger.getEffectiveLevel() > logging.INFO), + ) + + def __iter__(self): + return iter(self.tqdm) + + def log(self, stats, tag=None, step=None): + """Log intermediate stats according to log_interval.""" + self.tqdm.set_postfix(self._format_stats(stats), refresh=False) + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + postfix = self._str_pipes(self._format_stats(stats)) + with rename_logger(logger, tag): + logger.info("{} | {}".format(self.prefix, postfix)) + + +try: + _tensorboard_writers = {} + from tensorboardX import SummaryWriter +except ImportError: + SummaryWriter = None + + +def _close_writers(): + for w in _tensorboard_writers.values(): + w.close() + + +atexit.register(_close_writers) + + +class TensorboardProgressBarWrapper(BaseProgressBar): + """Log to tensorboard.""" + + def __init__(self, wrapped_bar, tensorboard_logdir): + self.wrapped_bar = wrapped_bar + self.tensorboard_logdir = tensorboard_logdir + + if SummaryWriter is None: + logger.warning( + "tensorboard not found, please install with: pip install tensorboardX" + ) + + def _writer(self, key): + if SummaryWriter is None: + return None + _writers = _tensorboard_writers + if key not in _writers: + _writers[key] = SummaryWriter(os.path.join(self.tensorboard_logdir, key)) + _writers[key].add_text("sys.argv", " ".join(sys.argv)) + return _writers[key] + + def __iter__(self): + return iter(self.wrapped_bar) + + def log(self, stats, tag=None, step=None): + """Log intermediate stats to tensorboard.""" + self._log_to_tensorboard(stats, tag, step) + self.wrapped_bar.log(stats, tag=tag, step=step) + + def print(self, stats, tag=None, step=None): + """Print end-of-epoch stats.""" + self._log_to_tensorboard(stats, tag, step) + self.wrapped_bar.print(stats, tag=tag, step=step) + + def _log_to_tensorboard(self, stats, tag=None, step=None): + writer = self._writer(tag or "") + if writer is None: + return + if step is None: + step = stats["num_updates"] + for key in stats.keys() - {"num_updates"}: + if isinstance(stats[key], AverageMeter): + writer.add_scalar(key, stats[key].val, step) + elif isinstance(stats[key], Number): + writer.add_scalar(key, stats[key], step) + writer.flush() diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/__init__.py new file mode 100644 index 00000000..69f21684 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import criterions, models, modules # noqa diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/criterions/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/criterions/__init__.py new file mode 100644 index 00000000..6239b503 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/criterions/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +# automatically import any Python files in the criterions/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("fairseq.model_parallel.criterions." + module) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/criterions/vocab_parallel_cross_entropy.py b/fairseq-tools/fairseq/fairseq/model_parallel/criterions/vocab_parallel_cross_entropy.py new file mode 100644 index 00000000..35c50ee1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/criterions/vocab_parallel_cross_entropy.py @@ -0,0 +1,87 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +from fairseq import metrics, utils +from fairseq.criterions import FairseqCriterion, register_criterion + + +try: + from fairseq.model_parallel.megatron.mpu.cross_entropy import ( + vocab_parallel_cross_entropy, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +@register_criterion("vocab_parallel_cross_entropy") +class VocabParallelCrossEntropyCriterion(FairseqCriterion): + def __init__(self, task, sentence_avg): + super().__init__(task) + self.sentence_avg = sentence_avg + if not has_megatron_submodule: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + + def forward(self, model, sample, reduce=True): + """Compute the loss for the given sample. + + Returns a tuple with three elements: + 1) the loss + 2) the sample size, which is used as the denominator for the gradient + 3) logging outputs to display while training + """ + net_output = model(**sample["net_input"]) + target = sample["target"] + + loss = vocab_parallel_cross_entropy(net_output[0].float(), target) + loss = (loss * (target != self.padding_idx)).sum() + sample_size = ( + sample["target"].size(0) if self.sentence_avg else sample["ntokens"] + ) + logging_output = { + "loss": utils.item(loss.data) if reduce else loss.data, + "ntokens": sample["ntokens"], + "nsentences": sample["target"].size(0), + "sample_size": sample_size, + } + return loss, sample_size, logging_output + + @staticmethod + def reduce_metrics(logging_outputs) -> None: + """Aggregate logging outputs from data parallel training.""" + loss_sum = sum(log.get("loss", 0) for log in logging_outputs) + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + sample_size = sum(log.get("sample_size", 0) for log in logging_outputs) + + metrics.log_scalar( + "loss", loss_sum / sample_size / math.log(2), sample_size, round=3 + ) + if sample_size != ntokens: + metrics.log_scalar( + "nll_loss", loss_sum / ntokens / math.log(2), ntokens, round=3 + ) + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["nll_loss"].avg) + ) + else: + metrics.log_derived( + "ppl", lambda meters: utils.get_perplexity(meters["loss"].avg) + ) + + @staticmethod + def logging_outputs_can_be_summed() -> bool: + """ + Whether the logging outputs returned by `forward` can be summed + across workers prior to calling `reduce_metrics`. Setting this + to True will improves distributed training speed. + """ + return True diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/megatron_trainer.py b/fairseq-tools/fairseq/fairseq/model_parallel/megatron_trainer.py new file mode 100644 index 00000000..761ffc8e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/megatron_trainer.py @@ -0,0 +1,66 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Train a network across multiple GPUs. +""" + +from fairseq import distributed_utils +from fairseq.trainer import Trainer + + +try: + from fairseq.model_parallel.megatron.mpu import ( + get_data_parallel_group, + get_data_parallel_rank, + get_data_parallel_world_size, + get_model_parallel_group, + get_model_parallel_src_rank, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +class MegatronTrainer(Trainer): + """Main class for model parallel with data parallel training.""" + + def __init__(self, args, task, model, criterion): + if not has_megatron_submodule: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + super().__init__(args, task, model, criterion) + + @property + def data_parallel_world_size(self): + return get_data_parallel_world_size() + + @property + def data_parallel_process_group(self): + return get_data_parallel_group() + + @property + def data_parallel_rank(self): + return get_data_parallel_rank() + + @property + def is_data_parallel_master(self): + return get_model_parallel_src_rank() == 0 + + def clip_grad_norm(self, clip_norm): + def _aggregate_model_parallel_grad_norm(total_norm): + total_norm = total_norm ** 2 + distributed_utils.all_reduce(total_norm, group=get_model_parallel_group()) + total_norm = total_norm ** 0.5 + return total_norm + + return self.optimizer.clip_grad_norm( + clip_norm, + aggregate_norm_fn=_aggregate_model_parallel_grad_norm, + ) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/__init__.py new file mode 100644 index 00000000..3532479e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/__init__.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +# automatically import any Python files in the models/ directory +models_dir = os.path.dirname(__file__) +for file in os.listdir(models_dir): + path = os.path.join(models_dir, file) + if ( + not file.startswith("_") + and not file.startswith(".") + and (file.endswith(".py") or os.path.isdir(path)) + ): + model_name = file[: file.find(".py")] if file.endswith(".py") else file + module = importlib.import_module("fairseq.model_parallel.models." + model_name) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/__init__.py new file mode 100644 index 00000000..117827c3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .model import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/layers.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/layers.py new file mode 100644 index 00000000..eb81ded3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/layers.py @@ -0,0 +1,600 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from collections import namedtuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import options, utils +from fairseq.modules import ( + AdaptiveSoftmax, + LayerNorm, + MultiheadAttention, + PositionalEmbedding, +) + + +EncoderOut = namedtuple( + "TransformerEncoderOut", + [ + "encoder_out", # T x B x C + "encoder_padding_mask", # B x T + "encoder_embedding", # B x T x C + "encoder_states", # List[T x B x C] + ], +) + + +class TransformerEncoderEmbedding(nn.Module): + """ Encoder Embedding + Positional Embedding """ + + def __init__(self, args, embed_tokens): + super().__init__() + self.dropout = args.dropout + self.max_source_positions = args.max_source_positions + self.embed_tokens = embed_tokens + if isinstance(embed_tokens, nn.ModuleList): + self.padding_idx = embed_tokens[0].padding_idx + embed_dim = sum(e.embedding_dim for e in embed_tokens) + else: + self.padding_idx = embed_tokens.padding_idx + embed_dim = embed_tokens.embedding_dim + self.embed_scale = math.sqrt(embed_dim) + self.embed_positions = ( + PositionalEmbedding( + args.max_source_positions, + embed_dim, + self.padding_idx, + learned=args.encoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + if getattr(args, "layernorm_embedding", False): + self.layernorm_embedding = LayerNorm(embed_dim) + else: + self.layernorm_embedding = None + + def forward(self, input): + # embed tokens and positions + src_tokens = input[0] + prev_output_tokens = input[2] + if isinstance(self.embed_tokens, nn.ModuleList): + x_embed_list = [] + for embed_tokens_part in self.embed_tokens: + x_embed_list.append(embed_tokens_part(src_tokens)) + + embedded = torch.cat(x_embed_list, dim=-1) + else: + embedded = self.embed_tokens(src_tokens) + x = embed = self.embed_scale * embedded + if self.embed_positions is not None: + x = embed + self.embed_positions(src_tokens) + if self.layernorm_embedding: + x = self.layernorm_embedding(x) + x = F.dropout(x, p=self.dropout, training=self.training) + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # compute padding mask + encoder_padding_mask = src_tokens.eq(self.padding_idx) + return (x, encoder_padding_mask, prev_output_tokens) + + +class TransformerEncoderLayerNorm(nn.Module): + """ + Layer norm at the the end of all encoder layers if + args.encoder_enormalize_before = True + """ + + def __init__(self, args, embed_dim): + super().__init__() + if args.encoder_normalize_before: + self.layer_norm = LayerNorm(embed_dim) + else: + self.layer_norm = None + + def forward(self, input): + x = input[0] + encoder_padding_mask = input[1] + prev_output_tokens = input[2] + if self.layer_norm: + x = self.layer_norm(x) + # keeping track of the incremental_state is not supported yet + return (x, encoder_padding_mask, prev_output_tokens) + + +class TransformerDecoderEmbedding(nn.Module): + """ Decoder Embedding + Positional Embedding """ + + def __init__(self, args, embed_tokens): + super().__init__() + self.dropout = args.dropout + self.share_input_output_embed = args.share_decoder_input_output_embed + input_embed_dim = ( + sum(e.embedding_dim for e in embed_tokens) + if isinstance(embed_tokens, nn.ModuleList) + else embed_tokens.embedding_dim + ) + embed_dim = args.decoder_embed_dim + self.output_embed_dim = args.decoder_output_dim + + padding_idx = ( + embed_tokens[0].padding_idx + if isinstance(embed_tokens, nn.ModuleList) + else embed_tokens.padding_idx + ) + self.max_target_positions = args.max_target_positions + + self.embed_tokens = embed_tokens + self.embed_scale = math.sqrt(embed_dim) # todo: try with input_embed_dim + + self.project_in_dim = ( + Linear(input_embed_dim, embed_dim, bias=False) + if embed_dim != input_embed_dim + else None + ) + + self.embed_positions = ( + PositionalEmbedding( + args.max_target_positions, + embed_dim, + padding_idx, + learned=args.decoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + def forward(self, input): + mt_task = False + if isinstance(input, tuple): + if len(input) == 3: + encoder_out = input[0] + encoder_padding_mask = input[1] + prev_output_tokens = input[2] + incremental_state = None # Hardcoding to avoid passing of None objects + mt_task = True + else: + # HACK for now, need to fix (TODO sidgoyal) + prev_output_tokens = input[0] + # discard "src_lengths" + encoder_out = None + encoder_padding_mask = None + incremental_state = None + + else: + prev_output_tokens = input + encoder_out = None + encoder_padding_mask = None + incremental_state = None + + positions = ( + self.embed_positions( + prev_output_tokens, + incremental_state=incremental_state, + ) + if self.embed_positions is not None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + if positions is not None: + positions = positions[:, -1:] + + # embed tokens and positions + + if isinstance(self.embed_tokens, nn.ModuleList): + x_embed_list = [] + for embed_tokens_part in self.embed_tokens: + x_embed_list.append(embed_tokens_part(prev_output_tokens)) + + x = self.embed_scale * torch.cat(x_embed_list, dim=-1) + else: + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + x = F.dropout(x, p=self.dropout, training=self.training) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + if mt_task: + return (x, encoder_out, encoder_padding_mask) + return x + + +class TransformerDecoderOutputLayer(nn.Module): + def __init__(self, args, embed_tokens, dictionary): + super().__init__() + self.share_input_output_embed = args.share_decoder_input_output_embed + self.embed_tokens = embed_tokens + self.output_embed_dim = args.decoder_output_dim + embed_dim = args.decoder_embed_dim + + self.project_out_dim = ( + Linear(embed_dim, self.output_embed_dim, bias=False) + if embed_dim != self.output_embed_dim and not args.tie_adaptive_weights + else None + ) + self.adaptive_softmax = None + if args.adaptive_softmax_cutoff is not None: + assert not isinstance(embed_tokens, nn.ModuleList) + self.adaptive_softmax = AdaptiveSoftmax( + len(dictionary), + self.output_embed_dim, + options.eval_str_list(args.adaptive_softmax_cutoff, type=int), + dropout=args.adaptive_softmax_dropout, + adaptive_inputs=embed_tokens if args.tie_adaptive_weights else None, + factor=args.adaptive_softmax_factor, + tie_proj=args.tie_adaptive_proj, + ) + elif not self.share_input_output_embed: + self.embed_tokens = nn.Parameter( + torch.Tensor(len(dictionary), self.output_embed_dim) + ) + nn.init.normal_( + self.embed_tokens, mean=0, std=self.output_embed_dim ** -0.5 + ) + + if args.decoder_normalize_before and not getattr( + args, "no_decoder_final_norm", False + ): + self.layer_norm = LayerNorm(embed_dim) + else: + self.layer_norm = None + + def forward(self, input, apply_final_proj=True): + if isinstance(input, tuple): + x = input[0] + else: + x = input + + if self.layer_norm: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + if apply_final_proj: + x = self.output_layer(x) + return x + + def output_layer(self, features, **kwargs): + """Project features to the vocabulary size.""" + if self.adaptive_softmax is None: + # project back to size of vocabulary + if self.share_input_output_embed: + if isinstance(self.embed_tokens, nn.ModuleList): + output = None + for i, emb in enumerate(self.embed_tokens): + sidx = i * emb.embedding_dim + eidx = (i + 1) * emb.embedding_dim + if output is None: + output = F.linear(features[:, :, sidx:eidx], emb.weight) + else: + output += F.linear(features[:, :, sidx:eidx], emb.weight) + + return output + else: + return F.linear(features, self.embed_tokens.weight) + else: + return F.linear(features, self.embed_tokens) + else: + return features + + +class TransformerEncoderLayer(nn.Module): + """Encoder layer block. + In the original paper each operation (multi-head attention or FFN) is + postprocessed with: `dropout -> add residual -> layernorm`. In the + tensor2tensor code they suggest that learning is more robust when + preprocessing each layer with layernorm and postprocessing with: + `dropout -> add residual`. We default to the approach in the paper, but the + tensor2tensor approach can be enabled by setting + *args.encoder_normalize_before* to ``True``. + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + + def __init__(self, args): + super().__init__() + self.embed_dim = args.encoder_embed_dim + self.self_attn = MultiheadAttention( + self.embed_dim, + args.encoder_attention_heads, + dropout=args.attention_dropout, + self_attention=True, + ) + self.self_attn_layer_norm = LayerNorm(self.embed_dim) + self.dropout = args.dropout + self.activation_fn = utils.get_activation_fn( + activation=getattr(args, "activation_fn", "relu") + ) + self.activation_dropout = getattr(args, "activation_dropout", 0) + if self.activation_dropout == 0: + # for backwards compatibility with models that use args.relu_dropout + self.activation_dropout = getattr(args, "relu_dropout", 0) + self.normalize_before = args.encoder_normalize_before + self.fc1 = Linear(self.embed_dim, args.encoder_ffn_embed_dim) + self.fc2 = Linear(args.encoder_ffn_embed_dim, self.embed_dim) + self.final_layer_norm = LayerNorm(self.embed_dim) + + def upgrade_state_dict_named(self, state_dict, name): + """ + Rename layer norm states from `...layer_norms.0.weight` to + `...self_attn_layer_norm.weight` and `...layer_norms.1.weight` to + `...final_layer_norm.weight` + """ + layer_norm_map = {"0": "self_attn_layer_norm", "1": "final_layer_norm"} + for old, new in layer_norm_map.items(): + for m in ("weight", "bias"): + k = "{}.layer_norms.{}.{}".format(name, old, m) + if k in state_dict: + state_dict["{}.{}.{}".format(name, new, m)] = state_dict[k] + del state_dict[k] + + def forward(self, input): + """ + Args: + input (Tuple): + input[0] (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + input[1] (ByteTensor/FloatTensor): encoder padding mask - + binary ByteTensor of shape `(batch, src_len)` where padding elements + are indicated by ``1``. + input[2] (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing) + Returns: + output (Tuple): + output[0] (Tensor): encoded output of shape `(batch, src_len, embed_dim)` + output[1] (ByteTensor/FloatTensor): encoder padding mask + output[2] (LongTensor): previous decoder outputs + """ + x = input[0] + encoder_padding_mask = input[1] + prev_output_tokens = input[2] + residual = x + x = self.maybe_layer_norm(self.self_attn_layer_norm, x, before=True) + x, _ = self.self_attn( + query=x, key=x, value=x, key_padding_mask=encoder_padding_mask + ) + x = F.dropout(x, p=self.dropout, training=self.training) + x = residual + x + x = self.maybe_layer_norm(self.self_attn_layer_norm, x, after=True) + + residual = x + x = self.maybe_layer_norm(self.final_layer_norm, x, before=True) + x = self.activation_fn(self.fc1(x)) + x = F.dropout(x, p=self.activation_dropout, training=self.training) + x = self.fc2(x) + x = F.dropout(x, p=self.dropout, training=self.training) + x = residual + x + x = self.maybe_layer_norm(self.final_layer_norm, x, after=True) + return (x, encoder_padding_mask, prev_output_tokens) + + def maybe_layer_norm(self, layer_norm, x, before=False, after=False): + assert before ^ after + if after ^ self.normalize_before: + return layer_norm(x) + else: + return x + + +class TransformerDecoderLayer(nn.Module): + """Decoder layer block. + + In the original paper each operation (multi-head attention, encoder + attention or FFN) is postprocessed with: `dropout -> add residual -> + layernorm`. In the tensor2tensor code they suggest that learning is more + robust when preprocessing each layer with layernorm and postprocessing with: + `dropout -> add residual`. We default to the approach in the paper, but the + tensor2tensor approach can be enabled by setting + *args.decoder_normalize_before* to ``True``. + + Args: + args (argparse.Namespace): parsed command-line arguments + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__( + self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False + ): + super().__init__() + self.embed_dim = args.decoder_embed_dim + self.self_attn = MultiheadAttention( + embed_dim=self.embed_dim, + num_heads=args.decoder_attention_heads, + dropout=args.attention_dropout, + add_bias_kv=add_bias_kv, + add_zero_attn=add_zero_attn, + self_attention=True, + ) + self.dropout = args.dropout + self.activation_fn = utils.get_activation_fn( + activation=getattr(args, "activation_fn", "relu") + ) + self.activation_dropout = getattr(args, "activation_dropout", 0) + if self.activation_dropout == 0: + # for backwards compatibility with models that use args.relu_dropout + self.activation_dropout = getattr(args, "relu_dropout", 0) + self.normalize_before = args.decoder_normalize_before + + # use layerNorm rather than FusedLayerNorm for exporting. + # char_inputs can be used to determint this. + # TODO remove this once we update apex with the fix + export = getattr(args, "char_inputs", False) + self.self_attn_layer_norm = LayerNorm(self.embed_dim, export=export) + + if no_encoder_attn: + self.encoder_attn = None + self.encoder_attn_layer_norm = None + else: + self.encoder_attn = MultiheadAttention( + self.embed_dim, + args.decoder_attention_heads, + kdim=getattr(args, "encoder_embed_dim", None), + vdim=getattr(args, "encoder_embed_dim", None), + dropout=args.attention_dropout, + encoder_decoder_attention=True, + ) + self.encoder_attn_layer_norm = LayerNorm(self.embed_dim, export=export) + + self.fc1 = Linear(self.embed_dim, args.decoder_ffn_embed_dim) + self.fc2 = Linear(args.decoder_ffn_embed_dim, self.embed_dim) + + self.final_layer_norm = LayerNorm(self.embed_dim, export=export) + self.need_attn = True + + self.onnx_trace = False + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def forward(self, input): + """ + Args: + input (Tuple): + input[0] (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + input[1] (Tensor): encoder output of shape `(batch, src_len, embed_dim)` + input[2] (ByteTensor/FloatTensor): encoder padding mask - + binary ByteTensor of shape `(batch, src_len)` where padding elements + are indicated by ``1``. + Returns: + output (Tuple): + output[0] (Tensor): encoded output of shape `(batch, src_len, embed_dim)` + output[1] (ByteTensor/FloatTensor): encoder padding mask + output[2] (LongTensor): previous decoder outputs + """ + # Note: incremental state is not yet supported + mt_task = False + if isinstance(input, tuple): + x = input[0] + encoder_out = input[1] + encoder_padding_mask = input[2] + incremental_state = None + mt_task = True + else: + x = input + encoder_out = None + encoder_padding_mask = None + incremental_state = None + + if incremental_state is None: + self_attn_mask = self.buffered_future_mask(x) + else: + self_attn_mask = None + + # TODO: add back prev_self_attn_state, prev_attn_state, + # self_attn_padding_mask + prev_self_attn_state = None + prev_attn_state = None + self_attn_padding_mask = None + + residual = x + x = self.maybe_layer_norm(self.self_attn_layer_norm, x, before=True) + if prev_self_attn_state is not None: + if incremental_state is None: + incremental_state = {} + prev_key, prev_value = prev_self_attn_state + saved_state = {"prev_key": prev_key, "prev_value": prev_value} + self.self_attn._set_input_buffer(incremental_state, saved_state) + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + incremental_state=incremental_state, + need_weights=False, + attn_mask=self_attn_mask, + ) + x = F.dropout(x, p=self.dropout, training=self.training) + x = residual + x + x = self.maybe_layer_norm(self.self_attn_layer_norm, x, after=True) + + if self.encoder_attn is not None: + residual = x + x = self.maybe_layer_norm(self.encoder_attn_layer_norm, x, before=True) + if prev_attn_state is not None: + if incremental_state is None: + incremental_state = {} + prev_key, prev_value = prev_attn_state + saved_state = {"prev_key": prev_key, "prev_value": prev_value} + self.encoder_attn._set_input_buffer(incremental_state, saved_state) + x, attn = self.encoder_attn( + query=x, + key=encoder_out, + value=encoder_out, + key_padding_mask=encoder_padding_mask, + incremental_state=incremental_state, + static_kv=True, + need_weights=(not self.training and self.need_attn), + ) + x = F.dropout(x, p=self.dropout, training=self.training) + x = residual + x + x = self.maybe_layer_norm(self.encoder_attn_layer_norm, x, after=True) + + residual = x + x = self.maybe_layer_norm(self.final_layer_norm, x, before=True) + x = self.activation_fn(self.fc1(x)) + x = F.dropout(x, p=self.activation_dropout, training=self.training) + x = self.fc2(x) + x = F.dropout(x, p=self.dropout, training=self.training) + x = residual + x + x = self.maybe_layer_norm(self.final_layer_norm, x, after=True) + + if mt_task: + return (x, encoder_out, encoder_padding_mask) + return x + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + if ( + not hasattr(self, "_future_mask") + or self._future_mask is None + or self._future_mask.device != tensor.device + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(tensor.new(dim, dim)), 1 + ) + if self._future_mask.size(0) < dim: + self._future_mask = torch.triu( + utils.fill_with_neg_inf(self._future_mask.resize_(dim, dim)), 1 + ) + return self._future_mask[:dim, :dim] + + def maybe_layer_norm(self, layer_norm, x, before=False, after=False): + assert before ^ after + if after ^ self.normalize_before: + return layer_norm(x) + else: + return x + + def make_generation_fast_(self, need_attn=False, **kwargs): + self.need_attn = need_attn + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.normal_(m.weight, mean=0, std=embedding_dim ** -0.5) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/model.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/model.py new file mode 100644 index 00000000..cbfc6ae4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/pipeline_parallel_transformer/model.py @@ -0,0 +1,721 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.model_parallel.models.pipeline_parallel_transformer.layers import ( + Embedding, + TransformerDecoderEmbedding, + TransformerDecoderLayer, + TransformerDecoderOutputLayer, + TransformerEncoderEmbedding, + TransformerEncoderLayer, + TransformerEncoderLayerNorm, +) +from fairseq.models import ( + BaseFairseqModel, + FairseqDecoder, + FairseqEncoder, + register_model, + register_model_architecture, +) +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.models.transformer import ( + base_architecture, + transformer_iwslt_de_en, + transformer_wmt_en_de_big, +) +from fairseq.modules import SinusoidalPositionalEmbedding + + +logger = logging.getLogger(__name__) + + +DEFAULT_MAX_SOURCE_POSITIONS = 1024 +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@register_model("pipeline_parallel_transformer") +class PipelineParallelTransformerModel(BaseFairseqModel): + def __init__(self, encoder, decoder, balance, devices, chunks, checkpoint): + try: + from fairscale.nn import Pipe + except ImportError: + raise ImportError("Please install fairscale with: pip install fairscale") + super().__init__() + assert isinstance(encoder, FairseqEncoder) + assert isinstance(decoder, FairseqDecoder) + encoder_module_list = ( + [encoder.embedding_layer] + + list(encoder.encoder_layers) + + [encoder.final_layer_norm] + ) + self.num_encoder_modules = len(encoder_module_list) + decoder_module_list = ( + [decoder.embedding_layer] + + list(decoder.decoder_layers) + + [decoder.decoder_output_layer] + ) + self.num_decoder_modules = len(decoder_module_list) + module_list = encoder_module_list + decoder_module_list + self.devices = devices + self.model = Pipe( + nn.Sequential(*module_list), + balance=balance, + devices=devices, + chunks=chunks, + checkpoint=checkpoint, + ) + self.encoder_max_positions = self.max_positions_helper( + encoder.embedding_layer, "max_source_positions" + ) + self.decoder_max_positions = self.max_positions_helper( + decoder.embedding_layer, "max_target_positions" + ) + self.adaptive_softmax = getattr(decoder, "adaptive_softmax", None) + # Note: To be populated during inference + self.encoder = None + self.decoder = None + + def forward(self, src_tokens, src_lengths, prev_output_tokens): + if self.training: + input_lst = [src_tokens, src_lengths, prev_output_tokens] + input = tuple(i.to(self.devices[0], non_blocking=True) for i in input_lst) + return self.model(input) + else: + assert self.encoder is not None and self.decoder is not None, ( + "encoder and decoder need to be initialized by " + + "calling the `prepare_for_inference_()` method" + ) + encoder_output_tuple = self.encoder(input) + return self.decoder(encoder_output_tuple) + + def prepare_for_inference_(self, args): + if self.encoder is not None and self.decoder is not None: + logger.info("Encoder and Decoder already initialized") + return + encoder_module_list = [] + decoder_module_list = [] + module_count = 0 + for partition in self.model.partitions: + for module in partition: + if module_count < self.num_encoder_modules: + encoder_module_list.append(module) + else: + decoder_module_list.append(module) + module_count += 1 + self.model = None + self.encoder = TransformerEncoder(args, None, None, encoder_module_list) + self.decoder = TransformerDecoder( + args, None, None, decoder_module_list=decoder_module_list + ) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--activation-fn', + choices=utils.get_available_activation_fns(), + help='activation function to use') + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--attention-dropout', type=float, metavar='D', + help='dropout probability for attention weights') + parser.add_argument('--activation-dropout', '--relu-dropout', type=float, metavar='D', + help='dropout probability after activation in FFN.') + parser.add_argument('--encoder-embed-path', type=str, metavar='STR', + help='path to pre-trained encoder embedding') + parser.add_argument('--encoder-embed-dim', type=int, metavar='N', + help='encoder embedding dimension') + parser.add_argument('--encoder-ffn-embed-dim', type=int, metavar='N', + help='encoder embedding dimension for FFN') + parser.add_argument('--encoder-layers', type=int, metavar='N', + help='num encoder layers') + parser.add_argument('--encoder-attention-heads', type=int, metavar='N', + help='num encoder attention heads') + parser.add_argument('--encoder-normalize-before', action='store_true', + help='apply layernorm before each encoder block') + parser.add_argument('--encoder-learned-pos', action='store_true', + help='use learned positional embeddings in the encoder') + parser.add_argument('--decoder-embed-path', type=str, metavar='STR', + help='path to pre-trained decoder embedding') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-ffn-embed-dim', type=int, metavar='N', + help='decoder embedding dimension for FFN') + parser.add_argument('--decoder-layers', type=int, metavar='N', + help='num decoder layers') + parser.add_argument('--decoder-attention-heads', type=int, metavar='N', + help='num decoder attention heads') + parser.add_argument('--decoder-learned-pos', action='store_true', + help='use learned positional embeddings in the decoder') + parser.add_argument('--decoder-normalize-before', action='store_true', + help='apply layernorm before each decoder block') + parser.add_argument('--share-decoder-input-output-embed', action='store_true', + help='share decoder input and output embeddings') + parser.add_argument('--share-all-embeddings', action='store_true', + help='share encoder, decoder and output embeddings' + ' (requires shared dictionary and embed dim)') + parser.add_argument('--no-token-positional-embeddings', default=False, action='store_true', + help='if set, disables positional embeddings (outside self attention)') + parser.add_argument('--adaptive-softmax-cutoff', metavar='EXPR', + help='comma separated list of adaptive softmax cutoff points. ' + 'Must be used with adaptive_loss criterion'), + parser.add_argument('--adaptive-softmax-dropout', type=float, metavar='D', + help='sets adaptive softmax dropout for the tail projections') + parser.add_argument('--num-embedding-chunks', type=int, metavar='N', default=1, + help='Number of embedding layer chunks (enables more even distribution' + 'of optimizer states across data parallel nodes' + 'when using optimizer state sharding and' + 'a big embedding vocabulary)') + # fmt: on + + @classmethod + def build_model_base(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if not hasattr(args, "max_source_positions"): + args.max_source_positions = DEFAULT_MAX_SOURCE_POSITIONS + if not hasattr(args, "max_target_positions"): + args.max_target_positions = DEFAULT_MAX_TARGET_POSITIONS + + src_dict, tgt_dict = task.source_dictionary, task.target_dictionary + + def build_embedding(dictionary, embed_dim, path=None, num_embed_chunks=1): + assert embed_dim % num_embed_chunks == 0, ( + f"Number of embedding chunks = {num_embed_chunks} should be " + + f"divisible by the embedding dimension = {embed_dim}" + ) + assert path is None or num_embed_chunks == 1, ( + "Loading embedding from a path with number of embedding chunks > 1" + + " is not yet supported" + ) + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + # if provided, load from preloaded dictionaries + if path: + emb = Embedding(num_embeddings, embed_dim, padding_idx) + embed_dict = utils.parse_embedding(path) + utils.load_embedding(embed_dict, dictionary, emb) + else: + embed_chunk_dim = embed_dim // num_embed_chunks + emb = nn.ModuleList() + for i in range(num_embed_chunks): + emb.append(Embedding(num_embeddings, embed_chunk_dim, padding_idx)) + return emb + + num_embed_chunks = args.num_embedding_chunks + if args.share_all_embeddings: + if src_dict != tgt_dict: + raise ValueError("--share-all-embeddings requires a joined dictionary") + if args.encoder_embed_dim != args.decoder_embed_dim: + raise ValueError( + "--share-all-embeddings requires --encoder-embed-dim to match --decoder-embed-dim" + ) + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise ValueError( + "--share-all-embeddings not compatible with --decoder-embed-path" + ) + encoder_embed_tokens = build_embedding( + src_dict, + args.encoder_embed_dim, + args.encoder_embed_path, + num_embed_chunks, + ) + decoder_embed_tokens = encoder_embed_tokens + args.share_decoder_input_output_embed = True + else: + assert args.share_decoder_input_output_embed or num_embed_chunks == 1, ( + "Not sharing decoder I/O embeddings is not yet supported with number of " + + "embedding chunks > 1" + ) + encoder_embed_tokens = build_embedding( + src_dict, + args.encoder_embed_dim, + args.encoder_embed_path, + num_embed_chunks, + ) + decoder_embed_tokens = build_embedding( + tgt_dict, + args.decoder_embed_dim, + args.decoder_embed_path, + num_embed_chunks, + ) + + encoder = cls.build_encoder(args, src_dict, encoder_embed_tokens) + decoder = cls.build_decoder(args, tgt_dict, decoder_embed_tokens) + return (encoder, decoder) + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerEncoder(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerDecoder(args, tgt_dict, embed_tokens) + + @classmethod + def build_model(cls, args, task): + encoder, decoder = cls.build_model_base(args, task) + return PipelineParallelTransformerModel( + encoder=encoder, + decoder=decoder, + balance=utils.eval_str_list(args.pipeline_balance, type=int), + devices=utils.eval_str_list(args.pipeline_devices, type=int), + chunks=args.pipeline_chunks, + checkpoint=args.pipeline_checkpoint, + ) + + def output_layer(self, features, **kwargs): + """Project features to the default output size (typically vocabulary size).""" + return self.decoder.output_layer(features, **kwargs) + + def max_positions(self): + """Maximum length supported by the model.""" + return (self.encoder_max_positions, self.decoder_max_positions) + + def max_positions_helper( + self, embedding_layer, max_positions_field="max_source_positions" + ): + """Maximum input length supported by the encoder or decoder.""" + if embedding_layer.embed_positions is None: + return getattr(embedding_layer, max_positions_field) + return min( + getattr(embedding_layer, max_positions_field), + embedding_layer.embed_positions.max_positions, + ) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + """Get normalized probabilities (or log probs) from a net's output.""" + + if hasattr(self, "adaptive_softmax") and self.adaptive_softmax is not None: + if sample is not None: + assert "target" in sample + target = sample["target"] + else: + target = None + out = self.adaptive_softmax.get_log_prob(net_output, target=target) + return out.exp_() if not log_probs else out + + # A Pipe() module returns a tuple of tensors as the output. + # In this case, the tuple has one element - the output tensor of logits + logits = net_output if isinstance(net_output, torch.Tensor) else net_output[0] + if log_probs: + return utils.log_softmax(logits, dim=-1, onnx_trace=False) + else: + return utils.softmax(logits, dim=-1, onnx_trace=False) + + def max_decoder_positions(self): + """Maximum length supported by the decoder.""" + return self.decoder_max_positions + + def load_state_dict(self, state_dict, strict=True, args=None): + """Copies parameters and buffers from *state_dict* into this module and + its descendants. + + Overrides the method in :class:`nn.Module`. Compared with that method + this additionally "upgrades" *state_dicts* from old checkpoints. + """ + self.upgrade_state_dict(state_dict) + is_regular_transformer = not any("model.partitions" in k for k in state_dict) + if is_regular_transformer: + state_dict = self.convert_to_pipeline_parallel_state_dict(state_dict) + return super().load_state_dict(state_dict, strict) + + def convert_to_pipeline_parallel_state_dict(self, state_dict): + new_state_dict = self.state_dict() + encoder_layer_idx = 0 + decoder_layer_idx = 0 + encoder_key_suffixes = [ + "self_attn.k_proj.weight", + "self_attn.k_proj.bias", + "self_attn.v_proj.weight", + "self_attn.v_proj.bias", + "self_attn.q_proj.weight", + "self_attn.q_proj.bias", + "self_attn.out_proj.weight", + "self_attn.out_proj.bias", + "self_attn_layer_norm.weight", + "self_attn_layer_norm.bias", + "fc1.weight", + "fc1.bias", + "fc2.weight", + "fc2.bias", + "final_layer_norm.weight", + "final_layer_norm.bias", + ] + decoder_key_suffixes = [ + "self_attn.k_proj.weight", + "self_attn.k_proj.bias", + "self_attn.v_proj.weight", + "self_attn.v_proj.bias", + "self_attn.q_proj.weight", + "self_attn.q_proj.bias", + "self_attn.out_proj.weight", + "self_attn.out_proj.bias", + "self_attn_layer_norm.weight", + "self_attn_layer_norm.bias", + "encoder_attn.k_proj.weight", + "encoder_attn.k_proj.bias", + "encoder_attn.v_proj.weight", + "encoder_attn.v_proj.bias", + "encoder_attn.q_proj.weight", + "encoder_attn.q_proj.bias", + "encoder_attn.out_proj.weight", + "encoder_attn.out_proj.bias", + "encoder_attn_layer_norm.weight", + "encoder_attn_layer_norm.bias", + "fc1.weight", + "fc1.bias", + "fc2.weight", + "fc2.bias", + "final_layer_norm.weight", + "final_layer_norm.bias", + ] + for pid, partition in enumerate(self.model.partitions): + logger.info(f"Begin Partition {pid}") + for mid, module in enumerate(partition): + # fmt: off + if isinstance(module, TransformerEncoderEmbedding): + new_state_dict[f'model.partitions.{pid}.{mid}.embed_tokens.weight'] = state_dict['encoder.embed_tokens.weight'] + new_state_dict[f'model.partitions.{pid}.{mid}.embed_positions._float_tensor'] = state_dict['encoder.embed_positions._float_tensor'] + if isinstance(module, TransformerEncoderLayer): + for suffix in encoder_key_suffixes: + new_state_dict[f'model.partitions.{pid}.{mid}.{suffix}'] = state_dict[f'encoder.layers.{encoder_layer_idx}.{suffix}'] + encoder_layer_idx += 1 + if isinstance(module, TransformerDecoderLayer): + for suffix in decoder_key_suffixes: + new_state_dict[f'model.partitions.{pid}.{mid}.{suffix}'] = state_dict[f'decoder.layers.{decoder_layer_idx}.{suffix}'] + decoder_layer_idx += 1 + if isinstance(module, TransformerEncoderLayerNorm): + if 'encoder.layer_norm.weight' in state_dict: + new_state_dict[f'model.partitions.{pid}.{mid}.layer_norm.weight'] = state_dict['encoder.layer_norm.weight'] + new_state_dict[f'model.partitions.{pid}.{mid}.layer_norm.bias'] = state_dict['encoder.layer_norm.bias'] + if isinstance(module, TransformerDecoderEmbedding): + new_state_dict[f'model.partitions.{pid}.{mid}.embed_tokens.weight'] = state_dict['decoder.embed_tokens.weight'] + new_state_dict[f'model.partitions.{pid}.{mid}.embed_positions._float_tensor'] = state_dict['decoder.embed_positions._float_tensor'] + if isinstance(module, TransformerDecoderOutputLayer): + new_state_dict[f'model.partitions.{pid}.{mid}.output_projection.weight'] = state_dict['decoder.output_projection.weight'] + # fmt: on + return new_state_dict + + +class TransformerEncoder(FairseqEncoder): + """ + Transformer encoder consisting of *args.encoder_layers* layers. Each layer + is a :class:`TransformerEncoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): encoding dictionary + embed_tokens (torch.nn.Embedding): input embedding + """ + + def __init__(self, args, dictionary, embed_tokens, encoder_module_list=None): + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([3])) + try: + from fairscale.nn import Pipe + except ImportError: + raise ImportError("Please install fairscale with: pip install fairscale") + if encoder_module_list is None: + embedding_layer = TransformerEncoderEmbedding(args, embed_tokens) + layers = [TransformerEncoderLayer(args) for i in range(args.encoder_layers)] + if isinstance(embed_tokens, nn.ModuleList): + emb_dim = sum(e.embedding_dim for e in embed_tokens) + else: + emb_dim = embed_tokens.embedding_dim + final_layer_norm = TransformerEncoderLayerNorm(args, emb_dim) + encoder_module_list = [embedding_layer] + layers + [final_layer_norm] + self.use_pipeline = getattr(args, "pipeline_encoder_balance", None) is not None + if self.use_pipeline: + encoder_balance = utils.eval_str_list( + args.pipeline_encoder_balance, type=int + ) + encoder_devices = utils.eval_str_list( + args.pipeline_encoder_devices, type=int + ) + assert sum(encoder_balance) == len(encoder_module_list), ( + f"Sum of encoder_balance={encoder_balance} is not equal " + + f"to num_encoder_modules={len(encoder_module_list)}" + ) + self.model = Pipe( + module=nn.Sequential(*encoder_module_list), + balance=encoder_balance, + devices=encoder_devices, + chunks=args.pipeline_chunks, + checkpoint=args.pipeline_checkpoint, + ) + else: + self.embedding_layer = encoder_module_list[0] + self.encoder_layers = nn.Sequential(*encoder_module_list[1:-1]) + self.final_layer_norm = encoder_module_list[-1] + + def forward(self, src_tokens, src_lengths): + """ + Args: + input_tuple( + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (torch.LongTensor): lengths of each source sentence of + shape `(batch)` + ) + + Returns: + output_tuple( + - **encoder_out** (Tensor): the last encoder layer's output of + shape `(src_len, batch, embed_dim)` + - **encoder_padding_mask** (ByteTensor): the positions of + padding elements of shape `(batch, src_len)` + - prev_output_tokens + - **encoder_states** (List[Tensor]): all intermediate + hidden states of shape `(src_len, batch, embed_dim)`. + Only populated if *return_all_hiddens* is True. + ) + """ + dummy_prev_output_tokens = torch.zeros( + 1, dtype=src_tokens.dtype, device=src_tokens.device + ) + input_tuple = (src_tokens, src_lengths, dummy_prev_output_tokens) + if self.use_pipeline: + input_tuple = tuple(i.to(self.model.devices[0]) for i in input_tuple) + encoder_out = self.model(input_tuple) + else: + encoder_embed_output_tuple = self.embedding_layer(input_tuple) + encoder_layers_output = self.encoder_layers(encoder_embed_output_tuple) + encoder_out = self.final_layer_norm(encoder_layers_output) + # first element is the encoder output + # second element is the encoder padding mask + # the remaining elements of EncoderOut are not computed by + # the PipelineParallelTransformer + return EncoderOut(encoder_out[0], encoder_out[1], None, None, None, None) + + def reorder_encoder_out(self, encoder_out, new_order): + """ + Reorder encoder output according to *new_order*. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + *encoder_out* rearranged according to *new_order* + """ + if encoder_out.encoder_out is not None: + encoder_out = encoder_out._replace( + encoder_out=encoder_out.encoder_out.index_select(1, new_order) + ) + if encoder_out.encoder_padding_mask is not None: + encoder_out = encoder_out._replace( + encoder_padding_mask=encoder_out.encoder_padding_mask.index_select( + 0, new_order + ) + ) + if encoder_out.encoder_embedding is not None: + encoder_out = encoder_out._replace( + encoder_embedding=encoder_out.encoder_embedding.index_select( + 0, new_order + ) + ) + if encoder_out.encoder_states is not None: + for idx, state in enumerate(encoder_out.encoder_states): + encoder_out.encoder_states[idx] = state.index_select(1, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + if self.embedding_layer.embed_positions is None: + return self.embedding_layer.max_source_positions + return min( + self.embedding_layer.max_source_positions, + self.embedding_layer.embed_positions.max_positions, + ) + + +class TransformerDecoder(FairseqDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__( + self, + args, + dictionary, + embed_tokens, + no_encoder_attn=False, + decoder_module_list=None, + ): + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([3])) + try: + from fairscale.nn import Pipe + except ImportError: + raise ImportError("Please install fairscale with: pip install fairscale") + if decoder_module_list is None: + embedding_layer = TransformerDecoderEmbedding(args, embed_tokens) + layers = [ + TransformerDecoderLayer(args, no_encoder_attn) + for _ in range(args.decoder_layers) + ] + decoder_output_layer = TransformerDecoderOutputLayer( + args, embed_tokens, dictionary + ) + decoder_module_list = [embedding_layer] + layers + [decoder_output_layer] + self.use_pipeline = getattr(args, "pipeline_decoder_balance", None) is not None + if self.use_pipeline: + decoder_balance = utils.eval_str_list( + args.pipeline_decoder_balance, type=int + ) + decoder_devices = utils.eval_str_list( + args.pipeline_decoder_devices, type=int + ) + assert sum(decoder_balance) == len(decoder_module_list), ( + f"Sum of decoder_balance={decoder_balance} is not equal " + + f"to num_decoder_modules={len(decoder_module_list)}" + ) + self.model = Pipe( + module=nn.Sequential(*decoder_module_list), + balance=decoder_balance, + devices=decoder_devices, + chunks=args.pipeline_chunks, + checkpoint=args.pipeline_checkpoint, + ) + else: + self.embedding_layer = decoder_module_list[0] + self.decoder_layers = nn.Sequential(*decoder_module_list[1:-1]) + self.decoder_output_layer = decoder_module_list[-1] + + def forward( + self, + prev_output_tokens, + encoder_out=None, + ): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (optional): output from the encoder, used for + encoder-side attention + incremental_state (dict): dictionary used for storing state during + :ref:`Incremental decoding` + features_only (bool, optional): only return features without + applying output layer (default: False). + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + input_tuple = ( + encoder_out.encoder_out, + encoder_out.encoder_padding_mask, + prev_output_tokens, + ) + if self.use_pipeline: + input_tuple = tuple(i.to(self.model.devices[0]) for i in input_tuple) + return (self.model(input_tuple),) + else: + embed_layer_output = self.embedding_layer(input_tuple) + state = self.decoder_layers(embed_layer_output) + return (self.decoder_output_layer(state),) + + def output_layer(self, features, **kwargs): + """Project features to the vocabulary size.""" + if self.adaptive_softmax is None: + # project back to size of vocabulary + if self.share_input_output_embed: + return F.linear(features, self.embed_tokens.weight) + else: + return F.linear(features, self.embed_out) + else: + return features + + def max_positions(self): + """Maximum output length supported by the decoder.""" + if self.embedding_layer.embed_positions is None: + return self.embedding_layer.max_target_positions + return min( + self.embedding_layer.max_target_positions, + self.embedding_layer.embed_positions.max_positions, + ) + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + if ( + not hasattr(self, "_future_mask") + or self._future_mask is None + or self._future_mask.device != tensor.device + or self._future_mask.size(0) < dim + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(tensor.new(dim, dim)), 1 + ) + return self._future_mask[:dim, :dim] + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + if isinstance(self.embed_positions, SinusoidalPositionalEmbedding): + weights_key = "{}.embed_positions.weights".format(name) + if weights_key in state_dict: + del state_dict[weights_key] + state_dict[ + "{}.embed_positions._float_tensor".format(name) + ] = torch.FloatTensor(1) + + for i in range(len(self.layers)): + # update layer norms + layer_norm_map = { + "0": "self_attn_layer_norm", + "1": "encoder_attn_layer_norm", + "2": "final_layer_norm", + } + for old, new in layer_norm_map.items(): + for m in ("weight", "bias"): + k = "{}.layers.{}.layer_norms.{}.{}".format(name, i, old, m) + if k in state_dict: + state_dict[ + "{}.layers.{}.{}.{}".format(name, i, new, m) + ] = state_dict[k] + del state_dict[k] + + version_key = "{}.version".format(name) + if utils.item(state_dict.get(version_key, torch.Tensor([1]))[0]) <= 2: + # earlier checkpoints did not normalize after the stack of layers + self.layer_norm = None + self.normalize = False + state_dict[version_key] = torch.Tensor([1]) + + return state_dict + + +@register_model_architecture( + "pipeline_parallel_transformer", "transformer_iwslt_de_en_pipeline_parallel" +) +def transformer_iwslt_de_en_dist(args): + transformer_iwslt_de_en(args) + + +@register_model_architecture( + "pipeline_parallel_transformer", "transformer_wmt_en_de_big_pipeline_parallel" +) +def transformer_wmt_en_de_big_dist(args): + transformer_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/__init__.py new file mode 100644 index 00000000..117827c3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .model import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/model.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/model.py new file mode 100644 index 00000000..68ad88d2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/roberta/model.py @@ -0,0 +1,287 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +RoBERTa: A Robustly Optimized BERT Pretraining Approach. +""" + +import logging + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.model_parallel.modules import ModelParallelTransformerSentenceEncoder +from fairseq.models import FairseqEncoder, register_model, register_model_architecture +from fairseq.models.roberta import ( + RobertaClassificationHead, + RobertaEncoder, + RobertaLMHead, + RobertaModel, +) +from fairseq.modules import LayerNorm, TransformerSentenceEncoder +from fairseq.modules.transformer_sentence_encoder import init_bert_params + + +try: + from fairseq.model_parallel.megatron.mpu import ( + copy_to_model_parallel_region, + gather_from_model_parallel_region, + ColumnParallelLinear, + RowParallelLinear, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + +logger = logging.getLogger(__name__) + + +@register_model("model_parallel_roberta") +class ModelParallelRobertaModel(RobertaModel): + def __init__(self, args, encoder): + super().__init__(args, encoder) + + self.classification_heads = nn.ModuleDict() + + @staticmethod + def add_args(parser): + super(ModelParallelRobertaModel, ModelParallelRobertaModel).add_args(parser) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present + base_architecture(args) + + task.source_dictionary.pad_to_multiple_(args.model_parallel_size * 8) + task.target_dictionary.pad_to_multiple_(args.model_parallel_size * 8) + + if not hasattr(args, "max_positions"): + args.max_positions = args.tokens_per_sample + + if getattr(args, "untie_weights_roberta", False): + raise NotImplementedError( + "--untie-weights-roberta is not supported in model parallel mode" + ) + + encoder = ModelParallelRobertaEncoder(args, task.source_dictionary) + return cls(args, encoder) + + def forward( + self, + src_tokens, + features_only=False, + return_all_hiddens=False, + classification_head_name=None, + **kwargs + ): + if classification_head_name is not None: + features_only = True + + x, extra = self.encoder(src_tokens, features_only, return_all_hiddens, **kwargs) + + if classification_head_name is not None: + x = self.classification_heads[classification_head_name](x) + return x, extra + + def register_classification_head( + self, name, num_classes=None, inner_dim=None, **kwargs + ): + """Register a classification head.""" + if name in self.classification_heads: + prev_num_classes = self.classification_heads[name].out_proj.out_features + prev_inner_dim = self.classification_heads[name].dense.out_features + if num_classes != prev_num_classes or inner_dim != prev_inner_dim: + logger.warning( + 're-registering head "{}" with num_classes {} (prev: {}) ' + "and inner_dim {} (prev: {})".format( + name, num_classes, prev_num_classes, inner_dim, prev_inner_dim + ) + ) + self.classification_heads[name] = ModelParallelRobertaClassificationHead( + self.args.encoder_embed_dim, + inner_dim or self.args.encoder_embed_dim, + num_classes, + self.args.pooler_activation_fn, + self.args.pooler_dropout, + ) + + +class ModelParallelRobertaLMHead(nn.Module): + """Head for masked language modeling.""" + + def __init__(self, embed_dim, output_dim, activation_fn, weight=None): + super().__init__() + self.dense = ColumnParallelLinear(embed_dim, embed_dim, gather_output=True) + self.activation_fn = utils.get_activation_fn(activation_fn) + self.layer_norm = LayerNorm(embed_dim) + + if weight is None: + weight = nn.Linear(embed_dim, output_dim, bias=False).weight + self.weight = weight + self.bias = nn.Parameter(torch.zeros(output_dim)) + + def forward(self, features, masked_tokens=None, **kwargs): + # Only project the unmasked tokens while training, + # saves both memory and computation + if masked_tokens is not None: + features = features[masked_tokens, :] + + x = self.dense(features) + x = self.activation_fn(x) + x = self.layer_norm(x) + + x = copy_to_model_parallel_region(x) + # project back to size of vocabulary with bias + x = F.linear(x, self.weight) + x = gather_from_model_parallel_region(x).contiguous() + x = x + self.bias + return x + + +class ModelParallelRobertaClassificationHead(nn.Module): + """Head for sentence-level classification tasks.""" + + def __init__( + self, input_dim, inner_dim, num_classes, activation_fn, pooler_dropout + ): + super().__init__() + self.dense = ColumnParallelLinear(input_dim, inner_dim, gather_output=True) + self.activation_fn = utils.get_activation_fn(activation_fn) + self.dropout = nn.Dropout(p=pooler_dropout) + self.out_proj = nn.Linear(inner_dim, num_classes) + + def forward(self, features, **kwargs): + x = features[:, 0, :] # take <s> token (equiv. to [CLS]) + x = self.dropout(x) + x = self.dense(x) + x = self.activation_fn(x) + x = self.dropout(x) + x = self.out_proj(x) + return x + + +class ModelParallelRobertaEncoder(FairseqEncoder): + """RoBERTa encoder. + + Implements the :class:`~fairseq.models.FairseqDecoder` interface required + by :class:`~fairseq.models.FairseqLanguageModel`. + """ + + def __init__(self, args, dictionary): + super().__init__(dictionary) + self.args = args + + # RoBERTa is a sentence encoder model, so users will intuitively trim + # encoder layers. However, the implementation uses the fairseq decoder, + # so we fix here. + if args.encoder_layers_to_keep: + args.encoder_layers = len(args.encoder_layers_to_keep.split(",")) + args.decoder_layers_to_keep = args.encoder_layers_to_keep + args.encoder_layers_to_keep = None + + self.sentence_encoder = ModelParallelTransformerSentenceEncoder( + padding_idx=dictionary.pad(), + vocab_size=len(dictionary), + num_encoder_layers=args.encoder_layers, + embedding_dim=args.encoder_embed_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=args.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.activation_dropout, + layerdrop=args.encoder_layerdrop, + max_seq_len=args.max_positions, + num_segments=0, + encoder_normalize_before=False, + apply_bert_init=False, + activation_fn=args.activation_fn, + ) + self.lm_head = ModelParallelRobertaLMHead( + embed_dim=args.encoder_embed_dim, + output_dim=len(dictionary), + activation_fn=args.activation_fn, + weight=self.sentence_encoder.embed_tokens.weight, + ) + + def forward( + self, + src_tokens, + features_only=False, + return_all_hiddens=False, + masked_tokens=None, + **unused + ): + """ + Args: + src_tokens (LongTensor): input tokens of shape `(batch, src_len)` + features_only (bool, optional): skip LM head and just return + features. If True, the output will be of shape + `(batch, src_len, embed_dim)`. + return_all_hiddens (bool, optional): also return all of the + intermediate hidden states (default: False). + + Returns: + tuple: + - the LM output of shape `(batch, src_len, vocab)` + - a dictionary of additional data, where 'inner_states' + is a list of hidden states. Note that the hidden + states have shape `(src_len, batch, vocab)`. + """ + x, extra = self.extract_features( + src_tokens, return_all_hiddens=return_all_hiddens + ) + if not features_only: + x = self.output_layer(x, masked_tokens=masked_tokens) + return x, extra + + def extract_features(self, src_tokens, return_all_hiddens=False, **unused): + inner_states, _ = self.sentence_encoder( + src_tokens, + last_state_only=not return_all_hiddens, + ) + features = inner_states[-1].transpose(0, 1) # T x B x C -> B x T x C + return features, {"inner_states": inner_states if return_all_hiddens else None} + + def output_layer(self, features, masked_tokens=None, **unused): + return self.lm_head(features, masked_tokens) + + def max_positions(self): + """Maximum output length supported by the encoder.""" + return self.args.max_positions + + +@register_model_architecture("model_parallel_roberta", "model_parallel_roberta") +def base_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 3072) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.pooler_dropout = getattr(args, "pooler_dropout", 0.0) + args.encoder_layers_to_keep = getattr(args, "encoder_layers_to_keep", None) + args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.0) + + +@register_model_architecture("model_parallel_roberta", "model_parallel_roberta_base") +def roberta_base_architecture(args): + base_architecture(args) + + +@register_model_architecture("model_parallel_roberta", "model_parallel_roberta_large") +def roberta_large_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 24) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer.py new file mode 100644 index 00000000..4f346452 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer.py @@ -0,0 +1,116 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import torch.nn as nn +import torch.nn.functional as F +from fairseq.model_parallel.modules import ( + ModelParallelTransformerDecoderLayer, + ModelParallelTransformerEncoderLayer, +) +from fairseq.models import register_model +from fairseq.models.transformer import ( + TransformerDecoder, + TransformerEncoder, + TransformerModel, +) + + +try: + from fairseq.model_parallel.megatron.mpu import ( + copy_to_model_parallel_region, + gather_from_model_parallel_region, + VocabParallelEmbedding, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +logger = logging.getLogger(__name__) + + +@register_model("model_parallel_transformer") +class ModelParallelTransformerModel(TransformerModel): + """ + Model parallel Transformer model. + """ + + @classmethod + def build_embedding(cls, args, dictionary, embed_dim, path=None): + if not has_megatron_submodule: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + dictionary.pad_to_multiple_(args.model_parallel_size * 8) + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + + def _vocab_init(tensor, **kwargs): + nn.init.normal_(tensor, mean=0, std=num_embeddings ** -0.5) + nn.init.constant_(tensor[1], 0) + + emb = VocabParallelEmbedding( + num_embeddings, embed_dim, padding_idx, init_method=_vocab_init + ) + # if provided, load from preloaded dictionaries + if path: + raise NotImplementedError( + "Loading of embedding from path is not supported for model parallel" + ) + return emb + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return ModelParallelTransformerEncoder(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return ModelParallelTransformerDecoder( + args, + tgt_dict, + embed_tokens, + no_encoder_attn=getattr(args, "no_cross_attention", False), + ) + + +class ModelParallelTransformerEncoder(TransformerEncoder): + """ + Model parallel Transformer encoder consisting of *args.encoder_layers* layers. Each layer + is a :class:`ModelParallelTransformerEncoderLayer`. + """ + + def build_encoder_layer(self, args): + return ModelParallelTransformerEncoderLayer(args) + + +class ModelParallelTransformerDecoder(TransformerDecoder): + """ + Model Parallel Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`ModelParallelTransformerDecoderLayer`. + """ + + def build_decoder_layer(self, args, no_encoder_attn=False): + return ModelParallelTransformerDecoderLayer(args, no_encoder_attn) + + def output_layer(self, features, **kwargs): + """Project features to the vocabulary size.""" + if not self.share_input_output_embed: + raise NotImplementedError( + "Model parallel training currently requires --share-decoder-input-output-embed" + ) + + features = copy_to_model_parallel_region(features) + + # project back to size of vocabulary + x = self.output_projection(features) + + if getattr(self.args, "criterion") != "vocab_parallel_cross_entropy": + x = gather_from_model_parallel_region(x).contiguous() + return x diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer_lm.py b/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer_lm.py new file mode 100644 index 00000000..5db6efb7 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/models/transformer_lm.py @@ -0,0 +1,170 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn as nn +from fairseq.model_parallel.models.transformer import ModelParallelTransformerDecoder +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer_lm import TransformerLanguageModel + + +try: + from fairseq.model_parallel.megatron.mpu import VocabParallelEmbedding + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@register_model("model_parallel_transformer_lm") +class ModelParallelTransformerLanguageModel(TransformerLanguageModel): + + @staticmethod + def add_args(parser): + TransformerLanguageModel.add_args(parser) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + if not has_megatron_submodule: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + + # make sure all arguments are present in older models + base_lm_architecture(args) + + task.source_dictionary.pad_to_multiple_(args.model_parallel_size * 8) + task.target_dictionary.pad_to_multiple_(args.model_parallel_size * 8) + + if args.decoder_layers_to_keep: + args.decoder_layers = len(args.decoder_layers_to_keep.split(",")) + + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = getattr( + args, "tokens_per_sample", DEFAULT_MAX_TARGET_POSITIONS + ) + + if args.character_embeddings: + raise NotImplementedError( + "Character embeddings is not supported for model parallel" + ) + elif args.adaptive_input: + raise NotImplementedError( + "Adaptive input is not supported for model parallel" + ) + else: + embed_tokens = cls.build_embedding( + args, task.source_dictionary, args.decoder_input_dim + ) + + decoder = ModelParallelTransformerDecoder( + args, + task.target_dictionary, + embed_tokens, + no_encoder_attn=True, + ) + return cls(decoder) + + @classmethod + def build_embedding(cls, args, dictionary, embed_dim, path=None): + def _vocab_init(tensor, **kwargs): + nn.init.normal_(tensor, mean=0, std=embed_dim ** -0.5) + nn.init.constant_(tensor[1], 0) + + embed_tokens = VocabParallelEmbedding( + len(dictionary), embed_dim, dictionary.pad(), init_method=_vocab_init + ) + return embed_tokens + + +def base_lm_architecture(args): + # backward compatibility for older model checkpoints + if hasattr(args, "no_tie_adaptive_proj"): + # previous models defined --no-tie-adaptive-proj, so use the existence of + # that option to determine if this is an "old" model checkpoint + args.no_decoder_final_norm = True # old models always set this to True + if args.no_tie_adaptive_proj is False: + args.tie_adaptive_proj = True + if hasattr(args, "decoder_final_norm"): + args.no_decoder_final_norm = not args.decoder_final_norm + + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.relu_dropout = getattr(args, "relu_dropout", 0.0) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 2048) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + # Model training is not stable without this + args.decoder_normalize_before = True + args.no_decoder_final_norm = getattr(args, "no_decoder_final_norm", False) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.adaptive_softmax_factor = getattr(args, "adaptive_softmax_factor", 4) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.character_embeddings = getattr(args, "character_embeddings", False) + args.character_filters = getattr( + args, + "character_filters", + "[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]", + ) + args.character_embedding_dim = getattr(args, "character_embedding_dim", 4) + args.char_embedder_highway_layers = getattr(args, "char_embedder_highway_layers", 2) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.adaptive_input_factor = getattr(args, "adaptive_input_factor", 4) + args.adaptive_input_cutoff = getattr(args, "adaptive_input_cutoff", None) + args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False) + args.tie_adaptive_proj = getattr(args, "tie_adaptive_proj", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0) + args.decoder_layers_to_keep = getattr(args, "decoder_layers_to_keep", None) + args.layernorm_embedding = getattr(args, "layernorm_embedding", False) + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + args.quant_noise_pq = getattr(args, "quant_noise_pq", 0.0) + args.quant_noise_pq_block_size = getattr(args, "quant_noise_pq_block_size", 8) + args.quant_noise_scalar = getattr(args, "quant_noise_scalar", 0.0) + args.add_bos_token = getattr(args, "add_bos_token", False) + + +@register_model_architecture("model_parallel_transformer_lm", "transformer_lm_megatron") +def transformer_lm_megatron(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 3072) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 3072 * 4) + args.decoder_layers = getattr(args, "decoder_layers", 72) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 32) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) + + +@register_model_architecture( + "model_parallel_transformer_lm", "transformer_lm_megatron_11b" +) +def transformer_lm_megatron_11b(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 3072) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 3072 * 6) + args.decoder_layers = getattr(args, "decoder_layers", 72) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 32) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/modules/__init__.py b/fairseq-tools/fairseq/fairseq/model_parallel/modules/__init__.py new file mode 100644 index 00000000..fb45b3c9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/modules/__init__.py @@ -0,0 +1,23 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +from .multihead_attention import ModelParallelMultiheadAttention +from .transformer_layer import ( + ModelParallelTransformerEncoderLayer, + ModelParallelTransformerDecoderLayer, +) +from .transformer_sentence_encoder_layer import ( + ModelParallelTransformerSentenceEncoderLayer, +) +from .transformer_sentence_encoder import ModelParallelTransformerSentenceEncoder + +__all__ = [ + "ModelParallelMultiheadAttention", + "ModelParallelTransformerEncoderLayer", + "ModelParallelTransformerDecoderLayer", + "ModelParallelTransformerSentenceEncoder", + "ModelParallelTransformerSentenceEncoderLayer", +] diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/modules/multihead_attention.py b/fairseq-tools/fairseq/fairseq/model_parallel/modules/multihead_attention.py new file mode 100644 index 00000000..4164bf91 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/modules/multihead_attention.py @@ -0,0 +1,352 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, Optional, Tuple + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout +from torch import Tensor, nn + + +try: + from fairseq.model_parallel.megatron.mpu import ( + get_cuda_rng_tracker, + get_model_parallel_world_size, + ColumnParallelLinear, + RowParallelLinear, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +@with_incremental_state +class ModelParallelMultiheadAttention(nn.Module): + """Model parallel Multi-headed attention. + This performs the Multi-headed attention over multiple gpus. + + See "Megatron-LM: https://arxiv.org/pdf/1909.08053.pdf" for more details. + """ + + def __init__( + self, + embed_dim, + num_heads, + kdim=None, + vdim=None, + dropout=0.0, + bias=True, + self_attention=False, + encoder_decoder_attention=False, + ): + super().__init__() + if not has_megatron_submodule: + raise ImportError( + "\n\nPlease install the megatron submodule:" + "\n\n git submodule update --init " + "fairseq/model_parallel/megatron" + ) + self.embed_dim = embed_dim + self.kdim = kdim if kdim is not None else embed_dim + self.vdim = vdim if vdim is not None else embed_dim + self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim + + self.model_parallel_size = get_model_parallel_world_size() + + self.num_heads_partition = num_heads // self.model_parallel_size + assert ( + self.num_heads_partition * self.model_parallel_size == num_heads + ), "Number of heads must be divisible by model parallel size" + + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + self.scaling = self.head_dim ** -0.5 + + self.self_attention = self_attention + self.encoder_decoder_attention = encoder_decoder_attention + + assert ( + not self.self_attention or self.qkv_same_dim + ), "Self-attention requires query, key and value to be of the same size" + + self.k_proj = ColumnParallelLinear( + self.kdim, embed_dim, bias=bias, gather_output=False + ) + self.v_proj = ColumnParallelLinear( + self.vdim, embed_dim, bias=bias, gather_output=False + ) + self.q_proj = ColumnParallelLinear( + embed_dim, embed_dim, bias=bias, gather_output=False + ) + self.out_proj = RowParallelLinear( + embed_dim, embed_dim, bias=bias, input_is_parallel=True + ) + + self.tpu = False + + def prepare_for_tpu_(self, **kwargs): + self.tpu = True + + def forward( + self, + query, + key: Optional[Tensor], + value: Optional[Tensor], + key_padding_mask: Optional[Tensor] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + static_kv: bool = False, + attn_mask: Optional[Tensor] = None, + **unused_kwargs, + ) -> Tuple[Tensor, Optional[Tensor]]: + """Input shape: Time x Batch x Channel + + Args: + key_padding_mask (ByteTensor, optional): mask to exclude + keys that are pads, of shape `(batch, src_len)`, where + padding elements are indicated by 1s. + attn_mask (ByteTensor, optional): typically used to + implement causal attention, where the mask prevents the + attention from looking forward in time (default: None). + """ + tgt_len, bsz, embed_dim = query.size() + assert embed_dim == self.embed_dim + assert list(query.size()) == [tgt_len, bsz, embed_dim] + + if incremental_state is not None: + saved_state = self._get_input_buffer(incremental_state) + if saved_state is not None and "prev_key" in saved_state: + # previous time steps are cached - no need to recompute + # key and value if they are static + if static_kv: + assert self.encoder_decoder_attention and not self.self_attention + key = value = None + else: + saved_state = None + + if self.self_attention: + q = self.q_proj(query) + k = self.k_proj(query) + v = self.v_proj(query) + elif self.encoder_decoder_attention: + # encoder-decoder attention + q = self.q_proj(query) + if key is None: + assert value is None + k = v = None + else: + k = self.k_proj(key) + v = self.v_proj(key) + + else: + assert key is not None and value is not None + q = self.q_proj(query) + k = self.k_proj(key) + v = self.v_proj(value) + q *= self.scaling + + q = ( + q.contiguous() + .view(tgt_len, bsz * self.num_heads_partition, self.head_dim) + .transpose(0, 1) + ) + if k is not None: + k = ( + k.contiguous() + .view(-1, bsz * self.num_heads_partition, self.head_dim) + .transpose(0, 1) + ) + if v is not None: + v = ( + v.contiguous() + .view(-1, bsz * self.num_heads_partition, self.head_dim) + .transpose(0, 1) + ) + + if saved_state is not None: + # saved states are stored with shape (bsz, num_heads_partition, seq_len, head_dim) + if "prev_key" in saved_state: + _prev_key = saved_state["prev_key"] + assert _prev_key is not None + prev_key = _prev_key.view( + bsz * self.num_heads_partition, -1, self.head_dim + ) + if static_kv: + k = prev_key + else: + assert k is not None + k = torch.cat([prev_key, k], dim=1) + if "prev_value" in saved_state: + _prev_value = saved_state["prev_value"] + assert _prev_value is not None + prev_value = _prev_value.view( + bsz * self.num_heads_partition, -1, self.head_dim + ) + if static_kv: + v = prev_value + else: + assert v is not None + v = torch.cat([prev_value, v], dim=1) + prev_key_padding_mask: Optional[Tensor] = None + if "prev_key_padding_mask" in saved_state: + prev_key_padding_mask = saved_state["prev_key_padding_mask"] + assert k is not None and v is not None + key_padding_mask = ( + ModelParallelMultiheadAttention._append_prev_key_padding_mask( + key_padding_mask=key_padding_mask, + prev_key_padding_mask=prev_key_padding_mask, + batch_size=bsz, + src_len=k.size(1), + static_kv=static_kv, + ) + ) + + saved_state["prev_key"] = k.view( + bsz, self.num_heads_partition, -1, self.head_dim + ) + saved_state["prev_value"] = v.view( + bsz, self.num_heads_partition, -1, self.head_dim + ) + saved_state["prev_key_padding_mask"] = key_padding_mask + # In this branch incremental_state is never None + assert incremental_state is not None + incremental_state = self._set_input_buffer(incremental_state, saved_state) + assert k is not None + src_len = k.size(1) + + # This is part of a workaround to get around fork/join parallelism + # not supporting Optional types. + if key_padding_mask is not None and key_padding_mask.dim() == 0: + key_padding_mask = None + + if key_padding_mask is not None: + assert key_padding_mask.size(0) == bsz + assert key_padding_mask.size(1) == src_len + + attn_weights = torch.bmm(q, k.transpose(1, 2)) + + assert list(attn_weights.size()) == [ + bsz * self.num_heads_partition, + tgt_len, + src_len, + ] + + if attn_mask is not None: + attn_mask = attn_mask.unsqueeze(0) + attn_weights += attn_mask + + if key_padding_mask is not None: + # don't attend to padding symbols + attn_weights = attn_weights.view( + bsz, self.num_heads_partition, tgt_len, src_len + ) + if not self.tpu: + attn_weights = attn_weights.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2).to(torch.bool), + float("-inf"), + ) + else: + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.masked_fill(key_padding_mask, float("-inf")) + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.view( + bsz * self.num_heads_partition, tgt_len, src_len + ) + + attn_weights_float = utils.softmax(attn_weights, dim=-1) + attn_weights = attn_weights_float.type_as(attn_weights) + + with get_cuda_rng_tracker().fork(): + attn_probs = self.dropout_module(attn_weights) + + assert v is not None + attn = torch.bmm(attn_probs, v) + assert list(attn.size()) == [ + bsz * self.num_heads_partition, + tgt_len, + self.head_dim, + ] + embed_dim_partition = embed_dim // self.model_parallel_size + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim_partition) + attn = self.out_proj(attn) + # return attn_weights None to keep the return type same as single gpu multihead attention + # This will be deprecated. + attn_weights: Optional[Tensor] = None + + return attn, attn_weights + + @staticmethod + def _append_prev_key_padding_mask( + key_padding_mask: Optional[Tensor], + prev_key_padding_mask: Optional[Tensor], + batch_size: int, + src_len: int, + static_kv: bool, + ) -> Optional[Tensor]: + # saved key padding masks have shape (bsz, seq_len) + if prev_key_padding_mask is not None and static_kv: + new_key_padding_mask = prev_key_padding_mask + elif prev_key_padding_mask is not None and key_padding_mask is not None: + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), key_padding_mask.float()], dim=1 + ) + # During incremental decoding, as the padding token enters and + # leaves the frame, there will be a time when prev or current + # is None + elif prev_key_padding_mask is not None: + + filler = torch.zeros(batch_size, src_len - prev_key_padding_mask.size(1)) + if prev_key_padding_mask.is_cuda: + filler = filler.cuda() + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), filler.float()], dim=1 + ) + elif key_padding_mask is not None: + filler = torch.zeros(batch_size, src_len - key_padding_mask.size(1)) + if key_padding_mask.is_cuda: + filler = filler.cuda() + new_key_padding_mask = torch.cat( + [filler.float(), key_padding_mask.float()], dim=1 + ) + else: + new_key_padding_mask = prev_key_padding_mask + return new_key_padding_mask + + def reorder_incremental_state( + self, incremental_state: Dict[str, Dict[str, Optional[Tensor]]], new_order + ): + """Reorder buffered internal state (for incremental generation).""" + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + for k in input_buffer.keys(): + if input_buffer[k] is not None: + input_buffer[k] = input_buffer[k].index_select(0, new_order) + incremental_state = self._set_input_buffer(incremental_state, input_buffer) + return incremental_state + + def _get_input_buffer( + self, incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] + ) -> Dict[str, Optional[Tensor]]: + result = self.get_incremental_state(incremental_state, "attn_state") + if result is not None: + return result + else: + empty_result: Dict[str, Optional[Tensor]] = {} + return empty_result + + def _set_input_buffer( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + buffer: Dict[str, Optional[Tensor]], + ): + return self.set_incremental_state(incremental_state, "attn_state", buffer) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_layer.py b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_layer.py new file mode 100644 index 00000000..7ab53c6e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_layer.py @@ -0,0 +1,78 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.model_parallel.modules import ModelParallelMultiheadAttention +from fairseq.modules import TransformerDecoderLayer, TransformerEncoderLayer + + +try: + from fairseq.model_parallel.megatron.mpu import ( + ColumnParallelLinear, + RowParallelLinear, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +class ModelParallelTransformerEncoderLayer(TransformerEncoderLayer): + """Encoder layer block over multiple gpus. + + See "Megatron-LM: https://arxiv.org/pdf/1909.08053.pdf" for more details. + """ + + def build_fc1(self, input_dim, output_dim, q_noise, qn_block_size): + if q_noise > 0: + raise NotImplementedError + return ColumnParallelLinear(input_dim, output_dim, gather_output=False) + + def build_fc2(self, input_dim, output_dim, q_noise, qn_block_size): + if q_noise > 0: + raise NotImplementedError + return RowParallelLinear(input_dim, output_dim, input_is_parallel=True) + + def build_self_attention(self, embed_dim, args, **unused_kwargs): + return ModelParallelMultiheadAttention( + embed_dim, + args.encoder_attention_heads, + dropout=args.attention_dropout, + self_attention=True, + ) + + +class ModelParallelTransformerDecoderLayer(TransformerDecoderLayer): + """Decoder layer block. + + See "Megatron-LM: https://arxiv.org/pdf/1909.08053.pdf" for more details. + """ + + def build_fc1(self, input_dim, output_dim, q_noise, qn_block_size): + if q_noise > 0: + raise NotImplementedError + return ColumnParallelLinear(input_dim, output_dim, gather_output=False) + + def build_fc2(self, input_dim, output_dim, q_noise, qn_block_size): + if q_noise > 0: + raise NotImplementedError + return RowParallelLinear(input_dim, output_dim, input_is_parallel=True) + + def build_self_attention(self, embed_dim, args, **unused_kwargs): + return ModelParallelMultiheadAttention( + embed_dim=embed_dim, + num_heads=args.decoder_attention_heads, + dropout=args.attention_dropout, + self_attention=not getattr(args, "cross_self_attention", False), + ) + + def build_encoder_attention(self, embed_dim, args, **unused_kwargs): + return ModelParallelMultiheadAttention( + embed_dim=embed_dim, + num_heads=args.decoder_attention_heads, + kdim=getattr(args, "encoder_embed_dim", None), + vdim=getattr(args, "encoder_embed_dim", None), + dropout=args.attention_dropout, + encoder_decoder_attention=True, + ) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder.py b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder.py new file mode 100644 index 00000000..a5d50a33 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder.py @@ -0,0 +1,59 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import random +from typing import Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq.model_parallel.modules import ModelParallelTransformerSentenceEncoderLayer +from fairseq.modules import ( + LayerNorm, + MultiheadAttention, + PositionalEmbedding, + TransformerSentenceEncoder, +) + + +try: + from fairseq.model_parallel.megatron.mpu import VocabParallelEmbedding + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +class ModelParallelTransformerSentenceEncoder(TransformerSentenceEncoder): + """ + Implementation for a Model Parallel Bi-directional Transformer based + Sentence Encoder used in BERT/XLM style pre-trained models. + """ + + def build_embedding(self, vocab_size, embedding_dim, padding_idx): + return VocabParallelEmbedding(vocab_size, embedding_dim, padding_idx) + + def build_transformer_sentence_encoder_layer( + self, + embedding_dim, + ffn_embedding_dim, + num_attention_heads, + dropout, + attention_dropout, + activation_dropout, + activation_fn, + export, + **unused, + ): + return ModelParallelTransformerSentenceEncoderLayer( + embedding_dim=embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + ) diff --git a/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder_layer.py b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder_layer.py new file mode 100644 index 00000000..e10bf523 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/model_parallel/modules/transformer_sentence_encoder_layer.py @@ -0,0 +1,77 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.model_parallel.modules import ModelParallelMultiheadAttention +from fairseq.modules import TransformerSentenceEncoderLayer + + +try: + from fairseq.model_parallel.megatron.mpu import ( + ColumnParallelLinear, + RowParallelLinear, + ) + + has_megatron_submodule = True +except (ImportError, ModuleNotFoundError): + has_megatron_submodule = False + + +class ModelParallelTransformerSentenceEncoderLayer(TransformerSentenceEncoderLayer): + """ + Implements a Model Parallel Transformer Encoder Layer used in + BERT/XLM style pre-trained models. + """ + + def build_fc1(self, input_dim, output_dim, **unused): + return ColumnParallelLinear(input_dim, output_dim, gather_output=False) + + def build_fc2(self, input_dim, output_dim, **unused): + return RowParallelLinear(input_dim, output_dim, input_is_parallel=True) + + def build_self_attention( + self, + embed_dim, + num_attention_heads, + dropout, + **kwargs, + ): + return ModelParallelMultiheadAttention( + embed_dim, num_attention_heads, dropout=dropout, self_attention=True + ) + + def forward( + self, + x: torch.Tensor, + self_attn_mask: torch.Tensor = None, + self_attn_padding_mask: torch.Tensor = None, + ): + """ + LayerNorm is applied either before or after the self-attention/ffn + modules similar to the original Transformer imlementation. + """ + residual = x + x = self.self_attn_layer_norm(x) + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + need_weights=False, + attn_mask=self_attn_mask, + ) + x = self.dropout_module(x) + x = residual + x + + residual = x + x = self.final_layer_norm(x) + x = self.activation_fn(self.fc1(x)) + x = self.activation_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = residual + x + return x, None diff --git a/fairseq-tools/fairseq/fairseq/models/__init__.py b/fairseq-tools/fairseq/fairseq/models/__init__.py new file mode 100644 index 00000000..7ff94427 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/__init__.py @@ -0,0 +1,188 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +import argparse +import importlib +import os +from argparse import Namespace +from typing import Union + +import fairseq +from fairseq.dataclass import FairseqDataclass +from omegaconf import DictConfig, OmegaConf + +from .composite_encoder import CompositeEncoder +from .distributed_fairseq_model import DistributedFairseqModel +from .fairseq_decoder import FairseqDecoder +from .fairseq_encoder import FairseqEncoder +from .fairseq_incremental_decoder import FairseqIncrementalDecoder +from .fairseq_model import ( + BaseFairseqModel, + FairseqEncoderDecoderModel, + FairseqEncoderModel, + FairseqLanguageModel, + FairseqModel, + FairseqMultiModel, +) + + +MODEL_REGISTRY = {} +MODEL_DATACLASS_REGISTRY = {} +ARCH_MODEL_REGISTRY = {} +ARCH_MODEL_NAME_REGISTRY = {} +ARCH_MODEL_INV_REGISTRY = {} +ARCH_CONFIG_REGISTRY = {} + + +__all__ = [ + "BaseFairseqModel", + "CompositeEncoder", + "DistributedFairseqModel", + "FairseqDecoder", + "FairseqEncoder", + "FairseqEncoderDecoderModel", + "FairseqEncoderModel", + "FairseqIncrementalDecoder", + "FairseqLanguageModel", + "FairseqModel", + "FairseqMultiModel", +] + + +def build_model(model_cfg: Union[DictConfig, Namespace], task): + if isinstance(model_cfg, DictConfig): + return ARCH_MODEL_REGISTRY[model_cfg._name].build_model(model_cfg, task) + return ARCH_MODEL_REGISTRY[model_cfg.arch].build_model(model_cfg, task) + + +def register_model(name, dataclass=None): + """ + New model types can be added to fairseq with the :func:`register_model` + function decorator. + + For example:: + + @register_model('lstm') + class LSTM(FairseqEncoderDecoderModel): + (...) + + .. note:: All models must implement the :class:`BaseFairseqModel` interface. + Typically you will extend :class:`FairseqEncoderDecoderModel` for + sequence-to-sequence tasks or :class:`FairseqLanguageModel` for + language modeling tasks. + + Args: + name (str): the name of the model + """ + + def register_model_cls(cls): + if name in MODEL_REGISTRY: + raise ValueError("Cannot register duplicate model ({})".format(name)) + if not issubclass(cls, BaseFairseqModel): + raise ValueError( + "Model ({}: {}) must extend BaseFairseqModel".format(name, cls.__name__) + ) + MODEL_REGISTRY[name] = cls + if dataclass is not None and not issubclass(dataclass, FairseqDataclass): + raise ValueError( + "Dataclass {} must extend FairseqDataclass".format(dataclass) + ) + + cls.__dataclass = dataclass + MODEL_DATACLASS_REGISTRY[name] = dataclass + return cls + + return register_model_cls + + +def register_model_architecture(model_name, arch_name): + """ + New model architectures can be added to fairseq with the + :func:`register_model_architecture` function decorator. After registration, + model architectures can be selected with the ``--arch`` command-line + argument. + + For example:: + + @register_model_architecture('lstm', 'lstm_luong_wmt_en_de') + def lstm_luong_wmt_en_de(args): + args.encoder_embed_dim = getattr(args, 'encoder_embed_dim', 1000) + (...) + + The decorated function should take a single argument *args*, which is a + :class:`argparse.Namespace` of arguments parsed from the command-line. The + decorated function should modify these arguments in-place to match the + desired architecture. + + Args: + model_name (str): the name of the Model (Model must already be + registered) + arch_name (str): the name of the model architecture (``--arch``) + """ + + def arch_override_from_yaml(args, arch): + root_dir = os.path.dirname(os.path.dirname(fairseq.__file__)) + yaml_path = os.path.join(root_dir, "config/model/{}.yaml".format(arch)) + if not os.path.exists(yaml_path): + raise RuntimeError(f"yaml file {yaml_path} does not exist!") + arch_cfg = OmegaConf.load(yaml_path) + for k, v in arch_cfg.items(): + setattr(args, k, getattr(args, k, v)) + + def register_model_arch_fn(fn): + if model_name not in MODEL_REGISTRY: + raise ValueError( + "Cannot register model architecture for unknown model type ({})".format( + model_name + ) + ) + if arch_name in ARCH_MODEL_REGISTRY: + raise ValueError( + "Cannot register duplicate model architecture ({})".format(arch_name) + ) + if not callable(fn): + raise ValueError( + "Model architecture must be callable ({})".format(arch_name) + ) + ARCH_MODEL_REGISTRY[arch_name] = MODEL_REGISTRY[model_name] + ARCH_MODEL_NAME_REGISTRY[arch_name] = model_name + ARCH_MODEL_INV_REGISTRY.setdefault(model_name, []).append(arch_name) + if type(fn) is type and issubclass(fn, BaseFairseqModel): + # for model classes migrated with hydra + # in this case, we are using this decorator directly on model class since + # we do not need arch overriding functions. + ARCH_CONFIG_REGISTRY[arch_name] = lambda args: arch_override_from_yaml( + args, arch=arch_name + ) + else: + ARCH_CONFIG_REGISTRY[arch_name] = fn + return fn + + return register_model_arch_fn + + +# automatically import any Python files in the models/ directory +models_dir = os.path.dirname(__file__) +for file in os.listdir(models_dir): + path = os.path.join(models_dir, file) + if ( + not file.startswith("_") + and not file.startswith(".") + and (file.endswith(".py") or os.path.isdir(path)) + ): + model_name = file[: file.find(".py")] if file.endswith(".py") else file + module = importlib.import_module("fairseq.models." + model_name) + + # extra `model_parser` for sphinx + if model_name in MODEL_REGISTRY: + parser = argparse.ArgumentParser(add_help=False) + group_archs = parser.add_argument_group("Named architectures") + group_archs.add_argument( + "--arch", choices=ARCH_MODEL_INV_REGISTRY[model_name] + ) + group_args = parser.add_argument_group("Additional command-line arguments") + MODEL_REGISTRY[model_name].add_args(group_args) + globals()[model_name + "_parser"] = parser diff --git a/fairseq-tools/fairseq/fairseq/models/bart/__init__.py b/fairseq-tools/fairseq/fairseq/models/bart/__init__.py new file mode 100644 index 00000000..a701923f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/bart/__init__.py @@ -0,0 +1,7 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .hub_interface import * # noqa +from .model import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/models/bart/hub_interface.py b/fairseq-tools/fairseq/fairseq/models/bart/hub_interface.py new file mode 100644 index 00000000..cdabe360 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/bart/hub_interface.py @@ -0,0 +1,201 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import copy +import logging +from typing import List + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.data import encoders + + +logger = logging.getLogger(__name__) + + +class BARTHubInterface(nn.Module): + """A simple PyTorch Hub interface to BART. + + Usage: https://github.com/pytorch/fairseq/tree/master/examples/bart + """ + + def __init__(self, args, task, model): + super().__init__() + self.args = args + self.task = task + self.model = model + + self.bpe = encoders.build_bpe(args) + + self.max_positions = min( + utils.resolve_max_positions( + self.task.max_positions(), + self.model.max_positions(), + ) + ) + + # this is useful for determining the device + self.register_buffer("_float_tensor", torch.tensor([0], dtype=torch.float)) + + @property + def device(self): + return self._float_tensor.device + + def encode( + self, sentence: str, *addl_sentences, no_separator=True + ) -> torch.LongTensor: + """ + BPE-encode a sentence (or multiple sentences). + + Every sequence begins with a beginning-of-sentence (`<s>`) symbol. + Every sentence ends with an end-of-sentence (`</s>`). + + Example (single sentence): `<s> a b c </s>` + Example (sentence pair): `<s> d e f </s> 1 2 3 </s>` + + The BPE encoding follows GPT-2. One subtle detail is that the GPT-2 BPE + requires leading spaces. For example:: + + >>> bart.encode('Hello world').tolist() + [0, 31414, 232, 2] + >>> bart.encode(' world').tolist() + [0, 232, 2] + >>> bart.encode('world').tolist() + [0, 8331, 2] + """ + tokens = self.bpe.encode(sentence) + if len(tokens.split(" ")) > self.max_positions - 2: + tokens = " ".join(tokens.split(" ")[: self.max_positions - 2]) + bpe_sentence = "<s> " + tokens + " </s>" + for s in addl_sentences: + bpe_sentence += " </s>" if not no_separator else "" + bpe_sentence += " " + self.bpe.encode(s) + " </s>" + tokens = self.task.source_dictionary.encode_line(bpe_sentence, append_eos=False) + return tokens.long() + + def decode(self, tokens: torch.LongTensor): + assert tokens.dim() == 1 + tokens = tokens.cpu().numpy() + if tokens[0] == self.task.source_dictionary.bos(): + tokens = tokens[1:] # remove <s> + eos_mask = tokens == self.task.source_dictionary.eos() + doc_mask = eos_mask[1:] & eos_mask[:-1] + sentences = np.split(tokens, doc_mask.nonzero()[0] + 1) + sentences = [ + self.bpe.decode(self.task.source_dictionary.string(s)) for s in sentences + ] + if len(sentences) == 1: + return sentences[0] + return sentences + + def _build_sample(self, src_tokens: List[torch.LongTensor]): + # assert torch.is_tensor(src_tokens) + dataset = self.task.build_dataset_for_inference( + src_tokens, + [x.numel() for x in src_tokens], + ) + sample = dataset.collater(dataset) + sample = utils.apply_to_sample(lambda tensor: tensor.to(self.device), sample) + return sample + + def sample( + self, sentences: List[str], beam: int = 1, verbose: bool = False, **kwargs + ) -> str: + input = [self.encode(sentence) for sentence in sentences] + hypos = self.generate(input, beam, verbose, **kwargs) + return [self.decode(x["tokens"]) for x in hypos] + + def generate( + self, + tokens: List[torch.LongTensor], + beam: int = 5, + verbose: bool = False, + **kwargs + ) -> torch.LongTensor: + sample = self._build_sample(tokens) + + # build generator using current args as well as any kwargs + gen_args = copy.copy(self.args) + gen_args.beam = beam + for k, v in kwargs.items(): + setattr(gen_args, k, v) + generator = self.task.build_generator([self.model], gen_args) + translations = self.task.inference_step( + generator, + [self.model], + sample, + prefix_tokens=sample["net_input"]["src_tokens"] + .new_zeros((len(tokens), 1)) + .fill_(self.task.source_dictionary.bos()), + ) + + if verbose: + src_str_with_unk = self.string(tokens) + logger.info("S\t{}".format(src_str_with_unk)) + + def getarg(name, default): + return getattr(gen_args, name, getattr(self.args, name, default)) + + # Process top predictions + hypos = [x[0] for x in translations] + hypos = [v for _, v in sorted(zip(sample["id"].tolist(), hypos))] + return hypos + + def extract_features( + self, tokens: torch.LongTensor, return_all_hiddens: bool = False + ) -> torch.Tensor: + if tokens.dim() == 1: + tokens = tokens.unsqueeze(0) + if tokens.size(-1) > min(self.model.max_positions()): + raise ValueError( + "tokens exceeds maximum length: {} > {}".format( + tokens.size(-1), self.model.max_positions() + ) + ) + tokens.to(device=self.device), + prev_output_tokens = tokens.clone() + + prev_output_tokens[:, 0] = tokens.gather( + 1, + (tokens.ne(self.task.source_dictionary.pad()).sum(dim=1) - 1).unsqueeze(-1), + ).squeeze() + + prev_output_tokens[:, 1:] = tokens[:, :-1] + features, extra = self.model( + src_tokens=tokens, + src_lengths=None, + prev_output_tokens=prev_output_tokens, + features_only=True, + return_all_hiddens=return_all_hiddens, + ) + if return_all_hiddens: + # convert from T x B x C -> B x T x C + inner_states = extra["inner_states"] + return [inner_state.transpose(0, 1) for inner_state in inner_states] + else: + return features # just the last layer's features + + def register_classification_head( + self, name: str, num_classes: int = None, embedding_size: int = None, **kwargs + ): + self.model.register_classification_head( + name, num_classes=num_classes, embedding_size=embedding_size, **kwargs + ) + + def predict(self, head: str, tokens: torch.LongTensor, return_logits: bool = False): + if tokens.dim() == 1: + tokens = tokens.unsqueeze(0) + features = self.extract_features(tokens.to(device=self.device)) + sentence_representation = features[ + tokens.eq(self.task.source_dictionary.eos()), : + ].view(features.size(0), -1, features.size(-1))[:, -1, :] + + logits = self.model.classification_heads[head](sentence_representation) + if return_logits: + return logits + return F.log_softmax(logits, dim=-1) diff --git a/fairseq-tools/fairseq/fairseq/models/bart/model.py b/fairseq-tools/fairseq/fairseq/models/bart/model.py new file mode 100644 index 00000000..0d50c791 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/bart/model.py @@ -0,0 +1,371 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. +""" +BART: Denoising Sequence-to-Sequence Pre-training for +Natural Language Generation, Translation, and Comprehension +""" + +import logging + +import torch +import torch.nn as nn +from fairseq import utils +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer import TransformerModel +from fairseq.modules.transformer_sentence_encoder import init_bert_params + +from .hub_interface import BARTHubInterface + + +logger = logging.getLogger(__name__) + + +@register_model("bart") +class BARTModel(TransformerModel): + @classmethod + def hub_models(cls): + return { + "bart.base": "http://dl.fbaipublicfiles.com/fairseq/models/bart.base.tar.gz", + "bart.large": "http://dl.fbaipublicfiles.com/fairseq/models/bart.large.tar.gz", + "bart.large.mnli": "http://dl.fbaipublicfiles.com/fairseq/models/bart.large.mnli.tar.gz", + "bart.large.cnn": "http://dl.fbaipublicfiles.com/fairseq/models/bart.large.cnn.tar.gz", + "bart.large.xsum": "http://dl.fbaipublicfiles.com/fairseq/models/bart.large.xsum.tar.gz", + } + + def __init__(self, args, encoder, decoder): + super().__init__(args, encoder, decoder) + + # We follow BERT's random weight initialization + self.apply(init_bert_params) + + self.classification_heads = nn.ModuleDict() + + @staticmethod + def add_args(parser): + super(BARTModel, BARTModel).add_args(parser) + parser.add_argument( + "--pooler-dropout", + type=float, + metavar="D", + help="dropout probability in the masked_lm pooler layers", + ) + parser.add_argument( + "--pooler-activation-fn", + choices=utils.get_available_activation_fns(), + help="activation function to use for pooler layer", + ) + parser.add_argument( + "--spectral-norm-classification-head", + action="store_true", + help="Apply spectral normalization on the classification head", + ) + + @property + def supported_targets(self): + return {"self"} + + def forward( + self, + src_tokens, + src_lengths, + prev_output_tokens, + features_only=False, + classification_head_name=None, + token_embeddings=None, + **kwargs, + ): + if classification_head_name is not None: + features_only = True + + encoder_out = self.encoder( + src_tokens, + src_lengths=src_lengths, + token_embeddings=token_embeddings, + **kwargs, + ) + x, extra = self.decoder( + prev_output_tokens, + encoder_out=encoder_out, + features_only=features_only, + **kwargs, + ) + + if classification_head_name is not None: + sentence_representation = x[ + src_tokens.eq(self.encoder.dictionary.eos()), : + ].view(x.size(0), -1, x.size(-1))[:, -1, :] + x = self.classification_heads[classification_head_name]( + sentence_representation + ) + return x, extra + + @classmethod + def from_pretrained( + cls, + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + bpe="gpt2", + **kwargs, + ): + from fairseq import hub_utils + + x = hub_utils.from_pretrained( + model_name_or_path, + checkpoint_file, + data_name_or_path, + archive_map=cls.hub_models(), + bpe=bpe, + load_checkpoint_heads=True, + **kwargs, + ) + return BARTHubInterface(x["args"], x["task"], x["models"][0]) + + def register_classification_head( + self, name, num_classes=None, inner_dim=None, **kwargs + ): + """Register a classification head.""" + logger.info("Registering classification head: {0}".format(name)) + if name in self.classification_heads: + prev_num_classes = self.classification_heads[name].out_proj.out_features + prev_inner_dim = self.classification_heads[name].dense.out_features + if num_classes != prev_num_classes or inner_dim != prev_inner_dim: + logger.warning( + 're-registering head "{}" with num_classes {} (prev: {}) ' + "and inner_dim {} (prev: {})".format( + name, num_classes, prev_num_classes, inner_dim, prev_inner_dim + ) + ) + self.classification_heads[name] = BARTClassificationHead( + input_dim=self.args.encoder_embed_dim, + inner_dim=inner_dim or self.args.encoder_embed_dim, + num_classes=num_classes, + activation_fn=self.args.pooler_activation_fn, + pooler_dropout=self.args.pooler_dropout, + do_spectral_norm=getattr( + self.args, "spectral_norm_classification_head", False + ), + ) + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + + prefix = name + "." if name != "" else "" + current_head_names = ( + [] + if not hasattr(self, "classification_heads") + else self.classification_heads.keys() + ) + + # Handle new classification heads present in the state dict. + keys_to_delete = [] + for k in state_dict.keys(): + if not k.startswith(prefix + "classification_heads."): + continue + + head_name = k[len(prefix + "classification_heads.") :].split(".")[0] + num_classes = state_dict[ + prefix + "classification_heads." + head_name + ".out_proj.weight" + ].size(0) + inner_dim = state_dict[ + prefix + "classification_heads." + head_name + ".dense.weight" + ].size(0) + + if getattr(self.args, "load_checkpoint_heads", False): + if head_name not in current_head_names: + self.register_classification_head(head_name, num_classes, inner_dim) + else: + if head_name not in current_head_names: + logger.warning( + "deleting classification head ({}) from checkpoint " + "not present in current model: {}".format(head_name, k) + ) + keys_to_delete.append(k) + elif ( + num_classes + != self.classification_heads[head_name].out_proj.out_features + or inner_dim + != self.classification_heads[head_name].dense.out_features + ): + logger.warning( + "deleting classification head ({}) from checkpoint " + "with different dimensions than current model: {}".format( + head_name, k + ) + ) + keys_to_delete.append(k) + for k in keys_to_delete: + del state_dict[k] + + def truncate_emb(key): + if key in state_dict: + state_dict[key] = state_dict[key][:-1, :] + + # When finetuning on translation task, remove last row of + # embedding matrix that corresponds to mask_idx token. + loaded_dict_size = state_dict["encoder.embed_tokens.weight"].size(0) + if ( + loaded_dict_size == len(self.encoder.dictionary) + 1 + and "<mask>" not in self.encoder.dictionary + ): + truncate_emb("encoder.embed_tokens.weight") + truncate_emb("decoder.embed_tokens.weight") + truncate_emb("encoder.output_projection.weight") + truncate_emb("decoder.output_projection.weight") + + # When continued pretraining on new set of languages for mbart, + # add extra lang embeddings at the end of embed_tokens. + # Note: newly added languages are assumed to have been added at the end. + if self.args.task == "multilingual_denoising" and loaded_dict_size < len( + self.encoder.dictionary + ): + logger.info( + "Adding extra language embeddings not found in pretrained model for " + "continued pretraining of MBART on new set of languages." + ) + loaded_mask_token_embedding = state_dict["encoder.embed_tokens.weight"][ + -1, : + ] + + num_langids_to_add = len(self.encoder.dictionary) - loaded_dict_size + embed_dim = state_dict["encoder.embed_tokens.weight"].size(1) + + new_lang_embed_to_add = torch.zeros(num_langids_to_add, embed_dim) + nn.init.normal_(new_lang_embed_to_add, mean=0, std=embed_dim ** -0.5) + new_lang_embed_to_add = new_lang_embed_to_add.to( + dtype=state_dict["encoder.embed_tokens.weight"].dtype, + ) + + state_dict["encoder.embed_tokens.weight"] = torch.cat( + [ + state_dict["encoder.embed_tokens.weight"][ + : loaded_dict_size - 1, : + ], + new_lang_embed_to_add, + loaded_mask_token_embedding.unsqueeze(0), + ] + ) + state_dict["decoder.embed_tokens.weight"] = torch.cat( + [ + state_dict["decoder.embed_tokens.weight"][ + : loaded_dict_size - 1, : + ], + new_lang_embed_to_add, + loaded_mask_token_embedding.unsqueeze(0), + ] + ) + + # Copy any newly-added classification heads into the state dict + # with their current weights. + if hasattr(self, "classification_heads"): + cur_state = self.classification_heads.state_dict() + for k, v in cur_state.items(): + if prefix + "classification_heads." + k not in state_dict: + logger.info("Overwriting", prefix + "classification_heads." + k) + state_dict[prefix + "classification_heads." + k] = v + + +class BARTClassificationHead(nn.Module): + """Head for sentence-level classification tasks.""" + + def __init__( + self, + input_dim, + inner_dim, + num_classes, + activation_fn, + pooler_dropout, + do_spectral_norm=False, + ): + super().__init__() + self.dense = nn.Linear(input_dim, inner_dim) + self.activation_fn = utils.get_activation_fn(activation_fn) + self.dropout = nn.Dropout(p=pooler_dropout) + self.out_proj = nn.Linear(inner_dim, num_classes) + + if do_spectral_norm: + self.out_proj = torch.nn.utils.spectral_norm(self.out_proj) + + def forward(self, features, **kwargs): + x = features + x = self.dropout(x) + x = self.dense(x) + x = self.activation_fn(x) + x = self.dropout(x) + x = self.out_proj(x) + return x + + +@register_model_architecture("bart", "bart_large") +def bart_large_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4 * 1024) + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", True) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 12) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", True) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.relu_dropout = getattr(args, "relu_dropout", 0.0) + args.dropout = getattr(args, "dropout", 0.1) + args.max_target_positions = getattr(args, "max_target_positions", 1024) + args.max_source_positions = getattr(args, "max_source_positions", 1024) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", True + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", True) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + args.no_scale_embedding = getattr(args, "no_scale_embedding", True) + args.layernorm_embedding = getattr(args, "layernorm_embedding", True) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + args.pooler_dropout = getattr(args, "pooler_dropout", 0.0) + + +@register_model_architecture("bart", "bart_base") +def bart_base_architecture(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4 * 768) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 12) + bart_large_architecture(args) + + +@register_model_architecture("bart", "mbart_large") +def mbart_large_architecture(args): + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + bart_large_architecture(args) + + +@register_model_architecture("bart", "mbart_base") +def mbart_base_architecture(args): + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + bart_base_architecture(args) + + +@register_model_architecture("bart", "mbart_base_wmt20") +def mbart_base_wmt20_architecture(args): + args.layernorm_embedding = getattr(args, "layernorm_embedding", False) + mbart_base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/composite_encoder.py b/fairseq-tools/fairseq/fairseq/models/composite_encoder.py new file mode 100644 index 00000000..4e20fe3a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/composite_encoder.py @@ -0,0 +1,57 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .fairseq_encoder import FairseqEncoder + + +class CompositeEncoder(FairseqEncoder): + """ + A wrapper around a dictionary of :class:`FairseqEncoder` objects. + + We run forward on each encoder and return a dictionary of outputs. The first + encoder's dictionary is used for initialization. + + Args: + encoders (dict): a dictionary of :class:`FairseqEncoder` objects. + """ + + def __init__(self, encoders): + super().__init__(next(iter(encoders.values())).dictionary) + self.encoders = encoders + for key in self.encoders: + self.add_module(key, self.encoders[key]) + + def forward(self, src_tokens, src_lengths): + """ + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (LongTensor): lengths of each source sentence of shape + `(batch)` + + Returns: + dict: + the outputs from each Encoder + """ + encoder_out = {} + for key in self.encoders: + encoder_out[key] = self.encoders[key](src_tokens, src_lengths) + return encoder_out + + def reorder_encoder_out(self, encoder_out, new_order): + """Reorder encoder output according to new_order.""" + for key in self.encoders: + encoder_out[key] = self.encoders[key].reorder_encoder_out( + encoder_out[key], new_order + ) + return encoder_out + + def max_positions(self): + return min(self.encoders[key].max_positions() for key in self.encoders) + + def upgrade_state_dict(self, state_dict): + for key in self.encoders: + self.encoders[key].upgrade_state_dict(state_dict) + return state_dict diff --git a/fairseq-tools/fairseq/fairseq/models/distributed_fairseq_model.py b/fairseq-tools/fairseq/fairseq/models/distributed_fairseq_model.py new file mode 100644 index 00000000..ece10c63 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/distributed_fairseq_model.py @@ -0,0 +1,103 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import inspect + +import torch.nn as nn +from fairseq.legacy_distributed_data_parallel import LegacyDistributedDataParallel + + +_GOSSIP_DISABLED = False +try: + import gossip +except ImportError: + _GOSSIP_DISABLED = True + + +def DistributedFairseqModel(args, model, process_group=None): + """ + Wrap a *model* to support distributed data parallel training. + + This is similar to the built-in DistributedDataParallel, but allows + additional configuration of the DistributedDataParallel class to + use, and also provides easier access to the wrapped model by + forwarding requests for missing attributes to the wrapped model. + + Args: + args (argparse.Namespace): fairseq args + model (BaseFairseqModel): model to wrap + """ + # determine which DDP class to extend + assert isinstance(model, nn.Module) + if args.distributed_wrapper == "DDP" and args.ddp_backend == "c10d": + ddp_class = nn.parallel.DistributedDataParallel + init_kwargs = dict( + module=model, + device_ids=[args.device_id], + output_device=args.device_id, + broadcast_buffers=args.broadcast_buffers, + bucket_cap_mb=args.bucket_cap_mb, + process_group=process_group, + ) + # Maintain backward compatibility + if "check_reduction" in inspect.getargspec(ddp_class)[0]: + init_kwargs["check_reduction"] = True + if "find_unused_parameters" in inspect.getargspec(ddp_class)[0]: + init_kwargs["find_unused_parameters"] = args.find_unused_parameters + elif args.distributed_wrapper == "DDP" and args.ddp_backend == "no_c10d": + ddp_class = LegacyDistributedDataParallel + init_kwargs = dict( + module=model, + world_size=args.distributed_world_size, + buffer_size=2 ** 28, + process_group=process_group, + ) + elif args.distributed_wrapper == "SlowMo": + if _GOSSIP_DISABLED: + raise ImportError( + "Cannot find gossip library. Please install from: " + "github.com/facebookresearch/stochastic_gradient_push" + ) + ddp_class = gossip.GossipDataParallel + + # The values of slowmo_momentum below were obtained by tuning on the + # En-De 16 dataset by training the transformer_wmt_en_de_large model + if args.slowmo_momentum is None: + if args.distributed_world_size <= 16: + args.slowmo_momentum = 0.0 + elif args.distributed_world_size <= 32: + args.slowmo_momentum = 0.2 + elif args.distributed_world_size <= 64: + args.slowmo_momentum = 0.5 + else: + args.slowmo_momentum = 0.6 + + init_kwargs = dict( + module=model, + device_ids=[args.device_id], + output_device=args.device_id, + broadcast_buffers=args.broadcast_buffers, + nprocs_per_node=args.nprocs_per_node, + slowmo_momentum=args.slowmo_momentum, + localsgd=(args.slowmo_algorithm == "LocalSGD"), + localsgd_frequency=args.localsgd_frequency, + ) + else: + raise ValueError("Unknown --ddp-backend: " + args.ddp_backend) + + class _DistributedFairseqModel(ddp_class): + """Extend DistributedDataParallel to check for missing + attributes in the wrapped module.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def __getattr__(self, name): + wrapped_module = super().__getattr__("module") + if hasattr(wrapped_module, name): + return getattr(wrapped_module, name) + return super().__getattr__(name) + + return _DistributedFairseqModel(**init_kwargs) diff --git a/fairseq-tools/fairseq/fairseq/models/fairseq_decoder.py b/fairseq-tools/fairseq/fairseq/models/fairseq_decoder.py new file mode 100644 index 00000000..fb6c52dc --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fairseq_decoder.py @@ -0,0 +1,90 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, List, Optional, Tuple + +import torch.nn as nn +from fairseq import utils +from torch import Tensor + + +class FairseqDecoder(nn.Module): + """Base class for decoders.""" + + def __init__(self, dictionary): + super().__init__() + self.dictionary = dictionary + self.onnx_trace = False + + def forward(self, prev_output_tokens, encoder_out=None, **kwargs): + """ + Args: + prev_output_tokens (LongTensor): shifted output tokens of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (dict, optional): output from the encoder, used for + encoder-side attention + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + x, extra = self.extract_features( + prev_output_tokens, encoder_out=encoder_out, **kwargs + ) + x = self.output_layer(x) + return x, extra + + def extract_features(self, prev_output_tokens, encoder_out=None, **kwargs): + """ + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + raise NotImplementedError + + def output_layer(self, features, **kwargs): + """ + Project features to the default output size, e.g., vocabulary size. + + Args: + features (Tensor): features returned by *extract_features*. + """ + raise NotImplementedError + + def get_normalized_probs( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Get normalized probabilities (or log probs) from a net's output.""" + + if hasattr(self, "adaptive_softmax") and self.adaptive_softmax is not None: + if sample is not None: + assert "target" in sample + target = sample["target"] + else: + target = None + out = self.adaptive_softmax.get_log_prob(net_output[0], target=target) + return out.exp_() if not log_probs else out + + logits = net_output[0] + if log_probs: + return utils.log_softmax(logits, dim=-1, onnx_trace=self.onnx_trace) + else: + return utils.softmax(logits, dim=-1, onnx_trace=self.onnx_trace) + + def max_positions(self): + """Maximum input length supported by the decoder.""" + return 1e6 # an arbitrary large number + + def upgrade_state_dict(self, state_dict): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + return state_dict + + def prepare_for_onnx_export_(self): + self.onnx_trace = True diff --git a/fairseq-tools/fairseq/fairseq/models/fairseq_encoder.py b/fairseq-tools/fairseq/fairseq/models/fairseq_encoder.py new file mode 100644 index 00000000..c8873daa --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fairseq_encoder.py @@ -0,0 +1,92 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, List, NamedTuple, Optional + +import torch +import torch.nn as nn +from torch import Tensor + + +EncoderOut = NamedTuple( + "EncoderOut", + [ + ("encoder_out", Tensor), # T x B x C + ("encoder_padding_mask", Optional[Tensor]), # B x T + ("encoder_embedding", Optional[Tensor]), # B x T x C + ("encoder_states", Optional[List[Tensor]]), # List[T x B x C] + ("src_tokens", Optional[Tensor]), # B x T + ("src_lengths", Optional[Tensor]), # B x 1 + ], +) + + +class FairseqEncoder(nn.Module): + """Base class for encoders.""" + + def __init__(self, dictionary): + super().__init__() + self.dictionary = dictionary + + def forward(self, src_tokens, src_lengths=None, **kwargs): + """ + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (LongTensor): lengths of each source sentence of shape + `(batch)` + """ + raise NotImplementedError + + def forward_torchscript(self, net_input: Dict[str, Tensor]): + """A TorchScript-compatible version of forward. + + Encoders which use additional arguments may want to override + this method for TorchScript compatibility. + """ + if torch.jit.is_scripting(): + return self.forward( + src_tokens=net_input["src_tokens"], + src_lengths=net_input["src_lengths"], + ) + else: + return self.forward_non_torchscript(net_input) + + @torch.jit.unused + def forward_non_torchscript(self, net_input: Dict[str, Tensor]): + encoder_input = { + k: v for k, v in net_input.items() if k != "prev_output_tokens" + } + return self.forward(**encoder_input) + + def reorder_encoder_out(self, encoder_out, new_order): + """ + Reorder encoder output according to `new_order`. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + `encoder_out` rearranged according to `new_order` + """ + raise NotImplementedError + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return 1e6 # an arbitrary large number + + def upgrade_state_dict(self, state_dict): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + return state_dict + + def set_num_updates(self, num_updates): + """State from trainer to pass along to model at every update.""" + + def _apply(m): + if hasattr(m, "set_num_updates") and m != self: + m.set_num_updates(num_updates) + + self.apply(_apply) diff --git a/fairseq-tools/fairseq/fairseq/models/fairseq_incremental_decoder.py b/fairseq-tools/fairseq/fairseq/models/fairseq_incremental_decoder.py new file mode 100644 index 00000000..cc72a0f8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fairseq_incremental_decoder.py @@ -0,0 +1,118 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from typing import Dict, Optional + +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.models import FairseqDecoder +from torch import Tensor + + +logger = logging.getLogger(__name__) + + +@with_incremental_state +class FairseqIncrementalDecoder(FairseqDecoder): + """Base class for incremental decoders. + + Incremental decoding is a special mode at inference time where the Model + only receives a single timestep of input corresponding to the previous + output token (for teacher forcing) and must produce the next output + *incrementally*. Thus the model must cache any long-term state that is + needed about the sequence, e.g., hidden states, convolutional states, etc. + + Compared to the standard :class:`FairseqDecoder` interface, the incremental + decoder interface allows :func:`forward` functions to take an extra keyword + argument (*incremental_state*) that can be used to cache state across + time-steps. + + The :class:`FairseqIncrementalDecoder` interface also defines the + :func:`reorder_incremental_state` method, which is used during beam search + to select and reorder the incremental state based on the selection of beams. + + To learn more about how incremental decoding works, refer to `this blog + <http://www.telesens.co/2019/04/21/understanding-incremental-decoding-in-fairseq/>`_. + """ + + def __init__(self, dictionary): + super().__init__(dictionary) + + def forward( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **kwargs + ): + """ + Args: + prev_output_tokens (LongTensor): shifted output tokens of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (dict, optional): output from the encoder, used for + encoder-side attention + incremental_state (dict, optional): dictionary used for storing + state during :ref:`Incremental decoding` + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + raise NotImplementedError + + def extract_features( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **kwargs + ): + """ + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + raise NotImplementedError + + def reorder_incremental_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + """Reorder incremental state. + + This will be called when the order of the input has changed from the + previous time step. A typical use case is beam search, where the input + order changes between time steps based on the selection of beams. + """ + pass + + def reorder_incremental_state_scripting( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + """Main entry point for reordering the incremental state. + + Due to limitations in TorchScript, we call this function in + :class:`fairseq.sequence_generator.SequenceGenerator` instead of + calling :func:`reorder_incremental_state` directly. + """ + for module in self.modules(): + if hasattr(module, "reorder_incremental_state"): + result = module.reorder_incremental_state(incremental_state, new_order) + if result is not None: + incremental_state = result + + def set_beam_size(self, beam_size): + """Sets the beam size in the decoder and all children.""" + if getattr(self, "_beam_size", -1) != beam_size: + seen = set() + + def apply_set_beam_size(module): + if ( + module != self + and hasattr(module, "set_beam_size") + and module not in seen + ): + seen.add(module) + module.set_beam_size(beam_size) + + self.apply(apply_set_beam_size) + self._beam_size = beam_size diff --git a/fairseq-tools/fairseq/fairseq/models/fairseq_model.py b/fairseq-tools/fairseq/fairseq/models/fairseq_model.py new file mode 100644 index 00000000..e6a0512a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fairseq_model.py @@ -0,0 +1,554 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Base classes for various fairseq models. +""" + +import logging +from typing import Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.checkpoint_utils import prune_state_dict +from fairseq.data import Dictionary +from fairseq.dataclass.utils import gen_parser_from_dataclass +from fairseq.models import FairseqDecoder, FairseqEncoder +from torch import Tensor + + +logger = logging.getLogger(__name__) + + +class BaseFairseqModel(nn.Module): + """Base class for fairseq models.""" + + def __init__(self): + super().__init__() + self._is_generation_fast = False + + @classmethod + def add_args(cls, parser): + """Add model-specific arguments to the parser.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + # do not set defaults so that settings defaults from various architectures still works + gen_parser_from_dataclass(parser, dc(), delete_default=True) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + raise NotImplementedError("Model must implement the build_model method") + + def get_targets(self, sample, net_output): + """Get targets from either the sample or the net's output.""" + return sample["target"] + + def get_normalized_probs( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Get normalized probabilities (or log probs) from a net's output.""" + return self.get_normalized_probs_scriptable(net_output, log_probs, sample) + + # TorchScript doesn't support super() method so that the scriptable Subclass + # can't access the base class model in Torchscript. + # Current workaround is to add a helper function with different name and + # call the helper function from scriptable Subclass. + def get_normalized_probs_scriptable( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Scriptable helper function for get_normalized_probs in ~BaseFairseqModel""" + if hasattr(self, "decoder"): + return self.decoder.get_normalized_probs(net_output, log_probs, sample) + elif torch.is_tensor(net_output): + # syntactic sugar for simple models which don't have a decoder + # (e.g., the classification tutorial) + logits = net_output.float() + if log_probs: + return F.log_softmax(logits, dim=-1) + else: + return F.softmax(logits, dim=-1) + raise NotImplementedError + + def extract_features(self, *args, **kwargs): + """Similar to *forward* but only return features.""" + return self(*args, **kwargs) + + def max_positions(self): + """Maximum length supported by the model.""" + return None + + def load_state_dict(self, state_dict, strict=True, args=None): + """Copies parameters and buffers from *state_dict* into this module and + its descendants. + + Overrides the method in :class:`nn.Module`. Compared with that method + this additionally "upgrades" *state_dicts* from old checkpoints. + """ + self.upgrade_state_dict(state_dict) + new_state_dict = prune_state_dict(state_dict, args) + return super().load_state_dict(new_state_dict, strict) + + def upgrade_state_dict(self, state_dict): + """Upgrade old state dicts to work with newer code.""" + self.upgrade_state_dict_named(state_dict, "") + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade old state dicts to work with newer code. + + Args: + state_dict (dict): state dictionary to upgrade, in place + name (str): the state dict key corresponding to the current module + """ + assert state_dict is not None + + def do_upgrade(m, prefix): + if len(prefix) > 0: + prefix += "." + + for n, c in m.named_children(): + name = prefix + n + if hasattr(c, "upgrade_state_dict_named"): + c.upgrade_state_dict_named(state_dict, name) + elif hasattr(c, "upgrade_state_dict"): + c.upgrade_state_dict(state_dict) + do_upgrade(c, name) + + do_upgrade(self, name) + + def set_num_updates(self, num_updates): + """State from trainer to pass along to model at every update.""" + + def _apply(m): + if hasattr(m, "set_num_updates") and m != self: + m.set_num_updates(num_updates) + + self.apply(_apply) + + def prepare_for_inference_(self, args): + """Prepare model for inference.""" + kwargs = {} + kwargs["beamable_mm_beam_size"] = ( + None if getattr(args, "no_beamable_mm", False) else getattr(args, "beam", 5) + ) + kwargs["need_attn"] = getattr(args, "print_alignment", False) + if hasattr(args, "retain_dropout"): + kwargs["retain_dropout"] = args.retain_dropout + kwargs["retain_dropout_modules"] = getattr( + args, "retain_dropout_modules", None + ) + self.make_generation_fast_(**kwargs) + + def make_generation_fast_(self, **kwargs): + """ + Legacy entry point to optimize model for faster generation. + Prefer prepare_for_inference_. + """ + if self._is_generation_fast: + return # only apply once + self._is_generation_fast = True + + # remove weight norm from all modules in the network + def apply_remove_weight_norm(module): + try: + nn.utils.remove_weight_norm(module) + except (AttributeError, ValueError): # this module didn't have weight norm + return + + self.apply(apply_remove_weight_norm) + + def apply_make_generation_fast_(module, prefix): + if len(prefix) > 0: + prefix += "." + + base_func = BaseFairseqModel.make_generation_fast_ + for n, m in module.named_modules(): + if ( + m != self + and hasattr(m, "make_generation_fast_") + # don't call this implementation again, e.g., if + # children modules also inherit from BaseFairseqModel + and m.make_generation_fast_.__func__ is not base_func + ): + name = prefix + n + m.make_generation_fast_(name=name, **kwargs) + + apply_make_generation_fast_(self, "") + + def train(mode=True): + if mode: + raise RuntimeError("cannot train after make_generation_fast") + + # this model should no longer be used for training + self.eval() + self.train = train + + def prepare_for_onnx_export_(self, **kwargs): + """Make model exportable via ONNX trace.""" + seen = set() + + def apply_prepare_for_onnx_export_(module): + if ( + module != self + and hasattr(module, "prepare_for_onnx_export_") + and module not in seen + ): + seen.add(module) + module.prepare_for_onnx_export_(**kwargs) + + self.apply(apply_prepare_for_onnx_export_) + + def prepare_for_tpu_(self, **kwargs): + """Optionally modify model for use on TPUs.""" + seen = set() + + def apply_prepare_for_tpu_(module): + if ( + module != self + and hasattr(module, "prepare_for_tpu_") + and module not in seen + ): + seen.add(module) + module.prepare_for_tpu_(**kwargs) + + self.apply(apply_prepare_for_tpu_) + + @classmethod + def upgrade_args(cls, args): + if hasattr(args, "max_sentences") and not hasattr(args, "batch_size"): + args.batch_size = args.max_sentences + + @classmethod + def from_pretrained( + cls, + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + **kwargs, + ): + """ + Load a :class:`~fairseq.models.FairseqModel` from a pre-trained model + file. Downloads and caches the pre-trained model file if needed. + + The base implementation returns a + :class:`~fairseq.hub_utils.GeneratorHubInterface`, which can be used to + generate translations or sample from language models. The underlying + :class:`~fairseq.models.FairseqModel` can be accessed via the + *generator.models* attribute. + + Other models may override this to implement custom hub interfaces. + + Args: + model_name_or_path (str): either the name of a pre-trained model to + load or a path/URL to a pre-trained model state dict + checkpoint_file (str, optional): colon-separated list of checkpoint + files in the model archive to ensemble (default: 'model.pt') + data_name_or_path (str, optional): point args.data to the archive + at the given path/URL. Can start with '.' or './' to reuse the + model archive path. + """ + from fairseq import hub_utils + + x = hub_utils.from_pretrained( + model_name_or_path, + checkpoint_file, + data_name_or_path, + archive_map=cls.hub_models(), + **kwargs, + ) + + cls.upgrade_args(x["args"]) + + logger.info(x["args"]) + return hub_utils.GeneratorHubInterface(x["args"], x["task"], x["models"]) + + @classmethod + def hub_models(cls): + return {} + + +class FairseqEncoderDecoderModel(BaseFairseqModel): + """Base class for encoder-decoder models. + + Args: + encoder (FairseqEncoder): the encoder + decoder (FairseqDecoder): the decoder + """ + + def __init__(self, encoder, decoder): + super().__init__() + + self.encoder = encoder + self.decoder = decoder + assert isinstance(self.encoder, FairseqEncoder) + assert isinstance(self.decoder, FairseqDecoder) + + def forward(self, src_tokens, src_lengths, prev_output_tokens, **kwargs): + """ + Run the forward pass for an encoder-decoder model. + + First feed a batch of source tokens through the encoder. Then, feed the + encoder output and previous decoder outputs (i.e., teacher forcing) to + the decoder to produce the next outputs:: + + encoder_out = self.encoder(src_tokens, src_lengths) + return self.decoder(prev_output_tokens, encoder_out) + + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (LongTensor): source sentence lengths of shape `(batch)` + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + decoder_out = self.decoder( + prev_output_tokens, encoder_out=encoder_out, **kwargs + ) + return decoder_out + + def forward_decoder(self, prev_output_tokens, **kwargs): + return self.decoder(prev_output_tokens, **kwargs) + + def extract_features(self, src_tokens, src_lengths, prev_output_tokens, **kwargs): + """ + Similar to *forward* but only return features. + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + features = self.decoder.extract_features( + prev_output_tokens, encoder_out=encoder_out, **kwargs + ) + return features + + def output_layer(self, features, **kwargs): + """Project features to the default output size (typically vocabulary size).""" + return self.decoder.output_layer(features, **kwargs) + + def max_positions(self): + """Maximum length supported by the model.""" + return (self.encoder.max_positions(), self.decoder.max_positions()) + + def max_decoder_positions(self): + """Maximum length supported by the decoder.""" + return self.decoder.max_positions() + + +class FairseqModel(FairseqEncoderDecoderModel): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + utils.deprecation_warning( + "FairseqModel is deprecated, please use FairseqEncoderDecoderModel " + "or BaseFairseqModel instead", + stacklevel=4, + ) + + +class FairseqMultiModel(BaseFairseqModel): + """Base class for combining multiple encoder-decoder models.""" + + def __init__(self, encoders, decoders): + super().__init__() + assert encoders.keys() == decoders.keys() + self.keys = list(encoders.keys()) + for key in self.keys: + assert isinstance(encoders[key], FairseqEncoder) + assert isinstance(decoders[key], FairseqDecoder) + + self.models = nn.ModuleDict( + { + key: FairseqEncoderDecoderModel(encoders[key], decoders[key]) + for key in self.keys + } + ) + + @staticmethod + def build_shared_embeddings( + dicts: Dict[str, Dictionary], + langs: List[str], + embed_dim: int, + build_embedding: callable, + pretrained_embed_path: Optional[str] = None, + ): + """ + Helper function to build shared embeddings for a set of languages after + checking that all dicts corresponding to those languages are equivalent. + + Args: + dicts: Dict of lang_id to its corresponding Dictionary + langs: languages that we want to share embeddings for + embed_dim: embedding dimension + build_embedding: callable function to actually build the embedding + pretrained_embed_path: Optional path to load pretrained embeddings + """ + shared_dict = dicts[langs[0]] + if any(dicts[lang] != shared_dict for lang in langs): + raise ValueError( + "--share-*-embeddings requires a joined dictionary: " + "--share-encoder-embeddings requires a joined source " + "dictionary, --share-decoder-embeddings requires a joined " + "target dictionary, and --share-all-embeddings requires a " + "joint source + target dictionary." + ) + return build_embedding(shared_dict, embed_dim, pretrained_embed_path) + + def forward(self, src_tokens, src_lengths, prev_output_tokens, **kwargs): + raise NotImplementedError + + def max_positions(self): + """Maximum length supported by the model.""" + return { + key: ( + self.models[key].encoder.max_positions(), + self.models[key].decoder.max_positions(), + ) + for key in self.keys + } + + def max_decoder_positions(self): + """Maximum length supported by the decoder.""" + return min(model.decoder.max_positions() for model in self.models.values()) + + @property + def encoder(self): + return self.models[self.keys[0]].encoder + + @property + def decoder(self): + return self.models[self.keys[0]].decoder + + def forward_decoder(self, prev_output_tokens, **kwargs): + return self.decoder(prev_output_tokens, **kwargs) + + def load_state_dict(self, state_dict, strict=True, args=None): + """Copies parameters and buffers from *state_dict* into this module and + its descendants. + + Overrides the method in :class:`nn.Module`. Compared with that method + this additionally "upgrades" *state_dicts* from old checkpoints. + """ + self.upgrade_state_dict(state_dict) + new_state_dict = prune_state_dict(state_dict, args) + return super().load_state_dict(new_state_dict, strict) + + +class FairseqLanguageModel(BaseFairseqModel): + """Base class for decoder-only models. + + Args: + decoder (FairseqDecoder): the decoder + """ + + def __init__(self, decoder): + super().__init__() + self.decoder = decoder + assert isinstance(self.decoder, FairseqDecoder) + + def forward(self, src_tokens, **kwargs): + """ + Run the forward pass for a decoder-only model. + + Feeds a batch of tokens through the decoder to predict the next tokens. + + Args: + src_tokens (LongTensor): tokens on which to condition the decoder, + of shape `(batch, tgt_len)` + src_lengths (LongTensor): source sentence lengths of shape `(batch)` + + Returns: + tuple: + - the decoder's output of shape `(batch, seq_len, vocab)` + - a dictionary with any model-specific outputs + """ + return self.decoder(src_tokens, **kwargs) + + def forward_decoder(self, prev_output_tokens, **kwargs): + return self.decoder(prev_output_tokens, **kwargs) + + def extract_features(self, src_tokens, **kwargs): + """ + Similar to *forward* but only return features. + + Returns: + tuple: + - the decoder's features of shape `(batch, seq_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + return self.decoder.extract_features(src_tokens, **kwargs) + + def output_layer(self, features, **kwargs): + """Project features to the default output size (typically vocabulary size).""" + return self.decoder.output_layer(features, **kwargs) + + def max_positions(self): + """Maximum length supported by the model.""" + return self.decoder.max_positions() + + def max_decoder_positions(self): + """Maximum length supported by the decoder.""" + return self.decoder.max_positions() + + @property + def supported_targets(self): + return {"future"} + + +class FairseqEncoderModel(BaseFairseqModel): + """Base class for encoder-only models. + + Args: + encoder (FairseqEncoder): the encoder + """ + + def __init__(self, encoder): + super().__init__() + self.encoder = encoder + assert isinstance(self.encoder, FairseqEncoder) + + def forward(self, src_tokens, src_lengths, **kwargs): + """ + Run the forward pass for a encoder-only model. + + Feeds a batch of tokens through the encoder to generate features. + + Args: + src_tokens (LongTensor): input tokens of shape `(batch, src_len)` + src_lengths (LongTensor): source sentence lengths of shape `(batch)` + + Returns: + the encoder's output, typically of shape `(batch, src_len, features)` + """ + return self.encoder(src_tokens, src_lengths, **kwargs) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + """Get normalized probabilities (or log probs) from a net's output.""" + encoder_out = net_output["encoder_out"] + if torch.is_tensor(encoder_out): + logits = encoder_out.float() + if log_probs: + return F.log_softmax(logits, dim=-1) + else: + return F.softmax(logits, dim=-1) + raise NotImplementedError + + def max_positions(self): + """Maximum length supported by the model.""" + return self.encoder.max_positions() diff --git a/fairseq-tools/fairseq/fairseq/models/fconv.py b/fairseq-tools/fairseq/fairseq/models/fconv.py new file mode 100644 index 00000000..c99a2151 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fconv.py @@ -0,0 +1,756 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.modules import ( + AdaptiveSoftmax, + BeamableMM, + FairseqDropout, + GradMultiply, + LearnedPositionalEmbedding, + LinearizedConvolution, +) + + +@register_model("fconv") +class FConvModel(FairseqEncoderDecoderModel): + """ + A fully convolutional model, i.e. a convolutional encoder and a + convolutional decoder, as described in `"Convolutional Sequence to Sequence + Learning" (Gehring et al., 2017) <https://arxiv.org/abs/1705.03122>`_. + + Args: + encoder (FConvEncoder): the encoder + decoder (FConvDecoder): the decoder + + The Convolutional model provides the following named architectures and + command-line arguments: + + .. argparse:: + :ref: fairseq.models.fconv_parser + :prog: + """ + + @classmethod + def hub_models(cls): + def moses_subword(path): + return { + "path": path, + "tokenizer": "moses", + "bpe": "subword_nmt", + } + + return { + "conv.wmt14.en-fr": moses_subword( + "https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2" + ), + "conv.wmt14.en-de": moses_subword( + "https://dl.fbaipublicfiles.com/fairseq/models/wmt14.en-de.fconv-py.tar.bz2" + ), + "conv.wmt17.en-de": moses_subword( + "https://dl.fbaipublicfiles.com/fairseq/models/wmt17.v2.en-de.fconv-py.tar.bz2" + ), + } + + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + self.encoder.num_attention_layers = sum( + layer is not None for layer in decoder.attention + ) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--encoder-embed-dim', type=int, metavar='N', + help='encoder embedding dimension') + parser.add_argument('--encoder-embed-path', type=str, metavar='STR', + help='path to pre-trained encoder embedding') + parser.add_argument('--encoder-layers', type=str, metavar='EXPR', + help='encoder layers [(dim, kernel_size), ...]') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-embed-path', type=str, metavar='STR', + help='path to pre-trained decoder embedding') + parser.add_argument('--decoder-layers', type=str, metavar='EXPR', + help='decoder layers [(dim, kernel_size), ...]') + parser.add_argument('--decoder-out-embed-dim', type=int, metavar='N', + help='decoder output embedding dimension') + parser.add_argument('--decoder-attention', type=str, metavar='EXPR', + help='decoder attention [True, ...]') + parser.add_argument('--share-input-output-embed', action='store_true', + help='share input and output embeddings (requires' + ' --decoder-out-embed-dim and --decoder-embed-dim' + ' to be equal)') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + # make sure that all args are properly defaulted (in case there are any new ones) + base_architecture(args) + + encoder_embed_dict = None + if args.encoder_embed_path: + encoder_embed_dict = utils.parse_embedding(args.encoder_embed_path) + utils.print_embed_overlap(encoder_embed_dict, task.source_dictionary) + + decoder_embed_dict = None + if args.decoder_embed_path: + decoder_embed_dict = utils.parse_embedding(args.decoder_embed_path) + utils.print_embed_overlap(decoder_embed_dict, task.target_dictionary) + + encoder = FConvEncoder( + dictionary=task.source_dictionary, + embed_dim=args.encoder_embed_dim, + embed_dict=encoder_embed_dict, + convolutions=eval(args.encoder_layers), + dropout=args.dropout, + max_positions=args.max_source_positions, + ) + decoder = FConvDecoder( + dictionary=task.target_dictionary, + embed_dim=args.decoder_embed_dim, + embed_dict=decoder_embed_dict, + convolutions=eval(args.decoder_layers), + out_embed_dim=args.decoder_out_embed_dim, + attention=eval(args.decoder_attention), + dropout=args.dropout, + max_positions=args.max_target_positions, + share_embed=args.share_input_output_embed, + ) + return FConvModel(encoder, decoder) + + +class FConvEncoder(FairseqEncoder): + """ + Convolutional encoder consisting of `len(convolutions)` layers. + + Args: + dictionary (~fairseq.data.Dictionary): encoding dictionary + embed_dim (int, optional): embedding dimension + embed_dict (str, optional): filename from which to load pre-trained + embeddings + max_positions (int, optional): maximum supported input sequence length + convolutions (list, optional): the convolutional layer structure. Each + list item `i` corresponds to convolutional layer `i`. Layers are + given as ``(out_channels, kernel_width, [residual])``. Residual + connections are added between layers when ``residual=1`` (which is + the default behavior). + dropout (float, optional): dropout to be applied before each conv layer + """ + + def __init__( + self, + dictionary, + embed_dim=512, + embed_dict=None, + max_positions=1024, + convolutions=((512, 3),) * 20, + dropout=0.1, + ): + super().__init__(dictionary) + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.num_attention_layers = None + + num_embeddings = len(dictionary) + self.padding_idx = dictionary.pad() + self.embed_tokens = Embedding(num_embeddings, embed_dim, self.padding_idx) + if embed_dict: + self.embed_tokens = utils.load_embedding( + embed_dict, self.dictionary, self.embed_tokens + ) + + self.embed_positions = PositionalEmbedding( + max_positions, + embed_dim, + self.padding_idx, + ) + + convolutions = extend_conv_spec(convolutions) + in_channels = convolutions[0][0] + self.fc1 = Linear(embed_dim, in_channels, dropout=dropout) + self.projections = nn.ModuleList() + self.convolutions = nn.ModuleList() + self.residuals = [] + + layer_in_channels = [in_channels] + for _, (out_channels, kernel_size, residual) in enumerate(convolutions): + if residual == 0: + residual_dim = out_channels + else: + residual_dim = layer_in_channels[-residual] + self.projections.append( + Linear(residual_dim, out_channels) + if residual_dim != out_channels + else None + ) + if kernel_size % 2 == 1: + padding = kernel_size // 2 + else: + padding = 0 + self.convolutions.append( + ConvTBC( + in_channels, + out_channels * 2, + kernel_size, + dropout=dropout, + padding=padding, + ) + ) + self.residuals.append(residual) + in_channels = out_channels + layer_in_channels.append(out_channels) + self.fc2 = Linear(in_channels, embed_dim) + + def forward(self, src_tokens, src_lengths): + """ + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (LongTensor): lengths of each source sentence of shape + `(batch)` + + Returns: + dict: + - **encoder_out** (tuple): a tuple with two elements, where the + first element is the last encoder layer's output and the + second element is the same quantity summed with the input + embedding (used for attention). The shape of both tensors is + `(batch, src_len, embed_dim)`. + - **encoder_padding_mask** (ByteTensor): the positions of + padding elements of shape `(batch, src_len)` + """ + # embed tokens and positions + x = self.embed_tokens(src_tokens) + self.embed_positions(src_tokens) + x = self.dropout_module(x) + input_embedding = x + + # project to size of convolution + x = self.fc1(x) + + # used to mask padding in input + encoder_padding_mask = src_tokens.eq(self.padding_idx).t() # -> T x B + if not encoder_padding_mask.any(): + encoder_padding_mask = None + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + residuals = [x] + # temporal convolutions + for proj, conv, res_layer in zip( + self.projections, self.convolutions, self.residuals + ): + if res_layer > 0: + residual = residuals[-res_layer] + residual = residual if proj is None else proj(residual) + else: + residual = None + + if encoder_padding_mask is not None: + x = x.masked_fill(encoder_padding_mask.unsqueeze(-1), 0) + + x = self.dropout_module(x) + if conv.kernel_size[0] % 2 == 1: + # padding is implicit in the conv + x = conv(x) + else: + padding_l = (conv.kernel_size[0] - 1) // 2 + padding_r = conv.kernel_size[0] // 2 + x = F.pad(x, (0, 0, 0, 0, padding_l, padding_r)) + x = conv(x) + x = F.glu(x, dim=2) + + if residual is not None: + x = (x + residual) * math.sqrt(0.5) + residuals.append(x) + + # T x B x C -> B x T x C + x = x.transpose(1, 0) + + # project back to size of embedding + x = self.fc2(x) + + if encoder_padding_mask is not None: + encoder_padding_mask = encoder_padding_mask.t() # -> B x T + x = x.masked_fill(encoder_padding_mask.unsqueeze(-1), 0) + + # scale gradients (this only affects backward, not forward) + x = GradMultiply.apply(x, 1.0 / (2.0 * self.num_attention_layers)) + + # add output to input embedding for attention + y = (x + input_embedding) * math.sqrt(0.5) + + return { + "encoder_out": (x, y), + "encoder_padding_mask": encoder_padding_mask, # B x T + } + + def reorder_encoder_out(self, encoder_out, new_order): + if encoder_out["encoder_out"] is not None: + encoder_out["encoder_out"] = ( + encoder_out["encoder_out"][0].index_select(0, new_order), + encoder_out["encoder_out"][1].index_select(0, new_order), + ) + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(0, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return self.embed_positions.max_positions + + +class AttentionLayer(nn.Module): + def __init__(self, conv_channels, embed_dim, bmm=None): + super().__init__() + # projects from output of convolution to embedding dimension + self.in_projection = Linear(conv_channels, embed_dim) + # projects from embedding dimension to convolution size + self.out_projection = Linear(embed_dim, conv_channels) + + self.bmm = bmm if bmm is not None else torch.bmm + + def forward(self, x, target_embedding, encoder_out, encoder_padding_mask): + residual = x + + # attention + x = (self.in_projection(x) + target_embedding) * math.sqrt(0.5) + x = self.bmm(x, encoder_out[0]) + + # don't attend over padding + if encoder_padding_mask is not None: + x = ( + x.float() + .masked_fill(encoder_padding_mask.unsqueeze(1), float("-inf")) + .type_as(x) + ) # FP16 support: cast to float and back + + # softmax over last dim + sz = x.size() + x = F.softmax(x.view(sz[0] * sz[1], sz[2]), dim=1) + x = x.view(sz) + attn_scores = x + + x = self.bmm(x, encoder_out[1]) + + # scale attention output (respecting potentially different lengths) + s = encoder_out[1].size(1) + if encoder_padding_mask is None: + x = x * (s * math.sqrt(1.0 / s)) + else: + s = s - encoder_padding_mask.type_as(x).sum( + dim=1, keepdim=True + ) # exclude padding + s = s.unsqueeze(-1) + x = x * (s * s.rsqrt()) + + # project back + x = (self.out_projection(x) + residual) * math.sqrt(0.5) + return x, attn_scores + + def make_generation_fast_(self, beamable_mm_beam_size=None, **kwargs): + """Replace torch.bmm with BeamableMM.""" + if beamable_mm_beam_size is not None: + del self.bmm + self.add_module("bmm", BeamableMM(beamable_mm_beam_size)) + + +class FConvDecoder(FairseqIncrementalDecoder): + """Convolutional decoder""" + + def __init__( + self, + dictionary, + embed_dim=512, + embed_dict=None, + out_embed_dim=256, + max_positions=1024, + convolutions=((512, 3),) * 20, + attention=True, + dropout=0.1, + share_embed=False, + positional_embeddings=True, + adaptive_softmax_cutoff=None, + adaptive_softmax_dropout=0.0, + ): + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([2])) + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.need_attn = True + + convolutions = extend_conv_spec(convolutions) + in_channels = convolutions[0][0] + if isinstance(attention, bool): + # expand True into [True, True, ...] and do the same with False + attention = [attention] * len(convolutions) + if not isinstance(attention, list) or len(attention) != len(convolutions): + raise ValueError( + "Attention is expected to be a list of booleans of " + "length equal to the number of layers." + ) + + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + self.embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx) + if embed_dict: + self.embed_tokens = utils.load_embedding( + embed_dict, self.dictionary, self.embed_tokens + ) + + self.embed_positions = ( + PositionalEmbedding( + max_positions, + embed_dim, + padding_idx, + ) + if positional_embeddings + else None + ) + + self.fc1 = Linear(embed_dim, in_channels, dropout=dropout) + self.projections = nn.ModuleList() + self.convolutions = nn.ModuleList() + self.attention = nn.ModuleList() + self.residuals = [] + + layer_in_channels = [in_channels] + for i, (out_channels, kernel_size, residual) in enumerate(convolutions): + if residual == 0: + residual_dim = out_channels + else: + residual_dim = layer_in_channels[-residual] + self.projections.append( + Linear(residual_dim, out_channels) + if residual_dim != out_channels + else None + ) + self.convolutions.append( + LinearizedConv1d( + in_channels, + out_channels * 2, + kernel_size, + padding=(kernel_size - 1), + dropout=dropout, + ) + ) + self.attention.append( + AttentionLayer(out_channels, embed_dim) if attention[i] else None + ) + self.residuals.append(residual) + in_channels = out_channels + layer_in_channels.append(out_channels) + + self.adaptive_softmax = None + self.fc2 = self.fc3 = None + + if adaptive_softmax_cutoff is not None: + assert not share_embed + self.adaptive_softmax = AdaptiveSoftmax( + num_embeddings, + in_channels, + adaptive_softmax_cutoff, + dropout=adaptive_softmax_dropout, + ) + else: + self.fc2 = Linear(in_channels, out_embed_dim) + if share_embed: + assert out_embed_dim == embed_dim, ( + "Shared embed weights implies same dimensions " + " out_embed_dim={} vs embed_dim={}".format(out_embed_dim, embed_dim) + ) + self.fc3 = nn.Linear(out_embed_dim, num_embeddings) + self.fc3.weight = self.embed_tokens.weight + else: + self.fc3 = Linear(out_embed_dim, num_embeddings, dropout=dropout) + + def forward( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **unused + ): + if encoder_out is not None: + encoder_padding_mask = encoder_out["encoder_padding_mask"] + encoder_out = encoder_out["encoder_out"] + + # split and transpose encoder outputs + encoder_a, encoder_b = self._split_encoder_out( + encoder_out, incremental_state + ) + + if self.embed_positions is not None: + pos_embed = self.embed_positions(prev_output_tokens, incremental_state) + else: + pos_embed = 0 + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + x = self._embed_tokens(prev_output_tokens, incremental_state) + + # embed tokens and combine with positional embeddings + x += pos_embed + x = self.dropout_module(x) + target_embedding = x + + # project to size of convolution + x = self.fc1(x) + + # B x T x C -> T x B x C + x = self._transpose_if_training(x, incremental_state) + + # temporal convolutions + avg_attn_scores = None + num_attn_layers = len(self.attention) + residuals = [x] + for proj, conv, attention, res_layer in zip( + self.projections, self.convolutions, self.attention, self.residuals + ): + if res_layer > 0: + residual = residuals[-res_layer] + residual = residual if proj is None else proj(residual) + else: + residual = None + + x = self.dropout_module(x) + x = conv(x, incremental_state) + x = F.glu(x, dim=2) + + # attention + if attention is not None: + x = self._transpose_if_training(x, incremental_state) + + x, attn_scores = attention( + x, target_embedding, (encoder_a, encoder_b), encoder_padding_mask + ) + + if not self.training and self.need_attn: + attn_scores = attn_scores / num_attn_layers + if avg_attn_scores is None: + avg_attn_scores = attn_scores + else: + avg_attn_scores.add_(attn_scores) + + x = self._transpose_if_training(x, incremental_state) + + # residual + if residual is not None: + x = (x + residual) * math.sqrt(0.5) + residuals.append(x) + + # T x B x C -> B x T x C + x = self._transpose_if_training(x, incremental_state) + + # project back to size of vocabulary if not using adaptive softmax + if self.fc2 is not None and self.fc3 is not None: + x = self.fc2(x) + x = self.dropout_module(x) + x = self.fc3(x) + + return x, avg_attn_scores + + def reorder_incremental_state(self, incremental_state, new_order): + super().reorder_incremental_state(incremental_state, new_order) + encoder_out = utils.get_incremental_state( + self, incremental_state, "encoder_out" + ) + if encoder_out is not None: + encoder_out = tuple(eo.index_select(0, new_order) for eo in encoder_out) + utils.set_incremental_state( + self, incremental_state, "encoder_out", encoder_out + ) + + def max_positions(self): + """Maximum output length supported by the decoder.""" + return ( + self.embed_positions.max_positions + if self.embed_positions is not None + else float("inf") + ) + + def upgrade_state_dict(self, state_dict): + if utils.item(state_dict.get("decoder.version", torch.Tensor([1]))[0]) < 2: + # old models use incorrect weight norm dimension + for i, conv in enumerate(self.convolutions): + # reconfigure weight norm + nn.utils.remove_weight_norm(conv) + self.convolutions[i] = nn.utils.weight_norm(conv, dim=0) + state_dict["decoder.version"] = torch.Tensor([1]) + return state_dict + + def make_generation_fast_(self, need_attn=False, **kwargs): + self.need_attn = need_attn + + def _embed_tokens(self, tokens, incremental_state): + if incremental_state is not None: + # keep only the last token for incremental forward pass + tokens = tokens[:, -1:] + return self.embed_tokens(tokens) + + def _split_encoder_out(self, encoder_out, incremental_state): + """Split and transpose encoder outputs. + + This is cached when doing incremental inference. + """ + cached_result = utils.get_incremental_state( + self, incremental_state, "encoder_out" + ) + if cached_result is not None: + return cached_result + + # transpose only once to speed up attention layers + encoder_a, encoder_b = encoder_out + encoder_a = encoder_a.transpose(1, 2).contiguous() + result = (encoder_a, encoder_b) + + if incremental_state is not None: + utils.set_incremental_state(self, incremental_state, "encoder_out", result) + return result + + def _transpose_if_training(self, x, incremental_state): + if incremental_state is None: + x = x.transpose(0, 1) + return x + + +def extend_conv_spec(convolutions): + """ + Extends convolutional spec that is a list of tuples of 2 or 3 parameters + (kernel size, dim size and optionally how many layers behind to look for residual) + to default the residual propagation param if it is not specified + """ + extended = [] + for spec in convolutions: + if len(spec) == 3: + extended.append(spec) + elif len(spec) == 2: + extended.append(spec + (1,)) + else: + raise Exception( + "invalid number of parameters in convolution spec " + + str(spec) + + ". expected 2 or 3" + ) + return tuple(extended) + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.normal_(m.weight, 0, 0.1) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def PositionalEmbedding(num_embeddings, embedding_dim, padding_idx): + m = LearnedPositionalEmbedding(num_embeddings, embedding_dim, padding_idx) + nn.init.normal_(m.weight, 0, 0.1) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, dropout=0.0): + """Weight-normalized Linear layer (input: N x T x C)""" + m = nn.Linear(in_features, out_features) + nn.init.normal_(m.weight, mean=0, std=math.sqrt((1 - dropout) / in_features)) + nn.init.constant_(m.bias, 0) + return nn.utils.weight_norm(m) + + +def LinearizedConv1d(in_channels, out_channels, kernel_size, dropout=0.0, **kwargs): + """Weight-normalized Conv1d layer optimized for decoding""" + m = LinearizedConvolution(in_channels, out_channels, kernel_size, **kwargs) + std = math.sqrt((4 * (1.0 - dropout)) / (m.kernel_size[0] * in_channels)) + nn.init.normal_(m.weight, mean=0, std=std) + nn.init.constant_(m.bias, 0) + return nn.utils.weight_norm(m, dim=2) + + +def ConvTBC(in_channels, out_channels, kernel_size, dropout=0.0, **kwargs): + """Weight-normalized Conv1d layer""" + from fairseq.modules import ConvTBC + + m = ConvTBC(in_channels, out_channels, kernel_size, **kwargs) + std = math.sqrt((4 * (1.0 - dropout)) / (m.kernel_size[0] * in_channels)) + nn.init.normal_(m.weight, mean=0, std=std) + nn.init.constant_(m.bias, 0) + return nn.utils.weight_norm(m, dim=2) + + +@register_model_architecture("fconv", "fconv") +def base_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_layers = getattr(args, "encoder_layers", "[(512, 3)] * 20") + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_layers = getattr(args, "decoder_layers", "[(512, 3)] * 20") + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 256) + args.decoder_attention = getattr(args, "decoder_attention", "True") + args.share_input_output_embed = getattr(args, "share_input_output_embed", False) + + +@register_model_architecture("fconv", "fconv_iwslt_de_en") +def fconv_iwslt_de_en(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 256) + args.encoder_layers = getattr(args, "encoder_layers", "[(256, 3)] * 4") + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 256) + args.decoder_layers = getattr(args, "decoder_layers", "[(256, 3)] * 3") + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 256) + base_architecture(args) + + +@register_model_architecture("fconv", "fconv_wmt_en_ro") +def fconv_wmt_en_ro(args): + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 512) + base_architecture(args) + + +@register_model_architecture("fconv", "fconv_wmt_en_de") +def fconv_wmt_en_de(args): + convs = "[(512, 3)] * 9" # first 9 layers have 512 units + convs += " + [(1024, 3)] * 4" # next 4 layers have 1024 units + convs += " + [(2048, 1)] * 2" # final 2 layers use 1x1 convolutions + + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_layers = getattr(args, "encoder_layers", convs) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 768) + args.decoder_layers = getattr(args, "decoder_layers", convs) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 512) + base_architecture(args) + + +@register_model_architecture("fconv", "fconv_wmt_en_fr") +def fconv_wmt_en_fr(args): + convs = "[(512, 3)] * 6" # first 6 layers have 512 units + convs += " + [(768, 3)] * 4" # next 4 layers have 768 units + convs += " + [(1024, 3)] * 3" # next 3 layers have 1024 units + convs += " + [(2048, 1)] * 1" # next 1 layer uses 1x1 convolutions + convs += " + [(4096, 1)] * 1" # final 1 layer uses 1x1 convolutions + + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_layers = getattr(args, "encoder_layers", convs) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 768) + args.decoder_layers = getattr(args, "decoder_layers", convs) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 512) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/fconv_lm.py b/fairseq-tools/fairseq/fairseq/models/fconv_lm.py new file mode 100644 index 00000000..07391eaa --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fconv_lm.py @@ -0,0 +1,135 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import utils +from fairseq.models import ( + FairseqLanguageModel, + register_model, + register_model_architecture, +) +from fairseq.models.fconv import FConvDecoder + + +@register_model("fconv_lm") +class FConvLanguageModel(FairseqLanguageModel): + def __init__(self, decoder): + super().__init__(decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--dropout", type=float, metavar="D", help="dropout probability" + ) + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-layers", + type=str, + metavar="EXPR", + help="decoder layers [(dim, kernel_size), ...]", + ) + parser.add_argument( + "--decoder-out-embed-dim", + type=int, + metavar="N", + help="decoder output embedding dimension", + ) + parser.add_argument( + "--adaptive-softmax-cutoff", + metavar="EXPR", + help="comma separated list of adaptive softmax cutoff points. " + "Must be used with adaptive_loss criterion", + ) + parser.add_argument( + "--adaptive-softmax-dropout", + type=float, + metavar="D", + help="sets adaptive softmax dropout for the tail projections", + ) + parser.add_argument( + "--decoder-attention", + type=str, + metavar="EXPR", + help="decoder attention [True, ...]", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + # make sure all arguments are present in older models + base_lm_architecture(args) + + if hasattr(args, "max_target_positions") and not hasattr( + args, "tokens_per_sample" + ): + args.tokens_per_sample = args.max_target_positions + + decoder = FConvDecoder( + dictionary=task.target_dictionary, + embed_dim=args.decoder_embed_dim, + convolutions=eval(args.decoder_layers), + out_embed_dim=args.decoder_embed_dim, + attention=eval(args.decoder_attention), + dropout=args.dropout, + max_positions=args.tokens_per_sample, + share_embed=False, + positional_embeddings=False, + adaptive_softmax_cutoff=( + utils.eval_str_list(args.adaptive_softmax_cutoff, type=int) + if args.criterion == "adaptive_loss" + else None + ), + adaptive_softmax_dropout=args.adaptive_softmax_dropout, + ) + return FConvLanguageModel(decoder) + + +@register_model_architecture("fconv_lm", "fconv_lm") +def base_lm_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 128) + args.decoder_layers = getattr(args, "decoder_layers", "[(1268, 4)] * 13") + args.decoder_attention = getattr(args, "decoder_attention", "False") + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + + +@register_model_architecture("fconv_lm", "fconv_lm_dauphin_wikitext103") +def fconv_lm_dauphin_wikitext103(args): + layers = "[(850, 6)] * 3" + layers += " + [(850, 1)] * 1" + layers += " + [(850, 5)] * 4" + layers += " + [(850, 1)] * 1" + layers += " + [(850, 4)] * 3" + layers += " + [(1024, 4)] * 1" + layers += " + [(2048, 4)] * 1" + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 280) + args.decoder_layers = getattr(args, "decoder_layers", layers) + args.decoder_attention = getattr(args, "decoder_attention", "False") + args.adaptive_softmax_cutoff = getattr( + args, "adaptive_softmax_cutoff", "10000,20000,200000" + ) + base_lm_architecture(args) + + +@register_model_architecture("fconv_lm", "fconv_lm_dauphin_gbw") +def fconv_lm_dauphin_gbw(args): + layers = "[(512, 5)]" + layers += " + [(128, 1, 0), (128, 5, 0), (512, 1, 3)] * 3" + layers += " + [(512, 1, 0), (512, 5, 0), (1024, 1, 3)] * 3" + layers += " + [(1024, 1, 0), (1024, 5, 0), (2048, 1, 3)] * 6" + layers += " + [(1024, 1, 0), (1024, 5, 0), (4096, 1, 3)]" + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 128) + args.decoder_layers = getattr(args, "decoder_layers", layers) + args.decoder_attention = getattr(args, "decoder_attention", "False") + args.adaptive_softmax_cutoff = getattr( + args, "adaptive_softmax_cutoff", "10000,50000,200000" + ) + base_lm_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/fconv_self_att.py b/fairseq-tools/fairseq/fairseq/models/fconv_self_att.py new file mode 100644 index 00000000..8357ef78 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/fconv_self_att.py @@ -0,0 +1,674 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import math +import os + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import checkpoint_utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.models import ( + CompositeEncoder, + FairseqDecoder, + FairseqEncoder, + FairseqEncoderDecoderModel, + register_model, + register_model_architecture, +) +from fairseq.modules import ( + DownsampledMultiHeadAttention, + FairseqDropout, + GradMultiply, + LayerNorm, + LearnedPositionalEmbedding, + LinearizedConvolution, +) + + +logger = logging.getLogger(__name__) + + +@register_model("fconv_self_att") +class FConvModelSelfAtt(FairseqEncoderDecoderModel): + @classmethod + def hub_models(cls): + return { + "conv.stories.pretrained": { + "path": "https://dl.fbaipublicfiles.com/fairseq/models/stories_checkpoint.tar.gz", + "checkpoint_file": "pretrained_checkpoint.pt", + "tokenizer": "nltk", + }, + "conv.stories": { + "path": "https://dl.fbaipublicfiles.com/fairseq/models/stories_checkpoint.tar.gz", + "checkpoint_file": "fusion_checkpoint.pt", + "tokenizer": "nltk", + "pretrained": "True", + "pretrained_checkpoint": "./pretrained_checkpoint.pt", + }, + # Test set containing dictionaries + "data.stories": "https://dl.fbaipublicfiles.com/fairseq/data/stories_test.tar.bz2", + } + + def __init__(self, encoder, decoder, pretrained_encoder=None): + super().__init__(encoder, decoder) + self.encoder.num_attention_layers = sum( + layer is not None for layer in decoder.attention + ) + self.pretrained_encoder = pretrained_encoder + if self.pretrained_encoder is None: + encoders = {"encoder": encoder} + else: + encoders = {"encoder": encoder, "pretrained": self.pretrained_encoder} + # for fusion model, CompositeEncoder contains both pretrained and training encoders + # these are forwarded and then combined in the decoder + self.encoder = CompositeEncoder(encoders) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--encoder-embed-dim', type=int, metavar='N', + help='encoder embedding dimension') + parser.add_argument('--encoder-layers', type=str, metavar='EXPR', + help='encoder layers [(dim, kernel_size), ...]') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-layers', type=str, metavar='EXPR', + help='decoder layers [(dim, kernel_size), ...]') + parser.add_argument('--decoder-out-embed-dim', type=int, metavar='N', + help='decoder output embedding dimension') + parser.add_argument('--decoder-attention', type=str, metavar='EXPR', + help='decoder attention [True, ...]') + parser.add_argument('--self-attention', type=str, metavar='EXPR', + help='decoder self-attention layers, ex: [True] + [False]*5') + parser.add_argument('--multihead-attention-nheads', type=int, + help='Number of heads to use in attention') + parser.add_argument('--multihead-self-attention-nheads', type=int, + help='Number of heads to use in self-attention') + parser.add_argument('--encoder-attention', type=str, metavar='EXPR', + help='encoder attention [True, ...]') + parser.add_argument('--encoder-attention-nheads', type=int, + help='Number of heads to use in encoder attention') + parser.add_argument('--project-input', type=str, metavar='EXPR', + help='Use projections in self-attention [True, ...]') + parser.add_argument('--gated-attention', type=str, metavar='EXPR', + help='Use GLU layers in self-attention projections [True, ...]') + parser.add_argument('--downsample', type=str, metavar='EXPR', + help='Use downsampling in self-attention [True, ...]') + parser.add_argument('--pretrained-checkpoint', metavar='DIR', + help='path to load checkpoint from pretrained model') + parser.add_argument('--pretrained', type=str, metavar='EXPR', + help='use pretrained model when training [True, ...]') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + trained_encoder, trained_decoder = None, None + pretrained = eval(args.pretrained) + if pretrained: + logger.info("loading pretrained model") + if not os.path.exists(args.pretrained_checkpoint): + new_pretrained_checkpoint = os.path.join( + args.data, args.pretrained_checkpoint + ) + if os.path.exists(new_pretrained_checkpoint): + args.pretrained_checkpoint = new_pretrained_checkpoint + trained_model = checkpoint_utils.load_model_ensemble( + filenames=[args.pretrained_checkpoint], + task=task, + )[0][0] + trained_decoder = list(trained_model.children())[1] + trained_encoder = list(trained_model.children())[0] + + # freeze pretrained model + for param in trained_decoder.parameters(): + param.requires_grad = False + for param in trained_encoder.parameters(): + param.requires_grad = False + + encoder = FConvEncoder( + task.source_dictionary, + embed_dim=args.encoder_embed_dim, + convolutions=eval(args.encoder_layers), + dropout=args.dropout, + max_positions=args.max_source_positions, + attention=eval(args.encoder_attention), + attention_nheads=args.encoder_attention_nheads, + ) + + decoder = FConvDecoder( + task.target_dictionary, + embed_dim=args.decoder_embed_dim, + convolutions=eval(args.decoder_layers), + out_embed_dim=args.decoder_out_embed_dim, + attention=eval(args.decoder_attention), + dropout=args.dropout, + max_positions=args.max_target_positions, + selfattention=eval(args.self_attention), + attention_nheads=args.multihead_attention_nheads, + selfattention_nheads=args.multihead_self_attention_nheads, + project_input=eval(args.project_input), + gated_attention=eval(args.gated_attention), + downsample=eval(args.downsample), + pretrained=pretrained, + trained_decoder=trained_decoder, + ) + model = FConvModelSelfAtt(encoder, decoder, trained_encoder) + + return model + + @property + def pretrained(self): + return self.pretrained_encoder is not None + + +class FConvEncoder(FairseqEncoder): + """Convolutional encoder""" + + def __init__( + self, + dictionary, + embed_dim=512, + max_positions=1024, + convolutions=((512, 3),) * 20, + dropout=0.1, + attention=False, + attention_nheads=1, + ): + super().__init__(dictionary) + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.num_attention_layers = None + + num_embeddings = len(dictionary) + self.padding_idx = dictionary.pad() + self.embed_tokens = Embedding(num_embeddings, embed_dim, self.padding_idx) + self.embed_positions = PositionalEmbedding( + max_positions, + embed_dim, + self.padding_idx, + ) + + def expand_bool_array(val): + if isinstance(val, bool): + # expand True into [True, True, ...] and do the same with False + return [val] * len(convolutions) + return val + + attention = expand_bool_array(attention) + + in_channels = convolutions[0][0] + self.fc1 = Linear(embed_dim, in_channels, dropout=dropout) + self.projections = nn.ModuleList() + self.convolutions = nn.ModuleList() + self.attention = nn.ModuleList() + self.attproj = nn.ModuleList() + for i, (out_channels, kernel_size) in enumerate(convolutions): + self.projections.append( + Linear(in_channels, out_channels) + if in_channels != out_channels + else None + ) + self.convolutions.append( + ConvTBC(in_channels, out_channels * 2, kernel_size, dropout=dropout) + ) + + self.attention.append( + SelfAttention(out_channels, embed_dim, attention_nheads) + if attention[i] + else None + ) + in_channels = out_channels + + self.fc2 = Linear(in_channels, embed_dim) + + def forward(self, src_tokens, src_lengths): + # embed tokens and positions + x = self.embed_tokens(src_tokens) + self.embed_positions(src_tokens) + x = self.dropout_module(x) + input_embedding = x.transpose(0, 1) + + # project to size of convolution + x = self.fc1(x) + + encoder_padding_mask = src_tokens.eq(self.padding_idx).t() # -> T x B + if not encoder_padding_mask.any(): + encoder_padding_mask = None + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # temporal convolutions + for proj, conv, attention in zip( + self.projections, self.convolutions, self.attention + ): + residual = x if proj is None else proj(x) + + if encoder_padding_mask is not None: + x = x.masked_fill(encoder_padding_mask.unsqueeze(-1), 0) + + x = self.dropout_module(x) + padding_l = (conv.kernel_size[0] - 1) // 2 + padding_r = conv.kernel_size[0] // 2 + x = F.pad(x, (0, 0, 0, 0, padding_l, padding_r)) + x = conv(x) + x = F.glu(x, dim=2) + if attention is not None: + x = attention(x) + x = (x + residual) * math.sqrt(0.5) + + # T x B x C -> B x T x C + x = x.transpose(1, 0) + + # project back to size of embedding + x = self.fc2(x) + + if encoder_padding_mask is not None: + encoder_padding_mask = encoder_padding_mask.t() # -> B x T + x = x.masked_fill(encoder_padding_mask.unsqueeze(-1), 0) + + # scale gradients (this only affects backward, not forward) + x = GradMultiply.apply(x, 1.0 / (2.0 * self.num_attention_layers)) + + # add output to input embedding for attention + y = (x + input_embedding.transpose(0, 1)) * math.sqrt(0.5) + + return { + "encoder_out": (x, y), + "encoder_padding_mask": encoder_padding_mask, # B x T + } + + def reorder_encoder_out(self, encoder_out, new_order): + encoder_out["encoder_out"] = tuple( + eo.index_select(0, new_order) for eo in encoder_out["encoder_out"] + ) + + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(0, new_order) + + if "pretrained" in encoder_out: + encoder_out["pretrained"]["encoder_out"] = tuple( + eo.index_select(0, new_order) + for eo in encoder_out["pretrained"]["encoder_out"] + ) + + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return self.embed_positions.max_positions + + +@with_incremental_state +class FConvDecoder(FairseqDecoder): + """Convolutional decoder""" + + def __init__( + self, + dictionary, + embed_dim=512, + out_embed_dim=256, + max_positions=1024, + convolutions=((512, 3),) * 8, + attention=True, + dropout=0.1, + selfattention=False, + attention_nheads=1, + selfattention_nheads=1, + project_input=False, + gated_attention=False, + downsample=False, + pretrained=False, + trained_decoder=None, + ): + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([2])) + self.pretrained = pretrained + self.pretrained_decoder = trained_decoder + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.need_attn = True + in_channels = convolutions[0][0] + + def expand_bool_array(val): + if isinstance(val, bool): + # expand True into [True, True, ...] and do the same with False + return [val] * len(convolutions) + return val + + attention = expand_bool_array(attention) + selfattention = expand_bool_array(selfattention) + + if not isinstance(attention, list) or len(attention) != len(convolutions): + raise ValueError( + "Attention is expected to be a list of booleans of " + "length equal to the number of layers." + ) + + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + self.embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx) + + self.embed_positions = PositionalEmbedding( + max_positions, + embed_dim, + padding_idx, + ) + + self.fc1 = Linear(embed_dim, in_channels, dropout=dropout) + self.projections = nn.ModuleList() + self.convolutions = nn.ModuleList() + self.attention = nn.ModuleList() + self.selfattention = nn.ModuleList() + self.attproj = nn.ModuleList() + for i, (out_channels, kernel_size) in enumerate(convolutions): + self.projections.append( + Linear(in_channels, out_channels) + if in_channels != out_channels + else None + ) + self.convolutions.append( + LinearizedConv1d( + in_channels, + out_channels * 2, + kernel_size, + padding=(kernel_size - 1), + dropout=dropout, + ) + ) + + self.attention.append( + DownsampledMultiHeadAttention( + out_channels, + embed_dim, + attention_nheads, + project_input=project_input, + gated=False, + downsample=False, + ) + if attention[i] + else None + ) + + self.attproj.append( + Linear(out_channels, embed_dim, dropout=dropout) + if attention[i] + else None + ) + self.selfattention.append( + SelfAttention( + out_channels, + embed_dim, + selfattention_nheads, + project_input=project_input, + gated=gated_attention, + downsample=downsample, + ) + if selfattention[i] + else None + ) + in_channels = out_channels + + self.fc2 = Linear(in_channels, out_embed_dim) + self.fc3 = Linear(out_embed_dim, num_embeddings, dropout=dropout) + + # model fusion + if self.pretrained: + # independent gates are learned from the concatenated input + self.gate1 = nn.Sequential( + Linear(out_embed_dim * 2, out_embed_dim), nn.Sigmoid() + ) + self.gate2 = nn.Sequential( + Linear(out_embed_dim * 2, out_embed_dim), nn.Sigmoid() + ) + # pretrained and trained models are joined + self.joining = nn.Sequential( + Linear(out_embed_dim * 2, out_embed_dim * 2), + LayerNorm(out_embed_dim * 2), + nn.GLU(), + Linear(out_embed_dim, out_embed_dim * 2), + LayerNorm(out_embed_dim * 2), + nn.GLU(), + Linear(out_embed_dim, out_embed_dim), + LayerNorm(out_embed_dim), + ) + # pretrained model contains an output layer that is nhid -> vocab size + # but the models are combined in their hidden state + # the hook stores the output of the pretrained model forward + self.pretrained_outputs = {} + + def save_output(): + def hook(a, b, output): + self.pretrained_outputs["out"] = output + + return hook + + self.pretrained_decoder.fc2.register_forward_hook(save_output()) + + def forward(self, prev_output_tokens, encoder_out): + trained_encoder_out = encoder_out["pretrained"] if self.pretrained else None + encoder_out = encoder_out["encoder"]["encoder_out"] + + encoder_a, encoder_b = self._split_encoder_out(encoder_out) + + # embed positions + positions = self.embed_positions(prev_output_tokens) + + # embed tokens and positions + x = self.embed_tokens(prev_output_tokens) + positions + x = self.dropout_module(x) + target_embedding = x.transpose(0, 1) + + # project to size of convolution + x = self.fc1(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # temporal convolutions + avg_attn_scores = None + for proj, conv, attention, selfattention, attproj in zip( + self.projections, + self.convolutions, + self.attention, + self.selfattention, + self.attproj, + ): + residual = x if proj is None else proj(x) + + x = self.dropout_module(x) + x = conv(x) + x = F.glu(x, dim=2) + + # attention + if attention is not None: + r = x + x, attn_scores = attention( + attproj(x) + target_embedding, encoder_a, encoder_b + ) + x = x + r + if not self.training and self.need_attn: + if avg_attn_scores is None: + avg_attn_scores = attn_scores + else: + avg_attn_scores.add_(attn_scores) + + if selfattention is not None: + x = selfattention(x) + + x = (x + residual) * math.sqrt(0.5) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + # project back to size of vocabulary + x = self.fc2(x) + x = self.dropout_module(x) + if not self.pretrained: + x = self.fc3(x) + + # fusion gating + if self.pretrained: + trained_x, _ = self.pretrained_decoder.forward( + prev_output_tokens, trained_encoder_out + ) + y = torch.cat([x, self.pretrained_outputs["out"]], dim=-1) + gate1 = self.gate1(y) + gate2 = self.gate2(y) + gated_x1 = gate1 * x + gated_x2 = gate2 * self.pretrained_outputs["out"] + fusion = torch.cat([gated_x1, gated_x2], dim=-1) + fusion = self.joining(fusion) + fusion_output = self.fc3(fusion) + return fusion_output, avg_attn_scores + else: + return x, avg_attn_scores + + def max_positions(self): + """Maximum output length supported by the decoder.""" + return self.embed_positions.max_positions + + def make_generation_fast_(self, need_attn=False, **kwargs): + self.need_attn = need_attn + + def _split_encoder_out(self, encoder_out): + """Split and transpose encoder outputs.""" + # transpose only once to speed up attention layers + encoder_a, encoder_b = encoder_out + encoder_a = encoder_a.transpose(0, 1).contiguous() + encoder_b = encoder_b.transpose(0, 1).contiguous() + result = (encoder_a, encoder_b) + return result + + +class SelfAttention(nn.Module): + def __init__( + self, + out_channels, + embed_dim, + num_heads, + project_input=False, + gated=False, + downsample=False, + ): + super().__init__() + self.attention = DownsampledMultiHeadAttention( + out_channels, + embed_dim, + num_heads, + dropout=0, + bias=True, + project_input=project_input, + gated=gated, + downsample=downsample, + ) + self.in_proj_q = Linear(out_channels, embed_dim) + self.in_proj_k = Linear(out_channels, embed_dim) + self.in_proj_v = Linear(out_channels, embed_dim) + self.ln = LayerNorm(out_channels) + + def forward(self, x): + residual = x + query = self.in_proj_q(x) + key = self.in_proj_k(x) + value = self.in_proj_v(x) + x, _ = self.attention( + query, key, value, mask_future_timesteps=True, use_scalar_bias=True + ) + return self.ln(x + residual) + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + m.weight.data.normal_(0, 0.1) + return m + + +def PositionalEmbedding(num_embeddings, embedding_dim, padding_idx): + m = LearnedPositionalEmbedding(num_embeddings, embedding_dim, padding_idx) + m.weight.data.normal_(0, 0.1) + return m + + +def Linear(in_features, out_features, dropout=0.0): + """Weight-normalized Linear layer (input: N x T x C)""" + m = nn.Linear(in_features, out_features) + m.weight.data.normal_(mean=0, std=math.sqrt((1 - dropout) / in_features)) + m.bias.data.zero_() + return m + + +def LinearizedConv1d(in_channels, out_channels, kernel_size, dropout=0.0, **kwargs): + """Weight-normalized Conv1d layer optimized for decoding""" + m = LinearizedConvolution(in_channels, out_channels, kernel_size, **kwargs) + std = math.sqrt((4 * (1.0 - dropout)) / (m.kernel_size[0] * in_channels)) + m.weight.data.normal_(mean=0, std=std) + m.bias.data.zero_() + return m + + +def ConvTBC(in_channels, out_channels, kernel_size, dropout=0.0, **kwargs): + """Weight-normalized Conv1d layer""" + from fairseq.modules import ConvTBC + + m = ConvTBC(in_channels, out_channels, kernel_size, **kwargs) + std = math.sqrt((4 * (1.0 - dropout)) / (m.kernel_size[0] * in_channels)) + m.weight.data.normal_(mean=0, std=std) + m.bias.data.zero_() + return m + + +@register_model_architecture("fconv_self_att", "fconv_self_att") +def base_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_layers = getattr(args, "encoder_layers", "[(512, 3)] * 3") + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_layers = getattr(args, "decoder_layers", "[(512, 3)] * 8") + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 256) + args.decoder_attention = getattr(args, "decoder_attention", "True") + args.self_attention = getattr(args, "self_attention", "False") + args.encoder_attention = getattr(args, "encoder_attention", "False") + args.multihead_attention_nheads = getattr(args, "multihead_attention_nheads", 1) + args.multihead_self_attention_nheads = getattr( + args, "multihead_self_attention_nheads", 1 + ) + args.encoder_attention_nheads = getattr(args, "encoder_attention_nheads", 1) + args.project_input = getattr(args, "project_input", "False") + args.gated_attention = getattr(args, "gated_attention", "False") + args.downsample = getattr(args, "downsample", "False") + args.pretrained_checkpoint = getattr(args, "pretrained_checkpoint", "") + args.pretrained = getattr(args, "pretrained", "False") + + +@register_model_architecture("fconv_self_att", "fconv_self_att_wp") +def fconv_self_att_wp(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 256) + args.encoder_layers = getattr( + args, "encoder_layers", "[(128, 3)] * 2 + [(512,3)] * 1" + ) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 256) + args.decoder_layers = getattr( + args, "decoder_layers", "[(512, 4)] * 4 + [(768, 4)] * 2 + [(1024, 4)] * 1" + ) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 256) + args.self_attention = getattr(args, "self_attention", "True") + args.multihead_self_attention_nheads = getattr( + args, "multihead_self_attention_nheads", 4 + ) + args.project_input = getattr(args, "project_input", "True") + args.gated_attention = getattr(args, "gated_attention", "True") + args.downsample = getattr(args, "downsample", "True") + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/huggingface/__init__.py b/fairseq-tools/fairseq/fairseq/models/huggingface/__init__.py new file mode 100644 index 00000000..f7911c2c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/huggingface/__init__.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib +import os + + +# automatically import any Python files in the models/huggingface/ directory +models_dir = os.path.dirname(__file__) +for file in os.listdir(models_dir): + path = os.path.join(models_dir, file) + if ( + not file.startswith("_") + and not file.startswith(".") + and (file.endswith(".py") or os.path.isdir(path)) + ): + model_name = file[: file.find(".py")] if file.endswith(".py") else file + module = importlib.import_module("fairseq.models.huggingface." + model_name) diff --git a/fairseq-tools/fairseq/fairseq/models/huggingface/hf_gpt2.py b/fairseq-tools/fairseq/fairseq/models/huggingface/hf_gpt2.py new file mode 100644 index 00000000..3a8eb781 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/huggingface/hf_gpt2.py @@ -0,0 +1,168 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +import sys +from typing import Dict, List, Optional + +import torch +from fairseq.models import ( + FairseqIncrementalDecoder, + FairseqLanguageModel, + register_model, + register_model_architecture, +) + + +logger = logging.getLogger(__name__) + + +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@register_model("hf_gpt2") +class HuggingFaceGPT2LanguageModel(FairseqLanguageModel): + def __init__(self, decoder): + super().__init__(decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--embed-dim', type=int, metavar='N', + help='embedding dimension') + parser.add_argument('--num-attention-heads', type=int, metavar='N', + help='num attention heads') + parser.add_argument('--num-layers', type=int, metavar='N', + help='num layers') + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability for all fully connected layers ' + 'in the embeddings, encoder, and pooler') + parser.add_argument('--attention-dropout', type=float, metavar='D', + help='dropout probability for attention weights') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + default_architecture(args) + return cls(HuggingFaceGPT2Decoder(args, task)) + + +class HuggingFaceGPT2Decoder(FairseqIncrementalDecoder): + def __init__(self, args, task): + try: + from transformers import GPT2Config, GPT2LMHeadModel + except ImportError: + raise ImportError( + "\n\nPlease install huggingface/transformers with:" + "\n\n pip install transformers" + ) + + super().__init__(task.target_dictionary) + + config = GPT2Config( + vocab_size=len(task.target_dictionary), + n_positions=args.max_target_positions + 1, + n_ctx=args.max_target_positions, + n_embd=args.embed_dim, + n_layer=args.num_layers, + n_head=args.num_attention_heads, + resid_pdrop=args.dropout, + embd_pdrop=args.dropout, + attn_pdrop=args.attention_dropout, + layer_norm_epsilon=1e-6, + ) + self.model = GPT2LMHeadModel(config) + + # set zero embedding for padding symbol + self.pad_idx = task.target_dictionary.pad() + self.model.transformer.wte.weight.data[self.pad_idx].zero_() + self.model.transformer.wpe.weight.data[0].zero_() + + def forward( + self, + prev_output_tokens, + src_lengths=None, + incremental_state: Optional[Dict[str, List[torch.Tensor]]] = None, + encoder_out=None, + ): + features = self.extract_features(prev_output_tokens, incremental_state) + lm_logits = self.model.lm_head(features) + return (lm_logits,) + + def extract_features( + self, + prev_output_tokens, + incremental_state: Optional[Dict[str, List[torch.Tensor]]] = None, + ): + if incremental_state: + past = self.get_incremental_state("past") + else: + past = None + + # don't attend to padding symbols + attention_mask = prev_output_tokens.ne(self.pad_idx).int() + + # set position ids to exclude padding symbols + position_ids = attention_mask * ( + torch.arange(1, 1 + prev_output_tokens.size(1)) + .to(prev_output_tokens) + .repeat(prev_output_tokens.size(0), 1) + ) + + outputs = self.model.transformer( + input_ids=prev_output_tokens, + past=past, + attention_mask=attention_mask, + position_ids=position_ids, + ) + last_hidden_states = outputs[0] + + if incremental_state: + self.set_incremental_state(incremental_state, "past", outputs[1]) + + return last_hidden_states + + def max_positions(self): + return self.model.config.n_positions - 1 + + +@register_model_architecture("hf_gpt2", "hf_gpt2") +def default_architecture(args): + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = getattr( + args, "tokens_per_sample", DEFAULT_MAX_TARGET_POSITIONS + ) + args.embed_dim = getattr(args, "embed_dim", 768) + args.num_attention_heads = getattr(args, "num_attention_heads", 12) + args.num_layers = getattr(args, "num_layers", 12) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + + +@register_model_architecture("hf_gpt2", "hf_gpt2_medium") +def hf_gpt2_medium(args): + args.embed_dim = getattr(args, "embed_dim", 1024) + args.num_attention_heads = getattr(args, "num_attention_heads", 16) + args.num_layers = getattr(args, "num_layers", 24) + default_architecture(args) + + +@register_model_architecture("hf_gpt2", "hf_gpt2_large") +def hf_gpt2_large(args): + args.embed_dim = getattr(args, "embed_dim", 1280) + args.num_attention_heads = getattr(args, "num_attention_heads", 20) + args.num_layers = getattr(args, "num_layers", 36) + default_architecture(args) + + +@register_model_architecture("hf_gpt2", "hf_gpt2_xl") +def hf_gpt2_xl(args): + args.embed_dim = getattr(args, "embed_dim", 1600) + args.num_attention_heads = getattr(args, "num_attention_heads", 25) + args.num_layers = getattr(args, "num_layers", 48) + default_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/lightconv.py b/fairseq-tools/fairseq/fairseq/models/lightconv.py new file mode 100644 index 00000000..b614da36 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/lightconv.py @@ -0,0 +1,1018 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.modules import ( + AdaptiveSoftmax, + DynamicConv, + FairseqDropout, + LayerNorm, + LightweightConv, + MultiheadAttention, + PositionalEmbedding, +) + + +@register_model("lightconv") +class LightConvModel(FairseqEncoderDecoderModel): + """ + LightConv and DynamicConv model from `"Pay Less Attention with Lightweight and Dynamic Convolutions" (Wu, et al, 2019) + <https://openreview.net/pdf?id=SkVhlh09tX>`_. + To use LightConv please set ``--encoder-conv-type lightweight --decoder-conv-type lightweight`` + To use DynamicConv please set ``--encoder-conv-type dynamic --decoder-conv-type dynamic`` + + Args: + encoder (LightConvEncoder): the encoder + decoder (LightConvDecoder): the decoder + + The LightConv model provides the following named architectures and + command-line arguments: + + .. argparse:: + :ref: fairseq.models.lightconv_parser + :prog: + """ + + @classmethod + def hub_models(cls): + # fmt: off + + def moses_subword(path): + return { + 'path': path, + 'tokenizer': 'moses', + 'bpe': 'subword_nmt', + } + + return { + 'lightconv.no_glu.iwslt14.de-en': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/iwslt14.de-en.lightconv.tar.gz'), + 'dynamicconv.no_glu.iwslt14.de-en': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/iwslt14.de-en.dynamicconv.tar.gz'), + 'lightconv.no_glu.wmt16.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.lightconv.tar.gz'), + 'dynamicconv.no_glu.wmt16.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.dynamicconv.tar.gz'), + 'lightconv.glu.wmt16.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.lightconv-glu.tar.gz'), + 'dynamicconv.glu.wmt16.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.dynamicconv-glu.tar.gz'), + 'lightconv.glu.wmt17.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.lightconv-glu.tar.gz'), + 'dynamicconv.glu.wmt17.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt16.en-de.joined-dict.dynamicconv-glu.tar.gz'), + 'lightconv.glu.wmt14.en-fr': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt14.en-fr.joined-dict.lightconv-glu.tar.gz'), + 'dynamicconv.glu.wmt14.en-fr': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt14.en-fr.joined-dict.dynamicconv-glu.tar.gz'), + 'lightconv.glu.wmt17.zh-en': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt17.zh-en.lightconv-glu.tar.gz'), + 'dynamicconv.glu.wmt17.zh-en': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/dynamicconv/wmt17.zh-en.dynamicconv-glu.tar.gz'), + } + # fmt: on + + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--dropout", type=float, metavar="D", help="dropout probability" + ) + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights", + ) + parser.add_argument( + "--relu-dropout", + type=float, + metavar="D", + help="dropout probability after ReLU in FFN", + ) + parser.add_argument( + "--input-dropout", + type=float, + metavar="D", + help="dropout probability of the inputs", + ) + parser.add_argument( + "--encoder-embed-path", + type=str, + metavar="STR", + help="path to pre-trained encoder embedding", + ) + parser.add_argument( + "--encoder-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension", + ) + parser.add_argument( + "--encoder-conv-dim", + type=int, + metavar="N", + help="encoder embedding dimension", + ) + parser.add_argument( + "--encoder-ffn-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension for FFN", + ) + parser.add_argument( + "--encoder-layers", type=int, metavar="N", help="num encoder layers" + ) + parser.add_argument( + "--encoder-attention-heads", + type=int, + metavar="N", + help="num encoder attention heads or LightConv/DynamicConv heads", + ) + parser.add_argument( + "--encoder-normalize-before", + action="store_true", + help="apply layernorm before each encoder block", + ) + parser.add_argument( + "--encoder-learned-pos", + action="store_true", + help="use learned positional embeddings in the encoder", + ) + parser.add_argument( + "--decoder-embed-path", + type=str, + metavar="STR", + help="path to pre-trained decoder embedding", + ) + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-conv-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-ffn-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension for FFN", + ) + parser.add_argument( + "--decoder-layers", type=int, metavar="N", help="num decoder layers" + ) + parser.add_argument( + "--decoder-attention-heads", + type=int, + metavar="N", + help="num decoder attention heads or LightConv/DynamicConv heads", + ) + parser.add_argument( + "--decoder-learned-pos", + action="store_true", + help="use learned positional embeddings in the decoder", + ) + parser.add_argument( + "--decoder-normalize-before", + action="store_true", + help="apply layernorm before each decoder block", + ) + parser.add_argument( + "--share-decoder-input-output-embed", + action="store_true", + help="share decoder input and output embeddings", + ) + parser.add_argument( + "--share-all-embeddings", + action="store_true", + help="share encoder, decoder and output embeddings" + " (requires shared dictionary and embed dim)", + ) + parser.add_argument( + "--adaptive-softmax-cutoff", + metavar="EXPR", + help="comma separated list of adaptive softmax cutoff points. " + "Must be used with adaptive_loss criterion", + ), + parser.add_argument( + "--adaptive-softmax-dropout", + type=float, + metavar="D", + help="sets adaptive softmax dropout for the tail projections", + ) + + """LightConv and DynamicConv arguments""" + parser.add_argument( + "--encoder-kernel-size-list", + type=lambda x: utils.eval_str_list(x, int), + help='list of kernel size (default: "[3,7,15,31,31,31,31]")', + ) + parser.add_argument( + "--decoder-kernel-size-list", + type=lambda x: utils.eval_str_list(x, int), + help='list of kernel size (default: "[3,7,15,31,31,31]")', + ) + parser.add_argument( + "--encoder-glu", type=utils.eval_bool, help="glu after in proj" + ) + parser.add_argument( + "--decoder-glu", type=utils.eval_bool, help="glu after in proj" + ) + parser.add_argument( + "--encoder-conv-type", + default="dynamic", + type=str, + choices=["dynamic", "lightweight"], + help="type of convolution", + ) + parser.add_argument( + "--decoder-conv-type", + default="dynamic", + type=str, + choices=["dynamic", "lightweight"], + help="type of convolution", + ) + parser.add_argument("--weight-softmax", default=True, type=utils.eval_bool) + parser.add_argument( + "--weight-dropout", + type=float, + metavar="D", + help="dropout probability for conv weights", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if not hasattr(args, "max_source_positions"): + args.max_source_positions = 1024 + if not hasattr(args, "max_target_positions"): + args.max_target_positions = 1024 + + src_dict, tgt_dict = task.source_dictionary, task.target_dictionary + + def build_embedding(dictionary, embed_dim, path=None): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + emb = Embedding(num_embeddings, embed_dim, padding_idx) + # if provided, load from preloaded dictionaries + if path: + embed_dict = utils.parse_embedding(path) + utils.load_embedding(embed_dict, dictionary, emb) + return emb + + if args.share_all_embeddings: + if src_dict != tgt_dict: + raise RuntimeError( + "--share-all-embeddings requires a joined dictionary" + ) + if args.encoder_embed_dim != args.decoder_embed_dim: + raise RuntimeError( + "--share-all-embeddings requires --encoder-embed-dim to match --decoder-embed-dim" + ) + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise RuntimeError( + "--share-all-embeddings not compatible with --decoder-embed-path" + ) + encoder_embed_tokens = build_embedding( + src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = encoder_embed_tokens + args.share_decoder_input_output_embed = True + else: + encoder_embed_tokens = build_embedding( + src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = build_embedding( + tgt_dict, args.decoder_embed_dim, args.decoder_embed_path + ) + + encoder = LightConvEncoder(args, src_dict, encoder_embed_tokens) + decoder = LightConvDecoder(args, tgt_dict, decoder_embed_tokens) + return LightConvModel(encoder, decoder) + + +class LightConvEncoder(FairseqEncoder): + """ + LightConv encoder consisting of *args.encoder_layers* layers. Each layer + is a :class:`LightConvEncoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): encoding dictionary + embed_tokens (torch.nn.Embedding): input embedding + """ + + def __init__(self, args, dictionary, embed_tokens): + super().__init__(dictionary) + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + + embed_dim = embed_tokens.embedding_dim + self.padding_idx = embed_tokens.padding_idx + self.max_source_positions = args.max_source_positions + + self.embed_tokens = embed_tokens + self.embed_scale = math.sqrt(embed_dim) + self.embed_positions = ( + PositionalEmbedding( + args.max_source_positions, + embed_dim, + self.padding_idx, + learned=args.encoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + LightConvEncoderLayer( + args, kernel_size=args.encoder_kernel_size_list[i] + ) + for i in range(args.encoder_layers) + ] + ) + self.register_buffer("version", torch.Tensor([2])) + self.normalize = args.encoder_normalize_before + if self.normalize: + self.layer_norm = LayerNorm(embed_dim) + + def forward(self, src_tokens, **unused): + """ + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + + Returns: + dict: + - **encoder_out** (Tensor): the last encoder layer's output of + shape `(src_len, batch, embed_dim)` + - **encoder_padding_mask** (ByteTensor): the positions of + padding elements of shape `(batch, src_len)` + """ + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(src_tokens) + if self.embed_positions is not None: + x += self.embed_positions(src_tokens) + x = self.dropout_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # compute padding mask + encoder_padding_mask = src_tokens.eq(self.padding_idx) + if not encoder_padding_mask.any(): + encoder_padding_mask = None + + # encoder layers + for layer in self.layers: + x = layer(x, encoder_padding_mask) + + if self.normalize: + x = self.layer_norm(x) + + return { + "encoder_out": x, # T x B x C + "encoder_padding_mask": encoder_padding_mask, # B x T + } + + def reorder_encoder_out(self, encoder_out, new_order): + """ + Reorder encoder output according to *new_order*. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + *encoder_out* rearranged according to *new_order* + """ + if encoder_out["encoder_out"] is not None: + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(0, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + if self.embed_positions is None: + return self.max_source_positions + return min(self.max_source_positions, self.embed_positions.max_positions) + + +class LightConvDecoder(FairseqIncrementalDecoder): + """ + LightConv decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`LightConvDecoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs. + Default: ``False`` + """ + + def __init__( + self, args, dictionary, embed_tokens, no_encoder_attn=False, final_norm=True + ): + super().__init__(dictionary) + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.share_input_output_embed = args.share_decoder_input_output_embed + + input_embed_dim = embed_tokens.embedding_dim + embed_dim = args.decoder_embed_dim + output_embed_dim = args.decoder_output_dim + + padding_idx = embed_tokens.padding_idx + self.max_target_positions = args.max_target_positions + + self.embed_tokens = embed_tokens + self.embed_scale = math.sqrt(embed_dim) # todo: try with input_embed_dim + + self.project_in_dim = ( + Linear(input_embed_dim, embed_dim, bias=False) + if embed_dim != input_embed_dim + else None + ) + + self.embed_positions = ( + PositionalEmbedding( + args.max_target_positions, + embed_dim, + padding_idx, + learned=args.decoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + LightConvDecoderLayer( + args, no_encoder_attn, kernel_size=args.decoder_kernel_size_list[i] + ) + for i in range(args.decoder_layers) + ] + ) + + self.adaptive_softmax = None + + self.project_out_dim = ( + Linear(embed_dim, output_embed_dim, bias=False) + if embed_dim != output_embed_dim and not args.tie_adaptive_weights + else None + ) + + if args.adaptive_softmax_cutoff is not None: + self.adaptive_softmax = AdaptiveSoftmax( + len(dictionary), + output_embed_dim, + utils.eval_str_list(args.adaptive_softmax_cutoff, type=int), + dropout=args.adaptive_softmax_dropout, + adaptive_inputs=embed_tokens if args.tie_adaptive_weights else None, + factor=args.adaptive_softmax_factor, + tie_proj=args.tie_adaptive_proj, + ) + elif not self.share_input_output_embed: + self.embed_out = nn.Parameter( + torch.Tensor(len(dictionary), output_embed_dim) + ) + nn.init.normal_(self.embed_out, mean=0, std=output_embed_dim ** -0.5) + self.register_buffer("version", torch.Tensor([2])) + self.normalize = args.decoder_normalize_before and final_norm + if self.normalize: + self.layer_norm = LayerNorm(embed_dim) + + def forward( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **kwargs + ): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (Tensor, optional): output from the encoder, used for + encoder-side attention + incremental_state (dict): dictionary used for storing state during + :ref:`Incremental decoding` + + Returns: + tuple: + - the last decoder layer's output of shape `(batch, tgt_len, + vocab)` + - the last decoder layer's attention weights of shape `(batch, + tgt_len, src_len)` + """ + # embed positions + positions = ( + self.embed_positions( + prev_output_tokens, + incremental_state=incremental_state, + ) + if self.embed_positions is not None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + if positions is not None: + positions = positions[:, -1:] + + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + x = self.dropout_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + attn = None + + inner_states = [x] + + # decoder layers + for layer in self.layers: + x, attn = layer( + x, + encoder_out["encoder_out"] if encoder_out is not None else None, + encoder_out["encoder_padding_mask"] + if encoder_out is not None + else None, + incremental_state, + ) + inner_states.append(x) + + if self.normalize: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + + if self.adaptive_softmax is None: + # project back to size of vocabulary + if self.share_input_output_embed: + x = F.linear(x, self.embed_tokens.weight) + else: + x = F.linear(x, self.embed_out) + + return x, {"attn": attn, "inner_states": inner_states} + + def max_positions(self): + """Maximum output length supported by the decoder.""" + if self.embed_positions is None: + return self.max_target_positions + return min(self.max_target_positions, self.embed_positions.max_positions) + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + if ( + not hasattr(self, "_future_mask") + or self._future_mask is None + or self._future_mask.device != tensor.device + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(tensor.new(dim, dim)), 1 + ) + if self._future_mask.size(0) < dim: + self._future_mask = torch.triu( + utils.fill_with_neg_inf(self._future_mask.resize_(dim, dim)), 1 + ) + return self._future_mask[:dim, :dim] + + +class LightConvEncoderLayer(nn.Module): + """Encoder layer block. + + Args: + args (argparse.Namespace): parsed command-line arguments + kernel_size: kernel size of the convolution + """ + + def __init__(self, args, kernel_size=0): + super().__init__() + self.embed_dim = args.encoder_embed_dim + self.conv_dim = args.encoder_conv_dim + padding_l = ( + kernel_size // 2 + if kernel_size % 2 == 1 + else ((kernel_size - 1) // 2, kernel_size // 2) + ) + + if args.encoder_glu: + self.linear1 = Linear(self.embed_dim, 2 * self.conv_dim) + self.act = nn.GLU() + else: + self.linear1 = Linear(self.embed_dim, self.conv_dim) + self.act = None + if args.encoder_conv_type == "lightweight": + self.conv = LightweightConv( + self.conv_dim, + kernel_size, + padding_l=padding_l, + weight_softmax=args.weight_softmax, + num_heads=args.encoder_attention_heads, + weight_dropout=args.weight_dropout, + ) + elif args.encoder_conv_type == "dynamic": + self.conv = DynamicConv( + self.conv_dim, + kernel_size, + padding_l=padding_l, + weight_softmax=args.weight_softmax, + num_heads=args.encoder_attention_heads, + weight_dropout=args.weight_dropout, + ) + else: + raise NotImplementedError + self.linear2 = Linear(self.conv_dim, self.embed_dim) + + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.relu_dropout_module = FairseqDropout( + args.relu_dropout, module_name=self.__class__.__name__ + ) + self.input_dropout_module = FairseqDropout( + args.input_dropout, module_name=self.__class__.__name__ + ) + self.normalize_before = args.encoder_normalize_before + self.fc1 = Linear(self.embed_dim, args.encoder_ffn_embed_dim) + self.fc2 = Linear(args.encoder_ffn_embed_dim, self.embed_dim) + self.layer_norms = nn.ModuleList([LayerNorm(self.embed_dim) for _ in range(2)]) + + def forward(self, x, encoder_padding_mask): + """ + Args: + x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + encoder_padding_mask (ByteTensor): binary ByteTensor of shape + `(batch, src_len)` where padding elements are indicated by ``1``. + + Returns: + encoded output of shape `(batch, src_len, embed_dim)` + """ + residual = x + x = self.maybe_layer_norm(0, x, before=True) + x = self.input_dropout_module(x) + x = self.linear1(x) + if self.act is not None: + x = self.act(x) + if encoder_padding_mask is not None: + x = x.masked_fill(encoder_padding_mask.transpose(0, 1).unsqueeze(2), 0) + x = self.conv(x) + x = self.linear2(x) + x = self.dropout_module(x) + x = residual + x + x = self.maybe_layer_norm(0, x, after=True) + + residual = x + x = self.maybe_layer_norm(1, x, before=True) + x = F.relu(self.fc1(x)) + x = self.relu_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = residual + x + x = self.maybe_layer_norm(1, x, after=True) + return x + + def maybe_layer_norm(self, i, x, before=False, after=False): + assert before ^ after + if after ^ self.normalize_before: + return self.layer_norms[i](x) + else: + return x + + def extra_repr(self): + return ( + "dropout={}, relu_dropout={}, input_dropout={}, normalize_before={}".format( + self.dropout_module.p, + self.relu_dropout_module.p, + self.input_dropout_module.p, + self.normalize_before, + ) + ) + + +class LightConvDecoderLayer(nn.Module): + """Decoder layer block. + + Args: + args (argparse.Namespace): parsed command-line arguments + no_encoder_attn (bool, optional): whether to attend to encoder outputs. + Default: ``False`` + kernel_size: kernel size of the convolution + """ + + def __init__(self, args, no_encoder_attn=False, kernel_size=0): + super().__init__() + self.embed_dim = args.decoder_embed_dim + self.conv_dim = args.decoder_conv_dim + if args.decoder_glu: + self.linear1 = Linear(self.embed_dim, 2 * self.conv_dim) + self.act = nn.GLU() + else: + self.linear1 = Linear(self.embed_dim, self.conv_dim) + self.act = None + if args.decoder_conv_type == "lightweight": + self.conv = LightweightConv( + self.conv_dim, + kernel_size, + padding_l=kernel_size - 1, + weight_softmax=args.weight_softmax, + num_heads=args.decoder_attention_heads, + weight_dropout=args.weight_dropout, + ) + elif args.decoder_conv_type == "dynamic": + self.conv = DynamicConv( + self.conv_dim, + kernel_size, + padding_l=kernel_size - 1, + weight_softmax=args.weight_softmax, + num_heads=args.decoder_attention_heads, + weight_dropout=args.weight_dropout, + ) + else: + raise NotImplementedError + self.linear2 = Linear(self.conv_dim, self.embed_dim) + + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.relu_dropout_module = FairseqDropout( + args.relu_dropout, module_name=self.__class__.__name__ + ) + self.input_dropout_module = FairseqDropout( + args.input_dropout, module_name=self.__class__.__name__ + ) + self.normalize_before = args.decoder_normalize_before + + self.conv_layer_norm = LayerNorm(self.embed_dim) + + if no_encoder_attn: + self.encoder_attn = None + self.encoder_attn_layer_norm = None + else: + self.encoder_attn = MultiheadAttention( + self.embed_dim, + args.decoder_attention_heads, + dropout=args.attention_dropout, + encoder_decoder_attention=True, + ) + self.encoder_attn_layer_norm = LayerNorm(self.embed_dim) + + self.fc1 = Linear(self.embed_dim, args.decoder_ffn_embed_dim) + self.fc2 = Linear(args.decoder_ffn_embed_dim, self.embed_dim) + + self.final_layer_norm = LayerNorm(self.embed_dim) + self.need_attn = True + + def forward( + self, + x, + encoder_out, + encoder_padding_mask, + incremental_state, + prev_conv_state=None, + prev_attn_state=None, + conv_mask=None, + conv_padding_mask=None, + ): + """ + Args: + x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + encoder_padding_mask (ByteTensor): binary ByteTensor of shape + `(batch, src_len)` where padding elements are indicated by ``1``. + + Returns: + encoded output of shape `(batch, src_len, embed_dim)` + """ + residual = x + x = self.maybe_layer_norm(self.conv_layer_norm, x, before=True) + if prev_conv_state is not None: + if incremental_state is None: + incremental_state = {} + self.conv._set_input_buffer(incremental_state, prev_conv_state) + x = self.input_dropout_module(x) + x = self.linear1(x) + if self.act is not None: + x = self.act(x) + x = self.conv(x, incremental_state=incremental_state) + x = self.linear2(x) + x = self.dropout_module(x) + x = residual + x + x = self.maybe_layer_norm(self.conv_layer_norm, x, after=True) + + attn = None + if self.encoder_attn is not None: + residual = x + x = self.maybe_layer_norm(self.encoder_attn_layer_norm, x, before=True) + if prev_attn_state is not None: + if incremental_state is None: + incremental_state = {} + prev_key, prev_value = prev_attn_state + saved_state = {"prev_key": prev_key, "prev_value": prev_value} + self.encoder_attn._set_input_buffer(incremental_state, saved_state) + x, attn = self.encoder_attn( + query=x, + key=encoder_out, + value=encoder_out, + key_padding_mask=encoder_padding_mask, + incremental_state=incremental_state, + static_kv=True, + need_weights=(not self.training and self.need_attn), + ) + x = self.dropout_module(x) + x = residual + x + x = self.maybe_layer_norm(self.encoder_attn_layer_norm, x, after=True) + + residual = x + x = self.maybe_layer_norm(self.final_layer_norm, x, before=True) + x = F.relu(self.fc1(x)) + x = self.relu_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = residual + x + x = self.maybe_layer_norm(self.final_layer_norm, x, after=True) + return x, attn + + def maybe_layer_norm(self, layer_norm, x, before=False, after=False): + assert before ^ after + if after ^ self.normalize_before: + return layer_norm(x) + else: + return x + + def make_generation_fast_(self, need_attn=False, **kwargs): + self.need_attn = need_attn + + def extra_repr(self): + return ( + "dropout={}, relu_dropout={}, input_dropout={}, normalize_before={}".format( + self.dropout_module.p, + self.relu_dropout_module.p, + self.input_dropout_module.p, + self.normalize_before, + ) + ) + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.normal_(m.weight, mean=0, std=embedding_dim ** -0.5) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m + + +@register_model_architecture("lightconv", "lightconv") +def base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 7) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.relu_dropout = getattr(args, "relu_dropout", 0.0) + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + args.encoder_conv_dim = getattr(args, "encoder_conv_dim", args.encoder_embed_dim) + args.decoder_conv_dim = getattr(args, "decoder_conv_dim", args.decoder_embed_dim) + + args.encoder_kernel_size_list = getattr( + args, "encoder_kernel_size_list", [3, 7, 15, 31, 31, 31, 31] + ) + args.decoder_kernel_size_list = getattr( + args, "decoder_kernel_size_list", [3, 7, 15, 31, 31, 31] + ) + if len(args.encoder_kernel_size_list) == 1: + args.encoder_kernel_size_list = ( + args.encoder_kernel_size_list * args.encoder_layers + ) + if len(args.decoder_kernel_size_list) == 1: + args.decoder_kernel_size_list = ( + args.decoder_kernel_size_list * args.decoder_layers + ) + assert ( + len(args.encoder_kernel_size_list) == args.encoder_layers + ), "encoder_kernel_size_list doesn't match encoder_layers" + assert ( + len(args.decoder_kernel_size_list) == args.decoder_layers + ), "decoder_kernel_size_list doesn't match decoder_layers" + args.encoder_glu = getattr(args, "encoder_glu", True) + args.decoder_glu = getattr(args, "decoder_glu", True) + args.input_dropout = getattr(args, "input_dropout", 0.1) + args.weight_dropout = getattr(args, "weight_dropout", args.attention_dropout) + + +@register_model_architecture("lightconv", "lightconv_iwslt_de_en") +def lightconv_iwslt_de_en(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.encoder_layers = getattr(args, "encoder_layers", 7) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 1024) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.weight_dropout = getattr(args, "weight_dropout", 0.1) + args.encoder_glu = getattr(args, "encoder_glu", False) + args.decoder_glu = getattr(args, "decoder_glu", False) + args.input_dropout = getattr(args, "input_dropout", 0.0) + base_architecture(args) + + +@register_model_architecture("lightconv", "lightconv_wmt_en_de") +def lightconv_wmt_en_de(args): + base_architecture(args) + + +@register_model_architecture("lightconv", "lightconv_wmt_en_de_big") +def lightconv_wmt_en_de_big(args): + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.3) + base_architecture(args) + + +@register_model_architecture("lightconv", "lightconv_wmt_en_fr_big") +def lightconv_wmt_en_fr_big(args): + args.dropout = getattr(args, "dropout", 0.1) + lightconv_wmt_en_de_big(args) + + +@register_model_architecture("lightconv", "lightconv_wmt_zh_en_big") +def lightconv_wmt_zh_en_big(args): + args.dropout = getattr(args, "dropout", 0.2) + args.attention_dropout = getattr(args, "attention_dropout", 0.2) + args.weight_dropout = getattr(args, "weight_dropout", 0.2) + lightconv_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/fairseq/models/lightconv_lm.py b/fairseq-tools/fairseq/fairseq/models/lightconv_lm.py new file mode 100644 index 00000000..1d9efc4e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/lightconv_lm.py @@ -0,0 +1,306 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import utils +from fairseq.models import ( + FairseqLanguageModel, + register_model, + register_model_architecture, +) +from fairseq.models.lightconv import Embedding, LightConvDecoder +from fairseq.modules import AdaptiveInput, CharacterTokenEmbedder + + +@register_model("lightconv_lm") +class LightConvLanguageModel(FairseqLanguageModel): + def __init__(self, decoder): + super().__init__(decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--dropout", + default=0.1, + type=float, + metavar="D", + help="dropout probability", + ) + parser.add_argument( + "--attention-dropout", + default=0.0, + type=float, + metavar="D", + help="dropout probability for attention weights", + ) + parser.add_argument( + "--relu-dropout", + default=0.0, + type=float, + metavar="D", + help="dropout probability after ReLU in FFN", + ) + parser.add_argument( + "--input-dropout", + type=float, + metavar="D", + help="dropout probability of the inputs", + ) + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-output-dim", + type=int, + metavar="N", + help="decoder output dimension", + ) + parser.add_argument( + "--decoder-input-dim", type=int, metavar="N", help="decoder input dimension" + ) + parser.add_argument( + "--decoder-ffn-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension for FFN", + ) + parser.add_argument( + "--decoder-layers", type=int, metavar="N", help="num decoder layers" + ) + parser.add_argument( + "--decoder-attention-heads", + type=int, + metavar="N", + help="num decoder attention heads or LightConv/DynamicConv heads", + ) + parser.add_argument( + "--decoder-normalize-before", + default=False, + action="store_true", + help="apply layernorm before each decoder block", + ) + parser.add_argument( + "--adaptive-softmax-cutoff", + metavar="EXPR", + help="comma separated list of adaptive softmax cutoff points. " + "Must be used with adaptive_loss criterion", + ) + parser.add_argument( + "--adaptive-softmax-dropout", + type=float, + metavar="D", + help="sets adaptive softmax dropout for the tail projections", + ) + parser.add_argument( + "--adaptive-softmax-factor", + type=float, + metavar="N", + help="adaptive input factor", + ) + parser.add_argument( + "--no-token-positional-embeddings", + default=False, + action="store_true", + help="if set, disables positional embeddings (outside self attention)", + ) + parser.add_argument( + "--share-decoder-input-output-embed", + default=False, + action="store_true", + help="share decoder input and output embeddings", + ) + parser.add_argument( + "--character-embeddings", + default=False, + action="store_true", + help="if set, uses character embedding convolutions to produce token embeddings", + ) + parser.add_argument( + "--character-filters", + type=str, + metavar="LIST", + default="[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]", + help="size of character embeddings", + ) + parser.add_argument( + "--character-embedding-dim", + type=int, + metavar="N", + default=4, + help="size of character embeddings", + ) + parser.add_argument( + "--char-embedder-highway-layers", + type=int, + metavar="N", + default=2, + help="number of highway layers for character token embeddder", + ) + parser.add_argument( + "--adaptive-input", + default=False, + action="store_true", + help="if set, uses adaptive input", + ) + parser.add_argument( + "--adaptive-input-factor", + type=float, + metavar="N", + help="adaptive input factor", + ) + parser.add_argument( + "--adaptive-input-cutoff", + metavar="EXPR", + help="comma separated list of adaptive input cutoff points.", + ) + parser.add_argument( + "--tie-adaptive-weights", + action="store_true", + help="if set, ties the weights of adaptive softmax and adaptive input", + ) + parser.add_argument( + "--tie-adaptive-proj", + action="store_true", + help="if set, ties the projection weights of adaptive softmax and adaptive input", + ) + parser.add_argument( + "--decoder-learned-pos", + action="store_true", + help="use learned positional embeddings in the decoder", + ) + + """LightConv and DynamicConv arguments""" + parser.add_argument( + "--decoder-kernel-size-list", + type=lambda x: utils.eval_str_list(x, int), + help='list of kernel size (default: "[3,7,15,31,31,31]")', + ) + parser.add_argument( + "--decoder-glu", type=utils.eval_bool, help="glu after in proj" + ) + parser.add_argument( + "--decoder-conv-type", + default="dynamic", + type=str, + choices=["dynamic", "lightweight"], + help="type of convolution", + ) + parser.add_argument("--weight-softmax", default=True, type=utils.eval_bool) + parser.add_argument( + "--weight-dropout", + type=float, + metavar="D", + help="dropout probability for conv weights", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_lm_architecture(args) + + if getattr(args, "max_source_positions", None) is None: + args.max_source_positions = args.tokens_per_sample + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = args.tokens_per_sample + + if args.character_embeddings: + embed_tokens = CharacterTokenEmbedder( + task.dictionary, + eval(args.character_filters), + args.character_embedding_dim, + args.decoder_embed_dim, + args.char_embedder_highway_layers, + ) + elif args.adaptive_input: + embed_tokens = AdaptiveInput( + len(task.dictionary), + task.dictionary.pad(), + args.decoder_input_dim, + args.adaptive_input_factor, + args.decoder_embed_dim, + utils.eval_str_list(args.adaptive_input_cutoff, type=int), + ) + else: + embed_tokens = Embedding( + len(task.dictionary), args.decoder_input_dim, task.dictionary.pad() + ) + + if args.tie_adaptive_weights: + assert args.adaptive_input + assert args.adaptive_input_factor == args.adaptive_softmax_factor + assert ( + args.adaptive_softmax_cutoff == args.adaptive_input_cutoff + ), "{} != {}".format( + args.adaptive_softmax_cutoff, args.adaptive_input_cutoff + ) + assert args.decoder_input_dim == args.decoder_output_dim + + decoder = LightConvDecoder( + args, + task.output_dictionary, + embed_tokens, + no_encoder_attn=True, + final_norm=False, + ) + return LightConvLanguageModel(decoder) + + +@register_model_architecture("lightconv_lm", "lightconv_lm") +def base_lm_architecture(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 2048) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.adaptive_softmax_factor = getattr(args, "adaptive_softmax_factor", 4) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + + args.character_embeddings = getattr(args, "character_embeddings", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + args.decoder_conv_dim = getattr(args, "decoder_conv_dim", args.decoder_embed_dim) + + # The model training is not stable without this + args.decoder_normalize_before = True + + args.adaptive_input = getattr(args, "adaptive_input", False) + args.adaptive_input_factor = getattr(args, "adaptive_input_factor", 4) + args.adaptive_input_cutoff = getattr(args, "adaptive_input_cutoff", None) + + args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False) + args.tie_adaptive_proj = getattr(args, "tie_adaptive_proj", False) + + args.decoder_kernel_size_list = getattr( + args, "decoder_kernel_size_list", [3, 7, 15, 31, 31, 31] + ) + if len(args.decoder_kernel_size_list) == 1: + args.decoder_kernel_size_list = ( + args.decoder_kernel_size_list * args.decoder_layers + ) + assert ( + len(args.decoder_kernel_size_list) == args.decoder_layers + ), "decoder_kernel_size_list doesn't match decoder_layers" + args.decoder_glu = getattr(args, "decoder_glu", True) + args.input_dropout = getattr(args, "input_dropout", 0.1) + args.weight_dropout = getattr(args, "weight_dropout", args.attention_dropout) + + +@register_model_architecture("lightconv_lm", "lightconv_lm_gbw") +def lightconv_lm_gbw(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + base_lm_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/lstm.py b/fairseq-tools/fairseq/fairseq/models/lstm.py new file mode 100644 index 00000000..1a9dca3c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/lstm.py @@ -0,0 +1,753 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.modules import AdaptiveSoftmax, FairseqDropout +from torch import Tensor + + +DEFAULT_MAX_SOURCE_POSITIONS = 1e5 +DEFAULT_MAX_TARGET_POSITIONS = 1e5 + + +@register_model("lstm") +class LSTMModel(FairseqEncoderDecoderModel): + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--encoder-embed-dim', type=int, metavar='N', + help='encoder embedding dimension') + parser.add_argument('--encoder-embed-path', type=str, metavar='STR', + help='path to pre-trained encoder embedding') + parser.add_argument('--encoder-freeze-embed', action='store_true', + help='freeze encoder embeddings') + parser.add_argument('--encoder-hidden-size', type=int, metavar='N', + help='encoder hidden size') + parser.add_argument('--encoder-layers', type=int, metavar='N', + help='number of encoder layers') + parser.add_argument('--encoder-bidirectional', action='store_true', + help='make all layers of encoder bidirectional') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-embed-path', type=str, metavar='STR', + help='path to pre-trained decoder embedding') + parser.add_argument('--decoder-freeze-embed', action='store_true', + help='freeze decoder embeddings') + parser.add_argument('--decoder-hidden-size', type=int, metavar='N', + help='decoder hidden size') + parser.add_argument('--decoder-layers', type=int, metavar='N', + help='number of decoder layers') + parser.add_argument('--decoder-out-embed-dim', type=int, metavar='N', + help='decoder output embedding dimension') + parser.add_argument('--decoder-attention', type=str, metavar='BOOL', + help='decoder attention') + parser.add_argument('--adaptive-softmax-cutoff', metavar='EXPR', + help='comma separated list of adaptive softmax cutoff points. ' + 'Must be used with adaptive_loss criterion') + parser.add_argument('--share-decoder-input-output-embed', default=False, + action='store_true', + help='share decoder input and output embeddings') + parser.add_argument('--share-all-embeddings', default=False, action='store_true', + help='share encoder, decoder and output embeddings' + ' (requires shared dictionary and embed dim)') + + # Granular dropout settings (if not specified these default to --dropout) + parser.add_argument('--encoder-dropout-in', type=float, metavar='D', + help='dropout probability for encoder input embedding') + parser.add_argument('--encoder-dropout-out', type=float, metavar='D', + help='dropout probability for encoder output') + parser.add_argument('--decoder-dropout-in', type=float, metavar='D', + help='dropout probability for decoder input embedding') + parser.add_argument('--decoder-dropout-out', type=float, metavar='D', + help='dropout probability for decoder output') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + # make sure that all args are properly defaulted (in case there are any new ones) + base_architecture(args) + + if args.encoder_layers != args.decoder_layers: + raise ValueError("--encoder-layers must match --decoder-layers") + + max_source_positions = getattr( + args, "max_source_positions", DEFAULT_MAX_SOURCE_POSITIONS + ) + max_target_positions = getattr( + args, "max_target_positions", DEFAULT_MAX_TARGET_POSITIONS + ) + + def load_pretrained_embedding_from_file(embed_path, dictionary, embed_dim): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx) + embed_dict = utils.parse_embedding(embed_path) + utils.print_embed_overlap(embed_dict, dictionary) + return utils.load_embedding(embed_dict, dictionary, embed_tokens) + + if args.encoder_embed_path: + pretrained_encoder_embed = load_pretrained_embedding_from_file( + args.encoder_embed_path, task.source_dictionary, args.encoder_embed_dim + ) + else: + num_embeddings = len(task.source_dictionary) + pretrained_encoder_embed = Embedding( + num_embeddings, args.encoder_embed_dim, task.source_dictionary.pad() + ) + + if args.share_all_embeddings: + # double check all parameters combinations are valid + if task.source_dictionary != task.target_dictionary: + raise ValueError("--share-all-embeddings requires a joint dictionary") + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise ValueError( + "--share-all-embed not compatible with --decoder-embed-path" + ) + if args.encoder_embed_dim != args.decoder_embed_dim: + raise ValueError( + "--share-all-embeddings requires --encoder-embed-dim to " + "match --decoder-embed-dim" + ) + pretrained_decoder_embed = pretrained_encoder_embed + args.share_decoder_input_output_embed = True + else: + # separate decoder input embeddings + pretrained_decoder_embed = None + if args.decoder_embed_path: + pretrained_decoder_embed = load_pretrained_embedding_from_file( + args.decoder_embed_path, + task.target_dictionary, + args.decoder_embed_dim, + ) + # one last double check of parameter combinations + if args.share_decoder_input_output_embed and ( + args.decoder_embed_dim != args.decoder_out_embed_dim + ): + raise ValueError( + "--share-decoder-input-output-embeddings requires " + "--decoder-embed-dim to match --decoder-out-embed-dim" + ) + + if args.encoder_freeze_embed: + pretrained_encoder_embed.weight.requires_grad = False + if args.decoder_freeze_embed: + pretrained_decoder_embed.weight.requires_grad = False + + encoder = LSTMEncoder( + dictionary=task.source_dictionary, + embed_dim=args.encoder_embed_dim, + hidden_size=args.encoder_hidden_size, + num_layers=args.encoder_layers, + dropout_in=args.encoder_dropout_in, + dropout_out=args.encoder_dropout_out, + bidirectional=args.encoder_bidirectional, + pretrained_embed=pretrained_encoder_embed, + max_source_positions=max_source_positions, + ) + decoder = LSTMDecoder( + dictionary=task.target_dictionary, + embed_dim=args.decoder_embed_dim, + hidden_size=args.decoder_hidden_size, + out_embed_dim=args.decoder_out_embed_dim, + num_layers=args.decoder_layers, + dropout_in=args.decoder_dropout_in, + dropout_out=args.decoder_dropout_out, + attention=utils.eval_bool(args.decoder_attention), + encoder_output_units=encoder.output_units, + pretrained_embed=pretrained_decoder_embed, + share_input_output_embed=args.share_decoder_input_output_embed, + adaptive_softmax_cutoff=( + utils.eval_str_list(args.adaptive_softmax_cutoff, type=int) + if args.criterion == "adaptive_loss" + else None + ), + max_target_positions=max_target_positions, + residuals=False, + ) + return cls(encoder, decoder) + + def forward( + self, + src_tokens, + src_lengths, + prev_output_tokens, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + ): + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths) + decoder_out = self.decoder( + prev_output_tokens, + encoder_out=encoder_out, + incremental_state=incremental_state, + ) + return decoder_out + + +class LSTMEncoder(FairseqEncoder): + """LSTM encoder.""" + + def __init__( + self, + dictionary, + embed_dim=512, + hidden_size=512, + num_layers=1, + dropout_in=0.1, + dropout_out=0.1, + bidirectional=False, + left_pad=True, + pretrained_embed=None, + padding_idx=None, + max_source_positions=DEFAULT_MAX_SOURCE_POSITIONS, + ): + super().__init__(dictionary) + self.num_layers = num_layers + self.dropout_in_module = FairseqDropout( + dropout_in, module_name=self.__class__.__name__ + ) + self.dropout_out_module = FairseqDropout( + dropout_out, module_name=self.__class__.__name__ + ) + self.bidirectional = bidirectional + self.hidden_size = hidden_size + self.max_source_positions = max_source_positions + + num_embeddings = len(dictionary) + self.padding_idx = padding_idx if padding_idx is not None else dictionary.pad() + if pretrained_embed is None: + self.embed_tokens = Embedding(num_embeddings, embed_dim, self.padding_idx) + else: + self.embed_tokens = pretrained_embed + + self.lstm = LSTM( + input_size=embed_dim, + hidden_size=hidden_size, + num_layers=num_layers, + dropout=self.dropout_out_module.p if num_layers > 1 else 0.0, + bidirectional=bidirectional, + ) + self.left_pad = left_pad + + self.output_units = hidden_size + if bidirectional: + self.output_units *= 2 + + def forward( + self, + src_tokens: Tensor, + src_lengths: Tensor, + enforce_sorted: bool = True, + ): + """ + Args: + src_tokens (LongTensor): tokens in the source language of + shape `(batch, src_len)` + src_lengths (LongTensor): lengths of each source sentence of + shape `(batch)` + enforce_sorted (bool, optional): if True, `src_tokens` is + expected to contain sequences sorted by length in a + decreasing order. If False, this condition is not + required. Default: True. + """ + if self.left_pad: + # nn.utils.rnn.pack_padded_sequence requires right-padding; + # convert left-padding to right-padding + src_tokens = utils.convert_padding_direction( + src_tokens, + torch.zeros_like(src_tokens).fill_(self.padding_idx), + left_to_right=True, + ) + + bsz, seqlen = src_tokens.size() + + # embed tokens + x = self.embed_tokens(src_tokens) + x = self.dropout_in_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # pack embedded source tokens into a PackedSequence + packed_x = nn.utils.rnn.pack_padded_sequence( + x, src_lengths.cpu(), enforce_sorted=enforce_sorted + ) + + # apply LSTM + if self.bidirectional: + state_size = 2 * self.num_layers, bsz, self.hidden_size + else: + state_size = self.num_layers, bsz, self.hidden_size + h0 = x.new_zeros(*state_size) + c0 = x.new_zeros(*state_size) + packed_outs, (final_hiddens, final_cells) = self.lstm(packed_x, (h0, c0)) + + # unpack outputs and apply dropout + x, _ = nn.utils.rnn.pad_packed_sequence( + packed_outs, padding_value=self.padding_idx * 1.0 + ) + x = self.dropout_out_module(x) + assert list(x.size()) == [seqlen, bsz, self.output_units] + + if self.bidirectional: + final_hiddens = self.combine_bidir(final_hiddens, bsz) + final_cells = self.combine_bidir(final_cells, bsz) + + encoder_padding_mask = src_tokens.eq(self.padding_idx).t() + + return tuple( + ( + x, # seq_len x batch x hidden + final_hiddens, # num_layers x batch x num_directions*hidden + final_cells, # num_layers x batch x num_directions*hidden + encoder_padding_mask, # seq_len x batch + ) + ) + + def combine_bidir(self, outs, bsz: int): + out = outs.view(self.num_layers, 2, bsz, -1).transpose(1, 2).contiguous() + return out.view(self.num_layers, bsz, -1) + + def reorder_encoder_out(self, encoder_out, new_order): + return tuple( + ( + encoder_out[0].index_select(1, new_order), + encoder_out[1].index_select(1, new_order), + encoder_out[2].index_select(1, new_order), + encoder_out[3].index_select(1, new_order), + ) + ) + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return self.max_source_positions + + +class AttentionLayer(nn.Module): + def __init__(self, input_embed_dim, source_embed_dim, output_embed_dim, bias=False): + super().__init__() + + self.input_proj = Linear(input_embed_dim, source_embed_dim, bias=bias) + self.output_proj = Linear( + input_embed_dim + source_embed_dim, output_embed_dim, bias=bias + ) + + def forward(self, input, source_hids, encoder_padding_mask): + # input: bsz x input_embed_dim + # source_hids: srclen x bsz x source_embed_dim + + # x: bsz x source_embed_dim + x = self.input_proj(input) + + # compute attention + attn_scores = (source_hids * x.unsqueeze(0)).sum(dim=2) + + # don't attend over padding + if encoder_padding_mask is not None: + attn_scores = ( + attn_scores.float() + .masked_fill_(encoder_padding_mask, float("-inf")) + .type_as(attn_scores) + ) # FP16 support: cast to float and back + + attn_scores = F.softmax(attn_scores, dim=0) # srclen x bsz + + # sum weighted sources + x = (attn_scores.unsqueeze(2) * source_hids).sum(dim=0) + + x = torch.tanh(self.output_proj(torch.cat((x, input), dim=1))) + return x, attn_scores + + +class LSTMDecoder(FairseqIncrementalDecoder): + """LSTM decoder.""" + + def __init__( + self, + dictionary, + embed_dim=512, + hidden_size=512, + out_embed_dim=512, + num_layers=1, + dropout_in=0.1, + dropout_out=0.1, + attention=True, + encoder_output_units=512, + pretrained_embed=None, + share_input_output_embed=False, + adaptive_softmax_cutoff=None, + max_target_positions=DEFAULT_MAX_TARGET_POSITIONS, + residuals=False, + ): + super().__init__(dictionary) + self.dropout_in_module = FairseqDropout( + dropout_in, module_name=self.__class__.__name__ + ) + self.dropout_out_module = FairseqDropout( + dropout_out, module_name=self.__class__.__name__ + ) + self.hidden_size = hidden_size + self.share_input_output_embed = share_input_output_embed + self.need_attn = True + self.max_target_positions = max_target_positions + self.residuals = residuals + self.num_layers = num_layers + + self.adaptive_softmax = None + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + if pretrained_embed is None: + self.embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx) + else: + self.embed_tokens = pretrained_embed + + self.encoder_output_units = encoder_output_units + if encoder_output_units != hidden_size and encoder_output_units != 0: + self.encoder_hidden_proj = Linear(encoder_output_units, hidden_size) + self.encoder_cell_proj = Linear(encoder_output_units, hidden_size) + else: + self.encoder_hidden_proj = self.encoder_cell_proj = None + + # disable input feeding if there is no encoder + # input feeding is described in arxiv.org/abs/1508.04025 + input_feed_size = 0 if encoder_output_units == 0 else hidden_size + self.layers = nn.ModuleList( + [ + LSTMCell( + input_size=input_feed_size + embed_dim + if layer == 0 + else hidden_size, + hidden_size=hidden_size, + ) + for layer in range(num_layers) + ] + ) + + if attention: + # TODO make bias configurable + self.attention = AttentionLayer( + hidden_size, encoder_output_units, hidden_size, bias=False + ) + else: + self.attention = None + + if hidden_size != out_embed_dim: + self.additional_fc = Linear(hidden_size, out_embed_dim) + + if adaptive_softmax_cutoff is not None: + # setting adaptive_softmax dropout to dropout_out for now but can be redefined + self.adaptive_softmax = AdaptiveSoftmax( + num_embeddings, + hidden_size, + adaptive_softmax_cutoff, + dropout=dropout_out, + ) + elif not self.share_input_output_embed: + self.fc_out = Linear(out_embed_dim, num_embeddings, dropout=dropout_out) + + def forward( + self, + prev_output_tokens, + encoder_out: Optional[Tuple[Tensor, Tensor, Tensor, Tensor]] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + src_lengths: Optional[Tensor] = None, + ): + x, attn_scores = self.extract_features( + prev_output_tokens, encoder_out, incremental_state + ) + return self.output_layer(x), attn_scores + + def extract_features( + self, + prev_output_tokens, + encoder_out: Optional[Tuple[Tensor, Tensor, Tensor, Tensor]] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + ): + """ + Similar to *forward* but only return features. + """ + # get outputs from encoder + if encoder_out is not None: + encoder_outs = encoder_out[0] + encoder_hiddens = encoder_out[1] + encoder_cells = encoder_out[2] + encoder_padding_mask = encoder_out[3] + else: + encoder_outs = torch.empty(0) + encoder_hiddens = torch.empty(0) + encoder_cells = torch.empty(0) + encoder_padding_mask = torch.empty(0) + srclen = encoder_outs.size(0) + + if incremental_state is not None and len(incremental_state) > 0: + prev_output_tokens = prev_output_tokens[:, -1:] + + bsz, seqlen = prev_output_tokens.size() + + # embed tokens + x = self.embed_tokens(prev_output_tokens) + x = self.dropout_in_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # initialize previous states (or get from cache during incremental generation) + if incremental_state is not None and len(incremental_state) > 0: + prev_hiddens, prev_cells, input_feed = self.get_cached_state( + incremental_state + ) + elif encoder_out is not None: + # setup recurrent cells + prev_hiddens = [encoder_hiddens[i] for i in range(self.num_layers)] + prev_cells = [encoder_cells[i] for i in range(self.num_layers)] + if self.encoder_hidden_proj is not None: + prev_hiddens = [self.encoder_hidden_proj(y) for y in prev_hiddens] + prev_cells = [self.encoder_cell_proj(y) for y in prev_cells] + input_feed = x.new_zeros(bsz, self.hidden_size) + else: + # setup zero cells, since there is no encoder + zero_state = x.new_zeros(bsz, self.hidden_size) + prev_hiddens = [zero_state for i in range(self.num_layers)] + prev_cells = [zero_state for i in range(self.num_layers)] + input_feed = None + + assert ( + srclen > 0 or self.attention is None + ), "attention is not supported if there are no encoder outputs" + attn_scores = ( + x.new_zeros(srclen, seqlen, bsz) if self.attention is not None else None + ) + outs = [] + for j in range(seqlen): + # input feeding: concatenate context vector from previous time step + if input_feed is not None: + input = torch.cat((x[j, :, :], input_feed), dim=1) + else: + input = x[j] + + for i, rnn in enumerate(self.layers): + # recurrent cell + hidden, cell = rnn(input, (prev_hiddens[i], prev_cells[i])) + + # hidden state becomes the input to the next layer + input = self.dropout_out_module(hidden) + if self.residuals: + input = input + prev_hiddens[i] + + # save state for next time step + prev_hiddens[i] = hidden + prev_cells[i] = cell + + # apply attention using the last layer's hidden state + if self.attention is not None: + assert attn_scores is not None + out, attn_scores[:, j, :] = self.attention( + hidden, encoder_outs, encoder_padding_mask + ) + else: + out = hidden + out = self.dropout_out_module(out) + + # input feeding + if input_feed is not None: + input_feed = out + + # save final output + outs.append(out) + + # Stack all the necessary tensors together and store + prev_hiddens_tensor = torch.stack(prev_hiddens) + prev_cells_tensor = torch.stack(prev_cells) + cache_state = torch.jit.annotate( + Dict[str, Optional[Tensor]], + { + "prev_hiddens": prev_hiddens_tensor, + "prev_cells": prev_cells_tensor, + "input_feed": input_feed, + }, + ) + self.set_incremental_state(incremental_state, "cached_state", cache_state) + + # collect outputs across time steps + x = torch.cat(outs, dim=0).view(seqlen, bsz, self.hidden_size) + + # T x B x C -> B x T x C + x = x.transpose(1, 0) + + if hasattr(self, "additional_fc") and self.adaptive_softmax is None: + x = self.additional_fc(x) + x = self.dropout_out_module(x) + # srclen x tgtlen x bsz -> bsz x tgtlen x srclen + if not self.training and self.need_attn and self.attention is not None: + assert attn_scores is not None + attn_scores = attn_scores.transpose(0, 2) + else: + attn_scores = None + return x, attn_scores + + def output_layer(self, x): + """Project features to the vocabulary size.""" + if self.adaptive_softmax is None: + if self.share_input_output_embed: + x = F.linear(x, self.embed_tokens.weight) + else: + x = self.fc_out(x) + return x + + def get_cached_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + ) -> Tuple[List[Tensor], List[Tensor], Optional[Tensor]]: + cached_state = self.get_incremental_state(incremental_state, "cached_state") + assert cached_state is not None + prev_hiddens_ = cached_state["prev_hiddens"] + assert prev_hiddens_ is not None + prev_cells_ = cached_state["prev_cells"] + assert prev_cells_ is not None + prev_hiddens = [prev_hiddens_[i] for i in range(self.num_layers)] + prev_cells = [prev_cells_[j] for j in range(self.num_layers)] + input_feed = cached_state[ + "input_feed" + ] # can be None for decoder-only language models + return prev_hiddens, prev_cells, input_feed + + def reorder_incremental_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + if incremental_state is None or len(incremental_state) == 0: + return + prev_hiddens, prev_cells, input_feed = self.get_cached_state(incremental_state) + prev_hiddens = [p.index_select(0, new_order) for p in prev_hiddens] + prev_cells = [p.index_select(0, new_order) for p in prev_cells] + if input_feed is not None: + input_feed = input_feed.index_select(0, new_order) + cached_state_new = torch.jit.annotate( + Dict[str, Optional[Tensor]], + { + "prev_hiddens": torch.stack(prev_hiddens), + "prev_cells": torch.stack(prev_cells), + "input_feed": input_feed, + }, + ) + self.set_incremental_state(incremental_state, "cached_state", cached_state_new), + return + + def max_positions(self): + """Maximum output length supported by the decoder.""" + return self.max_target_positions + + def make_generation_fast_(self, need_attn=False, **kwargs): + self.need_attn = need_attn + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.uniform_(m.weight, -0.1, 0.1) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def LSTM(input_size, hidden_size, **kwargs): + m = nn.LSTM(input_size, hidden_size, **kwargs) + for name, param in m.named_parameters(): + if "weight" in name or "bias" in name: + param.data.uniform_(-0.1, 0.1) + return m + + +def LSTMCell(input_size, hidden_size, **kwargs): + m = nn.LSTMCell(input_size, hidden_size, **kwargs) + for name, param in m.named_parameters(): + if "weight" in name or "bias" in name: + param.data.uniform_(-0.1, 0.1) + return m + + +def Linear(in_features, out_features, bias=True, dropout=0.0): + """Linear layer (input: N x T x C)""" + m = nn.Linear(in_features, out_features, bias=bias) + m.weight.data.uniform_(-0.1, 0.1) + if bias: + m.bias.data.uniform_(-0.1, 0.1) + return m + + +@register_model_architecture("lstm", "lstm") +def base_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_freeze_embed = getattr(args, "encoder_freeze_embed", False) + args.encoder_hidden_size = getattr( + args, "encoder_hidden_size", args.encoder_embed_dim + ) + args.encoder_layers = getattr(args, "encoder_layers", 1) + args.encoder_bidirectional = getattr(args, "encoder_bidirectional", False) + args.encoder_dropout_in = getattr(args, "encoder_dropout_in", args.dropout) + args.encoder_dropout_out = getattr(args, "encoder_dropout_out", args.dropout) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_freeze_embed = getattr(args, "decoder_freeze_embed", False) + args.decoder_hidden_size = getattr( + args, "decoder_hidden_size", args.decoder_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 1) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 512) + args.decoder_attention = getattr(args, "decoder_attention", "1") + args.decoder_dropout_in = getattr(args, "decoder_dropout_in", args.dropout) + args.decoder_dropout_out = getattr(args, "decoder_dropout_out", args.dropout) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.adaptive_softmax_cutoff = getattr( + args, "adaptive_softmax_cutoff", "10000,50000,200000" + ) + + +@register_model_architecture("lstm", "lstm_wiseman_iwslt_de_en") +def lstm_wiseman_iwslt_de_en(args): + args.dropout = getattr(args, "dropout", 0.1) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 256) + args.encoder_dropout_in = getattr(args, "encoder_dropout_in", 0) + args.encoder_dropout_out = getattr(args, "encoder_dropout_out", 0) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 256) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 256) + args.decoder_dropout_in = getattr(args, "decoder_dropout_in", 0) + args.decoder_dropout_out = getattr(args, "decoder_dropout_out", args.dropout) + base_architecture(args) + + +@register_model_architecture("lstm", "lstm_luong_wmt_en_de") +def lstm_luong_wmt_en_de(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1000) + args.encoder_layers = getattr(args, "encoder_layers", 4) + args.encoder_dropout_out = getattr(args, "encoder_dropout_out", 0) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1000) + args.decoder_layers = getattr(args, "decoder_layers", 4) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 1000) + args.decoder_dropout_out = getattr(args, "decoder_dropout_out", 0) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/lstm_lm.py b/fairseq-tools/fairseq/fairseq/models/lstm_lm.py new file mode 100644 index 00000000..454f0ac3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/lstm_lm.py @@ -0,0 +1,142 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq import utils +from fairseq.models import ( + FairseqLanguageModel, + register_model, + register_model_architecture, +) +from fairseq.models.lstm import Embedding, LSTMDecoder + + +DEFAULT_MAX_TARGET_POSITIONS = 1e5 + + +@register_model("lstm_lm") +class LSTMLanguageModel(FairseqLanguageModel): + def __init__(self, decoder): + super().__init__(decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-embed-path', type=str, metavar='STR', + help='path to pre-trained decoder embedding') + parser.add_argument('--decoder-hidden-size', type=int, metavar='N', + help='decoder hidden size') + parser.add_argument('--decoder-layers', type=int, metavar='N', + help='number of decoder layers') + parser.add_argument('--decoder-out-embed-dim', type=int, metavar='N', + help='decoder output embedding dimension') + parser.add_argument('--decoder-attention', type=str, metavar='BOOL', + help='decoder attention') + parser.add_argument('--adaptive-softmax-cutoff', metavar='EXPR', + help='comma separated list of adaptive softmax cutoff points. ' + 'Must be used with adaptive_loss criterion') + parser.add_argument('--residuals', default=False, + action='store_true', + help='applying residuals between LSTM layers') + + # Granular dropout settings (if not specified these default to --dropout) + parser.add_argument('--decoder-dropout-in', type=float, metavar='D', + help='dropout probability for decoder input embedding') + parser.add_argument('--decoder-dropout-out', type=float, metavar='D', + help='dropout probability for decoder output') + parser.add_argument('--share-decoder-input-output-embed', default=False, + action='store_true', + help='share decoder input and output embeddings') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if getattr(args, "max_target_positions", None) is not None: + max_target_positions = args.max_target_positions + else: + max_target_positions = getattr( + args, "tokens_per_sample", DEFAULT_MAX_TARGET_POSITIONS + ) + + def load_pretrained_embedding_from_file(embed_path, dictionary, embed_dim): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + embed_tokens = Embedding(num_embeddings, embed_dim, padding_idx) + embed_dict = utils.parse_embedding(embed_path) + utils.print_embed_overlap(embed_dict, dictionary) + return utils.load_embedding(embed_dict, dictionary, embed_tokens) + + pretrained_decoder_embed = None + if args.decoder_embed_path: + pretrained_decoder_embed = load_pretrained_embedding_from_file( + args.decoder_embed_path, task.target_dictionary, args.decoder_embed_dim + ) + + if args.share_decoder_input_output_embed: + # double check all parameters combinations are valid + if task.source_dictionary != task.target_dictionary: + raise ValueError( + "--share-decoder-input-output-embeddings requires a joint dictionary" + ) + + if args.decoder_embed_dim != args.decoder_out_embed_dim: + raise ValueError( + "--share-decoder-input-output-embeddings requires " + "--decoder-embed-dim to match --decoder-out-embed-dim" + ) + + decoder = LSTMDecoder( + dictionary=task.dictionary, + embed_dim=args.decoder_embed_dim, + hidden_size=args.decoder_hidden_size, + out_embed_dim=args.decoder_out_embed_dim, + num_layers=args.decoder_layers, + dropout_in=args.decoder_dropout_in, + dropout_out=args.decoder_dropout_out, + attention=False, # decoder-only language model doesn't support attention + encoder_output_units=0, + pretrained_embed=pretrained_decoder_embed, + share_input_output_embed=args.share_decoder_input_output_embed, + adaptive_softmax_cutoff=( + utils.eval_str_list(args.adaptive_softmax_cutoff, type=int) + if args.criterion == "adaptive_loss" + else None + ), + max_target_positions=max_target_positions, + residuals=args.residuals, + ) + + return cls(decoder) + + +@register_model_architecture("lstm_lm", "lstm_lm") +def base_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_hidden_size = getattr( + args, "decoder_hidden_size", args.decoder_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 1) + args.decoder_out_embed_dim = getattr(args, "decoder_out_embed_dim", 512) + args.decoder_attention = getattr(args, "decoder_attention", "0") + args.decoder_dropout_in = getattr(args, "decoder_dropout_in", args.dropout) + args.decoder_dropout_out = getattr(args, "decoder_dropout_out", args.dropout) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.adaptive_softmax_cutoff = getattr( + args, "adaptive_softmax_cutoff", "10000,50000,200000" + ) + args.residuals = getattr(args, "residuals", False) diff --git a/fairseq-tools/fairseq/fairseq/models/masked_lm.py b/fairseq-tools/fairseq/fairseq/models/masked_lm.py new file mode 100644 index 00000000..c786de91 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/masked_lm.py @@ -0,0 +1,403 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderModel, + register_model, + register_model_architecture, +) +from fairseq.modules import ( + LayerNorm, + SinusoidalPositionalEmbedding, + TransformerSentenceEncoder, +) +from fairseq.modules.transformer_sentence_encoder import init_bert_params + + +logger = logging.getLogger(__name__) + + +@register_model("masked_lm") +class MaskedLMModel(FairseqEncoderModel): + """ + Class for training a Masked Language Model. It also supports an + additional sentence level prediction if the sent-loss argument is set. + """ + + def __init__(self, args, encoder): + super().__init__(encoder) + self.args = args + + # if specified then apply bert initialization on the model. We need + # to explictly call this to make sure that the output embeddings + # and projection layers are also correctly initialized + if getattr(args, "apply_bert_init", False): + self.apply(init_bert_params) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # Arguments related to dropout + parser.add_argument( + "--dropout", type=float, metavar="D", help="dropout probability" + ) + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for" " attention weights", + ) + parser.add_argument( + "--act-dropout", + type=float, + metavar="D", + help="dropout probability after" " activation in FFN", + ) + + # Arguments related to hidden states and self-attention + parser.add_argument( + "--encoder-ffn-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension for FFN", + ) + parser.add_argument( + "--encoder-layers", type=int, metavar="N", help="num encoder layers" + ) + parser.add_argument( + "--encoder-attention-heads", + type=int, + metavar="N", + help="num encoder attention heads", + ) + + # Arguments related to input and output embeddings + parser.add_argument( + "--encoder-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension", + ) + parser.add_argument( + "--share-encoder-input-output-embed", + action="store_true", + help="share encoder input" " and output embeddings", + ) + parser.add_argument( + "--encoder-learned-pos", + action="store_true", + help="use learned positional embeddings in the encoder", + ) + parser.add_argument( + "--no-token-positional-embeddings", + action="store_true", + help="if set, disables positional embeddings" " (outside self attention)", + ) + parser.add_argument( + "--num-segment", type=int, metavar="N", help="num segment in the input" + ) + parser.add_argument( + "--max-positions", type=int, help="number of positional embeddings to learn" + ) + + # Arguments related to sentence level prediction + parser.add_argument( + "--sentence-class-num", + type=int, + metavar="N", + help="number of classes for sentence task", + ) + parser.add_argument( + "--sent-loss", + action="store_true", + help="if set," " calculate sentence level predictions", + ) + + # Arguments related to parameter initialization + parser.add_argument( + "--apply-bert-init", + action="store_true", + help="use custom param initialization for BERT", + ) + + # misc params + parser.add_argument( + "--activation-fn", + choices=utils.get_available_activation_fns(), + help="activation function to use", + ) + parser.add_argument( + "--pooler-activation-fn", + choices=utils.get_available_activation_fns(), + help="Which activation function to use for pooler layer.", + ) + parser.add_argument( + "--encoder-normalize-before", + action="store_true", + help="apply layernorm before each encoder block", + ) + + def forward(self, src_tokens, segment_labels=None, **kwargs): + return self.encoder(src_tokens, segment_labels=segment_labels, **kwargs) + + def max_positions(self): + return self.encoder.max_positions + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + # make sure all arguments are present in older models + base_architecture(args) + + if not hasattr(args, "max_positions"): + args.max_positions = args.tokens_per_sample + + logger.info(args) + + encoder = MaskedLMEncoder(args, task.dictionary) + return cls(args, encoder) + + +class MaskedLMEncoder(FairseqEncoder): + """ + Encoder for Masked Language Modelling. + """ + + def __init__(self, args, dictionary): + super().__init__(dictionary) + + self.padding_idx = dictionary.pad() + self.vocab_size = dictionary.__len__() + self.max_positions = args.max_positions + + self.sentence_encoder = TransformerSentenceEncoder( + padding_idx=self.padding_idx, + vocab_size=self.vocab_size, + num_encoder_layers=args.encoder_layers, + embedding_dim=args.encoder_embed_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=args.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.act_dropout, + max_seq_len=self.max_positions, + num_segments=args.num_segment, + use_position_embeddings=not args.no_token_positional_embeddings, + encoder_normalize_before=args.encoder_normalize_before, + apply_bert_init=args.apply_bert_init, + activation_fn=args.activation_fn, + learned_pos_embedding=args.encoder_learned_pos, + ) + + self.share_input_output_embed = args.share_encoder_input_output_embed + self.embed_out = None + self.sentence_projection_layer = None + self.sentence_out_dim = args.sentence_class_num + self.lm_output_learned_bias = None + + # Remove head is set to true during fine-tuning + self.load_softmax = not getattr(args, "remove_head", False) + + self.masked_lm_pooler = nn.Linear( + args.encoder_embed_dim, args.encoder_embed_dim + ) + self.pooler_activation = utils.get_activation_fn(args.pooler_activation_fn) + + self.lm_head_transform_weight = nn.Linear( + args.encoder_embed_dim, args.encoder_embed_dim + ) + self.activation_fn = utils.get_activation_fn(args.activation_fn) + self.layer_norm = LayerNorm(args.encoder_embed_dim) + + self.lm_output_learned_bias = None + if self.load_softmax: + self.lm_output_learned_bias = nn.Parameter(torch.zeros(self.vocab_size)) + + if not self.share_input_output_embed: + self.embed_out = nn.Linear( + args.encoder_embed_dim, self.vocab_size, bias=False + ) + + if args.sent_loss: + self.sentence_projection_layer = nn.Linear( + args.encoder_embed_dim, self.sentence_out_dim, bias=False + ) + + def forward(self, src_tokens, segment_labels=None, masked_tokens=None, **unused): + """ + Forward pass for Masked LM encoder. This first computes the token + embedding using the token embedding matrix, position embeddings (if + specified) and segment embeddings (if specified). + + Here we assume that the sentence representation corresponds to the + output of the classification_token (see bert_task or cross_lingual_lm + task for more details). + Args: + - src_tokens: B x T matrix representing sentences + - segment_labels: B x T matrix representing segment label for tokens + Returns: + - a tuple of the following: + - logits for predictions in format B x T x C to be used in + softmax afterwards + - a dictionary of additional data, where 'pooled_output' contains + the representation for classification_token and 'inner_states' + is a list of internal model states used to compute the + predictions (similar in ELMO). 'sentence_logits' + is the prediction logit for NSP task and is only computed if + this is specified in the input arguments. + """ + + inner_states, sentence_rep = self.sentence_encoder( + src_tokens, + segment_labels=segment_labels, + ) + + x = inner_states[-1].transpose(0, 1) + # project masked tokens only + if masked_tokens is not None: + x = x[masked_tokens, :] + x = self.layer_norm(self.activation_fn(self.lm_head_transform_weight(x))) + + pooled_output = self.pooler_activation(self.masked_lm_pooler(sentence_rep)) + + # project back to size of vocabulary + if self.share_input_output_embed and hasattr( + self.sentence_encoder.embed_tokens, "weight" + ): + x = F.linear(x, self.sentence_encoder.embed_tokens.weight) + elif self.embed_out is not None: + x = self.embed_out(x) + if self.lm_output_learned_bias is not None: + x = x + self.lm_output_learned_bias + sentence_logits = None + if self.sentence_projection_layer: + sentence_logits = self.sentence_projection_layer(pooled_output) + + return x, { + "inner_states": inner_states, + "pooled_output": pooled_output, + "sentence_logits": sentence_logits, + } + + def max_positions(self): + """Maximum output length supported by the encoder.""" + return self.max_positions + + def upgrade_state_dict_named(self, state_dict, name): + if isinstance( + self.sentence_encoder.embed_positions, SinusoidalPositionalEmbedding + ): + state_dict[ + name + ".sentence_encoder.embed_positions._float_tensor" + ] = torch.FloatTensor(1) + if not self.load_softmax: + for k in list(state_dict.keys()): + if ( + "embed_out.weight" in k + or "sentence_projection_layer.weight" in k + or "lm_output_learned_bias" in k + ): + del state_dict[k] + return state_dict + + +@register_model_architecture("masked_lm", "masked_lm") +def base_architecture(args): + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.act_dropout = getattr(args, "act_dropout", 0.0) + + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.share_encoder_input_output_embed = getattr( + args, "share_encoder_input_output_embed", False + ) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.num_segment = getattr(args, "num_segment", 2) + + args.sentence_class_num = getattr(args, "sentence_class_num", 2) + args.sent_loss = getattr(args, "sent_loss", False) + + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.activation_fn = getattr(args, "activation_fn", "relu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + + +@register_model_architecture("masked_lm", "bert_base") +def bert_base_architecture(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.share_encoder_input_output_embed = getattr( + args, "share_encoder_input_output_embed", True + ) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", True) + args.num_segment = getattr(args, "num_segment", 2) + + args.encoder_layers = getattr(args, "encoder_layers", 12) + + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 3072) + + args.sentence_class_num = getattr(args, "sentence_class_num", 2) + args.sent_loss = getattr(args, "sent_loss", True) + + args.apply_bert_init = getattr(args, "apply_bert_init", True) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + base_architecture(args) + + +@register_model_architecture("masked_lm", "bert_large") +def bert_large_architecture(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_layers = getattr(args, "encoder_layers", 24) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + bert_base_architecture(args) + + +@register_model_architecture("masked_lm", "xlm_base") +def xlm_architecture(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.share_encoder_input_output_embed = getattr( + args, "share_encoder_input_output_embed", True + ) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", True) + args.num_segment = getattr(args, "num_segment", 1) + + args.encoder_layers = getattr(args, "encoder_layers", 6) + + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + + args.sent_loss = getattr(args, "sent_loss", False) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + args.apply_bert_init = getattr(args, "apply_bert_init", True) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/model_utils.py b/fairseq-tools/fairseq/fairseq/models/model_utils.py new file mode 100644 index 00000000..732d66b1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/model_utils.py @@ -0,0 +1,92 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import List, Optional + +import torch +from torch import Tensor + + +@torch.jit.script +def script_skip_tensor_list(x: List[Tensor], mask): + res = [xi[mask] if xi.size(0) == mask.size(0) else xi[:, mask] for xi in x] + outputs = [] + for i, t in enumerate(res): + if t.numel() != 0: + outputs.append(t) + else: + outputs.append(x[i]) + return outputs + + +@torch.jit.script +def script_skip_tensor(x: Tensor, mask): + # None case + if x.size(0) == 0: + return x + res = x[mask] if x.size(0) == mask.size(0) else x[:, mask] + if res.numel() == 0: + return x + else: + return res + + +@torch.jit.script +def expand_2d_or_3d_tensor(x, trg_dim: int, padding_idx: int): + """ + Expand 2D/3D tensor on dim=1 + """ + if x is None: + return None + + assert x.dim() == 2 or x.dim() == 3 + assert trg_dim >= x.size(1), (trg_dim, x.size()) + if trg_dim == x.size(1): + return x + + dims = [x.size(0), trg_dim - x.size(1)] + if x.dim() == 3: + dims.append(x.size(2)) + x = torch.cat([x, torch.zeros(dims).to(x).fill_(padding_idx)], 1) + + return x + + +@torch.jit.script +def coalesce(x: Optional[Tensor], y: Tensor) -> Tensor: + return x if x is not None else y + + +@torch.jit.script +def fill_tensors( + x: Optional[Tensor], mask, y: Optional[Tensor], padding_idx: int +) -> Optional[Tensor]: + """ + Filling tensor x with y at masked positions (dim=0). + """ + if x is None or x.size()[0] == 0 or y is None: + return x + assert x.dim() == y.dim() and mask.size(0) == x.size(0) + assert x.dim() == 2 or (x.dim() == 3 and x.size(2) == y.size(2)) + + n_selected = mask.sum() + if n_selected == 0: + return x + assert n_selected == y.size(0) + if n_selected == x.size(0): + return y + + if x.size(1) < y.size(1): + x = expand_2d_or_3d_tensor(x, y.size(1), padding_idx) + x[mask] = y + elif x.size(1) > y.size(1): + x[mask] = torch.tensor(padding_idx).type_as(x) + if x.dim() == 2: + x[mask, : y.size(1)] = y + else: + x[mask, : y.size(1), :] = y + else: + x[mask] = y + return x diff --git a/fairseq-tools/fairseq/fairseq/models/multilingual_transformer.py b/fairseq-tools/fairseq/fairseq/models/multilingual_transformer.py new file mode 100644 index 00000000..e3fbbd57 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/multilingual_transformer.py @@ -0,0 +1,228 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import OrderedDict + +from fairseq import utils +from fairseq.models import ( + FairseqMultiModel, + register_model, + register_model_architecture, +) +from fairseq.models.transformer import ( + Embedding, + TransformerDecoder, + TransformerEncoder, + TransformerModel, + base_architecture, +) + + +@register_model("multilingual_transformer") +class MultilingualTransformerModel(FairseqMultiModel): + """Train Transformer models for multiple language pairs simultaneously. + + Requires `--task multilingual_translation`. + + We inherit all arguments from TransformerModel and assume that all language + pairs use a single Transformer architecture. In addition, we provide several + options that are specific to the multilingual setting. + + Args: + --share-encoder-embeddings: share encoder embeddings across all source languages + --share-decoder-embeddings: share decoder embeddings across all target languages + --share-encoders: share all encoder params (incl. embeddings) across all source languages + --share-decoders: share all decoder params (incl. embeddings) across all target languages + """ + + def __init__(self, encoders, decoders): + super().__init__(encoders, decoders) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + TransformerModel.add_args(parser) + parser.add_argument( + "--share-encoder-embeddings", + action="store_true", + help="share encoder embeddings across languages", + ) + parser.add_argument( + "--share-decoder-embeddings", + action="store_true", + help="share decoder embeddings across languages", + ) + parser.add_argument( + "--share-encoders", + action="store_true", + help="share encoders across languages", + ) + parser.add_argument( + "--share-decoders", + action="store_true", + help="share decoders across languages", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + from fairseq.tasks.multilingual_translation import MultilingualTranslationTask + + assert isinstance(task, MultilingualTranslationTask) + + # make sure all arguments are present in older models + base_multilingual_architecture(args) + + if not hasattr(args, "max_source_positions"): + args.max_source_positions = 1024 + if not hasattr(args, "max_target_positions"): + args.max_target_positions = 1024 + + src_langs = [lang_pair.split("-")[0] for lang_pair in task.model_lang_pairs] + tgt_langs = [lang_pair.split("-")[1] for lang_pair in task.model_lang_pairs] + + if args.share_encoders: + args.share_encoder_embeddings = True + if args.share_decoders: + args.share_decoder_embeddings = True + + def build_embedding(dictionary, embed_dim, path=None): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + emb = Embedding(num_embeddings, embed_dim, padding_idx) + # if provided, load from preloaded dictionaries + if path: + embed_dict = utils.parse_embedding(path) + utils.load_embedding(embed_dict, dictionary, emb) + return emb + + # build shared embeddings (if applicable) + shared_encoder_embed_tokens, shared_decoder_embed_tokens = None, None + if args.share_all_embeddings: + if args.encoder_embed_dim != args.decoder_embed_dim: + raise ValueError( + "--share-all-embeddings requires --encoder-embed-dim to match --decoder-embed-dim" + ) + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise ValueError( + "--share-all-embeddings not compatible with --decoder-embed-path" + ) + shared_encoder_embed_tokens = FairseqMultiModel.build_shared_embeddings( + dicts=task.dicts, + langs=task.langs, + embed_dim=args.encoder_embed_dim, + build_embedding=build_embedding, + pretrained_embed_path=args.encoder_embed_path, + ) + shared_decoder_embed_tokens = shared_encoder_embed_tokens + args.share_decoder_input_output_embed = True + else: + if args.share_encoder_embeddings: + shared_encoder_embed_tokens = FairseqMultiModel.build_shared_embeddings( + dicts=task.dicts, + langs=src_langs, + embed_dim=args.encoder_embed_dim, + build_embedding=build_embedding, + pretrained_embed_path=args.encoder_embed_path, + ) + if args.share_decoder_embeddings: + shared_decoder_embed_tokens = FairseqMultiModel.build_shared_embeddings( + dicts=task.dicts, + langs=tgt_langs, + embed_dim=args.decoder_embed_dim, + build_embedding=build_embedding, + pretrained_embed_path=args.decoder_embed_path, + ) + + # encoders/decoders for each language + lang_encoders, lang_decoders = {}, {} + + def get_encoder(lang): + if lang not in lang_encoders: + if shared_encoder_embed_tokens is not None: + encoder_embed_tokens = shared_encoder_embed_tokens + else: + encoder_embed_tokens = build_embedding( + task.dicts[lang], + args.encoder_embed_dim, + args.encoder_embed_path, + ) + lang_encoders[lang] = cls._get_module_class( + True, args, task.dicts[lang], encoder_embed_tokens, src_langs + ) + return lang_encoders[lang] + + def get_decoder(lang): + if lang not in lang_decoders: + if shared_decoder_embed_tokens is not None: + decoder_embed_tokens = shared_decoder_embed_tokens + else: + decoder_embed_tokens = build_embedding( + task.dicts[lang], + args.decoder_embed_dim, + args.decoder_embed_path, + ) + lang_decoders[lang] = cls._get_module_class( + False, args, task.dicts[lang], decoder_embed_tokens, tgt_langs + ) + return lang_decoders[lang] + + # shared encoders/decoders (if applicable) + shared_encoder, shared_decoder = None, None + if args.share_encoders: + shared_encoder = get_encoder(src_langs[0]) + if args.share_decoders: + shared_decoder = get_decoder(tgt_langs[0]) + + encoders, decoders = OrderedDict(), OrderedDict() + for lang_pair, src, tgt in zip(task.model_lang_pairs, src_langs, tgt_langs): + encoders[lang_pair] = ( + shared_encoder if shared_encoder is not None else get_encoder(src) + ) + decoders[lang_pair] = ( + shared_decoder if shared_decoder is not None else get_decoder(tgt) + ) + + return MultilingualTransformerModel(encoders, decoders) + + @classmethod + def _get_module_class(cls, is_encoder, args, lang_dict, embed_tokens, langs): + module_class = TransformerEncoder if is_encoder else TransformerDecoder + return module_class(args, lang_dict, embed_tokens) + + def load_state_dict(self, state_dict, strict=True, args=None): + state_dict_subset = state_dict.copy() + for k, _ in state_dict.items(): + assert k.startswith("models.") + lang_pair = k.split(".")[1] + if lang_pair not in self.models: + del state_dict_subset[k] + super().load_state_dict(state_dict_subset, strict=strict, args=args) + + +@register_model_architecture("multilingual_transformer", "multilingual_transformer") +def base_multilingual_architecture(args): + base_architecture(args) + args.share_encoder_embeddings = getattr(args, "share_encoder_embeddings", False) + args.share_decoder_embeddings = getattr(args, "share_decoder_embeddings", False) + args.share_encoders = getattr(args, "share_encoders", False) + args.share_decoders = getattr(args, "share_decoders", False) + + +@register_model_architecture( + "multilingual_transformer", "multilingual_transformer_iwslt_de_en" +) +def multilingual_transformer_iwslt_de_en(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 1024) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.decoder_layers = getattr(args, "decoder_layers", 6) + base_multilingual_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/__init__.py b/fairseq-tools/fairseq/fairseq/models/nat/__init__.py new file mode 100644 index 00000000..05fe8224 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +from .fairseq_nat_model import * +from .nonautoregressive_transformer import * +from .nat_crf_transformer import * +from .iterative_nonautoregressive_transformer import * +from .cmlm_transformer import * +from .levenshtein_transformer import * +from .insertion_transformer import * diff --git a/fairseq-tools/fairseq/fairseq/models/nat/cmlm_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/cmlm_transformer.py new file mode 100644 index 00000000..c876e945 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/cmlm_transformer.py @@ -0,0 +1,162 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +This file implements: +Ghazvininejad, Marjan, et al. +"Constant-time machine translation with conditional masked language models." +arXiv preprint arXiv:1904.09324 (2019). +""" + +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import NATransformerModel +from fairseq.utils import new_arange + + +def _skeptical_unmasking(output_scores, output_masks, p): + sorted_index = output_scores.sort(-1)[1] + boundary_len = ( + (output_masks.sum(1, keepdim=True).type_as(output_scores) - 2) * p + ).long() + skeptical_mask = new_arange(output_masks) < boundary_len + return skeptical_mask.scatter(1, sorted_index, skeptical_mask) + + +@register_model("cmlm_transformer") +class CMLMNATransformerModel(NATransformerModel): + @staticmethod + def add_args(parser): + NATransformerModel.add_args(parser) + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + assert not self.decoder.src_embedding_copy, "do not support embedding copy." + + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + # length prediction + length_out = self.decoder.forward_length( + normalize=False, encoder_out=encoder_out + ) + length_tgt = self.decoder.forward_length_prediction( + length_out, encoder_out, tgt_tokens + ) + + # decoding + word_ins_out = self.decoder( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + ) + word_ins_mask = prev_output_tokens.eq(self.unk) + + return { + "word_ins": { + "out": word_ins_out, + "tgt": tgt_tokens, + "mask": word_ins_mask, + "ls": self.args.label_smoothing, + "nll_loss": True, + }, + "length": { + "out": length_out, + "tgt": length_tgt, + "factor": self.decoder.length_loss_factor, + }, + } + + def forward_decoder(self, decoder_out, encoder_out, decoding_format=None, **kwargs): + + step = decoder_out.step + max_step = decoder_out.max_step + + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + history = decoder_out.history + + # execute the decoder + output_masks = output_tokens.eq(self.unk) + _scores, _tokens = self.decoder( + normalize=True, + prev_output_tokens=output_tokens, + encoder_out=encoder_out, + ).max(-1) + output_tokens.masked_scatter_(output_masks, _tokens[output_masks]) + output_scores.masked_scatter_(output_masks, _scores[output_masks]) + + if history is not None: + history.append(output_tokens.clone()) + + # skeptical decoding (depend on the maximum decoding steps.) + if (step + 1) < max_step: + skeptical_mask = _skeptical_unmasking( + output_scores, output_tokens.ne(self.pad), 1 - (step + 1) / max_step + ) + + output_tokens.masked_fill_(skeptical_mask, self.unk) + output_scores.masked_fill_(skeptical_mask, 0.0) + + if history is not None: + history.append(output_tokens.clone()) + + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=None, + history=history, + ) + + +@register_model_architecture("cmlm_transformer", "cmlm_transformer") +def cmlm_base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", True) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + # --- special arguments --- + args.sg_length_pred = getattr(args, "sg_length_pred", False) + args.pred_length_offset = getattr(args, "pred_length_offset", False) + args.length_loss_factor = getattr(args, "length_loss_factor", 0.1) + args.ngram_predictor = getattr(args, "ngram_predictor", 1) + args.src_embedding_copy = getattr(args, "src_embedding_copy", False) + + +@register_model_architecture("cmlm_transformer", "cmlm_transformer_wmt_en_de") +def cmlm_wmt_en_de(args): + cmlm_base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/fairseq_nat_model.py b/fairseq-tools/fairseq/fairseq/models/nat/fairseq_nat_model.py new file mode 100644 index 00000000..1dbc29d0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/fairseq_nat_model.py @@ -0,0 +1,159 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +from fairseq.models.transformer import ( + TransformerDecoder, + TransformerEncoder, + TransformerModel, +) +from fairseq.modules.transformer_sentence_encoder import init_bert_params + + +def ensemble_encoder(func): + def wrapper(self, *args, **kwargs): + if self.ensemble_models is None or len(self.ensemble_models) == 1: + return func(self, *args, **kwargs) + encoder_outs = [func(model, *args, **kwargs) for model in self.ensemble_models] + _encoder_out = encoder_outs[0] + + def stack(key): + outs = [getattr(e, key) for e in encoder_outs] + return torch.stack(outs, -1) if outs[0] is not None else None + + return _encoder_out._replace( + encoder_out=stack("encoder_out"), + encoder_embedding=stack("encoder_embedding"), + encoder_states=stack("encoder_states"), + ) + + return wrapper + + +def ensemble_decoder(func): + def wrapper(self, normalize=False, encoder_out=None, *args, **kwargs): + if self.ensemble_models is None or len(self.ensemble_models) == 1: + return func( + self, normalize=normalize, encoder_out=encoder_out, *args, **kwargs + ) + + action_outs = [ + func( + model, + normalize=normalize, + encoder_out=encoder_out._replace( + encoder_out=encoder_out.encoder_out[:, :, :, i] + ), + *args, + **kwargs + ) + for i, model in enumerate(self.ensemble_models) + ] + + if not isinstance(action_outs[0], tuple): # return multiple values + action_outs = [[a] for a in action_outs] + else: + action_outs = [list(a) for a in action_outs] + + ensembled_outs = [] + for i in range(len(action_outs[0])): + if i == 0 and normalize: + ensembled_outs += [ + torch.logsumexp( + torch.stack([a[i] for a in action_outs], -1), dim=-1 + ) + - math.log(len(self.ensemble_models)) + ] + elif action_outs[0][i] is not None: + ensembled_outs += [torch.stack([a[i] for a in action_outs], -1)] + else: + ensembled_outs += [None] + + if len(ensembled_outs) == 1: + return ensembled_outs[0] + return tuple(ensembled_outs) + + return wrapper + + +class FairseqNATModel(TransformerModel): + """ + Abstract class for all nonautoregressive-based models + """ + + def __init__(self, args, encoder, decoder): + super().__init__(args, encoder, decoder) + self.tgt_dict = decoder.dictionary + self.bos = decoder.dictionary.bos() + self.eos = decoder.dictionary.eos() + self.pad = decoder.dictionary.pad() + self.unk = decoder.dictionary.unk() + + self.ensemble_models = None + + @property + def allow_length_beam(self): + return False + + @property + def allow_ensemble(self): + return True + + def enable_ensemble(self, models): + self.encoder.ensemble_models = [m.encoder for m in models] + self.decoder.ensemble_models = [m.decoder for m in models] + + @staticmethod + def add_args(parser): + TransformerModel.add_args(parser) + parser.add_argument( + "--apply-bert-init", + action="store_true", + help="use custom param initialization for BERT", + ) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + decoder = FairseqNATDecoder(args, tgt_dict, embed_tokens) + if getattr(args, "apply_bert_init", False): + decoder.apply(init_bert_params) + return decoder + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + encoder = FairseqNATEncoder(args, src_dict, embed_tokens) + if getattr(args, "apply_bert_init", False): + encoder.apply(init_bert_params) + return encoder + + def forward_encoder(self, encoder_inputs): + return self.encoder(*encoder_inputs) + + def forward_decoder(self, *args, **kwargs): + return NotImplementedError + + def initialize_output_tokens(self, *args, **kwargs): + return NotImplementedError + + def forward(self, *args, **kwargs): + return NotImplementedError + + +class FairseqNATEncoder(TransformerEncoder): + def __init__(self, args, dictionary, embed_tokens): + super().__init__(args, dictionary, embed_tokens) + self.ensemble_models = None + + @ensemble_encoder + def forward(self, *args, **kwargs): + return super().forward(*args, **kwargs) + + +class FairseqNATDecoder(TransformerDecoder): + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__(args, dictionary, embed_tokens, no_encoder_attn) + self.ensemble_models = None diff --git a/fairseq-tools/fairseq/fairseq/models/nat/insertion_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/insertion_transformer.py new file mode 100644 index 00000000..bc28000f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/insertion_transformer.py @@ -0,0 +1,280 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +import torch.nn.functional as F +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import ( + FairseqNATModel, + LevenshteinTransformerDecoder, + LevenshteinTransformerModel, + ensemble_decoder, +) +from fairseq.models.transformer import Linear +from fairseq.modules.transformer_sentence_encoder import init_bert_params +from fairseq.utils import new_arange + + +class NegativeDistanceScore(object): + def __init__(self): + + # pre-compute some values + self.scores = {} + + self.scores[0.5] = self.compute_score_full(50, 0.5) + self.scores[1.0] = self.compute_score_full(50, 1.0) + self.scores[2.0] = self.compute_score_full(50, 2.0) + + def __call__(self, i, L, tau): + if (tau is None) or (tau > 1000): + return 1 / L + + if tau in self.scores: + if L < self.scores[tau].shape[0]: + return self.scores[tau][L - 1, i] + return self.compute_score(L, tau)[i] + + def compute_score(self, L, tau): + s = np.array([-abs(L / 2 - i) / tau for i in range(L)]) + s = np.exp(s - s.max()) + return s / s.sum() + + def compute_score_full(self, L, tau): + s = -abs(np.arange(0, L - 1)[:, None] / 2 - np.arange(L)[None, :]) / tau + s = np.tril(s, 0) + np.triu(s - float("inf"), 1) + s = np.exp(s - s.max(1, keepdims=True)) + return s / s.sum(1, keepdims=True) + + +neg_scorer = NegativeDistanceScore() + + +def _get_ins_targets(in_tokens, out_tokens, padding_idx, unk_idx, vocab_size, tau=None): + try: + from fairseq import libnat + except ImportError as e: + import sys + + sys.stderr.write("ERROR: missing libnat. run `pip install --editable .`\n") + raise e + + B = in_tokens.size(0) + T = in_tokens.size(1) + V = vocab_size + + with torch.cuda.device_of(in_tokens): + in_tokens_list = [ + [t for t in s if t != padding_idx] for i, s in enumerate(in_tokens.tolist()) + ] + out_tokens_list = [ + [t for t in s if t != padding_idx] + for i, s in enumerate(out_tokens.tolist()) + ] + + full_labels = libnat.suggested_ed2_path( + in_tokens_list, out_tokens_list, padding_idx + ) + insert_labels = [a[:-1] for a in full_labels] + + # numericalize1 + insert_label_tensors = in_tokens.new_zeros(B * (T - 1) * V).float() + insert_index, insert_labels = zip( + *[ + (w + (j + i * (T - 1)) * V, neg_scorer(k, len(label), tau)) + for i, labels in enumerate(insert_labels) + for j, label in enumerate(labels[1:-1]) + for k, w in enumerate(label) + ] + ) # HACK 1:-1 + insert_index, insert_labels = [ + torch.tensor(list(a), device=in_tokens.device) + for a in [insert_index, insert_labels] + ] + insert_label_tensors.scatter_(0, insert_index.long(), insert_labels) + insert_label_tensors = insert_label_tensors.view(B, T - 1, V) + + return insert_label_tensors + + +def _apply_ins_words(in_tokens, in_scores, word_ins_pred, word_ins_scores, padding_idx): + + padding_masks = in_tokens[:, 1:].eq(padding_idx) + word_ins_scores.masked_fill_(padding_masks, 0.0) + word_ins_pred.masked_fill_(padding_masks, padding_idx) + + in_coords = new_arange(in_tokens).type_as(in_scores) + + # shift all padding predictions to infinite + out_coords = (in_coords[:, 1:] - 0.5).masked_fill( + word_ins_pred.eq(padding_idx), float("inf") + ) + out_coords = torch.cat([in_coords, out_coords], 1).sort(-1)[1] + out_tokens = torch.cat([in_tokens, word_ins_pred], 1).gather(1, out_coords) + out_scores = torch.cat([in_scores, word_ins_scores], 1).gather(1, out_coords) + return out_tokens, out_scores + + +@register_model("insertion_transformer") +class InsertionTransformerModel(LevenshteinTransformerModel): + def __init__(self, args, encoder, decoder): + super().__init__(args, encoder, decoder) + + @staticmethod + def add_args(parser): + FairseqNATModel.add_args(parser) + parser.add_argument("--label-tau", default=None, type=float) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + decoder = InsertionTransformerDecoder(args, tgt_dict, embed_tokens) + if getattr(args, "apply_bert_init", False): + decoder.apply(init_bert_params) + return decoder + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + + assert tgt_tokens is not None, "forward function only supports training." + + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + + # generate training labels for insertion + word_ins_out = self.decoder.forward_word_ins( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + ) + + word_ins_tgt = _get_ins_targets( + prev_output_tokens, + tgt_tokens, + self.pad, + self.unk, + len(self.tgt_dict), + tau=self.decoder.label_tau, + ).type_as(word_ins_out) + word_ins_masks = prev_output_tokens[:, 1:].ne(self.pad) + + return { + "word_ins": { + "out": word_ins_out, + "tgt": word_ins_tgt, + "mask": word_ins_masks, + "ls": self.args.label_smoothing, + "nll_loss": True, + } + } + + def forward_decoder( + self, decoder_out, encoder_out, eos_penalty=0.0, max_ratio=None, **kwargs + ): + + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + history = decoder_out.history + + # TODO: decoding for InsertionTransformer + word_ins_score = self.decoder.forward_word_ins( + normalize=True, prev_output_tokens=output_tokens, encoder_out=encoder_out + ) + + if eos_penalty > 0.0: + word_ins_score[:, :, self.pad] -= eos_penalty + word_ins_score, word_ins_pred = word_ins_score.max(-1) + output_tokens, output_scores = _apply_ins_words( + output_tokens, output_scores, word_ins_pred, word_ins_score, self.pad + ) + + # delete some unnecessary paddings + cut_off = output_tokens.ne(self.pad).sum(1).max() + output_tokens = output_tokens[:, :cut_off] + output_scores = output_scores[:, :cut_off] + + if history is not None: + history.append(output_tokens.clone()) + + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=None, + history=history, + ) + + +class InsertionTransformerDecoder(LevenshteinTransformerDecoder): + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + # use the TransformerDecoder's __init__ + super(LevenshteinTransformerDecoder, self).__init__( + args, dictionary, embed_tokens, no_encoder_attn=no_encoder_attn + ) + + self.dictionary = dictionary + self.bos = dictionary.bos() + self.unk = dictionary.unk() + self.eos = dictionary.eos() + self.pool_out = Linear(self.output_embed_dim * 2, self.output_embed_dim) + + self.label_tau = getattr(args, "label_tau", None) + + @ensemble_decoder + def forward_word_ins(self, normalize, encoder_out, prev_output_tokens): + features = self.extract_features(prev_output_tokens, encoder_out=encoder_out)[0] + features = self.pool_out( + torch.cat([features[:, :-1, :], features[:, 1:, :]], 2) + ) + decoder_out = self.output_layer(features) + return F.log_softmax(decoder_out, -1) if normalize else decoder_out + + def forward_mask_ins(self, *args, **kwargs): + raise NotImplementedError + + def forward_word_del(self, *args, **kwargs): + raise NotImplementedError + + +@register_model_architecture("insertion_transformer", "insertion_transformer") +def insertion_base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + # special for insertion transformer + args.label_tau = getattr(args, "label_tau", None) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/iterative_nonautoregressive_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/iterative_nonautoregressive_transformer.py new file mode 100644 index 00000000..bc395099 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/iterative_nonautoregressive_transformer.py @@ -0,0 +1,228 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import NATransformerModel + + +def _sequential_poisoning(s, V, beta=0.33, bos=2, eos=3, pad=1): + # s: input batch + # V: vocabulary size + rand_words = torch.randint(low=4, high=V, size=s.size(), device=s.device) + choices = torch.rand(size=s.size(), device=s.device) + choices.masked_fill_((s == pad) | (s == bos) | (s == eos), 1) + + replace = choices < beta / 3 + repeat = (choices >= beta / 3) & (choices < beta * 2 / 3) + swap = (choices >= beta * 2 / 3) & (choices < beta) + safe = choices >= beta + + for i in range(s.size(1) - 1): + rand_word = rand_words[:, i] + next_word = s[:, i + 1] + self_word = s[:, i] + + replace_i = replace[:, i] + swap_i = swap[:, i] & (next_word != 3) + repeat_i = repeat[:, i] & (next_word != 3) + safe_i = safe[:, i] | ((next_word == 3) & (~replace_i)) + + s[:, i] = ( + self_word * (safe_i | repeat_i).long() + + next_word * swap_i.long() + + rand_word * replace_i.long() + ) + s[:, i + 1] = ( + next_word * (safe_i | replace_i).long() + + self_word * (swap_i | repeat_i).long() + ) + return s + + +def gumbel_noise(input, TINY=1e-8): + return ( + input.new_zeros(*input.size()) + .uniform_() + .add_(TINY) + .log_() + .neg_() + .add_(TINY) + .log_() + .neg_() + ) + + +@register_model("iterative_nonautoregressive_transformer") +class IterNATransformerModel(NATransformerModel): + @staticmethod + def add_args(parser): + NATransformerModel.add_args(parser) + parser.add_argument( + "--train-step", + type=int, + help="number of refinement iterations during training", + ) + parser.add_argument( + "--dae-ratio", + type=float, + help="the probability of switching to the denoising auto-encoder loss", + ) + parser.add_argument( + "--stochastic-approx", + action="store_true", + help="sampling from the decoder as the inputs for next iteration", + ) + + @classmethod + def build_model(cls, args, task): + model = super().build_model(args, task) + model.train_step = getattr(args, "train_step", 4) + model.dae_ratio = getattr(args, "dae_ratio", 0.5) + model.stochastic_approx = getattr(args, "stochastic_approx", False) + return model + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + + B, T = prev_output_tokens.size() + + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + + # length prediction + length_out = self.decoder.forward_length( + normalize=False, encoder_out=encoder_out + ) + length_tgt = self.decoder.forward_length_prediction( + length_out, encoder_out, tgt_tokens + ) + + # decoding + word_ins_outs, word_ins_tgts, word_ins_masks = [], [], [] + for t in range(self.train_step): + word_ins_out = self.decoder( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + step=t, + ) + word_ins_tgt = tgt_tokens + word_ins_mask = word_ins_tgt.ne(self.pad) + + word_ins_outs.append(word_ins_out) + word_ins_tgts.append(word_ins_tgt) + word_ins_masks.append(word_ins_mask) + + if t < (self.train_step - 1): + # prediction for next iteration + if self.stochastic_approx: + word_ins_prediction = ( + word_ins_out + gumbel_noise(word_ins_out) + ).max(-1)[1] + else: + word_ins_prediction = word_ins_out.max(-1)[1] + + prev_output_tokens = prev_output_tokens.masked_scatter( + word_ins_mask, word_ins_prediction[word_ins_mask] + ) + + if self.dae_ratio > 0: + # we do not perform denoising for the first iteration + corrputed = ( + torch.rand(size=(B,), device=prev_output_tokens.device) + < self.dae_ratio + ) + corrputed_tokens = _sequential_poisoning( + tgt_tokens[corrputed], + len(self.tgt_dict), + 0.33, + self.bos, + self.eos, + self.pad, + ) + prev_output_tokens[corrputed] = corrputed_tokens + + # concat everything + word_ins_out = torch.cat(word_ins_outs, 0) + word_ins_tgt = torch.cat(word_ins_tgts, 0) + word_ins_mask = torch.cat(word_ins_masks, 0) + + return { + "word_ins": { + "out": word_ins_out, + "tgt": word_ins_tgt, + "mask": word_ins_mask, + "ls": self.args.label_smoothing, + "nll_loss": True, + }, + "length": { + "out": length_out, + "tgt": length_tgt, + "factor": self.decoder.length_loss_factor, + }, + } + + +@register_model_architecture( + "iterative_nonautoregressive_transformer", "iterative_nonautoregressive_transformer" +) +def inat_base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + # --- special arguments --- + args.sg_length_pred = getattr(args, "sg_length_pred", False) + args.pred_length_offset = getattr(args, "pred_length_offset", False) + args.length_loss_factor = getattr(args, "length_loss_factor", 0.1) + args.ngram_predictor = getattr(args, "ngram_predictor", 1) + args.src_embedding_copy = getattr(args, "src_embedding_copy", False) + + args.train_step = getattr(args, "train_step", 4) + args.dae_ratio = getattr(args, "dae_ratio", 0.5) + args.stochastic_approx = getattr(args, "stochastic_approx", False) + + +@register_model_architecture( + "iterative_nonautoregressive_transformer", + "iterative_nonautoregressive_transformer_wmt_en_de", +) +def iter_nat_wmt_en_de(args): + inat_base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_transformer.py new file mode 100644 index 00000000..f7a3f003 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_transformer.py @@ -0,0 +1,502 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq.iterative_refinement_generator import DecoderOut +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import FairseqNATDecoder, FairseqNATModel, ensemble_decoder +from fairseq.models.transformer import Embedding, TransformerDecoderLayer +from fairseq.modules.transformer_sentence_encoder import init_bert_params + +from .levenshtein_utils import ( + _apply_del_words, + _apply_ins_masks, + _apply_ins_words, + _fill, + _get_del_targets, + _get_ins_targets, + _skip, + _skip_encoder_out, +) + + +@register_model("levenshtein_transformer") +class LevenshteinTransformerModel(FairseqNATModel): + @property + def allow_length_beam(self): + return False + + @staticmethod + def add_args(parser): + FairseqNATModel.add_args(parser) + parser.add_argument( + "--early-exit", + default="6,6,6", + type=str, + help="number of decoder layers before word_del, mask_ins, word_ins", + ) + parser.add_argument( + "--no-share-discriminator", + action="store_true", + help="separate parameters for discriminator", + ) + parser.add_argument( + "--no-share-maskpredictor", + action="store_true", + help="separate parameters for mask-predictor", + ) + parser.add_argument( + "--share-discriminator-maskpredictor", + action="store_true", + help="share the parameters for both mask-predictor and discriminator", + ) + parser.add_argument( + "--sampling-for-deletion", + action="store_true", + help="instead of argmax, use sampling to predict the tokens", + ) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + decoder = LevenshteinTransformerDecoder(args, tgt_dict, embed_tokens) + if getattr(args, "apply_bert_init", False): + decoder.apply(init_bert_params) + return decoder + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + + assert tgt_tokens is not None, "forward function only supports training." + + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + + # generate training labels for insertion + masked_tgt_masks, masked_tgt_tokens, mask_ins_targets = _get_ins_targets( + prev_output_tokens, tgt_tokens, self.pad, self.unk + ) + mask_ins_targets = mask_ins_targets.clamp(min=0, max=255) # for safe prediction + mask_ins_masks = prev_output_tokens[:, 1:].ne(self.pad) + + mask_ins_out, _ = self.decoder.forward_mask_ins( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + ) + word_ins_out, _ = self.decoder.forward_word_ins( + normalize=False, + prev_output_tokens=masked_tgt_tokens, + encoder_out=encoder_out, + ) + + # make online prediction + if self.decoder.sampling_for_deletion: + word_predictions = torch.multinomial( + F.softmax(word_ins_out, -1).view(-1, word_ins_out.size(-1)), 1 + ).view(word_ins_out.size(0), -1) + else: + word_predictions = F.log_softmax(word_ins_out, dim=-1).max(2)[1] + + word_predictions.masked_scatter_( + ~masked_tgt_masks, tgt_tokens[~masked_tgt_masks] + ) + + # generate training labels for deletion + word_del_targets = _get_del_targets(word_predictions, tgt_tokens, self.pad) + word_del_out, _ = self.decoder.forward_word_del( + normalize=False, + prev_output_tokens=word_predictions, + encoder_out=encoder_out, + ) + word_del_masks = word_predictions.ne(self.pad) + + return { + "mask_ins": { + "out": mask_ins_out, + "tgt": mask_ins_targets, + "mask": mask_ins_masks, + "ls": 0.01, + }, + "word_ins": { + "out": word_ins_out, + "tgt": tgt_tokens, + "mask": masked_tgt_masks, + "ls": self.args.label_smoothing, + "nll_loss": True, + }, + "word_del": { + "out": word_del_out, + "tgt": word_del_targets, + "mask": word_del_masks, + }, + } + + def forward_decoder( + self, decoder_out, encoder_out, eos_penalty=0.0, max_ratio=None, **kwargs + ): + + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + attn = decoder_out.attn + history = decoder_out.history + + bsz = output_tokens.size(0) + if max_ratio is None: + max_lens = torch.zeros_like(output_tokens).fill_(255) + else: + if encoder_out.encoder_padding_mask is None: + max_src_len = encoder_out.encoder_out.size(0) + src_lens = encoder_out.encoder_out.new(bsz).fill_(max_src_len) + else: + src_lens = (~encoder_out.encoder_padding_mask).sum(1) + max_lens = (src_lens * max_ratio).clamp(min=10).long() + + # delete words + # do not delete tokens if it is <s> </s> + can_del_word = output_tokens.ne(self.pad).sum(1) > 2 + if can_del_word.sum() != 0: # we cannot delete, skip + word_del_score, word_del_attn = self.decoder.forward_word_del( + normalize=True, + prev_output_tokens=_skip(output_tokens, can_del_word), + encoder_out=_skip_encoder_out(self.encoder, encoder_out, can_del_word), + ) + word_del_pred = word_del_score.max(-1)[1].bool() + + _tokens, _scores, _attn = _apply_del_words( + output_tokens[can_del_word], + output_scores[can_del_word], + word_del_attn, + word_del_pred, + self.pad, + self.bos, + self.eos, + ) + output_tokens = _fill(output_tokens, can_del_word, _tokens, self.pad) + output_scores = _fill(output_scores, can_del_word, _scores, 0) + attn = _fill(attn, can_del_word, _attn, 0.0) + + if history is not None: + history.append(output_tokens.clone()) + + # insert placeholders + can_ins_mask = output_tokens.ne(self.pad).sum(1) < max_lens + if can_ins_mask.sum() != 0: + mask_ins_score, _ = self.decoder.forward_mask_ins( + normalize=True, + prev_output_tokens=_skip(output_tokens, can_ins_mask), + encoder_out=_skip_encoder_out(self.encoder, encoder_out, can_ins_mask), + ) + if eos_penalty > 0.0: + mask_ins_score[:, :, 0] = mask_ins_score[:, :, 0] - eos_penalty + mask_ins_pred = mask_ins_score.max(-1)[1] + mask_ins_pred = torch.min( + mask_ins_pred, max_lens[can_ins_mask, None].expand_as(mask_ins_pred) + ) + + _tokens, _scores = _apply_ins_masks( + output_tokens[can_ins_mask], + output_scores[can_ins_mask], + mask_ins_pred, + self.pad, + self.unk, + self.eos, + ) + output_tokens = _fill(output_tokens, can_ins_mask, _tokens, self.pad) + output_scores = _fill(output_scores, can_ins_mask, _scores, 0) + + if history is not None: + history.append(output_tokens.clone()) + + # insert words + can_ins_word = output_tokens.eq(self.unk).sum(1) > 0 + if can_ins_word.sum() != 0: + word_ins_score, word_ins_attn = self.decoder.forward_word_ins( + normalize=True, + prev_output_tokens=_skip(output_tokens, can_ins_word), + encoder_out=_skip_encoder_out(self.encoder, encoder_out, can_ins_word), + ) + word_ins_score, word_ins_pred = word_ins_score.max(-1) + _tokens, _scores = _apply_ins_words( + output_tokens[can_ins_word], + output_scores[can_ins_word], + word_ins_pred, + word_ins_score, + self.unk, + ) + + output_tokens = _fill(output_tokens, can_ins_word, _tokens, self.pad) + output_scores = _fill(output_scores, can_ins_word, _scores, 0) + attn = _fill(attn, can_ins_word, word_ins_attn, 0.0) + + if history is not None: + history.append(output_tokens.clone()) + + # delete some unnecessary paddings + cut_off = output_tokens.ne(self.pad).sum(1).max() + output_tokens = output_tokens[:, :cut_off] + output_scores = output_scores[:, :cut_off] + attn = None if attn is None else attn[:, :cut_off, :] + + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=attn, + history=history, + ) + + def initialize_output_tokens(self, encoder_out, src_tokens): + initial_output_tokens = src_tokens.new_zeros(src_tokens.size(0), 2) + initial_output_tokens[:, 0] = self.bos + initial_output_tokens[:, 1] = self.eos + + initial_output_scores = initial_output_tokens.new_zeros( + *initial_output_tokens.size() + ).type_as(encoder_out.encoder_out) + + return DecoderOut( + output_tokens=initial_output_tokens, + output_scores=initial_output_scores, + attn=None, + step=0, + max_step=0, + history=None, + ) + + +class LevenshteinTransformerDecoder(FairseqNATDecoder): + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__( + args, dictionary, embed_tokens, no_encoder_attn=no_encoder_attn + ) + self.dictionary = dictionary + self.bos = dictionary.bos() + self.unk = dictionary.unk() + self.eos = dictionary.eos() + self.sampling_for_deletion = getattr(args, "sampling_for_deletion", False) + self.embed_mask_ins = Embedding(256, self.output_embed_dim * 2, None) + self.embed_word_del = Embedding(2, self.output_embed_dim, None) + + # del_word, ins_mask, ins_word + self.early_exit = [int(i) for i in args.early_exit.split(",")] + assert len(self.early_exit) == 3 + + # copy layers for mask-predict/deletion + self.layers_msk = None + if getattr(args, "no_share_maskpredictor", False): + self.layers_msk = nn.ModuleList( + [ + TransformerDecoderLayer(args, no_encoder_attn) + for _ in range(self.early_exit[1]) + ] + ) + self.layers_del = None + if getattr(args, "no_share_discriminator", False): + self.layers_del = nn.ModuleList( + [ + TransformerDecoderLayer(args, no_encoder_attn) + for _ in range(self.early_exit[0]) + ] + ) + + if getattr(args, "share_discriminator_maskpredictor", False): + assert getattr( + args, "no_share_discriminator", False + ), "must set saperate discriminator" + self.layers_msk = self.layers_del + + def extract_features( + self, + prev_output_tokens, + encoder_out=None, + early_exit=None, + layers=None, + **unused + ): + """ + Similar to *forward* but only return features. + Inputs: + prev_output_tokens: Tensor(B, T) + encoder_out: a dictionary of hidden states and masks + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + the LevenshteinTransformer decoder has full-attention to all generated tokens + """ + # embed positions + positions = ( + self.embed_positions(prev_output_tokens) + if self.embed_positions is not None + else None + ) + + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + x = self.dropout_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + attn = None + inner_states = [x] + + # decoder layers + decoder_padding_mask = prev_output_tokens.eq(self.padding_idx) + layers = self.layers if layers is None else layers + early_exit = len(layers) if early_exit is None else early_exit + for _, layer in enumerate(layers[:early_exit]): + x, attn, _ = layer( + x, + encoder_out.encoder_out if encoder_out is not None else None, + encoder_out.encoder_padding_mask if encoder_out is not None else None, + self_attn_mask=None, + self_attn_padding_mask=decoder_padding_mask, + ) + inner_states.append(x) + + if self.layer_norm: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + + return x, {"attn": attn, "inner_states": inner_states} + + @ensemble_decoder + def forward_mask_ins(self, normalize, encoder_out, prev_output_tokens, **unused): + features, extra = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + early_exit=self.early_exit[1], + layers=self.layers_msk, + **unused + ) + features_cat = torch.cat([features[:, :-1, :], features[:, 1:, :]], 2) + decoder_out = F.linear(features_cat, self.embed_mask_ins.weight) + if normalize: + return F.log_softmax(decoder_out, -1), extra["attn"] + return decoder_out, extra["attn"] + + @ensemble_decoder + def forward_word_ins(self, normalize, encoder_out, prev_output_tokens, **unused): + features, extra = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + early_exit=self.early_exit[2], + layers=self.layers, + **unused + ) + decoder_out = self.output_layer(features) + if normalize: + return F.log_softmax(decoder_out, -1), extra["attn"] + return decoder_out, extra["attn"] + + @ensemble_decoder + def forward_word_del(self, normalize, encoder_out, prev_output_tokens, **unused): + features, extra = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + early_exit=self.early_exit[0], + layers=self.layers_del, + **unused + ) + decoder_out = F.linear(features, self.embed_word_del.weight) + if normalize: + return F.log_softmax(decoder_out, -1), extra["attn"] + return decoder_out, extra["attn"] + + +@register_model_architecture("levenshtein_transformer", "levenshtein_transformer") +def levenshtein_base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.sampling_for_deletion = getattr(args, "sampling_for_deletion", False) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + args.early_exit = getattr(args, "early_exit", "6,6,6") + args.no_share_discriminator = getattr(args, "no_share_discriminator", False) + args.no_share_maskpredictor = getattr(args, "no_share_maskpredictor", False) + args.share_discriminator_maskpredictor = getattr( + args, "share_discriminator_maskpredictor", False + ) + args.no_share_last_layer = getattr(args, "no_share_last_layer", False) + + +@register_model_architecture( + "levenshtein_transformer", "levenshtein_transformer_wmt_en_de" +) +def levenshtein_transformer_wmt_en_de(args): + levenshtein_base_architecture(args) + + +# similar parameters used in the "Attention Is All You Need" paper (Vaswani et al., 2017) +@register_model_architecture( + "levenshtein_transformer", "levenshtein_transformer_vaswani_wmt_en_de_big" +) +def levenshtein_transformer_vaswani_wmt_en_de_big(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.3) + levenshtein_base_architecture(args) + + +# default parameters used in tensor2tensor implementation +@register_model_architecture( + "levenshtein_transformer", "levenshtein_transformer_wmt_en_de_big" +) +def levenshtein_transformer_wmt_en_de_big_t2t(args): + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.1) + levenshtein_transformer_vaswani_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_utils.py b/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_utils.py new file mode 100644 index 00000000..375a98c2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/levenshtein_utils.py @@ -0,0 +1,293 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq.utils import new_arange + + +# -------------- Helper Functions --------------------------------------------------- # + + +def load_libnat(): + try: + from fairseq import libnat_cuda + + return libnat_cuda, True + + except ImportError as e: + print(str(e) + "... fall back to CPU version") + + try: + from fairseq import libnat + + return libnat, False + + except ImportError as e: + import sys + + sys.stderr.write( + "ERROR: missing libnat_cuda. run `python setup.py build_ext --inplace`\n" + ) + raise e + + +def _get_ins_targets(in_tokens, out_tokens, padding_idx, unk_idx): + libnat, use_cuda = load_libnat() + + def _get_ins_targets_cuda(in_tokens, out_tokens, padding_idx, unk_idx): + in_masks = in_tokens.ne(padding_idx) + out_masks = out_tokens.ne(padding_idx) + mask_ins_targets, masked_tgt_masks = libnat.generate_insertion_labels( + out_tokens.int(), + libnat.levenshtein_distance( + in_tokens.int(), + out_tokens.int(), + in_masks.sum(1).int(), + out_masks.sum(1).int(), + ), + ) + masked_tgt_masks = masked_tgt_masks.bool() & out_masks + mask_ins_targets = mask_ins_targets.type_as(in_tokens)[ + :, 1 : in_masks.size(1) + ].masked_fill_(~in_masks[:, 1:], 0) + masked_tgt_tokens = out_tokens.masked_fill(masked_tgt_masks, unk_idx) + return masked_tgt_masks, masked_tgt_tokens, mask_ins_targets + + def _get_ins_targets_cpu(in_tokens, out_tokens, padding_idx, unk_idx): + in_seq_len, out_seq_len = in_tokens.size(1), out_tokens.size(1) + + in_tokens_list = [ + [t for t in s if t != padding_idx] for i, s in enumerate(in_tokens.tolist()) + ] + out_tokens_list = [ + [t for t in s if t != padding_idx] + for i, s in enumerate(out_tokens.tolist()) + ] + + full_labels = libnat.suggested_ed2_path( + in_tokens_list, out_tokens_list, padding_idx + ) + mask_inputs = [ + [len(c) if c[0] != padding_idx else 0 for c in a[:-1]] for a in full_labels + ] + + # generate labels + masked_tgt_masks = [] + for mask_input in mask_inputs: + mask_label = [] + for beam_size in mask_input[1:-1]: # HACK 1:-1 + mask_label += [0] + [1 for _ in range(beam_size)] + masked_tgt_masks.append( + mask_label + [0 for _ in range(out_seq_len - len(mask_label))] + ) + mask_ins_targets = [ + mask_input[1:-1] + + [0 for _ in range(in_seq_len - 1 - len(mask_input[1:-1]))] + for mask_input in mask_inputs + ] + + # transform to tensor + masked_tgt_masks = torch.tensor( + masked_tgt_masks, device=out_tokens.device + ).bool() + mask_ins_targets = torch.tensor(mask_ins_targets, device=in_tokens.device) + masked_tgt_tokens = out_tokens.masked_fill(masked_tgt_masks, unk_idx) + return masked_tgt_masks, masked_tgt_tokens, mask_ins_targets + + if use_cuda: + return _get_ins_targets_cuda(in_tokens, out_tokens, padding_idx, unk_idx) + return _get_ins_targets_cpu(in_tokens, out_tokens, padding_idx, unk_idx) + + +def _get_del_targets(in_tokens, out_tokens, padding_idx): + libnat, use_cuda = load_libnat() + + def _get_del_targets_cuda(in_tokens, out_tokens, padding_idx): + in_masks = in_tokens.ne(padding_idx) + out_masks = out_tokens.ne(padding_idx) + + word_del_targets = libnat.generate_deletion_labels( + in_tokens.int(), + libnat.levenshtein_distance( + in_tokens.int(), + out_tokens.int(), + in_masks.sum(1).int(), + out_masks.sum(1).int(), + ), + ) + word_del_targets = word_del_targets.type_as(in_tokens).masked_fill_( + ~in_masks, 0 + ) + return word_del_targets + + def _get_del_targets_cpu(in_tokens, out_tokens, padding_idx): + out_seq_len = out_tokens.size(1) + with torch.cuda.device_of(in_tokens): + in_tokens_list = [ + [t for t in s if t != padding_idx] + for i, s in enumerate(in_tokens.tolist()) + ] + out_tokens_list = [ + [t for t in s if t != padding_idx] + for i, s in enumerate(out_tokens.tolist()) + ] + + full_labels = libnat.suggested_ed2_path( + in_tokens_list, out_tokens_list, padding_idx + ) + word_del_targets = [b[-1] for b in full_labels] + word_del_targets = [ + labels + [0 for _ in range(out_seq_len - len(labels))] + for labels in word_del_targets + ] + + # transform to tensor + word_del_targets = torch.tensor(word_del_targets, device=out_tokens.device) + return word_del_targets + + if use_cuda: + return _get_del_targets_cuda(in_tokens, out_tokens, padding_idx) + return _get_del_targets_cpu(in_tokens, out_tokens, padding_idx) + + +def _apply_ins_masks( + in_tokens, in_scores, mask_ins_pred, padding_idx, unk_idx, eos_idx +): + + in_masks = in_tokens.ne(padding_idx) + in_lengths = in_masks.sum(1) + + # HACK: hacky way to shift all the paddings to eos first. + in_tokens.masked_fill_(~in_masks, eos_idx) + mask_ins_pred.masked_fill_(~in_masks[:, 1:], 0) + + out_lengths = in_lengths + mask_ins_pred.sum(1) + out_max_len = out_lengths.max() + out_masks = new_arange(out_lengths, out_max_len)[None, :] < out_lengths[:, None] + + reordering = (mask_ins_pred + in_masks[:, 1:].long()).cumsum(1) + out_tokens = ( + in_tokens.new_zeros(in_tokens.size(0), out_max_len) + .fill_(padding_idx) + .masked_fill_(out_masks, unk_idx) + ) + out_tokens[:, 0] = in_tokens[:, 0] + out_tokens.scatter_(1, reordering, in_tokens[:, 1:]) + + out_scores = None + if in_scores is not None: + in_scores.masked_fill_(~in_masks, 0) + out_scores = in_scores.new_zeros(*out_tokens.size()) + out_scores[:, 0] = in_scores[:, 0] + out_scores.scatter_(1, reordering, in_scores[:, 1:]) + + return out_tokens, out_scores + + +def _apply_ins_words(in_tokens, in_scores, word_ins_pred, word_ins_scores, unk_idx): + word_ins_masks = in_tokens.eq(unk_idx) + out_tokens = in_tokens.masked_scatter(word_ins_masks, word_ins_pred[word_ins_masks]) + + if in_scores is not None: + out_scores = in_scores.masked_scatter( + word_ins_masks, word_ins_scores[word_ins_masks] + ) + else: + out_scores = None + + return out_tokens, out_scores + + +def _apply_del_words( + in_tokens, in_scores, in_attn, word_del_pred, padding_idx, bos_idx, eos_idx +): + # apply deletion to a tensor + in_masks = in_tokens.ne(padding_idx) + bos_eos_masks = in_tokens.eq(bos_idx) | in_tokens.eq(eos_idx) + + max_len = in_tokens.size(1) + word_del_pred.masked_fill_(~in_masks, 1) + word_del_pred.masked_fill_(bos_eos_masks, 0) + + reordering = new_arange(in_tokens).masked_fill_(word_del_pred, max_len).sort(1)[1] + + out_tokens = in_tokens.masked_fill(word_del_pred, padding_idx).gather(1, reordering) + + out_scores = None + if in_scores is not None: + out_scores = in_scores.masked_fill(word_del_pred, 0).gather(1, reordering) + + out_attn = None + if in_attn is not None: + _mask = word_del_pred[:, :, None].expand_as(in_attn) + _reordering = reordering[:, :, None].expand_as(in_attn) + out_attn = in_attn.masked_fill(_mask, 0.0).gather(1, _reordering) + + return out_tokens, out_scores, out_attn + + +def _skip(x, mask): + """ + Getting sliced (dim=0) tensor by mask. Supporting tensor and list/dict of tensors. + """ + if isinstance(x, int): + return x + + if x is None: + return None + + if isinstance(x, torch.Tensor): + if x.size(0) == mask.size(0): + return x[mask] + elif x.size(1) == mask.size(0): + return x[:, mask] + + if isinstance(x, list): + return [_skip(x_i, mask) for x_i in x] + + if isinstance(x, dict): + return {k: _skip(v, mask) for k, v in x.items()} + + raise NotImplementedError + + +def _skip_encoder_out(encoder, encoder_out, mask): + if not mask.any(): + return encoder_out + else: + return encoder.reorder_encoder_out( + encoder_out, mask.nonzero(as_tuple=False).squeeze() + ) + + +def _fill(x, mask, y, padding_idx): + """ + Filling tensor x with y at masked positions (dim=0). + """ + if x is None: + return y + assert x.dim() == y.dim() and mask.size(0) == x.size(0) + assert x.dim() == 2 or (x.dim() == 3 and x.size(2) == y.size(2)) + n_selected = mask.sum() + assert n_selected == y.size(0) + + if n_selected == x.size(0): + return y + + if x.size(1) < y.size(1): + dims = [x.size(0), y.size(1) - x.size(1)] + if x.dim() == 3: + dims.append(x.size(2)) + x = torch.cat([x, x.new_zeros(*dims).fill_(padding_idx)], 1) + x[mask] = y + elif x.size(1) > y.size(1): + x[mask] = padding_idx + if x.dim() == 2: + x[mask, : y.size(1)] = y + else: + x[mask, : y.size(1), :] = y + else: + x[mask] = y + return x diff --git a/fairseq-tools/fairseq/fairseq/models/nat/nat_crf_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/nat_crf_transformer.py new file mode 100644 index 00000000..d4b3cd93 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/nat_crf_transformer.py @@ -0,0 +1,121 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import NATransformerModel, base_architecture +from fairseq.modules import DynamicCRF + + +@register_model("nacrf_transformer") +class NACRFTransformerModel(NATransformerModel): + def __init__(self, args, encoder, decoder): + super().__init__(args, encoder, decoder) + self.crf_layer = DynamicCRF( + num_embedding=len(self.tgt_dict), + low_rank=args.crf_lowrank_approx, + beam_size=args.crf_beam_approx, + ) + + @property + def allow_ensemble(self): + return False + + @staticmethod + def add_args(parser): + NATransformerModel.add_args(parser) + parser.add_argument( + "--crf-lowrank-approx", + type=int, + help="the dimension of low-rank approximation of transition", + ) + parser.add_argument( + "--crf-beam-approx", + type=int, + help="the beam size for apporixmating the normalizing factor", + ) + parser.add_argument( + "--word-ins-loss-factor", + type=float, + help="weights on NAT loss used to co-training with CRF loss.", + ) + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + + # length prediction + length_out = self.decoder.forward_length( + normalize=False, encoder_out=encoder_out + ) + length_tgt = self.decoder.forward_length_prediction( + length_out, encoder_out, tgt_tokens + ) + + # decoding + word_ins_out = self.decoder( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + ) + word_ins_tgt, word_ins_mask = tgt_tokens, tgt_tokens.ne(self.pad) + + # compute the log-likelihood of CRF + crf_nll = -self.crf_layer(word_ins_out, word_ins_tgt, word_ins_mask) + crf_nll = (crf_nll / word_ins_mask.type_as(crf_nll).sum(-1)).mean() + + return { + "word_ins": { + "out": word_ins_out, + "tgt": word_ins_tgt, + "mask": word_ins_mask, + "ls": self.args.label_smoothing, + "nll_loss": True, + "factor": self.args.word_ins_loss_factor, + }, + "word_crf": {"loss": crf_nll}, + "length": { + "out": length_out, + "tgt": length_tgt, + "factor": self.decoder.length_loss_factor, + }, + } + + def forward_decoder(self, decoder_out, encoder_out, decoding_format=None, **kwargs): + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + history = decoder_out.history + + # execute the decoder and get emission scores + output_masks = output_tokens.ne(self.pad) + word_ins_out = self.decoder( + normalize=False, prev_output_tokens=output_tokens, encoder_out=encoder_out + ) + + # run viterbi decoding through CRF + _scores, _tokens = self.crf_layer.forward_decoder(word_ins_out, output_masks) + output_tokens.masked_scatter_(output_masks, _tokens[output_masks]) + output_scores.masked_scatter_(output_masks, _scores[output_masks]) + if history is not None: + history.append(output_tokens.clone()) + + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=None, + history=history, + ) + + +@register_model_architecture("nacrf_transformer", "nacrf_transformer") +def nacrf_base_architecture(args): + args.crf_lowrank_approx = getattr(args, "crf_lowrank_approx", 32) + args.crf_beam_approx = getattr(args, "crf_beam_approx", 64) + args.word_ins_loss_factor = getattr(args, "word_ins_loss_factor", 0.5) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_ensembles.py b/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_ensembles.py new file mode 100644 index 00000000..46bb8aac --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_ensembles.py @@ -0,0 +1,254 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.nn.functional as F +from fairseq.models.nat import ( + _apply_del_words, + _apply_ins_masks, + _apply_ins_words, + _fill, + _skip, + _skip_encoder_out, +) + + +class _EnsembleModelEncoder(object): + def __init__(self, models): + self.models = models + + def reorder_encoder_out(self, encoder_outs, new_order): + encoder_outs = [ + model.encoder.reorder_encoder_out(encoder_out, new_order) + for model, encoder_out in zip(self.models, encoder_outs) + ] + return encoder_outs + + +class BasicEnsembleModel(torch.nn.Module): + """A wrapper around an ensemble of models.""" + + def __init__(self, models): + super().__init__() + self.models = torch.nn.ModuleList(models) + self.bos = self.models[0].decoder.dictionary.bos() + self.eos = self.models[0].decoder.dictionary.eos() + self.pad = self.models[0].decoder.dictionary.pad() + self.unk = self.models[0].decoder.dictionary.unk() + self.encoder = _EnsembleModelEncoder(self.models) + + def has_encoder(self): + return hasattr(self.models[0], "encoder") + + def max_decoder_positions(self): + return min(m.max_decoder_positions() for m in self.models) + + @torch.no_grad() + def forward_encoder(self, encoder_input): + if not self.has_encoder(): + return None + return [model.forward_encoder(encoder_input) for model in self.models] + + @torch.no_grad() + def forward_decoder(self, *inputs): + raise NotImplementedError + + def initialize_output_tokens(self, *inputs): + raise NotImplementedError + + +class EnsembleLevT(BasicEnsembleModel): + """A wrapper around an ensemble of models.""" + + def __init__(self, models): + super().__init__(models) + + @torch.no_grad() + def forward_decoder( + self, decoder_out, encoder_outs, eos_penalty=0.0, max_ratio=None, **kwargs + ): + # LevT ensembling + # A pipeline of three steps: deletion, placeholder, and word insertion. + # We need to average scores in each step in a pipeline way because of dependence. + # deletion + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + attn = decoder_out.attn + + bsz = output_tokens.size(0) + if max_ratio is None: + max_lens = output_tokens.new().fill_(255) + else: + if encoder_outs[0].encoder_padding_mask is None: + src_lens = ( + encoder_outs[0] + .encoder_out.new(bsz) + .fill_(encoder_outs[0].encoder_out.size(1)) + ) + else: + src_lens = (~encoder_outs[0].encoder_padding_mask).sum(1) + max_lens = (src_lens * max_ratio).clamp(min=10).long() + + # delete words + # do not delete tokens if it is <s> </s> + can_del_word = output_tokens.ne(self.pad).sum(1) > 2 + if can_del_word.sum() != 0: # we cannot delete, skip + output_tokens, output_scores, attn = self.forward_word_del( + encoder_outs, + output_tokens, + output_scores, + attn, + can_del_word, + ) + + # insert placeholders + can_ins_mask = output_tokens.ne(self.pad).sum(1) < max_lens + if can_ins_mask.sum() != 0: + output_tokens, output_scores = self.forward_mask_ins( + encoder_outs, + output_tokens, + output_scores, + can_ins_mask, + eos_penalty, + max_lens, + ) + + # insert words + can_ins_word = output_tokens.eq(self.unk).sum(1) > 0 + if can_ins_word.sum() != 0: + output_tokens, output_scores, attn = self.forward_word_ins( + encoder_outs, + output_tokens, + output_scores, + attn, + can_ins_word, + ) + + # delete some unnecessary paddings + cut_off = output_tokens.ne(self.pad).sum(1).max() + output_tokens = output_tokens[:, :cut_off] + output_scores = output_scores[:, :cut_off] + attn = None if attn is None else attn[:, :cut_off, :] + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=attn, + history=None, + ) + + def forward_word_del( + self, encoder_outs, output_tokens, output_scores, attn, can_del_word + ): + word_del_score_avg = [] + word_del_attn_avg = [] + for model, encoder_out in zip(self.models, encoder_outs): + word_del_out, word_del_attn = model.decoder.forward_word_del( + _skip(output_tokens, can_del_word), + _skip_encoder_out(model.encoder, encoder_out, can_del_word), + ) + word_del_score = F.log_softmax(word_del_out, 2) + word_del_score_avg.append(word_del_score) + word_del_attn_avg.append(word_del_attn) + word_del_score_avg = torch.logsumexp( + torch.stack(word_del_score_avg, dim=0), dim=0 + ) - math.log(len(self.models)) + word_del_pred = word_del_score_avg.max(-1)[1].bool() + if word_del_attn_avg[0] is not None: + word_del_attn_avg = torch.stack(word_del_attn_avg, dim=0) / len(self.models) + else: + word_del_attn_avg = None + + _tokens, _scores, _attn = _apply_del_words( + output_tokens[can_del_word], + output_scores[can_del_word], + word_del_attn_avg, + word_del_pred, + self.pad, + self.bos, + self.eos, + ) + output_tokens = _fill(output_tokens, can_del_word, _tokens, self.pad) + output_scores = _fill(output_scores, can_del_word, _scores, 0) + attn = _fill(attn, can_del_word, _attn, 0.0) + return output_tokens, output_scores, attn + + def forward_mask_ins( + self, + encoder_outs, + output_tokens, + output_scores, + can_ins_mask, + eos_penalty, + max_lens, + ): + mask_ins_score_avg = [] + for model, encoder_out in zip(self.models, encoder_outs): + mask_ins_out, _ = model.decoder.forward_mask_ins( + _skip(output_tokens, can_ins_mask), + _skip_encoder_out(model.encoder, encoder_out, can_ins_mask), + ) + mask_ins_score = F.log_softmax(mask_ins_out, 2) + if eos_penalty > 0.0: + mask_ins_score[:, :, 0] -= eos_penalty + mask_ins_score_avg.append(mask_ins_score) + mask_ins_score_avg = torch.logsumexp( + torch.stack(mask_ins_score_avg, dim=0), dim=0 + ) - math.log(len(self.models)) + mask_ins_pred = mask_ins_score_avg.max(-1)[1] + mask_ins_pred = torch.min( + mask_ins_pred, max_lens[can_ins_mask, None].expand_as(mask_ins_pred) + ) + _tokens, _scores = _apply_ins_masks( + output_tokens[can_ins_mask], + output_scores[can_ins_mask], + mask_ins_pred, + self.pad, + self.unk, + self.eos, + ) + output_tokens = _fill(output_tokens, can_ins_mask, _tokens, self.pad) + output_scores = _fill(output_scores, can_ins_mask, _scores, 0) + return output_tokens, output_scores + + def forward_word_ins( + self, encoder_outs, output_tokens, output_scores, attn, can_ins_word + ): + word_ins_score_avg = [] + word_ins_attn_avg = [] + for model, encoder_out in zip(self.models, encoder_outs): + word_ins_out, word_ins_attn = model.decoder.forward_word_ins( + _skip(output_tokens, can_ins_word), + _skip_encoder_out(model.encoder, encoder_out, can_ins_word), + ) + word_ins_score = F.log_softmax(word_ins_out, 2) + word_ins_score_avg.append(word_ins_score) + word_ins_attn_avg.append(word_ins_attn) + word_ins_score_avg = torch.logsumexp( + torch.stack(word_ins_score_avg, dim=0), dim=0 + ) - math.log(len(self.models)) + if word_ins_attn_avg[0] is not None: + word_ins_attn_avg = torch.stack(word_ins_attn_avg, dim=0) / len(self.models) + else: + word_ins_attn_avg = None + word_ins_score_max, word_ins_pred = word_ins_score_avg.max(-1) + + _tokens, _scores = _apply_ins_words( + output_tokens[can_ins_word], + output_scores[can_ins_word], + word_ins_pred, + word_ins_score_max, + self.unk, + ) + + output_tokens = _fill(output_tokens, can_ins_word, _tokens, self.pad) + output_scores = _fill(output_scores, can_ins_word, _scores, 0) + attn = _fill(attn, can_ins_word, word_ins_attn, 0.0) + return output_tokens, output_scores, attn + + def initialize_output_tokens(self, encoder_outs, src_tokens): + # LevT doesn't do length prediction. + return self.models[0].initialize_output_tokens(encoder_outs[0], src_tokens) diff --git a/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_transformer.py b/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_transformer.py new file mode 100644 index 00000000..735297fc --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/nat/nonautoregressive_transformer.py @@ -0,0 +1,440 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.iterative_refinement_generator import DecoderOut +from fairseq.models import register_model, register_model_architecture +from fairseq.models.nat import FairseqNATDecoder, FairseqNATModel, ensemble_decoder +from fairseq.models.transformer import Embedding +from fairseq.modules.transformer_sentence_encoder import init_bert_params + + +def _mean_pooling(enc_feats, src_masks): + # enc_feats: T x B x C + # src_masks: B x T or None + if src_masks is None: + enc_feats = enc_feats.mean(0) + else: + src_masks = (~src_masks).transpose(0, 1).type_as(enc_feats) + enc_feats = ( + (enc_feats / src_masks.sum(0)[None, :, None]) * src_masks[:, :, None] + ).sum(0) + return enc_feats + + +def _argmax(x, dim): + return (x == x.max(dim, keepdim=True)[0]).type_as(x) + + +def _uniform_assignment(src_lens, trg_lens): + max_trg_len = trg_lens.max() + steps = (src_lens.float() - 1) / (trg_lens.float() - 1) # step-size + # max_trg_len + index_t = utils.new_arange(trg_lens, max_trg_len).float() + index_t = steps[:, None] * index_t[None, :] # batch_size X max_trg_len + index_t = torch.round(index_t).long().detach() + return index_t + + +@register_model("nonautoregressive_transformer") +class NATransformerModel(FairseqNATModel): + @property + def allow_length_beam(self): + return True + + @staticmethod + def add_args(parser): + FairseqNATModel.add_args(parser) + + # length prediction + parser.add_argument( + "--src-embedding-copy", + action="store_true", + help="copy encoder word embeddings as the initial input of the decoder", + ) + parser.add_argument( + "--pred-length-offset", + action="store_true", + help="predicting the length difference between the target and source sentences", + ) + parser.add_argument( + "--sg-length-pred", + action="store_true", + help="stop the gradients back-propagated from the length predictor", + ) + parser.add_argument( + "--length-loss-factor", + type=float, + help="weights on the length prediction loss", + ) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + decoder = NATransformerDecoder(args, tgt_dict, embed_tokens) + if getattr(args, "apply_bert_init", False): + decoder.apply(init_bert_params) + return decoder + + def forward( + self, src_tokens, src_lengths, prev_output_tokens, tgt_tokens, **kwargs + ): + # encoding + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + + # length prediction + length_out = self.decoder.forward_length( + normalize=False, encoder_out=encoder_out + ) + length_tgt = self.decoder.forward_length_prediction( + length_out, encoder_out, tgt_tokens + ) + + # decoding + word_ins_out = self.decoder( + normalize=False, + prev_output_tokens=prev_output_tokens, + encoder_out=encoder_out, + ) + + return { + "word_ins": { + "out": word_ins_out, + "tgt": tgt_tokens, + "mask": tgt_tokens.ne(self.pad), + "ls": self.args.label_smoothing, + "nll_loss": True, + }, + "length": { + "out": length_out, + "tgt": length_tgt, + "factor": self.decoder.length_loss_factor, + }, + } + + def forward_decoder(self, decoder_out, encoder_out, decoding_format=None, **kwargs): + step = decoder_out.step + output_tokens = decoder_out.output_tokens + output_scores = decoder_out.output_scores + history = decoder_out.history + + # execute the decoder + output_masks = output_tokens.ne(self.pad) + _scores, _tokens = self.decoder( + normalize=True, + prev_output_tokens=output_tokens, + encoder_out=encoder_out, + step=step, + ).max(-1) + + output_tokens.masked_scatter_(output_masks, _tokens[output_masks]) + output_scores.masked_scatter_(output_masks, _scores[output_masks]) + if history is not None: + history.append(output_tokens.clone()) + + return decoder_out._replace( + output_tokens=output_tokens, + output_scores=output_scores, + attn=None, + history=history, + ) + + def initialize_output_tokens(self, encoder_out, src_tokens): + # length prediction + length_tgt = self.decoder.forward_length_prediction( + self.decoder.forward_length(normalize=True, encoder_out=encoder_out), + encoder_out=encoder_out, + ) + + max_length = length_tgt.clamp_(min=2).max() + idx_length = utils.new_arange(src_tokens, max_length) + + initial_output_tokens = src_tokens.new_zeros( + src_tokens.size(0), max_length + ).fill_(self.pad) + initial_output_tokens.masked_fill_( + idx_length[None, :] < length_tgt[:, None], self.unk + ) + initial_output_tokens[:, 0] = self.bos + initial_output_tokens.scatter_(1, length_tgt[:, None] - 1, self.eos) + + initial_output_scores = initial_output_tokens.new_zeros( + *initial_output_tokens.size() + ).type_as(encoder_out.encoder_out) + + return DecoderOut( + output_tokens=initial_output_tokens, + output_scores=initial_output_scores, + attn=None, + step=0, + max_step=0, + history=None, + ) + + def regenerate_length_beam(self, decoder_out, beam_size): + output_tokens = decoder_out.output_tokens + length_tgt = output_tokens.ne(self.pad).sum(1) + length_tgt = ( + length_tgt[:, None] + + utils.new_arange(length_tgt, 1, beam_size) + - beam_size // 2 + ) + length_tgt = length_tgt.view(-1).clamp_(min=2) + max_length = length_tgt.max() + idx_length = utils.new_arange(length_tgt, max_length) + + initial_output_tokens = output_tokens.new_zeros( + length_tgt.size(0), max_length + ).fill_(self.pad) + initial_output_tokens.masked_fill_( + idx_length[None, :] < length_tgt[:, None], self.unk + ) + initial_output_tokens[:, 0] = self.bos + initial_output_tokens.scatter_(1, length_tgt[:, None] - 1, self.eos) + + initial_output_scores = initial_output_tokens.new_zeros( + *initial_output_tokens.size() + ).type_as(decoder_out.output_scores) + + return decoder_out._replace( + output_tokens=initial_output_tokens, output_scores=initial_output_scores + ) + + +class NATransformerDecoder(FairseqNATDecoder): + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__( + args, dictionary, embed_tokens, no_encoder_attn=no_encoder_attn + ) + self.dictionary = dictionary + self.bos = dictionary.bos() + self.unk = dictionary.unk() + self.eos = dictionary.eos() + + self.encoder_embed_dim = args.encoder_embed_dim + self.sg_length_pred = getattr(args, "sg_length_pred", False) + self.pred_length_offset = getattr(args, "pred_length_offset", False) + self.length_loss_factor = getattr(args, "length_loss_factor", 0.1) + self.src_embedding_copy = getattr(args, "src_embedding_copy", False) + self.embed_length = Embedding(256, self.encoder_embed_dim, None) + + @ensemble_decoder + def forward(self, normalize, encoder_out, prev_output_tokens, step=0, **unused): + features, _ = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + embedding_copy=(step == 0) & self.src_embedding_copy, + ) + decoder_out = self.output_layer(features) + return F.log_softmax(decoder_out, -1) if normalize else decoder_out + + @ensemble_decoder + def forward_length(self, normalize, encoder_out): + enc_feats = encoder_out.encoder_out # T x B x C + src_masks = encoder_out.encoder_padding_mask # B x T or None + enc_feats = _mean_pooling(enc_feats, src_masks) + if self.sg_length_pred: + enc_feats = enc_feats.detach() + length_out = F.linear(enc_feats, self.embed_length.weight) + return F.log_softmax(length_out, -1) if normalize else length_out + + def extract_features( + self, + prev_output_tokens, + encoder_out=None, + early_exit=None, + embedding_copy=False, + **unused + ): + """ + Similar to *forward* but only return features. + + Inputs: + prev_output_tokens: Tensor(B, T) + encoder_out: a dictionary of hidden states and masks + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + the LevenshteinTransformer decoder has full-attention to all generated tokens + """ + # embedding + if embedding_copy: + src_embd = encoder_out.encoder_embedding + src_mask = encoder_out.encoder_padding_mask + src_mask = ( + ~src_mask + if src_mask is not None + else prev_output_tokens.new_ones(*src_embd.size()[:2]).bool() + ) + + x, decoder_padding_mask = self.forward_embedding( + prev_output_tokens, + self.forward_copying_source( + src_embd, src_mask, prev_output_tokens.ne(self.padding_idx) + ), + ) + + else: + + x, decoder_padding_mask = self.forward_embedding(prev_output_tokens) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + attn = None + inner_states = [x] + + # decoder layers + for i, layer in enumerate(self.layers): + + # early exit from the decoder. + if (early_exit is not None) and (i >= early_exit): + break + + x, attn, _ = layer( + x, + encoder_out.encoder_out if encoder_out is not None else None, + encoder_out.encoder_padding_mask if encoder_out is not None else None, + self_attn_mask=None, + self_attn_padding_mask=decoder_padding_mask, + ) + inner_states.append(x) + + if self.layer_norm: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + + return x, {"attn": attn, "inner_states": inner_states} + + def forward_embedding(self, prev_output_tokens, states=None): + # embed positions + positions = ( + self.embed_positions(prev_output_tokens) + if self.embed_positions is not None + else None + ) + + # embed tokens and positions + if states is None: + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + if self.project_in_dim is not None: + x = self.project_in_dim(x) + else: + x = states + + if positions is not None: + x += positions + x = self.dropout_module(x) + decoder_padding_mask = prev_output_tokens.eq(self.padding_idx) + return x, decoder_padding_mask + + def forward_copying_source(self, src_embeds, src_masks, tgt_masks): + length_sources = src_masks.sum(1) + length_targets = tgt_masks.sum(1) + mapped_inputs = _uniform_assignment(length_sources, length_targets).masked_fill( + ~tgt_masks, 0 + ) + copied_embedding = torch.gather( + src_embeds, + 1, + mapped_inputs.unsqueeze(-1).expand( + *mapped_inputs.size(), src_embeds.size(-1) + ), + ) + return copied_embedding + + def forward_length_prediction(self, length_out, encoder_out, tgt_tokens=None): + enc_feats = encoder_out.encoder_out # T x B x C + src_masks = encoder_out.encoder_padding_mask # B x T or None + if self.pred_length_offset: + if src_masks is None: + src_lengs = enc_feats.new_ones(enc_feats.size(1)).fill_( + enc_feats.size(0) + ) + else: + src_lengs = (~src_masks).transpose(0, 1).type_as(enc_feats).sum(0) + src_lengs = src_lengs.long() + + if tgt_tokens is not None: + # obtain the length target + tgt_lengs = tgt_tokens.ne(self.padding_idx).sum(1).long() + if self.pred_length_offset: + length_tgt = tgt_lengs - src_lengs + 128 + else: + length_tgt = tgt_lengs + length_tgt = length_tgt.clamp(min=0, max=255) + + else: + # predict the length target (greedy for now) + # TODO: implementing length-beam + pred_lengs = length_out.max(-1)[1] + if self.pred_length_offset: + length_tgt = pred_lengs - 128 + src_lengs + else: + length_tgt = pred_lengs + + return length_tgt + + +@register_model_architecture( + "nonautoregressive_transformer", "nonautoregressive_transformer" +) +def base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.apply_bert_init = getattr(args, "apply_bert_init", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + # --- special arguments --- + args.sg_length_pred = getattr(args, "sg_length_pred", False) + args.pred_length_offset = getattr(args, "pred_length_offset", False) + args.length_loss_factor = getattr(args, "length_loss_factor", 0.1) + args.src_embedding_copy = getattr(args, "src_embedding_copy", False) + + +@register_model_architecture( + "nonautoregressive_transformer", "nonautoregressive_transformer_wmt_en_de" +) +def nonautoregressive_transformer_wmt_en_de(args): + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/__init__.py b/fairseq-tools/fairseq/fairseq/models/roberta/__init__.py new file mode 100644 index 00000000..56579e59 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .hub_interface import * # noqa +from .model import * # noqa +from .model_camembert import * # noqa +from .model_xlmr import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/alignment_utils.py b/fairseq-tools/fairseq/fairseq/models/roberta/alignment_utils.py new file mode 100644 index 00000000..ccc7f74c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/alignment_utils.py @@ -0,0 +1,118 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import Counter +from typing import List + +import torch + + +def align_bpe_to_words(roberta, bpe_tokens: torch.LongTensor, other_tokens: List[str]): + """ + Helper to align GPT-2 BPE to other tokenization formats (e.g., spaCy). + + Args: + roberta (RobertaHubInterface): RoBERTa instance + bpe_tokens (torch.LongTensor): GPT-2 BPE tokens of shape `(T_bpe)` + other_tokens (List[str]): other tokens of shape `(T_words)` + + Returns: + List[str]: mapping from *other_tokens* to corresponding *bpe_tokens*. + """ + assert bpe_tokens.dim() == 1 + assert bpe_tokens[0] == 0 + + def clean(text): + return text.strip() + + # remove whitespaces to simplify alignment + bpe_tokens = [roberta.task.source_dictionary.string([x]) for x in bpe_tokens] + bpe_tokens = [ + clean(roberta.bpe.decode(x) if x not in {"<s>", ""} else x) for x in bpe_tokens + ] + other_tokens = [clean(str(o)) for o in other_tokens] + + # strip leading <s> + bpe_tokens = bpe_tokens[1:] + assert "".join(bpe_tokens) == "".join(other_tokens) + + # create alignment from every word to a list of BPE tokens + alignment = [] + bpe_toks = filter(lambda item: item[1] != "", enumerate(bpe_tokens, start=1)) + j, bpe_tok = next(bpe_toks) + for other_tok in other_tokens: + bpe_indices = [] + while True: + if other_tok.startswith(bpe_tok): + bpe_indices.append(j) + other_tok = other_tok[len(bpe_tok) :] + try: + j, bpe_tok = next(bpe_toks) + except StopIteration: + j, bpe_tok = None, None + elif bpe_tok.startswith(other_tok): + # other_tok spans multiple BPE tokens + bpe_indices.append(j) + bpe_tok = bpe_tok[len(other_tok) :] + other_tok = "" + else: + raise Exception('Cannot align "{}" and "{}"'.format(other_tok, bpe_tok)) + if other_tok == "": + break + assert len(bpe_indices) > 0 + alignment.append(bpe_indices) + assert len(alignment) == len(other_tokens) + + return alignment + + +def align_features_to_words(roberta, features, alignment): + """ + Align given features to words. + + Args: + roberta (RobertaHubInterface): RoBERTa instance + features (torch.Tensor): features to align of shape `(T_bpe x C)` + alignment: alignment between BPE tokens and words returned by + func:`align_bpe_to_words`. + """ + assert features.dim() == 2 + + bpe_counts = Counter(j for bpe_indices in alignment for j in bpe_indices) + assert bpe_counts[0] == 0 # <s> shouldn't be aligned + denom = features.new([bpe_counts.get(j, 1) for j in range(len(features))]) + weighted_features = features / denom.unsqueeze(-1) + + output = [weighted_features[0]] + largest_j = -1 + for bpe_indices in alignment: + output.append(weighted_features[bpe_indices].sum(dim=0)) + largest_j = max(largest_j, *bpe_indices) + for j in range(largest_j + 1, len(features)): + output.append(weighted_features[j]) + output = torch.stack(output) + assert torch.all(torch.abs(output.sum(dim=0) - features.sum(dim=0)) < 1e-4) + return output + + +def spacy_nlp(): + if getattr(spacy_nlp, "_nlp", None) is None: + try: + from spacy.lang.en import English + + spacy_nlp._nlp = English() + except ImportError: + raise ImportError("Please install spacy with: pip install spacy") + return spacy_nlp._nlp + + +def spacy_tokenizer(): + if getattr(spacy_tokenizer, "_tokenizer", None) is None: + try: + nlp = spacy_nlp() + spacy_tokenizer._tokenizer = nlp.Defaults.create_tokenizer(nlp) + except ImportError: + raise ImportError("Please install spacy with: pip install spacy") + return spacy_tokenizer._tokenizer diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/hub_interface.py b/fairseq-tools/fairseq/fairseq/models/roberta/hub_interface.py new file mode 100644 index 00000000..526823bd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/hub_interface.py @@ -0,0 +1,235 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.data import encoders + + +class RobertaHubInterface(nn.Module): + """A simple PyTorch Hub interface to RoBERTa. + + Usage: https://github.com/pytorch/fairseq/tree/master/examples/roberta + """ + + def __init__(self, args, task, model): + super().__init__() + self.args = args + self.task = task + self.model = model + + self.bpe = encoders.build_bpe(args) + + # this is useful for determining the device + self.register_buffer("_float_tensor", torch.tensor([0], dtype=torch.float)) + + @property + def device(self): + return self._float_tensor.device + + def encode( + self, sentence: str, *addl_sentences, no_separator=False + ) -> torch.LongTensor: + """ + BPE-encode a sentence (or multiple sentences). + + Every sequence begins with a beginning-of-sentence (`<s>`) symbol. + Every sentence ends with an end-of-sentence (`</s>`) and we use an + extra end-of-sentence (`</s>`) as a separator. + + Example (single sentence): `<s> a b c </s>` + Example (sentence pair): `<s> d e f </s> </s> 1 2 3 </s>` + + The BPE encoding follows GPT-2. One subtle detail is that the GPT-2 BPE + requires leading spaces. For example:: + + >>> roberta.encode('Hello world').tolist() + [0, 31414, 232, 2] + >>> roberta.encode(' world').tolist() + [0, 232, 2] + >>> roberta.encode('world').tolist() + [0, 8331, 2] + """ + bpe_sentence = "<s> " + self.bpe.encode(sentence) + " </s>" + for s in addl_sentences: + bpe_sentence += " </s>" if not no_separator else "" + bpe_sentence += " " + self.bpe.encode(s) + " </s>" + tokens = self.task.source_dictionary.encode_line( + bpe_sentence, append_eos=False, add_if_not_exist=False + ) + return tokens.long() + + def decode(self, tokens: torch.LongTensor): + assert tokens.dim() == 1 + tokens = tokens.numpy() + if tokens[0] == self.task.source_dictionary.bos(): + tokens = tokens[1:] # remove <s> + eos_mask = tokens == self.task.source_dictionary.eos() + doc_mask = eos_mask[1:] & eos_mask[:-1] + sentences = np.split(tokens, doc_mask.nonzero()[0] + 1) + sentences = [ + self.bpe.decode(self.task.source_dictionary.string(s)) for s in sentences + ] + if len(sentences) == 1: + return sentences[0] + return sentences + + def extract_features( + self, tokens: torch.LongTensor, return_all_hiddens: bool = False + ) -> torch.Tensor: + if tokens.dim() == 1: + tokens = tokens.unsqueeze(0) + if tokens.size(-1) > self.model.max_positions(): + raise ValueError( + "tokens exceeds maximum length: {} > {}".format( + tokens.size(-1), self.model.max_positions() + ) + ) + features, extra = self.model( + tokens.to(device=self.device), + features_only=True, + return_all_hiddens=return_all_hiddens, + ) + if return_all_hiddens: + # convert from T x B x C -> B x T x C + inner_states = extra["inner_states"] + return [inner_state.transpose(0, 1) for inner_state in inner_states] + else: + return features # just the last layer's features + + def register_classification_head( + self, name: str, num_classes: int = None, embedding_size: int = None, **kwargs + ): + self.model.register_classification_head( + name, num_classes=num_classes, embedding_size=embedding_size, **kwargs + ) + + def predict(self, head: str, tokens: torch.LongTensor, return_logits: bool = False): + features = self.extract_features(tokens.to(device=self.device)) + logits = self.model.classification_heads[head](features) + if return_logits: + return logits + return F.log_softmax(logits, dim=-1) + + def extract_features_aligned_to_words( + self, sentence: str, return_all_hiddens: bool = False + ) -> torch.Tensor: + """Extract RoBERTa features, aligned to spaCy's word-level tokenizer.""" + from fairseq.models.roberta import alignment_utils + from spacy.tokens import Doc + + nlp = alignment_utils.spacy_nlp() + tokenizer = alignment_utils.spacy_tokenizer() + + # tokenize both with GPT-2 BPE and spaCy + bpe_toks = self.encode(sentence) + spacy_toks = tokenizer(sentence) + spacy_toks_ws = [t.text_with_ws for t in tokenizer(sentence)] + alignment = alignment_utils.align_bpe_to_words(self, bpe_toks, spacy_toks_ws) + + # extract features and align them + features = self.extract_features( + bpe_toks, return_all_hiddens=return_all_hiddens + ) + features = features.squeeze(0) + aligned_feats = alignment_utils.align_features_to_words( + self, features, alignment + ) + + # wrap in spaCy Doc + doc = Doc( + nlp.vocab, + words=["<s>"] + [x.text for x in spacy_toks] + ["</s>"], + spaces=[True] + + [x.endswith(" ") for x in spacy_toks_ws[:-1]] + + [True, False], + ) + assert len(doc) == aligned_feats.size(0) + doc.user_token_hooks["vector"] = lambda token: aligned_feats[token.i] + return doc + + def fill_mask(self, masked_input: str, topk: int = 5): + masked_token = "<mask>" + assert ( + masked_token in masked_input and masked_input.count(masked_token) == 1 + ), "Please add one {0} token for the input, eg: 'He is a {0} guy'".format( + masked_token + ) + + text_spans = masked_input.split(masked_token) + text_spans_bpe = ( + (" {0} ".format(masked_token)) + .join([self.bpe.encode(text_span.rstrip()) for text_span in text_spans]) + .strip() + ) + tokens = self.task.source_dictionary.encode_line( + "<s> " + text_spans_bpe + " </s>", + append_eos=False, + add_if_not_exist=False, + ) + + masked_index = (tokens == self.task.mask_idx).nonzero() + if tokens.dim() == 1: + tokens = tokens.unsqueeze(0) + + with utils.model_eval(self.model): + features, extra = self.model( + tokens.long().to(device=self.device), + features_only=False, + return_all_hiddens=False, + ) + logits = features[0, masked_index, :].squeeze() + prob = logits.softmax(dim=0) + values, index = prob.topk(k=topk, dim=0) + topk_predicted_token_bpe = self.task.source_dictionary.string(index) + + topk_filled_outputs = [] + for index, predicted_token_bpe in enumerate( + topk_predicted_token_bpe.split(" ") + ): + predicted_token = self.bpe.decode(predicted_token_bpe) + # Quick hack to fix https://github.com/pytorch/fairseq/issues/1306 + if predicted_token_bpe.startswith("\u2581"): + predicted_token = " " + predicted_token + if " {0}".format(masked_token) in masked_input: + topk_filled_outputs.append( + ( + masked_input.replace( + " {0}".format(masked_token), predicted_token + ), + values[index].item(), + predicted_token, + ) + ) + else: + topk_filled_outputs.append( + ( + masked_input.replace(masked_token, predicted_token), + values[index].item(), + predicted_token, + ) + ) + return topk_filled_outputs + + def disambiguate_pronoun(self, sentence: str) -> bool: + """ + Usage:: + + >>> disambiguate_pronoun('The _trophy_ would not fit in the brown suitcase because [it] was too big.') + True + + >>> disambiguate_pronoun('The trophy would not fit in the brown suitcase because [it] was too big.') + 'The trophy' + """ + assert hasattr( + self.task, "disambiguate_pronoun" + ), "roberta.disambiguate_pronoun() requires a model trained with the WSC task." + with utils.model_eval(self.model): + return self.task.disambiguate_pronoun( + self.model, sentence, use_cuda=self.device.type == "cuda" + ) diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/model.py b/fairseq-tools/fairseq/fairseq/models/roberta/model.py new file mode 100644 index 00000000..d56496f8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/model.py @@ -0,0 +1,524 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +RoBERTa: A Robustly Optimized BERT Pretraining Approach. +""" + +import logging + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderModel, + register_model, + register_model_architecture, +) +from fairseq.modules import LayerNorm, TransformerSentenceEncoder +from fairseq.modules.quant_noise import quant_noise as apply_quant_noise_ +from fairseq.modules.transformer_sentence_encoder import init_bert_params + +from .hub_interface import RobertaHubInterface + + +logger = logging.getLogger(__name__) + + +@register_model("roberta") +class RobertaModel(FairseqEncoderModel): + @classmethod + def hub_models(cls): + return { + "roberta.base": "http://dl.fbaipublicfiles.com/fairseq/models/roberta.base.tar.gz", + "roberta.large": "http://dl.fbaipublicfiles.com/fairseq/models/roberta.large.tar.gz", + "roberta.large.mnli": "http://dl.fbaipublicfiles.com/fairseq/models/roberta.large.mnli.tar.gz", + "roberta.large.wsc": "http://dl.fbaipublicfiles.com/fairseq/models/roberta.large.wsc.tar.gz", + } + + def __init__(self, args, encoder): + super().__init__(encoder) + self.args = args + + # We follow BERT's random weight initialization + self.apply(init_bert_params) + + self.classification_heads = nn.ModuleDict() + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--encoder-layers", type=int, metavar="L", help="num encoder layers" + ) + parser.add_argument( + "--encoder-embed-dim", + type=int, + metavar="H", + help="encoder embedding dimension", + ) + parser.add_argument( + "--encoder-ffn-embed-dim", + type=int, + metavar="F", + help="encoder embedding dimension for FFN", + ) + parser.add_argument( + "--encoder-attention-heads", + type=int, + metavar="A", + help="num encoder attention heads", + ) + parser.add_argument( + "--activation-fn", + choices=utils.get_available_activation_fns(), + help="activation function to use", + ) + parser.add_argument( + "--pooler-activation-fn", + choices=utils.get_available_activation_fns(), + help="activation function to use for pooler layer", + ) + parser.add_argument( + "--encoder-normalize-before", + action="store_true", + help="apply layernorm before each encoder block", + ) + parser.add_argument( + "--dropout", type=float, metavar="D", help="dropout probability" + ) + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights", + ) + parser.add_argument( + "--activation-dropout", + type=float, + metavar="D", + help="dropout probability after activation in FFN", + ) + parser.add_argument( + "--pooler-dropout", + type=float, + metavar="D", + help="dropout probability in the masked_lm pooler layers", + ) + parser.add_argument( + "--max-positions", type=int, help="number of positional embeddings to learn" + ) + parser.add_argument( + "--load-checkpoint-heads", + action="store_true", + help="(re-)register and load heads when loading checkpoints", + ) + # args for "Reducing Transformer Depth on Demand with Structured Dropout" (Fan et al., 2019) + parser.add_argument( + "--encoder-layerdrop", + type=float, + metavar="D", + default=0, + help="LayerDrop probability for encoder", + ) + parser.add_argument( + "--encoder-layers-to-keep", + default=None, + help="which layers to *keep* when pruning as a comma-separated list", + ) + # args for Training with Quantization Noise for Extreme Model Compression ({Fan*, Stock*} et al., 2020) + parser.add_argument( + "--quant-noise-pq", + type=float, + metavar="D", + default=0, + help="iterative PQ quantization noise at training time", + ) + parser.add_argument( + "--quant-noise-pq-block-size", + type=int, + metavar="D", + default=8, + help="block size of quantization noise at training time", + ) + parser.add_argument( + "--quant-noise-scalar", + type=float, + metavar="D", + default=0, + help="scalar quantization noise and scalar quantization at training time", + ) + parser.add_argument( + "--untie-weights-roberta", + action="store_true", + help="Untie weights between embeddings and classifiers in RoBERTa", + ) + parser.add_argument( + "--spectral-norm-classification-head", + action="store_true", + default=False, + help="Apply spectral normalization on the classification head", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present + base_architecture(args) + + if not hasattr(args, "max_positions"): + args.max_positions = args.tokens_per_sample + + encoder = RobertaEncoder(args, task.source_dictionary) + return cls(args, encoder) + + def forward( + self, + src_tokens, + features_only=False, + return_all_hiddens=False, + classification_head_name=None, + **kwargs + ): + if classification_head_name is not None: + features_only = True + + x, extra = self.encoder(src_tokens, features_only, return_all_hiddens, **kwargs) + + if classification_head_name is not None: + x = self.classification_heads[classification_head_name](x) + return x, extra + + def get_normalized_probs(self, net_output, log_probs, sample=None): + """Get normalized probabilities (or log probs) from a net's output.""" + logits = net_output[0].float() + if log_probs: + return F.log_softmax(logits, dim=-1) + else: + return F.softmax(logits, dim=-1) + + def register_classification_head( + self, name, num_classes=None, inner_dim=None, **kwargs + ): + """Register a classification head.""" + if name in self.classification_heads: + prev_num_classes = self.classification_heads[name].out_proj.out_features + prev_inner_dim = self.classification_heads[name].dense.out_features + if num_classes != prev_num_classes or inner_dim != prev_inner_dim: + logger.warning( + 're-registering head "{}" with num_classes {} (prev: {}) ' + "and inner_dim {} (prev: {})".format( + name, num_classes, prev_num_classes, inner_dim, prev_inner_dim + ) + ) + self.classification_heads[name] = RobertaClassificationHead( + input_dim=self.args.encoder_embed_dim, + inner_dim=inner_dim or self.args.encoder_embed_dim, + num_classes=num_classes, + activation_fn=self.args.pooler_activation_fn, + pooler_dropout=self.args.pooler_dropout, + q_noise=self.args.quant_noise_pq, + qn_block_size=self.args.quant_noise_pq_block_size, + do_spectral_norm=self.args.spectral_norm_classification_head, + ) + + @property + def supported_targets(self): + return {"self"} + + @classmethod + def from_pretrained( + cls, + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + bpe="gpt2", + **kwargs + ): + from fairseq import hub_utils + + x = hub_utils.from_pretrained( + model_name_or_path, + checkpoint_file, + data_name_or_path, + archive_map=cls.hub_models(), + bpe=bpe, + load_checkpoint_heads=True, + **kwargs, + ) + cls.upgrade_args(x["args"]) + + logger.info(x["args"]) + return RobertaHubInterface(x["args"], x["task"], x["models"][0]) + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + + # rename decoder -> encoder before upgrading children modules + for k in list(state_dict.keys()): + if k.startswith(prefix + "decoder"): + new_k = prefix + "encoder" + k[len(prefix + "decoder") :] + state_dict[new_k] = state_dict[k] + del state_dict[k] + + # upgrade children modules + super().upgrade_state_dict_named(state_dict, name) + + # Handle new classification heads present in the state dict. + current_head_names = ( + [] + if not hasattr(self, "classification_heads") + else self.classification_heads.keys() + ) + keys_to_delete = [] + for k in state_dict.keys(): + if not k.startswith(prefix + "classification_heads."): + continue + + head_name = k[len(prefix + "classification_heads.") :].split(".")[0] + num_classes = state_dict[ + prefix + "classification_heads." + head_name + ".out_proj.weight" + ].size(0) + inner_dim = state_dict[ + prefix + "classification_heads." + head_name + ".dense.weight" + ].size(0) + + if getattr(self.args, "load_checkpoint_heads", False): + if head_name not in current_head_names: + self.register_classification_head(head_name, num_classes, inner_dim) + else: + if head_name not in current_head_names: + logger.warning( + "deleting classification head ({}) from checkpoint " + "not present in current model: {}".format(head_name, k) + ) + keys_to_delete.append(k) + elif ( + num_classes + != self.classification_heads[head_name].out_proj.out_features + or inner_dim + != self.classification_heads[head_name].dense.out_features + ): + logger.warning( + "deleting classification head ({}) from checkpoint " + "with different dimensions than current model: {}".format( + head_name, k + ) + ) + keys_to_delete.append(k) + for k in keys_to_delete: + del state_dict[k] + + # Copy any newly-added classification heads into the state dict + # with their current weights. + if hasattr(self, "classification_heads"): + cur_state = self.classification_heads.state_dict() + for k, v in cur_state.items(): + if prefix + "classification_heads." + k not in state_dict: + logger.info("Overwriting " + prefix + "classification_heads." + k) + state_dict[prefix + "classification_heads." + k] = v + + +class RobertaLMHead(nn.Module): + """Head for masked language modeling.""" + + def __init__(self, embed_dim, output_dim, activation_fn, weight=None): + super().__init__() + self.dense = nn.Linear(embed_dim, embed_dim) + self.activation_fn = utils.get_activation_fn(activation_fn) + self.layer_norm = LayerNorm(embed_dim) + + if weight is None: + weight = nn.Linear(embed_dim, output_dim, bias=False).weight + self.weight = weight + self.bias = nn.Parameter(torch.zeros(output_dim)) + + def forward(self, features, masked_tokens=None, **kwargs): + # Only project the masked tokens while training, + # saves both memory and computation + if masked_tokens is not None: + features = features[masked_tokens, :] + + x = self.dense(features) + x = self.activation_fn(x) + x = self.layer_norm(x) + # project back to size of vocabulary with bias + x = F.linear(x, self.weight) + self.bias + return x + + +class RobertaClassificationHead(nn.Module): + """Head for sentence-level classification tasks.""" + + def __init__( + self, + input_dim, + inner_dim, + num_classes, + activation_fn, + pooler_dropout, + q_noise=0, + qn_block_size=8, + do_spectral_norm=False, + ): + super().__init__() + self.dense = nn.Linear(input_dim, inner_dim) + self.activation_fn = utils.get_activation_fn(activation_fn) + self.dropout = nn.Dropout(p=pooler_dropout) + self.out_proj = apply_quant_noise_( + nn.Linear(inner_dim, num_classes), q_noise, qn_block_size + ) + if do_spectral_norm: + if q_noise != 0: + raise NotImplementedError( + "Attempting to use Spectral Normalization with Quant Noise. This is not officially supported" + ) + self.out_proj = torch.nn.utils.spectral_norm(self.out_proj) + + def forward(self, features, **kwargs): + x = features[:, 0, :] # take <s> token (equiv. to [CLS]) + x = self.dropout(x) + x = self.dense(x) + x = self.activation_fn(x) + x = self.dropout(x) + x = self.out_proj(x) + return x + + +class RobertaEncoder(FairseqEncoder): + """RoBERTa encoder.""" + + def __init__(self, args, dictionary): + super().__init__(dictionary) + self.args = args + + if args.encoder_layers_to_keep: + args.encoder_layers = len(args.encoder_layers_to_keep.split(",")) + + self.sentence_encoder = TransformerSentenceEncoder( + padding_idx=dictionary.pad(), + vocab_size=len(dictionary), + num_encoder_layers=args.encoder_layers, + embedding_dim=args.encoder_embed_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=args.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.activation_dropout, + layerdrop=args.encoder_layerdrop, + max_seq_len=args.max_positions, + num_segments=0, + encoder_normalize_before=True, + apply_bert_init=True, + activation_fn=args.activation_fn, + q_noise=args.quant_noise_pq, + qn_block_size=args.quant_noise_pq_block_size, + ) + args.untie_weights_roberta = getattr(args, "untie_weights_roberta", False) + + self.lm_head = RobertaLMHead( + embed_dim=args.encoder_embed_dim, + output_dim=len(dictionary), + activation_fn=args.activation_fn, + weight=( + self.sentence_encoder.embed_tokens.weight + if not args.untie_weights_roberta + else None + ), + ) + + def forward( + self, + src_tokens, + features_only=False, + return_all_hiddens=False, + masked_tokens=None, + **unused + ): + """ + Args: + src_tokens (LongTensor): input tokens of shape `(batch, src_len)` + features_only (bool, optional): skip LM head and just return + features. If True, the output will be of shape + `(batch, src_len, embed_dim)`. + return_all_hiddens (bool, optional): also return all of the + intermediate hidden states (default: False). + + Returns: + tuple: + - the LM output of shape `(batch, src_len, vocab)` + - a dictionary of additional data, where 'inner_states' + is a list of hidden states. Note that the hidden + states have shape `(src_len, batch, vocab)`. + """ + x, extra = self.extract_features( + src_tokens, return_all_hiddens=return_all_hiddens + ) + if not features_only: + x = self.output_layer(x, masked_tokens=masked_tokens) + return x, extra + + def extract_features(self, src_tokens, return_all_hiddens=False, **kwargs): + inner_states, _ = self.sentence_encoder( + src_tokens, + last_state_only=not return_all_hiddens, + token_embeddings=kwargs.get("token_embeddings", None), + ) + features = inner_states[-1].transpose(0, 1) # T x B x C -> B x T x C + return features, {"inner_states": inner_states if return_all_hiddens else None} + + def output_layer(self, features, masked_tokens=None, **unused): + return self.lm_head(features, masked_tokens) + + def max_positions(self): + """Maximum output length supported by the encoder.""" + return self.args.max_positions + + +@register_model_architecture("roberta", "roberta") +def base_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 3072) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + args.pooler_activation_fn = getattr(args, "pooler_activation_fn", "tanh") + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.pooler_dropout = getattr(args, "pooler_dropout", 0.0) + args.encoder_layers_to_keep = getattr(args, "encoder_layers_to_keep", None) + args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.0) + args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.0) + args.spectral_norm_classification_head = getattr( + args, "spectral_nrom_classification_head", False + ) + + +@register_model_architecture("roberta", "roberta_base") +def roberta_base_architecture(args): + base_architecture(args) + + +@register_model_architecture("roberta", "roberta_large") +def roberta_large_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 24) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + base_architecture(args) + + +@register_model_architecture("roberta", "xlm") +def xlm_architecture(args): + args.encoder_layers = getattr(args, "encoder_layers", 16) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1280) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1280 * 4) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/model_camembert.py b/fairseq-tools/fairseq/fairseq/models/roberta/model_camembert.py new file mode 100644 index 00000000..46447546 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/model_camembert.py @@ -0,0 +1,50 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +CamemBERT: a Tasty French Language Model +""" + +from fairseq.models import register_model + +from .hub_interface import RobertaHubInterface +from .model import RobertaModel + + +@register_model("camembert") +class CamembertModel(RobertaModel): + @classmethod + def hub_models(cls): + return { + "camembert": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base.tar.gz", + "camembert.v0": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base.tar.gz", + "camembert-base": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base.tar.gz", + "camembert-large": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-large.tar.gz", + "camembert-base-ccnet": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base-ccnet.tar.gz", + "camembert-base-ccnet-4gb": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base-ccnet-4gb.tar.gz", + "camembert-base-wikipedia-4gb": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base-wikipedia-4gb.tar.gz", + "camembert-base-oscar-4gb": "http://dl.fbaipublicfiles.com/fairseq/models/camembert-base-oscar-4gb.tar.gz", + } + + @classmethod + def from_pretrained( + cls, + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + bpe="sentencepiece", + **kwargs + ): + from fairseq import hub_utils + + x = hub_utils.from_pretrained( + model_name_or_path, + checkpoint_file, + data_name_or_path, + archive_map=cls.hub_models(), + bpe=bpe, + load_checkpoint_heads=True, + **kwargs, + ) + return RobertaHubInterface(x["args"], x["task"], x["models"][0]) diff --git a/fairseq-tools/fairseq/fairseq/models/roberta/model_xlmr.py b/fairseq-tools/fairseq/fairseq/models/roberta/model_xlmr.py new file mode 100644 index 00000000..5886880f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/roberta/model_xlmr.py @@ -0,0 +1,44 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Unsupervised Cross-lingual Representation Learning at Scale +""" + +from fairseq.models import register_model + +from .hub_interface import RobertaHubInterface +from .model import RobertaModel + + +@register_model("xlmr") +class XLMRModel(RobertaModel): + @classmethod + def hub_models(cls): + return { + "xlmr.base": "http://dl.fbaipublicfiles.com/fairseq/models/xlmr.base.tar.gz", + "xlmr.large": "http://dl.fbaipublicfiles.com/fairseq/models/xlmr.large.tar.gz", + } + + @classmethod + def from_pretrained( + cls, + model_name_or_path, + checkpoint_file="model.pt", + data_name_or_path=".", + bpe="sentencepiece", + **kwargs + ): + from fairseq import hub_utils + + x = hub_utils.from_pretrained( + model_name_or_path, + checkpoint_file, + data_name_or_path, + archive_map=cls.hub_models(), + bpe=bpe, + load_checkpoint_heads=True, + **kwargs, + ) + return RobertaHubInterface(x["args"], x["task"], x["models"][0]) diff --git a/fairseq-tools/fairseq/fairseq/models/speech_to_text/__init__.py b/fairseq-tools/fairseq/fairseq/models/speech_to_text/__init__.py new file mode 100644 index 00000000..5d7f59b3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/speech_to_text/__init__.py @@ -0,0 +1,7 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .berard import * # noqa +from .s2t_transformer import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/models/speech_to_text/berard.py b/fairseq-tools/fairseq/fairseq/models/speech_to_text/berard.py new file mode 100644 index 00000000..c505e3ac --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/speech_to_text/berard.py @@ -0,0 +1,606 @@ +#!/usr/bin/env python3 + +from ast import literal_eval +from typing import List, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import checkpoint_utils, utils +from fairseq.data.data_utils import lengths_to_padding_mask +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) + + +@register_model("s2t_berard") +class BerardModel(FairseqEncoderDecoderModel): + """Implementation of a model similar to https://arxiv.org/abs/1802.04200 + + Paper title: End-to-End Automatic Speech Translation of Audiobooks + An implementation is available in tensorflow at + https://github.com/eske/seq2seq + Relevant files in this implementation are the config + (https://github.com/eske/seq2seq/blob/master/config/LibriSpeech/AST.yaml) + and the model code + (https://github.com/eske/seq2seq/blob/master/translate/models.py). + The encoder and decoder try to be close to the original implementation. + The attention is an MLP as in Bahdanau et al. + (https://arxiv.org/abs/1409.0473). + There is no state initialization by averaging the encoder outputs. + """ + + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + parser.add_argument( + "--input-layers", + type=str, + metavar="EXPR", + help="List of linear layer dimensions. These " + "layers are applied to the input features and " + "are followed by tanh and possibly dropout.", + ) + parser.add_argument( + "--dropout", + type=float, + metavar="D", + help="Dropout probability to use in the encoder/decoder. " + "Note that this parameters control dropout in various places, " + "there is no fine-grained control for dropout for embeddings " + "vs LSTM layers for example.", + ) + parser.add_argument( + "--in-channels", + type=int, + metavar="N", + help="Number of encoder input channels. " "Typically value is 1.", + ) + parser.add_argument( + "--conv-layers", + type=str, + metavar="EXPR", + help="List of conv layers " "(format: (channels, kernel, stride)).", + ) + parser.add_argument( + "--num-blstm-layers", + type=int, + metavar="N", + help="Number of encoder bi-LSTM layers.", + ) + parser.add_argument( + "--lstm-size", type=int, metavar="N", help="LSTM hidden size." + ) + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="Embedding dimension of the decoder target tokens.", + ) + parser.add_argument( + "--decoder-hidden-dim", + type=int, + metavar="N", + help="Decoder LSTM hidden dimension.", + ) + parser.add_argument( + "--decoder-num-layers", + type=int, + metavar="N", + help="Number of decoder LSTM layers.", + ) + parser.add_argument( + "--attention-dim", + type=int, + metavar="N", + help="Hidden layer dimension in MLP attention.", + ) + parser.add_argument( + "--output-layer-dim", + type=int, + metavar="N", + help="Hidden layer dim for linear layer prior to output projection.", + ) + parser.add_argument( + "--load-pretrained-encoder-from", + type=str, + metavar="STR", + help="model to take encoder weights from (for initialization)", + ) + parser.add_argument( + "--load-pretrained-decoder-from", + type=str, + metavar="STR", + help="model to take decoder weights from (for initialization)", + ) + + @classmethod + def build_encoder(cls, args, task): + encoder = BerardEncoder( + input_layers=literal_eval(args.input_layers), + conv_layers=literal_eval(args.conv_layers), + in_channels=args.input_channels, + input_feat_per_channel=args.input_feat_per_channel, + num_blstm_layers=args.num_blstm_layers, + lstm_size=args.lstm_size, + dropout=args.dropout, + ) + if getattr(args, "load_pretrained_encoder_from", None): + encoder = checkpoint_utils.load_pretrained_component_from_model( + component=encoder, checkpoint=args.load_pretrained_encoder_from + ) + return encoder + + @classmethod + def build_decoder(cls, args, task): + decoder = LSTMDecoder( + dictionary=task.target_dictionary, + embed_dim=args.decoder_embed_dim, + num_layers=args.decoder_num_layers, + hidden_size=args.decoder_hidden_dim, + dropout=args.dropout, + encoder_output_dim=2 * args.lstm_size, # bidirectional + attention_dim=args.attention_dim, + output_layer_dim=args.output_layer_dim, + ) + if getattr(args, "load_pretrained_decoder_from", None): + decoder = checkpoint_utils.load_pretrained_component_from_model( + component=decoder, checkpoint=args.load_pretrained_decoder_from + ) + return decoder + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + encoder = cls.build_encoder(args, task) + decoder = cls.build_decoder(args, task) + + return cls(encoder, decoder) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + # net_output['encoder_out'] is a (B, T, D) tensor + lprobs = super().get_normalized_probs(net_output, log_probs, sample) + # lprobs is a (B, T, D) tensor + lprobs.batch_first = True + return lprobs + + +class BerardEncoder(FairseqEncoder): + def __init__( + self, + input_layers: List[int], + conv_layers: List[Tuple[int]], + in_channels: int, + input_feat_per_channel: int, + num_blstm_layers: int, + lstm_size: int, + dropout: float, + ): + """ + Args: + input_layers: list of linear layer dimensions. These layers are + applied to the input features and are followed by tanh and + possibly dropout. + conv_layers: list of conv2d layer configurations. A configuration is + a tuple (out_channels, conv_kernel_size, stride). + in_channels: number of input channels. + input_feat_per_channel: number of input features per channel. These + are speech features, typically 40 or 80. + num_blstm_layers: number of bidirectional LSTM layers. + lstm_size: size of the LSTM hidden (and cell) size. + dropout: dropout probability. Dropout can be applied after the + linear layers and LSTM layers but not to the convolutional + layers. + """ + super().__init__(None) + + self.input_layers = nn.ModuleList() + in_features = input_feat_per_channel + for out_features in input_layers: + if dropout > 0: + self.input_layers.append( + nn.Sequential( + nn.Linear(in_features, out_features), nn.Dropout(p=dropout) + ) + ) + else: + self.input_layers.append(nn.Linear(in_features, out_features)) + in_features = out_features + + self.in_channels = in_channels + self.input_dim = input_feat_per_channel + self.conv_kernel_sizes_and_strides = [] + self.conv_layers = nn.ModuleList() + lstm_input_dim = input_layers[-1] + for conv_layer in conv_layers: + out_channels, conv_kernel_size, conv_stride = conv_layer + self.conv_layers.append( + nn.Conv2d( + in_channels, + out_channels, + conv_kernel_size, + stride=conv_stride, + padding=conv_kernel_size // 2, + ) + ) + self.conv_kernel_sizes_and_strides.append((conv_kernel_size, conv_stride)) + in_channels = out_channels + lstm_input_dim //= conv_stride + + lstm_input_dim *= conv_layers[-1][0] + self.lstm_size = lstm_size + self.num_blstm_layers = num_blstm_layers + self.lstm = nn.LSTM( + input_size=lstm_input_dim, + hidden_size=lstm_size, + num_layers=num_blstm_layers, + dropout=dropout, + bidirectional=True, + ) + self.output_dim = 2 * lstm_size # bidirectional + if dropout > 0: + self.dropout = nn.Dropout(p=dropout) + else: + self.dropout = None + + def forward(self, src_tokens, src_lengths=None, **kwargs): + """ + Args + src_tokens: padded tensor (B, T, C * feat) + src_lengths: tensor of original lengths of input utterances (B,) + """ + bsz, max_seq_len, _ = src_tokens.size() + # (B, C, T, feat) + x = ( + src_tokens.view(bsz, max_seq_len, self.in_channels, self.input_dim) + .transpose(1, 2) + .contiguous() + ) + + for input_layer in self.input_layers: + x = input_layer(x) + x = torch.tanh(x) + + for conv_layer in self.conv_layers: + x = conv_layer(x) + + bsz, _, output_seq_len, _ = x.size() + + # (B, C, T, feat) -> (B, T, C, feat) -> (T, B, C, feat) -> + # (T, B, C * feat) + x = x.transpose(1, 2).transpose(0, 1).contiguous().view(output_seq_len, bsz, -1) + + input_lengths = src_lengths.clone() + for k, s in self.conv_kernel_sizes_and_strides: + p = k // 2 + input_lengths = (input_lengths.float() + 2 * p - k) / s + 1 + input_lengths = input_lengths.floor().long() + + packed_x = nn.utils.rnn.pack_padded_sequence(x, input_lengths) + + h0 = x.new(2 * self.num_blstm_layers, bsz, self.lstm_size).zero_() + c0 = x.new(2 * self.num_blstm_layers, bsz, self.lstm_size).zero_() + packed_outs, _ = self.lstm(packed_x, (h0, c0)) + + # unpack outputs and apply dropout + x, output_lengths = nn.utils.rnn.pad_packed_sequence(packed_outs) + if self.dropout is not None: + x = self.dropout(x) + + encoder_padding_mask = ( + lengths_to_padding_mask(output_lengths).to(src_tokens.device).t() + ) + + return { + "encoder_out": x, # (T, B, C) + "encoder_padding_mask": encoder_padding_mask, # (T, B) + } + + def reorder_encoder_out(self, encoder_out, new_order): + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(1, new_order) + return encoder_out + + +class MLPAttention(nn.Module): + """The original attention from Badhanau et al. (2014) + + https://arxiv.org/abs/1409.0473, based on a Multi-Layer Perceptron. + The attention score between position i in the encoder and position j in the + decoder is: alpha_ij = V_a * tanh(W_ae * enc_i + W_ad * dec_j + b_a) + """ + + def __init__(self, decoder_hidden_state_dim, context_dim, attention_dim): + super().__init__() + + self.context_dim = context_dim + self.attention_dim = attention_dim + # W_ae and b_a + self.encoder_proj = nn.Linear(context_dim, self.attention_dim, bias=True) + # W_ad + self.decoder_proj = nn.Linear( + decoder_hidden_state_dim, self.attention_dim, bias=False + ) + # V_a + self.to_scores = nn.Linear(self.attention_dim, 1, bias=False) + + def forward(self, decoder_state, source_hids, encoder_padding_mask): + """The expected input dimensions are: + decoder_state: bsz x decoder_hidden_state_dim + source_hids: src_len x bsz x context_dim + encoder_padding_mask: src_len x bsz + """ + src_len, bsz, _ = source_hids.size() + # (src_len*bsz) x context_dim (to feed through linear) + flat_source_hids = source_hids.view(-1, self.context_dim) + # (src_len*bsz) x attention_dim + encoder_component = self.encoder_proj(flat_source_hids) + # src_len x bsz x attention_dim + encoder_component = encoder_component.view(src_len, bsz, self.attention_dim) + # 1 x bsz x attention_dim + decoder_component = self.decoder_proj(decoder_state).unsqueeze(0) + # Sum with broadcasting and apply the non linearity + # src_len x bsz x attention_dim + hidden_att = torch.tanh( + (decoder_component + encoder_component).view(-1, self.attention_dim) + ) + # Project onto the reals to get attentions scores (src_len x bsz) + attn_scores = self.to_scores(hidden_att).view(src_len, bsz) + + # Mask + softmax (src_len x bsz) + if encoder_padding_mask is not None: + attn_scores = ( + attn_scores.float() + .masked_fill_(encoder_padding_mask, float("-inf")) + .type_as(attn_scores) + ) # FP16 support: cast to float and back + # srclen x bsz + normalized_masked_attn_scores = F.softmax(attn_scores, dim=0) + + # Sum weighted sources (bsz x context_dim) + attn_weighted_context = ( + source_hids * normalized_masked_attn_scores.unsqueeze(2) + ).sum(dim=0) + + return attn_weighted_context, normalized_masked_attn_scores + + +class LSTMDecoder(FairseqIncrementalDecoder): + def __init__( + self, + dictionary, + embed_dim, + num_layers, + hidden_size, + dropout, + encoder_output_dim, + attention_dim, + output_layer_dim, + ): + """ + Args: + dictionary: target text dictionary. + embed_dim: embedding dimension for target tokens. + num_layers: number of LSTM layers. + hidden_size: hidden size for LSTM layers. + dropout: dropout probability. Dropout can be applied to the + embeddings, the LSTM layers, and the context vector. + encoder_output_dim: encoder output dimension (hidden size of + encoder LSTM). + attention_dim: attention dimension for MLP attention. + output_layer_dim: size of the linear layer prior to output + projection. + """ + super().__init__(dictionary) + self.num_layers = num_layers + self.hidden_size = hidden_size + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + self.embed_tokens = nn.Embedding(num_embeddings, embed_dim, padding_idx) + if dropout > 0: + self.dropout = nn.Dropout(p=dropout) + else: + self.dropout = None + + self.layers = nn.ModuleList() + for layer_id in range(num_layers): + input_size = embed_dim if layer_id == 0 else encoder_output_dim + self.layers.append( + nn.LSTMCell(input_size=input_size, hidden_size=hidden_size) + ) + + self.context_dim = encoder_output_dim + self.attention = MLPAttention( + decoder_hidden_state_dim=hidden_size, + context_dim=encoder_output_dim, + attention_dim=attention_dim, + ) + + self.deep_output_layer = nn.Linear( + hidden_size + encoder_output_dim + embed_dim, output_layer_dim + ) + self.output_projection = nn.Linear(output_layer_dim, num_embeddings) + + def forward( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **kwargs + ): + encoder_padding_mask = encoder_out["encoder_padding_mask"] + encoder_outs = encoder_out["encoder_out"] + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + bsz, seqlen = prev_output_tokens.size() + + srclen = encoder_outs.size(0) + + # embed tokens + embeddings = self.embed_tokens(prev_output_tokens) + x = embeddings + if self.dropout is not None: + x = self.dropout(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # initialize previous states (or get from cache during incremental + # generation) + cached_state = utils.get_incremental_state( + self, incremental_state, "cached_state" + ) + if cached_state is not None: + prev_hiddens, prev_cells = cached_state + else: + prev_hiddens = [encoder_out["encoder_out"].mean(dim=0)] * self.num_layers + prev_cells = [x.new_zeros(bsz, self.hidden_size)] * self.num_layers + + attn_scores = x.new_zeros(bsz, srclen) + attention_outs = [] + outs = [] + for j in range(seqlen): + input = x[j, :, :] + attention_out = None + for i, layer in enumerate(self.layers): + # the previous state is one layer below except for the bottom + # layer where the previous state is the state emitted by the + # top layer + hidden, cell = layer( + input, + ( + prev_hiddens[(i - 1) % self.num_layers], + prev_cells[(i - 1) % self.num_layers], + ), + ) + if self.dropout is not None: + hidden = self.dropout(hidden) + prev_hiddens[i] = hidden + prev_cells[i] = cell + if attention_out is None: + attention_out, attn_scores = self.attention( + hidden, encoder_outs, encoder_padding_mask + ) + if self.dropout is not None: + attention_out = self.dropout(attention_out) + attention_outs.append(attention_out) + input = attention_out + + # collect the output of the top layer + outs.append(hidden) + + # cache previous states (no-op except during incremental generation) + utils.set_incremental_state( + self, incremental_state, "cached_state", (prev_hiddens, prev_cells) + ) + + # collect outputs across time steps + x = torch.cat(outs, dim=0).view(seqlen, bsz, self.hidden_size) + attention_outs_concat = torch.cat(attention_outs, dim=0).view( + seqlen, bsz, self.context_dim + ) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + attention_outs_concat = attention_outs_concat.transpose(0, 1) + + # concat LSTM output, attention output and embedding + # before output projection + x = torch.cat((x, attention_outs_concat, embeddings), dim=2) + x = self.deep_output_layer(x) + x = torch.tanh(x) + if self.dropout is not None: + x = self.dropout(x) + # project back to size of vocabulary + x = self.output_projection(x) + + # to return the full attn_scores tensor, we need to fix the decoder + # to account for subsampling input frames + # return x, attn_scores + return x, None + + def reorder_incremental_state(self, incremental_state, new_order): + super().reorder_incremental_state(incremental_state, new_order) + cached_state = utils.get_incremental_state( + self, incremental_state, "cached_state" + ) + if cached_state is None: + return + + def reorder_state(state): + if isinstance(state, list): + return [reorder_state(state_i) for state_i in state] + return state.index_select(0, new_order) + + new_state = tuple(map(reorder_state, cached_state)) + utils.set_incremental_state(self, incremental_state, "cached_state", new_state) + + +@register_model_architecture(model_name="s2t_berard", arch_name="s2t_berard") +def berard(args): + """The original version: "End-to-End Automatic Speech Translation of + Audiobooks" (https://arxiv.org/abs/1802.04200) + """ + args.input_layers = getattr(args, "input_layers", "[256, 128]") + args.conv_layers = getattr(args, "conv_layers", "[(16, 3, 2), (16, 3, 2)]") + args.num_blstm_layers = getattr(args, "num_blstm_layers", 3) + args.lstm_size = getattr(args, "lstm_size", 256) + args.dropout = getattr(args, "dropout", 0.2) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 128) + args.decoder_num_layers = getattr(args, "decoder_num_layers", 2) + args.decoder_hidden_dim = getattr(args, "decoder_hidden_dim", 512) + args.attention_dim = getattr(args, "attention_dim", 512) + args.output_layer_dim = getattr(args, "output_layer_dim", 128) + args.load_pretrained_encoder_from = getattr( + args, "load_pretrained_encoder_from", None + ) + args.load_pretrained_decoder_from = getattr( + args, "load_pretrained_decoder_from", None + ) + + +@register_model_architecture(model_name="s2t_berard", arch_name="s2t_berard_256_3_3") +def berard_256_3_3(args): + """Used in + * "Harnessing Indirect Training Data for End-to-End Automatic Speech + Translation: Tricks of the Trade" (https://arxiv.org/abs/1909.06515) + * "CoVoST: A Diverse Multilingual Speech-To-Text Translation Corpus" + (https://arxiv.org/pdf/2002.01320.pdf) + * "Self-Supervised Representations Improve End-to-End Speech Translation" + (https://arxiv.org/abs/2006.12124) + """ + args.decoder_num_layers = getattr(args, "decoder_num_layers", 3) + berard(args) + + +@register_model_architecture(model_name="s2t_berard", arch_name="s2t_berard_512_3_2") +def berard_512_3_2(args): + args.num_blstm_layers = getattr(args, "num_blstm_layers", 3) + args.lstm_size = getattr(args, "lstm_size", 512) + args.dropout = getattr(args, "dropout", 0.3) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 256) + args.decoder_num_layers = getattr(args, "decoder_num_layers", 2) + args.decoder_hidden_dim = getattr(args, "decoder_hidden_dim", 1024) + args.attention_dim = getattr(args, "attention_dim", 512) + args.output_layer_dim = getattr(args, "output_layer_dim", 256) + berard(args) + + +@register_model_architecture(model_name="s2t_berard", arch_name="s2t_berard_512_5_3") +def berard_512_5_3(args): + args.num_blstm_layers = getattr(args, "num_blstm_layers", 5) + args.lstm_size = getattr(args, "lstm_size", 512) + args.dropout = getattr(args, "dropout", 0.3) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 256) + args.decoder_num_layers = getattr(args, "decoder_num_layers", 3) + args.decoder_hidden_dim = getattr(args, "decoder_hidden_dim", 1024) + args.attention_dim = getattr(args, "attention_dim", 512) + args.output_layer_dim = getattr(args, "output_layer_dim", 256) + berard(args) diff --git a/fairseq-tools/fairseq/fairseq/models/speech_to_text/s2t_transformer.py b/fairseq-tools/fairseq/fairseq/models/speech_to_text/s2t_transformer.py new file mode 100644 index 00000000..8e48964f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/speech_to_text/s2t_transformer.py @@ -0,0 +1,473 @@ +#!/usr/bin/env python3 + +import logging +import math +from typing import Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +from fairseq import checkpoint_utils, utils +from fairseq.data.data_utils import lengths_to_padding_mask +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + register_model, + register_model_architecture, +) +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.models.transformer import Embedding, TransformerDecoder +from fairseq.modules import ( + FairseqDropout, + LayerNorm, + PositionalEmbedding, + TransformerEncoderLayer, +) +from torch import Tensor + + +logger = logging.getLogger(__name__) + + +class Conv1dSubsampler(nn.Module): + """Convolutional subsampler: a stack of 1D convolution (along temporal + dimension) followed by non-linear activation via gated linear units + (https://arxiv.org/abs/1911.08460) + + Args: + in_channels (int): the number of input channels + mid_channels (int): the number of intermediate channels + out_channels (int): the number of output channels + kernel_sizes (List[int]): the kernel size for each convolutional layer + """ + + def __init__( + self, + in_channels: int, + mid_channels: int, + out_channels: int, + kernel_sizes: List[int] = (3, 3), + ): + super(Conv1dSubsampler, self).__init__() + self.n_layers = len(kernel_sizes) + self.conv_layers = nn.ModuleList( + nn.Conv1d( + in_channels if i == 0 else mid_channels // 2, + mid_channels if i < self.n_layers - 1 else out_channels * 2, + k, + stride=2, + padding=k // 2, + ) + for i, k in enumerate(kernel_sizes) + ) + + def get_out_seq_lens_tensor(self, in_seq_lens_tensor): + out = in_seq_lens_tensor.clone() + for _ in range(self.n_layers): + out = ((out.float() - 1) / 2 + 1).floor().long() + return out + + def forward(self, src_tokens, src_lengths): + bsz, in_seq_len, _ = src_tokens.size() # B x T x (C x D) + x = src_tokens.transpose(1, 2).contiguous() # -> B x (C x D) x T + for conv in self.conv_layers: + x = conv(x) + x = nn.functional.glu(x, dim=1) + _, _, out_seq_len = x.size() + x = x.transpose(1, 2).transpose(0, 1).contiguous() # -> T x B x (C x D) + return x, self.get_out_seq_lens_tensor(src_lengths) + + +@register_model("s2t_transformer") +class S2TTransformerModel(FairseqEncoderDecoderModel): + """Adapted Transformer model (https://arxiv.org/abs/1706.03762) for + speech-to-text tasks. The Transformer encoder/decoder remains the same. + A trainable input subsampler is prepended to the Transformer encoder to + project inputs into the encoder dimension as well as downsample input + sequence for computational efficiency.""" + + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # input + parser.add_argument( + "--conv-kernel-sizes", + type=str, + metavar="N", + help="kernel sizes of Conv1d subsampling layers", + ) + parser.add_argument( + "--conv-channels", + type=int, + metavar="N", + help="# of channels in Conv1d subsampling layers", + ) + # Transformer + parser.add_argument( + "--activation-fn", + type=str, + default="relu", + choices=utils.get_available_activation_fns(), + help="activation function to use", + ) + parser.add_argument( + "--dropout", type=float, metavar="D", help="dropout probability" + ) + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights", + ) + parser.add_argument( + "--activation-dropout", + "--relu-dropout", + type=float, + metavar="D", + help="dropout probability after activation in FFN.", + ) + parser.add_argument( + "--encoder-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension", + ) + parser.add_argument( + "--encoder-ffn-embed-dim", + type=int, + metavar="N", + help="encoder embedding dimension for FFN", + ) + parser.add_argument( + "--encoder-layers", type=int, metavar="N", help="num encoder layers" + ) + parser.add_argument( + "--encoder-attention-heads", + type=int, + metavar="N", + help="num encoder attention heads", + ) + parser.add_argument( + "--encoder-normalize-before", + action="store_true", + help="apply layernorm before each encoder block", + ) + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-ffn-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension for FFN", + ) + parser.add_argument( + "--decoder-layers", type=int, metavar="N", help="num decoder layers" + ) + parser.add_argument( + "--decoder-attention-heads", + type=int, + metavar="N", + help="num decoder attention heads", + ) + parser.add_argument( + "--decoder-normalize-before", + action="store_true", + help="apply layernorm before each decoder block", + ) + parser.add_argument( + "--layernorm-embedding", + action="store_true", + help="add layernorm to embedding", + ) + parser.add_argument( + "--no-scale-embedding", + action="store_true", + help="if True, dont scale embeddings", + ) + parser.add_argument( + "--load-pretrained-encoder-from", + type=str, + metavar="STR", + help="model to take encoder weights from (for initialization)", + ) + + @classmethod + def build_encoder(cls, args): + encoder = S2TTransformerEncoder(args) + if getattr(args, "load_pretrained_encoder_from", None): + encoder = checkpoint_utils.load_pretrained_component_from_model( + component=encoder, checkpoint=args.load_pretrained_encoder_from + ) + logger.info( + f"loaded pretrained encoder from: " + f"{args.load_pretrained_encoder_from}" + ) + return encoder + + @classmethod + def build_decoder(cls, args, task, embed_tokens): + return TransformerDecoderScriptable(args, task.target_dictionary, embed_tokens) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + def build_embedding(dictionary, embed_dim): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + return Embedding(num_embeddings, embed_dim, padding_idx) + + decoder_embed_tokens = build_embedding( + task.target_dictionary, args.decoder_embed_dim + ) + encoder = cls.build_encoder(args) + decoder = cls.build_decoder(args, task, decoder_embed_tokens) + return cls(encoder, decoder) + + def get_normalized_probs( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + # net_output['encoder_out'] is a (B, T, D) tensor + lprobs = self.get_normalized_probs_scriptable(net_output, log_probs, sample) + lprobs.batch_first = True + return lprobs + + def forward(self, src_tokens, src_lengths, prev_output_tokens): + """ + The forward method inherited from the base class has a **kwargs + argument in its input, which is not supported in torchscript. This + method overrites the forward method definition without **kwargs. + """ + encoder_out = self.encoder(src_tokens=src_tokens, src_lengths=src_lengths) + decoder_out = self.decoder( + prev_output_tokens=prev_output_tokens, encoder_out=encoder_out + ) + return decoder_out + + +class S2TTransformerEncoder(FairseqEncoder): + """Speech-to-text Transformer encoder that consists of input subsampler and + Transformer encoder.""" + + def __init__(self, args): + super().__init__(None) + + self.dropout_module = FairseqDropout( + p=args.dropout, module_name=self.__class__.__name__ + ) + self.embed_scale = math.sqrt(args.encoder_embed_dim) + if args.no_scale_embedding: + self.embed_scale = 1.0 + self.padding_idx = 1 + + self.subsample = Conv1dSubsampler( + args.input_feat_per_channel * args.input_channels, + args.conv_channels, + args.encoder_embed_dim, + [int(k) for k in args.conv_kernel_sizes.split(",")], + ) + + self.embed_positions = PositionalEmbedding( + args.max_source_positions, args.encoder_embed_dim, self.padding_idx + ) + + self.transformer_layers = nn.ModuleList( + [TransformerEncoderLayer(args) for _ in range(args.encoder_layers)] + ) + if args.encoder_normalize_before: + self.layer_norm = LayerNorm(args.encoder_embed_dim) + else: + self.layer_norm = None + + def forward(self, src_tokens, src_lengths): + x, input_lengths = self.subsample(src_tokens, src_lengths) + x = self.embed_scale * x + + encoder_padding_mask = lengths_to_padding_mask(input_lengths) + positions = self.embed_positions(encoder_padding_mask).transpose(0, 1) + x += positions + x = self.dropout_module(x) + + for layer in self.transformer_layers: + x = layer(x, encoder_padding_mask) + + if not encoder_padding_mask.any(): + encoder_padding_mask = None + + if self.layer_norm is not None: + x = self.layer_norm(x) + + return EncoderOut( + encoder_out=x, + encoder_padding_mask=encoder_padding_mask, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + @torch.jit.export + def reorder_encoder_out(self, encoder_out: EncoderOut, new_order): + """ + Since encoder_padding_mask and encoder_embedding are both of type + Optional[Tensor] in EncoderOut, they need to be copied as local + variables for Torchscript Optional refinement + """ + + encoder_padding_mask: Optional[Tensor] = encoder_out.encoder_padding_mask + encoder_embedding: Optional[Tensor] = encoder_out.encoder_embedding + + new_encoder_out = ( + encoder_out.encoder_out + if encoder_out.encoder_out is None + else encoder_out.encoder_out.index_select(1, new_order) + ) + + new_encoder_padding_mask = ( + encoder_padding_mask + if encoder_padding_mask is None + else encoder_padding_mask.index_select(0, new_order) + ) + + new_encoder_embedding = ( + encoder_embedding + if encoder_embedding is None + else encoder_embedding.index_select(0, new_order) + ) + + encoder_states = encoder_out.encoder_states + if encoder_states is not None: + for idx, state in enumerate(encoder_states): + encoder_states[idx] = state.index_select(1, new_order) + + return EncoderOut( + encoder_out=new_encoder_out, # T x B x C + encoder_padding_mask=new_encoder_padding_mask, # B x T + encoder_embedding=new_encoder_embedding, # B x T x C + encoder_states=encoder_states, # List[T x B x C] + src_tokens=None, + src_lengths=None, + ) + + +class TransformerDecoderScriptable(TransformerDecoder): + def extract_features( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + full_context_alignment: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + ): + # call scriptable method from parent class + x, _ = self.extract_features_scriptable( + prev_output_tokens, + encoder_out, + incremental_state, + full_context_alignment, + alignment_layer, + alignment_heads, + ) + return x, None + + +@register_model_architecture(model_name="s2t_transformer", arch_name="s2t_transformer") +def base_architecture(args): + # Convolutional subsampler + args.conv_kernel_sizes = getattr(args, "conv_kernel_sizes", "5,5") + args.conv_channels = getattr(args, "conv_channels", 1024) + # Transformer + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", args.dropout) + args.activation_dropout = getattr(args, "activation_dropout", args.dropout) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0.0) + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + args.quant_noise_pq = getattr(args, "quant_noise_pq", 0) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_s") +def s2t_transformer_s(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 256) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 256 * 8) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.dropout = getattr(args, "dropout", 0.1) + base_architecture(args) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_sp") +def s2t_transformer_sp(args): + args.encoder_layers = getattr(args, "encoder_layers", 16) + s2t_transformer_s(args) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_m") +def s2t_transformer_m(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 512 * 4) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.dropout = getattr(args, "dropout", 0.15) + base_architecture(args) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_mp") +def s2t_transformer_mp(args): + args.encoder_layers = getattr(args, "encoder_layers", 16) + s2t_transformer_m(args) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_l") +def s2t_transformer_l(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024 * 4) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.2) + base_architecture(args) + + +@register_model_architecture("s2t_transformer", "s2t_transformer_lp") +def s2t_transformer_lp(args): + args.encoder_layers = getattr(args, "encoder_layers", 16) + s2t_transformer_l(args) diff --git a/fairseq-tools/fairseq/fairseq/models/transformer.py b/fairseq-tools/fairseq/fairseq/models/transformer.py new file mode 100644 index 00000000..fbb7ce23 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/transformer.py @@ -0,0 +1,1018 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Any, Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +from fairseq import utils +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.modules import ( + AdaptiveSoftmax, + FairseqDropout, + LayerDropModuleList, + LayerNorm, + PositionalEmbedding, + SinusoidalPositionalEmbedding, + TransformerDecoderLayer, + TransformerEncoderLayer, +) +from fairseq.modules.quant_noise import quant_noise as apply_quant_noise_ +from torch import Tensor + + +DEFAULT_MAX_SOURCE_POSITIONS = 1024 +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@register_model("transformer") +class TransformerModel(FairseqEncoderDecoderModel): + """ + Transformer model from `"Attention Is All You Need" (Vaswani, et al, 2017) + <https://arxiv.org/abs/1706.03762>`_. + + Args: + encoder (TransformerEncoder): the encoder + decoder (TransformerDecoder): the decoder + + The Transformer model provides the following named architectures and + command-line arguments: + + .. argparse:: + :ref: fairseq.models.transformer_parser + :prog: + """ + + @classmethod + def hub_models(cls): + # fmt: off + + def moses_subword(path): + return { + 'path': path, + 'tokenizer': 'moses', + 'bpe': 'subword_nmt', + } + + def moses_fastbpe(path): + return { + 'path': path, + 'tokenizer': 'moses', + 'bpe': 'fastbpe', + } + + return { + 'transformer.wmt14.en-fr': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/wmt14.en-fr.joined-dict.transformer.tar.bz2'), + 'transformer.wmt16.en-de': 'https://dl.fbaipublicfiles.com/fairseq/models/wmt16.en-de.joined-dict.transformer.tar.bz2', + 'transformer.wmt18.en-de': moses_subword('https://dl.fbaipublicfiles.com/fairseq/models/wmt18.en-de.ensemble.tar.gz'), + 'transformer.wmt19.en-de': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-de.joined-dict.ensemble.tar.gz'), + 'transformer.wmt19.en-ru': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-ru.ensemble.tar.gz'), + 'transformer.wmt19.de-en': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.de-en.joined-dict.ensemble.tar.gz'), + 'transformer.wmt19.ru-en': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.ru-en.ensemble.tar.gz'), + 'transformer.wmt19.en-de.single_model': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-de.joined-dict.single_model.tar.gz'), + 'transformer.wmt19.en-ru.single_model': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.en-ru.single_model.tar.gz'), + 'transformer.wmt19.de-en.single_model': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.de-en.joined-dict.single_model.tar.gz'), + 'transformer.wmt19.ru-en.single_model': moses_fastbpe('https://dl.fbaipublicfiles.com/fairseq/models/wmt19.ru-en.single_model.tar.gz'), + } + # fmt: on + + def __init__(self, args, encoder, decoder): + super().__init__(encoder, decoder) + self.args = args + self.supports_align_args = True + + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--activation-fn', + choices=utils.get_available_activation_fns(), + help='activation function to use') + parser.add_argument('--dropout', type=float, metavar='D', + help='dropout probability') + parser.add_argument('--attention-dropout', type=float, metavar='D', + help='dropout probability for attention weights') + parser.add_argument('--activation-dropout', '--relu-dropout', type=float, metavar='D', + help='dropout probability after activation in FFN.') + parser.add_argument('--encoder-embed-path', type=str, metavar='STR', + help='path to pre-trained encoder embedding') + parser.add_argument('--encoder-embed-dim', type=int, metavar='N', + help='encoder embedding dimension') + parser.add_argument('--encoder-ffn-embed-dim', type=int, metavar='N', + help='encoder embedding dimension for FFN') + parser.add_argument('--encoder-layers', type=int, metavar='N', + help='num encoder layers') + parser.add_argument('--encoder-attention-heads', type=int, metavar='N', + help='num encoder attention heads') + parser.add_argument('--encoder-normalize-before', action='store_true', + help='apply layernorm before each encoder block') + parser.add_argument('--encoder-learned-pos', action='store_true', + help='use learned positional embeddings in the encoder') + parser.add_argument('--decoder-embed-path', type=str, metavar='STR', + help='path to pre-trained decoder embedding') + parser.add_argument('--decoder-embed-dim', type=int, metavar='N', + help='decoder embedding dimension') + parser.add_argument('--decoder-ffn-embed-dim', type=int, metavar='N', + help='decoder embedding dimension for FFN') + parser.add_argument('--decoder-layers', type=int, metavar='N', + help='num decoder layers') + parser.add_argument('--decoder-attention-heads', type=int, metavar='N', + help='num decoder attention heads') + parser.add_argument('--decoder-learned-pos', action='store_true', + help='use learned positional embeddings in the decoder') + parser.add_argument('--decoder-normalize-before', action='store_true', + help='apply layernorm before each decoder block') + parser.add_argument('--decoder-output-dim', type=int, metavar='N', + help='decoder output dimension (extra linear layer ' + 'if different from decoder embed dim') + parser.add_argument('--share-decoder-input-output-embed', action='store_true', + help='share decoder input and output embeddings') + parser.add_argument('--share-all-embeddings', action='store_true', + help='share encoder, decoder and output embeddings' + ' (requires shared dictionary and embed dim)') + parser.add_argument('--no-token-positional-embeddings', default=False, action='store_true', + help='if set, disables positional embeddings (outside self attention)') + parser.add_argument('--adaptive-softmax-cutoff', metavar='EXPR', + help='comma separated list of adaptive softmax cutoff points. ' + 'Must be used with adaptive_loss criterion'), + parser.add_argument('--adaptive-softmax-dropout', type=float, metavar='D', + help='sets adaptive softmax dropout for the tail projections') + parser.add_argument('--layernorm-embedding', action='store_true', + help='add layernorm to embedding') + parser.add_argument('--no-scale-embedding', action='store_true', + help='if True, dont scale embeddings') + # args for "Cross+Self-Attention for Transformer Models" (Peitz et al., 2019) + parser.add_argument('--no-cross-attention', default=False, action='store_true', + help='do not perform cross-attention') + parser.add_argument('--cross-self-attention', default=False, action='store_true', + help='perform cross+self-attention') + # args for "Reducing Transformer Depth on Demand with Structured Dropout" (Fan et al., 2019) + parser.add_argument('--encoder-layerdrop', type=float, metavar='D', default=0, + help='LayerDrop probability for encoder') + parser.add_argument('--decoder-layerdrop', type=float, metavar='D', default=0, + help='LayerDrop probability for decoder') + parser.add_argument('--encoder-layers-to-keep', default=None, + help='which layers to *keep* when pruning as a comma-separated list') + parser.add_argument('--decoder-layers-to-keep', default=None, + help='which layers to *keep* when pruning as a comma-separated list') + # args for Training with Quantization Noise for Extreme Model Compression ({Fan*, Stock*} et al., 2020) + parser.add_argument('--quant-noise-pq', type=float, metavar='D', default=0, + help='iterative PQ quantization noise at training time') + parser.add_argument('--quant-noise-pq-block-size', type=int, metavar='D', default=8, + help='block size of quantization noise at training time') + parser.add_argument('--quant-noise-scalar', type=float, metavar='D', default=0, + help='scalar quantization noise and scalar quantization at training time') + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if args.encoder_layers_to_keep: + args.encoder_layers = len(args.encoder_layers_to_keep.split(",")) + if args.decoder_layers_to_keep: + args.decoder_layers = len(args.decoder_layers_to_keep.split(",")) + + if getattr(args, "max_source_positions", None) is None: + args.max_source_positions = DEFAULT_MAX_SOURCE_POSITIONS + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = DEFAULT_MAX_TARGET_POSITIONS + + src_dict, tgt_dict = task.source_dictionary, task.target_dictionary + + if args.share_all_embeddings: + if src_dict != tgt_dict: + raise ValueError("--share-all-embeddings requires a joined dictionary") + if args.encoder_embed_dim != args.decoder_embed_dim: + raise ValueError( + "--share-all-embeddings requires --encoder-embed-dim to match --decoder-embed-dim" + ) + if args.decoder_embed_path and ( + args.decoder_embed_path != args.encoder_embed_path + ): + raise ValueError( + "--share-all-embeddings not compatible with --decoder-embed-path" + ) + encoder_embed_tokens = cls.build_embedding( + args, src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = encoder_embed_tokens + args.share_decoder_input_output_embed = True + else: + encoder_embed_tokens = cls.build_embedding( + args, src_dict, args.encoder_embed_dim, args.encoder_embed_path + ) + decoder_embed_tokens = cls.build_embedding( + args, tgt_dict, args.decoder_embed_dim, args.decoder_embed_path + ) + + encoder = cls.build_encoder(args, src_dict, encoder_embed_tokens) + decoder = cls.build_decoder(args, tgt_dict, decoder_embed_tokens) + return cls(args, encoder, decoder) + + @classmethod + def build_embedding(cls, args, dictionary, embed_dim, path=None): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + + emb = Embedding(num_embeddings, embed_dim, padding_idx) + # if provided, load from preloaded dictionaries + if path: + embed_dict = utils.parse_embedding(path) + utils.load_embedding(embed_dict, dictionary, emb) + return emb + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerEncoder(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerDecoder( + args, + tgt_dict, + embed_tokens, + no_encoder_attn=getattr(args, "no_cross_attention", False), + ) + + # TorchScript doesn't support optional arguments with variable length (**kwargs). + # Current workaround is to add union of all arguments in child classes. + def forward( + self, + src_tokens, + src_lengths, + prev_output_tokens, + return_all_hiddens: bool = True, + features_only: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + ): + """ + Run the forward pass for an encoder-decoder model. + + Copied from the base class, but without ``**kwargs``, + which are not supported by TorchScript. + """ + encoder_out = self.encoder( + src_tokens, src_lengths=src_lengths, return_all_hiddens=return_all_hiddens + ) + decoder_out = self.decoder( + prev_output_tokens, + encoder_out=encoder_out, + features_only=features_only, + alignment_layer=alignment_layer, + alignment_heads=alignment_heads, + src_lengths=src_lengths, + return_all_hiddens=return_all_hiddens, + ) + return decoder_out + + # Since get_normalized_probs is in the Fairseq Model which is not scriptable, + # I rewrite the get_normalized_probs from Base Class to call the + # helper function in the Base Class. + @torch.jit.export + def get_normalized_probs( + self, + net_output: Tuple[Tensor, Optional[Dict[str, List[Optional[Tensor]]]]], + log_probs: bool, + sample: Optional[Dict[str, Tensor]] = None, + ): + """Get normalized probabilities (or log probs) from a net's output.""" + return self.get_normalized_probs_scriptable(net_output, log_probs, sample) + + +class TransformerEncoder(FairseqEncoder): + """ + Transformer encoder consisting of *args.encoder_layers* layers. Each layer + is a :class:`TransformerEncoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): encoding dictionary + embed_tokens (torch.nn.Embedding): input embedding + """ + + def __init__(self, args, dictionary, embed_tokens): + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([3])) + + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.encoder_layerdrop = args.encoder_layerdrop + + embed_dim = embed_tokens.embedding_dim + self.padding_idx = embed_tokens.padding_idx + self.max_source_positions = args.max_source_positions + + self.embed_tokens = embed_tokens + + self.embed_scale = 1.0 if args.no_scale_embedding else math.sqrt(embed_dim) + + self.embed_positions = ( + PositionalEmbedding( + args.max_source_positions, + embed_dim, + self.padding_idx, + learned=args.encoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + if getattr(args, "layernorm_embedding", False): + self.layernorm_embedding = LayerNorm(embed_dim) + else: + self.layernorm_embedding = None + + if not args.adaptive_input and args.quant_noise_pq > 0: + self.quant_noise = apply_quant_noise_( + nn.Linear(embed_dim, embed_dim, bias=False), + args.quant_noise_pq, + args.quant_noise_pq_block_size, + ) + else: + self.quant_noise = None + + if self.encoder_layerdrop > 0.0: + self.layers = LayerDropModuleList(p=self.encoder_layerdrop) + else: + self.layers = nn.ModuleList([]) + self.layers.extend( + [self.build_encoder_layer(args) for i in range(args.encoder_layers)] + ) + self.num_layers = len(self.layers) + + if args.encoder_normalize_before: + self.layer_norm = LayerNorm(embed_dim) + else: + self.layer_norm = None + + def build_encoder_layer(self, args): + return TransformerEncoderLayer(args) + + def forward_embedding( + self, src_tokens, token_embedding: Optional[torch.Tensor] = None + ): + # embed tokens and positions + if token_embedding is None: + token_embedding = self.embed_tokens(src_tokens) + x = embed = self.embed_scale * token_embedding + if self.embed_positions is not None: + x = embed + self.embed_positions(src_tokens) + if self.layernorm_embedding is not None: + x = self.layernorm_embedding(x) + x = self.dropout_module(x) + if self.quant_noise is not None: + x = self.quant_noise(x) + return x, embed + + def forward( + self, + src_tokens, + src_lengths, + return_all_hiddens: bool = False, + token_embeddings: Optional[torch.Tensor] = None, + ): + """ + Args: + src_tokens (LongTensor): tokens in the source language of shape + `(batch, src_len)` + src_lengths (torch.LongTensor): lengths of each source sentence of + shape `(batch)` + return_all_hiddens (bool, optional): also return all of the + intermediate hidden states (default: False). + token_embeddings (torch.Tensor, optional): precomputed embeddings + default `None` will recompute embeddings + + Returns: + namedtuple: + - **encoder_out** (Tensor): the last encoder layer's output of + shape `(src_len, batch, embed_dim)` + - **encoder_padding_mask** (ByteTensor): the positions of + padding elements of shape `(batch, src_len)` + - **encoder_embedding** (Tensor): the (scaled) embedding lookup + of shape `(batch, src_len, embed_dim)` + - **encoder_states** (List[Tensor]): all intermediate + hidden states of shape `(src_len, batch, embed_dim)`. + Only populated if *return_all_hiddens* is True. + """ + x, encoder_embedding = self.forward_embedding(src_tokens, token_embeddings) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + # compute padding mask + encoder_padding_mask = src_tokens.eq(self.padding_idx) + + encoder_states = [] if return_all_hiddens else None + + # encoder layers + for layer in self.layers: + x = layer(x, encoder_padding_mask) + if return_all_hiddens: + assert encoder_states is not None + encoder_states.append(x) + + if self.layer_norm is not None: + x = self.layer_norm(x) + + return EncoderOut( + encoder_out=x, # T x B x C + encoder_padding_mask=encoder_padding_mask, # B x T + encoder_embedding=encoder_embedding, # B x T x C + encoder_states=encoder_states, # List[T x B x C] + src_tokens=None, + src_lengths=None, + ) + + @torch.jit.export + def reorder_encoder_out(self, encoder_out: EncoderOut, new_order): + """ + Reorder encoder output according to *new_order*. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + *encoder_out* rearranged according to *new_order* + """ + """ + Since encoder_padding_mask and encoder_embedding are both of type + Optional[Tensor] in EncoderOut, they need to be copied as local + variables for Torchscript Optional refinement + """ + encoder_padding_mask: Optional[Tensor] = encoder_out.encoder_padding_mask + encoder_embedding: Optional[Tensor] = encoder_out.encoder_embedding + + new_encoder_out = ( + encoder_out.encoder_out + if encoder_out.encoder_out is None + else encoder_out.encoder_out.index_select(1, new_order) + ) + new_encoder_padding_mask = ( + encoder_padding_mask + if encoder_padding_mask is None + else encoder_padding_mask.index_select(0, new_order) + ) + new_encoder_embedding = ( + encoder_embedding + if encoder_embedding is None + else encoder_embedding.index_select(0, new_order) + ) + src_tokens = encoder_out.src_tokens + if src_tokens is not None: + src_tokens = src_tokens.index_select(0, new_order) + + src_lengths = encoder_out.src_lengths + if src_lengths is not None: + src_lengths = src_lengths.index_select(0, new_order) + + encoder_states = encoder_out.encoder_states + if encoder_states is not None: + for idx, state in enumerate(encoder_states): + encoder_states[idx] = state.index_select(1, new_order) + + return EncoderOut( + encoder_out=new_encoder_out, # T x B x C + encoder_padding_mask=new_encoder_padding_mask, # B x T + encoder_embedding=new_encoder_embedding, # B x T x C + encoder_states=encoder_states, # List[T x B x C] + src_tokens=src_tokens, # B x T + src_lengths=src_lengths, # B x 1 + ) + + def max_positions(self): + """Maximum input length supported by the encoder.""" + if self.embed_positions is None: + return self.max_source_positions + return min(self.max_source_positions, self.embed_positions.max_positions) + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + if isinstance(self.embed_positions, SinusoidalPositionalEmbedding): + weights_key = "{}.embed_positions.weights".format(name) + if weights_key in state_dict: + print("deleting {0}".format(weights_key)) + del state_dict[weights_key] + state_dict[ + "{}.embed_positions._float_tensor".format(name) + ] = torch.FloatTensor(1) + for i in range(self.num_layers): + # update layer norms + self.layers[i].upgrade_state_dict_named( + state_dict, "{}.layers.{}".format(name, i) + ) + + version_key = "{}.version".format(name) + if utils.item(state_dict.get(version_key, torch.Tensor([1]))[0]) < 2: + # earlier checkpoints did not normalize after the stack of layers + self.layer_norm = None + self.normalize = False + state_dict[version_key] = torch.Tensor([1]) + return state_dict + + +class TransformerDecoder(FairseqIncrementalDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + self.args = args + super().__init__(dictionary) + self.register_buffer("version", torch.Tensor([3])) + self._future_mask = torch.empty(0) + + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.decoder_layerdrop = args.decoder_layerdrop + self.share_input_output_embed = args.share_decoder_input_output_embed + + input_embed_dim = embed_tokens.embedding_dim + embed_dim = args.decoder_embed_dim + self.embed_dim = embed_dim + self.output_embed_dim = args.decoder_output_dim + + self.padding_idx = embed_tokens.padding_idx + self.max_target_positions = args.max_target_positions + + self.embed_tokens = embed_tokens + + self.embed_scale = 1.0 if args.no_scale_embedding else math.sqrt(embed_dim) + + if not args.adaptive_input and args.quant_noise_pq > 0: + self.quant_noise = apply_quant_noise_( + nn.Linear(embed_dim, embed_dim, bias=False), + args.quant_noise_pq, + args.quant_noise_pq_block_size, + ) + else: + self.quant_noise = None + + self.project_in_dim = ( + Linear(input_embed_dim, embed_dim, bias=False) + if embed_dim != input_embed_dim + else None + ) + + self.embed_positions = ( + PositionalEmbedding( + args.max_target_positions, + embed_dim, + self.padding_idx, + learned=args.decoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + if getattr(args, "layernorm_embedding", False): + self.layernorm_embedding = LayerNorm(embed_dim) + else: + self.layernorm_embedding = None + + self.cross_self_attention = getattr(args, "cross_self_attention", False) + + if self.decoder_layerdrop > 0.0: + self.layers = LayerDropModuleList(p=self.decoder_layerdrop) + else: + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + self.build_decoder_layer(args, no_encoder_attn) + for _ in range(args.decoder_layers) + ] + ) + self.num_layers = len(self.layers) + + if args.decoder_normalize_before and not getattr( + args, "no_decoder_final_norm", False + ): + self.layer_norm = LayerNorm(embed_dim) + else: + self.layer_norm = None + + self.project_out_dim = ( + Linear(embed_dim, self.output_embed_dim, bias=False) + if embed_dim != self.output_embed_dim and not args.tie_adaptive_weights + else None + ) + + self.adaptive_softmax = None + self.output_projection = None + if args.adaptive_softmax_cutoff is not None: + self.adaptive_softmax = AdaptiveSoftmax( + len(dictionary), + self.output_embed_dim, + utils.eval_str_list(args.adaptive_softmax_cutoff, type=int), + dropout=args.adaptive_softmax_dropout, + adaptive_inputs=embed_tokens if args.tie_adaptive_weights else None, + factor=args.adaptive_softmax_factor, + tie_proj=args.tie_adaptive_proj, + ) + elif self.share_input_output_embed: + self.output_projection = nn.Linear( + self.embed_tokens.weight.shape[1], + self.embed_tokens.weight.shape[0], + bias=False, + ) + self.output_projection.weight = self.embed_tokens.weight + else: + self.output_projection = nn.Linear( + self.output_embed_dim, len(dictionary), bias=False + ) + nn.init.normal_( + self.output_projection.weight, mean=0, std=self.output_embed_dim ** -0.5 + ) + + def build_decoder_layer(self, args, no_encoder_attn=False): + return TransformerDecoderLayer(args, no_encoder_attn) + + def forward( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + features_only: bool = False, + full_context_alignment: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + src_lengths: Optional[Any] = None, + return_all_hiddens: bool = False, + ): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (optional): output from the encoder, used for + encoder-side attention + incremental_state (dict): dictionary used for storing state during + :ref:`Incremental decoding` + features_only (bool, optional): only return features without + applying output layer (default: False). + full_context_alignment (bool, optional): don't apply + auto-regressive mask to self-attention (default: False). + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + x, extra = self.extract_features( + prev_output_tokens, + encoder_out=encoder_out, + incremental_state=incremental_state, + full_context_alignment=full_context_alignment, + alignment_layer=alignment_layer, + alignment_heads=alignment_heads, + ) + if not features_only: + x = self.output_layer(x) + return x, extra + + def extract_features( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + full_context_alignment: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + ): + return self.extract_features_scriptable( + prev_output_tokens, + encoder_out, + incremental_state, + full_context_alignment, + alignment_layer, + alignment_heads, + ) + + """ + A scriptable subclass of this class has an extract_features method and calls + super().extract_features, but super() is not supported in torchscript. Aa copy of + this function is made to be used in the subclass instead. + """ + + def extract_features_scriptable( + self, + prev_output_tokens, + encoder_out: Optional[EncoderOut] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + full_context_alignment: bool = False, + alignment_layer: Optional[int] = None, + alignment_heads: Optional[int] = None, + ): + """ + Similar to *forward* but only return features. + + Includes several features from "Jointly Learning to Align and + Translate with Transformer Models" (Garg et al., EMNLP 2019). + + Args: + full_context_alignment (bool, optional): don't apply + auto-regressive mask to self-attention (default: False). + alignment_layer (int, optional): return mean alignment over + heads at this layer (default: last layer). + alignment_heads (int, optional): only average alignment over + this many heads (default: all heads). + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + if alignment_layer is None: + alignment_layer = self.num_layers - 1 + + # embed positions + positions = ( + self.embed_positions( + prev_output_tokens, incremental_state=incremental_state + ) + if self.embed_positions is not None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + if positions is not None: + positions = positions[:, -1:] + + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + + if self.quant_noise is not None: + x = self.quant_noise(x) + + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + + if self.layernorm_embedding is not None: + x = self.layernorm_embedding(x) + + x = self.dropout_module(x) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + self_attn_padding_mask: Optional[Tensor] = None + if self.cross_self_attention or prev_output_tokens.eq(self.padding_idx).any(): + self_attn_padding_mask = prev_output_tokens.eq(self.padding_idx) + + # decoder layers + attn: Optional[Tensor] = None + inner_states: List[Optional[Tensor]] = [x] + for idx, layer in enumerate(self.layers): + if incremental_state is None and not full_context_alignment: + self_attn_mask = self.buffered_future_mask(x) + else: + self_attn_mask = None + + x, layer_attn, _ = layer( + x, + encoder_out.encoder_out if encoder_out is not None else None, + encoder_out.encoder_padding_mask if encoder_out is not None else None, + incremental_state, + self_attn_mask=self_attn_mask, + self_attn_padding_mask=self_attn_padding_mask, + need_attn=bool((idx == alignment_layer)), + need_head_weights=bool((idx == alignment_layer)), + ) + inner_states.append(x) + if layer_attn is not None and idx == alignment_layer: + attn = layer_attn.float().to(x) + + if attn is not None: + if alignment_heads is not None: + attn = attn[:alignment_heads] + + # average probabilities over heads + attn = attn.mean(dim=0) + + if self.layer_norm is not None: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + if self.project_out_dim is not None: + x = self.project_out_dim(x) + + return x, {"attn": [attn], "inner_states": inner_states} + + def output_layer(self, features): + """Project features to the vocabulary size.""" + if self.adaptive_softmax is None: + # project back to size of vocabulary + return self.output_projection(features) + else: + return features + + def max_positions(self): + """Maximum output length supported by the decoder.""" + if self.embed_positions is None: + return self.max_target_positions + return min(self.max_target_positions, self.embed_positions.max_positions) + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + # self._future_mask.device != tensor.device is not working in TorchScript. This is a workaround. + if ( + self._future_mask.size(0) == 0 + or (not self._future_mask.device == tensor.device) + or self._future_mask.size(0) < dim + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(torch.zeros([dim, dim])), 1 + ) + self._future_mask = self._future_mask.to(tensor) + return self._future_mask[:dim, :dim] + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + if isinstance(self.embed_positions, SinusoidalPositionalEmbedding): + weights_key = "{}.embed_positions.weights".format(name) + if weights_key in state_dict: + del state_dict[weights_key] + state_dict[ + "{}.embed_positions._float_tensor".format(name) + ] = torch.FloatTensor(1) + + if f"{name}.output_projection.weight" not in state_dict: + if self.share_input_output_embed: + embed_out_key = f"{name}.embed_tokens.weight" + else: + embed_out_key = f"{name}.embed_out" + if embed_out_key in state_dict: + state_dict[f"{name}.output_projection.weight"] = state_dict[ + embed_out_key + ] + if not self.share_input_output_embed: + del state_dict[embed_out_key] + + for i in range(self.num_layers): + # update layer norms + layer_norm_map = { + "0": "self_attn_layer_norm", + "1": "encoder_attn_layer_norm", + "2": "final_layer_norm", + } + for old, new in layer_norm_map.items(): + for m in ("weight", "bias"): + k = "{}.layers.{}.layer_norms.{}.{}".format(name, i, old, m) + if k in state_dict: + state_dict[ + "{}.layers.{}.{}.{}".format(name, i, new, m) + ] = state_dict[k] + del state_dict[k] + + version_key = "{}.version".format(name) + if utils.item(state_dict.get(version_key, torch.Tensor([1]))[0]) <= 2: + # earlier checkpoints did not normalize after the stack of layers + self.layer_norm = None + self.normalize = False + state_dict[version_key] = torch.Tensor([1]) + + return state_dict + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.normal_(m.weight, mean=0, std=embedding_dim ** -0.5) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m + + +@register_model_architecture("transformer", "transformer") +def base_architecture(args): + args.encoder_embed_path = getattr(args, "encoder_embed_path", None) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 2048) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 8) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.encoder_learned_pos = getattr(args, "encoder_learned_pos", False) + args.decoder_embed_path = getattr(args, "decoder_embed_path", None) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", args.encoder_embed_dim) + args.decoder_ffn_embed_dim = getattr( + args, "decoder_ffn_embed_dim", args.encoder_ffn_embed_dim + ) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + args.activation_fn = getattr(args, "activation_fn", "relu") + args.dropout = getattr(args, "dropout", 0.1) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.share_all_embeddings = getattr(args, "share_all_embeddings", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.adaptive_input = getattr(args, "adaptive_input", False) + args.no_cross_attention = getattr(args, "no_cross_attention", False) + args.cross_self_attention = getattr(args, "cross_self_attention", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + args.layernorm_embedding = getattr(args, "layernorm_embedding", False) + args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False) + + +@register_model_architecture("transformer", "transformer_iwslt_de_en") +def transformer_iwslt_de_en(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 512) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 1024) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 4) + args.encoder_layers = getattr(args, "encoder_layers", 6) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 1024) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 4) + args.decoder_layers = getattr(args, "decoder_layers", 6) + base_architecture(args) + + +@register_model_architecture("transformer", "transformer_wmt_en_de") +def transformer_wmt_en_de(args): + base_architecture(args) + + +# parameters used in the "Attention Is All You Need" paper (Vaswani et al., 2017) +@register_model_architecture("transformer", "transformer_vaswani_wmt_en_de_big") +def transformer_vaswani_wmt_en_de_big(args): + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 1024) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 4096) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 16) + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", False) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.3) + base_architecture(args) + + +@register_model_architecture("transformer", "transformer_vaswani_wmt_en_fr_big") +def transformer_vaswani_wmt_en_fr_big(args): + args.dropout = getattr(args, "dropout", 0.1) + transformer_vaswani_wmt_en_de_big(args) + + +@register_model_architecture("transformer", "transformer_wmt_en_de_big") +def transformer_wmt_en_de_big(args): + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + transformer_vaswani_wmt_en_de_big(args) + + +# default parameters used in tensor2tensor implementation +@register_model_architecture("transformer", "transformer_wmt_en_de_big_t2t") +def transformer_wmt_en_de_big_t2t(args): + args.encoder_normalize_before = getattr(args, "encoder_normalize_before", True) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", True) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.1) + transformer_vaswani_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/fairseq/models/transformer_align.py b/fairseq-tools/fairseq/fairseq/models/transformer_align.py new file mode 100644 index 00000000..eaf585bd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/transformer_align.py @@ -0,0 +1,93 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer import ( + TransformerModel, + base_architecture, + transformer_wmt_en_de_big, +) + + +@register_model("transformer_align") +class TransformerAlignModel(TransformerModel): + """ + See "Jointly Learning to Align and Translate with Transformer + Models" (Garg et al., EMNLP 2019). + """ + + def __init__(self, encoder, decoder, args): + super().__init__(args, encoder, decoder) + self.alignment_heads = args.alignment_heads + self.alignment_layer = args.alignment_layer + self.full_context_alignment = args.full_context_alignment + + @staticmethod + def add_args(parser): + # fmt: off + super(TransformerAlignModel, TransformerAlignModel).add_args(parser) + parser.add_argument('--alignment-heads', type=int, metavar='D', + help='Number of cross attention heads per layer to supervised with alignments') + parser.add_argument('--alignment-layer', type=int, metavar='D', + help='Layer number which has to be supervised. 0 corresponding to the bottommost layer.') + parser.add_argument('--full-context-alignment', action='store_true', + help='Whether or not alignment is supervised conditioned on the full target context.') + # fmt: on + + @classmethod + def build_model(cls, args, task): + # set any default arguments + transformer_align(args) + + transformer_model = TransformerModel.build_model(args, task) + return TransformerAlignModel( + transformer_model.encoder, transformer_model.decoder, args + ) + + def forward(self, src_tokens, src_lengths, prev_output_tokens): + encoder_out = self.encoder(src_tokens, src_lengths) + return self.forward_decoder(prev_output_tokens, encoder_out) + + def forward_decoder( + self, + prev_output_tokens, + encoder_out=None, + incremental_state=None, + features_only=False, + **extra_args, + ): + attn_args = { + "alignment_layer": self.alignment_layer, + "alignment_heads": self.alignment_heads, + } + decoder_out = self.decoder(prev_output_tokens, encoder_out, **attn_args) + + if self.full_context_alignment: + attn_args["full_context_alignment"] = self.full_context_alignment + _, alignment_out = self.decoder( + prev_output_tokens, + encoder_out, + features_only=True, + **attn_args, + **extra_args, + ) + decoder_out[1]["attn"] = alignment_out["attn"] + + return decoder_out + + +@register_model_architecture("transformer_align", "transformer_align") +def transformer_align(args): + args.alignment_heads = getattr(args, "alignment_heads", 1) + args.alignment_layer = getattr(args, "alignment_layer", 4) + args.full_context_alignment = getattr(args, "full_context_alignment", False) + base_architecture(args) + + +@register_model_architecture("transformer_align", "transformer_wmt_en_de_big_align") +def transformer_wmt_en_de_big_align(args): + args.alignment_heads = getattr(args, "alignment_heads", 1) + args.alignment_layer = getattr(args, "alignment_layer", 4) + transformer_wmt_en_de_big(args) diff --git a/fairseq-tools/fairseq/fairseq/models/transformer_from_pretrained_xlm.py b/fairseq-tools/fairseq/fairseq/models/transformer_from_pretrained_xlm.py new file mode 100644 index 00000000..236d9942 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/transformer_from_pretrained_xlm.py @@ -0,0 +1,152 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +from typing import Any, Dict + +from fairseq import checkpoint_utils +from fairseq.data.legacy.masked_lm_dictionary import MaskedLMDictionary +from fairseq.models import register_model, register_model_architecture +from fairseq.models.transformer import ( + TransformerDecoder, + TransformerEncoder, + TransformerModel, + base_architecture as transformer_base_architecture, +) + + +@register_model("transformer_from_pretrained_xlm") +class TransformerFromPretrainedXLMModel(TransformerModel): + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + TransformerModel.add_args(parser) + parser.add_argument( + "--pretrained-xlm-checkpoint", + type=str, + metavar="STR", + help="XLM model to use for initializing transformer encoder and/or decoder", + ) + parser.add_argument( + "--init-encoder-only", + action="store_true", + help="if set, don't load the XLM weights and embeddings into decoder", + ) + parser.add_argument( + "--init-decoder-only", + action="store_true", + help="if set, don't load the XLM weights and embeddings into encoder", + ) + + @classmethod + def build_model(self, args, task, cls_dictionary=MaskedLMDictionary): + assert hasattr(args, "pretrained_xlm_checkpoint"), ( + "You must specify a path for --pretrained-xlm-checkpoint to use " + "--arch transformer_from_pretrained_xlm" + ) + assert isinstance(task.source_dictionary, cls_dictionary) and isinstance( + task.target_dictionary, cls_dictionary + ), ( + "You should use a MaskedLMDictionary when using --arch " + "transformer_from_pretrained_xlm because the pretrained XLM model " + "was trained using data binarized with MaskedLMDictionary. " + "For translation, you may want to use --task " + "translation_from_pretrained_xlm" + ) + assert not ( + getattr(args, "init_encoder_only", False) + and getattr(args, "init_decoder_only", False) + ), "Only one of --init-encoder-only and --init-decoder-only can be set." + return super().build_model(args, task) + + @classmethod + def build_encoder(cls, args, src_dict, embed_tokens): + return TransformerEncoderFromPretrainedXLM(args, src_dict, embed_tokens) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerDecoderFromPretrainedXLM(args, tgt_dict, embed_tokens) + + +def upgrade_state_dict_with_xlm_weights( + state_dict: Dict[str, Any], pretrained_xlm_checkpoint: str +) -> Dict[str, Any]: + """ + Load XLM weights into a Transformer encoder or decoder model. + + Args: + state_dict: state dict for either TransformerEncoder or + TransformerDecoder + pretrained_xlm_checkpoint: checkpoint to load XLM weights from + + Raises: + AssertionError: If architecture (num layers, attention heads, etc.) + does not match between the current Transformer encoder or + decoder and the pretrained_xlm_checkpoint + """ + if not os.path.exists(pretrained_xlm_checkpoint): + raise IOError("Model file not found: {}".format(pretrained_xlm_checkpoint)) + + state = checkpoint_utils.load_checkpoint_to_cpu(pretrained_xlm_checkpoint) + xlm_state_dict = state["model"] + for key in xlm_state_dict.keys(): + + for search_key in ["embed_tokens", "embed_positions", "layers"]: + if search_key in key: + subkey = key[key.find(search_key) :] + assert subkey in state_dict, ( + "{} Transformer encoder / decoder " + "state_dict does not contain {}. Cannot " + "load {} from pretrained XLM checkpoint " + "{} into Transformer.".format( + str(state_dict.keys()), subkey, key, pretrained_xlm_checkpoint + ) + ) + + state_dict[subkey] = xlm_state_dict[key] + return state_dict + + +class TransformerEncoderFromPretrainedXLM(TransformerEncoder): + def __init__(self, args, dictionary, embed_tokens): + super().__init__(args, dictionary, embed_tokens) + if getattr(args, "init_decoder_only", False): + # Don't load XLM weights for encoder if --init-decoder-only + return + + assert hasattr(args, "pretrained_xlm_checkpoint"), ( + "--pretrained-xlm-checkpoint must be specified to load Transformer " + "encoder from pretrained XLM" + ) + xlm_loaded_state_dict = upgrade_state_dict_with_xlm_weights( + state_dict=self.state_dict(), + pretrained_xlm_checkpoint=args.pretrained_xlm_checkpoint, + ) + self.load_state_dict(xlm_loaded_state_dict, strict=True) + + +class TransformerDecoderFromPretrainedXLM(TransformerDecoder): + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__(args, dictionary, embed_tokens, no_encoder_attn) + if getattr(args, "init_encoder_only", False): + # Don't load XLM weights for decoder if --init-encoder-only + return + assert hasattr(args, "pretrained_xlm_checkpoint"), ( + "--pretrained-xlm-checkpoint must be specified to load Transformer " + "decoder from pretrained XLM" + ) + + xlm_loaded_state_dict = upgrade_state_dict_with_xlm_weights( + state_dict=self.state_dict(), + pretrained_xlm_checkpoint=args.pretrained_xlm_checkpoint, + ) + self.load_state_dict(xlm_loaded_state_dict, strict=True) + + +@register_model_architecture( + "transformer_from_pretrained_xlm", "transformer_from_pretrained_xlm" +) +def base_architecture(args): + transformer_base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/transformer_lm.py b/fairseq-tools/fairseq/fairseq/models/transformer_lm.py new file mode 100644 index 00000000..22b17f06 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/transformer_lm.py @@ -0,0 +1,393 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from dataclasses import dataclass, field +from typing import Optional + +from fairseq import options, utils +from fairseq.dataclass import ChoiceEnum, FairseqDataclass +from fairseq.models import ( + FairseqLanguageModel, + register_model, + register_model_architecture, +) +from fairseq.models.transformer import Embedding, TransformerDecoder +from fairseq.modules import AdaptiveInput, CharacterTokenEmbedder +from omegaconf import II + + +DEFAULT_MAX_TARGET_POSITIONS = 1024 + + +@dataclass +class TransformerLanguageModelConfig(FairseqDataclass): + activation_fn: ChoiceEnum(utils.get_available_activation_fns()) = field( + default="relu", metadata={"help": "activation function to use"} + ) + dropout: float = field(default=0.1, metadata={"help": "dropout probability"}) + attention_dropout: float = field( + default=0.0, metadata={"help": "dropout probability for attention weights"} + ) + activation_dropout: float = field( + default=0.0, metadata={"help": "dropout probability after activation in FFN."} + ) + relu_dropout: float = field( + default=0.0, metadata={"help": "dropout probability after activation in FFN."} + ) + decoder_embed_dim: int = field( + default=512, metadata={"help": "decoder embedding dimension"} + ) + decoder_output_dim: int = field( + default=512, metadata={"help": "decoder output dimension"} + ) + decoder_input_dim: int = field( + default=512, metadata={"help": "decoder input dimension"} + ) + decoder_ffn_embed_dim: int = field( + default=2048, metadata={"help": "decoder embedding dimension for FFN"} + ) + decoder_layers: int = field(default=6, metadata={"help": "num decoder layers"}) + decoder_attention_heads: int = field( + default=8, metadata={"help": "num decoder attention heads"} + ) + decoder_normalize_before: bool = field( + default=False, metadata={"help": "apply layernorm before each decoder block"} + ) + no_decoder_final_norm: bool = field( + default=False, + metadata={"help": "don't add an extra layernorm after the last decoder block"}, + ) + adaptive_softmax_cutoff: Optional[str] = field( + default=None, + metadata={ + "help": "comma separated list of adaptive softmax cutoff points. " + "Must be used with adaptive_loss criterion" + }, + ) + adaptive_softmax_dropout: float = field( + default=0, + metadata={"help": "sets adaptive softmax dropout for the tail projections"}, + ) + adaptive_softmax_factor: float = field( + default=4, metadata={"help": "adaptive input factor"} + ) + no_token_positional_embeddings: bool = field( + default=False, + metadata={ + "help": "if set, disables positional embeddings (outside self attention)" + }, + ) + share_decoder_input_output_embed: bool = field( + default=False, metadata={"help": "share decoder input and output embeddings"} + ) + character_embeddings: bool = field( + default=False, + metadata={ + "help": "if set, uses character embedding convolutions to produce token embeddings" + }, + ) + character_filters: str = field( + default="[(1, 64), (2, 128), (3, 192), (4, 256), (5, 256), (6, 256), (7, 256)]", + metadata={"help": "size of character embeddings"}, + ) + character_embedding_dim: int = field( + default=4, metadata={"help": "size of character embeddings"} + ) + char_embedder_highway_layers: int = field( + default=2, + metadata={"help": "number of highway layers for character token embeddder"}, + ) + adaptive_input: bool = field( + default=False, metadata={"help": "if set, uses adaptive input"} + ) + adaptive_input_factor: float = field( + default=4, metadata={"help": "adaptive input factor"} + ) + adaptive_input_cutoff: Optional[str] = field( + default=None, + metadata={"help": "comma separated list of adaptive input cutoff points."}, + ) + tie_adaptive_weights: bool = field( + default=False, + metadata={ + "help": "if set, ties the weights of adaptive softmax and adaptive input" + }, + ) + tie_adaptive_proj: bool = field( + default=False, + metadata={ + "help": "if set, ties the projection weights of adaptive softmax and adaptive input" + }, + ) + decoder_learned_pos: bool = field( + default=False, + metadata={"help": "use learned positional embeddings in the decoder"}, + ) + decoder_layerdrop: float = field( + default=0.0, metadata={"help": "LayerDrop probability for decoder"} + ) + decoder_layers_to_keep: Optional[str] = field( + default=None, + metadata={ + "help": "which layers to *keep* when pruning as a comma-separated list" + }, + ) + layernorm_embedding: bool = field( + default=False, metadata={"help": "add layernorm to embedding"} + ) + no_scale_embedding: bool = field( + default=False, metadata={"help": "if True, dont scale embeddings"} + ) + quant_noise_pq: float = field( + default=0.0, + metadata={"help": "iterative PQ quantization noise at training time"}, + ) + quant_noise_pq_block_size: int = field( + default=8, + metadata={"help": "block size of quantization noise at training time"}, + ) + # TODO common var add to parent + quant_noise_scalar: float = field( + default=0.0, + metadata={ + "help": "scalar quantization noise and scalar quantization at training time" + }, + ) + add_bos_token: bool = II("task.add_bos_token") + tokens_per_sample: int = II("task.tokens_per_sample") + max_target_positions: Optional[int] = II("task.max_target_positions") + tpu: bool = II("params.common.tpu") + + +@register_model("transformer_lm", dataclass=TransformerLanguageModelConfig) +class TransformerLanguageModel(FairseqLanguageModel): + @classmethod + def hub_models(cls): + def moses_fastbpe(path): + return {"path": path, "tokenizer": "moses", "bpe": "fastbpe"} + + return { + "transformer_lm.gbw.adaptive_huge": "https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_gbw_huge.tar.bz2", + "transformer_lm.wiki103.adaptive": "https://dl.fbaipublicfiles.com/fairseq/models/lm/adaptive_lm_wiki103.v2.tar.bz2", + "transformer_lm.wmt19.en": moses_fastbpe( + "https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.en.tar.bz2" + ), + "transformer_lm.wmt19.de": moses_fastbpe( + "https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.de.tar.bz2" + ), + "transformer_lm.wmt19.ru": moses_fastbpe( + "https://dl.fbaipublicfiles.com/fairseq/models/lm/wmt19.ru.tar.bz2" + ), + } + + def __init__(self, decoder): + super().__init__(decoder) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_lm_architecture(args) + + if args.decoder_layers_to_keep: + args.decoder_layers = len(args.decoder_layers_to_keep.split(",")) + + if getattr(args, "max_target_positions", None) is None: + args.max_target_positions = getattr( + args, "tokens_per_sample", DEFAULT_MAX_TARGET_POSITIONS + ) + + if args.character_embeddings: + embed_tokens = CharacterTokenEmbedder( + task.source_dictionary, + eval(args.character_filters), + args.character_embedding_dim, + args.decoder_embed_dim, + args.char_embedder_highway_layers, + ) + elif args.adaptive_input: + embed_tokens = AdaptiveInput( + len(task.source_dictionary), + task.source_dictionary.pad(), + args.decoder_input_dim, + args.adaptive_input_factor, + args.decoder_embed_dim, + options.eval_str_list(args.adaptive_input_cutoff, type=int), + args.quant_noise_pq, + args.quant_noise_pq_block_size, + ) + else: + embed_tokens = cls.build_embedding( + args, task.source_dictionary, args.decoder_input_dim + ) + + if args.tie_adaptive_weights: + assert args.adaptive_input + assert args.adaptive_input_factor == args.adaptive_softmax_factor + assert ( + args.adaptive_softmax_cutoff == args.adaptive_input_cutoff + ), "{} != {}".format( + args.adaptive_softmax_cutoff, args.adaptive_input_cutoff + ) + assert args.decoder_input_dim == args.decoder_output_dim + + decoder = TransformerDecoder( + args, task.target_dictionary, embed_tokens, no_encoder_attn=True + ) + return cls(decoder) + + @classmethod + def build_embedding(cls, args, dictionary, embed_dim, path=None): + embed_tokens = Embedding(len(dictionary), embed_dim, dictionary.pad()) + return embed_tokens + + +@register_model_architecture("transformer_lm", "transformer_lm") +def base_lm_architecture(args): + # backward compatibility for older model checkpoints + if hasattr(args, "no_tie_adaptive_proj"): + # previous models defined --no-tie-adaptive-proj, so use the existence of + # that option to determine if this is an "old" model checkpoint + args.no_decoder_final_norm = True # old models always set this to True + if args.no_tie_adaptive_proj is False: + args.tie_adaptive_proj = True + if hasattr(args, "decoder_final_norm"): + args.no_decoder_final_norm = not args.decoder_final_norm + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.0) + + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 2048) + args.decoder_layers = getattr(args, "decoder_layers", 6) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.adaptive_softmax_cutoff = getattr(args, "adaptive_softmax_cutoff", None) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0) + args.adaptive_softmax_factor = getattr(args, "adaptive_softmax_factor", 4) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.activation_fn = getattr(args, "activation_fn", "relu") + + args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0) + args.decoder_layers_to_keep = getattr(args, "decoder_layers_to_keep", None) + args.quant_noise_pq = getattr(args, "quant_noise_pq", 0) + args.quant_noise_pq_block_size = getattr(args, "quant_noise_pq_block_size", 8) + args.quant_noise_scalar = getattr(args, "quant_noise_scalar", 0) + + args.add_bos_token = getattr(args, "add_bos_token", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + args.character_embeddings = getattr(args, "character_embeddings", False) + + args.decoder_output_dim = getattr( + args, "decoder_output_dim", args.decoder_embed_dim + ) + args.decoder_input_dim = getattr(args, "decoder_input_dim", args.decoder_embed_dim) + + # Model training is not stable without this + args.decoder_normalize_before = True + args.no_decoder_final_norm = getattr(args, "no_decoder_final_norm", False) + + args.adaptive_input = getattr(args, "adaptive_input", False) + args.adaptive_input_factor = getattr(args, "adaptive_input_factor", 4) + args.adaptive_input_cutoff = getattr(args, "adaptive_input_cutoff", None) + + args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", False) + args.tie_adaptive_proj = getattr(args, "tie_adaptive_proj", False) + + args.no_scale_embedding = getattr(args, "no_scale_embedding", False) + args.layernorm_embedding = getattr(args, "layernorm_embedding", False) + + +@register_model_architecture("transformer_lm", "transformer_lm_big") +def transformer_lm_big(args): + args.decoder_layers = getattr(args, "decoder_layers", 12) + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + base_lm_architecture(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_wiki103") +@register_model_architecture("transformer_lm", "transformer_lm_baevski_wiki103") +def transformer_lm_baevski_wiki103(args): + args.decoder_layers = getattr(args, "decoder_layers", 16) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 8) + args.dropout = getattr(args, "dropout", 0.3) + args.adaptive_input = getattr(args, "adaptive_input", True) + args.tie_adaptive_weights = getattr(args, "tie_adaptive_weights", True) + args.adaptive_input_cutoff = getattr(args, "adaptive_input_cutoff", "20000,60000") + args.adaptive_softmax_cutoff = getattr( + args, "adaptive_softmax_cutoff", "20000,60000" + ) + args.adaptive_softmax_dropout = getattr(args, "adaptive_softmax_dropout", 0.2) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.1) + args.no_decoder_final_norm = getattr(args, "no_decoder_final_norm", True) + args.tie_adaptive_proj = getattr(args, "tie_adaptive_proj", True) + transformer_lm_big(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_gbw") +@register_model_architecture("transformer_lm", "transformer_lm_baevski_gbw") +def transformer_lm_baevski_gbw(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 512) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.no_decoder_final_norm = getattr(args, "no_decoder_final_norm", True) + transformer_lm_big(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_gpt") +def transformer_lm_gpt(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 768) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 3072) + args.decoder_layers = getattr(args, "decoder_layers", 12) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 12) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_gpt2_small") +def transformer_lm_gpt2_small(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_layers = getattr(args, "decoder_layers", 24) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_gpt2_medium") +def transformer_lm_gpt2_medium(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1280) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 5120) + args.decoder_layers = getattr(args, "decoder_layers", 36) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 20) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) + + +@register_model_architecture("transformer_lm", "transformer_lm_gpt2_big") +def transformer_lm_gpt2_big(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1600) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 6400) + args.decoder_layers = getattr(args, "decoder_layers", 48) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 25) + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_fn = getattr(args, "activation_fn", "gelu") + base_lm_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/models/wav2vec/__init__.py b/fairseq-tools/fairseq/fairseq/models/wav2vec/__init__.py new file mode 100644 index 00000000..06cec181 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/wav2vec/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .wav2vec import * # noqa +from .wav2vec2 import * # noqa +from .wav2vec2_asr import * # noqa diff --git a/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec.py b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec.py new file mode 100644 index 00000000..772995b5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec.py @@ -0,0 +1,735 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import math +import sys + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq.models import BaseFairseqModel, register_model, register_model_architecture +from fairseq.modules import ( + Fp32GroupNorm, + Fp32LayerNorm, + GumbelVectorQuantizer, + KmeansVectorQuantizer, + TransposeLast, +) +from fairseq.utils import buffered_arange + + +logger = logging.getLogger(__name__) + + +@register_model("wav2vec") +class Wav2VecModel(BaseFairseqModel): + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + parser.add_argument( + "--prediction-steps", + type=int, + metavar="N", + help="number of steps ahead to predict", + ) + parser.add_argument( + "--sample-distance", + type=int, + metavar="N", + help="sample distance from target. does not work properly with cross-sampling", + ) + parser.add_argument( + "--cross-sample-negatives", + type=int, + metavar="N", + help="num of cross sampled negatives", + ) + parser.add_argument( + "--num-negatives", type=int, metavar="N", help="number of negative examples" + ) + parser.add_argument( + "--conv-feature-layers", + type=str, + metavar="EXPR", + help="convolutional feature extraction layers [(dim, kernel_size, stride), ...]", + ) + parser.add_argument( + "--conv-aggregator-layers", + type=str, + metavar="EXPR", + help="convolutional feature extraction layers [(dim, kernel_size, stride), ...]", + ) + parser.add_argument( + "--dropout", + type=float, + metavar="D", + help="dropout to apply within the model", + ) + parser.add_argument( + "--dropout-features", + type=float, + metavar="D", + help="dropout to apply to the features", + ) + parser.add_argument( + "--dropout-agg", + type=float, + metavar="D", + help="dropout to apply after aggregation step", + ) + parser.add_argument( + "--encoder", type=str, choices=["cnn"], help="type of encoder to use" + ) + parser.add_argument( + "--aggregator", + type=str, + choices=["cnn", "gru"], + help="type of aggregator to use", + ) + parser.add_argument( + "--gru-dim", type=int, metavar="N", help="GRU dimensionality" + ) + + parser.add_argument( + "--no-conv-bias", + action="store_true", + help="if set, does not learn bias for conv layers", + ) + parser.add_argument( + "--agg-zero-pad", + action="store_true", + help="if set, zero pads in aggregator instead of repl pad", + ) + + parser.add_argument( + "--skip-connections-feat", + action="store_true", + help="if set, adds skip connections to the feature extractor", + ) + parser.add_argument( + "--skip-connections-agg", + action="store_true", + help="if set, adds skip connections to the aggregator", + ) + parser.add_argument( + "--residual-scale", + type=float, + metavar="D", + help="scales residual by sqrt(value)", + ) + + parser.add_argument( + "--log-compression", + action="store_true", + help="if set, adds a log compression to feature extractor", + ) + + parser.add_argument( + "--balanced-classes", + action="store_true", + help="if set, loss is scaled to balance for number of negatives", + ) + + parser.add_argument( + "--project-features", + choices=["none", "same", "new"], + help="if not none, features are projected using the (same or new) aggregator", + ) + + parser.add_argument( + "--non-affine-group-norm", + action="store_true", + help="if set, group norm is not affine", + ) + + parser.add_argument( + "--offset", + help="if set, introduces an offset from target to predictions. " + 'if set to "auto", it is computed automatically from the receptive field', + ) + + parser.add_argument( + "--activation", + type=str, + choices=["relu", "gelu"], + help="which activation function to use", + ) + + parser.add_argument( + "--vq-type", + type=str, + choices=["none", "gumbel", "kmeans"], + help="which type of quantizer to use", + ) + parser.add_argument( + "--vq-vars", + type=int, + metavar="N", + help="if set, project to this many vector quantized variables per group", + ) + parser.add_argument( + "--vq-groups", + type=int, + metavar="N", + help="number of groups of latent variables", + ) + parser.add_argument( + "--vq-dim", + type=int, + metavar="N", + help="uses this dimensionality for quantized vectors", + ) + parser.add_argument( + "--vq-depth", + type=int, + metavar="N", + help="number of layers for vq weight projection", + ) + parser.add_argument( + "--combine-groups", + action="store_true", + help="if set, variables are shared among groups", + ) + parser.add_argument( + "--vq-temp", + type=str, + metavar="TEMP", + help="temperature for latent variable sampling with gumbel softmax. should be a tuple of 3 values (start, end, decay)", + ) + parser.add_argument( + "--vq-gamma", + type=float, + metavar="D", + help="gamma parameter for kmeans style vector quantization", + ) + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_wav2vec_architecture(args) + + model = Wav2VecModel(args) + logger.info(model) + return model + + def __init__(self, args): + super().__init__() + + self.prediction_steps = args.prediction_steps + offset = args.offset + + if args.activation == "relu": + activation = nn.ReLU() + elif args.activation == "gelu": + activation = nn.GELU() + else: + raise Exception("unknown activation " + args.activation) + + if args.encoder == "cnn": + feature_enc_layers = eval(args.conv_feature_layers) + self.feature_extractor = ConvFeatureExtractionModel( + conv_layers=feature_enc_layers, + dropout=0.0, + log_compression=args.log_compression, + skip_connections=args.skip_connections_feat, + residual_scale=args.residual_scale, + non_affine_group_norm=args.non_affine_group_norm, + activation=activation, + ) + embed = feature_enc_layers[-1][0] + else: + raise Exception("unknown encoder type " + args.encoder) + + self.vector_quantizer = None + if args.vq_type == "gumbel": + self.vector_quantizer = GumbelVectorQuantizer( + dim=embed, + num_vars=args.vq_vars, + temp=eval(args.vq_temp), + groups=args.vq_groups, + combine_groups=args.combine_groups, + vq_dim=args.vq_dim if args.vq_dim > 0 else embed, + time_first=False, + activation=activation, + weight_proj_depth=args.vq_depth, + weight_proj_factor=2, + ) + elif args.vq_type == "kmeans": + self.vector_quantizer = KmeansVectorQuantizer( + dim=embed, + num_vars=args.vq_vars, + groups=args.vq_groups, + combine_groups=args.combine_groups, + vq_dim=args.vq_dim if args.vq_dim > 0 else embed, + time_first=False, + gamma=args.vq_gamma, + ) + else: + assert ( + args.vq_type == "none" or args.vq_type is None + ), "Unknown quantizer type" + + if args.offset == "auto": + assert args.encoder == "cnn" + jin = 0 + rin = 0 + for _, k, stride in feature_enc_layers: + if rin == 0: + rin = k + rin = rin + (k - 1) * jin + if jin == 0: + jin = stride + else: + jin *= stride + offset = math.ceil(rin / jin) + + offset = int(offset) + + def make_aggregator(): + if args.aggregator == "cnn": + agg_layers = eval(args.conv_aggregator_layers) + agg_dim = agg_layers[-1][0] + feature_aggregator = ConvAggegator( + conv_layers=agg_layers, + embed=embed, + dropout=args.dropout, + skip_connections=args.skip_connections_agg, + residual_scale=args.residual_scale, + non_affine_group_norm=args.non_affine_group_norm, + conv_bias=not args.no_conv_bias, + zero_pad=args.agg_zero_pad, + activation=activation, + ) + elif args.aggregator == "gru": + agg_dim = args.gru_dim + feature_aggregator = nn.Sequential( + TransposeLast(), + nn.GRU( + input_size=embed, + hidden_size=agg_dim, + num_layers=1, + dropout=args.dropout, + ), + TransposeLast(deconstruct_idx=0), + ) + else: + raise Exception("unknown aggregator type " + args.aggregator) + + return feature_aggregator, agg_dim + + self.feature_aggregator, agg_dim = make_aggregator() + + self.wav2vec_predictions = Wav2VecPredictionsModel( + in_dim=agg_dim, + out_dim=embed, + prediction_steps=args.prediction_steps, + n_negatives=args.num_negatives, + cross_sample_negatives=args.cross_sample_negatives, + sample_distance=args.sample_distance, + dropout=args.dropout, + offset=offset, + balanced_classes=args.balanced_classes, + infonce=args.infonce, + ) + + self.dropout_feats = nn.Dropout(p=args.dropout_features) + self.dropout_agg = nn.Dropout(p=args.dropout_agg) + + if args.project_features == "none": + self.project_features = None + elif args.project_features == "same": + self.project_features = self.feature_aggregator + elif args.project_features == "new": + self.project_features, _ = make_aggregator() + + def forward(self, source): + result = {} + + features = self.feature_extractor(source) + if self.vector_quantizer: + q_res = self.vector_quantizer(features) + features = q_res["x"] + for k in q_res.keys(): + if k != "x": + result[k] = q_res[k] + + x = self.dropout_feats(features) + x = self.feature_aggregator(x) + x = self.dropout_agg(x) + + if self.project_features is not None: + features = self.project_features(features) + x, targets = self.wav2vec_predictions(x, features) + result["cpc_logits"] = x + result["cpc_targets"] = targets + + return result + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + + def max_positions(self): + """Maximum length supported by the model.""" + return sys.maxsize + + def get_logits(self, net_output): + logits = net_output["cpc_logits"] + return logits + + def get_targets(self, sample, net_output): + t = net_output["cpc_targets"] + if isinstance(t, tuple): + t = t[0] + return t.contiguous() + + def get_target_weights(self, targets, net_output): + targets = net_output["cpc_targets"] + if isinstance(targets, tuple) and targets[-1] is not None: + return targets[-1] + return None + + def get_extra_losses(self, net_output): + loss = None + if "prob_perplexity" in net_output: + loss = net_output["num_vars"] - net_output["prob_perplexity"] + elif "kmeans_loss" in net_output: + loss = net_output["kmeans_loss"] + + return loss + + +def norm_block(is_layer_norm, dim, affine=True): + if is_layer_norm: + mod = nn.Sequential( + TransposeLast(), + Fp32LayerNorm(dim, elementwise_affine=affine), + TransposeLast(), + ) + else: + mod = Fp32GroupNorm(1, dim, affine=affine) + + return mod + + +class ConvFeatureExtractionModel(nn.Module): + def __init__( + self, + conv_layers, + dropout, + log_compression, + skip_connections, + residual_scale, + non_affine_group_norm, + activation, + ): + super().__init__() + + def block(n_in, n_out, k, stride): + return nn.Sequential( + nn.Conv1d(n_in, n_out, k, stride=stride, bias=False), + nn.Dropout(p=dropout), + norm_block( + is_layer_norm=False, dim=n_out, affine=not non_affine_group_norm + ), + activation, + ) + + in_d = 1 + self.conv_layers = nn.ModuleList() + for dim, k, stride in conv_layers: + self.conv_layers.append(block(in_d, dim, k, stride)) + in_d = dim + + self.log_compression = log_compression + self.skip_connections = skip_connections + self.residual_scale = math.sqrt(residual_scale) + + def forward(self, x): + # BxT -> BxCxT + x = x.unsqueeze(1) + + for conv in self.conv_layers: + residual = x + x = conv(x) + if self.skip_connections and x.size(1) == residual.size(1): + tsz = x.size(2) + r_tsz = residual.size(2) + residual = residual[..., :: r_tsz // tsz][..., :tsz] + x = (x + residual) * self.residual_scale + + if self.log_compression: + x = x.abs() + x = x + 1 + x = x.log() + + return x + + +class ZeroPad1d(nn.Module): + def __init__(self, pad_left, pad_right): + super().__init__() + self.pad_left = pad_left + self.pad_right = pad_right + + def forward(self, x): + return F.pad(x, (self.pad_left, self.pad_right)) + + +class ConvAggegator(nn.Module): + def __init__( + self, + conv_layers, + embed, + dropout, + skip_connections, + residual_scale, + non_affine_group_norm, + conv_bias, + zero_pad, + activation, + ): + super().__init__() + + def block(n_in, n_out, k, stride): + # padding dims only really make sense for stride = 1 + ka = k // 2 + kb = ka - 1 if k % 2 == 0 else ka + + pad = ( + ZeroPad1d(ka + kb, 0) if zero_pad else nn.ReplicationPad1d((ka + kb, 0)) + ) + + return nn.Sequential( + pad, + nn.Conv1d(n_in, n_out, k, stride=stride, bias=conv_bias), + nn.Dropout(p=dropout), + norm_block(False, n_out, affine=not non_affine_group_norm), + activation, + ) + + in_d = embed + self.conv_layers = nn.ModuleList() + self.residual_proj = nn.ModuleList() + for dim, k, stride in conv_layers: + if in_d != dim and skip_connections: + self.residual_proj.append(nn.Conv1d(in_d, dim, 1, bias=False)) + else: + self.residual_proj.append(None) + + self.conv_layers.append(block(in_d, dim, k, stride)) + in_d = dim + self.conv_layers = nn.Sequential(*self.conv_layers) + self.skip_connections = skip_connections + self.residual_scale = math.sqrt(residual_scale) + + def forward(self, x): + for rproj, conv in zip(self.residual_proj, self.conv_layers): + residual = x + x = conv(x) + if self.skip_connections: + if rproj is not None: + residual = rproj(residual) + x = (x + residual) * self.residual_scale + return x + + +class Wav2VecPredictionsModel(nn.Module): + def __init__( + self, + in_dim, + out_dim, + prediction_steps, + n_negatives, + cross_sample_negatives, + sample_distance, + dropout, + offset, + balanced_classes, + infonce, + ): + super().__init__() + + self.n_negatives = n_negatives + self.cross_sample_negatives = cross_sample_negatives + self.sample_distance = sample_distance + self.project_to_steps = nn.ConvTranspose2d( + in_dim, out_dim, (1, prediction_steps) + ) + self.dropout = nn.Dropout(p=dropout) + self.offset = offset + self.balanced_classes = balanced_classes + self.infonce = infonce + + def sample_negatives(self, y): + bsz, fsz, tsz = y.shape + + y = y.transpose(0, 1) # BCT -> CBT + y = y.contiguous().view(fsz, -1) # CBT => C(BxT) + + cross_high = tsz * bsz + high = tsz if self.sample_distance is None else min(tsz, self.sample_distance) + assert high > 1 + + neg_idxs = torch.randint(low=0, high=high, size=(bsz, self.n_negatives * tsz)) + + with torch.no_grad(): + if self.n_negatives > 0: + tszs = ( + buffered_arange(tsz) + .unsqueeze(-1) + .expand(-1, self.n_negatives) + .flatten() + ) + + neg_idxs = torch.randint( + low=0, high=high - 1, size=(bsz, self.n_negatives * tsz) + ) + neg_idxs[neg_idxs >= tszs] += 1 + + if self.cross_sample_negatives > 0: + tszs = ( + buffered_arange(tsz) + .unsqueeze(-1) + .expand(-1, self.cross_sample_negatives) + .flatten() + ) + + cross_neg_idxs = torch.randint( + low=0, + high=cross_high - 1, + size=(bsz, self.cross_sample_negatives * tsz), + ) + cross_neg_idxs[cross_neg_idxs >= tszs] += 1 + + if self.n_negatives > 0: + for i in range(1, bsz): + neg_idxs[i] += i * high + else: + neg_idxs = cross_neg_idxs + + if self.cross_sample_negatives > 0 and self.n_negatives > 0: + neg_idxs = torch.cat([neg_idxs, cross_neg_idxs], dim=1) + + negs = y[..., neg_idxs.view(-1)] + negs = negs.view( + fsz, bsz, self.n_negatives + self.cross_sample_negatives, tsz + ).permute( + 2, 1, 0, 3 + ) # to NxBxCxT + + return negs + + def forward(self, x, y): + + x = x.unsqueeze(-1) + x = self.project_to_steps(x) # BxCxTxS + x = self.dropout(x) + + negatives = self.sample_negatives(y) + y = y.unsqueeze(0) + targets = torch.cat([y, negatives], dim=0) # Copies x B x C x T + + copies = targets.size(0) + bsz, dim, tsz, steps = x.shape + steps = min(steps, tsz - self.offset) + + predictions = x.new( + bsz * copies * (tsz - self.offset + 1) * steps + - ((steps + 1) * steps // 2) * copies * bsz + ) + if self.infonce: + labels = predictions.new_full( + (predictions.shape[0] // copies,), 0, dtype=torch.long + ) + else: + labels = torch.zeros_like(predictions) + weights = ( + torch.full_like(labels, 1 / self.n_negatives) + if self.balanced_classes and not self.infonce + else None + ) + + start = end = 0 + for i in range(steps): + offset = i + self.offset + end = start + (tsz - offset) * bsz * copies + if self.infonce: + predictions[start:end] = torch.einsum( + "bct,nbct->tbn", x[..., :-offset, i], targets[..., offset:] + ).flatten() + else: + pos_num = (end - start) // copies + predictions[start:end] = torch.einsum( + "bct,nbct->nbt", x[..., :-offset, i], targets[..., offset:] + ).flatten() + labels[start : start + pos_num] = 1.0 + if weights is not None: + weights[start : start + pos_num] = 1.0 + start = end + assert end == predictions.numel(), "{} != {}".format(end, predictions.numel()) + + if self.infonce: + predictions = predictions.view(-1, copies) + else: + if weights is not None: + labels = (labels, weights) + + return predictions, labels + + +@register_model_architecture("wav2vec", "wav2vec") +def base_wav2vec_architecture(args): + conv_feature_layers = "[(512, 10, 5)]" + conv_feature_layers += " + [(512, 8, 4)]" + conv_feature_layers += " + [(512, 4, 2)] * 3" + args.conv_feature_layers = getattr(args, "conv_feature_layers", conv_feature_layers) + + args.conv_aggregator_layers = getattr( + args, "conv_aggregator_layers", "[(512, 3, 1)] * 9" + ) + + args.prediction_steps = getattr(args, "prediction_steps", 12) + args.num_negatives = getattr(args, "num_negatives", 1) + args.sample_distance = getattr(args, "sample_distance", None) + args.cross_sample_negatives = getattr(args, "cross_sample_negatives", 0) + + args.dropout = getattr(args, "dropout", 0.0) + args.dropout_features = getattr(args, "dropout_features", 0.0) + args.dropout_agg = getattr(args, "dropout_agg", 0.0) + args.encoder = getattr(args, "encoder", "cnn") + args.aggregator = getattr(args, "aggregator", "cnn") + + args.skip_connections_feat = getattr(args, "skip_connections_feat", False) + args.skip_connections_agg = getattr(args, "skip_connections_agg", False) + args.residual_scale = getattr(args, "residual_scale", 0.5) + + args.gru_dim = getattr(args, "gru_dim", 512) + + args.no_conv_bias = getattr(args, "no_conv_bias", False) + args.agg_zero_pad = getattr(args, "agg_zero_pad", False) + + args.log_compression = getattr(args, "log_compression", False) + + args.balanced_classes = getattr(args, "balanced_classes", False) + args.infonce = getattr(args, "infonce", False) + args.project_features = getattr(args, "project_features", "none") + + args.non_affine_group_norm = getattr(args, "non_affine_group_norm", False) + + args.offset = getattr(args, "offset", "auto") + + args.activation = getattr(args, "activation", "relu") + + args.vq_type = getattr(args, "vq_type", "none") + args.vq_vars = getattr(args, "vq_vars", 320) + args.vq_groups = getattr(args, "vq_groups", 2) + args.vq_dim = getattr(args, "vq_dim", 0) + args.vq_depth = getattr(args, "vq_depth", 1) + args.combine_groups = getattr(args, "combine_groups", False) + args.vq_temp = getattr(args, "vq_temp", "(2.0, 0.5, 0.999995)") + args.vq_gamma = getattr(args, "vq_gamma", 0.25) diff --git a/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2.py b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2.py new file mode 100644 index 00000000..6a0f7876 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2.py @@ -0,0 +1,1029 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import math +from typing import List, Tuple + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.data.data_utils import compute_mask_indices +from fairseq.models import BaseFairseqModel, register_model, register_model_architecture +from fairseq.modules import ( + Fp32GroupNorm, + Fp32LayerNorm, + GradMultiply, + GumbelVectorQuantizer, + LayerNorm, + MultiheadAttention, + SamePad, + TransposeLast, +) +from fairseq.modules.transformer_sentence_encoder import init_bert_params +from fairseq.utils import buffered_arange + + +@register_model("wav2vec2") +class Wav2Vec2Model(BaseFairseqModel): + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + + parser.add_argument( + "--extractor-mode", + choices=["default", "layer_norm"], + help="mode for feature extractor. default has a single group norm with d groups in the first conv block, whereas layer_norm has layer norms in every block (meant to use with --normalize)", + ) + + parser.add_argument( + "--encoder-layers", + type=int, + metavar="L", + help="num encoder layers in the transformer", + ) + parser.add_argument( + "--encoder-embed-dim", + type=int, + metavar="H", + help="encoder embedding dimension", + ) + parser.add_argument( + "--encoder-ffn-embed-dim", + type=int, + metavar="F", + help="encoder embedding dimension for FFN", + ) + parser.add_argument( + "--encoder-attention-heads", + type=int, + metavar="A", + help="num encoder attention heads", + ) + parser.add_argument( + "--activation-fn", + choices=utils.get_available_activation_fns(), + help="activation function to use", + ) + + parser.add_argument( + "--dropout", + type=float, + metavar="D", + help="dropout probability for the transformer", + ) + + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights", + ) + + parser.add_argument( + "--activation-dropout", + type=float, + metavar="D", + help="dropout probability after activation in FFN", + ) + + parser.add_argument( + "--final-dim", + type=int, + metavar="D", + help="project final representations and targets to this many dimensions", + ) + + parser.add_argument( + "--layer-norm-first", + action="store_true", + help="apply layernorm first in the transformer", + ) + + parser.add_argument( + "--encoder-layerdrop", + type=float, + help="probability of dropping a tarnsformer layer", + ) + + parser.add_argument( + "--conv-feature-layers", + type=str, + metavar="EXPR", + help="convolutional feature extraction layers [(dim, kernel_size, stride), ...]", + ) + + parser.add_argument( + "--logit-temp", type=float, help="temperature to divide logits by" + ) + + parser.add_argument( + "--quantize-targets", action="store_true", help="use quantized targets" + ) + + parser.add_argument( + "--quantize-input", action="store_true", help="use quantized inputs" + ) + + parser.add_argument( + "--same-quantizer", + action="store_true", + help="use same quantizer for inputs and targets", + ) + + parser.add_argument( + "--feature-grad-mult", + type=float, + help="multiply feature extractor var grads by this", + ) + + parser.add_argument( + "--latent-vars", + type=int, + metavar="N", + help="number of latent variables V in each group of the codebook", + ) + + parser.add_argument( + "--latent-groups", + type=int, + metavar="N", + help="number of groups G of latent variables in the codebook", + ) + + parser.add_argument( + "--latent-dim", + type=int, + metavar="N", + help="if set, uses this dimensionality for latent variables. otherwise uses final_dim / latent_groups", + ) + + parser.add_argument("--mask-length", type=int, help="mask length") + + parser.add_argument( + "--mask-prob", type=float, help="probability of replacing a token with mask" + ) + + parser.add_argument( + "--mask-selection", + type=str, + choices=["static", "uniform", "normal", "poisson"], + help="how to choose masks", + ) + + parser.add_argument( + "--mask-other", + type=float, + help="secondary mask argument (used for more complex distributions), see help in compute_mask_indices", + ) + + parser.add_argument( + "--no-mask-overlap", + action="store_true", + help="whether to allow masks to overlap", + ) + + parser.add_argument( + "--mask-min-space", + type=int, + help="min space between spans (if no overlap is enabled)", + ) + + parser.add_argument( + "--mask-channel-length", + type=int, + help="repeat the mask indices multiple times", + ) + + parser.add_argument( + "--mask-channel-prob", + type=float, + help="probability of replacing a token with mask", + ) + + parser.add_argument( + "--mask-channel-selection", + type=str, + choices=["static", "uniform", "normal", "poisson"], + help="how to choose masks", + ) + + parser.add_argument( + "--mask-channel-other", + type=float, + help="secondary mask argument (used for more complex distributions), see help in compute_mask_indices", + ) + + parser.add_argument( + "--no-mask-channel-overlap", + action="store_true", + help="whether to allow masks to overlap", + ) + + parser.add_argument( + "--mask-channel-min-space", + type=int, + help="min space between spans (if no overlap is enabled)", + ) + + parser.add_argument( + "--dropout-input", + type=float, + metavar="D", + help="dropout to apply to the input (after feat extr)", + ) + + parser.add_argument( + "--dropout-features", + type=float, + metavar="D", + help="dropout to apply to the features (after feat extr)", + ) + + parser.add_argument( + "--num-negatives", type=int, metavar="N", help="number of negative examples" + ) + + parser.add_argument( + "--negatives-from-everywhere", + action="store_true", + help="sample negatives from everywhere, not just masked states", + ) + + parser.add_argument( + "--cross-sample-negatives", + type=int, + metavar="N", + help="num of cross sampled negatives", + ) + + parser.add_argument( + "--codebook-negatives", + type=int, + metavar="N", + help="num of codebook sampled negatives", + ) + + parser.add_argument( + "--conv-pos", + type=int, + metavar="N", + help="number of filters for convolutional positional embeddings", + ) + + parser.add_argument( + "--conv-pos-groups", + type=int, + metavar="N", + help="number of groups for convolutional positional embedding", + ) + + parser.add_argument( + "--latent-temp", + type=str, + metavar="D", + help="temperature for latent variable sampling. can be tuple of 3 values (start, end, decay)", + ) + + parser.add_argument( + "--target-glu", action="store_true", help="adds projection + glu to targets" + ) + + parser.add_argument( + "--conv-bias", action="store_true", help="include bias in conv encoder" + ) + + def __init__(self, args): + super().__init__() + self.args = args + + feature_enc_layers = eval(args.conv_feature_layers) + self.embed = feature_enc_layers[-1][0] + + self.feature_extractor = ConvFeatureExtractionModel( + conv_layers=feature_enc_layers, + dropout=0.0, + mode=args.extractor_mode, + conv_bias=args.conv_bias, + ) + + self.post_extract_proj = ( + nn.Linear(self.embed, args.encoder_embed_dim) + if self.embed != args.encoder_embed_dim and not args.quantize_input + else None + ) + + self.mask_prob = args.mask_prob + self.mask_selection = args.mask_selection + self.mask_other = args.mask_other + self.mask_length = args.mask_length + self.no_mask_overlap = args.no_mask_overlap + self.mask_min_space = args.mask_min_space + + self.mask_channel_prob = args.mask_channel_prob + self.mask_channel_selection = args.mask_channel_selection + self.mask_channel_other = args.mask_channel_other + self.mask_channel_length = args.mask_channel_length + self.no_mask_channel_overlap = args.no_mask_channel_overlap + self.mask_channel_min_space = args.mask_channel_min_space + + self.dropout_input = nn.Dropout(args.dropout_input) + self.dropout_features = nn.Dropout(args.dropout_features) + + self.feature_grad_mult = args.feature_grad_mult + + self.quantizer = None + self.input_quantizer = None + + self.n_negatives = args.num_negatives + self.cross_sample_negatives = args.cross_sample_negatives + self.codebook_negatives = args.codebook_negatives + self.negatives_from_everywhere = args.negatives_from_everywhere + + self.logit_temp = args.logit_temp + + final_dim = args.final_dim if args.final_dim > 0 else args.encoder_embed_dim + + if args.quantize_targets: + vq_dim = args.latent_dim if args.latent_dim > 0 else final_dim + self.quantizer = GumbelVectorQuantizer( + dim=self.embed, + num_vars=args.latent_vars, + temp=eval(args.latent_temp), + groups=args.latent_groups, + combine_groups=False, + vq_dim=vq_dim, + time_first=True, + ) + self.project_q = nn.Linear(vq_dim, final_dim) + else: + self.project_q = nn.Linear(self.embed, final_dim) + + if args.quantize_input: + if args.same_quantizer and self.quantizer is not None: + vq_dim = final_dim + self.input_quantizer = self.quantizer + else: + vq_dim = ( + args.latent_dim if args.latent_dim > 0 else args.encoder_embed_dim + ) + self.input_quantizer = GumbelVectorQuantizer( + dim=self.embed, + num_vars=args.latent_vars, + temp=eval(args.latent_temp), + groups=args.latent_groups, + combine_groups=False, + vq_dim=vq_dim, + time_first=True, + ) + self.project_inp = nn.Linear(vq_dim, args.encoder_embed_dim) + + self.mask_emb = nn.Parameter( + torch.FloatTensor(args.encoder_embed_dim).uniform_() + ) + + self.encoder = TransformerEncoder(args) + self.layer_norm = LayerNorm(self.embed) + + self.target_glu = None + if args.target_glu: + self.target_glu = nn.Sequential( + nn.Linear(final_dim, final_dim * 2), nn.GLU() + ) + + self.final_proj = nn.Linear(args.encoder_embed_dim, final_dim) + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + return state_dict + + @classmethod + def build_model(cls, args, task=None): + """Build a new model instance.""" + + # make sure all arguments are present + base_architecture(args) + + return cls(args) + + def apply_mask(self, x, padding_mask): + B, T, C = x.shape + if self.mask_prob > 0: + mask_indices = compute_mask_indices( + (B, T), + padding_mask, + self.mask_prob, + self.mask_length, + self.mask_selection, + self.mask_other, + min_masks=2, + no_overlap=self.no_mask_overlap, + min_space=self.mask_min_space, + ) + mask_indices = torch.from_numpy(mask_indices).to(x.device) + x[mask_indices] = self.mask_emb + else: + mask_indices = None + + if self.mask_channel_prob > 0: + mask_channel_indices = compute_mask_indices( + (B, C), + None, + self.mask_channel_prob, + self.mask_channel_length, + self.mask_channel_selection, + self.mask_channel_other, + no_overlap=self.no_mask_channel_overlap, + min_space=self.mask_channel_min_space, + ) + mask_channel_indices = ( + torch.from_numpy(mask_channel_indices) + .to(x.device) + .unsqueeze(1) + .expand(-1, T, -1) + ) + x[mask_channel_indices] = 0 + + return x, mask_indices + + def sample_negatives(self, y, num): + + if self.n_negatives == 0 and self.cross_sample_negatives == 0: + return y.new(0) + + bsz, tsz, fsz = y.shape + y = y.view(-1, fsz) # BTC => (BxT)C + + cross_high = tsz * bsz + high = tsz + with torch.no_grad(): + assert high > 1, f"{bsz,tsz,fsz}" + + if self.n_negatives > 0: + tszs = ( + buffered_arange(num) + .unsqueeze(-1) + .expand(-1, self.n_negatives) + .flatten() + ) + + neg_idxs = torch.randint( + low=0, high=high - 1, size=(bsz, self.n_negatives * num) + ) + neg_idxs[neg_idxs >= tszs] += 1 + + if self.cross_sample_negatives > 0: + tszs = ( + buffered_arange(num) + .unsqueeze(-1) + .expand(-1, self.cross_sample_negatives) + .flatten() + ) + + cross_neg_idxs = torch.randint( + low=0, + high=cross_high - 1, + size=(bsz, self.cross_sample_negatives * num), + ) + cross_neg_idxs[cross_neg_idxs >= tszs] += 1 + + if self.n_negatives > 0: + for i in range(1, bsz): + neg_idxs[i] += i * high + else: + neg_idxs = cross_neg_idxs + + if self.cross_sample_negatives > 0 and self.n_negatives > 0: + neg_idxs = torch.cat([neg_idxs, cross_neg_idxs], dim=1) + + negs = y[neg_idxs.view(-1)] + negs = negs.view( + bsz, num, self.n_negatives + self.cross_sample_negatives, fsz + ).permute( + 2, 0, 1, 3 + ) # to NxBxTxC + return negs, neg_idxs + + def compute_preds(self, x, y, negatives): + + neg_is_pos = (y == negatives).all(-1) + y = y.unsqueeze(0) + targets = torch.cat([y, negatives], dim=0) + + logits = torch.cosine_similarity(x.float(), targets.float(), dim=-1).type_as(x) + + logits /= self.logit_temp + + if neg_is_pos.any(): + logits[1:][neg_is_pos] = float("-inf") + + return logits + + def forward(self, source, padding_mask=None, mask=True, features_only=False): + + if self.feature_grad_mult > 0: + features = self.feature_extractor(source) + if self.feature_grad_mult != 1.0: + features = GradMultiply.apply(features, self.feature_grad_mult) + else: + with torch.no_grad(): + features = self.feature_extractor(source) + + features_pen = features.float().pow(2).mean() + + features = features.transpose(1, 2) + features = self.layer_norm(features) + unmasked_features = features.clone() + + if padding_mask is not None: + extra = padding_mask.size(1) % features.size(1) + if extra > 0: + padding_mask = padding_mask[:, :-extra] + padding_mask = padding_mask.view(padding_mask.size(0), features.size(1), -1) + padding_mask = padding_mask.all(-1) + + if self.post_extract_proj is not None: + features = self.post_extract_proj(features) + + features = self.dropout_input(features) + unmasked_features = self.dropout_features(unmasked_features) + + num_vars = None + code_ppl = None + prob_ppl = None + curr_temp = None + + if self.input_quantizer: + q = self.input_quantizer(features, produce_targets=False) + features = q["x"] + num_vars = q["num_vars"] + code_ppl = q["code_perplexity"] + prob_ppl = q["prob_perplexity"] + curr_temp = q["temp"] + features = self.project_inp(features) + + if mask: + x, mask_indices = self.apply_mask(features, padding_mask) + if mask_indices is not None: + y = unmasked_features[mask_indices].view( + unmasked_features.size(0), -1, unmasked_features.size(-1) + ) + else: + y = unmasked_features + else: + x = features + y = unmasked_features + mask_indices = None + + x = self.encoder(x, padding_mask=padding_mask) + + if features_only: + return {"x": x, "padding_mask": padding_mask} + + if self.quantizer: + q = self.quantizer(y, produce_targets=False) + y = q["x"] + num_vars = q["num_vars"] + code_ppl = q["code_perplexity"] + prob_ppl = q["prob_perplexity"] + curr_temp = q["temp"] + + y = self.project_q(y) + + if self.negatives_from_everywhere: + neg_cands, *_ = self.quantizer(unmasked_features, produce_targets=False) + negs, _ = self.sample_negatives(neg_cands, y.size(1)) + negs = self.project_q(negs) + + else: + negs, _ = self.sample_negatives(y, y.size(1)) + + if self.codebook_negatives > 0: + cb_negs = self.quantizer.sample_from_codebook( + y.size(0) * y.size(1), self.codebook_negatives + ) + cb_negs = cb_negs.view( + self.codebook_negatives, y.size(0), y.size(1), -1 + ) # order doesnt matter + cb_negs = self.project_q(cb_negs) + negs = torch.cat([negs, cb_negs], dim=0) + else: + y = self.project_q(y) + + if self.negatives_from_everywhere: + negs, _ = self.sample_negatives(unmasked_features, y.size(1)) + negs = self.project_q(negs) + else: + negs, _ = self.sample_negatives(y, y.size(1)) + + x = x[mask_indices].view(x.size(0), -1, x.size(-1)) + + if self.target_glu: + y = self.target_glu(y) + negs = self.target_glu(negs) + + x = self.final_proj(x) + x = self.compute_preds(x, y, negs) + + result = {"x": x, "padding_mask": padding_mask, "features_pen": features_pen} + + if prob_ppl is not None: + result["prob_perplexity"] = prob_ppl + result["code_perplexity"] = code_ppl + result["num_vars"] = num_vars + result["temp"] = curr_temp + + return result + + def quantize(self, x): + assert self.quantizer is not None + x = self.feature_extractor(x) + x = x.transpose(1, 2) + x = self.layer_norm(x) + return self.quantizer.forward_idx(x) + + def extract_features(self, source, padding_mask, mask=False): + res = self.forward(source, padding_mask, mask=mask, features_only=True) + return res["x"], res["padding_mask"] + + def get_logits(self, net_output): + logits = net_output["x"] + logits = logits.transpose(0, 2) + logits = logits.reshape(-1, logits.size(-1)) + return logits + + def get_targets(self, sample, net_output, expand_steps=True): + x = net_output["x"] + return x.new_zeros(x.size(1) * x.size(2), dtype=torch.long) + + def get_extra_losses(self, net_output): + pen = [] + + if "prob_perplexity" in net_output: + pen.append( + (net_output["num_vars"] - net_output["prob_perplexity"]) + / net_output["num_vars"] + ) + + if "features_pen" in net_output: + pen.append(net_output["features_pen"]) + + return pen + + def remove_pretraining_modules(self): + self.quantizer = None + self.project_q = None + self.target_glu = None + self.final_proj = None + + +class ConvFeatureExtractionModel(nn.Module): + def __init__( + self, + conv_layers: List[Tuple[int, int, int]], + dropout: float = 0.0, + mode: str = "default", + conv_bias: bool = False, + ): + super().__init__() + + assert mode in {"default", "layer_norm"} + + def block( + n_in, + n_out, + k, + stride, + is_layer_norm=False, + is_group_norm=False, + conv_bias=False, + ): + def make_conv(): + conv = nn.Conv1d(n_in, n_out, k, stride=stride, bias=conv_bias) + nn.init.kaiming_normal_(conv.weight) + return conv + + assert ( + is_layer_norm and is_group_norm + ) == False, "layer norm and group norm are exclusive" + + if is_layer_norm: + return nn.Sequential( + make_conv(), + nn.Dropout(p=dropout), + nn.Sequential( + TransposeLast(), + Fp32LayerNorm(dim, elementwise_affine=True), + TransposeLast(), + ), + nn.GELU(), + ) + elif is_group_norm: + return nn.Sequential( + make_conv(), + nn.Dropout(p=dropout), + Fp32GroupNorm(dim, dim, affine=True), + nn.GELU(), + ) + else: + return nn.Sequential(make_conv(), nn.Dropout(p=dropout), nn.GELU()) + + in_d = 1 + self.conv_layers = nn.ModuleList() + for i, cl in enumerate(conv_layers): + assert len(cl) == 3, "invalid conv definition: " + str(cl) + (dim, k, stride) = cl + + self.conv_layers.append( + block( + in_d, + dim, + k, + stride, + is_layer_norm=mode == "layer_norm", + is_group_norm=mode == "default" and i == 0, + conv_bias=conv_bias, + ) + ) + in_d = dim + + def forward(self, x): + + # BxT -> BxCxT + x = x.unsqueeze(1) + + for conv in self.conv_layers: + x = conv(x) + + return x + + +class TransformerEncoder(nn.Module): + def __init__(self, args): + super().__init__() + + self.dropout = args.dropout + self.embedding_dim = args.encoder_embed_dim + + self.pos_conv = nn.Conv1d( + self.embedding_dim, + self.embedding_dim, + kernel_size=args.conv_pos, + padding=args.conv_pos // 2, + groups=args.conv_pos_groups, + ) + dropout = 0 + std = math.sqrt((4 * (1.0 - dropout)) / (args.conv_pos * self.embedding_dim)) + nn.init.normal_(self.pos_conv.weight, mean=0, std=std) + nn.init.constant_(self.pos_conv.bias, 0) + + self.pos_conv = nn.utils.weight_norm(self.pos_conv, name="weight", dim=2) + self.pos_conv = nn.Sequential(self.pos_conv, SamePad(args.conv_pos), nn.GELU()) + + self.layers = nn.ModuleList( + [ + TransformerSentenceEncoderLayer( + embedding_dim=self.embedding_dim, + ffn_embedding_dim=args.encoder_ffn_embed_dim, + num_attention_heads=args.encoder_attention_heads, + dropout=self.dropout, + attention_dropout=args.attention_dropout, + activation_dropout=args.activation_dropout, + activation_fn=args.activation_fn, + layer_norm_first=args.layer_norm_first, + ) + for _ in range(args.encoder_layers) + ] + ) + + self.layer_norm_first = args.layer_norm_first + self.layer_norm = LayerNorm(self.embedding_dim) + self.layerdrop = args.encoder_layerdrop + + self.apply(init_bert_params) + + def forward(self, x, padding_mask=None): + x = self.extract_features(x, padding_mask) + + if self.layer_norm_first: + x = self.layer_norm(x) + + return x + + def extract_features(self, x, padding_mask=None): + + if padding_mask is not None: + x[padding_mask] = 0 + + x_conv = self.pos_conv(x.transpose(1, 2)) + x_conv = x_conv.transpose(1, 2) + x += x_conv + + if not self.layer_norm_first: + x = self.layer_norm(x) + + x = F.dropout(x, p=self.dropout, training=self.training) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + layer_results = [] + for i, layer in enumerate(self.layers): + dropout_probability = np.random.random() + if not self.training or (dropout_probability > self.layerdrop): + x, z = layer(x, self_attn_padding_mask=padding_mask, need_weights=False) + layer_results.append(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + return x + + def max_positions(self): + """Maximum output length supported by the encoder.""" + return self.args.max_positions + + def upgrade_state_dict_named(self, state_dict, name): + """Upgrade a (possibly old) state dict for new versions of fairseq.""" + return state_dict + + +class TransformerSentenceEncoderLayer(nn.Module): + """ + Implements a Transformer Encoder Layer used in BERT/XLM style pre-trained + models. + """ + + def __init__( + self, + embedding_dim: float = 768, + ffn_embedding_dim: float = 3072, + num_attention_heads: float = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + activation_fn: str = "relu", + layer_norm_first: bool = False, + ) -> None: + + super().__init__() + # Initialize parameters + self.embedding_dim = embedding_dim + self.dropout = dropout + self.activation_dropout = activation_dropout + + # Initialize blocks + self.activation_fn = utils.get_activation_fn(activation_fn) + self.self_attn = MultiheadAttention( + self.embedding_dim, + num_attention_heads, + dropout=attention_dropout, + self_attention=True, + ) + + self.dropout1 = nn.Dropout(dropout) + self.dropout2 = nn.Dropout(self.activation_dropout) + self.dropout3 = nn.Dropout(dropout) + + self.layer_norm_first = layer_norm_first + + # layer norm associated with the self attention layer + self.self_attn_layer_norm = LayerNorm(self.embedding_dim) + self.fc1 = nn.Linear(self.embedding_dim, ffn_embedding_dim) + self.fc2 = nn.Linear(ffn_embedding_dim, self.embedding_dim) + + # layer norm associated with the position wise feed-forward NN + self.final_layer_norm = LayerNorm(self.embedding_dim) + + def forward( + self, + x: torch.Tensor, + self_attn_mask: torch.Tensor = None, + self_attn_padding_mask: torch.Tensor = None, + need_weights: bool = False, + att_args=None, + ): + """ + LayerNorm is applied either before or after the self-attention/ffn + modules similar to the original Transformer imlementation. + """ + residual = x + + if self.layer_norm_first: + x = self.self_attn_layer_norm(x) + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + need_weights=False, + attn_mask=self_attn_mask, + ) + x = self.dropout1(x) + x = residual + x + + residual = x + x = self.final_layer_norm(x) + x = self.activation_fn(self.fc1(x)) + x = self.dropout2(x) + x = self.fc2(x) + x = self.dropout3(x) + x = residual + x + else: + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + need_weights=need_weights, + ) + + x = self.dropout1(x) + x = residual + x + + x = self.self_attn_layer_norm(x) + + residual = x + x = self.activation_fn(self.fc1(x)) + x = self.dropout2(x) + x = self.fc2(x) + x = self.dropout3(x) + x = residual + x + x = self.final_layer_norm(x) + + return x, attn + + +@register_model_architecture("wav2vec2", "wav2vec2") +def base_architecture(args): + args.extractor_mode = getattr(args, "extractor_mode", "default") + + args.encoder_layers = getattr(args, "encoder_layers", 12) + args.encoder_embed_dim = getattr(args, "encoder_embed_dim", 768) + args.encoder_ffn_embed_dim = getattr(args, "encoder_ffn_embed_dim", 3072) + args.encoder_attention_heads = getattr(args, "encoder_attention_heads", 12) + + args.activation_fn = getattr(args, "activation_fn", "gelu") + + args.dropout = getattr(args, "dropout", 0.1) + args.attention_dropout = getattr(args, "attention_dropout", 0.1) + args.activation_dropout = getattr(args, "activation_dropout", 0.0) + + args.final_dim = getattr(args, "final_dim", 0) + + args.layer_norm_first = getattr(args, "layer_norm_first", False) + args.encoder_layerdrop = getattr(args, "encoder_layerdrop", 0.0) + + conv_feature_layers = "[(512, 10, 5)]" + conv_feature_layers += " + [(512, 8, 4)]" + conv_feature_layers += " + [(512, 4, 2)] * 3" + conv_feature_layers += " + [(512, 1, 1)]" + args.conv_feature_layers = getattr(args, "conv_feature_layers", conv_feature_layers) + + args.logit_temp = getattr(args, "logit_temp", 0.1) + + args.quantize_targets = getattr(args, "quantize_targets", False) + args.quantize_input = getattr(args, "quantize_input", False) + args.same_quantizer = getattr(args, "same_quantizer", False) + + args.feature_grad_mult = getattr(args, "feature_grad_mult", 1.0) + + args.latent_vars = getattr(args, "latent_vars", 320) + args.latent_groups = getattr(args, "latent_groups", 2) + args.latent_dim = getattr(args, "latent_dim", 0) + + args.mask_length = getattr(args, "mask_length", 10) + args.mask_prob = getattr(args, "mask_prob", 0.65) + args.mask_selection = getattr(args, "mask_selection", "static") + args.mask_other = getattr(args, "mask_other", 0) + args.no_mask_overlap = getattr(args, "no_mask_overlap", False) + args.mask_min_space = getattr(args, "mask_min_space", 1) + + args.mask_channel_length = getattr(args, "mask_channel_length", 10) + args.mask_channel_prob = getattr(args, "mask_channel_prob", 0) + args.mask_channel_selection = getattr(args, "mask_channel_selection", "static") + args.mask_channel_other = getattr(args, "mask_channel_other", 0) + args.no_mask_channel_overlap = getattr(args, "no_mask_channel_overlap", False) + args.mask_channel_min_space = getattr(args, "mask_channel_min_space", 1) + + args.dropout_input = getattr(args, "dropout_input", 0) + args.dropout_features = getattr(args, "dropout_features", 0) + + args.num_negatives = getattr(args, "num_negatives", 100) + args.negatives_from_everywhere = getattr(args, "negatives_from_everywhere", False) + args.cross_sample_negatives = getattr(args, "cross_sample_negatives", 0) + args.codebook_negatives = getattr(args, "codebook_negatives", 0) + + args.conv_pos = getattr(args, "conv_pos", 128) + args.conv_pos_groups = getattr(args, "conv_pos_groups", 16) + + args.latent_temp = getattr(args, "latent_temp", "(2,0.5,0.999995)") + + args.target_glu = getattr(args, "target_glu", False) + + args.conv_bias = getattr(args, "conv_bias", False) diff --git a/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2_asr.py b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2_asr.py new file mode 100644 index 00000000..52ca9a80 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/models/wav2vec/wav2vec2_asr.py @@ -0,0 +1,675 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import copy +import math + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import checkpoint_utils, tasks, utils +from fairseq.models import ( + BaseFairseqModel, + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, + register_model, + register_model_architecture, +) +from fairseq.modules import LayerNorm, PositionalEmbedding, TransformerDecoderLayer + + +def add_common_args(parser): + parser.add_argument("--w2v-path", help="path to wav2vec 2.0 model") + parser.add_argument( + "--no-pretrained-weights", + action="store_true", + help="if true, does not load pretrained weights", + ) + parser.add_argument( + "--dropout-input", + type=float, + metavar="D", + help="dropout to apply to the input (after feat extr)", + ) + parser.add_argument( + "--final-dropout", + type=float, + metavar="D", + help="dropout after transformer and before final projection", + ) + parser.add_argument( + "--apply-mask", action="store_true", help="apply masking during fine-tuning" + ) + parser.add_argument( + "--dropout", + type=float, + metavar="D", + help="dropout probability inside wav2vec 2.0 model", + ) + parser.add_argument( + "--attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights inside wav2vec 2.0 model", + ) + parser.add_argument( + "--activation-dropout", + "--relu-dropout", + type=float, + metavar="D", + help="dropout probability after activation in FFN inside wav2vec 2.0 model", + ) + + parser.add_argument( + "--mask-length", type=int, help="repeat the mask indices multiple times" + ) + + parser.add_argument( + "--mask-prob", type=float, help="probability of replacing a token with mask" + ) + + parser.add_argument( + "--mask-selection", + type=str, + choices=["static", "uniform", "normal", "poisson"], + help="how to choose masks", + ) + + parser.add_argument( + "--mask-other", + type=float, + help="stdev of the mask length in case of 'normal' selection strategy", + ) + + parser.add_argument( + "--no-mask-overlap", + action="store_true", + help="whether to allow masks to overlap", + ) + + parser.add_argument( + "--mask-channel-length", type=int, help="repeat the mask indices multiple times" + ) + + parser.add_argument( + "--mask-channel-prob", + type=float, + help="probability of replacing a token with mask", + ) + + parser.add_argument( + "--mask-channel-selection", + type=str, + choices=["static", "uniform", "normal", "poisson"], + help="how to choose masks", + ) + + parser.add_argument( + "--mask-channel-other", + type=float, + help="stdev of the mask length in case of 'normal' selection strategy", + ) + + parser.add_argument( + "--no-mask-channel-overlap", + action="store_true", + help="whether to allow masks to overlap", + ) + + parser.add_argument( + "--freeze-finetune-updates", + default=0, + type=int, + help="dont finetune wav2vec for this many updates", + ) + + parser.add_argument( + "--feature-grad-mult", + default=None, + type=float, + help="reset feature grad mult in wav2vec 2.0 to this", + ) + + parser.add_argument( + "--layerdrop", + default=0.0, + type=float, + help="probability of dropping a layer in wav2vec 2.0", + ) + + +@register_model("wav2vec_ctc") +class Wav2VecCtc(BaseFairseqModel): + @staticmethod + def add_args(parser): + """Add model-specific arguments to the parser.""" + add_common_args(parser) + + def __init__(self, w2v_encoder, args): + super().__init__() + self.w2v_encoder = w2v_encoder + self.args = args + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + return state_dict + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + base_architecture(args) + w2v_encoder = Wav2VecEncoder(args, task.target_dictionary) + return cls(w2v_encoder, args) + + def get_normalized_probs(self, net_output, log_probs): + """Get normalized probabilities (or log probs) from a net's output.""" + + logits = net_output["encoder_out"] + if log_probs: + return utils.log_softmax(logits.float(), dim=-1) + else: + return utils.softmax(logits.float(), dim=-1) + + def forward(self, **kwargs): + x = self.w2v_encoder(**kwargs) + return x + + # def max_positions(self): + # return None + + +@register_model("wav2vec_seq2seq") +class TransformerModel(FairseqEncoderDecoderModel): + def __init__(self, args, encoder, decoder): + super().__init__(encoder, decoder) + + @staticmethod + def add_args(parser): + add_common_args(parser) + + parser.add_argument( + "--decoder-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension", + ) + parser.add_argument( + "--decoder-ffn-embed-dim", + type=int, + metavar="N", + help="decoder embedding dimension for FFN", + ) + parser.add_argument( + "--decoder-layers", type=int, metavar="N", help="num decoder layers" + ) + parser.add_argument( + "--decoder-layerdrop", + type=float, + metavar="D", + help="decoder layerdrop chance", + ) + parser.add_argument( + "--decoder-attention-heads", + type=int, + metavar="N", + help="num decoder attention heads", + ) + parser.add_argument( + "--decoder-learned-pos", + action="store_true", + help="use learned positional embeddings in the decoder", + ) + parser.add_argument( + "--decoder-normalize-before", + action="store_true", + help="apply layernorm before each decoder block", + ) + parser.add_argument( + "--no-token-positional-embeddings", + default=False, + action="store_true", + help="if set, disables positional embeddings (outside self attention)", + ) + + parser.add_argument( + "--decoder-dropout", + type=float, + metavar="D", + help="dropout probability in the decoder", + ) + parser.add_argument( + "--decoder-attention-dropout", + type=float, + metavar="D", + help="dropout probability for attention weights inside the decoder", + ) + parser.add_argument( + "--decoder-activation-dropout", + type=float, + metavar="D", + help="dropout probability after activation in FFN inside the decoder", + ) + + # fmt: on + + @classmethod + def build_model(cls, args, task): + """Build a new model instance.""" + + # make sure all arguments are present in older models + base_architecture(args) + + if not hasattr(args, "max_source_positions"): + args.max_source_positions = 2048 + if not hasattr(args, "max_target_positions"): + args.max_target_positions = 2048 + + src_dict, tgt_dict = task.source_dictionary, task.target_dictionary + + def build_embedding(dictionary, embed_dim): + num_embeddings = len(dictionary) + padding_idx = dictionary.pad() + emb = Embedding(num_embeddings, embed_dim, padding_idx) + return emb + + decoder_embed_tokens = build_embedding(tgt_dict, args.decoder_embed_dim) + + encoder = cls.build_encoder(args) + decoder = cls.build_decoder(args, tgt_dict, decoder_embed_tokens) + return TransformerModel(args, encoder, decoder) + + @classmethod + def build_encoder(cls, args): + return Wav2VecEncoder(args) + + @classmethod + def build_decoder(cls, args, tgt_dict, embed_tokens): + return TransformerDecoder(args, tgt_dict, embed_tokens) + + def forward(self, **kwargs): + encoder_out = self.encoder(tbc=False, **kwargs) + decoder_out = self.decoder(encoder_out=encoder_out, **kwargs) + return decoder_out + + def upgrade_state_dict_named(self, state_dict, name): + super().upgrade_state_dict_named(state_dict, name) + return state_dict + + +class Wav2VecEncoder(FairseqEncoder): + def __init__(self, args, tgt_dict=None): + self.apply_mask = args.apply_mask + + arg_overrides = { + "dropout": args.dropout, + "activation_dropout": args.activation_dropout, + "dropout_input": args.dropout_input, + "attention_dropout": args.attention_dropout, + "mask_length": args.mask_length, + "mask_prob": args.mask_prob, + "mask_selection": args.mask_selection, + "mask_other": args.mask_other, + "no_mask_overlap": args.no_mask_overlap, + "mask_channel_length": args.mask_channel_length, + "mask_channel_prob": args.mask_channel_prob, + "mask_channel_selection": args.mask_channel_selection, + "mask_channel_other": args.mask_channel_other, + "no_mask_channel_overlap": args.no_mask_channel_overlap, + "encoder_layerdrop": args.layerdrop, + "feature_grad_mult": args.feature_grad_mult, + } + + if getattr(args, "w2v_args", None) is None: + state = checkpoint_utils.load_checkpoint_to_cpu( + args.w2v_path, arg_overrides + ) + w2v_args = state["args"] + else: + state = None + w2v_args = args.w2v_args + + assert ( + args.normalize == w2v_args.normalize + ), "Fine-tuning works best when data normalization is the same" + + w2v_args.data = args.data + task = tasks.setup_task(w2v_args) + model = task.build_model(w2v_args) + + if state is not None and not args.no_pretrained_weights: + model.load_state_dict(state["model"], strict=True) + + model.remove_pretraining_modules() + + super().__init__(task.source_dictionary) + + d = w2v_args.encoder_embed_dim + + self.w2v_model = model + + self.final_dropout = nn.Dropout(args.final_dropout) + self.freeze_finetune_updates = args.freeze_finetune_updates + self.num_updates = 0 + + if tgt_dict is not None: + self.proj = Linear(d, len(tgt_dict)) + elif getattr(args, "decoder_embed_dim", d) != d: + self.proj = Linear(d, args.decoder_embed_dim) + else: + self.proj = None + + def set_num_updates(self, num_updates): + """Set the number of parameters updates.""" + super().set_num_updates(num_updates) + self.num_updates = num_updates + + def forward(self, source, padding_mask, tbc=True, **kwargs): + + w2v_args = { + "source": source, + "padding_mask": padding_mask, + "mask": self.apply_mask and self.training, + } + + ft = self.freeze_finetune_updates <= self.num_updates + + with torch.no_grad() if not ft else contextlib.ExitStack(): + x, padding_mask = self.w2v_model.extract_features(**w2v_args) + + if tbc: + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + x = self.final_dropout(x) + + if self.proj: + x = self.proj(x) + + return { + "encoder_out": x, # T x B x C + "encoder_padding_mask": padding_mask, # B x T + "padding_mask": padding_mask, + } + + def reorder_encoder_out(self, encoder_out, new_order): + if encoder_out["encoder_out"] is not None: + encoder_out["encoder_out"] = encoder_out["encoder_out"].index_select( + 1, new_order + ) + if encoder_out["encoder_padding_mask"] is not None: + encoder_out["encoder_padding_mask"] = encoder_out[ + "encoder_padding_mask" + ].index_select(0, new_order) + return encoder_out + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return None + + def upgrade_state_dict_named(self, state_dict, name): + return state_dict + + +class TransformerDecoder(FairseqIncrementalDecoder): + """ + Transformer decoder consisting of *args.decoder_layers* layers. Each layer + is a :class:`TransformerDecoderLayer`. + + Args: + args (argparse.Namespace): parsed command-line arguments + dictionary (~fairseq.data.Dictionary): decoding dictionary + embed_tokens (torch.nn.Embedding): output embedding + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__(self, args, dictionary, embed_tokens, no_encoder_attn=False): + super().__init__(dictionary) + + self.dropout = args.decoder_dropout + self.share_input_output_embed = args.share_decoder_input_output_embed + + input_embed_dim = embed_tokens.embedding_dim + embed_dim = args.decoder_embed_dim + self.output_embed_dim = args.decoder_embed_dim + args.encoder_embed_dim = embed_dim + + self.layerdrop = args.decoder_layerdrop + + padding_idx = embed_tokens.padding_idx + self.max_target_positions = args.max_target_positions + + self.embed_tokens = embed_tokens + self.embed_scale = math.sqrt(embed_dim) # todo: try with input_embed_dim + + self.project_in_dim = ( + Linear(input_embed_dim, embed_dim, bias=False) + if embed_dim != input_embed_dim + else None + ) + + self.embed_positions = ( + PositionalEmbedding( + args.max_target_positions, + embed_dim, + padding_idx, + learned=args.decoder_learned_pos, + ) + if not args.no_token_positional_embeddings + else None + ) + + args = copy.deepcopy(args) + args.dropout = args.decoder_dropout + args.attention_dropout = args.decoder_attention_dropout + args.activation_dropout = args.decoder_activation_dropout + + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + TransformerDecoderLayer(args, no_encoder_attn) + for _ in range(args.decoder_layers) + ] + ) + + if not self.share_input_output_embed: + self.embed_out = nn.Parameter( + torch.Tensor(len(dictionary), self.output_embed_dim) + ) + nn.init.normal_(self.embed_out, mean=0, std=self.output_embed_dim ** -0.5) + + if args.decoder_normalize_before and not getattr( + args, "no_decoder_final_norm", False + ): + self.layer_norm = LayerNorm(embed_dim) + else: + self.layer_norm = None + + def forward( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **unused + ): + """ + Args: + prev_output_tokens (LongTensor): previous decoder outputs of shape + `(batch, tgt_len)`, for teacher forcing + encoder_out (Tensor, optional): output from the encoder, used for + encoder-side attention + incremental_state (dict): dictionary used for storing state during + :ref:`Incremental decoding` + + Returns: + tuple: + - the decoder's output of shape `(batch, tgt_len, vocab)` + - a dictionary with any model-specific outputs + """ + prev_output_tokens = prev_output_tokens.long() + x, extra = self.extract_features( + prev_output_tokens, encoder_out, incremental_state + ) + x = self.output_layer(x) + return x, extra + + def extract_features( + self, prev_output_tokens, encoder_out=None, incremental_state=None, **unused + ): + """ + Similar to *forward* but only return features. + + Returns: + tuple: + - the decoder's features of shape `(batch, tgt_len, embed_dim)` + - a dictionary with any model-specific outputs + """ + + # embed positions + positions = ( + self.embed_positions( + prev_output_tokens, incremental_state=incremental_state + ) + if self.embed_positions is not None + else None + ) + + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + if positions is not None: + positions = positions[:, -1:] + + # embed tokens and positions + x = self.embed_scale * self.embed_tokens(prev_output_tokens) + + if self.project_in_dim is not None: + x = self.project_in_dim(x) + + if positions is not None: + x += positions + x = F.dropout(x, p=self.dropout, training=self.training) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + attn = None + + inner_states = [x] + + # decoder layers + for layer in self.layers: + dropout_probability = np.random.random() + if not self.training or (dropout_probability > self.layerdrop): + x, attn, _ = layer( + x, + encoder_out["encoder_out"] if encoder_out is not None else None, + encoder_out["encoder_padding_mask"] + if encoder_out is not None + else None, + incremental_state, + self_attn_mask=self.buffered_future_mask(x) + if incremental_state is None + else None, + ) + inner_states.append(x) + + if self.layer_norm: + x = self.layer_norm(x) + + # T x B x C -> B x T x C + x = x.transpose(0, 1) + + return x, {"attn": attn, "inner_states": inner_states} + + def output_layer(self, features, **kwargs): + """Project features to the vocabulary size.""" + # project back to size of vocabulary + if self.share_input_output_embed: + return F.linear(features, self.embed_tokens.weight) + else: + return F.linear(features, self.embed_out) + + def max_positions(self): + """Maximum output length supported by the decoder.""" + if self.embed_positions is None: + return self.max_target_positions + return min(self.max_target_positions, self.embed_positions.max_positions) + + def buffered_future_mask(self, tensor): + dim = tensor.size(0) + if ( + not hasattr(self, "_future_mask") + or self._future_mask is None + or self._future_mask.device != tensor.device + or self._future_mask.size(0) < dim + ): + self._future_mask = torch.triu( + utils.fill_with_neg_inf(tensor.new(dim, dim)), 1 + ) + return self._future_mask[:dim, :dim] + + def upgrade_state_dict_named(self, state_dict, name): + return state_dict + + +def Embedding(num_embeddings, embedding_dim, padding_idx): + m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) + nn.init.normal_(m.weight, mean=0, std=embedding_dim ** -0.5) + nn.init.constant_(m.weight[padding_idx], 0) + return m + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m + + +@register_model_architecture("wav2vec_ctc", "wav2vec_ctc") +def base_architecture(args): + args.no_pretrained_weights = getattr(args, "no_pretrained_weights", False) + args.dropout_input = getattr(args, "dropout_input", 0) + args.final_dropout = getattr(args, "final_dropout", 0) + args.apply_mask = getattr(args, "apply_mask", False) + args.dropout = getattr(args, "dropout", 0) + args.attention_dropout = getattr(args, "attention_dropout", 0) + args.activation_dropout = getattr(args, "activation_dropout", 0) + + args.mask_length = getattr(args, "mask_length", 10) + args.mask_prob = getattr(args, "mask_prob", 0.5) + args.mask_selection = getattr(args, "mask_selection", "static") + args.mask_other = getattr(args, "mask_other", 0) + args.no_mask_overlap = getattr(args, "no_mask_overlap", False) + args.mask_channel_length = getattr(args, "mask_channel_length", 10) + args.mask_channel_prob = getattr(args, "mask_channel_prob", 0.5) + args.mask_channel_selection = getattr(args, "mask_channel_selection", "static") + args.mask_channel_other = getattr(args, "mask_channel_other", 0) + args.no_mask_channel_overlap = getattr(args, "no_mask_channel_overlap", False) + + args.freeze_finetune_updates = getattr(args, "freeze_finetune_updates", 0) + args.feature_grad_mult = getattr(args, "feature_grad_mult", 0) + args.layerdrop = getattr(args, "layerdrop", 0.0) + + +@register_model_architecture("wav2vec_seq2seq", "wav2vec_seq2seq") +def seq2seq_architecture(args): + args.decoder_embed_dim = getattr(args, "decoder_embed_dim", 1024) + args.decoder_ffn_embed_dim = getattr(args, "decoder_ffn_embed_dim", 4096) + args.decoder_layers = getattr(args, "decoder_layers", 10) + args.decoder_layerdrop = getattr(args, "decoder_layerdrop", 0) + args.decoder_attention_heads = getattr(args, "decoder_attention_heads", 16) + args.decoder_learned_pos = getattr(args, "decoder_learned_pos", False) + args.decoder_normalize_before = getattr(args, "decoder_normalize_before", False) + args.no_token_positional_embeddings = getattr( + args, "no_token_positional_embeddings", False + ) + args.decoder_dropout = getattr(args, "decoder_dropout", 0) + args.decoder_attention_dropout = getattr(args, "decoder_attention_dropout", 0) + args.decoder_activation_dropout = getattr(args, "decoder_activation_dropout", 0) + args.share_decoder_input_output_embed = getattr( + args, "share_decoder_input_output_embed", False + ) + + base_architecture(args) diff --git a/fairseq-tools/fairseq/fairseq/modules/__init__.py b/fairseq-tools/fairseq/fairseq/modules/__init__.py new file mode 100644 index 00000000..e2326ac6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/__init__.py @@ -0,0 +1,76 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +from .adaptive_input import AdaptiveInput +from .adaptive_softmax import AdaptiveSoftmax +from .beamable_mm import BeamableMM +from .character_token_embedder import CharacterTokenEmbedder +from .conv_tbc import ConvTBC +from .cross_entropy import cross_entropy +from .downsampled_multihead_attention import DownsampledMultiHeadAttention +from .dynamic_convolution import DynamicConv, DynamicConv1dTBC +from .dynamic_crf_layer import DynamicCRF +from .fairseq_dropout import FairseqDropout +from .fp32_group_norm import Fp32GroupNorm +from .gelu import gelu, gelu_accurate +from .grad_multiply import GradMultiply +from .gumbel_vector_quantizer import GumbelVectorQuantizer +from .kmeans_vector_quantizer import KmeansVectorQuantizer +from .layer_drop import LayerDropModuleList +from .layer_norm import Fp32LayerNorm, LayerNorm +from .learned_positional_embedding import LearnedPositionalEmbedding +from .lightweight_convolution import LightweightConv, LightweightConv1dTBC +from .linearized_convolution import LinearizedConvolution +from .multihead_attention import MultiheadAttention +from .positional_embedding import PositionalEmbedding +from .same_pad import SamePad +from .scalar_bias import ScalarBias +from .sinusoidal_positional_embedding import SinusoidalPositionalEmbedding +from .transformer_sentence_encoder_layer import TransformerSentenceEncoderLayer +from .transformer_sentence_encoder import TransformerSentenceEncoder +from .transpose_last import TransposeLast +from .unfold import unfold1d +from .transformer_layer import TransformerDecoderLayer, TransformerEncoderLayer +from .vggblock import VGGBlock + +__all__ = [ + "AdaptiveInput", + "AdaptiveSoftmax", + "BeamableMM", + "CharacterTokenEmbedder", + "ConvTBC", + "cross_entropy", + "DownsampledMultiHeadAttention", + "DynamicConv1dTBC", + "DynamicConv", + "DynamicCRF", + "FairseqDropout", + "Fp32GroupNorm", + "Fp32LayerNorm", + "gelu", + "gelu_accurate", + "GradMultiply", + "GumbelVectorQuantizer", + "KmeansVectorQuantizer", + "LayerDropModuleList", + "LayerNorm", + "LearnedPositionalEmbedding", + "LightweightConv1dTBC", + "LightweightConv", + "LinearizedConvolution", + "MultiheadAttention", + "PositionalEmbedding", + "SamePad", + "ScalarBias", + "SinusoidalPositionalEmbedding", + "TransformerSentenceEncoderLayer", + "TransformerSentenceEncoder", + "TransformerDecoderLayer", + "TransformerEncoderLayer", + "TransposeLast", + "VGGBlock", + "unfold1d", +] diff --git a/fairseq-tools/fairseq/fairseq/modules/adaptive_input.py b/fairseq-tools/fairseq/fairseq/modules/adaptive_input.py new file mode 100644 index 00000000..446534a9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/adaptive_input.py @@ -0,0 +1,80 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from typing import List + +import torch +from fairseq.modules.quant_noise import quant_noise +from torch import nn + + +class AdaptiveInput(nn.Module): + def __init__( + self, + vocab_size: int, + padding_idx: int, + initial_dim: int, + factor: float, + output_dim: int, + cutoff: List[int], + q_noise: float = 0, + qn_block_size: int = 8, + ): + super().__init__() + + if vocab_size > cutoff[-1]: + cutoff = cutoff + [vocab_size] + else: + assert ( + vocab_size == cutoff[-1] + ), "cannot specify cutoff larger than vocab size" + + self.cutoff = cutoff + self.embedding_dim = output_dim + self.padding_idx = padding_idx + + self.embeddings = nn.ModuleList() + for i in range(len(self.cutoff)): + prev = self.cutoff[i - 1] if i > 0 else 0 + size = self.cutoff[i] - prev + dim = int(initial_dim // (factor ** i)) + seq = nn.Sequential( + nn.Embedding(size, dim, self.padding_idx), + quant_noise( + nn.Linear(dim, output_dim, bias=False), q_noise, qn_block_size + ), + ) + + self.embeddings.append(seq) + self.padding_idx = None + self.padding_idx = padding_idx + + def init_weights(m): + if isinstance(m, nn.Embedding): + nn.init.normal_(m.weight, mean=0, std=m.weight.shape[1] ** -0.5) + nn.init.constant_(m.weight[padding_idx], 0) + elif hasattr(m, "weight"): + nn.init.xavier_uniform_(m.weight) + + self.apply(init_weights) + + self.register_buffer("_float_tensor", torch.FloatTensor(1)) + + def weights_for_band(self, band: int): + return self.embeddings[band][0].weight, self.embeddings[band][1].weight + + def forward(self, input: torch.Tensor): + result = self._float_tensor.new(input.shape + (self.embedding_dim,)) + for i in range(len(self.cutoff)): + mask = input.lt(self.cutoff[i]) + if i > 0: + mask.mul_(input.ge(self.cutoff[i - 1])) + chunk_input = input[mask] - self.cutoff[i - 1] + else: + chunk_input = input[mask] + if mask.any(): + result[mask] = self.embeddings[i](chunk_input) + return result diff --git a/fairseq-tools/fairseq/fairseq/modules/adaptive_softmax.py b/fairseq-tools/fairseq/fairseq/modules/adaptive_softmax.py new file mode 100644 index 00000000..ae0c77ba --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/adaptive_softmax.py @@ -0,0 +1,268 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import functools +import operator + +import torch +import torch.nn.functional as F +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.quant_noise import quant_noise +from torch import nn + + +class TiedLinear(nn.Module): + def __init__(self, weight, transpose): + super().__init__() + self.weight = weight + self.transpose = transpose + + def forward(self, input): + return F.linear(input, self.weight.t() if self.transpose else self.weight) + + +class TiedHeadModule(nn.Module): + def __init__(self, weights, input_dim, num_classes, q_noise, qn_block_size): + super().__init__() + tied_emb, _ = weights + self.num_words, emb_dim = tied_emb.size() + + self.word_proj = quant_noise( + TiedLinear(tied_emb, transpose=False), q_noise, qn_block_size + ) + if input_dim != emb_dim: + self.word_proj = nn.Sequential( + quant_noise( + nn.Linear(input_dim, emb_dim, bias=False), q_noise, qn_block_size + ), + self.word_proj, + ) + + self.class_proj = quant_noise( + nn.Linear(input_dim, num_classes, bias=False), q_noise, qn_block_size + ) + self.out_dim = self.num_words + num_classes + + self.register_buffer("_float_tensor", torch.FloatTensor(1)) + + def forward(self, input): + inp_sz = functools.reduce(operator.mul, input.shape[:-1], 1) + out = self._float_tensor.new(inp_sz, self.out_dim) + out[:, : self.num_words] = self.word_proj(input.view(inp_sz, -1)) + out[:, self.num_words :] = self.class_proj(input.view(inp_sz, -1)) + return out + + +class AdaptiveSoftmax(nn.Module): + """ + This is an implementation of the efficient softmax approximation for + graphical processing units (GPU), described in the paper "Efficient softmax + approximation for GPUs" (http://arxiv.org/abs/1609.04309). + """ + + def __init__( + self, + vocab_size, + input_dim, + cutoff, + dropout, + factor=4.0, + adaptive_inputs=None, + tie_proj=False, + q_noise=0, + qn_block_size=8, + ): + super().__init__() + + if vocab_size > cutoff[-1]: + cutoff = cutoff + [vocab_size] + else: + assert ( + vocab_size == cutoff[-1] + ), "cannot specify cutoff larger than vocab size" + + output_dim = cutoff[0] + len(cutoff) - 1 + + self.vocab_size = vocab_size + self.cutoff = cutoff + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.input_dim = input_dim + self.factor = factor + self.q_noise = q_noise + self.qn_block_size = qn_block_size + + self.lsm = nn.LogSoftmax(dim=1) + + if adaptive_inputs is not None: + self.head = TiedHeadModule( + adaptive_inputs.weights_for_band(0), + input_dim, + len(cutoff) - 1, + self.q_noise, + self.qn_block_size, + ) + else: + self.head = quant_noise( + nn.Linear(input_dim, output_dim, bias=False), + self.q_noise, + self.qn_block_size, + ) + + self._make_tail(adaptive_inputs, tie_proj) + + def init_weights(m): + if ( + hasattr(m, "weight") + and not isinstance(m, TiedLinear) + and not isinstance(m, TiedHeadModule) + ): + nn.init.xavier_uniform_(m.weight) + + self.apply(init_weights) + + self.register_buffer("version", torch.LongTensor([1])) + + def _make_tail(self, adaptive_inputs=None, tie_proj=False): + self.tail = nn.ModuleList() + for i in range(len(self.cutoff) - 1): + dim = int(self.input_dim // self.factor ** (i + 1)) + + tied_emb, tied_proj = ( + adaptive_inputs.weights_for_band(i + 1) + if adaptive_inputs is not None + else (None, None) + ) + + if tied_proj is not None: + if tie_proj: + proj = quant_noise( + TiedLinear(tied_proj, transpose=True), + self.q_noise, + self.qn_block_size, + ) + else: + proj = quant_noise( + nn.Linear(tied_proj.size(0), tied_proj.size(1), bias=False), + self.q_noise, + self.qn_block_size, + ) + else: + proj = quant_noise( + nn.Linear(self.input_dim, dim, bias=False), + self.q_noise, + self.qn_block_size, + ) + + if tied_emb is None: + out_proj = nn.Linear( + dim, self.cutoff[i + 1] - self.cutoff[i], bias=False + ) + else: + out_proj = TiedLinear(tied_emb, transpose=False) + + m = nn.Sequential( + proj, + nn.Dropout(self.dropout_module.p), + quant_noise(out_proj, self.q_noise, self.qn_block_size), + ) + + self.tail.append(m) + + def upgrade_state_dict_named(self, state_dict, name): + version_name = name + ".version" + if version_name not in state_dict: + raise Exception("This version of the model is no longer supported") + + def adapt_target(self, target): + """ + In order to be efficient, the AdaptiveSoftMax does not compute the + scores for all the word of the vocabulary for all the examples. It is + thus necessary to call the method adapt_target of the AdaptiveSoftMax + layer inside each forward pass. + """ + + target = target.view(-1) + new_target = [target.clone()] + target_idxs = [] + + for i in range(len(self.cutoff) - 1): + mask = target.ge(self.cutoff[i]).mul(target.lt(self.cutoff[i + 1])) + new_target[0][mask] = self.cutoff[0] + i + + if mask.any(): + target_idxs.append(mask.nonzero(as_tuple=False).squeeze(1)) + new_target.append(target[mask].add(-self.cutoff[i])) + else: + target_idxs.append(None) + new_target.append(None) + + return new_target, target_idxs + + def forward(self, input, target): + """ + Args: + input: (b x t x d) + target: (b x t) + Returns: + 2 lists: output for each cutoff section and new targets by cut off + """ + + input = input.contiguous().view(-1, input.size(-1)) + input = self.dropout_module(input) + + new_target, target_idxs = self.adapt_target(target) + output = [self.head(input)] + + for i in range(len(target_idxs)): + if target_idxs[i] is not None: + output.append(self.tail[i](input.index_select(0, target_idxs[i]))) + else: + output.append(None) + + return output, new_target + + def get_log_prob(self, input, target): + """ + Computes the log probabilities for all the words of the vocabulary, + given a 2D tensor of hidden vectors. + """ + + bsz, length, dim = input.size() + input = input.contiguous().view(-1, dim) + + if target is not None: + _, target_idxs = self.adapt_target(target) + else: + target_idxs = None + + head_y = self.head(input) + log_probs = head_y.new_zeros(input.size(0), self.vocab_size) + + head_sz = self.cutoff[0] + len(self.tail) + log_probs[:, :head_sz] = self.lsm(head_y) + tail_priors = log_probs[:, self.cutoff[0] : head_sz].clone() + + for i in range(len(self.tail)): + start = self.cutoff[i] + end = self.cutoff[i + 1] + + if target_idxs is None: + tail_out = log_probs[:, start:end] + tail_out.copy_(self.tail[i](input)) + log_probs[:, start:end] = self.lsm(tail_out).add_( + tail_priors[:, i, None] + ) + elif target_idxs[i] is not None: + idxs = target_idxs[i] + tail_out = log_probs[idxs, start:end] + tail_out.copy_(self.tail[i](input[idxs])) + log_probs[idxs, start:end] = self.lsm(tail_out).add_( + tail_priors[idxs, i, None] + ) + + log_probs = log_probs.view(bsz, length, -1) + return log_probs diff --git a/fairseq-tools/fairseq/fairseq/modules/beamable_mm.py b/fairseq-tools/fairseq/fairseq/modules/beamable_mm.py new file mode 100644 index 00000000..eff1a460 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/beamable_mm.py @@ -0,0 +1,49 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn + + +class BeamableMM(nn.Module): + """This module provides an optimized MM for beam decoding with attention. + + It leverage the fact that the source-side of the input is replicated beam + times and the target-side of the input is of width one. This layer speeds up + inference by replacing the inputs {(bsz x 1 x nhu), (bsz x sz2 x nhu)} + with smaller inputs {(bsz/beam x beam x nhu), (bsz/beam x sz2 x nhu)}. + """ + + def __init__(self, beam_size=None): + super(BeamableMM, self).__init__() + self.beam_size = beam_size + + def forward(self, input1, input2): + if ( + not self.training + and self.beam_size is not None # test mode + and input1.dim() == 3 # beam size is set + and input1.size(1) # only support batched input + == 1 # single time step update + ): + bsz, beam = input1.size(0), self.beam_size + + # bsz x 1 x nhu --> bsz/beam x beam x nhu + input1 = input1[:, 0, :].unfold(0, beam, beam).transpose(2, 1) + + # bsz x sz2 x nhu --> bsz/beam x sz2 x nhu + input2 = input2.unfold(0, beam, beam)[:, :, :, 0] + + # use non batched operation if bsz = beam + if input1.size(0) == 1: + output = torch.mm(input1[0, :, :], input2[0, :, :]) + else: + output = input1.bmm(input2) + return output.view(bsz, 1, -1) + else: + return input1.bmm(input2) + + def set_beam_size(self, beam_size): + self.beam_size = beam_size diff --git a/fairseq-tools/fairseq/fairseq/modules/character_token_embedder.py b/fairseq-tools/fairseq/fairseq/modules/character_token_embedder.py new file mode 100644 index 00000000..181221b6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/character_token_embedder.py @@ -0,0 +1,214 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from typing import List, Tuple + +import torch +import torch.nn.functional as F +from fairseq.data import Dictionary +from torch import nn + + +CHAR_PAD_IDX = 0 +CHAR_EOS_IDX = 257 + + +logger = logging.getLogger(__name__) + + +class CharacterTokenEmbedder(torch.nn.Module): + def __init__( + self, + vocab: Dictionary, + filters: List[Tuple[int, int]], + char_embed_dim: int, + word_embed_dim: int, + highway_layers: int, + max_char_len: int = 50, + char_inputs: bool = False, + ): + super(CharacterTokenEmbedder, self).__init__() + + self.onnx_trace = False + self.embedding_dim = word_embed_dim + self.max_char_len = max_char_len + self.char_embeddings = nn.Embedding(257, char_embed_dim, padding_idx=0) + self.symbol_embeddings = nn.Parameter(torch.FloatTensor(2, word_embed_dim)) + self.eos_idx, self.unk_idx = 0, 1 + self.char_inputs = char_inputs + + self.convolutions = nn.ModuleList() + for width, out_c in filters: + self.convolutions.append( + nn.Conv1d(char_embed_dim, out_c, kernel_size=width) + ) + + last_dim = sum(f[1] for f in filters) + + self.highway = Highway(last_dim, highway_layers) if highway_layers > 0 else None + + self.projection = nn.Linear(last_dim, word_embed_dim) + + assert ( + vocab is not None or char_inputs + ), "vocab must be set if not using char inputs" + self.vocab = None + if vocab is not None: + self.set_vocab(vocab, max_char_len) + + self.reset_parameters() + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def set_vocab(self, vocab, max_char_len): + word_to_char = torch.LongTensor(len(vocab), max_char_len) + + truncated = 0 + for i in range(len(vocab)): + if i < vocab.nspecial: + char_idxs = [0] * max_char_len + else: + chars = vocab[i].encode() + # +1 for padding + char_idxs = [c + 1 for c in chars] + [0] * (max_char_len - len(chars)) + if len(char_idxs) > max_char_len: + truncated += 1 + char_idxs = char_idxs[:max_char_len] + word_to_char[i] = torch.LongTensor(char_idxs) + + if truncated > 0: + logger.info( + "truncated {} words longer than {} characters".format( + truncated, max_char_len + ) + ) + + self.vocab = vocab + self.word_to_char = word_to_char + + @property + def padding_idx(self): + return Dictionary().pad() if self.vocab is None else self.vocab.pad() + + def reset_parameters(self): + nn.init.xavier_normal_(self.char_embeddings.weight) + nn.init.xavier_normal_(self.symbol_embeddings) + nn.init.xavier_uniform_(self.projection.weight) + + nn.init.constant_( + self.char_embeddings.weight[self.char_embeddings.padding_idx], 0.0 + ) + nn.init.constant_(self.projection.bias, 0.0) + + def forward( + self, + input: torch.Tensor, + ): + if self.char_inputs: + chars = input.view(-1, self.max_char_len) + pads = chars[:, 0].eq(CHAR_PAD_IDX) + eos = chars[:, 0].eq(CHAR_EOS_IDX) + if eos.any(): + if self.onnx_trace: + chars = torch.where(eos.unsqueeze(1), chars.new_zeros(1), chars) + else: + chars[eos] = 0 + + unk = None + else: + flat_words = input.view(-1) + chars = self.word_to_char[flat_words.type_as(self.word_to_char)].type_as( + input + ) + pads = flat_words.eq(self.vocab.pad()) + eos = flat_words.eq(self.vocab.eos()) + unk = flat_words.eq(self.vocab.unk()) + + word_embs = self._convolve(chars) + if self.onnx_trace: + if pads.any(): + word_embs = torch.where( + pads.unsqueeze(1), word_embs.new_zeros(1), word_embs + ) + if eos.any(): + word_embs = torch.where( + eos.unsqueeze(1), self.symbol_embeddings[self.eos_idx], word_embs + ) + if unk is not None and unk.any(): + word_embs = torch.where( + unk.unsqueeze(1), self.symbol_embeddings[self.unk_idx], word_embs + ) + else: + if pads.any(): + word_embs[pads] = 0 + if eos.any(): + word_embs[eos] = self.symbol_embeddings[self.eos_idx] + if unk is not None and unk.any(): + word_embs[unk] = self.symbol_embeddings[self.unk_idx] + + return word_embs.view(input.size()[:2] + (-1,)) + + def _convolve( + self, + char_idxs: torch.Tensor, + ): + char_embs = self.char_embeddings(char_idxs) + char_embs = char_embs.transpose(1, 2) # BTC -> BCT + + conv_result = [] + + for conv in self.convolutions: + x = conv(char_embs) + x, _ = torch.max(x, -1) + x = F.relu(x) + conv_result.append(x) + + x = torch.cat(conv_result, dim=-1) + + if self.highway is not None: + x = self.highway(x) + x = self.projection(x) + + return x + + +class Highway(torch.nn.Module): + """ + A `Highway layer <https://arxiv.org/abs/1505.00387>`_. + Adopted from the AllenNLP implementation. + """ + + def __init__(self, input_dim: int, num_layers: int = 1): + super(Highway, self).__init__() + self.input_dim = input_dim + self.layers = nn.ModuleList( + [nn.Linear(input_dim, input_dim * 2) for _ in range(num_layers)] + ) + self.activation = nn.ReLU() + + self.reset_parameters() + + def reset_parameters(self): + for layer in self.layers: + # As per comment in AllenNLP: + # We should bias the highway layer to just carry its input forward. We do that by + # setting the bias on `B(x)` to be positive, because that means `g` will be biased to + # be high, so we will carry the input forward. The bias on `B(x)` is the second half + # of the bias vector in each Linear layer. + nn.init.constant_(layer.bias[self.input_dim :], 1) + + nn.init.constant_(layer.bias[: self.input_dim], 0) + nn.init.xavier_normal_(layer.weight) + + def forward(self, x: torch.Tensor): + for layer in self.layers: + projection = layer(x) + proj_x, gate = projection.chunk(2, dim=-1) + proj_x = self.activation(proj_x) + gate = torch.sigmoid(gate) + x = gate * x + (gate.new_tensor([1]) - gate) * proj_x + return x diff --git a/fairseq-tools/fairseq/fairseq/modules/conv_tbc.py b/fairseq-tools/fairseq/fairseq/modules/conv_tbc.py new file mode 100644 index 00000000..2dc46c4b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/conv_tbc.py @@ -0,0 +1,42 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from torch.nn.modules.utils import _single + + +class ConvTBC(torch.nn.Module): + """1D convolution over an input of shape (time x batch x channel) + + The implementation uses gemm to perform the convolution. This implementation + is faster than cuDNN for small kernel sizes. + """ + + def __init__(self, in_channels, out_channels, kernel_size, padding=0): + super(ConvTBC, self).__init__() + self.in_channels = in_channels + self.out_channels = out_channels + self.kernel_size = _single(kernel_size) + self.padding = _single(padding) + + self.weight = torch.nn.Parameter( + torch.Tensor(self.kernel_size[0], in_channels, out_channels) + ) + self.bias = torch.nn.Parameter(torch.Tensor(out_channels)) + + def forward(self, input): + return torch.conv_tbc( + input.contiguous(), self.weight, self.bias, self.padding[0] + ) + + def __repr__(self): + s = ( + "{name}({in_channels}, {out_channels}, kernel_size={kernel_size}" + ", padding={padding}" + ) + if self.bias is None: + s += ", bias=False" + s += ")" + return s.format(name=self.__class__.__name__, **self.__dict__) diff --git a/fairseq-tools/fairseq/fairseq/modules/cross_entropy.py b/fairseq-tools/fairseq/fairseq/modules/cross_entropy.py new file mode 100644 index 00000000..0d2beb44 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/cross_entropy.py @@ -0,0 +1,59 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import torch +import torch.nn.functional as F + + +logger = logging.getLogger(__name__) + + +def _cross_entropy_pytorch(logits, target, ignore_index=None, reduction="mean"): + lprobs = F.log_softmax(logits, dim=-1, dtype=torch.float32) + return F.nll_loss( + lprobs, + target, + ignore_index=ignore_index, + reduction=reduction, + ) + + +try: + import xentropy_cuda + from apex.contrib import xentropy + + logger.info("using fused cross entropy") + + def cross_entropy(logits, target, ignore_index=-100, reduction="mean"): + if logits.device == torch.device("cpu"): + return _cross_entropy_pytorch(logits, target, ignore_index, reduction) + else: + half_to_float = logits.dtype == torch.half + losses = xentropy.SoftmaxCrossEntropyLoss.apply( + logits, + target, + 0.0, + ignore_index, + half_to_float, + ) + if reduction == "sum": + return losses.sum() + elif reduction == "mean": + if ignore_index >= 0: + return losses.sum() / target.ne(ignore_index).sum() + else: + return losses.mean() + elif reduction == "none": + return losses + else: + raise NotImplementedError + + +except ImportError: + + def cross_entropy(logits, target, ignore_index=-100, reduction="mean"): + return _cross_entropy_pytorch(logits, target, ignore_index, reduction) diff --git a/fairseq-tools/fairseq/fairseq/modules/cuda_utils.cu b/fairseq-tools/fairseq/fairseq/modules/cuda_utils.cu new file mode 100644 index 00000000..516f1d92 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/cuda_utils.cu @@ -0,0 +1,203 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + +template <typename U, typename V> +constexpr __host__ __device__ auto divUp(U a, V b) -> decltype(a + b) { + return (a + b - 1) / b; +} + + +template<int FS, int SB, int padding_l, typename scalar_t> +__inline__ __device__ +void zeroSharedMem(scalar_t* data) { + /* + Given an array of length FS + SB, zero out the first padding_l and last + (FS - padding_l) values in the array + */ + + int tid = threadIdx.x; + + if (FS < SB) { + + // zero all if we have enough threads in a block to do all of them + if (tid < padding_l || tid > SB - FS + padding_l - 1) { + data[tid] = scalar_t(0.0); + } + } else { + + // otherwise zero out one block at a time + const int numIterations = divUp<int, int>(FS, SB); + for (int i = 0; i < numIterations; i++) { + int offset = i * SB; + if (tid + offset < padding_l) { + data[tid + offset] = scalar_t(0.0); + } else if (tid + offset < FS) { + data[SB + tid + offset] = scalar_t(0.0); + } + } + } +} + +template<typename scalar_t> +__inline__ __device__ +scalar_t warpReduce(scalar_t data) { + /* + Reduce an array within each warp. After processing all values in warp will + caontain the sum of all original values in that warp. + + data - pointer to data to reduce + */ + data += __shfl_xor_sync(SHFL_MASK, data, 16); + data += __shfl_xor_sync(SHFL_MASK, data, 8); + data += __shfl_xor_sync(SHFL_MASK, data, 4); + data += __shfl_xor_sync(SHFL_MASK, data, 2); + data += __shfl_xor_sync(SHFL_MASK, data, 1); + return data; +} + +template<typename scalar_t> +__inline__ __device__ +scalar_t blockReduce(scalar_t data) { + /* + Reduce an entire array on the block level. After processing, the + first value in the array will contain the reduced sum. + + data - pointer to data to reduce + */ + + static __shared__ scalar_t warpSum[32]; + const int tid = threadIdx.x; + int wid = tid / 32; + int lane = tid % 32; + + __syncthreads(); + + // reduce each warp then write to shared memory + scalar_t sum = warpReduce(data); + if (lane == 0) { + warpSum[wid] = sum; + } + + __syncthreads(); + + scalar_t v; + // perform final sum of partial warp sums + if (tid < blockDim.x / 32) { + v = warpSum[lane]; + } else { + v = scalar_t(0.0); + } + + if (wid == 0) { + v = warpReduce(v); + } + __syncthreads(); + + return v; +} + +void checkCudaStatus(cudaError_t status, int lineNumber = -1) { + + if (status != cudaSuccess) { + std::cout << cudaGetErrorString(status) + << " at line " << lineNumber << std::endl; + std::cout << "Exiting" << std::endl; + exit(1); + } +} + +template<int FS, int SB, int padding_l, typename scalar_t> +__device__ +void load_input_to_shared(const scalar_t* input, // global memory + int inputOffset, int sequenceLength, + int iteration, int numIterations, + bool no_prev, scalar_t* output /* shared memory */) { + /* + Load a block size of input into shared memory with + right and left overhang of total size FS. If previously + loaded memory, overlap will be shifted over to reduce + global memory access + + input - pointer to start of channel sequence + inputOffset - how far in the sequence to start loading + sequenceLength - total length of sequence + iteration - which block of sequence we are loading + numIterations - total number of blocks to load + no_prev - whether to load the whole block if the previous block + wasn't loaded + output - shared memory to write input to + */ + + const int tid = threadIdx.x; + + // Load the left "overhang" of input + if (iteration > 0) { + if (padding_l < SB) { + + // load all at once + if (tid < padding_l) { + output[tid] = (no_prev) ? input[inputOffset - padding_l + tid] : output[tid + SB]; + } + } else { + + // load in chunks of size SB + int numIterations = divUp<int, int>(padding_l, SB); + for (int i = 0; i < numIterations; i++) { + int offset = i * SB; + if ((tid + offset) < padding_l) { + output[tid + offset] = (no_prev) ? input[inputOffset - padding_l + tid + offset] : output[tid + offset + SB]; + } + } + } + } + + // Load the right "overhang" of input + if (iteration < (numIterations - 1)) { + const int elementsLeft = sequenceLength - (iteration+1) * SB; + + if ((FS - padding_l) < SB) { + + // load all at once + if (tid < (FS - padding_l)) { + output[padding_l + SB + tid] = (tid < elementsLeft) ? input[inputOffset + SB + tid] : scalar_t(0.0); + } + } else { + + // load in chunks of size SB + int numIterations = divUp<int, int>(FS - padding_l, SB); + for (int i = 0; i < numIterations; i++) { + int offset = i * SB; + if ((tid + offset) < (FS - padding_l)) { + output[padding_l + SB + tid + offset] = ((tid + offset) < elementsLeft) ? input[inputOffset + SB + tid + offset] : scalar_t(0.0); + } + } + } + } + + // We should also clear out the right "overhang" + if (iteration == (numIterations - 1)) { + if ((FS - padding_l) < SB) { + + // clear out all at once + if (tid < (FS - padding_l)) { + output[padding_l + SB + tid] = scalar_t(0.0); + } + } else { + + // clear in chunks of size SB + int numIterations = divUp<int, int>(FS - padding_l, SB); + for (int i = 0; i < numIterations; i++) { + int offset = i * SB; + if ((tid + offset) < (FS - padding_l)) { + output[padding_l + SB + tid + offset] = scalar_t(0.0); + } + } + } + } + output[tid + padding_l] = ((inputOffset + tid) < sequenceLength) ? input[inputOffset + tid] : scalar_t(0.0); +} diff --git a/fairseq-tools/fairseq/fairseq/modules/downsampled_multihead_attention.py b/fairseq-tools/fairseq/fairseq/modules/downsampled_multihead_attention.py new file mode 100644 index 00000000..2cdece3f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/downsampled_multihead_attention.py @@ -0,0 +1,316 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# + +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.scalar_bias import scalar_bias + + +class SingleHeadAttention(nn.Module): + """ + Single-head attention that supports Gating and Downsampling + """ + + def __init__( + self, + out_channels, + embed_dim, + head_dim, + head_index, + dropout=0.0, + bias=True, + project_input=True, + gated=False, + downsample=False, + num_heads=1, + ): + super().__init__() + self.embed_dim = embed_dim + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.head_index = head_index + self.head_dim = head_dim + self.project_input = project_input + self.gated = gated + self.downsample = downsample + self.num_heads = num_heads + self.projection = None + + k_layers = [] + v_layers = [] + if self.downsample: + k_layers.append(Downsample(self.head_index)) + v_layers.append(Downsample(self.head_index)) + out_proj_size = self.head_dim + else: + out_proj_size = self.head_dim * self.num_heads + if self.gated: + k_layers.append(GatedLinear(self.embed_dim, out_proj_size, bias=bias)) + self.in_proj_q = GatedLinear(self.embed_dim, out_proj_size, bias=bias) + v_layers.append(GatedLinear(self.embed_dim, out_proj_size, bias=bias)) + else: + k_layers.append(Linear(self.embed_dim, out_proj_size, bias=bias)) + self.in_proj_q = Linear(self.embed_dim, out_proj_size, bias=bias) + v_layers.append(Linear(self.embed_dim, out_proj_size, bias=bias)) + + self.in_proj_k = nn.Sequential(*k_layers) + self.in_proj_v = nn.Sequential(*v_layers) + + if self.downsample: + self.out_proj = Linear(out_proj_size, self.head_dim, bias=bias) + else: + self.out_proj = Linear(out_proj_size, out_channels, bias=bias) + + self.scaling = self.head_dim ** -0.5 + + def forward( + self, + query, + key, + value, + mask_future_timesteps=False, + key_padding_mask=None, + use_scalar_bias=False, + ): + """Input shape: Time x Batch x Channel + Self-attention can be implemented by passing in the same arguments for + query, key and value. Future timesteps can be masked with the + `mask_future_timesteps` argument. Padding elements can be excluded from + the key by passing a binary ByteTensor (`key_padding_mask`) with shape: + batch x src_len, where padding elements are indicated by 1s. + """ + src_len, bsz, out_channels = key.size() + tgt_len = query.size(0) + assert list(query.size()) == [tgt_len, bsz, out_channels] + assert key.size() == value.size() + + if key_padding_mask is not None: + assert key_padding_mask.size(0) == bsz + assert key_padding_mask.size(1) == src_len + + if self.downsample: + size = bsz + else: + size = bsz * self.num_heads + + k = key + v = value + q = query + if self.project_input: + q = self.in_proj_q(q) + k = self.in_proj_k(k) + v = self.in_proj_v(v) + src_len = k.size()[0] + q *= self.scaling + + if not self.downsample: + q = q.view(tgt_len, size, self.head_dim) + k = k.view(src_len, size, self.head_dim) + v = v.view(src_len, size, self.head_dim) + + q = q.transpose(0, 1) + k = k.transpose(0, 1) + v = v.transpose(0, 1) + + attn_weights = torch.bmm(q, k.transpose(1, 2)) + if mask_future_timesteps: + assert ( + query.size() == key.size() + ), "mask_future_timesteps only applies to self-attention" + attn_weights *= torch.tril( + attn_weights.data.new([1]).expand(tgt_len, tgt_len).clone(), + diagonal=-1, + )[:, :: self.head_index + 1 if self.downsample else 1].unsqueeze(0) + attn_weights += torch.triu( + attn_weights.data.new([-math.inf]).expand(tgt_len, tgt_len).clone(), + diagonal=0, + )[:, :: self.head_index + 1 if self.downsample else 1].unsqueeze(0) + tgt_size = tgt_len + if use_scalar_bias: + attn_weights = scalar_bias(attn_weights, 2) + v = scalar_bias(v, 1) + tgt_size += 1 + + if key_padding_mask is not None: + # don't attend to padding symbols + if key_padding_mask.max() > 0: + if self.downsample: + attn_weights = attn_weights.view(bsz, 1, tgt_len, src_len) + else: + attn_weights = attn_weights.view( + size, self.num_heads, tgt_len, src_len + ) + attn_weights = attn_weights.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2), + -math.inf, + ) + attn_weights = attn_weights.view(size, tgt_len, src_len) + attn_weights = F.softmax(attn_weights, dim=-1) + attn_weights = self.dropout_module(attn_weights) + + attn = torch.bmm(attn_weights, v) + if self.downsample: + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, self.head_dim) + else: + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, self.embed_dim) + + attn = self.out_proj(attn) + + return attn, attn_weights + + +class DownsampledMultiHeadAttention(nn.ModuleList): + """ + Multi-headed attention with Gating and Downsampling + """ + + def __init__( + self, + out_channels, + embed_dim, + num_heads, + dropout=0.0, + bias=True, + project_input=True, + gated=False, + downsample=False, + ): + self.embed_dim = embed_dim + self.num_heads = num_heads + self.head_dim = embed_dim // num_heads + self.downsample = downsample + self.gated = gated + self.project_input = project_input + assert self.head_dim * num_heads == embed_dim + + if self.downsample: + attention_heads = [] + for index in range(self.num_heads): + attention_heads.append( + SingleHeadAttention( + out_channels, + self.embed_dim, + self.head_dim, + index, + dropout, + bias, + self.project_input, + self.gated, + self.downsample, + self.num_heads, + ) + ) + super().__init__(modules=attention_heads) + self.out_proj = Linear(embed_dim, out_channels, bias=bias) + else: + # either we have a list of attention heads, or just one attention head + # if not being downsampled, we can do the heads with one linear layer instead of separate ones + super().__init__() + self.attention_module = SingleHeadAttention( + out_channels, + self.embed_dim, + self.head_dim, + 1, + dropout, + bias, + self.project_input, + self.gated, + self.downsample, + self.num_heads, + ) + + def forward( + self, + query, + key, + value, + mask_future_timesteps=False, + key_padding_mask=None, + use_scalar_bias=False, + ): + src_len, bsz, embed_dim = key.size() + tgt_len = query.size(0) + assert embed_dim == self.embed_dim + assert list(query.size()) == [tgt_len, bsz, embed_dim] + assert key.size() == value.size() + + tgt_size = tgt_len + if use_scalar_bias: + tgt_size += 1 + + attn = [] + attn_weights = [] + if self.downsample: + for attention_head_number in range(self.num_heads): + # call the forward of each attention head + _attn, _attn_weight = self[attention_head_number]( + query, + key, + value, + mask_future_timesteps, + key_padding_mask, + use_scalar_bias, + ) + attn.append(_attn) + attn_weights.append(_attn_weight) + full_attn = torch.cat(attn, dim=2) + full_attn = self.out_proj(full_attn) + return full_attn, attn_weights[0].clone() + else: + _attn, _attn_weight = self.attention_module( + query, + key, + value, + mask_future_timesteps, + key_padding_mask, + use_scalar_bias, + ) + attn.append(_attn) + attn_weights.append(_attn_weight) + full_attn = torch.cat(attn, dim=2) + full_attn_weights = torch.cat(attn_weights) + full_attn_weights = full_attn_weights.view( + bsz, self.num_heads, tgt_size, src_len + ) + full_attn_weights = full_attn_weights.sum(dim=1) / self.num_heads + return full_attn, full_attn_weights + + +class Downsample(nn.Module): + """ + Selects every nth element, where n is the index + """ + + def __init__(self, index): + super().__init__() + self.index = index + + def forward(self, x): + return x[:: self.index + 1] + + +def Linear(in_features, out_features, dropout=0.0, bias=True): + """Weight-normalized Linear layer (input: B x T x C)""" + m = nn.Linear(in_features, out_features, bias=bias) + m.weight.data.normal_(mean=0, std=math.sqrt((1 - dropout) / in_features)) + m.bias.data.zero_() + return nn.utils.weight_norm(m) + + +def GatedLinear(in_features, out_features, dropout=0.0, bias=True): + """Weight-normalized Linear layer (input: B x T x C) with interspersed GLU units""" + return nn.Sequential( + Linear(in_features, out_features * 4, dropout, bias), + nn.GLU(), + Linear(out_features * 2, out_features * 2, dropout, bias), + nn.GLU(), + Linear(out_features, out_features, dropout, bias), + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamic_convolution.py b/fairseq-tools/fairseq/fairseq/modules/dynamic_convolution.py new file mode 100644 index 00000000..5999a045 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamic_convolution.py @@ -0,0 +1,304 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout + +from .unfold import unfold1d + + +def DynamicConv( + input_size, + kernel_size=1, + padding_l=None, + num_heads=1, + weight_dropout=0.0, + weight_softmax=False, + renorm_padding=False, + bias=False, + conv_bias=False, + query_size=None, + in_proj=False, +): + if torch.cuda.is_available(): + try: + from fairseq.modules.dynamicconv_layer import DynamicconvLayer + + return DynamicconvLayer( + input_size, + kernel_size=kernel_size, + padding_l=padding_l, + num_heads=num_heads, + weight_dropout=weight_dropout, + weight_softmax=weight_softmax, + bias=bias, + ) + except ImportError as e: + print(e) + return DynamicConv1dTBC( + input_size, + kernel_size=kernel_size, + padding_l=padding_l, + num_heads=num_heads, + weight_dropout=weight_dropout, + weight_softmax=weight_softmax, + bias=bias, + ) + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m + + +@with_incremental_state +class DynamicConv1dTBC(nn.Module): + """Dynamic lightweight convolution taking T x B x C inputs + Args: + input_size: # of channels of the input + kernel_size: convolution channels + padding_l: padding to the left when using "same" padding + num_heads: number of heads used. The weight is of shape (num_heads, 1, kernel_size) + weight_dropout: the drop rate of the DropConnect to drop the weight + weight_softmax: normalize the weight with softmax before the convolution + renorm_padding: re-normalize the filters to ignore the padded part (only the non-padding parts sum up to 1) + bias: use bias + conv_bias: bias of the convolution + query_size: specified when feeding a different input as the query + in_proj: project the input and generate the filter together + + Shape: + Input: TxBxC, i.e. (timesteps, batch_size, input_size) + Output: TxBxC, i.e. (timesteps, batch_size, input_size) + + Attributes: + weight: the learnable weights of the module of shape + `(num_heads, 1, kernel_size)` + bias: the learnable bias of the module of shape `(input_size)` + """ + + def __init__( + self, + input_size, + kernel_size=1, + padding_l=None, + num_heads=1, + weight_dropout=0.0, + weight_softmax=False, + renorm_padding=False, + bias=False, + conv_bias=False, + query_size=None, + in_proj=False, + ): + super().__init__() + self.input_size = input_size + self.query_size = input_size if query_size is None else query_size + self.kernel_size = kernel_size + self.padding_l = padding_l + self.num_heads = num_heads + self.weight_dropout_module = FairseqDropout( + weight_dropout, module_name=self.__class__.__name__ + ) + self.weight_softmax = weight_softmax + self.renorm_padding = renorm_padding + + if in_proj: + self.weight_linear = Linear( + self.input_size, self.input_size + num_heads * kernel_size * 1 + ) + else: + self.weight_linear = Linear( + self.query_size, num_heads * kernel_size * 1, bias=bias + ) + if conv_bias: + self.conv_bias = nn.Parameter(torch.Tensor(input_size)) + else: + self.conv_bias = None + self.reset_parameters() + + @property + def in_proj(self): + return ( + self.weight_linear.out_features + == self.input_size + self.num_heads * self.kernel_size + ) + + def reset_parameters(self): + self.weight_linear.reset_parameters() + if self.conv_bias is not None: + nn.init.constant_(self.conv_bias, 0.0) + + def forward(self, x, incremental_state=None, query=None, unfold=None): + """Assuming the input, x, of the shape T x B x C and producing an output in the shape T x B x C + args: + x: Input of shape T x B x C, i.e. (timesteps, batch_size, input_size) + incremental_state: A dict to keep the state + unfold: unfold the input or not. If not, we use the matrix trick instead + query: use the specified query to predict the conv filters + """ + unfold = ( + x.size(0) > 512 if unfold is None else unfold + ) # use unfold mode as default for long sequence to save memory + unfold = unfold or (incremental_state is not None) + assert query is None or not self.in_proj + + if query is None: + query = x + if unfold: + output = self._forward_unfolded(x, incremental_state, query) + else: + output = self._forward_expanded(x, incremental_state, query) + + if self.conv_bias is not None: + output = output + self.conv_bias.view(1, 1, -1) + return output + + def _forward_unfolded(self, x, incremental_state, query): + """The conventional implementation of convolutions. + Unfolding the input by having a window shifting to the right.""" + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + + if self.in_proj: + proj = self.weight_linear(x) + x = proj.narrow(2, 0, self.input_size).contiguous() + weight = ( + proj.narrow(2, self.input_size, H * K).contiguous().view(T * B * H, -1) + ) + else: + weight = self.weight_linear(query).view(T * B * H, -1) + + # renorm_padding is only implemented in _forward_expanded + assert not self.renorm_padding or incremental_state is not None + + if incremental_state is not None: + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is None: + input_buffer = x.new() + x_unfold = torch.cat([input_buffer, x.unsqueeze(3)], dim=3) + if self.kernel_size > 1: + self._set_input_buffer( + incremental_state, x_unfold[:, :, :, -self.kernel_size + 1 :] + ) + x_unfold = x_unfold.view(T * B * H, R, -1) + else: + padding_l = self.padding_l + if K > T and padding_l == K - 1: + weight = weight.narrow(1, K - T, T) + K, padding_l = T, T - 1 + # unfold the input: T x B x C --> T' x B x C x K + x_unfold = unfold1d(x, K, padding_l, 0) + x_unfold = x_unfold.view(T * B * H, R, K) + + if self.weight_softmax and not self.renorm_padding: + weight = F.softmax(weight, dim=1) + weight = weight.narrow(1, 0, K) + + if incremental_state is not None: + weight = weight[:, -x_unfold.size(2) :] + K = weight.size(1) + + if self.weight_softmax and self.renorm_padding: + weight = F.softmax(weight, dim=1) + + weight = self.weight_dropout_module(weight, inplace=False) + + output = torch.bmm(x_unfold, weight.unsqueeze(2)) # T*B*H x R x 1 + output = output.view(T, B, C) + return output + + def _forward_expanded(self, x, incremental_stat, query): + """Turn the convolution filters into band matrices and do matrix multiplication. + This is faster when the sequence is short, but less memory efficient. + This is not used in the decoder during inference. + """ + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + if self.in_proj: + proj = self.weight_linear(x) + x = proj.narrow(2, 0, self.input_size).contiguous() + weight = ( + proj.narrow(2, self.input_size, H * K).contiguous().view(T * B * H, -1) + ) + else: + weight = self.weight_linear(query).view(T * B * H, -1) + + if not self.renorm_padding: + if self.weight_softmax: + weight = F.softmax(weight, dim=1) + weight = self.weight_dropout_module(weight, inplace=False) + weight = weight.narrow(1, 0, K).contiguous() + weight = weight.view(T, B * H, K).transpose(0, 1) + + x = x.view(T, B * H, R).transpose(0, 1) + if self.weight_softmax and self.renorm_padding: + # turn the convolution filters into band matrices + weight_expanded = weight.new(B * H, T, T + K - 1).fill_(float("-inf")) + weight_expanded.as_strided( + (B * H, T, K), (T * (T + K - 1), T + K, 1) + ).copy_(weight) + weight_expanded = weight_expanded.narrow(2, self.padding_l, T) + # normalize the weight over valid positions like self-attention + weight_expanded = F.softmax(weight_expanded, dim=2) + weight_expanded = self.weight_dropout_module(weight_expanded, inplace=False) + else: + P = self.padding_l + # For efficieny, we cut the kernel size and reduce the padding when the kernel is larger than the length + if K > T and P == K - 1: + weight = weight.narrow(2, K - T, T) + K, P = T, T - 1 + # turn the convolution filters into band matrices + weight_expanded = weight.new_zeros(B * H, T, T + K - 1, requires_grad=False) + weight_expanded.as_strided( + (B * H, T, K), (T * (T + K - 1), T + K, 1) + ).copy_(weight) + weight_expanded = weight_expanded.narrow(2, P, T) # B*H x T x T + output = torch.bmm(weight_expanded, x) + output = output.transpose(0, 1).contiguous().view(T, B, C) + return output + + def reorder_incremental_state(self, incremental_state, new_order): + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + input_buffer = input_buffer.index_select(1, new_order) + self._set_input_buffer(incremental_state, input_buffer) + + def _get_input_buffer(self, incremental_state): + return utils.get_incremental_state(self, incremental_state, "input_buffer") + + def _set_input_buffer(self, incremental_state, new_buffer): + return utils.set_incremental_state( + self, incremental_state, "input_buffer", new_buffer + ) + + def extra_repr(self): + s = "{}, kernel_size={}, padding_l={}, num_heads={}, weight_softmax={}, conv_bias={}, renorm_padding={}, in_proj={}".format( + self.input_size, + self.kernel_size, + self.padding_l, + self.num_heads, + self.weight_softmax, + self.conv_bias is not None, + self.renorm_padding, + self.in_proj, + ) + + if self.query_size != self.input_size: + s += ", query_size={}".format(self.query_size) + if self.weight_dropout_module.p > 0.0: + s += ", weight_dropout={}".format(self.weight_dropout_module.p) + return s diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamic_crf_layer.py b/fairseq-tools/fairseq/fairseq/modules/dynamic_crf_layer.py new file mode 100644 index 00000000..8fcc6b8d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamic_crf_layer.py @@ -0,0 +1,189 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +This file is to re-implemented the low-rank and beam approximation of CRF layer +Proposed by: + +Sun, Zhiqing, et al. +Fast Structured Decoding for Sequence Models +https://arxiv.org/abs/1910.11555 + +The CRF implementation is mainly borrowed from +https://github.com/kmkurn/pytorch-crf/blob/master/torchcrf/__init__.py + +""" + +import numpy as np +import torch +import torch.nn as nn + + +def logsumexp(x, dim=1): + return torch.logsumexp(x.float(), dim=dim).type_as(x) + + +class DynamicCRF(nn.Module): + """Dynamic CRF layer is used to approximate the traditional + Conditional Random Fields (CRF) + $P(y | x) = 1/Z(x) exp(sum_i s(y_i, x) + sum_i t(y_{i-1}, y_i, x))$ + + where in this function, we assume the emition scores (s) are given, + and the transition score is a |V| x |V| matrix $M$ + + in the following two aspects: + (1) it used a low-rank approximation for the transition matrix: + $M = E_1 E_2^T$ + (2) it used a beam to estimate the normalizing factor Z(x) + """ + + def __init__(self, num_embedding, low_rank=32, beam_size=64): + super().__init__() + + self.E1 = nn.Embedding(num_embedding, low_rank) + self.E2 = nn.Embedding(num_embedding, low_rank) + + self.vocb = num_embedding + self.rank = low_rank + self.beam = beam_size + + def extra_repr(self): + return "vocab_size={}, low_rank={}, beam_size={}".format( + self.vocb, self.rank, self.beam + ) + + def forward(self, emissions, targets, masks, beam=None): + """ + Compute the conditional log-likelihood of a sequence of target tokens given emission scores + + Args: + emissions (`~torch.Tensor`): Emission score are usually the unnormalized decoder output + ``(batch_size, seq_len, vocab_size)``. We assume batch-first + targets (`~torch.LongTensor`): Sequence of target token indices + ``(batch_size, seq_len) + masks (`~torch.ByteTensor`): Mask tensor with the same size as targets + + Returns: + `~torch.Tensor`: approximated log-likelihood + """ + numerator = self._compute_score(emissions, targets, masks) + denominator = self._compute_normalizer(emissions, targets, masks, beam) + return numerator - denominator + + def forward_decoder(self, emissions, masks=None, beam=None): + """ + Find the most likely output sequence using Viterbi algorithm. + + Args: + emissions (`~torch.Tensor`): Emission score are usually the unnormalized decoder output + ``(batch_size, seq_len, vocab_size)``. We assume batch-first + masks (`~torch.ByteTensor`): Mask tensor with the same size as targets + + Returns: + `~torch.LongTensor`: decoded sequence from the CRF model + """ + return self._viterbi_decode(emissions, masks, beam) + + def _compute_score(self, emissions, targets, masks=None): + batch_size, seq_len = targets.size() + emission_scores = emissions.gather(2, targets[:, :, None])[:, :, 0] # B x T + transition_scores = (self.E1(targets[:, :-1]) * self.E2(targets[:, 1:])).sum(2) + + scores = emission_scores + scores[:, 1:] += transition_scores + + if masks is not None: + scores = scores * masks.type_as(scores) + return scores.sum(-1) + + def _compute_normalizer(self, emissions, targets=None, masks=None, beam=None): + # HACK: we include "target" which is a hueristic for training + # HACK: we use a beam of tokens to approximate the normalizing factor (which is bad?) + + beam = beam if beam is not None else self.beam + batch_size, seq_len = emissions.size()[:2] + if targets is not None: + _emissions = emissions.scatter(2, targets[:, :, None], np.float("inf")) + beam_targets = _emissions.topk(beam, 2)[1] + beam_emission_scores = emissions.gather(2, beam_targets) + else: + beam_emission_scores, beam_targets = emissions.topk(beam, 2) + beam_transition_score1 = self.E1(beam_targets[:, :-1]) # B x (T-1) x K x D + beam_transition_score2 = self.E2(beam_targets[:, 1:]) # B x (T-1) x K x D + beam_transition_matrix = torch.bmm( + beam_transition_score1.view(-1, beam, self.rank), + beam_transition_score2.view(-1, beam, self.rank).transpose(1, 2), + ) + beam_transition_matrix = beam_transition_matrix.view(batch_size, -1, beam, beam) + + # compute the normalizer in the log-space + score = beam_emission_scores[:, 0] # B x K + for i in range(1, seq_len): + next_score = score[:, :, None] + beam_transition_matrix[:, i - 1] + next_score = logsumexp(next_score, dim=1) + beam_emission_scores[:, i] + + if masks is not None: + score = torch.where(masks[:, i : i + 1], next_score, score) + else: + score = next_score + + # Sum (log-sum-exp) over all possible tags + return logsumexp(score, dim=1) + + def _viterbi_decode(self, emissions, masks=None, beam=None): + # HACK: we use a beam of tokens to approximate the normalizing factor (which is bad?) + + beam = beam if beam is not None else self.beam + batch_size, seq_len = emissions.size()[:2] + beam_emission_scores, beam_targets = emissions.topk(beam, 2) + beam_transition_score1 = self.E1(beam_targets[:, :-1]) # B x (T-1) x K x D + beam_transition_score2 = self.E2(beam_targets[:, 1:]) # B x (T-1) x K x D + beam_transition_matrix = torch.bmm( + beam_transition_score1.view(-1, beam, self.rank), + beam_transition_score2.view(-1, beam, self.rank).transpose(1, 2), + ) + beam_transition_matrix = beam_transition_matrix.view(batch_size, -1, beam, beam) + + traj_tokens, traj_scores = [], [] + finalized_tokens, finalized_scores = [], [] + + # compute the normalizer in the log-space + score = beam_emission_scores[:, 0] # B x K + dummy = ( + torch.arange(beam, device=score.device).expand(*score.size()).contiguous() + ) + + for i in range(1, seq_len): + traj_scores.append(score) + _score = score[:, :, None] + beam_transition_matrix[:, i - 1] + _score, _index = _score.max(dim=1) + _score = _score + beam_emission_scores[:, i] + + if masks is not None: + score = torch.where(masks[:, i : i + 1], _score, score) + index = torch.where(masks[:, i : i + 1], _index, dummy) + else: + score, index = _score, _index + traj_tokens.append(index) + + # now running the back-tracing and find the best + best_score, best_index = score.max(dim=1) + finalized_tokens.append(best_index[:, None]) + finalized_scores.append(best_score[:, None]) + + for idx, scs in zip(reversed(traj_tokens), reversed(traj_scores)): + previous_index = finalized_tokens[-1] + finalized_tokens.append(idx.gather(1, previous_index)) + finalized_scores.append(scs.gather(1, previous_index)) + + finalized_tokens.reverse() + finalized_tokens = torch.cat(finalized_tokens, 1) + finalized_tokens = beam_targets.gather(2, finalized_tokens[:, :, None])[:, :, 0] + + finalized_scores.reverse() + finalized_scores = torch.cat(finalized_scores, 1) + finalized_scores[:, 1:] = finalized_scores[:, 1:] - finalized_scores[:, :-1] + + return finalized_scores, finalized_tokens diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/__init__.py b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/__init__.py new file mode 100644 index 00000000..22dc6f40 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .dynamicconv_layer import DynamicconvLayer # noqa diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/cuda_function_gen.py b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/cuda_function_gen.py new file mode 100644 index 00000000..9304f99e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/cuda_function_gen.py @@ -0,0 +1,223 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +def gen_forward(): + + kernels = [3, 5, 7, 15, 31, 63, 127, 255] + blocks = [32, 64, 128, 256] + + head = """ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "dynamicconv_cuda.cuh" + +std::vector<at::Tensor> dynamicconv_cuda_forward(at::Tensor input, at::Tensor weight, int padding_l) { + + at::DeviceGuard g(input.device()); + const auto minibatch = input.size(0); + const auto numFeatures = input.size(1); + const auto sequenceLength = input.size(2); + + const auto numHeads = weight.size(1); + const auto filterSize = weight.size(2); + + const auto numFiltersInBlock = numFeatures / numHeads; + const dim3 blocks(minibatch, numFeatures); + + auto output = at::zeros_like(input); + auto stream = at::cuda::getCurrentCUDAStream(); +""" + + switch = """ + switch(filterSize) { +""" + + case_k = """ + case {k}: +""" + + main_block = """ + if (padding_l == {pad}) {{ + AT_DISPATCH_FLOATING_TYPES_AND_HALF(input.scalar_type(), "dynamicconv_forward", ([&] {{ + dynamicconv_forward_kernel<{k}, {b_size}, {pad}, scalar_t> + <<<blocks, {b_size}, 0, stream>>>( + input.data<scalar_t>(), + weight.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + numHeads, + output.data<scalar_t>()); + }})); + }} else +""" + + bad_padding = """ + { + std::cout << "WARNING: Unsupported padding size - skipping forward pass" << std::endl; + } + break;\n +""" + + end = """ + default: + std::cout << "WARNING: Unsupported filter length passed - skipping forward pass" << std::endl; + } + + return {output}; +} +""" + + with open("dynamicconv_cuda_forward.cu", "w") as forward: + forward.write(head) + forward.write(switch) + for k in kernels: + b_size = 32 + for b in blocks: + if b > k: + b_size = b + break + forward.write(case_k.format(k=k)) + for pad in [k // 2, k - 1]: + forward.write(main_block.format(k=k, b_size=b_size, pad=pad)) + forward.write(bad_padding) + forward.write(end) + + +def gen_backward(): + + kernels = [3, 5, 7, 15, 31, 63, 127, 255] + thresh = [512, 512, 512, 512, 512, 380, 256, 256] + min_block = [64, 64, 64, 64, 64, 64, 128, 256] + seqs = [32 * x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]] + + head = """ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "dynamicconv_cuda.cuh" + +std::vector<at::Tensor> dynamicconv_cuda_backward(at::Tensor gradOutput, int padding_l, at::Tensor input, at::Tensor weight) { + + at::DeviceGuard g(input.device()); + const auto minibatch = input.size(0); + const auto numFeatures = input.size(1); + const auto sequenceLength = input.size(2); + + const auto numHeads = weight.size(1); + const auto filterSize = weight.size(2); + + const auto numFiltersInBlock = numFeatures / numHeads; + auto numChunks = 1; + + auto gradInput = at::zeros_like(input); + auto gradWeight = at::zeros_like(weight); + auto stream = at::cuda::getCurrentCUDAStream(); + + dim3 blocks(minibatch, numHeads, numChunks); +""" + + sequence_if = """ + if (sequenceLength < {seq}) {{ + switch(filterSize) {{ +""" + + case_k = """ + case {k}: +""" + + chunks_reset = """ + numChunks = int(ceilf(sequenceLength/float({b_size}))); + blocks = dim3(minibatch, numHeads, numChunks); +""" + + main_block = """ + if (padding_l == {p}) {{ + AT_DISPATCH_FLOATING_TYPES_AND_HALF(gradOutput.scalar_type(), "dynamicconv_backward", ([&] {{ + dynamicconv_backward_kernel<{k}, {b_size}, {p}, scalar_t> + <<<blocks, {b_size}, 0, stream>>>( + gradOutput.data<scalar_t>(), + input.data<scalar_t>(), + weight.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + numHeads, + gradWeight.data<scalar_t>(), + gradInput.data<scalar_t>()); + }})); + }} else +""" + + bad_padding = """ + { + std::cout << "WARNING: Unsupported padding size - skipping backward pass" << std::endl; + } + break;\n +""" + + bad_filter = """ + default: + std::cout << "WARNING: Unsupported filter length passed - skipping backward pass" << std::endl; + } +""" + + con_else = """ + } else +""" + + final_else = """ + { + switch(filterSize) { +""" + + last_return = """ + } + return {gradInput, gradWeight}; +} +""" + + with open("dynamicconv_cuda_backward.cu", "w") as backward: + backward.write(head) + for seq in seqs: + backward.write(sequence_if.format(seq=seq)) + for k, t, m in zip(kernels, thresh, min_block): + backward.write(case_k.format(k=k)) + if seq <= t: + b_size = seq + else: + b_size = m + backward.write(chunks_reset.format(b_size=b_size)) + for p in [k // 2, k - 1]: + backward.write(main_block.format(k=k, b_size=b_size, p=p)) + backward.write(bad_padding) + backward.write(bad_filter) + backward.write(con_else) + backward.write(final_else) + for k, m in zip(kernels, min_block): + backward.write(case_k.format(k=k)) + backward.write(chunks_reset.format(b_size=m)) + for p in [k // 2, k - 1]: + backward.write(main_block.format(k=k, b_size=m, p=p)) + backward.write(bad_padding) + backward.write(bad_filter) + backward.write(last_return) + + +if __name__ == "__main__": + gen_forward() + gen_backward() diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cpp b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cpp new file mode 100644 index 00000000..ebd4df0e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cpp @@ -0,0 +1,56 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <torch/extension.h> +#include <vector> + +std::vector<at::Tensor> dynamicconv_cuda_forward( + at::Tensor input, + at::Tensor filters, + int padding_l); + +std::vector<at::Tensor> dynamicconv_cuda_backward( + at::Tensor gradOutput, + int padding_l, + at::Tensor input, + at::Tensor filters); + + +#define CHECK_CUDA(x) AT_ASSERTM(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) AT_ASSERTM(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + +std::vector<at::Tensor> dynamicconv_forward( + at::Tensor input, + at::Tensor filters, + int padding_l) { + + CHECK_INPUT(input); + CHECK_INPUT(filters); + + return dynamicconv_cuda_forward(input, filters, + padding_l); +} + +std::vector<at::Tensor> dynamicconv_backward( + at::Tensor gradOutput, + int padding_l, + at::Tensor input, + at::Tensor filters) { + + CHECK_INPUT(gradOutput); + CHECK_INPUT(input); + CHECK_INPUT(filters); + + return dynamicconv_cuda_backward(gradOutput, padding_l, + input, filters); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("forward", &dynamicconv_forward, "dynamicconv forward (CUDA)"); + m.def("backward", &dynamicconv_backward, "dynamicconv backward (CUDA)"); +} diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cuh b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cuh new file mode 100644 index 00000000..21962594 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda.cuh @@ -0,0 +1,51 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <ATen/ATen.h> +#include <c10/cuda/CUDAStream.h> + +#include <cuda.h> +#include <cuda_fp16.h> +#include <cuda_runtime.h> + +#include <algorithm> +#include <functional> +#include <iostream> +#include <stdexcept> +#include <utility> +#include <vector> + +#include <stdlib.h> +#include <assert.h> +#include <math.h> + +#define SHFL_MASK 0xffffffff + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void dynamicconv_forward_kernel(const scalar_t* input, + const scalar_t* weight, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + scalar_t* output); + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void dynamicconv_backward_kernel( + const scalar_t* gradOutput, // B * C * T + const scalar_t* input, // B * C * T + const scalar_t* weight, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + scalar_t* gradWeight, + scalar_t* gradInput); // B * H * k * T diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda_kernel.cu b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda_kernel.cu new file mode 100644 index 00000000..300d35b6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_cuda_kernel.cu @@ -0,0 +1,168 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "dynamicconv_cuda.cuh" +#include "dynamicconv_cuda_forward.cu" +#include "dynamicconv_cuda_backward.cu" +#include "../cuda_utils.cu" + +// FS is filter size and kernels are specialized for filter sizes +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void dynamicconv_forward_kernel(const scalar_t* input, + const scalar_t* weight, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + scalar_t* output) { + assert(blockDim.x == SB); + + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int featureIdx = blockIdx.y; + const int head = featureIdx / numFiltersInBlock; + + const int IOOffset = batchIdx * numFeatures * sequenceLength + + featureIdx * sequenceLength; + const scalar_t* inputFeature = &input[IOOffset]; + scalar_t* outputFeature = &output[IOOffset]; + + scalar_t filter[FS]; + + __shared__ scalar_t tempInput[SB + FS]; + zeroSharedMem<FS, SB, padding_l>(tempInput); + + const int numIterations = divUp<int, int>(sequenceLength, SB); + + for (int i = 0; i < numIterations; ++i) { + __syncthreads(); + const int inputOffset = i * SB; + load_input_to_shared<FS, SB, padding_l>(inputFeature, inputOffset, + sequenceLength, i, + numIterations, false, tempInput); + __syncthreads(); + if (inputOffset + tid < sequenceLength) { + + #pragma unroll + for (int k = 0; k < FS; ++k) { + const int filterOffset = batchIdx * numHeads * FS * sequenceLength + + head * FS * sequenceLength + + k * sequenceLength + + i * SB + tid; + filter[k] = weight[filterOffset]; + } + + scalar_t out = scalar_t(0.0); + #pragma unroll + for (int k = 0; k < FS; ++k) { + out += filter[k] * tempInput[tid + k]; + } + + outputFeature[inputOffset + tid] = out; + + } + } +} + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void dynamicconv_backward_kernel( + const scalar_t* gradOutput, // B * C * T + const scalar_t* input, // B * C * T + const scalar_t* weight, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + scalar_t* gradWeight, + scalar_t* gradInput) { // B * H * k * T + + assert(blockDim.x == SB); + + // each block operates on a single batch and filter head + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int headIdx = blockIdx.y; + const int chunkIdx = blockIdx.z; + + const int numChunks = divUp<int, int>(sequenceLength, SB); + const int inputOffset = chunkIdx * SB; + + // initialize shared memory for output gradient and input + __shared__ scalar_t tempGradOutput[SB + FS]; + __shared__ scalar_t tempInput[SB + FS]; + const int padding = FS - padding_l - 1; + + zeroSharedMem<FS, SB, padding>(tempGradOutput); + zeroSharedMem<FS, SB, padding_l>(tempInput); + + // initialize local filter and weight gradient sum arrays + scalar_t tempGradSum[FS]; + scalar_t bfilter[FS]; + for (int k = 0; k < FS; ++k) { + tempGradSum[k] = scalar_t(0.0); + + int idxOffset = inputOffset + tid + k - padding; + if (idxOffset >= 0 && idxOffset < sequenceLength) { + int bfilterOffset = batchIdx * numHeads * FS * sequenceLength + + headIdx * FS * sequenceLength + + (FS - k - 1) * sequenceLength + + idxOffset; + bfilter[k] = weight[bfilterOffset]; + } else { + bfilter[k] = scalar_t(0.0); + } + } + + + // iterate over filter block + for (int featureIdx = 0; featureIdx < numFiltersInBlock; ++featureIdx) { + __syncthreads(); + + // load input and output gradient for this channel and chunk + const int IOOffset = batchIdx * numFeatures * sequenceLength + + (headIdx * numFiltersInBlock + featureIdx) * sequenceLength; + const scalar_t* inputFeature = &input[IOOffset]; + const scalar_t* gradOutputFeature = &gradOutput[IOOffset]; + scalar_t* gradInputFeature = &gradInput[IOOffset]; + + load_input_to_shared<FS, SB, padding>(gradOutputFeature, inputOffset, + sequenceLength, chunkIdx, + numChunks, true, tempGradOutput); + load_input_to_shared<FS, SB, padding_l>(inputFeature, inputOffset, + sequenceLength, chunkIdx, + numChunks, true, tempInput); + __syncthreads(); + + // sum input and weight gradients + scalar_t out = scalar_t(0.0); + #pragma unroll + for (int k = 0; k < FS; ++k) { + tempGradSum[k] += tempInput[tid + k] * tempGradOutput[tid + padding]; + out += bfilter[k] * tempGradOutput[tid + k]; + } + + if (inputOffset + tid < sequenceLength) { + gradInputFeature[inputOffset + tid] = out; + } + } + + const int gradOffset = batchIdx * numHeads * FS * sequenceLength + + headIdx * FS * sequenceLength; + scalar_t *gradWeightFeature = &gradWeight[gradOffset]; + + // write weight gradient + if (inputOffset + tid < sequenceLength) { + for (int k = 0; k < FS; ++k) { + const int outputOffset = k * sequenceLength + inputOffset + tid; + gradWeightFeature[outputOffset] = tempGradSum[k]; + } + } +} diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_layer.py b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_layer.py new file mode 100644 index 00000000..4a683d26 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamicconv_layer.py @@ -0,0 +1,227 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import dynamicconv_cuda +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.unfold import unfold1d +from torch import nn +from torch.autograd import Function + + +class dynamicconvFunction(Function): + @staticmethod + def forward(ctx, x, weights, padding_l): + ctx.padding_l = padding_l + outputs = dynamicconv_cuda.forward(x, weights, padding_l) + variables = [x, weights] + ctx.save_for_backward(*variables) + return outputs[0] + + @staticmethod + def backward(ctx, grad_output): + outputs = dynamicconv_cuda.backward( + grad_output.contiguous(), ctx.padding_l, *ctx.saved_tensors + ) + grad_input, grad_weights = outputs + return grad_input, grad_weights, None + + +@with_incremental_state +class DynamicconvLayer(nn.Module): + def __init__( + self, + input_size, + kernel_size=1, + padding_l=None, + weight_softmax=False, + num_heads=1, + weight_dropout=0.0, + bias=False, + renorm_padding=False, + conv_bias=False, + query_size=None, + ): + + super(DynamicconvLayer, self).__init__() + self.input_size = input_size + self.query_size = input_size if query_size is None else query_size + self.kernel_size = kernel_size + self.padding_l = padding_l + self.num_heads = num_heads + self.weight_softmax = weight_softmax + self.weight_dropout_module = FairseqDropout( + weight_dropout, module_name=self.__class__.__name__ + ) + self.renorm_padding = renorm_padding + self.bias = bias + + self.weight_linear = nn.Linear(input_size, num_heads * kernel_size, bias) + if conv_bias: + self.conv_bias = nn.Parameter(torch.Tensor(input_size)) + else: + self.conv_bias = None + self.reset_parameters() + + def reset_parameters(self): + nn.init.xavier_uniform_(self.weight_linear.weight) + if self.conv_bias is not None: + nn.init.constant_(self.conv_bias, 0.0) + nn.init.constant_(self.weight_linaer.bias, 0.0) + + def forward(self, x, incremental_state=None, query=None, unfold=None): + + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + # R = C // H + + # during inference time, incremental BMM is faster + if incremental_state is not None: + unfold = ( + x.size(0) > 512 if unfold is None else unfold + ) # use unfold mode as default for long sequence to save memory + unfold = unfold or (incremental_state is not None) + assert query is None + + if query is None: + query = x + if unfold: + output = self._forward_unfolded(x, incremental_state, query) + else: + output = self._forward_expanded(x, incremental_state, query) + + if self.conv_bias is not None: + output = output + self.conv_bias.view(1, 1, -1) + + return output + + # during training time, use CUDA kernel + else: + weight = self.weight_linear(x).view(T, B, H, K) + if self.weight_softmax: + weight = F.softmax(weight, dim=-1) + if self.weight_dropout_module.p: + weight = self.weight_dropout_module(weight) + + weight = weight.permute(1, 2, 3, 0).contiguous() + self.filters = weight + x = x.permute(1, 2, 0).contiguous() + output = dynamicconvFunction.apply(x, weight, self.padding_l).permute( + 2, 0, 1 + ) + if self.conv_bias is not None: + output = output + self.conv_bias.view(1, 1, -1) + return output + + def reorder_incremental_state(self, incremental_state, new_order): + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + input_buffer = input_buffer.index_select(1, new_order) + self._set_input_buffer(incremental_state, input_buffer) + + def _get_input_buffer(self, incremental_state): + return utils.get_incremental_state(self, incremental_state, "input_buffer") + + def _set_input_buffer(self, incremental_state, new_buffer): + return utils.set_incremental_state( + self, incremental_state, "input_buffer", new_buffer + ) + + def _forward_unfolded(self, x, incremental_state, query): + """The conventional implementation of convolutions. + Unfolding the input by having a window shifting to the right.""" + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + + weight = self.weight_linear(query).view(T * B * H, -1) + + # renorm_padding is only implemented in _forward_expanded + assert not self.renorm_padding or incremental_state is not None + + if incremental_state is not None: + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is None: + input_buffer = x.new() + x_unfold = torch.cat([input_buffer, x.unsqueeze(3)], dim=3) + if self.kernel_size > 1: + self._set_input_buffer( + incremental_state, x_unfold[:, :, :, -self.kernel_size + 1 :] + ) + x_unfold = x_unfold.view(T * B * H, R, -1) + else: + padding_l = self.padding_l + if K > T and padding_l == K - 1: + weight = weight.narrow(1, K - T, T) + K, padding_l = T, T - 1 + # unfold the input: T x B x C --> T' x B x C x K + x_unfold = unfold1d(x, K, padding_l, 0) + x_unfold = x_unfold.view(T * B * H, R, K) + + if self.weight_softmax and not self.renorm_padding: + weight = F.softmax(weight, dim=1) + weight = weight.narrow(1, 0, K) + + if incremental_state is not None: + weight = weight[:, -x_unfold.size(2) :] + K = weight.size(1) + + if self.weight_softmax and self.renorm_padding: + weight = F.softmax(weight, dim=1) + + weight = self.weight_dropout_module(weight, inplace=False) + + output = torch.bmm(x_unfold, weight.unsqueeze(2)) # T*B*H x R x 1 + output = output.view(T, B, C) + return output + + def _forward_expanded(self, x, incremental_stat, query): + """Turn the convolution filters into band matrices and do matrix multiplication. + This is faster when the sequence is short, but less memory efficient. + This is not used in the decoder during inference. + """ + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + weight = self.weight_linear(query).view(T * B * H, -1) + + if not self.renorm_padding: + if self.weight_softmax: + weight = F.softmax(weight, dim=1) + weight = self.weight_dropout_module(weight, inplace=False) + weight = weight.narrow(1, 0, K).contiguous() + weight = weight.view(T, B * H, K).transpose(0, 1) + + x = x.view(T, B * H, R).transpose(0, 1) + if self.weight_softmax and self.renorm_padding: + # turn the convolution filters into band matrices + weight_expanded = weight.new(B * H, T, T + K - 1).fill_(float("-inf")) + weight_expanded.as_strided( + (B * H, T, K), (T * (T + K - 1), T + K, 1) + ).copy_(weight) + weight_expanded = weight_expanded.narrow(2, self.padding_l, T) + # normalize the weight over valid positions like self-attention + weight_expanded = F.softmax(weight_expanded, dim=2) + weight_expanded = self.weight_dropout_module(weight_expanded, inplace=False) + else: + P = self.padding_l + # For efficieny, we cut the kernel size and reduce the padding when the kernel is larger than the length + if K > T and P == K - 1: + weight = weight.narrow(2, K - T, T) + K, P = T, T - 1 + # turn the convolution filters into band matrices + weight_expanded = weight.new_zeros(B * H, T, T + K - 1, requires_grad=False) + weight_expanded.as_strided( + (B * H, T, K), (T * (T + K - 1), T + K, 1) + ).copy_(weight) + weight_expanded = weight_expanded.narrow(2, P, T) # B*H x T x T + output = torch.bmm(weight_expanded, x) + output = output.transpose(0, 1).contiguous().view(T, B, C) + return output diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamiconv_cpu.cpp b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamiconv_cpu.cpp new file mode 100644 index 00000000..8a6af428 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/dynamiconv_cpu.cpp @@ -0,0 +1,35 @@ +#include <torch/torch.h> +#include <vector> + +std::vector<float*> dynamicconv_cpu_forward( + float* input, + float* filters, + int padding_l); + +std::vector<float*> dynamicconv_cpu_backward( + float* gradOutput, + int padding_l, + float* input, + float* filters); + +std::vector<float*> dynamicconv_forward( + float* input, + float* filters, + int padding_l) { + + return dynamicconv_cpu_forward(input, filters, padding_l); +} + +std::vector<float*> dynamicconv_backward( + float* gradOutput, + int padding_l, + float* input, + float* filters) { + + return dynamicconv_cpu_backward(gradOutput, padding_l, input, filters); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("forward", &dynamicconv_forward, "dynamicconv forward (CPU)"); + m.def("backward", &dynamicconv_backward, "dynamicconv backward (CPU)"); +} diff --git a/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/setup.py b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/setup.py new file mode 100644 index 00000000..6a21f7e2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/dynamicconv_layer/setup.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from setuptools import setup +from torch.utils.cpp_extension import BuildExtension, CUDAExtension + + +setup( + name="dynamicconv_layer", + ext_modules=[ + CUDAExtension( + name="dynamicconv_cuda", + sources=[ + "dynamicconv_cuda.cpp", + "dynamicconv_cuda_kernel.cu", + ], + ), + ], + cmdclass={"build_ext": BuildExtension}, +) diff --git a/fairseq-tools/fairseq/fairseq/modules/fairseq_dropout.py b/fairseq-tools/fairseq/fairseq/modules/fairseq_dropout.py new file mode 100644 index 00000000..f070a804 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/fairseq_dropout.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from typing import List, Optional + +import torch.nn as nn +import torch.nn.functional as F + + +logger = logging.getLogger(__name__) + + +class FairseqDropout(nn.Module): + def __init__(self, p, module_name=None): + super().__init__() + self.p = p + self.module_name = module_name + self.apply_during_inference = False + + def forward(self, x, inplace: bool = False): + if self.training or self.apply_during_inference: + return F.dropout(x, p=self.p, training=True, inplace=inplace) + else: + return x + + def make_generation_fast_( + self, + name: str, + retain_dropout: bool = False, + retain_dropout_modules: Optional[List[str]] = None, + **kwargs + ): + if retain_dropout: + if retain_dropout_modules is not None and self.module_name is None: + logger.warning( + "Cannot enable dropout during inference for module {} " + "because module_name was not set".format(name) + ) + elif ( + retain_dropout_modules is None # if None, apply to all modules + or self.module_name in retain_dropout_modules + ): + logger.info( + "Enabling dropout during inference for module: {}".format(name) + ) + self.apply_during_inference = True + else: + logger.info("Disabling dropout for module: {}".format(name)) diff --git a/fairseq-tools/fairseq/fairseq/modules/fp32_group_norm.py b/fairseq-tools/fairseq/fairseq/modules/fp32_group_norm.py new file mode 100644 index 00000000..d03aac02 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/fp32_group_norm.py @@ -0,0 +1,25 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Layer norm done in fp32 (for fp16 training) +""" + +import torch.nn as nn +import torch.nn.functional as F + + +class Fp32GroupNorm(nn.GroupNorm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def forward(self, input): + output = F.group_norm( + input.float(), + self.num_groups, + self.weight.float() if self.weight is not None else None, + self.bias.float() if self.bias is not None else None, + self.eps, + ) + return output.type_as(input) diff --git a/fairseq-tools/fairseq/fairseq/modules/gelu.py b/fairseq-tools/fairseq/fairseq/modules/gelu.py new file mode 100644 index 00000000..a2f1ecff --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/gelu.py @@ -0,0 +1,25 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +See "Gaussian Error Linear Units (GELUs)" by Dan Hendrycks and Kevin Gimpel with +the corresponding GitHub repo: https://github.com/hendrycks/GELUs +""" + +import math + +import torch +import torch.nn as nn + + +def gelu_accurate(x): + if not hasattr(gelu_accurate, "_a"): + gelu_accurate._a = math.sqrt(2 / math.pi) + return ( + 0.5 * x * (1 + torch.tanh(gelu_accurate._a * (x + 0.044715 * torch.pow(x, 3)))) + ) + + +def gelu(x: torch.Tensor) -> torch.Tensor: + return torch.nn.functional.gelu(x.float()).type_as(x) diff --git a/fairseq-tools/fairseq/fairseq/modules/grad_multiply.py b/fairseq-tools/fairseq/fairseq/modules/grad_multiply.py new file mode 100644 index 00000000..08d15f55 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/grad_multiply.py @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +class GradMultiply(torch.autograd.Function): + @staticmethod + def forward(ctx, x, scale): + ctx.scale = scale + res = x.new(x) + return res + + @staticmethod + def backward(ctx, grad): + return grad * ctx.scale, None diff --git a/fairseq-tools/fairseq/fairseq/modules/gumbel_vector_quantizer.py b/fairseq-tools/fairseq/fairseq/modules/gumbel_vector_quantizer.py new file mode 100644 index 00000000..47657bb0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/gumbel_vector_quantizer.py @@ -0,0 +1,199 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class GumbelVectorQuantizer(nn.Module): + def __init__( + self, + dim, + num_vars, + temp, + groups, + combine_groups, + vq_dim, + time_first, + activation=nn.GELU(), + weight_proj_depth=1, + weight_proj_factor=1, + ): + """Vector quantization using gumbel softmax + + Args: + dim: input dimension (channels) + num_vars: number of quantized vectors per group + temp: temperature for training. this should be a tuple of 3 elements: (start, stop, decay factor) + groups: number of groups for vector quantization + combine_groups: whether to use the vectors for all groups + vq_dim: dimensionality of the resulting quantized vector + time_first: if true, expect input in BxTxC format, otherwise in BxCxT + activation: what activation to use (should be a module). this is only used if weight_proj_depth is > 1 + weight_proj_depth: number of layers (with activation in between) to project input before computing logits + weight_proj_factor: this is used only if weight_proj_depth is > 1. scales the inner dimensionality of + projections by this factor + """ + super().__init__() + + self.groups = groups + self.combine_groups = combine_groups + self.input_dim = dim + self.num_vars = num_vars + self.time_first = time_first + + assert ( + vq_dim % groups == 0 + ), f"dim {vq_dim} must be divisible by groups {groups} for concatenation" + + var_dim = vq_dim // groups + num_groups = groups if not combine_groups else 1 + + self.vars = nn.Parameter(torch.FloatTensor(1, num_groups * num_vars, var_dim)) + nn.init.uniform_(self.vars) + + if weight_proj_depth > 1: + + def block(input_dim, output_dim): + return nn.Sequential(nn.Linear(input_dim, output_dim), activation) + + inner_dim = self.input_dim * weight_proj_factor + self.weight_proj = nn.Sequential( + *[ + block(self.input_dim if i == 0 else inner_dim, inner_dim) + for i in range(weight_proj_depth - 1) + ], + nn.Linear(inner_dim, groups * num_vars), + ) + else: + self.weight_proj = nn.Linear(self.input_dim, groups * num_vars) + nn.init.normal_(self.weight_proj.weight, mean=0, std=1) + nn.init.zeros_(self.weight_proj.bias) + + assert len(temp) == 3, temp + + self.max_temp, self.min_temp, self.temp_decay = temp + self.curr_temp = self.max_temp + self.codebook_indices = None + + def set_num_updates(self, num_updates): + self.curr_temp = max( + self.max_temp * self.temp_decay ** num_updates, self.min_temp + ) + + def get_codebook_indices(self): + if self.codebook_indices is None: + from itertools import product + + p = [range(self.num_vars)] * self.groups + inds = list(product(*p)) + self.codebook_indices = torch.tensor( + inds, dtype=torch.long, device=self.vars.device + ).flatten() + + if not self.combine_groups: + self.codebook_indices = self.codebook_indices.view( + self.num_vars ** self.groups, -1 + ) + for b in range(1, self.groups): + self.codebook_indices[:, b] += self.num_vars * b + self.codebook_indices = self.codebook_indices.flatten() + return self.codebook_indices + + def codebook(self): + indices = self.get_codebook_indices() + return ( + self.vars.squeeze(0) + .index_select(0, indices) + .view(self.num_vars ** self.groups, -1) + ) + + def sample_from_codebook(self, b, n): + indices = self.get_codebook_indices() + indices = indices.view(-1, self.groups) + cb_size = indices.size(0) + assert ( + n < cb_size + ), f"sample size {n} is greater than size of codebook {cb_size}" + sample_idx = torch.randint(low=0, high=cb_size, size=(b * n,)) + indices = indices[sample_idx] + + z = self.vars.squeeze(0).index_select(0, indices.flatten()).view(b, n, -1) + return z + + def to_codebook_index(self, indices): + res = indices.new_full(indices.shape[:-1], 0) + for i in range(self.groups): + exponent = self.groups - i - 1 + res += indices[..., i] * (self.num_vars ** exponent) + return res + + def forward_idx(self, x): + res = self.forward(x, produce_targets=True) + return res["x"], res["targets"] + + def forward(self, x, produce_targets=False): + + result = {"num_vars": self.num_vars * self.groups} + + if not self.time_first: + x = x.transpose(1, 2) + + bsz, tsz, fsz = x.shape + x = x.reshape(-1, fsz) + x = self.weight_proj(x) + x = x.view(bsz * tsz * self.groups, -1) + + _, k = x.max(-1) + hard_x = ( + x.new_zeros(*x.shape) + .scatter_(-1, k.view(-1, 1), 1.0) + .view(bsz * tsz, self.groups, -1) + ) + hard_probs = torch.mean(hard_x.float(), dim=0) + result["code_perplexity"] = torch.exp( + -torch.sum(hard_probs * torch.log(hard_probs + 1e-7), dim=-1) + ).sum() + + avg_probs = torch.softmax( + x.view(bsz * tsz, self.groups, -1).float(), dim=-1 + ).mean(dim=0) + result["prob_perplexity"] = torch.exp( + -torch.sum(avg_probs * torch.log(avg_probs + 1e-7), dim=-1) + ).sum() + + result["temp"] = self.curr_temp + + if self.training: + x = F.gumbel_softmax(x.float(), tau=self.curr_temp, hard=True).type_as(x) + else: + x = hard_x + + x = x.view(bsz * tsz, -1) + + vars = self.vars + if self.combine_groups: + vars = vars.repeat(1, self.groups, 1) + + if produce_targets: + result["targets"] = ( + x.view(bsz * tsz * self.groups, -1) + .argmax(dim=-1) + .view(bsz, tsz, self.groups) + .detach() + ) + + x = x.unsqueeze(-1) * vars + x = x.view(bsz * tsz, self.groups, self.num_vars, -1) + x = x.sum(-2) + x = x.view(bsz, tsz, -1) + + if not self.time_first: + x = x.transpose(1, 2) # BTC -> BCT + + result["x"] = x + + return result diff --git a/fairseq-tools/fairseq/fairseq/modules/kmeans_vector_quantizer.py b/fairseq-tools/fairseq/fairseq/modules/kmeans_vector_quantizer.py new file mode 100644 index 00000000..040db1e8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/kmeans_vector_quantizer.py @@ -0,0 +1,127 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +from fairseq.modules import Fp32GroupNorm + + +class KmeansVectorQuantizer(nn.Module): + def __init__( + self, dim, num_vars, groups, combine_groups, vq_dim, time_first, gamma=0.25 + ): + """Vector quantization using straight pass-through estimator (i.e. kmeans) + + Args: + dim: input dimension (channels) + num_vars: number of quantized vectors per group + groups: number of groups for vector quantization + combine_groups: whether to use the vectors for all groups + vq_dim: dimensionality of the resulting quantized vector + time_first: if true, expect input in BxTxC format, otherwise in BxCxT + gamma: commitment loss coefficient + """ + super().__init__() + + self.groups = groups + self.combine_groups = combine_groups + self.input_dim = dim + self.num_vars = num_vars + self.vq_dim = vq_dim + self.time_first = time_first + + assert ( + vq_dim % groups == 0 + ), f"dim {vq_dim} must be divisible by groups {groups} for concatenation" + + self.var_dim = vq_dim // groups + num_groups = groups if not combine_groups else 1 + + self.embedding = nn.Parameter( + 0.01 * torch.randn(num_vars, num_groups, self.var_dim) + ) + self.projection = nn.Sequential( + nn.Conv1d(dim, dim, kernel_size=1, groups=groups, bias=False), + Fp32GroupNorm(groups, dim), + ) + self.gamma = gamma + self.mse_mean = nn.MSELoss(reduction="mean") + + def _pass_grad(self, x, y): + """Manually set gradient for backward pass. + for y = f(x), ensure that during the backward pass, + dL/dy = dL/dx regardless of f(x). + Returns: + y, with the gradient forced to be dL/dy = dL/dx. + """ + + return y.detach() + (x - x.detach()) + + @property + def expand_embedding(self): + if self.combine_groups: + return self.embedding.expand(self.num_vars, self.groups, self.var_dim) + return self.embedding + + def forward_idx(self, x): + res = self.forward(x, produce_targets=True) + return res["x"], res["targets"] + + def forward(self, x, produce_targets=False): + + result = {"num_vars": self.num_vars} + + if self.time_first: + x = x.transpose(1, 2) + + bsz, fsz, tsz = x.shape + + ze = self.projection(x) + ze_ = ze.view(bsz, self.groups, self.var_dim, tsz).permute(0, 3, 1, 2) + d = ( + (ze_.unsqueeze(0) - self.expand_embedding.unsqueeze(1).unsqueeze(1)) + .view(self.num_vars, bsz, tsz, self.groups, -1) + .norm(dim=-1, p=2) + ) + idx = d.argmin(dim=0) + zq = ( + torch.stack( + [ + self.expand_embedding[idx[..., group], group] + for group in range(self.groups) + ], + dim=-2, + ) + .view(bsz, tsz, self.groups * self.var_dim) + .permute(0, 2, 1) + ) + assert ze.shape == zq.shape, (ze.shape, zq.shape) + x = self._pass_grad(ze, zq) + + hard_x = ( + idx.new_zeros(bsz * tsz * self.groups, self.num_vars) + .scatter_(-1, idx.view(-1, 1), 1.0) + .view(bsz * tsz, self.groups, -1) + ) + hard_probs = torch.mean(hard_x.float(), dim=0) + result["code_perplexity"] = torch.exp( + -torch.sum(hard_probs * torch.log(hard_probs + 1e-7), dim=-1) + ).sum() + + if produce_targets: + result["targets"] = idx + + if self.time_first: + x = x.transpose(1, 2) # BCT -> BTC + result["x"] = x + + ze = ze.float() + zq = zq.float() + latent_loss = self.mse_mean(zq, ze.detach()) + commitment_loss = self.mse_mean(ze, zq.detach()) + + result["kmeans_loss"] = latent_loss + self.gamma * commitment_loss + + return result diff --git a/fairseq-tools/fairseq/fairseq/modules/layer_drop.py b/fairseq-tools/fairseq/fairseq/modules/layer_drop.py new file mode 100644 index 00000000..8961d8bc --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/layer_drop.py @@ -0,0 +1,44 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +LayerDrop as described in https://arxiv.org/abs/1909.11556. +""" + +import torch +import torch.nn as nn + + +class LayerDropModuleList(nn.ModuleList): + """ + A LayerDrop implementation based on :class:`torch.nn.ModuleList`. + + We refresh the choice of which layers to drop every time we iterate + over the LayerDropModuleList instance. During evaluation we always + iterate over all layers. + + Usage:: + + layers = LayerDropList(p=0.5, modules=[layer1, layer2, layer3]) + for layer in layers: # this might iterate over layers 1 and 3 + x = layer(x) + for layer in layers: # this might iterate over all layers + x = layer(x) + for layer in layers: # this might not iterate over any layers + x = layer(x) + + Args: + p (float): probability of dropping out each layer + modules (iterable, optional): an iterable of modules to add + """ + + def __init__(self, p, modules=None): + super().__init__(modules) + self.p = p + + def __iter__(self): + dropout_probs = torch.empty(len(self)).uniform_() + for i, m in enumerate(super().__iter__()): + if not self.training or (dropout_probs[i] > self.p): + yield m diff --git a/fairseq-tools/fairseq/fairseq/modules/layer_norm.py b/fairseq-tools/fairseq/fairseq/modules/layer_norm.py new file mode 100644 index 00000000..234609d9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/layer_norm.py @@ -0,0 +1,50 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +try: + from apex.normalization import FusedLayerNorm as _FusedLayerNorm + + has_fused_layernorm = True + + class FusedLayerNorm(_FusedLayerNorm): + @torch.jit.unused + def forward(self, x): + if not x.is_cuda: + return super().forward(x) + else: + with torch.cuda.device(x.device): + return super().forward(x) + + +except ImportError: + has_fused_layernorm = False + + +def LayerNorm(normalized_shape, eps=1e-5, elementwise_affine=True, export=False): + if torch.jit.is_scripting(): + export = True + if not export and torch.cuda.is_available() and has_fused_layernorm: + return FusedLayerNorm(normalized_shape, eps, elementwise_affine) + return torch.nn.LayerNorm(normalized_shape, eps, elementwise_affine) + + +class Fp32LayerNorm(nn.LayerNorm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def forward(self, input): + output = F.layer_norm( + input.float(), + self.normalized_shape, + self.weight.float() if self.weight is not None else None, + self.bias.float() if self.bias is not None else None, + self.eps, + ) + return output.type_as(input) diff --git a/fairseq-tools/fairseq/fairseq/modules/learned_positional_embedding.py b/fairseq-tools/fairseq/fairseq/modules/learned_positional_embedding.py new file mode 100644 index 00000000..378d0f70 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/learned_positional_embedding.py @@ -0,0 +1,61 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, Optional + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from torch import Tensor + + +class LearnedPositionalEmbedding(nn.Embedding): + """ + This module learns positional embeddings up to a fixed maximum size. + Padding ids are ignored by either offsetting based on padding_idx + or by setting padding_idx to None and ensuring that the appropriate + position ids are passed to the forward function. + """ + + def __init__(self, num_embeddings: int, embedding_dim: int, padding_idx: int): + super().__init__(num_embeddings, embedding_dim, padding_idx) + self.onnx_trace = False + if self.padding_idx is not None: + self.max_positions = self.num_embeddings - self.padding_idx - 1 + else: + self.max_positions = self.num_embeddings + + def forward( + self, + input: Tensor, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + positions: Optional[Tensor] = None, + ): + """Input is expected to be of size [bsz x seqlen].""" + assert (positions is None) or ( + self.padding_idx is None + ), "If positions is pre-computed then padding_idx should not be set." + + if positions is None: + if incremental_state is not None: + # positions is the same for every token when decoding a single step + # Without the int() cast, it doesn't work in some cases when exporting to ONNX + positions = torch.zeros( + (1, 1), device=input.device, dtype=input.dtype + ).fill_(int(self.padding_idx + input.size(1))) + else: + positions = utils.make_positions( + input, self.padding_idx, onnx_trace=self.onnx_trace + ) + return F.embedding( + positions, + self.weight, + self.padding_idx, + self.max_norm, + self.norm_type, + self.scale_grad_by_freq, + self.sparse, + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/__init__.py b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/__init__.py new file mode 100644 index 00000000..3b2a99c1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .lightconv_layer import LightconvLayer # noqa diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/cuda_function_gen.py b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/cuda_function_gen.py new file mode 100644 index 00000000..a25433dd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/cuda_function_gen.py @@ -0,0 +1,289 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +def gen_forward(): + + kernels = [3, 5, 7, 15, 31, 63, 127, 255] + seqs = [32 * x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]] + + head = """ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "lightconv_cuda.cuh" + +std::vector<at::Tensor> lightconv_cuda_forward(at::Tensor input, at::Tensor filters, int padding_l) { + + at::DeviceGuard g(input.device()); + const auto minibatch = input.size(0); + const auto numFeatures = input.size(1); + const auto sequenceLength = input.size(2); + + const auto numHeads = filters.size(0); + const auto filterSize = filters.size(1); + + const auto numFiltersInBlock = numFeatures / numHeads; + + const dim3 blocks(minibatch, numFeatures); + + auto output = at::zeros_like(input); + auto stream = at::cuda::getCurrentCUDAStream(); +""" + + sequence_if = """ + if (sequenceLength <= {seq}) {{ + switch(filterSize) {{ +""" + + case_k = """ + case {k}: +""" + + main_block = """ + if (padding_l == {pad}) {{ + AT_DISPATCH_FLOATING_TYPES_AND_HALF(input.scalar_type(), "lightconv_forward", ([&] {{ + lightconv_forward_kernel<{k}, {b_size}, {pad}, scalar_t> + <<<blocks, {b_size}, 0, stream>>>( + input.data<scalar_t>(), + filters.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + output.data<scalar_t>()); + }})); + }} else +""" + + bad_padding = """ + { + std::cout << "WARNING: Unsupported padding size - skipping forward pass" << std::endl; + } + break; +""" + + bad_filter = """ + default: + std::cout << "WARNING: Unsupported filter length passed - skipping forward pass" << std::endl; + } +""" + + con_else = """ + } else +""" + + final_else = """ + { + switch(filterSize) { +""" + + final_return = """ + } + + return {output}; +} +""" + + with open("lightconv_cuda_forward.cu", "w") as forward: + forward.write(head) + for seq in seqs: + forward.write(sequence_if.format(seq=seq)) + for k in kernels: + forward.write(case_k.format(k=k)) + for pad in [k // 2, k - 1]: + forward.write(main_block.format(k=k, b_size=seq, pad=pad)) + forward.write(bad_padding) + forward.write(bad_filter) + forward.write(con_else) + + forward.write(final_else) + for k in kernels: + forward.write(case_k.format(k=k)) + for pad in [k // 2, k - 1]: + forward.write(main_block.format(k=k, b_size=seq, pad=pad)) + forward.write(bad_padding) + forward.write(bad_filter) + forward.write(final_return) + + +def gen_backward(): + + head = """ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "lightconv_cuda.cuh" + +std::vector<at::Tensor> lightconv_cuda_backward( + at::Tensor gradOutput, + int padding_l, + at::Tensor input, + at::Tensor filters) { + + // gradWrtInput + const int minibatch = input.size(0); + const int numFeatures = input.size(1); + const int sequenceLength = input.size(2); + + const int numHeads = filters.size(0); + const int filterSize = filters.size(1); + + const dim3 gradBlocks(minibatch, numFeatures); + const dim3 weightGradFirstpassShortBlocks(minibatch, numHeads); + const dim3 weightGradSecondpassBlocks(numHeads, filterSize); + + const int numFiltersInBlock = numFeatures / numHeads; + + auto gradInput = at::zeros_like(input); + auto gradFilters = at::zeros_like(filters); + + at::DeviceGuard g(input.device()); + auto stream = at::cuda::getCurrentCUDAStream(); + + switch(filterSize) { +""" + + sequence_if = """ + if (sequenceLength <= {seq}) {{ +""" + + case_k = """ + case {k}: +""" + + main_block = """ + if (padding_l == {p}) {{ + AT_DISPATCH_FLOATING_TYPES_AND_HALF(input.scalar_type(), "lightconv_backward", ([&] {{ + lightconv_grad_wrt_input_kernel<{k}, {b_size}, {p}, scalar_t> + <<<gradBlocks, {b_size}, 0, stream>>>( + gradOutput.data<scalar_t>(), + filters.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + gradInput.data<scalar_t>()); + +""" + + weight_grad_short = """ + at::Tensor tempSumGradFilters = at::zeros({{minibatch, numHeads, filterSize}}, input.options().dtype(at::kFloat)); + lightconv_grad_wrt_weights_firstpass_short_kernel<{k}, {b_size}, {p}, scalar_t> + <<<weightGradFirstpassShortBlocks, {b_size}, 0, stream>>>( + input.data<scalar_t>(), + gradOutput.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + numHeads, + tempSumGradFilters.data<float>() + ); + + lightconv_grad_wrt_weights_secondpass_short_kernel<{k}, {b_size}, scalar_t> + <<<weightGradSecondpassBlocks, {b_size}, 0, stream>>>( + tempSumGradFilters.data<float>(), + minibatch, + numFiltersInBlock, + gradFilters.data<scalar_t>() + ); + }})); + }} else +""" + + weight_grad = """ + at::Tensor tempSumGradFilters = at::zeros({{minibatch, numFeatures, filterSize}}, input.options().dtype(at::kFloat)); + lightconv_grad_wrt_weights_firstpass_kernel<{k}, {b_size}, {p}, scalar_t> + <<<gradBlocks, {b_size}, 0, stream>>>( + input.data<scalar_t>(), + gradOutput.data<scalar_t>(), + minibatch, + sequenceLength, + numFeatures, + numFiltersInBlock, + tempSumGradFilters.data<float>() + ); + + lightconv_grad_wrt_weights_secondpass_kernel<{k}, {b_size}, scalar_t> + <<<weightGradSecondpassBlocks, {b_size}, 0, stream>>>( + tempSumGradFilters.data<float>(), + minibatch, + numFiltersInBlock, + gradFilters.data<scalar_t>() + ); + }})); + }} else +""" + + bad_padding = """ + { + std::cout << "WARNING: Unsupported padding size - skipping backward pass" << std::endl; + } +""" + + breakout = """ + break; +""" + + bad_filter = """ + default: + std::cout << "WARNING: Unsupported filter length passed - skipping backward pass" << std::endl; +""" + + con_else = """ + } else +""" + + final_else = """ + { + switch(filterSize) { +""" + + last_return = """ + } + return {gradInput, gradFilters}; +} +""" + + kernels = [3, 5, 7, 15, 31, 63, 127, 255] + seqs = [32 * x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]] + thresh = [32, 32, 64, 128, 256, -1, -1, -1] + max_mem = [-1, -1, -1, -1, -1, 192, 96, 64] + + with open("lightconv_cuda_backward.cu", "w") as backward: + backward.write(head) + for (k, t, mem) in zip(kernels, thresh, max_mem): + backward.write(case_k.format(k=k)) + for seq in seqs: + if (t == -1 or seq <= t) and (mem == -1 or seq < mem): + backward.write(sequence_if.format(seq=seq)) + for p in [k // 2, k - 1]: + backward.write(main_block.format(k=k, b_size=seq, p=p)) + backward.write(weight_grad_short.format(k=k, b_size=seq, p=p)) + backward.write(bad_padding) + else: + for p in [k // 2, k - 1]: + backward.write(main_block.format(k=k, b_size=32, p=p)) + backward.write(weight_grad.format(k=k, b_size=32, p=p)) + backward.write(bad_padding) + backward.write(breakout) + break + backward.write(con_else) + backward.write(bad_filter) + backward.write(last_return) + + +if __name__ == "__main__": + gen_forward() + gen_backward() diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cpp b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cpp new file mode 100644 index 00000000..4bf6b5ad --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cpp @@ -0,0 +1,54 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <torch/extension.h> +#include <vector> + +std::vector<at::Tensor> lightconv_cuda_forward( + at::Tensor input, + at::Tensor filters, + int padding_l); + +std::vector<at::Tensor> lightconv_cuda_backward( + at::Tensor gradOutput, + int padding_l, + at::Tensor input, + at::Tensor filters); + + +#define CHECK_CUDA(x) AT_ASSERTM(x.type().is_cuda(), #x " must be a CUDA tensor") +#define CHECK_CONTIGUOUS(x) AT_ASSERTM(x.is_contiguous(), #x " must be contiguous") +#define CHECK_INPUT(x) CHECK_CUDA(x); CHECK_CONTIGUOUS(x) + +std::vector<at::Tensor> lightconv_forward( + at::Tensor input, + at::Tensor filters, + int padding_l) { + + CHECK_INPUT(input); + CHECK_INPUT(filters); + + return lightconv_cuda_forward(input, filters, padding_l); +} + +std::vector<at::Tensor> lightconv_backward( + at::Tensor gradOutput, + int padding_l, + at::Tensor input, + at::Tensor filters) { + + CHECK_INPUT(gradOutput); + CHECK_INPUT(input); + CHECK_INPUT(filters); + + return lightconv_cuda_backward(gradOutput, padding_l, input, filters); +} + +PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { + m.def("forward", &lightconv_forward, "lighconv forward (CUDA)"); + m.def("backward", &lightconv_backward, "lighconv backward (CUDA)"); +} diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cuh b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cuh new file mode 100644 index 00000000..3cae57b6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda.cuh @@ -0,0 +1,83 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include <ATen/ATen.h> +#include <c10/cuda/CUDAStream.h> + +#include <cuda.h> +#include <cuda_runtime.h> + +#include <algorithm> +#include <functional> +#include <iostream> +#include <stdexcept> +#include <utility> +#include <vector> + +#include <stdlib.h> +#include <assert.h> + +#define SHFL_MASK 0xffffffff + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_forward_kernel(const scalar_t* input, + const scalar_t* filters, + int minibatch, int sequenceLength, + int numFeatures, int numFiltersInBlock, + scalar_t* output); + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_input_kernel( + const scalar_t* input, + const scalar_t* filters, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + scalar_t* output); + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_firstpass_short_kernel( + const scalar_t* input, + const scalar_t* gradInput, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + float* output); + +template<int FS, int SB, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_secondpass_short_kernel( + const float* input, + const int minibatch, + const int numFiltersInBlock, + scalar_t* output); + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_firstpass_kernel( + const scalar_t* input, + const scalar_t* gradInput, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + float* output); + +template<int FS, int SB, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_secondpass_kernel( + const float* input, + const int minibatch, + const int numFiltersInBlock, + scalar_t* output); + diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda_kernel.cu b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda_kernel.cu new file mode 100644 index 00000000..8ee83a56 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_cuda_kernel.cu @@ -0,0 +1,375 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "lightconv_cuda.cuh" +#include "lightconv_cuda_forward.cu" +#include "lightconv_cuda_backward.cu" +#include "../cuda_utils.cu" + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_forward_kernel(const scalar_t* input, + const scalar_t* filters, + int minibatch, int sequenceLength, + int numFeatures, int numFiltersInBlock, + scalar_t* output) { + + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int featureIdx = blockIdx.y; + const int filterIdx = featureIdx / numFiltersInBlock; + + const int IOOffset = numFeatures * sequenceLength * batchIdx + featureIdx * sequenceLength; + const scalar_t* inputFeature = &input[IOOffset]; + scalar_t* outputFeature = &output[IOOffset]; + const scalar_t* inputFilter = &filters[filterIdx * FS]; + + assert(blockDim.x == SB); + + scalar_t filter[FS]; + #pragma unroll + for (int i = 0; i < FS; ++i) { + filter[i] = inputFilter[i]; + } + + __shared__ scalar_t temp[SB + FS]; + zeroSharedMem<FS, SB, padding_l>(temp); + + const int numIterations = divUp<int, int>(sequenceLength, SB); + + for (int i = 0; i < numIterations; ++i) { + // Read input into shared memory + const int inputOffset = i * SB; + + load_input_to_shared<FS, SB, padding_l>(inputFeature, inputOffset, sequenceLength, + i, numIterations, (numIterations == 1), temp); + + __syncthreads(); + + scalar_t out = 0; + #pragma unroll + for (int j = 0; j < FS; ++j) { + out += filter[j] * temp[tid + j]; + } + + // Write output + const int outputOffset = inputOffset; + if ((outputOffset + tid) < sequenceLength) { + outputFeature[outputOffset + tid] = out; + } + + __syncthreads(); + } +} + +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_input_kernel( + const scalar_t* input, + const scalar_t* filters, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + scalar_t* output) { + + // input grad kernel is similar to forward kernel + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int featureIdx = blockIdx.y; + const int filterIdx = featureIdx / numFiltersInBlock; + + const int IOOffset = numFeatures * sequenceLength * batchIdx + featureIdx * sequenceLength; + const scalar_t* inputFeature = &input[IOOffset]; + scalar_t* outputFeature = &output[IOOffset]; + const scalar_t* inputFilter = &filters[filterIdx * FS]; + + assert(blockDim.x == SB); + + scalar_t filter[FS]; + + // The only change is loading the filter in reverse + #pragma unroll + for (int i = 0; i < FS; ++i) { + filter[i] = inputFilter[FS - i - 1]; + } + + __shared__ scalar_t temp[SB + FS]; + const int padding = FS - padding_l - 1; + zeroSharedMem<FS, SB, padding>(temp); + + __syncthreads(); + + const int numIterations = divUp<int, int>(sequenceLength, SB); + + for (int i = 0; i < numIterations; ++i) { + // Read input into shared memory + const int inputOffset = i * SB; + + load_input_to_shared<FS, SB, padding>(inputFeature, inputOffset, sequenceLength, + i, numIterations, false, temp); + + __syncthreads(); + + scalar_t out = 0; + #pragma unroll + for (int j = 0; j < FS; ++j) { + out += filter[j] * temp[tid + j]; + } + + // Write output + const int outputOffset = inputOffset; + if ((outputOffset + tid) < sequenceLength) { + outputFeature[outputOffset + tid] = out; + } + + __syncthreads(); + } +} + +// This is by far the most expensive kernel in terms of time taken. +// Can be 16x slower than the forward or grad_wrt_input when filter size is 31 +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_firstpass_short_kernel( + const scalar_t* input, + const scalar_t* gradInput, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + int numHeads, + float* output) { + + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int filterIdx = blockIdx.y; + + const int numIterations = divUp<int, int>(sequenceLength, SB); + + float* tempOutputGradWeight = &output[filterIdx * FS * minibatch]; + + assert(blockDim.x == SB); + + __shared__ scalar_t tempInput[SB + FS]; + __shared__ scalar_t tempGradInput[SB + FS]; + + // local weight accumulation + float accumWeights[FS]; + + // Initialize memory + for (int i = 0; i < FS; ++i) { + accumWeights[i] = float(0.0); + } + + + // loop over each sequence within filterblock + for (int idxInFilterBlock = 0; idxInFilterBlock < numFiltersInBlock; ++idxInFilterBlock) { + + const int featureOffset = batchIdx * numFeatures * sequenceLength + (filterIdx * numFiltersInBlock + idxInFilterBlock) * sequenceLength; + const scalar_t* inputFeature = &input[featureOffset]; + const scalar_t* gradInputFeature = &gradInput[featureOffset]; + + zeroSharedMem<FS, SB, padding_l>(tempInput); + zeroSharedMem<FS, SB, (FS/2)>(tempGradInput); + __syncthreads(); + + for (int i = 0; i < numIterations; ++i) { + + const int inputOffset = i * SB; + + load_input_to_shared<FS, SB, padding_l>(inputFeature, inputOffset, sequenceLength, + i, numIterations, false, tempInput); + load_input_to_shared<FS, SB, (FS/2)>(gradInputFeature, inputOffset, sequenceLength, + i, numIterations, false, tempGradInput); + + __syncthreads(); + + const int gradIndex = (FS/2) + tid; + scalar_t tempGrad = tempGradInput[gradIndex]; + + #pragma unroll + for (int j = 0; j < FS; j++) { + const int inputIndex = tid + j; + accumWeights[j] += tempInput[inputIndex] * tempGrad; + } + + __syncthreads(); + + } + + } + + // Row-major sum + for (int filterWeightIdx = 0; filterWeightIdx < FS; ++filterWeightIdx) { + + float temp; + if (tid < sequenceLength) { + temp = accumWeights[filterWeightIdx]; + } else { + temp = float(0.0); + } + + const int outputOffset = filterWeightIdx * minibatch + batchIdx; + + temp = blockReduce(temp); + + if (tid == 0) { + tempOutputGradWeight[outputOffset] = temp; + } + } +} + +template<int FS, int SB, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_secondpass_short_kernel( + const float* input, + const int minibatch, + const int numFiltersInBlock, + scalar_t* output) { + + assert(blockDim.x == SB); + + const int tid = threadIdx.x; + + const int filterIdx = blockIdx.x; + const int filterWeightIdx = blockIdx.y; + + const int inputOffset = filterIdx * FS * minibatch + + filterWeightIdx * minibatch; + const float* tempInput = &input[inputOffset]; + + // read into shared memory for reduction + int readIndex = tid; + + float sum = 0.0; + while (readIndex < minibatch) { + sum += tempInput[readIndex]; + readIndex += SB; + } + + float temp = blockReduce(sum); + + if (tid == 0) { + output[blockIdx.x * FS + blockIdx.y] = temp; + } +} + +// This is by far the most expensive kernel in terms of time taken. +// Can be 16x slower than the forward or grad_wrt_input when filter size is 31 +template<int FS, int SB, int padding_l, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_firstpass_kernel( + const scalar_t* input, + const scalar_t* gradInput, + int minibatch, + int sequenceLength, + int numFeatures, + int numFiltersInBlock, + float* output) { + + assert(blockDim.x == SB); + + const int tid = threadIdx.x; + const int batchIdx = blockIdx.x; + const int featureIdx = blockIdx.y; + const int filterIdx = featureIdx / numFiltersInBlock; + const int idxInFilterBlock = featureIdx % numFiltersInBlock; + + const int numIterations = divUp<int, int>(sequenceLength, SB); + + float temp; + + __shared__ scalar_t tempInput[SB + FS]; + __shared__ scalar_t tempGradInput[SB + FS]; + zeroSharedMem<FS, SB, padding_l>(tempInput); + zeroSharedMem<FS, SB, (FS/2)>(tempGradInput); + __syncthreads(); + + float accumWeights[FS]; + + for (int i = 0; i < FS; ++i) { + accumWeights[i] = float(0.0); + } + + const int IOOffset = batchIdx * numFeatures * sequenceLength + featureIdx * sequenceLength; + const scalar_t* inputFeature = &input[IOOffset]; + const scalar_t* gradInputFeature = &gradInput[IOOffset]; + float* tempOutputGradWeight = &output[filterIdx * FS * minibatch * numFiltersInBlock]; + + for (int i = 0; i < numIterations; ++i) { + const int inputOffset = i * SB; + + load_input_to_shared<FS, SB, padding_l>(inputFeature, inputOffset, sequenceLength, + i, numIterations, false, tempInput); + load_input_to_shared<FS, SB, (FS/2)>(gradInputFeature, inputOffset, sequenceLength, + i, numIterations, false, tempGradInput); + __syncthreads(); + + #pragma unroll + for (int j = 0; j < FS; ++j) { + accumWeights[j] += tempInput[tid + j] * tempGradInput[tid + (FS/2)]; + } + + __syncthreads(); + } + + // Row-major sum + for (int filterWeightIdx = 0; filterWeightIdx < FS; ++filterWeightIdx) { + + // Write to shared memory before reduction + if (tid < sequenceLength) { + temp = accumWeights[filterWeightIdx]; + } else { + temp = float(0.0); + } + + temp = blockReduce(temp); + + const int outputOffset = filterWeightIdx * minibatch * numFiltersInBlock + + batchIdx * numFiltersInBlock + + idxInFilterBlock; + + if (tid == 0) { + tempOutputGradWeight[outputOffset] = temp; + } + } +} + +template<int FS, int SB, typename scalar_t> +__global__ +void lightconv_grad_wrt_weights_secondpass_kernel( + const float* input, + const int minibatch, + const int numFiltersInBlock, + scalar_t* output) { + + assert(blockDim.x == SB); + const int tid = threadIdx.x; + + // What is the id within a minibatch + const int filterIdx = blockIdx.x; + const int filterWeightIdx = blockIdx.y; + + const int inputOffset = filterIdx * FS * minibatch * numFiltersInBlock + + filterWeightIdx * minibatch * numFiltersInBlock; + const float* tempInput = &input[inputOffset]; + + int readIndex = tid; + + float sum = float(0.0); + while (readIndex < (minibatch * numFiltersInBlock)) { + sum += tempInput[readIndex]; + readIndex += SB; + } + + float temp = blockReduce(sum); + + if (tid == 0) { + output[blockIdx.x * FS + blockIdx.y] = temp; + } +} diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_layer.py b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_layer.py new file mode 100644 index 00000000..e7e597f4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/lightconv_layer.py @@ -0,0 +1,137 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import lightconv_cuda +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout +from torch import nn +from torch.autograd import Function + + +class lightconvFunction(Function): + @staticmethod + def forward(ctx, x, weights, padding_l): + ctx.padding_l = padding_l + outputs = lightconv_cuda.forward(x, weights, padding_l) + variables = [x, weights] + ctx.save_for_backward(*variables) + return outputs[0] + + @staticmethod + def backward(ctx, grad_output): + outputs = lightconv_cuda.backward( + grad_output.contiguous(), ctx.padding_l, *ctx.saved_tensors + ) + grad_input, grad_weights = outputs + return grad_input, grad_weights, None + + +@with_incremental_state +class LightconvLayer(nn.Module): + def __init__( + self, + input_size, + kernel_size=1, + padding_l=None, + weight_softmax=False, + num_heads=1, + weight_dropout=0.0, + bias=False, + ): + super(LightconvLayer, self).__init__() + self.input_size = input_size + self.kernel_size = kernel_size + self.padding_l = padding_l + self.num_heads = num_heads + self.weight_softmax = weight_softmax + self.weight_dropout_module = FairseqDropout( + weight_dropout, module_name=self.__class__.__name__ + ) + + self.weight = nn.Parameter(torch.Tensor(num_heads, kernel_size)) + if bias: + self.bias = nn.Parameter(torch.Tensor(input_size)) + else: + self.bias = None + self.reset_parameters() + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + for k, v in state_dict.items(): + if k.endswith(prefix + "weight"): + if v.dim() == 3 and v.size(1) == 1: + state_dict[k] = v.squeeze(1) + + def reset_parameters(self): + nn.init.xavier_uniform_(self.weight) + if self.bias is not None: + nn.init.constant_(self.bias, 0.0) + + def forward(self, x, incremental_state=None): + + # during inference time, incremental BMM is faster + if incremental_state is not None: + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is None: + input_buffer = x.new() + x_unfold = torch.cat([input_buffer, x.unsqueeze(3)], dim=3) + if self.kernel_size > 1: + self._set_input_buffer( + incremental_state, x_unfold[:, :, :, -self.kernel_size + 1 :] + ) + x_unfold = x_unfold.view(T * B * H, R, -1) + + weight = self.weight + if self.weight_softmax: + weight = F.softmax(weight.float(), dim=1).type_as(weight) + + weight = weight[:, -x_unfold.size(2) :] + + K = weight.size(1) + + weight = ( + weight.view(1, H, K) + .expand(T * B, H, K) + .contiguous() + .view(T * B * H, K, 1) + ) + + weight = self.weight_dropout_module(weight) + output = torch.bmm(x_unfold, weight) # T*B*H x R x 1 + output = output.view(T, B, C) + return output + + # during training time, use CUDA kernel + else: + x = x.permute(1, 2, 0).contiguous() + weight = self.weight + if self.weight_softmax: + weight = F.softmax(self.weight, -1) + if self.weight_dropout_module.p: + weight = self.weight_dropout_module(weight) + return lightconvFunction.apply(x, weight, self.padding_l).permute(2, 0, 1) + + def reorder_incremental_state(self, incremental_state, new_order): + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + input_buffer = input_buffer.index_select(1, new_order) + self._set_input_buffer(incremental_state, input_buffer) + + def _get_input_buffer(self, incremental_state): + return utils.get_incremental_state(self, incremental_state, "input_buffer") + + def _set_input_buffer(self, incremental_state, new_buffer): + return utils.set_incremental_state( + self, incremental_state, "input_buffer", new_buffer + ) + + def half(self): + return self._apply(lambda t: t.half() if t.is_floating_point() else t) diff --git a/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/setup.py b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/setup.py new file mode 100644 index 00000000..052635be --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightconv_layer/setup.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from setuptools import setup +from torch.utils.cpp_extension import BuildExtension, CUDAExtension + + +setup( + name="lightconv_layer", + ext_modules=[ + CUDAExtension( + "lightconv_cuda", + [ + "lightconv_cuda.cpp", + "lightconv_cuda_kernel.cu", + ], + ), + ], + cmdclass={"build_ext": BuildExtension}, +) diff --git a/fairseq-tools/fairseq/fairseq/modules/lightweight_convolution.py b/fairseq-tools/fairseq/fairseq/modules/lightweight_convolution.py new file mode 100644 index 00000000..ec11a950 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/lightweight_convolution.py @@ -0,0 +1,310 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.unfold import unfold1d + + +def LightweightConv( + input_size, + kernel_size=1, + padding_l=None, + num_heads=1, + weight_dropout=0.0, + weight_softmax=False, + bias=False, +): + if torch.cuda.is_available(): + try: + from fairseq.modules.lightconv_layer import LightconvLayer + + return LightconvLayer( + input_size, + kernel_size=kernel_size, + padding_l=padding_l, + num_heads=num_heads, + weight_dropout=weight_dropout, + weight_softmax=weight_softmax, + bias=bias, + ) + except ImportError as e: + print(e) + return LightweightConv1dTBC( + input_size, + kernel_size=kernel_size, + padding_l=padding_l, + num_heads=num_heads, + weight_dropout=weight_dropout, + weight_softmax=weight_softmax, + bias=bias, + ) + + +class LightweightConv1d(nn.Module): + """Lightweight Convolution assuming the input is BxCxT + This is just an example that explains LightConv clearer than the TBC version. + We don't use this module in the model. + + Args: + input_size: # of channels of the input and output + kernel_size: convolution channels + padding: padding + num_heads: number of heads used. The weight is of shape + `(num_heads, 1, kernel_size)` + weight_softmax: normalize the weight with softmax before the convolution + + Shape: + Input: BxCxT, i.e. (batch_size, input_size, timesteps) + Output: BxCxT, i.e. (batch_size, input_size, timesteps) + + Attributes: + weight: the learnable weights of the module of shape + `(num_heads, 1, kernel_size)` + bias: the learnable bias of the module of shape `(input_size)` + """ + + def __init__( + self, + input_size, + kernel_size=1, + padding=0, + num_heads=1, + weight_softmax=False, + bias=False, + weight_dropout=0.0, + ): + super().__init__() + self.input_size = input_size + self.kernel_size = kernel_size + self.num_heads = num_heads + self.padding = padding + self.weight_softmax = weight_softmax + self.weight = nn.Parameter(torch.Tensor(num_heads, 1, kernel_size)) + + if bias: + self.bias = nn.Parameter(torch.Tensor(input_size)) + else: + self.bias = None + self.weight_dropout_module = FairseqDropout( + weight_dropout, module_name=self.__class__.__name__ + ) + self.reset_parameters() + + def reset_parameters(self): + nn.init.xavier_uniform_(self.weight) + if self.bias is not None: + nn.init.constant_(self.bias, 0.0) + + def forward(self, input): + """ + input size: B x C x T + output size: B x C x T + """ + B, C, T = input.size() + H = self.num_heads + + weight = self.weight + if self.weight_softmax: + weight = F.softmax(weight, dim=-1) + + weight = self.weight_dropout_module(weight) + # Merge every C/H entries into the batch dimension (C = self.input_size) + # B x C x T -> (B * C/H) x H x T + # One can also expand the weight to C x 1 x K by a factor of C/H + # and do not reshape the input instead, which is slow though + input = input.view(-1, H, T) + output = F.conv1d(input, weight, padding=self.padding, groups=self.num_heads) + output = output.view(B, C, T) + if self.bias is not None: + output = output + self.bias.view(1, -1, 1) + + return output + + +@with_incremental_state +class LightweightConv1dTBC(nn.Module): + """Lightweight Convolution assuming the input is TxBxC + Args: + input_size: # of channels of the input + kernel_size: convolution channels + padding_l: padding to the left when using "same" padding + num_heads: number of heads used. The weight is of shape (num_heads, 1, kernel_size) + weight_dropout: the drop rate of the DropConnect to drop the weight + weight_softmax: normalize the weight with softmax before the convolution + bias: use bias + + Shape: + Input: TxBxC, i.e. (timesteps, batch_size, input_size) + Output: TxBxC, i.e. (timesteps, batch_size, input_size) + + Attributes: + weight: the learnable weights of the module of shape + `(num_heads, 1, kernel_size)` + bias: the learnable bias of the module of shape `(input_size)` + """ + + def __init__( + self, + input_size, + kernel_size=1, + padding_l=None, + num_heads=1, + weight_dropout=0.0, + weight_softmax=False, + bias=False, + ): + super().__init__() + self.input_size = input_size + self.kernel_size = kernel_size + self.padding_l = padding_l + self.num_heads = num_heads + self.weight_dropout_module = FairseqDropout( + weight_dropout, module_name=self.__class__.__name__ + ) + self.weight_softmax = weight_softmax + + self.weight = nn.Parameter(torch.Tensor(num_heads, 1, kernel_size)) + if bias: + self.bias = nn.Parameter(torch.Tensor(input_size)) + else: + self.bias = None + + self.reset_parameters() + self.onnx_trace = False + + def reset_parameters(self): + nn.init.xavier_uniform_(self.weight) + if self.bias is not None: + nn.init.constant_(self.bias, 0.0) + + def forward(self, x, incremental_state=None, unfold=False): + """Assuming the input, x, of the shape T x B x C and producing an output in the shape T x B x C + args: + x: Input of shape T x B x C, i.e. (timesteps, batch_size, input_size) + incremental_state: A dict to keep the state + unfold: unfold the input or not. If not, we use the matrix trick instead + """ + unfold = unfold or (incremental_state is not None) + + if unfold: + output = self._forward_unfolded(x, incremental_state) + else: + output = self._forward_expanded(x, incremental_state) + + if self.bias is not None: + output = output + self.bias.view(1, 1, -1) + return output + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def _forward_unfolded(self, x, incremental_state): + """The conventional implementation of convolutions. + Unfolding the input by having a window shifting to the right.""" + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + + weight = self.weight.view(H, K) + if incremental_state is not None: + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is None: + input_buffer = x.new() + x_unfold = torch.cat([input_buffer, x.unsqueeze(3)], dim=3) + if self.kernel_size > 1: + self._set_input_buffer( + incremental_state, x_unfold[:, :, :, -self.kernel_size + 1 :] + ) + x_unfold = x_unfold.view(T * B * H, R, -1) + else: + # unfold the input: T x B x C --> T' x B x C x K + x_unfold = unfold1d(x, self.kernel_size, self.padding_l, 0) + x_unfold = x_unfold.view(T * B * H, R, K) + + if self.weight_softmax: + weight = utils.softmax(weight, dim=1, onnx_trace=self.onnx_trace).type_as( + weight + ) + + if incremental_state is not None: + weight = weight[:, -x_unfold.size(2) :] + K = weight.size(1) + + weight = ( + weight.view(1, H, K).expand(T * B, H, K).contiguous().view(T * B * H, K, 1) + ) + + weight = self.weight_dropout_module(weight) + output = torch.bmm(x_unfold, weight) # T*B*H x R x 1 + output = output.view(T, B, C) + return output + + def _forward_expanded(self, x, incremental_state): + """Turn the convolution filters into band matrices and do matrix multiplication. + This is faster when the sequence is short, but less memory efficient. + This is not used in the decoder during inference. + """ + T, B, C = x.size() + K, H = self.kernel_size, self.num_heads + R = C // H + assert R * H == C == self.input_size + + weight = self.weight.view(H, K) + if self.weight_softmax: + weight = utils.softmax(weight, dim=1, onnx_trace=self.onnx_trace).type_as( + weight + ) + weight = weight.view(1, H, K).expand(T * B, H, K).contiguous() + weight = weight.view(T, B * H, K).transpose(0, 1) + + x = x.view(T, B * H, R).transpose(0, 1) + P = self.padding_l + if K > T and P == K - 1: + weight = weight.narrow(2, K - T, T) + K, P = T, T - 1 + # turn the convolution filters into band matrices + weight_expanded = weight.new_zeros(B * H, T, T + K - 1, requires_grad=False) + weight_expanded.as_strided((B * H, T, K), (T * (T + K - 1), T + K, 1)).copy_( + weight + ) + weight_expanded = weight_expanded.narrow(2, P, T) + weight_expanded = self.weight_dropout_module(weight_expanded) + + output = torch.bmm(weight_expanded, x) + output = output.transpose(0, 1).contiguous().view(T, B, C) + return output + + def reorder_incremental_state(self, incremental_state, new_order): + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + input_buffer = input_buffer.index_select(1, new_order) + self._set_input_buffer(incremental_state, input_buffer) + + def _get_input_buffer(self, incremental_state): + return utils.get_incremental_state(self, incremental_state, "input_buffer") + + def _set_input_buffer(self, incremental_state, new_buffer): + return utils.set_incremental_state( + self, incremental_state, "input_buffer", new_buffer + ) + + def extra_repr(self): + s = "{}, kernel_size={}, padding_l={}, num_heads={}, weight_softmax={}, bias={}".format( + self.input_size, + self.kernel_size, + self.padding_l, + self.num_heads, + self.weight_softmax, + self.bias is not None, + ) + if self.weight_dropout_module.p > 0.0: + s += ", weight_dropout={}".format(self.weight_dropout_module.p) + return s diff --git a/fairseq-tools/fairseq/fairseq/modules/linearized_convolution.py b/fairseq-tools/fairseq/fairseq/modules/linearized_convolution.py new file mode 100644 index 00000000..09a8f201 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/linearized_convolution.py @@ -0,0 +1,104 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state + +from .conv_tbc import ConvTBC + + +@with_incremental_state +class LinearizedConvolution(ConvTBC): + """An optimized version of nn.Conv1d. + + At training time, this module uses ConvTBC, which is an optimized version + of Conv1d. At inference time, it optimizes incremental generation (i.e., + one time step at a time) by replacing the convolutions with linear layers. + Note that the input order changes from training to inference. + """ + + def __init__(self, in_channels, out_channels, kernel_size, **kwargs): + super().__init__(in_channels, out_channels, kernel_size, **kwargs) + self._linearized_weight = None + self.register_backward_hook(self._clear_linearized_weight) + + def state_dict(self, destination=None, prefix="", keep_vars=False): + state = ConvTBC.state_dict(self, destination, prefix, keep_vars=keep_vars) + # don't store redundant _linearized_weight in checkpoints + if prefix + "_linearized_weight" in state: + del state[prefix + "_linearized_weight"] + return state + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + if prefix + "_linearized_weight" in state_dict: + del state_dict[prefix + "_linearized_weight"] + + def forward(self, input, incremental_state=None): + """ + Args: + incremental_state: Used to buffer signal; if not None, then input is + expected to contain a single frame. If the input order changes + between time steps, call reorder_incremental_state. + Input: + Time x Batch x Channel during training + Batch x Time x Channel during inference + """ + if incremental_state is None: + output = super().forward(input) + if self.kernel_size[0] > 1 and self.padding[0] > 0: + # remove future timesteps added by padding + output = output[: -self.padding[0], :, :] + return output + + # reshape weight + weight = self._get_linearized_weight() + kw = self.kernel_size[0] + + bsz = input.size(0) # input: bsz x len x dim + if kw > 1: + input = input.data + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is None: + input_buffer = input.new(bsz, kw, input.size(2)).zero_() + self._set_input_buffer(incremental_state, input_buffer) + else: + # shift buffer + input_buffer[:, :-1, :] = input_buffer[:, 1:, :].clone() + # append next input + input_buffer[:, -1, :] = input[:, -1, :] + input = input_buffer + with torch.no_grad(): + output = F.linear(input.view(bsz, -1), weight, self.bias) + return output.view(bsz, 1, -1) + + def reorder_incremental_state(self, incremental_state, new_order): + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + input_buffer = input_buffer.index_select(0, new_order) + self._set_input_buffer(incremental_state, input_buffer) + + def _get_input_buffer(self, incremental_state): + return utils.get_incremental_state(self, incremental_state, "input_buffer") + + def _set_input_buffer(self, incremental_state, new_buffer): + return utils.set_incremental_state( + self, incremental_state, "input_buffer", new_buffer + ) + + def _get_linearized_weight(self): + if self._linearized_weight is None: + kw = self.kernel_size[0] + weight = self.weight.transpose(2, 1).transpose(1, 0).contiguous() + assert weight.size() == (self.out_channels, kw, self.in_channels) + self._linearized_weight = torch.nn.Parameter( + weight.view(self.out_channels, -1) + ) + return self._linearized_weight + + def _clear_linearized_weight(self, *args): + self._linearized_weight = None diff --git a/fairseq-tools/fairseq/fairseq/modules/multihead_attention.py b/fairseq-tools/fairseq/fairseq/modules/multihead_attention.py new file mode 100644 index 00000000..99f95deb --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/multihead_attention.py @@ -0,0 +1,488 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Dict, Optional, Tuple + +import torch +import torch.nn.functional as F +from fairseq import utils +from fairseq.incremental_decoding_utils import with_incremental_state +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.quant_noise import quant_noise +from torch import Tensor, nn +from torch.nn import Parameter + + +@with_incremental_state +class MultiheadAttention(nn.Module): + """Multi-headed attention. + + See "Attention Is All You Need" for more details. + """ + + def __init__( + self, + embed_dim, + num_heads, + kdim=None, + vdim=None, + dropout=0.0, + bias=True, + add_bias_kv=False, + add_zero_attn=False, + self_attention=False, + encoder_decoder_attention=False, + q_noise=0.0, + qn_block_size=8, + ): + super().__init__() + self.embed_dim = embed_dim + self.kdim = kdim if kdim is not None else embed_dim + self.vdim = vdim if vdim is not None else embed_dim + self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim + + self.num_heads = num_heads + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + + self.head_dim = embed_dim // num_heads + assert ( + self.head_dim * num_heads == self.embed_dim + ), "embed_dim must be divisible by num_heads" + self.scaling = self.head_dim ** -0.5 + + self.self_attention = self_attention + self.encoder_decoder_attention = encoder_decoder_attention + + assert not self.self_attention or self.qkv_same_dim, ( + "Self-attention requires query, key and " "value to be of the same size" + ) + + self.k_proj = quant_noise( + nn.Linear(self.kdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.v_proj = quant_noise( + nn.Linear(self.vdim, embed_dim, bias=bias), q_noise, qn_block_size + ) + self.q_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + self.out_proj = quant_noise( + nn.Linear(embed_dim, embed_dim, bias=bias), q_noise, qn_block_size + ) + + if add_bias_kv: + self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim)) + self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim)) + else: + self.bias_k = self.bias_v = None + + self.add_zero_attn = add_zero_attn + + self.reset_parameters() + + self.onnx_trace = False + self.tpu = False + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def prepare_for_tpu_(self, **kwargs): + self.tpu = True + + def reset_parameters(self): + if self.qkv_same_dim: + # Empirically observed the convergence to be much better with + # the scaled initialization + nn.init.xavier_uniform_(self.k_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.v_proj.weight, gain=1 / math.sqrt(2)) + nn.init.xavier_uniform_(self.q_proj.weight, gain=1 / math.sqrt(2)) + else: + nn.init.xavier_uniform_(self.k_proj.weight) + nn.init.xavier_uniform_(self.v_proj.weight) + nn.init.xavier_uniform_(self.q_proj.weight) + + nn.init.xavier_uniform_(self.out_proj.weight) + if self.out_proj.bias is not None: + nn.init.constant_(self.out_proj.bias, 0.0) + if self.bias_k is not None: + nn.init.xavier_normal_(self.bias_k) + if self.bias_v is not None: + nn.init.xavier_normal_(self.bias_v) + + def forward( + self, + query, + key: Optional[Tensor], + value: Optional[Tensor], + key_padding_mask: Optional[Tensor] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + need_weights: bool = True, + static_kv: bool = False, + attn_mask: Optional[Tensor] = None, + before_softmax: bool = False, + need_head_weights: bool = False, + ) -> Tuple[Tensor, Optional[Tensor]]: + """Input shape: Time x Batch x Channel + + Args: + key_padding_mask (ByteTensor, optional): mask to exclude + keys that are pads, of shape `(batch, src_len)`, where + padding elements are indicated by 1s. + need_weights (bool, optional): return the attention weights, + averaged over heads (default: False). + attn_mask (ByteTensor, optional): typically used to + implement causal attention, where the mask prevents the + attention from looking forward in time (default: None). + before_softmax (bool, optional): return the raw attention + weights and values before the attention softmax. + need_head_weights (bool, optional): return the attention + weights for each head. Implies *need_weights*. Default: + return the average attention weights over all heads. + """ + if need_head_weights: + need_weights = True + + tgt_len, bsz, embed_dim = query.size() + assert embed_dim == self.embed_dim + assert list(query.size()) == [tgt_len, bsz, embed_dim] + + if ( + not self.onnx_trace + and not self.tpu # don't use PyTorch version on TPUs + and incremental_state is None + and not static_kv + # A workaround for quantization to work. Otherwise JIT compilation + # treats bias in linear module as method. + and not torch.jit.is_scripting() + ): + assert key is not None and value is not None + return F.multi_head_attention_forward( + query, + key, + value, + self.embed_dim, + self.num_heads, + torch.empty([0]), + torch.cat((self.q_proj.bias, self.k_proj.bias, self.v_proj.bias)), + self.bias_k, + self.bias_v, + self.add_zero_attn, + self.dropout_module.p, + self.out_proj.weight, + self.out_proj.bias, + self.training or self.dropout_module.apply_during_inference, + key_padding_mask, + need_weights, + attn_mask, + use_separate_proj_weight=True, + q_proj_weight=self.q_proj.weight, + k_proj_weight=self.k_proj.weight, + v_proj_weight=self.v_proj.weight, + ) + + if incremental_state is not None: + saved_state = self._get_input_buffer(incremental_state) + if saved_state is not None and "prev_key" in saved_state: + # previous time steps are cached - no need to recompute + # key and value if they are static + if static_kv: + assert self.encoder_decoder_attention and not self.self_attention + key = value = None + else: + saved_state = None + + if self.self_attention: + q = self.q_proj(query) + k = self.k_proj(query) + v = self.v_proj(query) + elif self.encoder_decoder_attention: + # encoder-decoder attention + q = self.q_proj(query) + if key is None: + assert value is None + k = v = None + else: + k = self.k_proj(key) + v = self.v_proj(key) + + else: + assert key is not None and value is not None + q = self.q_proj(query) + k = self.k_proj(key) + v = self.v_proj(value) + q *= self.scaling + + if self.bias_k is not None: + assert self.bias_v is not None + k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)]) + v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)]) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + if key_padding_mask is not None: + key_padding_mask = torch.cat( + [ + key_padding_mask, + key_padding_mask.new_zeros(key_padding_mask.size(0), 1), + ], + dim=1, + ) + + q = ( + q.contiguous() + .view(tgt_len, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if k is not None: + k = ( + k.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + if v is not None: + v = ( + v.contiguous() + .view(-1, bsz * self.num_heads, self.head_dim) + .transpose(0, 1) + ) + + if saved_state is not None: + # saved states are stored with shape (bsz, num_heads, seq_len, head_dim) + if "prev_key" in saved_state: + _prev_key = saved_state["prev_key"] + assert _prev_key is not None + prev_key = _prev_key.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + k = prev_key + else: + assert k is not None + k = torch.cat([prev_key, k], dim=1) + if "prev_value" in saved_state: + _prev_value = saved_state["prev_value"] + assert _prev_value is not None + prev_value = _prev_value.view(bsz * self.num_heads, -1, self.head_dim) + if static_kv: + v = prev_value + else: + assert v is not None + v = torch.cat([prev_value, v], dim=1) + prev_key_padding_mask: Optional[Tensor] = None + if "prev_key_padding_mask" in saved_state: + prev_key_padding_mask = saved_state["prev_key_padding_mask"] + assert k is not None and v is not None + key_padding_mask = MultiheadAttention._append_prev_key_padding_mask( + key_padding_mask=key_padding_mask, + prev_key_padding_mask=prev_key_padding_mask, + batch_size=bsz, + src_len=k.size(1), + static_kv=static_kv, + ) + + saved_state["prev_key"] = k.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_value"] = v.view(bsz, self.num_heads, -1, self.head_dim) + saved_state["prev_key_padding_mask"] = key_padding_mask + # In this branch incremental_state is never None + assert incremental_state is not None + incremental_state = self._set_input_buffer(incremental_state, saved_state) + assert k is not None + src_len = k.size(1) + + # This is part of a workaround to get around fork/join parallelism + # not supporting Optional types. + if key_padding_mask is not None and key_padding_mask.dim() == 0: + key_padding_mask = None + + if key_padding_mask is not None: + assert key_padding_mask.size(0) == bsz + assert key_padding_mask.size(1) == src_len + + if self.add_zero_attn: + assert v is not None + src_len += 1 + k = torch.cat([k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1) + v = torch.cat([v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1) + if attn_mask is not None: + attn_mask = torch.cat( + [attn_mask, attn_mask.new_zeros(attn_mask.size(0), 1)], dim=1 + ) + if key_padding_mask is not None: + key_padding_mask = torch.cat( + [ + key_padding_mask, + torch.zeros(key_padding_mask.size(0), 1).type_as( + key_padding_mask + ), + ], + dim=1, + ) + + attn_weights = torch.bmm(q, k.transpose(1, 2)) + attn_weights = self.apply_sparse_mask(attn_weights, tgt_len, src_len, bsz) + + assert list(attn_weights.size()) == [bsz * self.num_heads, tgt_len, src_len] + + if attn_mask is not None: + attn_mask = attn_mask.unsqueeze(0) + if self.onnx_trace: + attn_mask = attn_mask.repeat(attn_weights.size(0), 1, 1) + attn_weights += attn_mask + + if key_padding_mask is not None: + # don't attend to padding symbols + attn_weights = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) + if not self.tpu: + attn_weights = attn_weights.masked_fill( + key_padding_mask.unsqueeze(1).unsqueeze(2).to(torch.bool), + float("-inf"), + ) + else: + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.masked_fill(key_padding_mask, float("-inf")) + attn_weights = attn_weights.transpose(0, 2) + attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len) + + if before_softmax: + return attn_weights, v + + attn_weights_float = utils.softmax( + attn_weights, dim=-1, onnx_trace=self.onnx_trace + ) + attn_weights = attn_weights_float.type_as(attn_weights) + attn_probs = self.dropout_module(attn_weights) + + assert v is not None + attn = torch.bmm(attn_probs, v) + assert list(attn.size()) == [bsz * self.num_heads, tgt_len, self.head_dim] + if self.onnx_trace and attn.size(1) == 1: + # when ONNX tracing a single decoder step (sequence length == 1) + # the transpose is a no-op copy before view, thus unnecessary + attn = attn.contiguous().view(tgt_len, bsz, embed_dim) + else: + attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) + attn = self.out_proj(attn) + attn_weights: Optional[Tensor] = None + if need_weights: + attn_weights = attn_weights_float.view( + bsz, self.num_heads, tgt_len, src_len + ).transpose(1, 0) + if not need_head_weights: + # average attention weights over heads + attn_weights = attn_weights.mean(dim=0) + + return attn, attn_weights + + @staticmethod + def _append_prev_key_padding_mask( + key_padding_mask: Optional[Tensor], + prev_key_padding_mask: Optional[Tensor], + batch_size: int, + src_len: int, + static_kv: bool, + ) -> Optional[Tensor]: + # saved key padding masks have shape (bsz, seq_len) + if prev_key_padding_mask is not None and static_kv: + new_key_padding_mask = prev_key_padding_mask + elif prev_key_padding_mask is not None and key_padding_mask is not None: + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), key_padding_mask.float()], dim=1 + ) + # During incremental decoding, as the padding token enters and + # leaves the frame, there will be a time when prev or current + # is None + elif prev_key_padding_mask is not None: + filler = torch.zeros( + (batch_size, src_len - prev_key_padding_mask.size(1)), + device=prev_key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [prev_key_padding_mask.float(), filler.float()], dim=1 + ) + elif key_padding_mask is not None: + filler = torch.zeros( + (batch_size, src_len - key_padding_mask.size(1)), + device=key_padding_mask.device, + ) + new_key_padding_mask = torch.cat( + [filler.float(), key_padding_mask.float()], dim=1 + ) + else: + new_key_padding_mask = prev_key_padding_mask + return new_key_padding_mask + + @torch.jit.export + def reorder_incremental_state( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + new_order: Tensor, + ): + """Reorder buffered internal state (for incremental generation).""" + input_buffer = self._get_input_buffer(incremental_state) + if input_buffer is not None: + for k in input_buffer.keys(): + input_buffer_k = input_buffer[k] + if input_buffer_k is not None: + if self.encoder_decoder_attention and input_buffer_k.size( + 0 + ) == new_order.size(0): + break + input_buffer[k] = input_buffer_k.index_select(0, new_order) + incremental_state = self._set_input_buffer(incremental_state, input_buffer) + return incremental_state + + def _get_input_buffer( + self, incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] + ) -> Dict[str, Optional[Tensor]]: + result = self.get_incremental_state(incremental_state, "attn_state") + if result is not None: + return result + else: + empty_result: Dict[str, Optional[Tensor]] = {} + return empty_result + + def _set_input_buffer( + self, + incremental_state: Dict[str, Dict[str, Optional[Tensor]]], + buffer: Dict[str, Optional[Tensor]], + ): + return self.set_incremental_state(incremental_state, "attn_state", buffer) + + def apply_sparse_mask(self, attn_weights, tgt_len: int, src_len: int, bsz: int): + return attn_weights + + def upgrade_state_dict_named(self, state_dict, name): + prefix = name + "." if name != "" else "" + items_to_add = {} + keys_to_remove = [] + for k in state_dict.keys(): + if k.endswith(prefix + "in_proj_weight"): + # in_proj_weight used to be q + k + v with same dimensions + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.weight"] = state_dict[k][:dim] + items_to_add[prefix + "k_proj.weight"] = state_dict[k][dim : 2 * dim] + items_to_add[prefix + "v_proj.weight"] = state_dict[k][2 * dim :] + + keys_to_remove.append(k) + + k_bias = prefix + "in_proj_bias" + if k_bias in state_dict.keys(): + dim = int(state_dict[k].shape[0] / 3) + items_to_add[prefix + "q_proj.bias"] = state_dict[k_bias][:dim] + items_to_add[prefix + "k_proj.bias"] = state_dict[k_bias][ + dim : 2 * dim + ] + items_to_add[prefix + "v_proj.bias"] = state_dict[k_bias][2 * dim :] + + keys_to_remove.append(prefix + "in_proj_bias") + + for k in keys_to_remove: + del state_dict[k] + + for key, value in items_to_add.items(): + state_dict[key] = value diff --git a/fairseq-tools/fairseq/fairseq/modules/positional_embedding.py b/fairseq-tools/fairseq/fairseq/modules/positional_embedding.py new file mode 100644 index 00000000..8e94e35e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/positional_embedding.py @@ -0,0 +1,35 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn as nn + +from .learned_positional_embedding import LearnedPositionalEmbedding +from .sinusoidal_positional_embedding import SinusoidalPositionalEmbedding + + +def PositionalEmbedding( + num_embeddings: int, + embedding_dim: int, + padding_idx: int, + learned: bool = False, +): + if learned: + # if padding_idx is specified then offset the embedding ids by + # this index and adjust num_embeddings appropriately + # TODO: The right place for this offset would be inside + # LearnedPositionalEmbedding. Move this there for a cleaner implementation. + if padding_idx is not None: + num_embeddings = num_embeddings + padding_idx + 1 + m = LearnedPositionalEmbedding(num_embeddings, embedding_dim, padding_idx) + nn.init.normal_(m.weight, mean=0, std=embedding_dim ** -0.5) + if padding_idx is not None: + nn.init.constant_(m.weight[padding_idx], 0) + else: + m = SinusoidalPositionalEmbedding( + embedding_dim, + padding_idx, + init_size=num_embeddings + padding_idx + 1, + ) + return m diff --git a/fairseq-tools/fairseq/fairseq/modules/quant_noise.py b/fairseq-tools/fairseq/fairseq/modules/quant_noise.py new file mode 100644 index 00000000..d777dfbb --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quant_noise.py @@ -0,0 +1,107 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn + + +def quant_noise(module, p, block_size): + """ + Wraps modules and applies quantization noise to the weights for + subsequent quantization with Iterative Product Quantization as + described in "Training with Quantization Noise for Extreme Model Compression" + + Args: + - module: nn.Module + - p: amount of Quantization Noise + - block_size: size of the blocks for subsequent quantization with iPQ + + Remarks: + - Module weights must have the right sizes wrt the block size + - Only Linear, Embedding and Conv2d modules are supported for the moment + - For more detail on how to quantize by blocks with convolutional weights, + see "And the Bit Goes Down: Revisiting the Quantization of Neural Networks" + - We implement the simplest form of noise here as stated in the paper + which consists in randomly dropping blocks + """ + + # if no quantization noise, don't register hook + if p <= 0: + return module + + # supported modules + assert isinstance(module, (nn.Linear, nn.Embedding, nn.Conv2d)) + + # test whether module.weight has the right sizes wrt block_size + is_conv = module.weight.ndim == 4 + + # 2D matrix + if not is_conv: + assert ( + module.weight.size(1) % block_size == 0 + ), "Input features must be a multiple of block sizes" + + # 4D matrix + else: + # 1x1 convolutions + if module.kernel_size == (1, 1): + assert ( + module.in_channels % block_size == 0 + ), "Input channels must be a multiple of block sizes" + # regular convolutions + else: + k = module.kernel_size[0] * module.kernel_size[1] + assert k % block_size == 0, "Kernel size must be a multiple of block size" + + def _forward_pre_hook(mod, input): + # no noise for evaluation + if mod.training: + if not is_conv: + # gather weight and sizes + weight = mod.weight + in_features = weight.size(1) + out_features = weight.size(0) + + # split weight matrix into blocks and randomly drop selected blocks + mask = torch.zeros( + in_features // block_size * out_features, device=weight.device + ) + mask.bernoulli_(p) + mask = mask.repeat_interleave(block_size, -1).view(-1, in_features) + + else: + # gather weight and sizes + weight = mod.weight + in_channels = mod.in_channels + out_channels = mod.out_channels + + # split weight matrix into blocks and randomly drop selected blocks + if mod.kernel_size == (1, 1): + mask = torch.zeros( + int(in_channels // block_size * out_channels), + device=weight.device, + ) + mask.bernoulli_(p) + mask = mask.repeat_interleave(block_size, -1).view(-1, in_channels) + else: + mask = torch.zeros( + weight.size(0), weight.size(1), device=weight.device + ) + mask.bernoulli_(p) + mask = ( + mask.unsqueeze(2) + .unsqueeze(3) + .repeat(1, 1, mod.kernel_size[0], mod.kernel_size[1]) + ) + + # scale weights and apply mask + mask = mask.to( + torch.bool + ) # x.bool() is not currently supported in TorchScript + s = 1 / (1 - p) + mod.weight.data = s * weight.masked_fill(mask, 0) + + module.register_forward_pre_hook(_forward_pre_hook) + return module diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/__init__.py b/fairseq-tools/fairseq/fairseq/modules/quantization/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/__init__.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/__init__.py new file mode 100644 index 00000000..5b10b51b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .utils import SizeTracker, quantize_model_ # NOQA diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/em.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/em.py new file mode 100644 index 00000000..6f15c3e4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/em.py @@ -0,0 +1,211 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +import random +from collections import Counter + +import torch + + +class EM: + """ + EM algorithm used to quantize the columns of W to minimize + + ||W - W_hat||^2 + + Args: + - W: weight matrix of size (in_features x out_features) + - n_iter: number of k-means iterations + - n_centroids: number of centroids (size of codebook) + - eps: for cluster reassignment when an empty cluster is found + - max_tentatives for cluster reassignment when an empty cluster is found + - verbose: print error after each iteration + + Remarks: + - If one cluster is empty, the most populated cluster is split into + two clusters + - All the relevant dimensions are specified in the code + """ + + def __init__( + self, W, n_centroids=256, n_iter=20, eps=1e-6, max_tentatives=30, verbose=True + ): + self.W = W + self.n_centroids = n_centroids + self.n_iter = n_iter + self.eps = eps + self.max_tentatives = max_tentatives + self.verbose = verbose + self.centroids = torch.Tensor() + self.assignments = torch.Tensor() + self.objective = [] + + def initialize_centroids(self): + """ + Initializes the centroids by sampling random columns from W. + """ + + in_features, out_features = self.W.size() + indices = torch.randint( + low=0, high=out_features, size=(self.n_centroids,) + ).long() + self.centroids = self.W[:, indices].t() # (n_centroids x in_features) + + def step(self, i): + """ + There are two standard steps for each iteration: expectation (E) and + minimization (M). The E-step (assignment) is performed with an exhaustive + search and the M-step (centroid computation) is performed with + the exact solution. + + Args: + - i: step number + + Remarks: + - The E-step heavily uses PyTorch broadcasting to speed up computations + and reduce the memory overhead + """ + + # assignments (E-step) + distances = self.compute_distances() # (n_centroids x out_features) + self.assignments = torch.argmin(distances, dim=0) # (out_features) + n_empty_clusters = self.resolve_empty_clusters() + + # centroids (M-step) + for k in range(self.n_centroids): + W_k = self.W[:, self.assignments == k] # (in_features x size_of_cluster_k) + self.centroids[k] = W_k.mean(dim=1) # (in_features) + + # book-keeping + obj = (self.centroids[self.assignments].t() - self.W).norm(p=2).item() + self.objective.append(obj) + if self.verbose: + logging.info( + f"Iteration: {i},\t" + f"objective: {obj:.6f},\t" + f"resolved empty clusters: {n_empty_clusters}" + ) + + def resolve_empty_clusters(self): + """ + If one cluster is empty, the most populated cluster is split into + two clusters by shifting the respective centroids. This is done + iteratively for a fixed number of tentatives. + """ + + # empty clusters + counts = Counter(map(lambda x: x.item(), self.assignments)) + empty_clusters = set(range(self.n_centroids)) - set(counts.keys()) + n_empty_clusters = len(empty_clusters) + + tentatives = 0 + while len(empty_clusters) > 0: + # given an empty cluster, find most populated cluster and split it into two + k = random.choice(list(empty_clusters)) + m = counts.most_common(1)[0][0] + e = torch.randn_like(self.centroids[m]) * self.eps + self.centroids[k] = self.centroids[m].clone() + self.centroids[k] += e + self.centroids[m] -= e + + # recompute assignments + distances = self.compute_distances() # (n_centroids x out_features) + self.assignments = torch.argmin(distances, dim=0) # (out_features) + + # check for empty clusters + counts = Counter(map(lambda x: x.item(), self.assignments)) + empty_clusters = set(range(self.n_centroids)) - set(counts.keys()) + + # increment tentatives + if tentatives == self.max_tentatives: + logging.info( + f"Could not resolve all empty clusters, {len(empty_clusters)} remaining" + ) + raise EmptyClusterResolveError + tentatives += 1 + + return n_empty_clusters + + def compute_distances(self): + """ + For every centroid m, computes + + ||M - m[None, :]||_2 + + Remarks: + - We rely on PyTorch's broadcasting to speed up computations + and reduce the memory overhead + - Without chunking, the sizes in the broadcasting are modified as: + (n_centroids x n_samples x out_features) -> (n_centroids x out_features) + - The broadcasting computation is automatically chunked so that + the tensors fit into the memory of the GPU + """ + + nb_centroids_chunks = 1 + + while True: + try: + return torch.cat( + [ + (self.W[None, :, :] - centroids_c[:, :, None]).norm(p=2, dim=1) + for centroids_c in self.centroids.chunk( + nb_centroids_chunks, dim=0 + ) + ], + dim=0, + ) + except RuntimeError: + nb_centroids_chunks *= 2 + + def assign(self): + """ + Assigns each column of W to its closest centroid, thus essentially + performing the E-step in train(). + + Remarks: + - The function must be called after train() or after loading + centroids using self.load(), otherwise it will return empty tensors + """ + + distances = self.compute_distances() # (n_centroids x out_features) + self.assignments = torch.argmin(distances, dim=0) # (out_features) + + def save(self, path, layer): + """ + Saves centroids and assignments. + + Args: + - path: folder used to save centroids and assignments + """ + + torch.save(self.centroids, os.path.join(path, "{}_centroids.pth".format(layer))) + torch.save( + self.assignments, os.path.join(path, "{}_assignments.pth".format(layer)) + ) + torch.save(self.objective, os.path.join(path, "{}_objective.pth".format(layer))) + + def load(self, path, layer): + """ + Loads centroids and assignments from a given path + + Args: + - path: folder use to load centroids and assignments + """ + + self.centroids = torch.load( + os.path.join(path, "{}_centroids.pth".format(layer)) + ) + self.assignments = torch.load( + os.path.join(path, "{}_assignments.pth".format(layer)) + ) + self.objective = torch.load( + os.path.join(path, "{}_objective.pth".format(layer)) + ) + + +class EmptyClusterResolveError(Exception): + pass diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/__init__.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/__init__.py new file mode 100644 index 00000000..b67c8e8a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/__init__.py @@ -0,0 +1,8 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .qconv import PQConv2d # NOQA +from .qemb import PQEmbedding # NOQA +from .qlinear import PQLinear # NOQA diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qconv.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qconv.py new file mode 100644 index 00000000..d15ec192 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qconv.py @@ -0,0 +1,115 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch.nn.modules.utils import _pair + + +class PQConv2d(nn.Module): + """ + Quantized counterpart of nn.Conv2d module. Stores the centroid, the assignments + and the non-quantized biases. The full weight is re-instantiated at each forward + pass and autograd automatically computes the gradients with respect to the + centroids. + + Args: + - centroids: centroids of size n_centroids x block_size + - assignments: assignments of the centroids to the subvectors + of size self.out_channels x n_blocks + - bias: the non-quantized bias, must be either torch.Tensor or None + + Remarks: + - We refer the reader to the official documentation of the nn.Conv2d module + for the other arguments and the behavior of the module. + - Performance tests on GPU show that this implementation is 10% slower than + the non-quantized nn.Conv2d module for a standard training loop. + - During the backward, the gradients are averaged by cluster and not summed. + This explains the hook registered to the centroids. + """ + + def __init__( + self, + centroids, + assignments, + bias, + in_channels, + out_channels, + kernel_size, + stride=1, + padding=0, + dilation=1, + groups=1, + padding_mode="zeros", + ): + super(PQConv2d, self).__init__() + self.block_size = centroids.size(1) + self.n_centroids = centroids.size(0) + self.in_channels = in_channels + self.out_channels = out_channels + self.kernel_size = _pair(kernel_size) + self.stride = _pair(stride) + self.padding = _pair(padding) + self.dilation = _pair(dilation) + self.groups = groups + self.padding_mode = padding_mode + # check compatibility + if in_channels // groups * np.prod(self.kernel_size) % self.block_size != 0: + raise ValueError("Wrong PQ sizes") + if len(assignments) % out_channels != 0: + raise ValueError("Wrong PQ sizes") + if in_channels % groups != 0: + raise ValueError("in_channels must be divisible by groups") + if out_channels % groups != 0: + raise ValueError("out_channels must be divisible by groups") + # define parameters + self.centroids = nn.Parameter(centroids, requires_grad=True) + self.register_buffer("assignments", assignments) + self.register_buffer("counts", torch.bincount(assignments).type_as(centroids)) + if bias is not None: + self.bias = nn.Parameter(bias) + else: + self.register_parameter("bias", None) + # register hook for averaging gradients per centroids instead of summing + self.centroids.register_hook(lambda x: x / self.counts[:, None]) + + @property + def weight(self): + return ( + self.centroids[self.assignments] + .reshape(-1, self.out_channels, self.block_size) + .permute(1, 0, 2) + .reshape( + self.out_channels, self.in_channels // self.groups, *self.kernel_size + ) + ) + + def forward(self, x): + return F.conv2d( + x, + self.weight, + self.bias, + self.stride, + self.padding, + self.dilation, + self.groups, + ) + + def extra_repr(self): + s = "{in_channels}, {out_channels}, kernel_size={kernel_size}, stride={stride}" + if self.padding != (0,) * len(self.padding): + s += ", padding={padding}" + if self.dilation != (1,) * len(self.dilation): + s += ", dilation={dilation}" + if self.groups != 1: + s += ", groups={groups}" + if self.bias is None: + s += ", bias=False" + if self.padding_mode != "zeros": + s += ", padding_mode={padding_mode}" + s += ", n_centroids={n_centroids}, block_size={block_size}" + return s.format(**self.__dict__) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qemb.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qemb.py new file mode 100644 index 00000000..3a74ad3c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qemb.py @@ -0,0 +1,107 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class PQEmbedding(nn.Module): + """ + Quantized counterpart of nn.Embedding module. Stores the centroids and + the assignments. The full weight is re-instantiated at each forward + pass. + + Args: + - centroids: centroids of size n_centroids x block_size + - assignments: assignments of the centroids to the subvectors + of size self.out_features x n_blocks + - bias: the non-quantized bias + + Remarks: + - We refer the reader to the official documentation of the nn.Embedding module + for the other arguments and the behavior of the module + - Performance tests on GPU show that this implementation is 10% slower than + the non-quantized nn.Embedding module for a standard training loop. + """ + + def __init__( + self, + centroids, + assignments, + num_embeddings, + embedding_dim, + padding_idx=None, + max_norm=None, + norm_type=2.0, + scale_grad_by_freq=False, + sparse=False, + _weight=None, + ): + super(PQEmbedding, self).__init__() + self.block_size = centroids.size(1) + self.n_centroids = centroids.size(0) + self.num_embeddings = num_embeddings + self.embedding_dim = embedding_dim + if padding_idx is not None: + if padding_idx > 0: + assert ( + padding_idx < self.num_embeddings + ), "Padding_idx must be within num_embeddings" + elif padding_idx < 0: + assert ( + padding_idx >= -self.num_embeddings + ), "Padding_idx must be within num_embeddings" + padding_idx = self.num_embeddings + padding_idx + self.padding_idx = padding_idx + self.max_norm = max_norm + self.norm_type = norm_type + self.scale_grad_by_freq = scale_grad_by_freq + self.sparse = sparse + # check compatibility + if self.embedding_dim % self.block_size != 0: + raise ValueError("Wrong PQ sizes") + if len(assignments) % self.num_embeddings != 0: + raise ValueError("Wrong PQ sizes") + # define parameters + self.centroids = nn.Parameter(centroids, requires_grad=True) + self.register_buffer("assignments", assignments) + self.register_buffer("counts", torch.bincount(assignments).type_as(centroids)) + + @property + def weight(self): + return ( + self.centroids[self.assignments] + .reshape(-1, self.num_embeddings, self.block_size) + .permute(1, 0, 2) + .flatten(1, 2) + ) + + def forward(self, input): + return F.embedding( + input, + self.weight, + self.padding_idx, + self.max_norm, + self.norm_type, + self.scale_grad_by_freq, + self.sparse, + ) + + def extra_repr(self): + s = "{num_embeddings}, {embedding_dim}" + if self.padding_idx is not None: + s += ", padding_idx={padding_idx}" + if self.max_norm is not None: + s += ", max_norm={max_norm}" + if self.norm_type != 2: + s += ", norm_type={norm_type}" + if self.scale_grad_by_freq is not False: + s += ", scale_grad_by_freq={scale_grad_by_freq}" + if self.sparse is not False: + s += ", sparse=True" + s += ", n_centroids={n_centroids}, block_size={block_size}" + + return s.format(**self.__dict__) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qlinear.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qlinear.py new file mode 100644 index 00000000..9bdd25a8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/modules/qlinear.py @@ -0,0 +1,71 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +class PQLinear(nn.Module): + """ + Quantized counterpart of nn.Linear module. Stores the centroid, the assignments + and the non-quantized biases. The full weight is re-instantiated at each forward + pass. + + Args: + - centroids: centroids of size n_centroids x block_size + - assignments: assignments of the centroids to the subvectors + of size self.out_features x n_blocks + - bias: the non-quantized bias + + Remarks: + - We refer the reader to the official documentation of the nn.Linear module + for the other arguments and the behavior of the module + - Performance tests on GPU show that this implementation is 15% slower than + the non-quantized nn.Linear module for a standard training loop. + """ + + def __init__(self, centroids, assignments, bias, in_features, out_features): + super(PQLinear, self).__init__() + self.block_size = centroids.size(1) + self.n_centroids = centroids.size(0) + self.in_features = in_features + self.out_features = out_features + # check compatibility + if self.in_features % self.block_size != 0: + raise ValueError("Wrong PQ sizes") + if len(assignments) % self.out_features != 0: + raise ValueError("Wrong PQ sizes") + # define parameters + self.centroids = nn.Parameter(centroids, requires_grad=True) + self.register_buffer("assignments", assignments) + self.register_buffer("counts", torch.bincount(assignments).type_as(centroids)) + if bias is not None: + self.bias = nn.Parameter(bias) + else: + self.register_parameter("bias", None) + + @property + def weight(self): + return ( + self.centroids[self.assignments] + .reshape(-1, self.out_features, self.block_size) + .permute(1, 0, 2) + .flatten(1, 2) + ) + + def forward(self, x): + return F.linear( + x, + self.weight, + self.bias, + ) + + def extra_repr(self): + return f"in_features={self.in_features},\ + out_features={self.out_features},\ + n_centroids={self.n_centroids},\ + block_size={self.block_size},\ + bias={self.bias is not None}" diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/pq.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/pq.py new file mode 100644 index 00000000..eddc2eb3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/pq.py @@ -0,0 +1,128 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .em import EM, EmptyClusterResolveError + + +class PQ(EM): + """ + Quantizes the layer weights W with the standard Product Quantization + technique. This learns a codebook of codewords or centroids of size + block_size from W. For further reference on using PQ to quantize + neural networks, see "And the Bit Goes Down: Revisiting the Quantization + of Neural Networks", Stock et al., ICLR 2020. + + PQ is performed in two steps: + (1) The matrix W (weights or fully-connected or convolutional layer) + is reshaped to (block_size, -1). + - If W is fully-connected (2D), its columns are split into + blocks of size block_size. + - If W is convolutional (4D), its filters are split along the + spatial dimension. + (2) We apply the standard EM/k-means algorithm to the resulting reshaped matrix. + + Args: + - W: weight matrix to quantize of size (in_features x out_features) + - block_size: size of the blocks (subvectors) + - n_centroids: number of centroids + - n_iter: number of k-means iterations + - eps: for cluster reassignment when an empty cluster is found + - max_tentatives for cluster reassignment when an empty cluster is found + - verbose: print information after each iteration + + Remarks: + - block_size be compatible with the shape of W + """ + + def __init__( + self, + W, + block_size, + n_centroids=256, + n_iter=20, + eps=1e-6, + max_tentatives=30, + verbose=True, + ): + self.block_size = block_size + W_reshaped = self._reshape(W) + super(PQ, self).__init__( + W_reshaped, + n_centroids=n_centroids, + n_iter=n_iter, + eps=eps, + max_tentatives=max_tentatives, + verbose=verbose, + ) + + def _reshape(self, W): + """ + Reshapes the matrix W as expained in step (1). + """ + + # fully connected: by convention the weight has size out_features x in_features + if len(W.size()) == 2: + self.out_features, self.in_features = W.size() + assert ( + self.in_features % self.block_size == 0 + ), "Linear: n_blocks must be a multiple of in_features" + return ( + W.reshape(self.out_features, -1, self.block_size) + .permute(2, 1, 0) + .flatten(1, 2) + ) + + # convolutional: we reshape along the spatial dimension + elif len(W.size()) == 4: + self.out_channels, self.in_channels, self.k_h, self.k_w = W.size() + assert ( + self.in_channels * self.k_h * self.k_w + ) % self.block_size == 0, ( + "Conv2d: n_blocks must be a multiple of in_channels * k_h * k_w" + ) + return ( + W.reshape(self.out_channels, -1, self.block_size) + .permute(2, 1, 0) + .flatten(1, 2) + ) + # not implemented + else: + raise NotImplementedError(W.size()) + + def encode(self): + """ + Performs self.n_iter EM steps. + """ + + self.initialize_centroids() + for i in range(self.n_iter): + try: + self.step(i) + except EmptyClusterResolveError: + break + + def decode(self): + """ + Returns the encoded full weight matrix. Must be called after + the encode function. + """ + + # fully connected case + if "k_h" not in self.__dict__: + return ( + self.centroids[self.assignments] + .reshape(-1, self.out_features, self.block_size) + .permute(1, 0, 2) + .flatten(1, 2) + ) + + # convolutional case + else: + return ( + self.centroids[self.assignments] + .reshape(-1, self.out_channels, self.block_size) + .permute(1, 0, 2) + .reshape(self.out_channels, self.in_channels, self.k_h, self.k_w) + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/pq/utils.py b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/utils.py new file mode 100644 index 00000000..03b15e4b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/pq/utils.py @@ -0,0 +1,337 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import re +from operator import attrgetter, itemgetter + +import numpy as np +import torch.distributed as dist +import torch.nn as nn + +from .modules import PQConv2d, PQEmbedding, PQLinear +from .pq import PQ + + +def quantize_model_( + model, + size_tracker, + layers_to_quantize, + block_sizes_config, + n_centroids_config, + step=0, + n_iter=15, + eps=1e-6, + max_tentatives=100, + verbose=True, +): + """ + Quantize a model in-place by stages. All the targeted + layers are replaced by their quantized counterpart, + and the model is ready for the finetuning of the + centroids in a standard training loop (no modifications + required). Note that we do not quantize biases. + + Args: + - model: a nn.Module + - size_tracker: useful for tracking quatization statistics + - layers_to_quantize: a list containing regexps for + filtering the layers to quantize at each stage according + to their name (as in model.named_parameters()) + - block_sizes_config: dict like + { + 'Conv2d': ('kernel_size', {'(3, 3)': 9, '(1, 1)': 4}), + 'Linear': ('in_features', {'*': 8}) + } + For instance, all conv2d layers with kernel size 3x3 have + a block size of 9 and all Linear layers are quantized with + a block size of 8, irrespective of their size. + - n_centroids_config: dict like + { + 'Conv2d': ('kernel_size', {'*': 256}), + 'Linear': ('in_features', {'*': 256}) + } + For instance, all conv2d layers are quantized with 256 centroids + - step: the layers to quantize inplace corresponding + to layers_to_quantize[step] + """ + + quantized_layers = get_layers(model, layers_to_quantize[step]) + + for layer in quantized_layers: + + # book-keeping + is_master_process = (not dist.is_initialized()) or ( + dist.is_initialized() and dist.get_rank() == 0 + ) + verbose = verbose and is_master_process + + # get block size and centroids + module = attrgetter(layer)(model) + block_size = get_param(module, layer, block_sizes_config) + n_centroids = get_param(module, layer, n_centroids_config) + if verbose: + logging.info( + f"Quantizing layer {layer} with block size {block_size} and {n_centroids} centroids" + ) + + # quantize layer + weight = module.weight.data.clone() + is_bias = "bias" in [x[0] for x in module.named_parameters()] + bias = module.bias.data.clone() if is_bias else None + quantizer = PQ( + weight, + block_size, + n_centroids=n_centroids, + n_iter=n_iter, + eps=eps, + max_tentatives=max_tentatives, + verbose=verbose, + ) + + # quantization performed on all GPUs with same seed + quantizer.encode() + centroids = quantizer.centroids.contiguous() + assignments = quantizer.assignments.contiguous() + + # broadcast results to make sure weights are up-to-date + if dist.is_initialized(): + dist.broadcast(centroids, 0) + dist.broadcast(assignments, 0) + + # instantiate the quantized counterpart + if isinstance(module, nn.Linear): + out_features, in_features = map( + lambda k: module.__dict__[k], ["out_features", "in_features"] + ) + quantized_module = PQLinear( + centroids, assignments, bias, in_features, out_features + ) + elif isinstance(module, nn.Embedding): + num_embeddings, embedding_dim = map( + lambda k: module.__dict__[k], ["num_embeddings", "embedding_dim"] + ) + quantized_module = PQEmbedding( + centroids, assignments, num_embeddings, embedding_dim + ) + elif isinstance(module, nn.Conv2d): + out_channels, in_channels, kernel_size = map( + lambda k: module.__dict__[k], + ["out_channels", "in_channels", "kernel_size"], + ) + stride, padding, dilation, groups, padding_mode = map( + lambda k: module.__dict__[k], + ["stride", "padding", "dilation", "groups", "padding_mode"], + ) + + quantized_module = PQConv2d( + centroids, + assignments, + bias, + in_channels, + out_channels, + kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + padding_mode=padding_mode, + ) + else: + raise ValueError(f"Module {module} not yet supported for quantization") + + # replace layer by its quantized counterpart + attrsetter(layer)(model, quantized_module) + + # update statistics + size_tracker.update(weight, block_size, n_centroids) + + # return name of quantized layers + return quantized_layers + + +def get_layers(model, filter_regexp): + """ + Filters out the layers according to a regexp. Note that + we omit biases. + + Args: + - model: a nn.Module + - filter_regexp: a regexp to filter the layers to keep + according to their name in model.named_parameters(). + For instance, the regexp: + + down_layers\\.[123456]\\.(conv[12]|identity\\.conv)) + + is keeping blocks down_layers from 1 to 6, and inside + each block is keeping conv1, conv2 and identity.conv. + + Remarks: + - We add (module\\.)? at the beginning of the regexp to + account for the possible use of nn.parallel.DataParallel + """ + + # get all parameter names + all_layers = map(itemgetter(0), model.named_parameters()) + + # remove biases + all_layers = filter(lambda x: "bias" not in x, all_layers) + + # remove .weight in all other names (or .weight_orig is spectral norm) + all_layers = map(lambda x: x.replace(".weight_orig", ""), all_layers) + all_layers = map(lambda x: x.replace(".weight", ""), all_layers) + + # return filtered layers + filter_regexp = "(module\\.)?" + "(" + filter_regexp + ")" + r = re.compile(filter_regexp) + + return list(filter(r.match, all_layers)) + + +def get_param(module, layer_name, param_config): + """ + Given a quantization configuration, get the right parameter + for the module to be quantized. + + Args: + - module: a nn.Module + - layer_name: the name of the layer + - param_config: a dict like + { + 'Conv2d': ('kernel_size', {'(3, 3)': 9, '(1, 1)': 4}), + 'Linear': ('in_features', {'*': 8}) + } + For instance, all conv2d layers with kernel size 3x3 have + a block size of 9 and all Linear layers are quantized with + a block size of 8, irrespective of their size. + + Remarks: + - if 'fuzzy_name' is passed as a parameter, layers whose layer_name + include 'fuzzy_name' will be assigned the given parameter. + In the following example, conv.expand layers will have a block + size of 9 while conv.reduce will have a block size of 4 and all + other layers will have a block size of 2. + { + 'Conv2d': ('fuzzy_name', {'expand': 9, 'reduce': 4, '*': 2}), + 'Linear': ('fuzzy_name', {'classifier': 8, 'projection': 4}) + } + + """ + + layer_type = module.__class__.__name__ + + if layer_type not in param_config: + raise KeyError(f"Layer type {layer_type} not in config for layer {module}") + + feature, params = param_config[module.__class__.__name__] + + if feature != "fuzzy_name": + feature_value = str(getattr(module, feature)) + if feature_value not in params: + if "*" in params: + feature_value = "*" + else: + raise KeyError( + f"{feature}={feature_value} not in config for layer {module}" + ) + else: + feature_values = [name for name in params if name in layer_name] + if len(feature_values) == 0: + if "*" in params: + feature_value = "*" + else: + raise KeyError(f"name={layer_name} not in config for {module}") + else: + feature_value = feature_values[0] + + return params[feature_value] + + +class SizeTracker(object): + """ + Class to keep track of the compressed network size with iPQ. + + Args: + - model: a nn.Module + + Remarks: + - The compressed size is the sum of three components + for each layer in the network: + (1) Storing the centroids given by iPQ in fp16 + (2) Storing the assignments of the blocks in int8 + (3) Storing all non-compressed elements such as biases + - This cost in only valid if we use 256 centroids (then + indexing can indeed by done with int8). + """ + + def __init__(self, model): + self.model = model + self.size_non_compressed_model = self.compute_size() + self.size_non_quantized = self.size_non_compressed_model + self.size_index = 0 + self.size_centroids = 0 + self.n_quantized_layers = 0 + + def compute_size(self): + """ + Computes the size of the model (in MB). + """ + + res = 0 + for _, p in self.model.named_parameters(): + res += p.numel() + return res * 4 / 1024 / 1024 + + def update(self, W, block_size, n_centroids): + """ + Updates the running statistics when quantizing a new layer. + """ + + # bits per weights + bits_per_weight = np.log2(n_centroids) / block_size + self.n_quantized_layers += 1 + + # size of indexing the subvectors of size block_size (in MB) + size_index_layer = bits_per_weight * W.numel() / 8 / 1024 / 1024 + self.size_index += size_index_layer + + # size of the centroids stored in float16 (in MB) + size_centroids_layer = n_centroids * block_size * 2 / 1024 / 1024 + self.size_centroids += size_centroids_layer + + # size of non-compressed layers, e.g. LayerNorms or biases (in MB) + size_uncompressed_layer = W.numel() * 4 / 1024 / 1024 + self.size_non_quantized -= size_uncompressed_layer + + def __repr__(self): + size_compressed = ( + self.size_index + self.size_centroids + self.size_non_quantized + ) + compression_ratio = self.size_non_compressed_model / size_compressed # NOQA + return ( + f"Non-compressed model size: {self.size_non_compressed_model:.2f} MB. " + f"After quantizing {self.n_quantized_layers} layers, size " + f"(indexing + centroids + other): {self.size_index:.2f} MB + " + f"{self.size_centroids:.2f} MB + {self.size_non_quantized:.2f} MB = " + f"{size_compressed:.2f} MB, compression ratio: {compression_ratio:.2f}x" + ) + + +def attrsetter(*items): + def resolve_attr(obj, attr): + attrs = attr.split(".") + head = attrs[:-1] + tail = attrs[-1] + + for name in head: + obj = getattr(obj, name) + return obj, tail + + def g(obj, val): + for attr in items: + resolved_obj, resolved_attr = resolve_attr(obj, attr) + setattr(resolved_obj, resolved_attr, val) + + return g diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/quantization_options.py b/fairseq-tools/fairseq/fairseq/modules/quantization/quantization_options.py new file mode 100644 index 00000000..b46d682c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/quantization_options.py @@ -0,0 +1,44 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +def parse_config_yaml(yaml_data): + # Initialize to default options. + quantization_options = { + "n_centroids": { + "Linear": ["in_features", {"*": 256}], + "Embedding": ["embedding_dim", {"*": 256}], + }, + "block_sizes": { + "Linear": ["fuzzy_name", {"fc": 8, "attn": 4, "emb": 4}], + "Embedding": ["fuzzy_name", {"emb": 8}], + }, + "layers_to_quantize": [ + "decoder\\.layers\\.\\d+\\.fc[12]", + "decoder\\.embed_tokens\\.embeddings\\.[012]\\.[01]", + "decoder\\.layers\\.\\d+\\.self_attn\\.(k_proj|v_proj|q_proj|out_proj)", + ], + } + + if "n_centroids" in yaml_data: + quantization_options["n_centroids"] = { + layer: convert_yaml_to_tuple(layer_data) + for layer, layer_data in yaml_data["n_centroids"].items() + } + if "block_sizes" in yaml_data: + quantization_options["block_sizes"] = { + layer: convert_yaml_to_tuple(layer_data) + for layer, layer_data in yaml_data["block_sizes"].items() + } + if "layers_to_quantize" in yaml_data: + quantization_options["layers_to_quantize"] = yaml_data["layers_to_quantize"] + + return quantization_options + + +def convert_yaml_to_tuple(yaml_dictionary): + """Converts a yaml dictionary with two keys: `key` and `value` into a two + argument tuple of those values.""" + return (yaml_dictionary["key"], yaml_dictionary["value"]) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/__init__.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/__init__.py new file mode 100644 index 00000000..143834f3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/__init__.py @@ -0,0 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .utils import quantize_model_ # NOQA diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/__init__.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/__init__.py new file mode 100644 index 00000000..8031d9cd --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/__init__.py @@ -0,0 +1,9 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from .qact import ActivationQuantizer # NOQA +from .qconv import IntConv2d # NOQA +from .qemb import IntEmbedding # NOQA +from .qlinear import IntLinear # NOQA diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qact.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qact.py new file mode 100644 index 00000000..c5dd1d63 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qact.py @@ -0,0 +1,88 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + +from ..ops import emulate_int + + +class ActivationQuantizer: + """ + Fake scalar quantization of the activations using a forward hook. + + Args: + - module. a nn.Module for which we quantize the *post-activations* + - p: proportion of activations to quantize, set by default to 1 + - update_step: to recompute quantization parameters + - bits: number of bits for quantization + - method: choose among {"tensor", "histogram", "channel"} + - clamp_threshold: to prevent gradients overflow + + Remarks: + - Parameters scale and zero_point are recomputed every update_step + forward pass to reduce the overhead + - For the list of quantization methods and number of bits, see ops.py + - To remove the hook from the module, simply call self.handle.remove() + - At test time, the activations are fully quantized + - We use the straight-through estimator so that the gradients + back-propagate nicely in the network, this is implemented with + the detach() trick + - The activations are hard-clamped in [-clamp_threshold, clamp_threshold] + to prevent overflow during the backward pass + """ + + def __init__( + self, + module, + p=1, + update_step=1000, + bits=8, + method="histogram", + clamp_threshold=5, + ): + self.module = module + self.p = p + self.update_step = update_step + self.counter = 0 + self.bits = bits + self.method = method + self.clamp_threshold = clamp_threshold + self.handle = None + self.register_hook() + + def register_hook(self): + # forward hook + def quantize_hook(module, x, y): + + # update parameters every 1000 iterations + if self.counter % self.update_step == 0: + self.scale = None + self.zero_point = None + self.counter += 1 + + # train with QuantNoise and evaluate the fully quantized network + p = self.p if self.module.training else 1 + + # quantize activations + y_q, self.scale, self.zero_point = emulate_int( + y.detach(), + bits=self.bits, + method=self.method, + scale=self.scale, + zero_point=self.zero_point, + ) + + # mask to apply noise + mask = torch.zeros_like(y) + mask.bernoulli_(1 - p) + noise = (y_q - y).masked_fill(mask.bool(), 0) + + # using straight-through estimator (STE) + clamp_low = -self.scale * self.zero_point + clamp_high = self.scale * (2 ** self.bits - 1 - self.zero_point) + return torch.clamp(y, clamp_low.item(), clamp_high.item()) + noise.detach() + + # register hook + self.handle = self.module.register_forward_hook(quantize_hook) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qconv.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qconv.py new file mode 100644 index 00000000..83788c6f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qconv.py @@ -0,0 +1,149 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn.functional as F +from torch.nn.modules.conv import _ConvNd +from torch.nn.modules.utils import _pair + +from ..ops import emulate_int + + +class IntConv2d(_ConvNd): + """ + Quantized counterpart of the nn.Conv2d module that applies QuantNoise during training. + + Args: + - standard nn.Conv2d parameters + - p: amount of noise to inject (0 = no quantization, 1 = quantize all the weights) + - bits: number of bits + - method: choose among {"tensor", "histogram", "channel"} + - update_step: recompute scale and zero_point every update_steps iterations + + Remarks: + - We use the straight-thgourh estimator so that the gradients + back-propagate nicely in the network, this is implemented with + the detach() trick + - Parameters scale and zero_point are recomputed every update_step + forward pass to reduce the overhead + - At test time, the weights are fully quantized + """ + + def __init__( + self, + in_channels, + out_channels, + kernel_size, + stride=1, + padding=0, + dilation=1, + groups=1, + bias=True, + padding_mode="zeros", + p=0, + bits=8, + method="histogram", + update_step=1000, + ): + kernel_size = _pair(kernel_size) + stride = _pair(stride) + padding = _pair(padding) + dilation = _pair(dilation) + super(IntConv2d, self).__init__( + in_channels, + out_channels, + kernel_size, + stride, + padding, + dilation, + False, + _pair(0), + groups, + bias, + padding_mode, + ) + + # quantization parameters + self.p = p + self.bits = bits + self.method = method + self.update_step = update_step + self.counter = 0 + + def _conv_forward(self, input, weight): + if self.padding_mode != "zeros": + return F.conv2d( + F.pad(input, self._padding_repeated_twice, mode=self.padding_mode), + weight, + self.bias, + self.stride, + _pair(0), + self.dilation, + self.groups, + ) + return F.conv2d( + input, + weight, + self.bias, + self.stride, + self.padding, + self.dilation, + self.groups, + ) + + def forward(self, input): + # train with QuantNoise and evaluate the fully quantized network + p = self.p if self.training else 1 + + # update parameters every 100 iterations + if self.counter % self.update_step == 0: + self.scale = None + self.zero_point = None + self.counter += 1 + + # quantize weight + weight_quantized, self.scale, self.zero_point = emulate_int( + self.weight.detach(), + bits=self.bits, + method=self.method, + scale=self.scale, + zero_point=self.zero_point, + ) + + # mask to apply noise + mask = torch.zeros_like(self.weight) + mask.bernoulli_(1 - p) + noise = (weight_quantized - self.weight).masked_fill(mask.bool(), 0) + + # using straight-through estimator (STE) + clamp_low = -self.scale * self.zero_point + clamp_high = self.scale * (2 ** self.bits - 1 - self.zero_point) + weight = ( + torch.clamp(self.weight, clamp_low.item(), clamp_high.item()) + + noise.detach() + ) + + # return output + output = self._conv_forward(input, weight) + return output + + def extra_repr(self): + return ( + "in_channels={}, out_channels={}, kernel_size={}, stride={}, " + "padding={}, dilation={}, groups={}, bias={}, quant_noise={}, " + "bits={}, method={}".format( + self.in_channels, + self.out_channels, + self.kernel_size, + self.stride, + self.padding, + self.dilation, + self.groups, + self.bias is not None, + self.p, + self.bits, + self.method, + ) + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qemb.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qemb.py new file mode 100644 index 00000000..d6cf06e5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qemb.py @@ -0,0 +1,147 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from ..ops import emulate_int + + +class IntEmbedding(nn.Module): + """ + Quantized counterpart of the nn.Embedding module that applies QuantNoise during training. + + Args: + - num_embeddings: number of tokens + - embedding_dim: embedding dimension + - p: amount of noise to inject (0 = no quantization, 1 = quantize all the weights) + - bits: number of bits + - method: choose among {"tensor", "histogram", "channel"} + - update_step: recompute scale and zero_point every update_steps iterations + + Remarks: + - We use the straight-through estimator so that the gradients + back-propagate nicely in the network, this is implemented with + the detach() trick + - Parameters scale and zero_point are recomputed every update_step + forward pass to reduce the overhead + - At test time, the weights are fully quantized + """ + + def __init__( + self, + num_embeddings, + embedding_dim, + padding_idx=None, + max_norm=None, + norm_type=2.0, + scale_grad_by_freq=False, + sparse=False, + _weight=None, + p=0, + update_step=1000, + bits=8, + method="histogram", + ): + super(IntEmbedding, self).__init__() + self.num_embeddings = num_embeddings + self.embedding_dim = embedding_dim + if padding_idx is not None: + if padding_idx > 0: + assert ( + padding_idx < self.num_embeddings + ), "Padding_idx must be within num_embeddings" + elif padding_idx < 0: + assert ( + padding_idx >= -self.num_embeddings + ), "Padding_idx must be within num_embeddings" + padding_idx = self.num_embeddings + padding_idx + self.padding_idx = padding_idx + self.max_norm = max_norm + self.norm_type = norm_type + self.scale_grad_by_freq = scale_grad_by_freq + if _weight is None: + self.weight = nn.Parameter(torch.Tensor(num_embeddings, embedding_dim)) + self.reset_parameters() + else: + assert list(_weight.shape) == [ + num_embeddings, + embedding_dim, + ], "Shape of weight does not match num_embeddings and embedding_dim" + self.weight = nn.Parameter(_weight) + self.sparse = sparse + + # quantization parameters + self.p = p + self.bits = bits + self.method = method + self.update_step = update_step + self.counter = 0 + + def reset_parameters(self): + nn.init.normal_(self.weight) + if self.padding_idx is not None: + with torch.no_grad(): + self.weight[self.padding_idx].fill_(0) + + def forward(self, input): + # train with QuantNoise and evaluate the fully quantized network + p = self.p if self.training else 1 + + # update parameters every 1000 iterations + if self.counter % self.update_step == 0: + self.scale = None + self.zero_point = None + self.counter += 1 + + # quantize weight + weight_quantized, self.scale, self.zero_point = emulate_int( + self.weight.detach(), + bits=self.bits, + method=self.method, + scale=self.scale, + zero_point=self.zero_point, + ) + + # mask to apply noise + mask = torch.zeros_like(self.weight) + mask.bernoulli_(1 - p) + noise = (weight_quantized - self.weight).masked_fill(mask.bool(), 0) + + # using straight-through estimator (STE) + clamp_low = -self.scale * self.zero_point + clamp_high = self.scale * (2 ** self.bits - 1 - self.zero_point) + weight = ( + torch.clamp(self.weight, clamp_low.item(), clamp_high.item()) + + noise.detach() + ) + + # return output + output = F.embedding( + input, + weight, + self.padding_idx, + self.max_norm, + self.norm_type, + self.scale_grad_by_freq, + self.sparse, + ) + return output + + def extra_repr(self): + s = "{num_embeddings}, {embedding_dim}" + if self.padding_idx is not None: + s += ", padding_idx={padding_idx}" + if self.max_norm is not None: + s += ", max_norm={max_norm}" + if self.norm_type != 2: + s += ", norm_type={norm_type}" + if self.scale_grad_by_freq is not False: + s += ", scale_grad_by_freq={scale_grad_by_freq}" + if self.sparse is not False: + s += ", sparse=True" + s += "quant_noise={p}, bits={bits}, method={method}" + return s.format(**self.__dict__) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qlinear.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qlinear.py new file mode 100644 index 00000000..9db15593 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/modules/qlinear.py @@ -0,0 +1,113 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from ..ops import emulate_int + + +class IntLinear(nn.Module): + """ + Quantized counterpart of the nn.Linear module that applies QuantNoise during training. + + Args: + - in_features: input features + - out_features: output features + - bias: bias or not + - p: amount of noise to inject (0 = no quantization, 1 = quantize all the weights) + - bits: number of bits + - method: choose among {"tensor", "histogram", "channel"} + - update_step: recompute scale and zero_point every update_steps iterations + + Remarks: + - We use the straight-through estimator so that the gradients + back-propagate nicely in the network, this is implemented with + the detach() trick. + - Parameters scale and zero_point are recomputed every update_step + forward pass to reduce the overhead + - At test time, the weights are fully quantized + """ + + def __init__( + self, + in_features, + out_features, + bias=True, + p=0, + update_step=3000, + bits=8, + method="histogram", + ): + super(IntLinear, self).__init__() + self.in_features = int(in_features) + self.out_features = int(out_features) + self.weight = torch.nn.Parameter(torch.Tensor(out_features, in_features)) + self.chosen_bias = bias + if self.chosen_bias: + self.bias = torch.nn.Parameter(torch.Tensor(out_features)) + else: + self.register_parameter("bias", None) + self.reset_parameters() + + # quantization parameters + self.p = p + self.bits = bits + self.method = method + self.update_step = update_step + self.counter = 0 + + def reset_parameters(self): + nn.init.xavier_uniform_(self.weight) + if self.chosen_bias: + nn.init.constant_(self.bias, 0.0) + return + + def forward(self, input): + # train with QuantNoise and evaluate the fully quantized network + p = self.p if self.training else 1 + + # update parameters every 100 iterations + if self.counter % self.update_step == 0: + self.scale = None + self.zero_point = None + self.counter += 1 + + # quantize weight + weight_quantized, self.scale, self.zero_point = emulate_int( + self.weight.detach(), + bits=self.bits, + method=self.method, + scale=self.scale, + zero_point=self.zero_point, + ) + + # mask to apply noise + mask = torch.zeros_like(self.weight) + mask.bernoulli_(1 - p) + noise = (weight_quantized - self.weight).masked_fill(mask.bool(), 0) + + # using straight-through estimator (STE) + clamp_low = -self.scale * self.zero_point + clamp_high = self.scale * (2 ** self.bits - 1 - self.zero_point) + weight = ( + torch.clamp(self.weight, clamp_low.item(), clamp_high.item()) + + noise.detach() + ) + + # return output + output = F.linear(input, weight, self.bias) + return output + + def extra_repr(self): + return "in_features={}, out_features={}, bias={}, quant_noise={}, bits={}, method={}".format( + self.in_features, + self.out_features, + self.bias is not None, + self.p, + self.bits, + self.method, + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/ops.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/ops.py new file mode 100644 index 00000000..2a855159 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/ops.py @@ -0,0 +1,49 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch + + +def emulate_int(w, bits, method, scale=None, zero_point=None): + q = globals()[f"emulate_int{bits}_{method}"] + return q(w, scale=scale, zero_point=zero_point) + + +def quantize(w, scale, zero_point): + return ( + torch.clamp(torch.round(w / scale + zero_point), 0, 255) - zero_point + ) * scale + + +def emulate_int8_histogram(w, scale=None, zero_point=None): + if scale is None: + obs = torch.quantization.observer.HistogramObserver() + _ = obs(w.float()) + scale, zero_point = obs.calculate_qparams() + scale = scale.cuda().type_as(w) + zero_point = zero_point.cuda().type_as(w) + return quantize(w, scale, zero_point), scale, zero_point + + +def emulate_int8_channel(w, scale=None, zero_point=None): + if scale is None: + obs = torch.quantization.observer.PerChannelMinMaxObserver( + ch_axis=-1, qscheme=torch.per_channel_symmetric + ) + _ = obs(w) + scale, zero_point, ch_axis = obs.get_qparams() + scale = scale.cuda().type_as(w) + zero_point = zero_point.cuda().type_as(w) + return quantize(w, scale, zero_point), scale, zero_point + + +def emulate_int8_tensor(w, scale=None, zero_point=None): + if scale is None: + obs = torch.quantization.observer.MinMaxObserver() + _ = obs(w) + scale, zero_point = obs.calculate_qparams() + scale = scale.cuda().type_as(w) + zero_point = zero_point.cuda().type_as(w) + return quantize(w, scale, zero_point), scale, zero_point diff --git a/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/utils.py b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/utils.py new file mode 100644 index 00000000..32cf6165 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/quantization/scalar/utils.py @@ -0,0 +1,77 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +from operator import attrgetter + +import torch.distributed as dist +import torch.nn as nn + +from ..pq.utils import attrsetter, get_layers +from .modules import ActivationQuantizer, IntConv2d, IntEmbedding, IntLinear + + +MAPPING = {nn.Linear: IntLinear, nn.Embedding: IntEmbedding, nn.Conv2d: IntConv2d} + + +def quantize_model_(model, p=0.2, bits=8, update_step=3000): + """ + Replaces all modules with their scalar quantized counterpart and + registers hooks to quantize the post-ativations of those modules. + + Args: + - model: a nn.Module + - p: amount of noise (0 for no noise, 1 to quantize all the weights/activations) + - bits: number of bits + - update_step: update quantization parameters every update_step steps + """ + + # quantize all layers + quantized_layers = get_layers(model, "(.*?)") + + for layer in quantized_layers: + + # book-keeping + is_master_process = (not dist.is_initialized()) or ( + dist.is_initialized() and dist.get_rank() == 0 + ) + + # recover module + module = attrgetter(layer)(model) + if is_master_process: + logging.info( + f"Quantizing layer {layer} with bits={bits} and QuantNoise={p}" + ) + + # quantization params + q_params = { + "p": p, + "update_step": update_step, + "bits": bits, + "method": "histogram", + "counter": 0, + } + + # instantiate the quantized counterpart + if isinstance(module, tuple(MAPPING.keys())): + QuantizedModule = MAPPING[module.__class__] + quantized_module = QuantizedModule.__new__(QuantizedModule) + params = module.__dict__ + params.update(q_params) + quantized_module.__dict__.update(params) + + else: + if is_master_process: + logging.info(f"Module {module} not yet supported for quantization") + continue + + # activation quantization + a_q = ActivationQuantizer(quantized_module, p=0, bits=bits, method="histogram") + + # replace layer by its quantized counterpart + attrsetter(layer)(model, quantized_module) + + # return name of quantized layers + return quantized_layers diff --git a/fairseq-tools/fairseq/fairseq/modules/same_pad.py b/fairseq-tools/fairseq/fairseq/modules/same_pad.py new file mode 100644 index 00000000..b46f94d6 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/same_pad.py @@ -0,0 +1,18 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +from torch import nn + + +class SamePad(nn.Module): + def __init__(self, kernel_size): + super().__init__() + self.remove = kernel_size % 2 == 0 + + def forward(self, x): + if self.remove: + x = x[:, :, :-1] + return x diff --git a/fairseq-tools/fairseq/fairseq/modules/scalar_bias.py b/fairseq-tools/fairseq/fairseq/modules/scalar_bias.py new file mode 100644 index 00000000..c96247c7 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/scalar_bias.py @@ -0,0 +1,31 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# + +import torch + + +class ScalarBias(torch.autograd.Function): + """ + Adds a vector of scalars, used in self-attention mechanism to allow + the model to optionally attend to this vector instead of the past + """ + + @staticmethod + def forward(ctx, input, dim, bias_init): + size = list(input.size()) + size[dim] += 1 + output = input.new(*size).fill_(bias_init) + output.narrow(dim, 1, size[dim] - 1).copy_(input) + ctx.dim = dim + return output + + @staticmethod + def backward(ctx, grad): + return grad.narrow(ctx.dim, 1, grad.size(ctx.dim) - 1), None, None + + +def scalar_bias(input, dim, bias_init=0): + return ScalarBias.apply(input, dim, bias_init) diff --git a/fairseq-tools/fairseq/fairseq/modules/sinusoidal_positional_embedding.py b/fairseq-tools/fairseq/fairseq/modules/sinusoidal_positional_embedding.py new file mode 100644 index 00000000..857830fa --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/sinusoidal_positional_embedding.py @@ -0,0 +1,105 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Any, Optional + +import torch +import torch.onnx.operators +from fairseq import utils +from torch import Tensor, nn + + +class SinusoidalPositionalEmbedding(nn.Module): + """This module produces sinusoidal positional embeddings of any length. + + Padding symbols are ignored. + """ + + def __init__(self, embedding_dim, padding_idx, init_size=1024): + super().__init__() + self.embedding_dim = embedding_dim + self.padding_idx = padding_idx + self.weights = SinusoidalPositionalEmbedding.get_embedding( + init_size, embedding_dim, padding_idx + ) + self.onnx_trace = False + self.register_buffer("_float_tensor", torch.FloatTensor(1)) + self.max_positions = int(1e5) + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + @staticmethod + def get_embedding( + num_embeddings: int, embedding_dim: int, padding_idx: Optional[int] = None + ): + """Build sinusoidal embeddings. + + This matches the implementation in tensor2tensor, but differs slightly + from the description in Section 3.5 of "Attention Is All You Need". + """ + half_dim = embedding_dim // 2 + emb = math.log(10000) / (half_dim - 1) + emb = torch.exp(torch.arange(half_dim, dtype=torch.float) * -emb) + emb = torch.arange(num_embeddings, dtype=torch.float).unsqueeze( + 1 + ) * emb.unsqueeze(0) + emb = torch.cat([torch.sin(emb), torch.cos(emb)], dim=1).view( + num_embeddings, -1 + ) + if embedding_dim % 2 == 1: + # zero pad + emb = torch.cat([emb, torch.zeros(num_embeddings, 1)], dim=1) + if padding_idx is not None: + emb[padding_idx, :] = 0 + return emb + + def forward( + self, + input, + incremental_state: Optional[Any] = None, + timestep: Optional[Tensor] = None, + positions: Optional[Any] = None, + ): + """Input is expected to be of size [bsz x seqlen].""" + bspair = torch.onnx.operators.shape_as_tensor(input) + bsz, seq_len = bspair[0], bspair[1] + max_pos = self.padding_idx + 1 + seq_len + if self.weights is None or max_pos > self.weights.size(0): + # recompute/expand embeddings if needed + self.weights = SinusoidalPositionalEmbedding.get_embedding( + max_pos, self.embedding_dim, self.padding_idx + ) + self.weights = self.weights.to(self._float_tensor) + + if incremental_state is not None: + # positions is the same for every token when decoding a single step + pos = timestep.view(-1)[0] + 1 if timestep is not None else seq_len + if self.onnx_trace: + return ( + self.weights.index_select(index=self.padding_idx + pos, dim=0) + .unsqueeze(1) + .repeat(bsz, 1, 1) + ) + return self.weights[self.padding_idx + pos, :].expand(bsz, 1, -1) + + positions = utils.make_positions( + input, self.padding_idx, onnx_trace=self.onnx_trace + ) + if self.onnx_trace: + flat_embeddings = self.weights.detach().index_select(0, positions.view(-1)) + embedding_shape = torch.cat( + (bsz.view(1), seq_len.view(1), torch.tensor([-1], dtype=torch.long)) + ) + embeddings = torch.onnx.operators.reshape_from_tensor_shape( + flat_embeddings, embedding_shape + ) + return embeddings + return ( + self.weights.index_select(0, positions.view(-1)) + .view(bsz, seq_len, -1) + .detach() + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/sparse_multihead_attention.py b/fairseq-tools/fairseq/fairseq/modules/sparse_multihead_attention.py new file mode 100644 index 00000000..3cbd9d67 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/sparse_multihead_attention.py @@ -0,0 +1,140 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch + +from .multihead_attention import MultiheadAttention + + +class SparseMultiheadAttention(MultiheadAttention): + """Sparse Multi-Headed Attention. + + "Generating Long Sequences with Sparse Transformers". Implements + fixed factorized self attention, where l=stride and c=expressivity. + A(1) includes all words in the stride window and A(2) takes a summary of c + words from the end of each stride window. + If is_bidirectional=False, we do not include any words past the current word, + as in the paper. + """ + + def __init__( + self, + embed_dim, + num_heads, + kdim=None, + vdim=None, + dropout=0.0, + bias=True, + add_bias_kv=False, + add_zero_attn=False, + self_attention=False, + encoder_decoder_attention=False, + stride=32, + expressivity=8, + is_bidirectional=True, + ): + + super().__init__( + embed_dim, + num_heads, + kdim, + vdim, + dropout, + bias, + add_bias_kv, + add_zero_attn, + self_attention, + encoder_decoder_attention, + ) + + self.is_bidirectional = is_bidirectional + self.stride = stride + self.expressivity = expressivity + assert self.stride > 0 and self.stride >= self.expressivity + + # Used for Ai(2) calculations - beginning of [l-c, l] range + def compute_checkpoint(self, word_index): + if word_index % self.stride == 0 and word_index != 0: + checkpoint_index = word_index - self.expressivity + else: + checkpoint_index = ( + math.floor(word_index / self.stride) * self.stride + + self.stride + - self.expressivity + ) + return checkpoint_index + + # Computes Ai(2) + def compute_subset_summaries(self, absolute_max): + checkpoint_index = self.compute_checkpoint(0) + subset_two = set() + while checkpoint_index <= absolute_max - 1: + summary = set( + range( + checkpoint_index, + min(checkpoint_index + self.expressivity + 1, absolute_max), + ) + ) + subset_two = subset_two.union(summary) + checkpoint_index = self.compute_checkpoint(checkpoint_index + self.stride) + return subset_two + + # Sparse Transformer Fixed Attention Pattern: https://arxiv.org/pdf/1904.10509.pdf + def compute_fixed_attention_subset(self, word_index, tgt_len): + # +1s account for range function; [min, max) -> [min, max] + if not self.is_bidirectional: + absolute_max = word_index + 1 + else: + absolute_max = tgt_len + + # Subset 1 - whole window + rounded_index = ( + math.floor((word_index + self.stride) / self.stride) * self.stride + ) + if word_index % self.stride == 0 and word_index != 0: + subset_one = set( + range(word_index - self.stride, min(absolute_max, word_index + 1)) + ) + else: + subset_one = set( + range( + max(0, rounded_index - self.stride), + min(absolute_max, rounded_index + 1), + ) + ) + + # Subset 2 - summary per window + # If bidirectional, subset 2 is the same for every index + subset_two = set() + if not self.is_bidirectional: + subset_two = self.compute_subset_summaries(absolute_max) + + return subset_one.union(subset_two) + + # Compute sparse mask - if bidirectional, can pre-compute and store + def buffered_sparse_mask(self, tensor, tgt_len, src_len): + assert tgt_len > self.stride + sparse_mask = torch.empty((tgt_len, src_len)).float().fill_(float("-inf")) + + # If bidirectional, subset 2 is the same for every index + subset_summaries = set() + if self.is_bidirectional: + subset_summaries = self.compute_subset_summaries(tgt_len) + + for i in range(tgt_len): + fixed_attention_subset = self.compute_fixed_attention_subset(i, tgt_len) + fixed_attention_subset = fixed_attention_subset.union(subset_summaries) + included_word_indices = torch.LongTensor(list(fixed_attention_subset)) + sparse_mask[i].index_fill_(0, included_word_indices, 0) + return sparse_mask.type_as(tensor) + + def apply_sparse_mask(self, attn_weights, tgt_len, src_len, bsz): + sparse_mask = self.buffered_sparse_mask(attn_weights, tgt_len, src_len) + sparse_mask = sparse_mask.unsqueeze(0).expand( + bsz * self.num_heads, tgt_len, src_len + ) + attn_weights += sparse_mask diff --git a/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder.py b/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder.py new file mode 100644 index 00000000..f41ec093 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder.py @@ -0,0 +1,96 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn as nn +from fairseq.modules import TransformerSentenceEncoder +from fairseq.modules.sparse_transformer_sentence_encoder_layer import ( + SparseTransformerSentenceEncoderLayer, +) + + +class SparseTransformerSentenceEncoder(TransformerSentenceEncoder): + """ + Sparse implementation of the TransformerSentenceEncoder + - see SparseMultiheadAttention + """ + + def __init__( + self, + padding_idx: int, + vocab_size: int, + num_encoder_layers: int = 6, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + max_seq_len: int = 256, + num_segments: int = 2, + use_position_embeddings: bool = True, + offset_positions_by_padding: bool = True, + encoder_normalize_before: bool = False, + apply_bert_init: bool = False, + activation_fn: str = "relu", + learned_pos_embedding: bool = True, + embed_scale: float = None, + freeze_embeddings: bool = False, + n_trans_layers_to_freeze: int = 0, + export: bool = False, + is_bidirectional: bool = True, + stride: int = 32, + expressivity: int = 8, + ) -> None: + + super().__init__( + padding_idx, + vocab_size, + num_encoder_layers, + embedding_dim, + ffn_embedding_dim, + num_attention_heads, + dropout, + attention_dropout, + activation_dropout, + max_seq_len, + num_segments, + use_position_embeddings, + offset_positions_by_padding, + encoder_normalize_before, + apply_bert_init, + activation_fn, + learned_pos_embedding, + embed_scale, + freeze_embeddings, + n_trans_layers_to_freeze, + export, + ) + + self.layers = nn.ModuleList( + [ + SparseTransformerSentenceEncoderLayer( + embedding_dim=self.embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + is_bidirectional=is_bidirectional, + stride=stride, + expressivity=expressivity, + ) + for _ in range(num_encoder_layers) + ] + ) + + def freeze_module_params(m): + if m is not None: + for p in m.parameters(): + p.requires_grad = False + + for layer in range(n_trans_layers_to_freeze): + freeze_module_params(self.layers[layer]) diff --git a/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder_layer.py b/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder_layer.py new file mode 100644 index 00000000..d95da59c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/sparse_transformer_sentence_encoder_layer.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.modules import TransformerSentenceEncoderLayer +from fairseq.modules.sparse_multihead_attention import SparseMultiheadAttention + + +class SparseTransformerSentenceEncoderLayer(TransformerSentenceEncoderLayer): + """ + Implements a Sprase Transformer Encoder Layer (see SparseMultiheadAttention) + """ + + def __init__( + self, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + activation_fn: str = "relu", + export: bool = False, + is_bidirectional: bool = True, + stride: int = 32, + expressivity: int = 8, + ) -> None: + + super().__init__( + embedding_dim, + ffn_embedding_dim, + num_attention_heads, + dropout, + attention_dropout, + activation_dropout, + activation_fn, + export, + ) + + self.self_attn = SparseMultiheadAttention( + self.embedding_dim, + num_attention_heads, + dropout=attention_dropout, + add_bias_kv=False, + add_zero_attn=False, + self_attention=True, + is_bidirectional=is_bidirectional, + stride=stride, + expressivity=expressivity, + ) diff --git a/fairseq-tools/fairseq/fairseq/modules/transformer_layer.py b/fairseq-tools/fairseq/fairseq/modules/transformer_layer.py new file mode 100644 index 00000000..48cd4c73 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/transformer_layer.py @@ -0,0 +1,423 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Dict, List, Optional + +import torch +import torch.nn as nn +from fairseq import utils +from fairseq.modules import LayerNorm, MultiheadAttention +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.quant_noise import quant_noise +from torch import Tensor + + +class TransformerEncoderLayer(nn.Module): + """Encoder layer block. + + In the original paper each operation (multi-head attention or FFN) is + postprocessed with: `dropout -> add residual -> layernorm`. In the + tensor2tensor code they suggest that learning is more robust when + preprocessing each layer with layernorm and postprocessing with: + `dropout -> add residual`. We default to the approach in the paper, but the + tensor2tensor approach can be enabled by setting + *args.encoder_normalize_before* to ``True``. + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + + def __init__(self, args): + super().__init__() + self.embed_dim = args.encoder_embed_dim + self.quant_noise = getattr(args, "quant_noise_pq", 0) + self.quant_noise_block_size = getattr(args, "quant_noise_pq_block_size", 8) + self.self_attn = self.build_self_attention(self.embed_dim, args) + self.self_attn_layer_norm = LayerNorm(self.embed_dim) + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.activation_fn = utils.get_activation_fn( + activation=getattr(args, "activation_fn", "relu") + ) + activation_dropout_p = getattr(args, "activation_dropout", 0) + if activation_dropout_p == 0: + # for backwards compatibility with models that use args.relu_dropout + activation_dropout_p = getattr(args, "relu_dropout", 0) + self.activation_dropout_module = FairseqDropout( + float(activation_dropout_p), module_name=self.__class__.__name__ + ) + self.normalize_before = args.encoder_normalize_before + self.fc1 = self.build_fc1( + self.embed_dim, + args.encoder_ffn_embed_dim, + self.quant_noise, + self.quant_noise_block_size, + ) + self.fc2 = self.build_fc2( + args.encoder_ffn_embed_dim, + self.embed_dim, + self.quant_noise, + self.quant_noise_block_size, + ) + + self.final_layer_norm = LayerNorm(self.embed_dim) + + def build_fc1(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise( + nn.Linear(input_dim, output_dim), p=q_noise, block_size=qn_block_size + ) + + def build_fc2(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise( + nn.Linear(input_dim, output_dim), p=q_noise, block_size=qn_block_size + ) + + def build_self_attention(self, embed_dim, args): + return MultiheadAttention( + embed_dim, + args.encoder_attention_heads, + dropout=args.attention_dropout, + self_attention=True, + q_noise=self.quant_noise, + qn_block_size=self.quant_noise_block_size, + ) + + def residual_connection(self, x, residual): + return residual + x + + def upgrade_state_dict_named(self, state_dict, name): + """ + Rename layer norm states from `...layer_norms.0.weight` to + `...self_attn_layer_norm.weight` and `...layer_norms.1.weight` to + `...final_layer_norm.weight` + """ + layer_norm_map = {"0": "self_attn_layer_norm", "1": "final_layer_norm"} + for old, new in layer_norm_map.items(): + for m in ("weight", "bias"): + k = "{}.layer_norms.{}.{}".format(name, old, m) + if k in state_dict: + state_dict["{}.{}.{}".format(name, new, m)] = state_dict[k] + del state_dict[k] + + def forward(self, x, encoder_padding_mask, attn_mask: Optional[Tensor] = None): + """ + Args: + x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + encoder_padding_mask (ByteTensor): binary ByteTensor of shape + `(batch, seq_len)` where padding elements are indicated by ``1``. + attn_mask (ByteTensor): binary tensor of shape `(tgt_len, src_len)`, + where `tgt_len` is the length of output and `src_len` is the + length of input, though here both are equal to `seq_len`. + `attn_mask[tgt_i, src_j] = 1` means that when calculating the + embedding for `tgt_i`, we exclude (mask out) `src_j`. This is + useful for strided self-attention. + + Returns: + encoded output of shape `(seq_len, batch, embed_dim)` + """ + # anything in original attn_mask = 1, becomes -1e8 + # anything in original attn_mask = 0, becomes 0 + # Note that we cannot use -inf here, because at some edge cases, + # the attention weight (before softmax) for some padded element in query + # will become -inf, which results in NaN in model parameters + if attn_mask is not None: + attn_mask = attn_mask.masked_fill(attn_mask.to(torch.bool), -1e8) + + residual = x + if self.normalize_before: + x = self.self_attn_layer_norm(x) + x, _ = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=encoder_padding_mask, + attn_mask=attn_mask, + ) + x = self.dropout_module(x) + x = self.residual_connection(x, residual) + if not self.normalize_before: + x = self.self_attn_layer_norm(x) + + residual = x + if self.normalize_before: + x = self.final_layer_norm(x) + + x = self.activation_fn(self.fc1(x)) + x = self.activation_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = self.residual_connection(x, residual) + if not self.normalize_before: + x = self.final_layer_norm(x) + return x + + +class TransformerDecoderLayer(nn.Module): + """Decoder layer block. + + In the original paper each operation (multi-head attention, encoder + attention or FFN) is postprocessed with: `dropout -> add residual -> + layernorm`. In the tensor2tensor code they suggest that learning is more + robust when preprocessing each layer with layernorm and postprocessing with: + `dropout -> add residual`. We default to the approach in the paper, but the + tensor2tensor approach can be enabled by setting + *args.decoder_normalize_before* to ``True``. + + Args: + args (argparse.Namespace): parsed command-line arguments + no_encoder_attn (bool, optional): whether to attend to encoder outputs + (default: False). + """ + + def __init__( + self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False + ): + super().__init__() + self.embed_dim = args.decoder_embed_dim + self.dropout_module = FairseqDropout( + args.dropout, module_name=self.__class__.__name__ + ) + self.quant_noise = getattr(args, "quant_noise_pq", 0) + self.quant_noise_block_size = getattr(args, "quant_noise_pq_block_size", 8) + + self.cross_self_attention = getattr(args, "cross_self_attention", False) + + self.self_attn = self.build_self_attention( + self.embed_dim, + args, + add_bias_kv=add_bias_kv, + add_zero_attn=add_zero_attn, + ) + + self.activation_fn = utils.get_activation_fn( + activation=str(args.activation_fn) + if getattr(args, "activation_fn", None) is not None + else "relu" + ) + activation_dropout_p = getattr(args, "activation_dropout", 0) + if activation_dropout_p == 0: + # for backwards compatibility with models that use args.relu_dropout + activation_dropout_p = getattr(args, "relu_dropout", 0) + self.activation_dropout_module = FairseqDropout( + float(activation_dropout_p), module_name=self.__class__.__name__ + ) + self.normalize_before = args.decoder_normalize_before + + # use layerNorm rather than FusedLayerNorm for exporting. + # char_inputs can be used to determint this. + # TODO remove this once we update apex with the fix + export = getattr(args, "char_inputs", False) + self.self_attn_layer_norm = LayerNorm(self.embed_dim, export=export) + + if no_encoder_attn: + self.encoder_attn = None + self.encoder_attn_layer_norm = None + else: + self.encoder_attn = self.build_encoder_attention(self.embed_dim, args) + self.encoder_attn_layer_norm = LayerNorm(self.embed_dim, export=export) + + self.fc1 = self.build_fc1( + self.embed_dim, + args.decoder_ffn_embed_dim, + self.quant_noise, + self.quant_noise_block_size, + ) + self.fc2 = self.build_fc2( + args.decoder_ffn_embed_dim, + self.embed_dim, + self.quant_noise, + self.quant_noise_block_size, + ) + + self.final_layer_norm = LayerNorm(self.embed_dim, export=export) + self.need_attn = True + + self.onnx_trace = False + + def build_fc1(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise(nn.Linear(input_dim, output_dim), q_noise, qn_block_size) + + def build_fc2(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise(nn.Linear(input_dim, output_dim), q_noise, qn_block_size) + + def build_self_attention( + self, embed_dim, args, add_bias_kv=False, add_zero_attn=False + ): + return MultiheadAttention( + embed_dim, + args.decoder_attention_heads, + dropout=args.attention_dropout, + add_bias_kv=add_bias_kv, + add_zero_attn=add_zero_attn, + self_attention=not getattr(args, "cross_self_attention", False), + q_noise=self.quant_noise, + qn_block_size=self.quant_noise_block_size, + ) + + def build_encoder_attention(self, embed_dim, args): + return MultiheadAttention( + embed_dim, + args.decoder_attention_heads, + kdim=getattr(args, "encoder_embed_dim", None), + vdim=getattr(args, "encoder_embed_dim", None), + dropout=args.attention_dropout, + encoder_decoder_attention=True, + q_noise=self.quant_noise, + qn_block_size=self.quant_noise_block_size, + ) + + def prepare_for_onnx_export_(self): + self.onnx_trace = True + + def residual_connection(self, x, residual): + return residual + x + + def forward( + self, + x, + encoder_out: Optional[torch.Tensor] = None, + encoder_padding_mask: Optional[torch.Tensor] = None, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None, + prev_self_attn_state: Optional[List[torch.Tensor]] = None, + prev_attn_state: Optional[List[torch.Tensor]] = None, + self_attn_mask: Optional[torch.Tensor] = None, + self_attn_padding_mask: Optional[torch.Tensor] = None, + need_attn: bool = False, + need_head_weights: bool = False, + ): + """ + Args: + x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)` + encoder_padding_mask (ByteTensor, optional): binary + ByteTensor of shape `(batch, src_len)` where padding + elements are indicated by ``1``. + need_attn (bool, optional): return attention weights + need_head_weights (bool, optional): return attention weights + for each head (default: return average over heads). + + Returns: + encoded output of shape `(seq_len, batch, embed_dim)` + """ + if need_head_weights: + need_attn = True + + residual = x + if self.normalize_before: + x = self.self_attn_layer_norm(x) + if prev_self_attn_state is not None: + prev_key, prev_value = prev_self_attn_state[:2] + saved_state: Dict[str, Optional[Tensor]] = { + "prev_key": prev_key, + "prev_value": prev_value, + } + if len(prev_self_attn_state) >= 3: + saved_state["prev_key_padding_mask"] = prev_self_attn_state[2] + assert incremental_state is not None + self.self_attn._set_input_buffer(incremental_state, saved_state) + _self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state) + if self.cross_self_attention and not ( + incremental_state is not None + and _self_attn_input_buffer is not None + and "prev_key" in _self_attn_input_buffer + ): + if self_attn_mask is not None: + assert encoder_out is not None + self_attn_mask = torch.cat( + (x.new_zeros(x.size(0), encoder_out.size(0)), self_attn_mask), dim=1 + ) + if self_attn_padding_mask is not None: + if encoder_padding_mask is None: + assert encoder_out is not None + encoder_padding_mask = self_attn_padding_mask.new_zeros( + encoder_out.size(1), encoder_out.size(0) + ) + self_attn_padding_mask = torch.cat( + (encoder_padding_mask, self_attn_padding_mask), dim=1 + ) + assert encoder_out is not None + y = torch.cat((encoder_out, x), dim=0) + else: + y = x + + x, attn = self.self_attn( + query=x, + key=y, + value=y, + key_padding_mask=self_attn_padding_mask, + incremental_state=incremental_state, + need_weights=False, + attn_mask=self_attn_mask, + ) + x = self.dropout_module(x) + x = self.residual_connection(x, residual) + if not self.normalize_before: + x = self.self_attn_layer_norm(x) + + if self.encoder_attn is not None and encoder_out is not None: + residual = x + if self.normalize_before: + x = self.encoder_attn_layer_norm(x) + if prev_attn_state is not None: + prev_key, prev_value = prev_attn_state[:2] + saved_state: Dict[str, Optional[Tensor]] = { + "prev_key": prev_key, + "prev_value": prev_value, + } + if len(prev_attn_state) >= 3: + saved_state["prev_key_padding_mask"] = prev_attn_state[2] + assert incremental_state is not None + self.encoder_attn._set_input_buffer(incremental_state, saved_state) + + x, attn = self.encoder_attn( + query=x, + key=encoder_out, + value=encoder_out, + key_padding_mask=encoder_padding_mask, + incremental_state=incremental_state, + static_kv=True, + need_weights=need_attn or (not self.training and self.need_attn), + need_head_weights=need_head_weights, + ) + x = self.dropout_module(x) + x = self.residual_connection(x, residual) + if not self.normalize_before: + x = self.encoder_attn_layer_norm(x) + + residual = x + if self.normalize_before: + x = self.final_layer_norm(x) + + x = self.activation_fn(self.fc1(x)) + x = self.activation_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = self.residual_connection(x, residual) + if not self.normalize_before: + x = self.final_layer_norm(x) + if self.onnx_trace and incremental_state is not None: + saved_state = self.self_attn._get_input_buffer(incremental_state) + assert saved_state is not None + if self_attn_padding_mask is not None: + self_attn_state = [ + saved_state["prev_key"], + saved_state["prev_value"], + saved_state["prev_key_padding_mask"], + ] + else: + self_attn_state = [saved_state["prev_key"], saved_state["prev_value"]] + return x, attn, self_attn_state + return x, attn, None + + def make_generation_fast_(self, need_attn: bool = False, **kwargs): + self.need_attn = need_attn + + +def Linear(in_features, out_features, bias=True): + m = nn.Linear(in_features, out_features, bias) + nn.init.xavier_uniform_(m.weight) + if bias: + nn.init.constant_(m.bias, 0.0) + return m diff --git a/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder.py b/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder.py new file mode 100644 index 00000000..208488f5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder.py @@ -0,0 +1,286 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Optional, Tuple + +import torch +import torch.nn as nn +from fairseq.modules import ( + FairseqDropout, + LayerDropModuleList, + LayerNorm, + MultiheadAttention, + PositionalEmbedding, + TransformerSentenceEncoderLayer, +) +from fairseq.modules.quant_noise import quant_noise as apply_quant_noise_ + + +def init_bert_params(module): + """ + Initialize the weights specific to the BERT Model. + This overrides the default initializations depending on the specified arguments. + 1. If normal_init_linear_weights is set then weights of linear + layer will be initialized using the normal distribution and + bais will be set to the specified value. + 2. If normal_init_embed_weights is set then weights of embedding + layer will be initialized using the normal distribution. + 3. If normal_init_proj_weights is set then weights of + in_project_weight for MultiHeadAttention initialized using + the normal distribution (to be validated). + """ + + if isinstance(module, nn.Linear): + module.weight.data.normal_(mean=0.0, std=0.02) + if module.bias is not None: + module.bias.data.zero_() + if isinstance(module, nn.Embedding): + module.weight.data.normal_(mean=0.0, std=0.02) + if module.padding_idx is not None: + module.weight.data[module.padding_idx].zero_() + if isinstance(module, MultiheadAttention): + module.q_proj.weight.data.normal_(mean=0.0, std=0.02) + module.k_proj.weight.data.normal_(mean=0.0, std=0.02) + module.v_proj.weight.data.normal_(mean=0.0, std=0.02) + + +class TransformerSentenceEncoder(nn.Module): + """ + Implementation for a Bi-directional Transformer based Sentence Encoder used + in BERT/XLM style pre-trained models. + + This first computes the token embedding using the token embedding matrix, + position embeddings (if specified) and segment embeddings + (if specified). After applying the specified number of + TransformerEncoderLayers, it outputs all the internal states of the + encoder as well as the final representation associated with the first + token (usually CLS token). + + Input: + - tokens: B x T matrix representing sentences + - segment_labels: B x T matrix representing segment label for tokens + + Output: + - a tuple of the following: + - a list of internal model states used to compute the + predictions where each tensor has shape T x B x C + - sentence representation associated with first input token + in format B x C. + """ + + def __init__( + self, + padding_idx: int, + vocab_size: int, + num_encoder_layers: int = 6, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + layerdrop: float = 0.0, + max_seq_len: int = 256, + num_segments: int = 2, + use_position_embeddings: bool = True, + offset_positions_by_padding: bool = True, + encoder_normalize_before: bool = False, + apply_bert_init: bool = False, + activation_fn: str = "relu", + learned_pos_embedding: bool = True, + embed_scale: float = None, + freeze_embeddings: bool = False, + n_trans_layers_to_freeze: int = 0, + export: bool = False, + traceable: bool = False, + q_noise: float = 0.0, + qn_block_size: int = 8, + ) -> None: + + super().__init__() + self.padding_idx = padding_idx + self.vocab_size = vocab_size + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.layerdrop = layerdrop + self.max_seq_len = max_seq_len + self.embedding_dim = embedding_dim + self.num_segments = num_segments + self.use_position_embeddings = use_position_embeddings + self.apply_bert_init = apply_bert_init + self.learned_pos_embedding = learned_pos_embedding + self.traceable = traceable + self.tpu = False # whether we're on TPU + + self.embed_tokens = self.build_embedding( + self.vocab_size, self.embedding_dim, self.padding_idx + ) + self.embed_scale = embed_scale + + if q_noise > 0: + self.quant_noise = apply_quant_noise_( + nn.Linear(self.embedding_dim, self.embedding_dim, bias=False), + q_noise, + qn_block_size, + ) + else: + self.quant_noise = None + + self.segment_embeddings = ( + nn.Embedding(self.num_segments, self.embedding_dim, padding_idx=None) + if self.num_segments > 0 + else None + ) + + self.embed_positions = ( + PositionalEmbedding( + self.max_seq_len, + self.embedding_dim, + padding_idx=(self.padding_idx if offset_positions_by_padding else None), + learned=self.learned_pos_embedding, + ) + if self.use_position_embeddings + else None + ) + + if self.layerdrop > 0.0: + self.layers = LayerDropModuleList(p=self.layerdrop) + else: + self.layers = nn.ModuleList([]) + self.layers.extend( + [ + self.build_transformer_sentence_encoder_layer( + embedding_dim=self.embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=self.dropout_module.p, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + for _ in range(num_encoder_layers) + ] + ) + + if encoder_normalize_before: + self.emb_layer_norm = LayerNorm(self.embedding_dim, export=export) + else: + self.emb_layer_norm = None + + # Apply initialization of model params after building the model + if self.apply_bert_init: + self.apply(init_bert_params) + + def freeze_module_params(m): + if m is not None: + for p in m.parameters(): + p.requires_grad = False + + if freeze_embeddings: + freeze_module_params(self.embed_tokens) + freeze_module_params(self.segment_embeddings) + freeze_module_params(self.embed_positions) + freeze_module_params(self.emb_layer_norm) + + for layer in range(n_trans_layers_to_freeze): + freeze_module_params(self.layers[layer]) + + def build_embedding(self, vocab_size, embedding_dim, padding_idx): + return nn.Embedding(vocab_size, embedding_dim, padding_idx) + + def build_transformer_sentence_encoder_layer( + self, + embedding_dim, + ffn_embedding_dim, + num_attention_heads, + dropout, + attention_dropout, + activation_dropout, + activation_fn, + export, + q_noise, + qn_block_size, + ): + return TransformerSentenceEncoderLayer( + embedding_dim=embedding_dim, + ffn_embedding_dim=ffn_embedding_dim, + num_attention_heads=num_attention_heads, + dropout=dropout, + attention_dropout=attention_dropout, + activation_dropout=activation_dropout, + activation_fn=activation_fn, + export=export, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + + def prepare_for_tpu_(self, **kwargs): + self.tpu = True + + def forward( + self, + tokens: torch.Tensor, + segment_labels: torch.Tensor = None, + last_state_only: bool = False, + positions: Optional[torch.Tensor] = None, + token_embeddings: Optional[torch.Tensor] = None, + ) -> Tuple[torch.Tensor, torch.Tensor]: + + # compute padding mask. This is needed for multi-head attention + padding_mask = tokens.eq(self.padding_idx) + if not self.traceable and not self.tpu and not padding_mask.any(): + padding_mask = None + + if token_embeddings is not None: + x = token_embeddings + else: + x = self.embed_tokens(tokens) + + if self.embed_scale is not None: + x = x * self.embed_scale + + if self.embed_positions is not None: + x = x + self.embed_positions(tokens, positions=positions) + + if self.segment_embeddings is not None and segment_labels is not None: + x = x + self.segment_embeddings(segment_labels) + + if self.quant_noise is not None: + x = self.quant_noise(x) + + if self.emb_layer_norm is not None: + x = self.emb_layer_norm(x) + + x = self.dropout_module(x) + + # account for padding while computing the representation + if padding_mask is not None: + x = x * (1 - padding_mask.unsqueeze(-1).type_as(x)) + + # B x T x C -> T x B x C + x = x.transpose(0, 1) + + inner_states = [] + if not last_state_only: + inner_states.append(x) + + for layer in self.layers: + x, _ = layer(x, self_attn_padding_mask=padding_mask) + if not last_state_only: + inner_states.append(x) + + sentence_rep = x[0, :, :] + + if last_state_only: + inner_states = [x] + + if self.traceable: + return torch.stack(inner_states), sentence_rep + else: + return inner_states, sentence_rep diff --git a/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder_layer.py b/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder_layer.py new file mode 100644 index 00000000..3589c60f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/transformer_sentence_encoder_layer.py @@ -0,0 +1,134 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from typing import Callable, Optional + +import torch +import torch.nn as nn +from fairseq import utils +from fairseq.modules import LayerNorm, MultiheadAttention +from fairseq.modules.fairseq_dropout import FairseqDropout +from fairseq.modules.quant_noise import quant_noise + + +class TransformerSentenceEncoderLayer(nn.Module): + """ + Implements a Transformer Encoder Layer used in BERT/XLM style pre-trained + models. + """ + + def __init__( + self, + embedding_dim: int = 768, + ffn_embedding_dim: int = 3072, + num_attention_heads: int = 8, + dropout: float = 0.1, + attention_dropout: float = 0.1, + activation_dropout: float = 0.1, + activation_fn: str = "relu", + export: bool = False, + q_noise: float = 0.0, + qn_block_size: int = 8, + init_fn: Callable = None, + ) -> None: + super().__init__() + + if init_fn is not None: + init_fn() + + # Initialize parameters + self.embedding_dim = embedding_dim + self.dropout_module = FairseqDropout( + dropout, module_name=self.__class__.__name__ + ) + self.activation_dropout_module = FairseqDropout( + activation_dropout, module_name=self.__class__.__name__ + ) + + # Initialize blocks + self.activation_fn = utils.get_activation_fn(activation_fn) + self.self_attn = self.build_self_attention( + self.embedding_dim, + num_attention_heads, + dropout=attention_dropout, + self_attention=True, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + + # layer norm associated with the self attention layer + self.self_attn_layer_norm = LayerNorm(self.embedding_dim, export=export) + + self.fc1 = self.build_fc1( + self.embedding_dim, + ffn_embedding_dim, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + self.fc2 = self.build_fc2( + ffn_embedding_dim, + self.embedding_dim, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + + # layer norm associated with the position wise feed-forward NN + self.final_layer_norm = LayerNorm(self.embedding_dim, export=export) + + def build_fc1(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise(nn.Linear(input_dim, output_dim), q_noise, qn_block_size) + + def build_fc2(self, input_dim, output_dim, q_noise, qn_block_size): + return quant_noise(nn.Linear(input_dim, output_dim), q_noise, qn_block_size) + + def build_self_attention( + self, + embed_dim, + num_attention_heads, + dropout, + self_attention, + q_noise, + qn_block_size, + ): + return MultiheadAttention( + embed_dim, + num_attention_heads, + dropout=dropout, + self_attention=True, + q_noise=q_noise, + qn_block_size=qn_block_size, + ) + + def forward( + self, + x: torch.Tensor, + self_attn_mask: Optional[torch.Tensor] = None, + self_attn_padding_mask: Optional[torch.Tensor] = None, + ): + """ + LayerNorm is applied either before or after the self-attention/ffn + modules similar to the original Transformer implementation. + """ + residual = x + x, attn = self.self_attn( + query=x, + key=x, + value=x, + key_padding_mask=self_attn_padding_mask, + need_weights=False, + attn_mask=self_attn_mask, + ) + x = self.dropout_module(x) + x = residual + x + x = self.self_attn_layer_norm(x) + + residual = x + x = self.activation_fn(self.fc1(x)) + x = self.activation_dropout_module(x) + x = self.fc2(x) + x = self.dropout_module(x) + x = residual + x + x = self.final_layer_norm(x) + return x, attn diff --git a/fairseq-tools/fairseq/fairseq/modules/transpose_last.py b/fairseq-tools/fairseq/fairseq/modules/transpose_last.py new file mode 100644 index 00000000..e578b3ec --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/transpose_last.py @@ -0,0 +1,20 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +transpose last 2 dimensions of the input +""" + +import torch.nn as nn + + +class TransposeLast(nn.Module): + def __init__(self, deconstruct_idx=None): + super().__init__() + self.deconstruct_idx = deconstruct_idx + + def forward(self, x): + if self.deconstruct_idx is not None: + x = x[self.deconstruct_idx] + return x.transpose(-2, -1) diff --git a/fairseq-tools/fairseq/fairseq/modules/unfold.py b/fairseq-tools/fairseq/fairseq/modules/unfold.py new file mode 100644 index 00000000..138272f1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/unfold.py @@ -0,0 +1,19 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.nn.functional as F + + +def unfold1d(x, kernel_size, padding_l, pad_value=0): + """unfold T x B x C to T x B x C x K""" + if kernel_size > 1: + T, B, C = x.size() + x = F.pad( + x, (0, 0, 0, 0, padding_l, kernel_size - 1 - padding_l), value=pad_value + ) + x = x.as_strided((T, B, C, kernel_size), (B * C, C, 1, B * C)) + else: + x = x.unsqueeze(3) + return x diff --git a/fairseq-tools/fairseq/fairseq/modules/vggblock.py b/fairseq-tools/fairseq/fairseq/modules/vggblock.py new file mode 100644 index 00000000..ee5ee19a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/modules/vggblock.py @@ -0,0 +1,116 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +from collections.abc import Iterable +from itertools import repeat + +import torch +import torch.nn as nn + + +def _pair(v): + if isinstance(v, Iterable): + assert len(v) == 2, "len(v) != 2" + return v + return tuple(repeat(v, 2)) + + +def infer_conv_output_dim(conv_op, input_dim, sample_inchannel): + sample_seq_len = 200 + sample_bsz = 10 + x = torch.randn(sample_bsz, sample_inchannel, sample_seq_len, input_dim) + # N x C x H x W + # N: sample_bsz, C: sample_inchannel, H: sample_seq_len, W: input_dim + x = conv_op(x) + # N x C x H x W + x = x.transpose(1, 2) + # N x H x C x W + bsz, seq = x.size()[:2] + per_channel_dim = x.size()[3] + # bsz: N, seq: H, CxW the rest + return x.contiguous().view(bsz, seq, -1).size(-1), per_channel_dim + + +class VGGBlock(torch.nn.Module): + """ + VGG motibated cnn module https://arxiv.org/pdf/1409.1556.pdf + + Args: + in_channels: (int) number of input channels (typically 1) + out_channels: (int) number of output channels + conv_kernel_size: convolution channels + pooling_kernel_size: the size of the pooling window to take a max over + num_conv_layers: (int) number of convolution layers + input_dim: (int) input dimension + conv_stride: the stride of the convolving kernel. + Can be a single number or a tuple (sH, sW) Default: 1 + padding: implicit paddings on both sides of the input. + Can be a single number or a tuple (padH, padW). Default: None + layer_norm: (bool) if layer norm is going to be applied. Default: False + + Shape: + Input: BxCxTxfeat, i.e. (batch_size, input_size, timesteps, features) + Output: BxCxTxfeat, i.e. (batch_size, input_size, timesteps, features) + """ + + def __init__( + self, + in_channels, + out_channels, + conv_kernel_size, + pooling_kernel_size, + num_conv_layers, + input_dim, + conv_stride=1, + padding=None, + layer_norm=False, + ): + assert ( + input_dim is not None + ), "Need input_dim for LayerNorm and infer_conv_output_dim" + super(VGGBlock, self).__init__() + self.in_channels = in_channels + self.out_channels = out_channels + self.conv_kernel_size = _pair(conv_kernel_size) + self.pooling_kernel_size = _pair(pooling_kernel_size) + self.num_conv_layers = num_conv_layers + self.padding = ( + tuple(e // 2 for e in self.conv_kernel_size) + if padding is None + else _pair(padding) + ) + self.conv_stride = _pair(conv_stride) + + self.layers = nn.ModuleList() + for layer in range(num_conv_layers): + conv_op = nn.Conv2d( + in_channels if layer == 0 else out_channels, + out_channels, + self.conv_kernel_size, + stride=self.conv_stride, + padding=self.padding, + ) + self.layers.append(conv_op) + if layer_norm: + conv_output_dim, per_channel_dim = infer_conv_output_dim( + conv_op, input_dim, in_channels if layer == 0 else out_channels + ) + self.layers.append(nn.LayerNorm(per_channel_dim)) + input_dim = per_channel_dim + self.layers.append(nn.ReLU()) + + if self.pooling_kernel_size is not None: + pool_op = nn.MaxPool2d(kernel_size=self.pooling_kernel_size, ceil_mode=True) + self.layers.append(pool_op) + self.total_output_dim, self.output_dim = infer_conv_output_dim( + pool_op, input_dim, out_channels + ) + + def forward(self, x): + for i, _ in enumerate(self.layers): + x = self.layers[i](x) + return x diff --git a/fairseq-tools/fairseq/fairseq/nan_detector.py b/fairseq-tools/fairseq/fairseq/nan_detector.py new file mode 100644 index 00000000..faa8031d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/nan_detector.py @@ -0,0 +1,108 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +import torch + + +logger = logging.getLogger(__name__) + + +class NanDetector: + """ + Detects the first NaN or Inf in forward and/or backward pass and logs, together with the module name + """ + + def __init__(self, model, forward=True, backward=True): + self.bhooks = [] + self.fhooks = [] + self.forward = forward + self.backward = backward + self.named_parameters = list(model.named_parameters()) + self.reset() + + for name, mod in model.named_modules(): + mod.__module_name = name + self.add_hooks(mod) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, exc_traceback): + # Dump out all model gnorms to enable better debugging + norm = {} + gradients = {} + for name, param in self.named_parameters: + if param.grad is not None: + grad_norm = torch.norm(param.grad.data, p=2, dtype=torch.float32) + norm[name] = grad_norm.item() + if torch.isnan(grad_norm).any() or torch.isinf(grad_norm).any(): + gradients[name] = param.grad.data + if len(gradients) > 0: + logger.info("Detected nan/inf grad norm, dumping norms...") + logger.info(f"norms: {norm}") + logger.info(f"gradients: {gradients}") + + self.close() + + def add_hooks(self, module): + if self.forward: + self.fhooks.append(module.register_forward_hook(self.fhook_fn)) + if self.backward: + self.bhooks.append(module.register_backward_hook(self.bhook_fn)) + + def reset(self): + self.has_printed_f = False + self.has_printed_b = False + + def _detect(self, tensor, name, backward): + err = None + if ( + torch.is_floating_point(tensor) + # single value tensors (like the loss) will not provide much info + and tensor.numel() >= 2 + ): + with torch.no_grad(): + if torch.isnan(tensor).any(): + err = "NaN" + elif torch.isinf(tensor).any(): + err = "Inf" + if err is not None: + err = f"{err} detected in output of {name}, shape: {tensor.shape}, {'backward' if backward else 'forward'}" + return err + + def _apply(self, module, inp, x, backward): + if torch.is_tensor(x): + if isinstance(inp, tuple) and len(inp) > 0: + inp = inp[0] + err = self._detect(x, module.__module_name, backward) + if err is not None: + if torch.is_tensor(inp) and not backward: + err += ( + f" input max: {inp.max().item()}, input min: {inp.min().item()}" + ) + + has_printed_attr = "has_printed_b" if backward else "has_printed_f" + logger.warning(err) + setattr(self, has_printed_attr, True) + elif isinstance(x, dict): + for v in x.values(): + self._apply(module, inp, v, backward) + elif isinstance(x, list) or isinstance(x, tuple): + for v in x: + self._apply(module, inp, v, backward) + + def fhook_fn(self, module, inp, output): + if not self.has_printed_f: + self._apply(module, inp, output, backward=False) + + def bhook_fn(self, module, inp, output): + if not self.has_printed_b: + self._apply(module, inp, output, backward=True) + + def close(self): + for hook in self.fhooks + self.bhooks: + hook.remove() diff --git a/fairseq-tools/fairseq/fairseq/optim/__init__.py b/fairseq-tools/fairseq/fairseq/optim/__init__.py new file mode 100644 index 00000000..94eb2c7e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/__init__.py @@ -0,0 +1,52 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +import importlib +import os +from argparse import Namespace +from typing import Union + +from fairseq import registry +from fairseq.optim.bmuf import FairseqBMUF # noqa +from fairseq.optim.fairseq_optimizer import ( # noqa + FairseqOptimizer, + LegacyFairseqOptimizer, +) +from fairseq.optim.fp16_optimizer import FP16Optimizer, MemoryEfficientFP16Optimizer +from fairseq.optim.shard import shard_ +from omegaconf import DictConfig + + +__all__ = [ + "FairseqOptimizer", + "FP16Optimizer", + "MemoryEfficientFP16Optimizer", + "shard_", +] + + +( + _build_optimizer, + register_optimizer, + OPTIMIZER_REGISTRY, + OPTIMIZER_DATACLASS_REGISTRY, +) = registry.setup_registry("--optimizer", base_class=FairseqOptimizer, required=True) + + +def build_optimizer( + optimizer_cfg: Union[DictConfig, Namespace], params, *extra_args, **extra_kwargs +): + if all(isinstance(p, dict) for p in params): + params = [t for p in params for t in p.values()] + params = list(filter(lambda p: p.requires_grad, params)) + return _build_optimizer(optimizer_cfg, params, *extra_args, **extra_kwargs) + + +# automatically import any Python files in the optim/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + file_name = file[: file.find(".py")] + importlib.import_module("fairseq.optim." + file_name) diff --git a/fairseq-tools/fairseq/fairseq/optim/adadelta.py b/fairseq-tools/fairseq/fairseq/optim/adadelta.py new file mode 100644 index 00000000..f1a21549 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/adadelta.py @@ -0,0 +1,47 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.optim + +from . import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("adadelta") +class Adadelta(LegacyFairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = torch.optim.Adadelta(params, **self.optimizer_config) + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--adadelta-rho', type=float, default=0.9, metavar='RHO', + help='coefficient used for computing a running average of squared gradients') + parser.add_argument('--adadelta-eps', type=float, default=1e-6, metavar='EPS', + help='term added to the denominator to improve numerical stability') + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + parser.add_argument('--anneal-eps', action='store_true', help='flag to anneal eps') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "rho": self.args.adadelta_rho, + "eps": self.args.adadelta_eps, + "weight_decay": self.args.weight_decay, + } + + @property + def supports_flat_params(self): + return True diff --git a/fairseq-tools/fairseq/fairseq/optim/adafactor.py b/fairseq-tools/fairseq/fairseq/optim/adafactor.py new file mode 100644 index 00000000..91745ce1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/adafactor.py @@ -0,0 +1,268 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +import torch +import torch.optim + +from . import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("adafactor") +class FairseqAdafactor(LegacyFairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = Adafactor(params, **self.optimizer_config) + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--adafactor-eps', default='(1e-30, 1e-3)', metavar="E", + help='epsilons for Adafactor optimizer') + parser.add_argument('--clip-threshold', type=float, default=1.0, metavar="C", + help='threshold for clipping update root mean square') + parser.add_argument('--decay-rate', type=float, default=-0.8, metavar="D", + help='decay rate of the second moment estimator') + parser.add_argument('--beta1', type=float, default=None, metavar="B", + help='beta for first moment estimator. Optional') + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + parser.add_argument('--scale-parameter', action='store_true', + help='scale learning rate by root mean square of parameter') + parser.add_argument('--relative-step', action='store_true', + help='set learning rate to inverse square root of timestep,' + 'otherwise use external learning rate') + parser.add_argument('--warmup-init', action='store_true', + help='use relative step for warm-up learning rate schedule') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + Note : Convergence issues empirically observed with fp16 on. + Might require search for appropriate configuration. + """ + return { + "lr": self.args.lr[0], + "eps": eval(self.args.adafactor_eps), + "clip_threshold": self.args.clip_threshold, + "decay_rate": self.args.decay_rate, + "beta1": self.args.beta1, + "weight_decay": self.args.weight_decay, + "scale_parameter": self.args.scale_parameter, # defaults to False + "relative_step": self.args.relative_step, # defaults to False + "warmup_init": self.args.warmup_init, + } + + +class Adafactor(torch.optim.Optimizer): + """Implements Adafactor algorithm. + + This implementation is based on: + `Adafactor: Adaptive Learning Rates with Sublinear Memory Cost` + (see https://arxiv.org/abs/1804.04235) + + Note that this optimizer internally adjusts the learning rate + depending on the *scale_parameter*, *relative_step* and + *warmup_init* options. To use a manual (external) learning rate + schedule you should set `scale_parameter=False` and + `relative_step=False`. + + Arguments: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups + lr (float, optional): external learning rate (default: None) + eps (tuple[float, float]): regularization constans for square gradient + and parameter scale respectively (default: (1e-30, 1e-3)) + clip_threshold (float): threshold of root mean square of + final gradient update (default: 1.0) + decay_rate (float): coefficient used to compute running averages of square + gradient (default: -0.8) + beta1 (float): coefficient used for computing running averages of gradient + (default: None) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + scale_parameter (bool): if True, learning rate is scaled by root mean square of + parameter (default: True) + relative_step (bool): if True, time-dependent learning rate is computed + instead of external learning rate (default: True) + warmup_init (bool): time-dependent learning rate computation depends on + whether warm-up initialization is being used (default: False) + """ + + def __init__( + self, + params, + lr=None, + eps=(1e-30, 1e-3), + clip_threshold=1.0, + decay_rate=-0.8, + beta1=None, + weight_decay=0.0, + scale_parameter=True, + relative_step=True, + warmup_init=False, + ): + if lr is not None and relative_step: + raise ValueError("Cannot combine manual lr and relative_step options") + if warmup_init and not relative_step: + raise ValueError("warmup_init requires relative_step=True") + + defaults = dict( + lr=lr, + eps=eps, + clip_threshold=clip_threshold, + decay_rate=decay_rate, + beta1=beta1, + weight_decay=weight_decay, + scale_parameter=scale_parameter, + relative_step=relative_step, + warmup_init=warmup_init, + ) + super(Adafactor, self).__init__(params, defaults) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return False + + def _get_lr(self, param_group, param_state): + rel_step_sz = param_group["lr"] + if param_group["relative_step"]: + min_step = ( + 1e-6 * param_state["step"] if param_group["warmup_init"] else 1e-2 + ) + rel_step_sz = min(min_step, 1.0 / math.sqrt(param_state["step"])) + param_scale = 1.0 + if param_group["scale_parameter"]: + param_scale = max(param_group["eps"][1], param_state["RMS"]) + return param_scale * rel_step_sz + + def _get_options(self, param_group, param_shape): + factored = len(param_shape) >= 2 + use_first_moment = param_group["beta1"] is not None + return factored, use_first_moment + + def _rms(self, tensor): + return tensor.norm(2) / (tensor.numel() ** 0.5) + + def _approx_sq_grad(self, exp_avg_sq_row, exp_avg_sq_col): + r_factor = ( + (exp_avg_sq_row / exp_avg_sq_row.mean(dim=-1, keepdim=True)) + .rsqrt_() + .unsqueeze(-1) + ) + c_factor = exp_avg_sq_col.unsqueeze(-2).rsqrt() + return torch.mul(r_factor, c_factor) + + def step(self, closure=None): + """Performs a single optimization step. + + Arguments: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + """ + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + for p in group["params"]: + if p.grad is None: + continue + grad = p.grad.data + if grad.dtype in {torch.float16, torch.bfloat16}: + grad = grad.float() + if grad.is_sparse: + raise RuntimeError("Adafactor does not support sparse gradients.") + + state = self.state[p] + grad_shape = grad.shape + + factored, use_first_moment = self._get_options(group, grad_shape) + # State Initialization + if len(state) == 0: + state["step"] = 0 + + if use_first_moment: + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(grad) + if factored: + state["exp_avg_sq_row"] = torch.zeros(grad_shape[:-1]).to(grad) + state["exp_avg_sq_col"] = torch.zeros( + grad_shape[:-2] + grad_shape[-1:] + ).to(grad) + else: + state["exp_avg_sq"] = torch.zeros_like(grad) + + state["RMS"] = 0 + else: + if use_first_moment: + state["exp_avg"] = state["exp_avg"].to(grad) + if factored: + state["exp_avg_sq_row"] = state["exp_avg_sq_row"].to(grad) + state["exp_avg_sq_col"] = state["exp_avg_sq_col"].to(grad) + else: + state["exp_avg_sq"] = state["exp_avg_sq"].to(grad) + + p_data_fp32 = p.data + if p.data.dtype in {torch.float16, torch.bfloat16}: + p_data_fp32 = p_data_fp32.float() + + state["step"] += 1 + state["RMS"] = self._rms(p_data_fp32) + group["lr"] = self._get_lr(group, state) + + beta2t = 1.0 - math.pow(state["step"], group["decay_rate"]) + update = (grad ** 2) + group["eps"][0] + if factored: + exp_avg_sq_row = state["exp_avg_sq_row"] + exp_avg_sq_col = state["exp_avg_sq_col"] + + exp_avg_sq_row.mul_(beta2t).add_( + update.mean(dim=-1), alpha=1.0 - beta2t + ) + exp_avg_sq_col.mul_(beta2t).add_( + update.mean(dim=-2), alpha=1.0 - beta2t + ) + + # Approximation of exponential moving average of square of gradient + update = self._approx_sq_grad(exp_avg_sq_row, exp_avg_sq_col) + update.mul_(grad) + else: + exp_avg_sq = state["exp_avg_sq"] + + exp_avg_sq.mul_(beta2t).add_(update, alpha=1.0 - beta2t) + update = exp_avg_sq.rsqrt().mul_(grad) + + update.div_( + (self._rms(update) / group["clip_threshold"]).clamp_(min=1.0) + ) + update.mul_(group["lr"]) + + if use_first_moment: + exp_avg = state["exp_avg"] + exp_avg.mul_(group["beta1"]).add_(update, alpha=1 - group["beta1"]) + update = exp_avg + + if group["weight_decay"] != 0: + p_data_fp32.add_( + p_data_fp32, alpha=-group["weight_decay"] * group["lr"] + ) + + p_data_fp32.add_(-update) + + if p.data.dtype in {torch.float16, torch.bfloat16}: + p.data.copy_(p_data_fp32) + + return loss diff --git a/fairseq-tools/fairseq/fairseq/optim/adagrad.py b/fairseq-tools/fairseq/fairseq/optim/adagrad.py new file mode 100644 index 00000000..a79b6c39 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/adagrad.py @@ -0,0 +1,40 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.optim + +from . import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("adagrad") +class Adagrad(LegacyFairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = torch.optim.Adagrad(params, **self.optimizer_config) + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "weight_decay": self.args.weight_decay, + } + + @property + def supports_flat_params(self): + return True diff --git a/fairseq-tools/fairseq/fairseq/optim/adam.py b/fairseq-tools/fairseq/fairseq/optim/adam.py new file mode 100644 index 00000000..f678a9f5 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/adam.py @@ -0,0 +1,223 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import math +from dataclasses import dataclass, field +from typing import List + +import torch +import torch.distributed as dist +import torch.optim +from fairseq.dataclass import FairseqDataclass +from fairseq.optim import FairseqOptimizer, register_optimizer +from fairseq.optim.fused_adam import get_fused_adam_class +from omegaconf import II + + +logger = logging.getLogger(__name__) + + +@dataclass +class FairseqAdamConfig(FairseqDataclass): + adam_betas: str = field( + default="(0.9, 0.999)", metadata={"help": "betas for Adam optimizer"} + ) + adam_eps: float = field( + default=1e-8, metadata={"help": "epsilon for Adam optimizer"} + ) + weight_decay: float = field(default=0.0, metadata={"help": "weight decay"}) + use_old_adam: bool = field( + default=False, metadata={"help": "Use fairseq.optim.adam.Adam"} + ) + # TODO common vars below in parent + tpu: bool = II("params.common.tpu") + lr: List[float] = II("params.optimization.lr") + + +@register_optimizer("adam", dataclass=FairseqAdamConfig) +class FairseqAdam(FairseqOptimizer): + """Adam optimizer for fairseq. + + Important note: this optimizer corresponds to the "AdamW" variant of + Adam in its weight decay behavior. As such, it is most closely + analogous to torch.optim.AdamW from PyTorch. + """ + + def __init__(self, args, params): + super().__init__(args) + fused_adam_cls = get_fused_adam_class() + use_fused_adam = ( + not getattr(args, "use_old_adam", False) + and fused_adam_cls is not None + and torch.cuda.is_available() + ) + if getattr(args, "tpu", False): + # on TPUs we use the Adam defined here, since it + # automatically casts gradients to FP32 + self._optimizer = Adam(params, **self.optimizer_config) + elif use_fused_adam: + logger.info("using FusedAdam") + self._optimizer = fused_adam_cls(params, **self.optimizer_config) + else: + self._optimizer = Adam(params, **self.optimizer_config) + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "betas": eval(self.args.adam_betas), + "eps": self.args.adam_eps, + "weight_decay": self.args.weight_decay, + } + + def average_params(self): + """Reduce Params is only used during BMUF distributed training.""" + state_dict = self.optimizer.state_dict() + total_gpus = float(dist.get_world_size()) + + for _, value in state_dict["state"].items(): + value["exp_avg"] /= total_gpus + value["exp_avg_sq"] /= total_gpus + dist.all_reduce(value["exp_avg"], op=dist.ReduceOp.SUM) + dist.all_reduce(value["exp_avg_sq"], op=dist.ReduceOp.SUM) + + +class Adam(torch.optim.Optimizer): + """Implements Adam algorithm. + + This implementation is modified from torch.optim.Adam based on: + `Fixed Weight Decay Regularization in Adam` + (see https://arxiv.org/abs/1711.05101) + + It has been proposed in `Adam: A Method for Stochastic Optimization`_. + + Arguments: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups + lr (float, optional): learning rate (default: 1e-3) + betas (Tuple[float, float], optional): coefficients used for computing + running averages of gradient and its square (default: (0.9, 0.999)) + eps (float, optional): term added to the denominator to improve + numerical stability (default: 1e-8) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + amsgrad (boolean, optional): whether to use the AMSGrad variant of this + algorithm from the paper `On the Convergence of Adam and Beyond`_ + + .. _Adam\: A Method for Stochastic Optimization: + https://arxiv.org/abs/1412.6980 + .. _On the Convergence of Adam and Beyond: + https://openreview.net/forum?id=ryQu7f-RZ + """ + + def __init__( + self, + params, + lr=1e-3, + betas=(0.9, 0.999), + eps=1e-8, + weight_decay=0, + amsgrad=False, + ): + defaults = dict( + lr=lr, betas=betas, eps=eps, weight_decay=weight_decay, amsgrad=amsgrad + ) + super(Adam, self).__init__(params, defaults) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step(self, closure=None): + """Performs a single optimization step. + + Arguments: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + """ + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + for p in group["params"]: + if p.grad is None: + continue + grad = p.grad.data + if grad.dtype in {torch.float16, torch.bfloat16}: + grad = grad.float() + if grad.is_sparse: + raise RuntimeError( + "Adam does not support sparse gradients, please consider SparseAdam instead" + ) + amsgrad = group.get("amsgrad", False) + + p_data_fp32 = p.data + if p.data.dtype in {torch.float16, torch.bfloat16}: + p_data_fp32 = p_data_fp32.float() + + state = self.state[p] + + # State initialization + if len(state) == 0: + state["step"] = 0 + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p_data_fp32) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like(p_data_fp32) + if amsgrad: + # Maintains max of all exp. moving avg. of sq. grad. values + state["max_exp_avg_sq"] = torch.zeros_like(p_data_fp32) + else: + state["exp_avg"] = state["exp_avg"].to(p_data_fp32) + state["exp_avg_sq"] = state["exp_avg_sq"].to(p_data_fp32) + if amsgrad: + state["max_exp_avg_sq"] = state["max_exp_avg_sq"].to( + p_data_fp32 + ) + + exp_avg, exp_avg_sq = state["exp_avg"], state["exp_avg_sq"] + if amsgrad: + max_exp_avg_sq = state["max_exp_avg_sq"] + beta1, beta2 = group["betas"] + + state["step"] += 1 + + # Decay the first and second moment running average coefficient + exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1) + exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1 - beta2) + if amsgrad: + # Maintains the maximum of all 2nd moment running avg. till now + torch.max(max_exp_avg_sq, exp_avg_sq, out=max_exp_avg_sq) + # Use the max. for normalizing running avg. of gradient + denom = max_exp_avg_sq.sqrt().add_(group["eps"]) + else: + denom = exp_avg_sq.sqrt().add_(group["eps"]) + + bias_correction1 = 1 - beta1 ** state["step"] + bias_correction2 = 1 - beta2 ** state["step"] + step_size = group["lr"] * math.sqrt(bias_correction2) / bias_correction1 + + if group["weight_decay"] != 0: + p_data_fp32.add_( + p_data_fp32, alpha=-group["weight_decay"] * group["lr"] + ) + + p_data_fp32.addcdiv_(exp_avg, denom, value=-step_size) + + if p.data.dtype in {torch.float16, torch.bfloat16}: + p.data.copy_(p_data_fp32) + + return loss diff --git a/fairseq-tools/fairseq/fairseq/optim/adamax.py b/fairseq-tools/fairseq/fairseq/optim/adamax.py new file mode 100644 index 00000000..577a6881 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/adamax.py @@ -0,0 +1,172 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +import torch.optim + +from . import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("adamax") +class FairseqAdamax(LegacyFairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = Adamax(params, **self.optimizer_config) + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--adamax-betas', default='(0.9, 0.999)', metavar='B', + help='betas for Adam optimizer') + parser.add_argument('--adamax-eps', type=float, default=1e-8, metavar='D', + help='epsilon for Adam optimizer') + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + parser.add_argument('--no-bias-correction', default=False, action='store_true', + help='disable bias correction') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "betas": eval(self.args.adamax_betas), + "eps": self.args.adamax_eps, + "weight_decay": self.args.weight_decay, + "bias_correction": not self.args.no_bias_correction, + } + + +class Adamax(torch.optim.Optimizer): + """Implements Adamax algorithm (a variant of Adam based on infinity norm). + + It has been proposed in `Adam: A Method for Stochastic Optimization`__. + + Compared to the version in PyTorch, this version implements a fix for weight decay. + + Arguments: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups + lr (float, optional): learning rate (default: 2e-3) + betas (Tuple[float, float], optional): coefficients used for computing + running averages of gradient and its square + eps (float, optional): term added to the denominator to improve + numerical stability (default: 1e-8) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + bias_correction (bool, optional): enable bias correction (default: True) + + __ https://arxiv.org/abs/1412.6980 + """ + + def __init__( + self, + params, + lr=2e-3, + betas=(0.9, 0.999), + eps=1e-8, + weight_decay=0, + bias_correction=True, + ): + if not 0.0 <= lr: + raise ValueError("Invalid learning rate: {}".format(lr)) + if not 0.0 <= eps: + raise ValueError("Invalid epsilon value: {}".format(eps)) + if not 0.0 <= betas[0] < 1.0: + raise ValueError("Invalid beta parameter at index 0: {}".format(betas[0])) + if not 0.0 <= betas[1] < 1.0: + raise ValueError("Invalid beta parameter at index 1: {}".format(betas[1])) + if not 0.0 <= weight_decay: + raise ValueError("Invalid weight_decay value: {}".format(weight_decay)) + + defaults = dict( + lr=lr, + betas=betas, + eps=eps, + weight_decay=weight_decay, + bias_correction=bias_correction, + ) + super(Adamax, self).__init__(params, defaults) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step(self, closure=None): + """Performs a single optimization step. + + Arguments: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + """ + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + for p in group["params"]: + if p.grad is None: + continue + grad = p.grad.data.float() + if grad.is_sparse: + raise RuntimeError("Adamax does not support sparse gradients") + + p_data_fp32 = p.data + if p.data.dtype in {torch.float16, torch.bfloat16}: + p_data_fp32 = p_data_fp32.float() + + state = self.state[p] + + # State initialization + if len(state) == 0: + state["step"] = 0 + state["exp_avg"] = torch.zeros_like(p_data_fp32) + state["exp_inf"] = torch.zeros_like(p_data_fp32) + else: + state["exp_avg"] = state["exp_avg"].to(p_data_fp32) + state["exp_inf"] = state["exp_inf"].to(p_data_fp32) + + exp_avg, exp_inf = state["exp_avg"], state["exp_inf"] + beta1, beta2 = group["betas"] + eps = group["eps"] + + state["step"] += 1 + + # Update biased first moment estimate. + exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1) + + # Update the exponentially weighted infinity norm. + torch.max( + exp_inf.mul_(beta2), + grad.abs_(), + out=exp_inf, + ) + + step_size = group["lr"] + if group["bias_correction"]: + bias_correction = 1 - beta1 ** state["step"] + step_size /= bias_correction + + if group["weight_decay"] != 0: + p_data_fp32.add_( + p_data_fp32, alpha=-group["weight_decay"] * group["lr"] + ) + + p_data_fp32.addcdiv_(exp_avg, exp_inf.add(eps), value=-step_size) + + if p.data.dtype in {torch.float16, torch.bfloat16}: + p.data.copy_(p_data_fp32) + + return loss diff --git a/fairseq-tools/fairseq/fairseq/optim/bmuf.py b/fairseq-tools/fairseq/fairseq/optim/bmuf.py new file mode 100644 index 00000000..3312f811 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/bmuf.py @@ -0,0 +1,231 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from dataclasses import dataclass, field + +import torch +import torch.distributed as dist +from fairseq.dataclass import FairseqDataclass +from fairseq.dataclass.utils import gen_parser_from_dataclass +from fairseq.optim.fairseq_optimizer import FairseqOptimizer +from omegaconf import II + + +@dataclass +class FairseqBMUFConfig(FairseqDataclass): + block_lr: float = field( + default=1, metadata={"help": "block learning rate for bmuf"} + ) + block_momentum: float = field( + default=0.875, metadata={"help": "block momentum for bmuf"} + ) + global_sync_iter: int = field( + default=50, metadata={"help": "Iteration for syncing global model"} + ) + warmup_iterations: int = field( + default=500, metadata={"help": "warmup iterations for model to broadcast"} + ) + use_nbm: bool = field( + default=False, + metadata={"help": "Specify whether you want to use classical BM / Nesterov BM"}, + ) + average_sync: bool = field( + default=False, + metadata={ + "help": "Specify whether you want to average the local momentum after each sync" + }, + ) + distributed_world_size: int = II( + "params.distributed_training.distributed_world_size" + ) + + +class FairseqBMUF(FairseqOptimizer): + """ + Implements incremental block distributed data parallelism similar to + https://ieeexplore.ieee.org/document/7472805 + + Paper title: Scalable training of deep learning machines by incremental + block training with intra-block parallel optimization and blockwise + model-update filtering + """ + + def __init__(self, args, optimizer): + + super().__init__(args) + self._optimizer = optimizer + self._num_updates = 0 + self.sync_iter = self.args.global_sync_iter + self.block_momentum = self.args.block_momentum + self.block_lr = self.args.block_lr + self._reset_local_data() + self.warmup_iteration = self.args.warmup_iterations + self.use_nbm = self.args.use_nbm + self.initial_state = self._optimizer.state_dict() + self.average_sync = self.args.average_sync + self.world_size = self.args.distributed_world_size + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + gen_parser_from_dataclass(parser, FairseqBMUFConfig()) + + @property + def optimizer(self): + return self._optimizer.optimizer + + @property + def optimizer_config(self): + return self._optimizer.optimizer_config + + def get_lr(self): + return self._optimizer.get_lr() + + def set_lr(self, lr): + self._optimizer.set_lr(lr) + + def state_dict(self): + return self._optimizer.state_dict() + + def load_state_dict(self, state_dict, optimizer_overrides=None): + self._optimizer.load_state_dict(state_dict, optimizer_overrides) + self.initial_state = self._optimizer.state_dict() + + def multiply_grads(self, c): + """Multiplies grads by a constant *c*.""" + self._optimizer.multiply_grads(c) + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm.""" + return self._optimizer.clip_grad_norm(max_norm, aggregate_norm_fn) + + def average_params(self): + self._optimizer.average_params() + + def _block_sync(self): + if self.world_size <= 1: + return + # Update the global model using local models from all GPUs + # (Step-1) Calculate grad between previously synced model and + # currrent local model + if self.block_momentum != 0: + self._calc_grad() + + # (Step-2) Average gradient from all GPUs + self._avg_grad_from_all_gpus() + + # (Step-3) Calculate global momentum and update the global model + if self.block_momentum != 0: + self._update_global_model() + + # (Step-4) Average local optimizer params + if self.average_sync: + self.average_params() + + def _is_warmup_end(self): + # Check whether train iterations is equal to warmup iter + if self.get_num_updates() == self.warmup_iteration: + return True + return False + + def _is_bmuf_iter(self): + # Check whether train iterations is equal to bmuf sync iter + if (self.get_num_updates() > self.warmup_iteration) and ( + self.get_num_updates() % self.sync_iter == 0 + ): + return True + return False + + def _warmup_sync(self, root_rank=0): + if self.world_size <= 1: + return + # Broadcast the local model to all gpus + for param in self.params: + dist.broadcast(param.data, src=root_rank) + + # Update local optimizer state + if self.average_sync: + self._optimizer.average_params() + else: + self._optimizer.load_state_dict(self.initial_state) + + self._reset_local_data() + + def step(self, closure=None): + """Performs a single optimization step.""" + self._optimizer.step(closure) + self.set_num_updates(self.get_num_updates() + 1) + if self._is_warmup_end(): + self._warmup_sync() + elif self._is_bmuf_iter(): + self._block_sync() + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + self._optimizer.zero_grad() + + def get_num_updates(self): + """Get the number of parameters updates.""" + return self._num_updates + + def set_num_updates(self, num_updates): + """Set the number of parameters updates.""" + self._num_updates = num_updates + + @torch.no_grad() + def _reset_local_data(self): + # (Step-0) Initialize global momentum parameters and store global copy on each gpu + self.global_params = [torch.zeros_like(p.data) for p in self.params] + self.smoothed_grads = [p.data.new_zeros(p.data.size()) for p in self.params] + self.grads = [p.data.new_zeros(p.data.size()) for p in self.params] + + # saving the global model locally for calculating gradient during bmuf sync + for param, global_param in zip(self.params, self.global_params): + global_param.copy_(param.data) + + @torch.no_grad() + def _calc_grad(self): + # global_params is basically the global copy from the previously finished + # synchronisation. param.data is local parameter after block_sync_freq + # for the local gpu. so grad is difference between previously synced + # model and currrent local model. + for index, (param, global_param) in enumerate( + zip(self.params, self.global_params) + ): + self.grads[index] = global_param - param.data + + def _avg_grad_from_all_gpus(self): + for index, param in enumerate(self.params): + sync_para = param.data if self.block_momentum == 0 else self.grads[index] + sync_para /= float(dist.get_world_size()) + dist.all_reduce(sync_para, op=dist.ReduceOp.SUM) + + @torch.no_grad() + def _update_global_model(self): + for index, (param, global_param, smoothed_grad, grad) in enumerate( + zip( + self.params, + self.global_params, + self.smoothed_grads, + # all gpus would share the same value of smoothed_grad, since it is + # always computed on synchronized gradients. + self.grads, + ) + ): + # global_param is basically last syncrhornized parameter. though + # smoothed_grad is local, all processes will have same value of + # smoothed_grad and hence param is globally synchronized copy. + # smoothed_grad(t) = BM * smoothed_grad(t-1) + BM_lr * grad(t) + smoothed_grad = self.block_momentum * smoothed_grad + self.block_lr * grad + param.data.copy_(global_param - smoothed_grad) + + # A Nesterov momentum here is to do a partial weight update before + # calculating the gradient + if self.use_nbm: + param.data.copy_(param.data - self.block_momentum * smoothed_grad) + + # backup for the next synchronization. + self.smoothed_grads[index] = smoothed_grad + global_param.copy_(param.data) diff --git a/fairseq-tools/fairseq/fairseq/optim/dynamic_loss_scaler.py b/fairseq-tools/fairseq/fairseq/optim/dynamic_loss_scaler.py new file mode 100644 index 00000000..c5da6042 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/dynamic_loss_scaler.py @@ -0,0 +1,70 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +class DynamicLossScaler(object): + def __init__( + self, + init_scale=2.0 ** 15, + scale_factor=2.0, + scale_window=2000, + tolerance=0.05, + threshold=None, + min_loss_scale=1e-4, + ): + self.loss_scale = init_scale + self.scale_factor = scale_factor + self.scale_window = scale_window + self.tolerance = tolerance + self.threshold = threshold + self._iter = 0 + self._last_overflow_iter = -1 + self._last_rescale_iter = -1 + self._overflows_since_rescale = 0 + self.min_loss_scale = min_loss_scale + + def scale(self, outputs): + return self.loss_scale * outputs + + def update(self): + if (self._iter - self._last_overflow_iter) % self.scale_window == 0: + self.loss_scale *= self.scale_factor + self._last_rescale_iter = self._iter + self._iter += 1 + + def _decrease_loss_scale(self): + self.loss_scale /= self.scale_factor + if self.threshold is not None: + self.loss_scale = max(self.loss_scale, self.threshold) + + def check_overflow(self, grad_norm): + # detect inf and nan + if grad_norm == float("inf") or grad_norm != grad_norm: + # overflow has occured + prev_scale = self.loss_scale + iter_since_rescale = self._iter - self._last_rescale_iter + + self._last_overflow_iter = self._iter + self._overflows_since_rescale += 1 + pct_overflow = self._overflows_since_rescale / float(iter_since_rescale) + if pct_overflow >= self.tolerance: + self._decrease_loss_scale() + self._last_rescale_iter = self._iter + self._overflows_since_rescale = 0 + + if self.loss_scale <= self.min_loss_scale: + # Use FloatingPointError as an uncommon error that parent + # functions can safely catch to stop training. + self.loss_scale = prev_scale + raise FloatingPointError( + ( + "Minimum loss scale reached ({}). Your loss is probably exploding. " + "Try lowering the learning rate, using gradient clipping or " + "increasing the batch size." + ).format(self.min_loss_scale) + ) + + self._iter += 1 + raise OverflowError("setting loss scale to: " + str(self.loss_scale)) diff --git a/fairseq-tools/fairseq/fairseq/optim/fairseq_optimizer.py b/fairseq-tools/fairseq/fairseq/optim/fairseq_optimizer.py new file mode 100644 index 00000000..8a10399a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/fairseq_optimizer.py @@ -0,0 +1,150 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq import utils +from fairseq.dataclass.utils import gen_parser_from_dataclass + + +class FairseqOptimizer(object): + def __init__(self, args): + super().__init__() + self.args = args + + @classmethod + def add_args(cls, parser): + """Add optimizer-specific arguments to the parser.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + gen_parser_from_dataclass(parser, dc()) + + @property + def optimizer(self): + """Return a torch.optim.optimizer.Optimizer instance.""" + if not hasattr(self, "_optimizer"): + raise NotImplementedError + if not isinstance(self._optimizer, torch.optim.Optimizer): + raise ValueError("_optimizer must be an instance of torch.optim.Optimizer") + return self._optimizer + + @optimizer.setter + def optimizer(self, optimizer): + """Reset optimizer instance.""" + if not hasattr(self, "_optimizer"): + raise NotImplementedError + if not isinstance(self._optimizer, torch.optim.Optimizer): + raise ValueError("_optimizer must be an instance of torch.optim.Optimizer") + self._optimizer = optimizer + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + raise NotImplementedError + + @property + def params(self): + """Return an iterable of the parameters held by the optimizer.""" + for param_group in self.param_groups: + for p in param_group["params"]: + yield p + + @property + def param_groups(self): + return self.optimizer.param_groups + + def __getstate__(self): + return self._optimizer.__getstate__() + + def get_lr(self): + """Return the current learning rate.""" + return self.param_groups[0]["lr"] + + def set_lr(self, lr): + """Set the learning rate.""" + for param_group in self.param_groups: + param_group["lr"] = lr + + def state_dict(self): + """Return the optimizer's state dict.""" + return self.optimizer.state_dict() + + def load_state_dict(self, state_dict, optimizer_overrides=None): + """Load an optimizer state dict. + + In general we should prefer the configuration of the existing optimizer + instance (e.g., learning rate) over that found in the state_dict. This + allows us to resume training from a checkpoint using a new set of + optimizer args. + """ + self.optimizer.load_state_dict(state_dict) + + if optimizer_overrides is not None and len(optimizer_overrides) > 0: + # override learning rate, momentum, etc. with latest values + for group in self.param_groups: + group.update(optimizer_overrides) + + def backward(self, loss): + """Computes the sum of gradients of the given tensor w.r.t. graph leaves.""" + loss.backward() + + def multiply_grads(self, c): + """Multiplies grads by a constant *c*.""" + for p in self.params: + if p.grad is not None: + p.grad.data.mul_(c) + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm.""" + return utils.clip_grad_norm_(self.params, max_norm, aggregate_norm_fn) + + def step(self, closure=None, scale=1.0): + """Performs a single optimization step.""" + if self.supports_step_with_scale: + self.optimizer.step(closure, scale=scale) + else: + if scale != 1.0: + self.multiply_grads(1.0 / scale) + self.optimizer.step(closure) + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + for p in self.params: + p.grad = None + self.optimizer.zero_grad() + + @property + def supports_memory_efficient_fp16(self): + if hasattr(self.optimizer, "supports_memory_efficient_fp16"): + return self.optimizer.supports_memory_efficient_fp16 + return False + + @property + def supports_step_with_scale(self): + if hasattr(self.optimizer, "supports_step_with_scale"): + return self.optimizer.supports_step_with_scale + return False + + @property + def supports_flat_params(self): + """ + Whether the optimizer supports collapsing of the model + parameters/gradients into a single contiguous Tensor. + """ + if hasattr(self.optimizer, "supports_flat_params"): + return self.optimizer.supports_flat_params + return False + + def average_params(self): + pass + + +class LegacyFairseqOptimizer(FairseqOptimizer): + def __init__(self, args): + self.args = args diff --git a/fairseq-tools/fairseq/fairseq/optim/fp16_optimizer.py b/fairseq-tools/fairseq/fairseq/optim/fp16_optimizer.py new file mode 100644 index 00000000..68731503 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/fp16_optimizer.py @@ -0,0 +1,491 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from collections import defaultdict +from itertools import chain + +import torch +from fairseq import optim, utils + +from .dynamic_loss_scaler import DynamicLossScaler + + +class _FP16OptimizerMixin(object): + def __init__(self, *args, **kwargs): + # forward __init__ call to the next class in mro(method resolution order) + super().__init__(*args, **kwargs) + self._multiply_factor = 1.0 + + @property + def has_flat_params(self): + return torch.is_tensor(self.fp32_params) or ( + isinstance(self.fp32_params, dict) + and all(torch.is_tensor(t) for t in self.fp32_params.values()) + ) + + @classmethod + def build_fp32_params(cls, args, params, flatten=True): + # create FP32 copy of parameters and grads + if flatten: + is_pipeline_parallel = getattr( + args, "pipeline_model_parallel", False + ) and getattr(args, "distributed_no_spawn", False) + total_param_size = sum(p.data.numel() for p in params) + devices = [torch.cuda.current_device()] + if is_pipeline_parallel: + devices = list(set(args.pipeline_devices)) + fp32_params = {} + for device in devices: + if is_pipeline_parallel: + device_param_size = sum( + p.data.numel() for p in params if p.device.index == device + ) + device_params = [p for p in params if p.device.index == device] + else: + device_param_size = total_param_size + device_params = params + fp32_params[device] = ( + device_params[0].new(0).float().new(device_param_size) + ) + offset = 0 + for p in device_params: + numel = p.data.numel() + fp32_params[device][offset : offset + numel].copy_(p.data.view(-1)) + offset += numel + fp32_params[device] = torch.nn.Parameter(fp32_params[device]) + fp32_params[device].grad = fp32_params[device].data.new( + device_param_size + ) + return fp32_params + else: + fp32_params = [] + for p in params: + p32 = torch.nn.Parameter(p.data.float()) + p32.grad = torch.zeros_like(p32.data) + fp32_params.append(p32) + return fp32_params + + def state_dict(self): + """Return the optimizer's state dict.""" + state_dict = self.fp32_optimizer.state_dict() + if self.scaler is not None: + state_dict["loss_scale"] = self.scaler.loss_scale + return state_dict + + def load_state_dict(self, state_dict, optimizer_overrides=None): + """Load an optimizer state dict. + + In general we should prefer the configuration of the existing optimizer + instance (e.g., learning rate) over that found in the state_dict. This + allows us to resume training from a checkpoint using a new set of + optimizer args. + """ + if "loss_scale" in state_dict and self.scaler is not None: + self.scaler.loss_scale = state_dict["loss_scale"] + self.fp32_optimizer.load_state_dict(state_dict, optimizer_overrides) + + def backward(self, loss): + """Computes the sum of gradients of the given tensor w.r.t. graph leaves. + + Compared to :func:`fairseq.optim.FairseqOptimizer.backward`, this + function additionally dynamically scales the loss to avoid gradient + underflow. + """ + if self.scaler is not None: + loss = self.scaler.scale(loss) + loss.backward() + self._needs_sync = True + + def _sync_fp16_grads_to_fp32(self): + if self._needs_sync: + # copy FP16 grads to FP32 + if self.has_flat_params: + devices = list(self.fp32_params.keys()) + device_params_dict = defaultdict(list) + for p in self.fp16_params: + if p.requires_grad: + device_params_dict[p.device.index].append(p) + for device in devices: + device_params = device_params_dict[device] + offset = 0 + for p in device_params: + grad_data = ( + p.grad.data + if p.grad is not None + else p.data.new_zeros(p.data.shape) + ) + numel = grad_data.numel() + self.fp32_params[device].grad.data[ + offset : offset + numel + ].copy_(grad_data.view(-1)) + offset += numel + else: + for p, p32 in zip(self.fp16_params, self.fp32_params): + if not p.requires_grad: + continue + if p.grad is not None: + p32.grad.data.copy_(p.grad.data) + else: + p32.grad = torch.zeros_like(p.data, dtype=torch.float) + + self._needs_sync = False + + def _sync_fp32_params_to_fp16(self): + # copy FP32 params back into FP16 model + if self.has_flat_params: + devices = list(self.fp32_params.keys()) + device_params_dict = defaultdict(list) + for p in self.fp16_params: + device_params_dict[p.device.index].append(p) + for device in devices: + device_params = device_params_dict[device] + offset = 0 + for p in device_params: + numel = p.data.numel() + p.data.copy_( + self.fp32_params[device] + .data[offset : offset + numel] + .view_as(p.data) + ) + offset += numel + else: + for p, p32 in zip(self.fp16_params, self.fp32_params): + if not p.requires_grad: + continue + p.data.copy_(p32.data) + + def _unscale_grads(self): + self._sync_fp16_grads_to_fp32() + if self._multiply_factor != 1.0: + self.fp32_optimizer.multiply_grads(self._multiply_factor) + self._multiply_factor = 1.0 + + def multiply_grads(self, c): + """Multiplies grads by a constant ``c``.""" + self._multiply_factor *= c + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm and updates dynamic loss scaler.""" + self._sync_fp16_grads_to_fp32() + + grad_norm = self._multiply_factor * self.fp32_optimizer.clip_grad_norm( + 0, aggregate_norm_fn + ) + + if self.scaler is not None: + if grad_norm > max_norm > 0.0: + self._multiply_factor *= max_norm / grad_norm + + self.scaler.check_overflow(grad_norm) + elif max_norm > 0.0: + clip_coef = (max_norm / (grad_norm + 1e-6)).clamp_(max=1) + self._multiply_factor *= clip_coef + + return grad_norm + + def step(self, closure=None): + """Performs a single optimization step.""" + self._sync_fp16_grads_to_fp32() + + if getattr(self, "supports_step_with_scale", False): + self.fp32_optimizer.step(closure, scale=(1.0 / self._multiply_factor)) + else: + self._unscale_grads() + self.fp32_optimizer.step(closure) + + if self.scaler is not None: + self.scaler.update() + + self._sync_fp32_params_to_fp16() + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + for p in self.fp16_params: + p.grad = None + if self.has_flat_params: + if torch.is_tensor(self.fp32_params): + self.fp32_params.grad.zero_() + elif isinstance(self.fp32_params, dict): + for fp32_params in self.fp32_params.values(): + fp32_params.grad.zero_() + else: + raise ("self.fp32_params must be a tensor or dict") + else: + for p32 in self.fp32_params: + if p32.grad is None: + p32.grad.zero_() + self._needs_sync = False + + if self.scaler is not None: + self._multiply_factor = 1.0 / float(self.scaler.loss_scale) + + +class FP16Optimizer(_FP16OptimizerMixin, optim.FairseqOptimizer): + """ + Wrap an *optimizer* to support FP16 (mixed precision) training. + """ + + def __init__(self, args, params, fp32_optimizer, fp32_params): + super().__init__(args) + self.fp16_params = params + self.fp32_optimizer = fp32_optimizer + self.fp32_params = fp32_params + + if getattr(args, "fp16_scale_window", None) is None: + if len(args.update_freq) > 1: + raise ValueError( + "--fp16-scale-window must be given explicitly when using a " + "custom --update-freq schedule" + ) + data_parallel_size = int( + args.distributed_world_size / args.model_parallel_size + ) + scale_window = int(2 ** 14 / data_parallel_size / args.update_freq[0]) + else: + scale_window = args.fp16_scale_window + + if not getattr(args, "bf16", False): + self.scaler = DynamicLossScaler( + init_scale=args.fp16_init_scale, + scale_window=scale_window, + tolerance=args.fp16_scale_tolerance, + threshold=args.threshold_loss_scale, + min_loss_scale=args.min_loss_scale, + ) + else: + # disable loss scaling for bfloat16 + self.scaler = None + + @classmethod + def build_optimizer(cls, args, params): + """ + Args: + args (argparse.Namespace): fairseq args + params (iterable): iterable of parameters to optimize + """ + flatten = not getattr(args, "fp16_no_flatten_grads", False) + if getattr(args, "bf16", False): + flatten = False # mixed precision is faster on TPUs without flat grads + fp32_params = cls.build_fp32_params(args, params, flatten=flatten) + if flatten: + fp32_optimizer = optim.build_optimizer(args, [fp32_params]) + else: + fp32_optimizer = optim.build_optimizer(args, fp32_params) + if flatten and not fp32_optimizer.supports_flat_params: + raise RuntimeError( + "chosen optimizer does not support flat params, " + "please set --fp16-no-flatten-grads" + ) + return cls(args, params, fp32_optimizer, fp32_params) + + @property + def optimizer(self): + return self.fp32_optimizer.optimizer + + @optimizer.setter + def optimizer(self, optimizer): + self.fp32_optimizer.optimizer = optimizer + + @property + def optimizer_config(self): + return self.fp32_optimizer.optimizer_config + + def get_lr(self): + return self.fp32_optimizer.get_lr() + + def set_lr(self, lr): + self.fp32_optimizer.set_lr(lr) + + +class _MemoryEfficientFP16OptimizerMixin(object): + def __init__(self, *args, **kwargs): + # forward __init__ call to the next class in MRO (method resolution order) + super().__init__(*args, **kwargs) + self._multiply_factor = 1.0 + + @property + def has_flat_params(self): + return False + + def state_dict(self): + """Return the optimizer's state dict.""" + state_dict = self.wrapped_optimizer.state_dict() + if self.scaler is not None: + state_dict["loss_scale"] = self.scaler.loss_scale + return state_dict + + def load_state_dict(self, state_dict, optimizer_overrides=None): + """Load an optimizer state dict. + + In general we should prefer the configuration of the existing optimizer + instance (e.g., learning rate) over that found in the state_dict. This + allows us to resume training from a checkpoint using a new set of + optimizer args. + """ + if "loss_scale" in state_dict and self.scaler is not None: + self.scaler.loss_scale = state_dict["loss_scale"] + + self.wrapped_optimizer.load_state_dict(state_dict, optimizer_overrides) + + # Hack: PyTorch automatically casts the optimizer state to match the + # type of the current parameters. But with --memory-efficient-fp16 the + # params are FP16 while the optimizer state is FP32 and we don't want + # to cast. A workaround is to manually copy back the original state + # after the optimizer has been loaded. + if not getattr(self.optimizer, "disable_mem_eff_fp16_loading_hack", False): + groups = self.optimizer.param_groups + saved_groups = state_dict["param_groups"] + id_map = { + old_id: p + for old_id, p in zip( + chain(*(g["params"] for g in saved_groups)), + chain(*(g["params"] for g in groups)), + ) + } + for k, v in state_dict["state"].items(): + if k in id_map: + param = id_map[k] + self.optimizer.state[param] = v + + def backward(self, loss): + """Computes the sum of gradients of the given tensor w.r.t. graph leaves. + + Compared to :func:`fairseq.optim.FairseqOptimizer.backward`, this + function additionally dynamically scales the loss to avoid gradient + underflow. + """ + if self.scaler is not None: + loss = self.scaler.scale(loss) + loss.backward() + + def _unscale_grads(self): + if self._multiply_factor != 1.0: + self.wrapped_optimizer.multiply_grads(self._multiply_factor) + self._multiply_factor = 1.0 + + def multiply_grads(self, c): + """Multiplies grads by a constant *c*.""" + self._multiply_factor *= c + + def clip_grad_norm(self, max_norm, aggregate_norm_fn=None): + """Clips gradient norm and updates dynamic loss scaler.""" + max_norm = float(max_norm) + grad_norm = self._multiply_factor * self.wrapped_optimizer.clip_grad_norm( + 0, aggregate_norm_fn + ) + + if self.scaler is not None: + grad_norm_cpu = float(grad_norm) + if grad_norm_cpu > max_norm > 0.0: + self._multiply_factor *= max_norm / grad_norm_cpu + + # detect overflow and adjust loss scale + self.scaler.check_overflow(grad_norm_cpu) + elif max_norm > 0.0: + clip_coef = (max_norm / (grad_norm + 1e-6)).clamp_(max=1) + self._multiply_factor *= clip_coef + + return grad_norm + + def step(self, closure=None): + """Performs a single optimization step.""" + if getattr(self, "supports_step_with_scale", False): + # NOTE(msb) optimizer divides by scale factor + self.wrapped_optimizer.step(closure, scale=(1.0 / self._multiply_factor)) + else: + self._unscale_grads() + self.wrapped_optimizer.step(closure) + + if self.scaler is not None: + self.scaler.update() + + def zero_grad(self): + """Clears the gradients of all optimized parameters.""" + self.wrapped_optimizer.zero_grad() + if self.scaler is not None: + self._multiply_factor = 1.0 / float(self.scaler.loss_scale) + else: + self._multiply_factor = 1.0 + + +class MemoryEfficientFP16Optimizer( + _MemoryEfficientFP16OptimizerMixin, optim.FairseqOptimizer +): + """ + Wrap an *optimizer* to support FP16 (mixed precision) training. + + Compared to :class:`fairseq.optim.FP16Optimizer`, this version does not + maintain an FP32 copy of the model. We instead expect the optimizer to + convert the gradients to FP32 internally and sync the results back to the + FP16 model params. This significantly reduces memory usage but slightly + increases the time spent in the optimizer. + + Since this wrapper depends on specific functionality in the wrapped + optimizer (i.e., on-the-fly conversion of grads to FP32), only certain + optimizers can be wrapped. This is determined by the + *supports_memory_efficient_fp16* property. + """ + + def __init__(self, args, params, optimizer): + if not optimizer.supports_memory_efficient_fp16: + raise ValueError( + "Unsupported optimizer: {}".format(optimizer.__class__.__name__) + ) + + super().__init__(args) + self.wrapped_optimizer = optimizer + + if getattr(args, "fp16_scale_window", None) is None: + if len(args.update_freq) > 1: + raise ValueError( + "--fp16-scale-window must be given explicitly when using a " + "custom --update-freq schedule" + ) + data_parallel_size = int( + args.distributed_world_size / args.model_parallel_size + ) + scale_window = 2 ** 14 / data_parallel_size / args.update_freq[0] + else: + scale_window = args.fp16_scale_window + + if not getattr(args, "bf16", False): + self.scaler = DynamicLossScaler( + init_scale=args.fp16_init_scale, + scale_window=scale_window, + tolerance=args.fp16_scale_tolerance, + threshold=args.threshold_loss_scale, + min_loss_scale=args.min_loss_scale, + ) + else: + # disable loss scaling for bfloat16 + self.scaler = None + + @classmethod + def build_optimizer(cls, args, params): + """ + Args: + args (argparse.Namespace): fairseq args + params (iterable): iterable of parameters to optimize + """ + fp16_optimizer = optim.build_optimizer(args, params) + return cls(args, params, fp16_optimizer) + + @property + def optimizer(self): + return self.wrapped_optimizer.optimizer + + @optimizer.setter + def optimizer(self, optimizer): + self.wrapped_optimizer.optimizer = optimizer + + @property + def optimizer_config(self): + return self.wrapped_optimizer.optimizer_config + + def get_lr(self): + return self.wrapped_optimizer.get_lr() + + def set_lr(self, lr): + self.wrapped_optimizer.set_lr(lr) diff --git a/fairseq-tools/fairseq/fairseq/optim/fused_adam.py b/fairseq-tools/fairseq/fairseq/optim/fused_adam.py new file mode 100644 index 00000000..1780f9c0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/fused_adam.py @@ -0,0 +1,348 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import types + +import torch + + +def get_fused_adam_class(): + """ + Look for the FusedAdam optimizer from apex. We first try to load the + "contrib" interface, which is a bit faster than the main interface, + but is technically deprecated. + """ + try: + # The "deprecated" interface in recent versions of apex is a bit + # faster than the main interface, since we don't use the apex + # optimizer. This can be installed by passing the + # `--deprecated_fused_adam` option when building apex. + global fused_adam_cuda + import importlib + + fused_adam_cuda = importlib.import_module("fused_adam_cuda") + return FusedAdamV1 + except ImportError: + try: + # fallback to the newer interface + from apex.optimizers import FusedAdam as _FusedAdam # noqa + from apex.multi_tensor_apply import multi_tensor_applier + + if multi_tensor_applier.available: + return FusedAdamV2 + except ImportError: + pass + return None + + +class FusedAdamV1(torch.optim.Optimizer): + """ + Implements Adam algorithm. Currently GPU-only. Requires Apex to be installed via + ``python setup.py install --cuda_ext --cpp_ext``. + + It has been proposed in `Adam: A Method for Stochastic Optimization`_. + + Compared to the original version in Apex, the fairseq version casts grads + and params to FP32 internally to support ``--memory-efficient-fp16``. + + Arguments: + params (iterable): iterable of parameters to optimize or dicts defining + parameter groups. + lr (float, optional): learning rate. (default: 1e-3) + betas (Tuple[float, float], optional): coefficients used for computing + running averages of gradient and its square. (default: (0.9, 0.999)) + eps (float, optional): term added to the denominator to improve + numerical stability. (default: 1e-8) + weight_decay (float, optional): weight decay (L2 penalty) (default: 0) + amsgrad (boolean, optional): whether to use the AMSGrad variant of this + algorithm from the paper `On the Convergence of Adam and Beyond`_ + (default: False) NOT SUPPORTED in FusedAdam! + eps_inside_sqrt (boolean, optional): in the 'update parameters' step, + adds eps to the bias-corrected second moment estimate before + evaluating square root instead of adding it to the square root of + second moment estimate as in the original paper. (default: False) + .. _Adam: A Method for Stochastic Optimization: + https://arxiv.org/abs/1412.6980 + .. _On the Convergence of Adam and Beyond: + https://openreview.net/forum?id=ryQu7f-RZ + """ + + def __init__( + self, + params, + lr=1e-3, + bias_correction=True, + betas=(0.9, 0.999), + eps=1e-8, + eps_inside_sqrt=False, + weight_decay=0.0, + max_grad_norm=0.0, + amsgrad=False, + ): + global fused_adam_cuda + import importlib + + fused_adam_cuda = importlib.import_module("fused_adam_cuda") + + if amsgrad: + raise RuntimeError("FusedAdam does not support the AMSGrad variant.") + defaults = { + "lr": lr, + "bias_correction": bias_correction, + "betas": betas, + "eps": eps, + "weight_decay": weight_decay, + "max_grad_norm": max_grad_norm, + } + super().__init__(params, defaults) + self.eps_mode = 0 if eps_inside_sqrt else 1 + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + @property + def supports_step_with_scale(self): + return True + + def step(self, closure=None, grads=None, scale=1.0, grad_norms=None): + """Performs a single optimization step. + Arguments: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + grads (list of tensors, optional): weight gradient to use for the + optimizer update. If gradients have type torch.half, parameters + are expected to be in type torch.float. (default: None) + output params (list of tensors, optional): A reduced precision copy + of the updated weights written out in addition to the regular + updated weights. Have to be of same type as gradients. (default: None) + scale (float, optional): factor to divide gradient tensor values + by before applying to weights. (default: 1) + """ + loss = None + if closure is not None: + loss = closure() + + if grads is None: + grads_group = [None] * len(self.param_groups) + # backward compatibility + # assuming a list/generator of parameter means single group + elif isinstance(grads, types.GeneratorType): + grads_group = [grads] + elif type(grads[0]) != list: + grads_group = [grads] + else: + grads_group = grads + + if grad_norms is None: + grad_norms = [None] * len(self.param_groups) + + for group, grads_this_group, grad_norm in zip( + self.param_groups, grads_group, grad_norms + ): + if grads_this_group is None: + grads_this_group = [None] * len(group["params"]) + + # compute combined scale factor for this group + combined_scale = scale + if group.get("max_grad_norm", 0) > 0: + # norm is in fact norm*scale + clip = ((grad_norm / scale) + 1e-6) / group["max_grad_norm"] + if clip > 1: + combined_scale = clip * scale + + bias_correction = 1 if group.get("bias_correction", 1) else 0 + + for p, grad in zip(group["params"], grads_this_group): + # note: p.grad should not ever be set for correct + # operation of mixed precision optimizer that sometimes + # sends None gradients + if p.grad is None and grad is None: + continue + if grad is None: + grad = p.grad.data + if grad.is_sparse: + raise RuntimeError( + "FusedAdam does not support sparse gradients, " + "please consider SparseAdam instead" + ) + + p_data_fp32 = p.data.float() + + state = self.state[p] + + # State initialization + if len(state) == 0: + state["step"] = 0 + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p_data_fp32) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like(p_data_fp32) + else: + state["exp_avg"] = state["exp_avg"].to(p_data_fp32) + state["exp_avg_sq"] = state["exp_avg_sq"].to(p_data_fp32) + + exp_avg = state["exp_avg"] + exp_avg_sq = state["exp_avg_sq"] + beta1, beta2 = group["betas"] + + state["step"] += 1 + + out_p = p.data + with torch.cuda.device(p.device): + fused_adam_cuda.adam( + p_data_fp32, + out_p, + exp_avg, + exp_avg_sq, + grad, + group["lr"], + beta1, + beta2, + group["eps"], + combined_scale, + state["step"], + self.eps_mode, + bias_correction, + group["weight_decay"], + ) + + return loss + + +try: + from apex.optimizers import FusedAdam + from apex.multi_tensor_apply import multi_tensor_applier + + class FusedAdamV2(FusedAdam): + """ + Compared to the original version in Apex, the fairseq version casts grads + and params to FP32 internally to support ``--memory-efficient-fp16``. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if not hasattr(self, "multi_tensor_adam"): + raise Exception( + "Apex installation is outdated. Please install an updated version of apex." + ) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step( + self, + closure=None, + grads=None, + output_params=None, + scale=None, + grad_norms=None, + ): + """Performs a single optimization step.""" + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + bias_correction = 1 if group["bias_correction"] else 0 + beta1, beta2 = group["betas"] + + # assume same step across group now to simplify things + # per parameter step can be easily support by making it tensor, or pass list into kernel + if "step" in group: + group["step"] += 1 + else: + group["step"] = 1 + + # create lists for multi-tensor apply + g_16, p_16, orig_p_16, m_16, v_16 = [], [], [], [], [] + g_32, p_32, m_32, v_32 = [], [], [], [] + + for p in group["params"]: + if p.grad is None: + continue + if p.grad.data.is_sparse: + raise RuntimeError( + "FusedAdam does not support sparse gradients, " + "please consider SparseAdam instead" + ) + + state = self.state[p] + # State initialization + if len(state) == 0: + # Exponential moving average of gradient values + state["exp_avg"] = torch.zeros_like(p.data, dtype=torch.float) + # Exponential moving average of squared gradient values + state["exp_avg_sq"] = torch.zeros_like( + p.data, dtype=torch.float + ) + else: + state["exp_avg"] = state["exp_avg"].to( + device=p.data.device, dtype=torch.float + ) + state["exp_avg_sq"] = state["exp_avg_sq"].to( + device=p.data.device, dtype=torch.float + ) + + if p.dtype == torch.float16: + g_16.append(p.grad.data.float()) + p_16.append(p.data.float()) + orig_p_16.append(p.data) + m_16.append(state["exp_avg"]) + v_16.append(state["exp_avg_sq"]) + elif p.dtype == torch.float32: + g_32.append(p.grad.data) + p_32.append(p.data) + m_32.append(state["exp_avg"]) + v_32.append(state["exp_avg_sq"]) + else: + raise RuntimeError("FusedAdam only support fp16 and fp32.") + + with torch.cuda.device(p.device): + if len(g_16) > 0: + multi_tensor_applier( + self.multi_tensor_adam, + self._dummy_overflow_buf, + [g_16, p_16, m_16, v_16], + group["lr"], + beta1, + beta2, + group["eps"], + group["step"], + self.adam_w_mode, + bias_correction, + group["weight_decay"], + ) + for orig_p, p in zip(orig_p_16, p_16): + orig_p.copy_(p.data) + if len(g_32) > 0: + multi_tensor_applier( + self.multi_tensor_adam, + self._dummy_overflow_buf, + [g_32, p_32, m_32, v_32], + group["lr"], + beta1, + beta2, + group["eps"], + group["step"], + self.adam_w_mode, + bias_correction, + group["weight_decay"], + ) + + return loss + + +except ImportError: + pass diff --git a/fairseq-tools/fairseq/fairseq/optim/fused_lamb.py b/fairseq-tools/fairseq/fairseq/optim/fused_lamb.py new file mode 100644 index 00000000..f4f2bdb0 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/fused_lamb.py @@ -0,0 +1,51 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.optim import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("lamb") +class FairseqLAMB(LegacyFairseqOptimizer): + """LAMB optimizer.""" + + def __init__(self, args, params): + super().__init__(args) + try: + from apex.optimizers import FusedLAMB + + self._optimizer = FusedLAMB(params, **self.optimizer_config) + except ImportError: + raise ImportError("Please install apex to use LAMB optimizer") + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--lamb-betas', default='(0.9, 0.999)', metavar='B', + help='betas for LAMB optimizer') + parser.add_argument('--lamb-eps', type=float, default=1e-8, metavar='D', + help='epsilon for LAMB optimizer') + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "betas": eval(self.args.lamb_betas), + "eps": self.args.lamb_eps, + "weight_decay": self.args.weight_decay, + } + + @property + def supports_flat_params(self): + return False diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/__init__.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/__init__.py new file mode 100644 index 00000000..7b72c257 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/__init__.py @@ -0,0 +1,38 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +import importlib +import os +from argparse import Namespace +from typing import Union + +from fairseq import registry +from fairseq.optim.lr_scheduler.fairseq_lr_scheduler import ( # noqa + FairseqLRScheduler, + LegacyFairseqLRScheduler, +) +from omegaconf import DictConfig + + +( + build_lr_scheduler_, + register_lr_scheduler, + LR_SCHEDULER_REGISTRY, + LR_SCHEDULER_DATACLASS_REGISTRY, +) = registry.setup_registry( + "--lr-scheduler", base_class=FairseqLRScheduler, default="fixed" +) + + +def build_lr_scheduler(lr_scheduler_cfg: Union[DictConfig, Namespace], optimizer): + return build_lr_scheduler_(lr_scheduler_cfg, optimizer) + + +# automatically import any Python files in the optim/lr_scheduler/ directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + file_name = file[: file.find(".py")] + importlib.import_module("fairseq.optim.lr_scheduler." + file_name) diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/cosine_lr_scheduler.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/cosine_lr_scheduler.py new file mode 100644 index 00000000..98d55750 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/cosine_lr_scheduler.py @@ -0,0 +1,145 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from dataclasses import dataclass, field +from typing import List + +from fairseq.dataclass import FairseqDataclass +from omegaconf import II + +from . import FairseqLRScheduler, register_lr_scheduler + + +@dataclass +class CosineConfig(FairseqDataclass): + warmup_updates: int = field( + default=0, + metadata={"help": "warmup the learning rate linearly for the first N updates"}, + ) + warmup_init_lr: float = field( + default=-1, + metadata={ + "help": "initial learning rate during warmup phase; default is args.lr" + }, + ) + max_lr: float = field( + default=1.0, metadata={"help": "max learning rate, must be more than args.lr"} + ) + t_mult: float = field( + default=1.0, metadata={"help": "factor to grow the length of each period"} + ) + lr_period_updates: float = field( + default=-1, metadata={"help": "initial number of updates per period"} + ) + lr_shrink: float = field( + default=0.1, metadata={"help": "shrink factor for annealing"} + ) + # TODO common var for parent class + lr: List[float] = II("params.optimization.lr") + max_update: int = II("params.optimization.max_update") + + +@register_lr_scheduler("cosine", dataclass=CosineConfig) +class CosineSchedule(FairseqLRScheduler): + """Assign LR based on a cyclical schedule that follows the cosine function. + + See https://arxiv.org/pdf/1608.03983.pdf for details. + + We also support a warmup phase where we linearly increase the learning rate + from some initial learning rate (``--warmup-init-lr``) until the configured + max learning rate (``--max-lr``). + + During warmup:: + + lrs = torch.linspace(args.warmup_init_lr, args.lr, args.warmup_updates) + lr = lrs[update_num] + + After warmup:: + + lr = lr_min + 0.5*(lr_max - lr_min)*(1 + cos(t_curr / t_i)) + + where ``t_curr`` is current percentage of updates within the current period + range and ``t_i`` is the current period range, which is scaled by ``t_mul`` + after every iteration. + """ + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + if len(args.lr) > 1: + raise ValueError( + "Cannot use a fixed learning rate schedule with cosine." + " Consider --lr-scheduler=fixed instead." + ) + + warmup_end_lr = args.max_lr + if args.warmup_init_lr < 0: + args.warmup_init_lr = args.lr[0] + + self.min_lr = args.lr[0] + self.max_lr = args.max_lr + + assert self.max_lr > self.min_lr, "max_lr must be more than lr" + + self.t_mult = args.t_mult + self.period = args.lr_period_updates + + if self.period <= 0: + assert ( + args.max_update >= 0 + ), "Either --max_update or --lr-period-updates must be set" + self.period = args.max_update - args.warmup_updates + + if args.warmup_updates > 0: + # linearly warmup for the first args.warmup_updates + self.lr_step = (warmup_end_lr - args.warmup_init_lr) / args.warmup_updates + else: + self.lr_step = 1 + + self.warmup_updates = args.warmup_updates + self.lr_shrink = args.lr_shrink + + # initial learning rate + self.lr = args.warmup_init_lr + self.optimizer.set_lr(self.lr) + + def step(self, epoch, val_loss=None): + """Update the learning rate at the end of the given epoch.""" + super().step(epoch, val_loss) + # we don't change the learning rate at epoch boundaries + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + if num_updates < self.args.warmup_updates: + self.lr = self.args.warmup_init_lr + num_updates * self.lr_step + else: + curr_updates = num_updates - self.args.warmup_updates + if self.t_mult != 1: + i = math.floor( + math.log( + 1 - curr_updates / self.period * (1 - self.t_mult), self.t_mult + ) + ) + t_i = self.t_mult ** i * self.period + t_curr = ( + curr_updates + - (1 - self.t_mult ** i) / (1 - self.t_mult) * self.period + ) + else: + i = math.floor(curr_updates / self.period) + t_i = self.period + t_curr = curr_updates - (self.period * i) + + lr_shrink = self.lr_shrink ** i + min_lr = self.min_lr * lr_shrink + max_lr = self.max_lr * lr_shrink + + self.lr = min_lr + 0.5 * (max_lr - min_lr) * ( + 1 + math.cos(math.pi * t_curr / t_i) + ) + + self.optimizer.set_lr(self.lr) + return self.lr diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fairseq_lr_scheduler.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fairseq_lr_scheduler.py new file mode 100644 index 00000000..e0253748 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fairseq_lr_scheduler.py @@ -0,0 +1,60 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from argparse import Namespace + +from fairseq.dataclass.utils import gen_parser_from_dataclass + +from .. import FairseqOptimizer + + +class FairseqLRScheduler(object): + def __init__(self, args, optimizer): + super().__init__() + if not isinstance(optimizer, FairseqOptimizer): + raise ValueError("optimizer must be an instance of FairseqOptimizer") + self.args = args + self.optimizer = optimizer + self.best = None + + @classmethod + def add_args(cls, parser): + """Add arguments to the parser for this LR scheduler.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + gen_parser_from_dataclass(parser, dc()) + + def state_dict(self): + """Return the LR scheduler state dict.""" + return {"best": self.best} + + def load_state_dict(self, state_dict): + """Load an LR scheduler state dict.""" + self.best = state_dict["best"] + + def step_begin_epoch(self, epoch): + """Update the learning rate at the beginning of the given epoch.""" + pass + + def step(self, epoch, val_loss=None): + """Update the learning rate at the end of the given epoch.""" + if val_loss is not None: + if self.best is None: + self.best = val_loss + else: + self.best = min(self.best, val_loss) + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + return self.optimizer.get_lr() + + +class LegacyFairseqLRScheduler(FairseqLRScheduler): + def __init__(self, args: Namespace, optimizer): + if not isinstance(optimizer, FairseqOptimizer): + raise ValueError("optimizer must be an instance of FairseqOptimizer") + self.args = args + self.optimizer = optimizer + self.best = None diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fixed_schedule.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fixed_schedule.py new file mode 100644 index 00000000..e91ba86f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/fixed_schedule.py @@ -0,0 +1,69 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import LegacyFairseqLRScheduler, register_lr_scheduler + + +@register_lr_scheduler("fixed") +class FixedSchedule(LegacyFairseqLRScheduler): + """Decay the LR on a fixed schedule.""" + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + + # set defaults + args.warmup_updates = getattr(args, "warmup_updates", 0) or 0 + + self.lr = args.lr[0] + if args.warmup_updates > 0: + self.warmup_factor = 1.0 / args.warmup_updates + else: + self.warmup_factor = 1 + + @staticmethod + def add_args(parser): + """Add arguments to the parser for this LR scheduler.""" + # fmt: off + parser.add_argument('--force-anneal', '--fa', type=int, metavar='N', + help='force annealing at specified epoch (epochs start at 1)') + parser.add_argument('--lr-shrink', default=0.1, type=float, metavar='LS', + help='shrink factor for annealing, lr_new = (lr * lr_shrink)') + parser.add_argument('--warmup-updates', default=0, type=int, metavar='N', + help='warmup the learning rate linearly for the first N updates') + # fmt: on + + def state_dict(self): + return {"lr": self.lr} + + def load_state_dict(self, state_dict): + if "lr" in state_dict: + self.lr = state_dict["lr"] + + def get_next_lr(self, epoch): + lrs = self.args.lr + if self.args.force_anneal is None or epoch < self.args.force_anneal: + # use fixed LR schedule + next_lr = lrs[min(epoch - 1, len(lrs) - 1)] + else: + # annneal based on lr_shrink + next_lr = lrs[-1] * self.args.lr_shrink ** ( + epoch + 1 - self.args.force_anneal + ) + return next_lr + + def step_begin_epoch(self, epoch): + """Update the learning rate at the beginning of the given epoch.""" + self.lr = self.get_next_lr(epoch) + self.optimizer.set_lr(self.warmup_factor * self.lr) + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + if self.args.warmup_updates > 0 and num_updates < self.args.warmup_updates: + self.warmup_factor = (num_updates + 1) / float(self.args.warmup_updates) + self.optimizer.set_lr(self.warmup_factor * self.lr) + else: + self.optimizer.set_lr(self.lr) + return self.optimizer.get_lr() diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/inverse_square_root_schedule.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/inverse_square_root_schedule.py new file mode 100644 index 00000000..d27261ad --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/inverse_square_root_schedule.py @@ -0,0 +1,85 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from dataclasses import dataclass, field +from typing import List + +from fairseq.dataclass import FairseqDataclass +from omegaconf import II + +from . import FairseqLRScheduler, register_lr_scheduler + + +@dataclass +class InverseSquareRootScheduleConfig(FairseqDataclass): + warmup_updates: int = field( + default=4000, + metadata={"help": "warmup the learning rate linearly for the first N updates"}, + ) + warmup_init_lr: float = field( + default=-1, + metadata={ + "help": "initial learning rate during warmup phase; default is args.lr" + }, + ) + # TODO common vars at parent class + lr: List[float] = II("params.optimization.lr") + + +@register_lr_scheduler("inverse_sqrt", dataclass=InverseSquareRootScheduleConfig) +class InverseSquareRootSchedule(FairseqLRScheduler): + """Decay the LR based on the inverse square root of the update number. + + We also support a warmup phase where we linearly increase the learning rate + from some initial learning rate (``--warmup-init-lr``) until the configured + learning rate (``--lr``). Thereafter we decay proportional to the number of + updates, with a decay factor set to align with the configured learning rate. + + During warmup:: + + lrs = torch.linspace(args.warmup_init_lr, args.lr, args.warmup_updates) + lr = lrs[update_num] + + After warmup:: + + decay_factor = args.lr * sqrt(args.warmup_updates) + lr = decay_factor / sqrt(update_num) + """ + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + if len(args.lr) > 1: + raise ValueError( + "Cannot use a fixed learning rate schedule with inverse_sqrt." + " Consider --lr-scheduler=fixed instead." + ) + warmup_end_lr = args.lr[0] + if args.warmup_init_lr < 0: + args.warmup_init_lr = 0 if args.warmup_updates > 0 else warmup_end_lr + + # linearly warmup for the first args.warmup_updates + self.lr_step = (warmup_end_lr - args.warmup_init_lr) / args.warmup_updates + + # then, decay prop. to the inverse square root of the update number + self.decay_factor = warmup_end_lr * args.warmup_updates ** 0.5 + + # initial learning rate + self.lr = args.warmup_init_lr + self.optimizer.set_lr(self.lr) + + def step(self, epoch, val_loss=None): + """Update the learning rate at the end of the given epoch.""" + super().step(epoch, val_loss) + # we don't change the learning rate at epoch boundaries + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + if num_updates < self.args.warmup_updates: + self.lr = self.args.warmup_init_lr + num_updates * self.lr_step + else: + self.lr = self.decay_factor * num_updates ** -0.5 + self.optimizer.set_lr(self.lr) + return self.lr diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/polynomial_decay_schedule.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/polynomial_decay_schedule.py new file mode 100644 index 00000000..63adc740 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/polynomial_decay_schedule.py @@ -0,0 +1,81 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from . import LegacyFairseqLRScheduler, register_lr_scheduler + + +@register_lr_scheduler("polynomial_decay") +class PolynomialDecaySchedule(LegacyFairseqLRScheduler): + """Decay the LR on a fixed schedule.""" + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + + # set defaults + args.warmup_updates = getattr(args, "warmup_updates", 0) or 0 + + self.lr = args.lr[0] + if args.warmup_updates > 0: + self.warmup_factor = 1.0 / args.warmup_updates + else: + self.warmup_factor = 1 + self.end_learning_rate = args.end_learning_rate + self.total_num_update = args.total_num_update + self.power = args.power + self.optimizer.set_lr(self.warmup_factor * self.lr) + + @staticmethod + def add_args(parser): + """Add arguments to the parser for this LR scheduler.""" + parser.add_argument( + "--force-anneal", + "--fa", + type=int, + metavar="N", + help="force annealing at specified epoch", + ) + parser.add_argument( + "--warmup-updates", + default=0, + type=int, + metavar="N", + help="warmup the learning rate linearly for the first N updates", + ) + parser.add_argument("--end-learning-rate", default=0.0, type=float) + parser.add_argument("--power", default=1.0, type=float) + parser.add_argument("--total-num-update", default=1000000, type=int) + + def get_next_lr(self, epoch): + lrs = self.args.lr + if self.args.force_anneal is None or epoch < self.args.force_anneal: + # use fixed LR schedule + next_lr = lrs[min(epoch, len(lrs) - 1)] + else: + # annneal based on lr_shrink + next_lr = self.optimizer.get_lr() + return next_lr + + def step_begin_epoch(self, epoch): + """Update the learning rate at the beginning of the given epoch.""" + self.lr = self.get_next_lr(epoch) + self.optimizer.set_lr(self.warmup_factor * self.lr) + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + if self.args.warmup_updates > 0 and num_updates <= self.args.warmup_updates: + self.warmup_factor = num_updates / float(self.args.warmup_updates) + lr = self.warmup_factor * self.lr + elif num_updates >= self.total_num_update: + lr = self.end_learning_rate + else: + warmup = self.args.warmup_updates + lr_range = self.lr - self.end_learning_rate + pct_remaining = 1 - (num_updates - warmup) / ( + self.total_num_update - warmup + ) + lr = lr_range * pct_remaining ** (self.power) + self.end_learning_rate + self.optimizer.set_lr(lr) + return self.optimizer.get_lr() diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/reduce_lr_on_plateau.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/reduce_lr_on_plateau.py new file mode 100644 index 00000000..82bb36ef --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/reduce_lr_on_plateau.py @@ -0,0 +1,115 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.optim.lr_scheduler + +from . import LegacyFairseqLRScheduler, register_lr_scheduler + + +@register_lr_scheduler("reduce_lr_on_plateau") +class ReduceLROnPlateau(LegacyFairseqLRScheduler): + """ + Decay the LR by a factor every time the validation loss plateaus. + Also comes with optional warmup phase, where we linearly increase + the learning rate from some initial learning rate + (``--warmup-init-lr``) until the configured learning rate + (``--lr``). Thereafter the lr is adjusted according to original + reduce_on_plateau scheme. + + During warmup:: + + lrs = torch.linspace( + args.warmup_init_lr, args.lr, args.warmup_updates + ) + lr = lrs[update_num] + """ + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + if len(args.lr) > 1: + raise ValueError( + "Cannot use a fixed learning rate schedule with reduce_lr_on_plateau." + " Consider --lr-scheduler=fixed instead." + ) + self.lr_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau( + self.optimizer.optimizer, + patience=args.lr_patience, + factor=args.lr_shrink, + mode="max" if args.maximize_best_checkpoint_metric else "min", + threshold=args.lr_threshold, + ) + warmup_end_lr = args.lr[0] + # if no warm up, sets initial lr to be args.lr[0] + if args.warmup_init_lr < 0: + args.warmup_init_lr = 0 if args.warmup_updates > 0 else warmup_end_lr + + # linearly warmup for the first args.warmup_updates + if args.warmup_updates > 0: + self.lr_step = (warmup_end_lr - args.warmup_init_lr) / args.warmup_updates + + # this flag is either set from arg when no warm up, or set by + # step_update() when warmup finishes + self.warmup_end = True if args.warmup_updates <= 0 else False + + # initial learning rate + # this self.lr is used only during init and/or warm up period + self.lr = args.warmup_init_lr + self.optimizer.set_lr(self.lr) + + @staticmethod + def add_args(parser): + """Add arguments to the parser for this LR scheduler.""" + # fmt: off + parser.add_argument('--lr-shrink', default=0.1, type=float, metavar='LS', + help='shrink factor for annealing, lr_new = (lr * lr_shrink)') + parser.add_argument('--lr-threshold', default=1e-4, type=float, metavar='LT', + help='threshold for measuring the new optimum, ' + 'to only focus on significant changes') + parser.add_argument('--lr-patience', default=0, type=int, + help='number of epochs with no improvement after which ' + 'learning rate will be reduced') + parser.add_argument('--warmup-updates', default=0, type=int, metavar='N', + help='warmup the learning rate linearly for the first N updates') + parser.add_argument('--warmup-init-lr', default=-1, type=float, metavar='LR', + help='initial learning rate during warmup phase; default is args.lr') + # fmt: on + + def state_dict(self): + """Return the LR scheduler state dict.""" + return { + "best": self.lr_scheduler.best, + "last_epoch": self.lr_scheduler.last_epoch, + } + + def load_state_dict(self, state_dict): + """Load an LR scheduler state dict.""" + self.lr_scheduler.best = state_dict["best"] + if "last_epoch" in state_dict: + self.lr_scheduler.last_epoch = state_dict["last_epoch"] + + def step(self, epoch, val_loss=None): + """ + Update the learning rate at the end of the given epoch if warmup + finishes otherwise no update of lr on epoch boundaries + """ + if val_loss is not None and self.warmup_end is True: + self.lr_scheduler.step(val_loss) + else: + self.lr_scheduler.last_epoch = epoch + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """ + Update the learning rate after each update.""" + # if there is warmup + if self.args.warmup_updates > 0: + if num_updates <= self.args.warmup_updates: + self.lr = self.args.warmup_init_lr + num_updates * self.lr_step + self.optimizer.set_lr(self.lr) + else: + if self.warmup_end is False: + self.warmup_end = True + # else do nothing + return self.optimizer.get_lr() diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/tri_stage_lr_scheduler.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/tri_stage_lr_scheduler.py new file mode 100644 index 00000000..c573237f --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/tri_stage_lr_scheduler.py @@ -0,0 +1,165 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +from . import LegacyFairseqLRScheduler, register_lr_scheduler + + +@register_lr_scheduler("tri_stage") +class TriStageLRSchedule(LegacyFairseqLRScheduler): + """Tristage learning rate schedulr + + Implement the learning rate scheduler in https://arxiv.org/pdf/1904.08779.pdf + + Similar to inverse_squre_root scheduler, but tri_stage learning rate employs + three stages LR scheduling: + + - warmup stage, starting from `lr` * `init_lr_scale`, linearly + increased to `lr` in `warmup_steps` iterations + + - hold stage, after `warmup_steps`, keep the LR as `lr` for `hold_steps` + iterations + + - decay stage, after hold stage, decay LR exponetially to + `lr` * `final_lr_scale` in `decay_steps`; + after that LR is keep as `final_lr_scale` * `lr` + + During warmup:: + + init_lr = args.init_lr_scale * args.lr + lrs = torch.linspace(init_lr, args.lr, args.warmup_steps) + lr = lrs[update_num] + + During hold:: + + lr = args.lr + + During decay:: + + decay_factor = - math.log(args.final_lr_scale) / args.decay_steps + lr = args.lr * exp(- (update_num - warmup_steps - decay_steps) * decay_factor) + + After that:: + + lr = args.lr * args.final_lr_scale + """ + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + if len(args.lr) > 1: + raise ValueError( + "Cannot use a fixed learning rate schedule with tri-stage lr." + " Consider --lr-scheduler=fixed instead." + ) + + # calculate LR at each point + self.peak_lr = args.lr[0] + self.init_lr = args.init_lr_scale * args.lr[0] + self.final_lr = args.final_lr_scale * args.lr[0] + + # remember the steps at each stage + self.warmup_steps = args.warmup_steps + self.hold_steps = args.hold_steps + self.decay_steps = args.decay_steps + + self.warmup_rate = ( + (self.peak_lr - self.init_lr) / self.warmup_steps + if self.warmup_steps != 0 + else 0 + ) + self.decay_factor = -math.log(args.final_lr_scale) / args.decay_steps + + # initial learning rate + self.lr = self.init_lr + self.optimizer.set_lr(self.lr) + + @staticmethod + def add_args(parser): + """Add arguments to the parser for this LR scheduler.""" + # fmt: off + parser.add_argument( + '--warmup-steps', + default=4000, + type=int, + metavar='N', + help='warmup the learning rate linearly for the first N updates' + ) + parser.add_argument( + '--hold-steps', + default=20000, + type=int, + metavar='N', + help='steps in hold stage.' + ) + parser.add_argument( + '--decay-steps', + default=60000, + type=int, + metavar='N', + help='steps in decay stages' + ) + parser.add_argument( + '--init-lr-scale', + default=0.01, + type=float, + help=""" + initial learning rate scale during warmup phase; default is 0.01""") + parser.add_argument( + '--final-lr-scale', + default=0.01, + type=float, + help="final learning rate scale; default to 0.01" + ) + # fmt: on + + def _decide_stage(self, update_step): + """ + return stage, and the corresponding steps within the current stage + """ + if update_step < self.warmup_steps: + # warmup state + return 0, update_step + + offset = self.warmup_steps + + if update_step < offset + self.hold_steps: + # hold stage + return 1, update_step - offset + + offset += self.hold_steps + + if update_step <= offset + self.decay_steps: + # decay stage + return 2, update_step - offset + + offset += self.decay_steps + + # still here ? constant lr stage + return 3, update_step - offset + + def step(self, epoch, val_loss=None): + """Update the learning rate at the end of the given epoch.""" + super().step(epoch, val_loss) + # we don't change the learning rate at epoch boundaries + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + stage, steps_in_stage = self._decide_stage(num_updates) + if stage == 0: + self.lr = self.init_lr + self.warmup_rate * steps_in_stage + elif stage == 1: + self.lr = self.peak_lr + elif stage == 2: + self.lr = self.peak_lr * math.exp(-self.decay_factor * steps_in_stage) + elif stage == 3: + self.lr = self.final_lr + else: + raise ValueError("Undefined stage") + + self.optimizer.set_lr(self.lr) + + return self.lr diff --git a/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/triangular_lr_scheduler.py b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/triangular_lr_scheduler.py new file mode 100644 index 00000000..0f3193f2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/lr_scheduler/triangular_lr_scheduler.py @@ -0,0 +1,74 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math + +from . import LegacyFairseqLRScheduler, register_lr_scheduler + + +@register_lr_scheduler("triangular") +class TriangularSchedule(LegacyFairseqLRScheduler): + """Assign LR based on a triangular cyclical schedule. + + See https://arxiv.org/pdf/1506.01186.pdf for details. + """ + + def __init__(self, args, optimizer): + super().__init__(args, optimizer) + if len(args.lr) > 1: + raise ValueError( + "Cannot use a fixed learning rate schedule with triangular." + " Consider --lr-scheduler=fixed instead." + ) + + lr = args.lr[0] + + assert args.max_lr > lr, "max_lr must be more than lr" + self.min_lr = lr + self.max_lr = args.max_lr + self.stepsize = args.lr_period_updates // 2 + self.lr_shrink = args.lr_shrink + self.shrink_min = args.shrink_min + + # initial learning rate + self.lr = self.min_lr + self.optimizer.set_lr(self.lr) + + @staticmethod + def add_args(parser): + """Add arguments to the parser for this LR scheduler.""" + # fmt: off + parser.add_argument('--max-lr', required=True, type=float, metavar='LR', + help='max learning rate, must be more than args.lr') + parser.add_argument('--lr-period-updates', default=5000, type=float, metavar='LR', + help='initial number of updates per period (cycle length)') + parser.add_argument('--lr-shrink', default=0.1, type=float, metavar='LS', + help='shrink factor for annealing') + parser.add_argument('--shrink-min', action='store_true', + help='if set, also shrinks min lr') + # fmt: on + + def step(self, epoch, val_loss=None): + """Update the learning rate at the end of the given epoch.""" + super().step(epoch, val_loss) + # we don't change the learning rate at epoch boundaries + return self.optimizer.get_lr() + + def step_update(self, num_updates): + """Update the learning rate after each update.""" + cycle = math.floor(num_updates / (2 * self.stepsize)) + + lr_shrink = self.lr_shrink ** cycle + max_lr = self.max_lr * lr_shrink + if self.shrink_min: + min_lr = self.min_lr * lr_shrink + else: + min_lr = self.min_lr + + x = abs(num_updates / self.stepsize - 2 * (cycle + 1) + 1) + self.lr = min_lr + (max_lr - min_lr) * max(0, (1 - x)) + + self.optimizer.set_lr(self.lr) + return self.lr diff --git a/fairseq-tools/fairseq/fairseq/optim/nag.py b/fairseq-tools/fairseq/fairseq/optim/nag.py new file mode 100644 index 00000000..58d2f356 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/nag.py @@ -0,0 +1,108 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from dataclasses import dataclass, field +from typing import List + +import torch +from fairseq.dataclass import FairseqDataclass +from omegaconf import II +from torch.optim.optimizer import Optimizer, required + +from . import FairseqOptimizer, register_optimizer + + +@dataclass +class FairseqNAGConfig(FairseqDataclass): + momentum: float = field(default=0.99, metadata={"help": "momentum factor"}) + weight_decay: float = field(default=0.0, metadata={"help": "weight decay"}) + # TODO common vars in parent class + lr: List[float] = II("params.optimization.lr") + + +@register_optimizer("nag", dataclass=FairseqNAGConfig) +class FairseqNAG(FairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = NAG(params, **self.optimizer_config) + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "momentum": self.args.momentum, + "weight_decay": self.args.weight_decay, + } + + +class NAG(Optimizer): + def __init__(self, params, lr=required, momentum=0, weight_decay=0): + defaults = dict(lr=lr, lr_old=lr, momentum=momentum, weight_decay=weight_decay) + super(NAG, self).__init__(params, defaults) + + @property + def supports_memory_efficient_fp16(self): + return True + + @property + def supports_flat_params(self): + return True + + def step(self, closure=None): + """Performs a single optimization step. + + Arguments: + closure (callable, optional): A closure that reevaluates the model + and returns the loss. + """ + loss = None + if closure is not None: + loss = closure() + + for group in self.param_groups: + weight_decay = group["weight_decay"] + momentum = group["momentum"] + lr = group["lr"] + lr_old = group.get("lr_old", lr) + lr_correct = lr / lr_old + + for p in group["params"]: + if p.grad is None: + continue + + p_data_fp32 = p.data + if p_data_fp32.dtype in {torch.float16, torch.bfloat16}: + p_data_fp32 = p_data_fp32.float() + + d_p = p.grad.data.float() + param_state = self.state[p] + if "momentum_buffer" not in param_state: + param_state["momentum_buffer"] = torch.zeros_like(d_p) + else: + param_state["momentum_buffer"] = param_state["momentum_buffer"].to( + d_p + ) + + buf = param_state["momentum_buffer"] + + if weight_decay != 0: + p_data_fp32.mul_(1 - lr * weight_decay) + p_data_fp32.add_(buf, alpha=momentum * momentum * lr_correct) + p_data_fp32.add_(d_p, alpha=-(1 + momentum) * lr) + + buf.mul_(momentum * lr_correct).add_(d_p, alpha=-lr) + + if p.data.dtype in {torch.float16, torch.bfloat16}: + p.data.copy_(p_data_fp32) + + group["lr_old"] = lr + + return loss diff --git a/fairseq-tools/fairseq/fairseq/optim/sgd.py b/fairseq-tools/fairseq/fairseq/optim/sgd.py new file mode 100644 index 00000000..8e34fb99 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/sgd.py @@ -0,0 +1,43 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch.optim + +from . import LegacyFairseqOptimizer, register_optimizer + + +@register_optimizer("sgd") +class SGD(LegacyFairseqOptimizer): + def __init__(self, args, params): + super().__init__(args) + self._optimizer = torch.optim.SGD(params, **self.optimizer_config) + + @staticmethod + def add_args(parser): + """Add optimizer-specific arguments to the parser.""" + # fmt: off + parser.add_argument('--momentum', default=0.0, type=float, metavar='M', + help='momentum factor') + parser.add_argument('--weight-decay', '--wd', default=0.0, type=float, metavar='WD', + help='weight decay') + # fmt: on + + @property + def optimizer_config(self): + """ + Return a kwarg dictionary that will be used to override optimizer + args stored in checkpoints. This allows us to load a checkpoint and + resume training using a different set of optimizer args, e.g., with a + different learning rate. + """ + return { + "lr": self.args.lr[0], + "momentum": self.args.momentum, + "weight_decay": self.args.weight_decay, + } + + @property + def supports_flat_params(self): + return True diff --git a/fairseq-tools/fairseq/fairseq/optim/shard.py b/fairseq-tools/fairseq/fairseq/optim/shard.py new file mode 100644 index 00000000..a035a1c1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/optim/shard.py @@ -0,0 +1,41 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +try: + from fairscale.optim import OSS + + _has_fairscale = True +except ImportError: + _has_fairscale = False + + +def shard_(args, optimizer, group): + if not _has_fairscale: + raise ImportError( + "\n\nPlease install the fairscale package:" "\n\n pip install fairscale" + ) + + class FairseqOSS(OSS): + @property + def disable_mem_eff_fp16_loading_hack(self): + return True + + def __getattr__(self, name): + if name.startswith("supports") and hasattr(self.optim, name): + return getattr(self.optim, name) + raise AttributeError( + "'FairseqOSS' object has no attribute {0!r}".format(name) + ) + + torch_optimizer = optimizer.optimizer + optim_cls = type(torch_optimizer) + + optimizer.optimizer = FairseqOSS( + torch_optimizer.param_groups, + optim_cls, + group=group, + **optimizer.optimizer_config + ) diff --git a/fairseq-tools/fairseq/fairseq/options.py b/fairseq-tools/fairseq/fairseq/options.py new file mode 100644 index 00000000..1a24fcca --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/options.py @@ -0,0 +1,441 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +from typing import Callable, List, Optional + +import torch +from fairseq import utils +from fairseq.data.indexed_dataset import get_available_dataset_impl +from fairseq.dataclass.data_class import ( + CheckpointParams, + CommonEvalParams, + CommonParams, + DatasetParams, + DistributedTrainingParams, + EvalLMParams, + OptimizationParams, +) +from fairseq.dataclass.utils import gen_parser_from_dataclass + +# this import is for backward compatibility +from fairseq.utils import csv_str_list, eval_bool, eval_str_dict, eval_str_list # noqa + + +def get_preprocessing_parser(default_task="translation"): + parser = get_parser("Preprocessing", default_task) + add_preprocess_args(parser) + return parser + + +def get_training_parser(default_task="translation"): + parser = get_parser("Trainer", default_task) + add_dataset_args(parser, train=True) + add_distributed_training_args(parser) + add_model_args(parser) + add_optimization_args(parser) + add_checkpoint_args(parser) + return parser + + +def get_generation_parser(interactive=False, default_task="translation"): + parser = get_parser("Generation", default_task) + add_dataset_args(parser, gen=True) + add_distributed_training_args(parser, default_world_size=1) + add_generation_args(parser) + if interactive: + add_interactive_args(parser) + return parser + + +def get_interactive_generation_parser(default_task="translation"): + return get_generation_parser(interactive=True, default_task=default_task) + + +def get_eval_lm_parser(default_task="language_modeling"): + parser = get_parser("Evaluate Language Model", default_task) + add_dataset_args(parser, gen=True) + add_distributed_training_args(parser, default_world_size=1) + add_eval_lm_args(parser) + return parser + + +def get_validation_parser(default_task=None): + parser = get_parser("Validation", default_task) + add_dataset_args(parser, train=True) + add_distributed_training_args(parser, default_world_size=1) + group = parser.add_argument_group("Evaluation") + gen_parser_from_dataclass(group, CommonEvalParams()) + return parser + + +def parse_args_and_arch( + parser: argparse.ArgumentParser, + input_args: List[str] = None, + parse_known: bool = False, + suppress_defaults: bool = False, + modify_parser: Optional[Callable[[argparse.ArgumentParser], None]] = None, +): + """ + Args: + parser (ArgumentParser): the parser + input_args (List[str]): strings to parse, defaults to sys.argv + parse_known (bool): only parse known arguments, similar to + `ArgumentParser.parse_known_args` + suppress_defaults (bool): parse while ignoring all default values + modify_parser (Optional[Callable[[ArgumentParser], None]]): + function to modify the parser, e.g., to set default values + """ + if suppress_defaults: + # Parse args without any default values. This requires us to parse + # twice, once to identify all the necessary task/model args, and a second + # time with all defaults set to None. + args = parse_args_and_arch( + parser, + input_args=input_args, + parse_known=parse_known, + suppress_defaults=False, + ) + suppressed_parser = argparse.ArgumentParser(add_help=False, parents=[parser]) + suppressed_parser.set_defaults(**{k: None for k, v in vars(args).items()}) + args = suppressed_parser.parse_args(input_args) + return argparse.Namespace( + **{k: v for k, v in vars(args).items() if v is not None} + ) + + from fairseq.models import ARCH_MODEL_REGISTRY, ARCH_CONFIG_REGISTRY, MODEL_REGISTRY + + # Before creating the true parser, we need to import optional user module + # in order to eagerly import custom tasks, optimizers, architectures, etc. + usr_parser = argparse.ArgumentParser(add_help=False, allow_abbrev=False) + usr_parser.add_argument("--user-dir", default=None) + usr_args, _ = usr_parser.parse_known_args(input_args) + utils.import_user_module(usr_args) + + if modify_parser is not None: + modify_parser(parser) + + # The parser doesn't know about model/criterion/optimizer-specific args, so + # we parse twice. First we parse the model/criterion/optimizer, then we + # parse a second time after adding the *-specific arguments. + # If input_args is given, we will parse those args instead of sys.argv. + args, _ = parser.parse_known_args(input_args) + + # Add model-specific args to parser. + if hasattr(args, "arch"): + model_specific_group = parser.add_argument_group( + "Model-specific configuration", + # Only include attributes which are explicitly given as command-line + # arguments or which have default values. + argument_default=argparse.SUPPRESS, + ) + if args.arch in ARCH_MODEL_REGISTRY: + ARCH_MODEL_REGISTRY[args.arch].add_args(model_specific_group) + elif args.arch in MODEL_REGISTRY: + MODEL_REGISTRY[args.arch].add_args(model_specific_group) + else: + raise RuntimeError() + + # Add *-specific args to parser. + from fairseq.registry import REGISTRIES + + for registry_name, REGISTRY in REGISTRIES.items(): + choice = getattr(args, registry_name, None) + if choice is not None: + cls = REGISTRY["registry"][choice] + if hasattr(cls, "add_args"): + cls.add_args(parser) + if hasattr(args, "task"): + from fairseq.tasks import TASK_REGISTRY + + TASK_REGISTRY[args.task].add_args(parser) + if getattr(args, "use_bmuf", False): + # hack to support extra args for block distributed data parallelism + from fairseq.optim.bmuf import FairseqBMUF + + FairseqBMUF.add_args(parser) + + # Modify the parser a second time, since defaults may have been reset + if modify_parser is not None: + modify_parser(parser) + + # Parse a second time. + if parse_known: + args, extra = parser.parse_known_args(input_args) + else: + args = parser.parse_args(input_args) + extra = None + # Post-process args. + if ( + hasattr(args, "batch_size_valid") and args.batch_size_valid is None + ) or not hasattr(args, "batch_size_valid"): + args.batch_size_valid = args.batch_size + if hasattr(args, "max_tokens_valid") and args.max_tokens_valid is None: + args.max_tokens_valid = args.max_tokens + if getattr(args, "memory_efficient_fp16", False): + args.fp16 = True + if getattr(args, "memory_efficient_bf16", False): + args.bf16 = True + args.tpu = getattr(args, "tpu", False) + args.bf16 = getattr(args, "bf16", False) + if args.bf16: + args.tpu = True + if args.tpu and args.fp16: + raise ValueError("Cannot combine --fp16 and --tpu, use --bf16 on TPUs") + + if getattr(args, "seed", None) is None: + args.seed = 1 # default seed for training + args.no_seed_provided = True + else: + args.no_seed_provided = False + + # Apply architecture configuration. + if hasattr(args, "arch") and args.arch in ARCH_CONFIG_REGISTRY: + ARCH_CONFIG_REGISTRY[args.arch](args) + + if parse_known: + return args, extra + else: + return args + + +def get_parser(desc, default_task="translation"): + # Before creating the true parser, we need to import optional user module + # in order to eagerly import custom tasks, optimizers, architectures, etc. + usr_parser = argparse.ArgumentParser(add_help=False, allow_abbrev=False) + usr_parser.add_argument("--user-dir", default=None) + usr_args, _ = usr_parser.parse_known_args() + utils.import_user_module(usr_args) + + parser = argparse.ArgumentParser(allow_abbrev=False) + gen_parser_from_dataclass(parser, CommonParams()) + + from fairseq.registry import REGISTRIES + + for registry_name, REGISTRY in REGISTRIES.items(): + parser.add_argument( + "--" + registry_name.replace("_", "-"), + default=REGISTRY["default"], + choices=REGISTRY["registry"].keys(), + ) + + # Task definitions can be found under fairseq/tasks/ + from fairseq.tasks import TASK_REGISTRY + + parser.add_argument( + "--task", + metavar="TASK", + default=default_task, + choices=TASK_REGISTRY.keys(), + help="task", + ) + # fmt: on + return parser + + +def add_preprocess_args(parser): + group = parser.add_argument_group("Preprocessing") + # fmt: off + group.add_argument("-s", "--source-lang", default=None, metavar="SRC", + help="source language") + group.add_argument("-t", "--target-lang", default=None, metavar="TARGET", + help="target language") + group.add_argument("--trainpref", metavar="FP", default=None, + help="train file prefix") + group.add_argument("--validpref", metavar="FP", default=None, + help="comma separated, valid file prefixes") + group.add_argument("--testpref", metavar="FP", default=None, + help="comma separated, test file prefixes") + group.add_argument("--align-suffix", metavar="FP", default=None, + help="alignment file suffix") + group.add_argument("--destdir", metavar="DIR", default="data-bin", + help="destination dir") + group.add_argument("--thresholdtgt", metavar="N", default=0, type=int, + help="map words appearing less than threshold times to unknown") + group.add_argument("--thresholdsrc", metavar="N", default=0, type=int, + help="map words appearing less than threshold times to unknown") + group.add_argument("--tgtdict", metavar="FP", + help="reuse given target dictionary") + group.add_argument("--srcdict", metavar="FP", + help="reuse given source dictionary") + group.add_argument("--nwordstgt", metavar="N", default=-1, type=int, + help="number of target words to retain") + group.add_argument("--nwordssrc", metavar="N", default=-1, type=int, + help="number of source words to retain") + group.add_argument("--alignfile", metavar="ALIGN", default=None, + help="an alignment file (optional)") + parser.add_argument('--dataset-impl', metavar='FORMAT', default='mmap', + choices=get_available_dataset_impl(), + help='output dataset implementation') + group.add_argument("--joined-dictionary", action="store_true", + help="Generate joined dictionary") + group.add_argument("--only-source", action="store_true", + help="Only process the source language") + group.add_argument("--padding-factor", metavar="N", default=8, type=int, + help="Pad dictionary size to be multiple of N") + group.add_argument("--workers", metavar="N", default=1, type=int, + help="number of parallel workers") + # fmt: on + return parser + + +def add_dataset_args(parser, train=False, gen=False): + group = parser.add_argument_group("dataset_data_loading") + gen_parser_from_dataclass(group, DatasetParams()) + # fmt: on + return group + + +def add_distributed_training_args(parser, default_world_size=None): + group = parser.add_argument_group("distributed_training") + if default_world_size is None: + default_world_size = max(1, torch.cuda.device_count()) + gen_parser_from_dataclass( + group, DistributedTrainingParams(distributed_world_size=default_world_size) + ) + return group + + +def add_optimization_args(parser): + group = parser.add_argument_group("optimization") + # fmt: off + gen_parser_from_dataclass(group, OptimizationParams()) + # fmt: on + return group + + +def add_checkpoint_args(parser): + group = parser.add_argument_group("checkpoint") + # fmt: off + gen_parser_from_dataclass(group, CheckpointParams()) + # fmt: on + return group + + +def add_common_eval_args(group): + gen_parser_from_dataclass(group, CommonEvalParams()) + + +def add_eval_lm_args(parser): + group = parser.add_argument_group("LM Evaluation") + add_common_eval_args(group) + gen_parser_from_dataclass(group, EvalLMParams()) + + +def add_generation_args(parser): + group = parser.add_argument_group("Generation") + add_common_eval_args(group) + # fmt: off + group.add_argument('--beam', default=5, type=int, metavar='N', + help='beam size') + group.add_argument('--nbest', default=1, type=int, metavar='N', + help='number of hypotheses to output') + group.add_argument('--max-len-a', default=0, type=float, metavar='N', + help=('generate sequences of maximum length ax + b, ' + 'where x is the source length')) + group.add_argument('--max-len-b', default=200, type=int, metavar='N', + help=('generate sequences of maximum length ax + b, ' + 'where x is the source length')) + group.add_argument('--min-len', default=1, type=float, metavar='N', + help=('minimum generation length')) + group.add_argument('--match-source-len', default=False, action='store_true', + help=('generations should match the source length')) + group.add_argument('--no-early-stop', action='store_true', + help='deprecated') + group.add_argument('--unnormalized', action='store_true', + help='compare unnormalized hypothesis scores') + group.add_argument('--no-beamable-mm', action='store_true', + help='don\'t use BeamableMM in attention layers') + group.add_argument('--lenpen', default=1, type=float, + help='length penalty: <1.0 favors shorter, >1.0 favors longer sentences') + group.add_argument('--unkpen', default=0, type=float, + help='unknown word penalty: <0 produces more unks, >0 produces fewer') + group.add_argument('--replace-unk', nargs='?', const=True, default=None, + help='perform unknown replacement (optionally with alignment dictionary)') + group.add_argument('--sacrebleu', action='store_true', + help='score with sacrebleu') + group.add_argument('--score-reference', action='store_true', + help='just score the reference translation') + group.add_argument('--prefix-size', default=0, type=int, metavar='PS', + help='initialize generation by target prefix of given length') + group.add_argument('--no-repeat-ngram-size', default=0, type=int, metavar='N', + help='ngram blocking such that this size ngram cannot be repeated in the generation') + group.add_argument('--sampling', action='store_true', + help='sample hypotheses instead of using beam search') + group.add_argument('--sampling-topk', default=-1, type=int, metavar='PS', + help='sample from top K likely next words instead of all words') + group.add_argument('--sampling-topp', default=-1.0, type=float, metavar='PS', + help='sample from the smallest set whose cumulative probability mass exceeds p for next words') + group.add_argument('--constraints', const="ordered", nargs="?", choices=["ordered", "unordered"], + help='enables lexically constrained decoding') + group.add_argument('--temperature', default=1., type=float, metavar='N', + help='temperature for generation') + group.add_argument('--diverse-beam-groups', default=-1, type=int, metavar='N', + help='number of groups for Diverse Beam Search') + group.add_argument('--diverse-beam-strength', default=0.5, type=float, metavar='N', + help='strength of diversity penalty for Diverse Beam Search') + group.add_argument('--diversity-rate', default=-1.0, type=float, metavar='N', + help='strength of diversity penalty for Diverse Siblings Search') + group.add_argument('--print-alignment', action='store_true', + help='if set, uses attention feedback to compute and print alignment to source tokens') + group.add_argument('--print-step', action='store_true') + + group.add_argument('--lm-path', default=None, type=str, metavar='PATH', + help='path to lm checkpoint for lm fusion') + group.add_argument('--lm-weight', default=0.0, type=float, metavar='N', + help='weight for lm probs for lm fusion') + + # arguments for iterative refinement generator + group.add_argument('--iter-decode-eos-penalty', default=0.0, type=float, metavar='N', + help='if > 0.0, it penalized early-stopping in decoding.') + group.add_argument('--iter-decode-max-iter', default=10, type=int, metavar='N', + help='maximum iterations for iterative refinement.') + group.add_argument('--iter-decode-force-max-iter', action='store_true', + help='if set, run exact the maximum number of iterations without early stop') + group.add_argument('--iter-decode-with-beam', default=1, type=int, metavar='N', + help='if > 1, model will generate translations varying by the lengths.') + group.add_argument('--iter-decode-with-external-reranker', action='store_true', + help='if set, the last checkpoint are assumed to be a reranker to rescore the translations'), + group.add_argument('--retain-iter-history', action='store_true', + help='if set, decoding returns the whole history of iterative refinement') + group.add_argument('--retain-dropout', action='store_true', + help='Use dropout at inference time') + group.add_argument('--retain-dropout-modules', default=None, nargs='+', type=str, + help='if set, only retain dropout for the specified modules; ' + 'if not set, then dropout will be retained for all modules') + + # special decoding format for advanced decoding. + group.add_argument('--decoding-format', default=None, type=str, choices=['unigram', 'ensemble', 'vote', 'dp', 'bs']) + # fmt: on + return group + + +def add_interactive_args(parser): + group = parser.add_argument_group("Interactive") + # fmt: off + group.add_argument('--buffer-size', default=0, type=int, metavar='N', + help='read this many sentences into a buffer before processing them') + group.add_argument('--input', default='-', type=str, metavar='FILE', + help='file to read from; use - for stdin') + # fmt: on + + +def add_model_args(parser): + group = parser.add_argument_group("Model configuration") + # fmt: off + + # Model definitions can be found under fairseq/models/ + # + # The model architecture can be specified in several ways. + # In increasing order of priority: + # 1) model defaults (lowest priority) + # 2) --arch argument + # 3) --encoder/decoder-* arguments (highest priority) + from fairseq.models import ARCH_MODEL_REGISTRY + group.add_argument('--arch', '-a', metavar='ARCH', + choices=ARCH_MODEL_REGISTRY.keys(), + help='model architecture') + # fmt: on + return group diff --git a/fairseq-tools/fairseq/fairseq/pdb.py b/fairseq-tools/fairseq/fairseq/pdb.py new file mode 100644 index 00000000..1ba6ef0d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/pdb.py @@ -0,0 +1,47 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import multiprocessing +import os +import pdb +import sys + + +__all__ = ["set_trace"] + + +_stdin = [None] +_stdin_lock = multiprocessing.Lock() +try: + _stdin_fd = sys.stdin.fileno() +except Exception: + _stdin_fd = None + + +class MultiprocessingPdb(pdb.Pdb): + """A Pdb wrapper that works in a multiprocessing environment. + + Usage: `from fairseq import pdb; pdb.set_trace()` + """ + + def __init__(self): + pdb.Pdb.__init__(self, nosigint=True) + + def _cmdloop(self): + stdin_bak = sys.stdin + with _stdin_lock: + try: + if _stdin_fd is not None: + if not _stdin[0]: + _stdin[0] = os.fdopen(_stdin_fd) + sys.stdin = _stdin[0] + self.cmdloop() + finally: + sys.stdin = stdin_bak + + +def set_trace(): + pdb = MultiprocessingPdb() + pdb.set_trace(sys._getframe().f_back) diff --git a/fairseq-tools/fairseq/fairseq/quantization_utils.py b/fairseq-tools/fairseq/fairseq/quantization_utils.py new file mode 100644 index 00000000..69dd61d7 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/quantization_utils.py @@ -0,0 +1,142 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging + +from fairseq.modules.quantization import pq, quantization_options, scalar + + +logger = logging.getLogger(__name__) + + +def quantize_model_scalar(model, args): + quant_noise_scalar = getattr(args, "quant_noise_scalar", 0) + if quant_noise_scalar > 0: + # quantize_model edits the model in place + scalar.quantize_model_(model, p=quant_noise_scalar, bits=8, update_step=1000) + return model + + +class Quantizer(object): + def __init__(self, config_path, max_epoch, max_update): + try: + import yaml + except ImportError: + raise ImportError("Please install yaml with: pip install yaml") + + # parse config + if config_path: + with open(config_path) as config_file: + config = quantization_options.parse_config_yaml( + yaml.safe_load(config_file) + ) + else: + config = quantization_options.parse_config_yaml({}) + + self.n_centroids_config = config["n_centroids"] + self.block_sizes_config = config["block_sizes"] + self.layers_to_quantize = config["layers_to_quantize"] + + # We assume that training will run for a fixed number of epochs + # (or updates) and that we should train for equal durations + # between iterations of PQ. + num_iterations = len(self.layers_to_quantize) + if max_epoch > 0: + assert max_epoch % num_iterations == 0, ( + "for iterative PQ, --max-epoch (={}) must be evenly divisible by " + "len(layers_to_quantize) (={})".format(max_epoch, num_iterations) + ) + self.epoch_schedule = max_epoch // num_iterations + else: + self.epoch_schedule = None + if max_update > 0: + assert max_update % num_iterations == 0, ( + "for iterative PQ, --max-update (={}) must be evenly divisible by " + "len(layers_to_quantize) (={})".format(max_update, num_iterations) + ) + self.update_schedule = max_update // num_iterations + else: + self.update_schedule = None + assert (self.epoch_schedule is not None) ^ ( + self.update_schedule is not None + ), "for iterative PQ, cannot specify both --max-update and --max-epoch" + + # 0 is a special value for quantization step, which will force + # the first call to begin_epoch() to call step() + self.quantization_step = 0 + + def set_trainer(self, trainer): + self.trainer = trainer + self.size_tracker = pq.SizeTracker(self.trainer.get_model()) + + def step(self): + """Move to the next stage of quantization.""" + if self.quantization_step >= len(self.layers_to_quantize): + # Maybe we just finished the last training step or we loaded + # a checkpoint for an iterative PQ model which previously + # finished training. Either way, don't quantize again. + return + + logger.info( + "quantizing model (step={}; layers_to_quantize[step]={})".format( + self.quantization_step, self.layers_to_quantize[self.quantization_step] + ) + ) + quantized_layers = pq.quantize_model_( + self.trainer.get_model(), + self.size_tracker, + self.layers_to_quantize, + self.block_sizes_config, + self.n_centroids_config, + step=self.quantization_step, + ) + logger.info("quantized layers: {}".format(quantized_layers)) + logger.info(self.size_tracker) + + self.quantization_step += 1 + + # reintialize the Trainer since model parameters have changed + self.trainer.reinitialize() + + def begin_epoch(self, epoch): + """Called at the beginning of each epoch (epochs start at 1).""" + if ( + ( + self.epoch_schedule is not None + and epoch > 0 + and (epoch - 1) % self.epoch_schedule == 0 + ) + # we always step once in the beginning, even if using + # update-based quantization + or self.quantization_step == 0 + ): + self.step() + + def step_update(self, num_updates): + """Called at the end of each step.""" + if ( + self.update_schedule is not None + and num_updates > 0 + and num_updates % self.update_schedule == 0 + ): + self.step() + + def state_dict(self): + return { + "n_centroids_config": self.n_centroids_config, + "block_sizes_config": self.block_sizes_config, + "layers_to_quantize": self.layers_to_quantize, + "epoch_schedule": self.epoch_schedule, + "update_schedule": self.update_schedule, + "quantization_step": self.quantization_step, + } + + def load_state_dict(self, state_dict): + self.n_centroids_config = state_dict["n_centroids_config"] + self.block_sizes_config = state_dict["block_sizes_config"] + self.layers_to_quantize = state_dict["layers_to_quantize"] + self.epoch_schedule = state_dict["epoch_schedule"] + self.update_schedule = state_dict["update_schedule"] + self.quantization_step = state_dict["quantization_step"] diff --git a/fairseq-tools/fairseq/fairseq/registry.py b/fairseq-tools/fairseq/fairseq/registry.py new file mode 100644 index 00000000..382dec22 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/registry.py @@ -0,0 +1,106 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +from argparse import Namespace +from typing import Union + +from fairseq.dataclass import FairseqDataclass +from omegaconf import DictConfig + + +REGISTRIES = {} + + +def setup_registry(registry_name: str, base_class=None, default=None, required=False): + assert registry_name.startswith("--") + registry_name = registry_name[2:].replace("-", "_") + + REGISTRY = {} + REGISTRY_CLASS_NAMES = set() + DATACLASS_REGISTRY = {} + + # maintain a registry of all registries + if registry_name in REGISTRIES: + return # registry already exists + REGISTRIES[registry_name] = {"registry": REGISTRY, "default": default} + + def build_x(args: Union[DictConfig, Namespace], *extra_args, **extra_kwargs): + if isinstance(args, DictConfig): + if getattr(args, "_name", None) is not None: + choice = args._name + elif hasattr(args, registry_name): + choice = args.registry_name + else: + raise RuntimeError( + f"Neither _name nor {registry_name} in args, args = {args}" + ) + else: + choice = getattr(args, registry_name, None) + + if choice is None: + if required: + raise ValueError("--{} is required!".format(registry_name)) + return None + cls = REGISTRY[choice] + if hasattr(cls, "build_" + registry_name): + builder = getattr(cls, "build_" + registry_name) + else: + builder = cls + if isinstance(args, Namespace): + set_defaults(args, cls) + return builder(args, *extra_args, **extra_kwargs) + + def register_x(name, dataclass=None): + def register_x_cls(cls): + if name in REGISTRY: + raise ValueError( + "Cannot register duplicate {} ({})".format(registry_name, name) + ) + if cls.__name__ in REGISTRY_CLASS_NAMES: + raise ValueError( + "Cannot register {} with duplicate class name ({})".format( + registry_name, cls.__name__ + ) + ) + if base_class is not None and not issubclass(cls, base_class): + raise ValueError( + "{} must extend {}".format(cls.__name__, base_class.__name__) + ) + + if dataclass is not None and not issubclass(dataclass, FairseqDataclass): + raise ValueError( + "Dataclass {} must extend FairseqDataclass".format(dataclass) + ) + + cls.__dataclass = dataclass + REGISTRY[name] = cls + DATACLASS_REGISTRY[name] = cls.__dataclass + REGISTRY_CLASS_NAMES.add(cls.__name__) + return cls + + return register_x_cls + + return build_x, register_x, REGISTRY, DATACLASS_REGISTRY + + +def set_defaults(args: Namespace, cls): + """Helper to set default arguments based on *add_args*.""" + if not hasattr(cls, "add_args"): + return + parser = argparse.ArgumentParser( + argument_default=argparse.SUPPRESS, allow_abbrev=False + ) + cls.add_args(parser) + # copied from argparse.py: + defaults = argparse.Namespace() + for action in parser._actions: + if action.dest is not argparse.SUPPRESS: + if not hasattr(defaults, action.dest): + if action.default is not argparse.SUPPRESS: + setattr(defaults, action.dest, action.default) + for key, default_value in vars(defaults).items(): + if not hasattr(args, key): + setattr(args, key, default_value) diff --git a/fairseq-tools/fairseq/fairseq/scoring/__init__.py b/fairseq-tools/fairseq/fairseq/scoring/__init__.py new file mode 100644 index 00000000..4be0cb51 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/scoring/__init__.py @@ -0,0 +1,61 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + + +import importlib +import os +from abc import ABC, abstractmethod + +from fairseq import registry + + +class BaseScorer(ABC): + def __init__(self, args): + self.args = args + self.ref = [] + self.pred = [] + + @staticmethod + def add_args(parser): + pass + + def add_string(self, ref, pred): + self.ref.append(ref) + self.pred.append(pred) + + @abstractmethod + def score(self) -> float: + pass + + @abstractmethod + def result_string(self) -> str: + pass + + +_build_scorer, register_scorer, SCORER_REGISTRY, _ = registry.setup_registry( + "--scoring", default="bleu" +) + + +def build_scorer(args, tgt_dict): + from fairseq import utils + + if args.sacrebleu: + utils.deprecation_warning( + "--sacrebleu is deprecated. Please use --scoring sacrebleu instead." + ) + args.scoring = "sacrebleu" + if args.scoring == "bleu": + from fairseq.scoring import bleu + + return bleu.Scorer(tgt_dict.pad(), tgt_dict.eos(), tgt_dict.unk()) + return _build_scorer(args) + + +# automatically import any Python files in the current directory +for file in os.listdir(os.path.dirname(__file__)): + if file.endswith(".py") and not file.startswith("_"): + module = file[: file.find(".py")] + importlib.import_module("fairseq.scoring." + module) diff --git a/fairseq-tools/fairseq/fairseq/scoring/bleu.py b/fairseq-tools/fairseq/fairseq/scoring/bleu.py new file mode 100644 index 00000000..7f8bd73b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/scoring/bleu.py @@ -0,0 +1,157 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import ctypes +import math +import sys + +import torch +from fairseq.scoring import BaseScorer, register_scorer +from fairseq.scoring.tokenizer import EvaluationTokenizer + + +class BleuStat(ctypes.Structure): + _fields_ = [ + ("reflen", ctypes.c_size_t), + ("predlen", ctypes.c_size_t), + ("match1", ctypes.c_size_t), + ("count1", ctypes.c_size_t), + ("match2", ctypes.c_size_t), + ("count2", ctypes.c_size_t), + ("match3", ctypes.c_size_t), + ("count3", ctypes.c_size_t), + ("match4", ctypes.c_size_t), + ("count4", ctypes.c_size_t), + ] + + +@register_scorer("sacrebleu") +class SacrebleuScorer(BaseScorer): + def __init__(self, args): + super(SacrebleuScorer, self).__init__(args) + import sacrebleu + + self.sacrebleu = sacrebleu + self.tokenizer = EvaluationTokenizer( + tokenizer_type=self.args.sacrebleu_tokenizer, + lowercase=self.args.sacrebleu_lowercase, + character_tokenization=self.args.sacrebleu_char_level, + ) + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--sacrebleu-tokenizer', type=str, default='13a', + choices=EvaluationTokenizer.ALL_TOKENIZER_TYPES, + help='tokenizer') + parser.add_argument('--sacrebleu-lowercase', type=str, default=False, + help='apply lowercasing') + parser.add_argument('--sacrebleu-char-level', action='store_true', + help='evaluate at character level') + # fmt: on + + def add_string(self, ref, pred): + self.ref.append(self.tokenizer.tokenize(ref)) + self.pred.append(self.tokenizer.tokenize(pred)) + + def score(self, order=4): + return self.result_string(order).score + + def result_string(self, order=4): + if order != 4: + raise NotImplementedError + # tokenization and lowercasing are performed by self.tokenizer instead. + return self.sacrebleu.corpus_bleu( + self.pred, [self.ref], tokenize="none" + ).format() + + +@register_scorer("bleu") +class Scorer(object): + def __init__(self, pad, eos, unk): + self.stat = BleuStat() + self.pad = pad + self.eos = eos + self.unk = unk + + try: + from fairseq import libbleu + except ImportError as e: + sys.stderr.write( + "ERROR: missing libbleu.so. run `pip install --editable .`\n" + ) + raise e + + self.C = ctypes.cdll.LoadLibrary(libbleu.__file__) + + self.reset() + + def reset(self, one_init=False): + if one_init: + self.C.bleu_one_init(ctypes.byref(self.stat)) + else: + self.C.bleu_zero_init(ctypes.byref(self.stat)) + + def add(self, ref, pred): + if not isinstance(ref, torch.IntTensor): + raise TypeError("ref must be a torch.IntTensor (got {})".format(type(ref))) + if not isinstance(pred, torch.IntTensor): + raise TypeError("pred must be a torch.IntTensor(got {})".format(type(pred))) + + # don't match unknown words + rref = ref.clone() + assert not rref.lt(0).any() + rref[rref.eq(self.unk)] = -999 + + rref = rref.contiguous().view(-1) + pred = pred.contiguous().view(-1) + + self.C.bleu_add( + ctypes.byref(self.stat), + ctypes.c_size_t(rref.size(0)), + ctypes.c_void_p(rref.data_ptr()), + ctypes.c_size_t(pred.size(0)), + ctypes.c_void_p(pred.data_ptr()), + ctypes.c_int(self.pad), + ctypes.c_int(self.eos), + ) + + def score(self, order=4): + psum = sum( + math.log(p) if p > 0 else float("-Inf") for p in self.precision()[:order] + ) + return self.brevity() * math.exp(psum / order) * 100 + + def precision(self): + def ratio(a, b): + return a / b if b > 0 else 0 + + return [ + ratio(self.stat.match1, self.stat.count1), + ratio(self.stat.match2, self.stat.count2), + ratio(self.stat.match3, self.stat.count3), + ratio(self.stat.match4, self.stat.count4), + ] + + def brevity(self): + r = self.stat.reflen / self.stat.predlen + return min(1, math.exp(1 - r)) + + def result_string(self, order=4): + assert order <= 4, "BLEU scores for order > 4 aren't supported" + fmt = "BLEU{} = {:2.2f}, {:2.1f}" + for _ in range(1, order): + fmt += "/{:2.1f}" + fmt += " (BP={:.3f}, ratio={:.3f}, syslen={}, reflen={})" + bleup = [p * 100 for p in self.precision()[:order]] + return fmt.format( + order, + self.score(order=order), + *bleup, + self.brevity(), + self.stat.predlen / self.stat.reflen, + self.stat.predlen, + self.stat.reflen + ) diff --git a/fairseq-tools/fairseq/fairseq/scoring/chrf.py b/fairseq-tools/fairseq/fairseq/scoring/chrf.py new file mode 100644 index 00000000..0d6cb773 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/scoring/chrf.py @@ -0,0 +1,27 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.scoring import BaseScorer, register_scorer + + +@register_scorer("chrf") +class ChrFScorer(BaseScorer): + def __init__(self, args): + super(ChrFScorer, self).__init__(args) + import sacrebleu + + self.sacrebleu = sacrebleu + + def add_string(self, ref, pred): + self.ref.append(ref) + self.pred.append(pred) + + def score(self, order=4): + return self.result_string(order).score + + def result_string(self, order=4): + if order != 4: + raise NotImplementedError + return self.sacrebleu.corpus_chrf(self.pred, [self.ref]).format() diff --git a/fairseq-tools/fairseq/fairseq/scoring/tokenizer.py b/fairseq-tools/fairseq/fairseq/scoring/tokenizer.py new file mode 100644 index 00000000..dbcc6e4d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/scoring/tokenizer.py @@ -0,0 +1,65 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unicodedata + + +class EvaluationTokenizer(object): + """A generic evaluation-time tokenizer, which leverages built-in tokenizers + in sacreBLEU (https://github.com/mjpost/sacrebleu). It additionally provides + lowercasing, punctuation removal and character tokenization, which are + applied after sacreBLEU tokenization. + + Args: + tokenizer_type (str): the type of sacreBLEU tokenizer to apply. + lowercase (bool): lowercase the text. + punctuation_removal (bool): remove punctuation (based on unicode + category) from text. + character_tokenization (bool): tokenize the text to characters. + """ + + SPACE = chr(32) + SPACE_ESCAPE = chr(9601) + ALL_TOKENIZER_TYPES = ["none", "13a", "intl", "zh", "ja-mecab"] + + def __init__( + self, + tokenizer_type: str = "13a", + lowercase: bool = False, + punctuation_removal: bool = False, + character_tokenization: bool = False, + ): + from sacrebleu.tokenizers import TOKENIZERS + + assert tokenizer_type in self.ALL_TOKENIZER_TYPES + self.lowercase = lowercase + self.punctuation_removal = punctuation_removal + self.character_tokenization = character_tokenization + self.tokenizer = TOKENIZERS[tokenizer_type] + + @classmethod + def remove_punctuation(cls, sent: str): + """Remove punctuation based on Unicode category.""" + return cls.SPACE.join( + t + for t in sent.split(cls.SPACE) + if not all(unicodedata.category(c)[0] == "P" for c in t) + ) + + def tokenize(self, sent: str): + tokenized = self.tokenizer()(sent) + + if self.punctuation_removal: + tokenized = self.remove_punctuation(tokenized) + + if self.character_tokenization: + tokenized = self.SPACE.join( + list(tokenized.replace(self.SPACE, self.SPACE_ESCAPE)) + ) + + if self.lowercase: + tokenized = tokenized.lower() + + return tokenized diff --git a/fairseq-tools/fairseq/fairseq/scoring/wer.py b/fairseq-tools/fairseq/fairseq/scoring/wer.py new file mode 100644 index 00000000..21efefd9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/scoring/wer.py @@ -0,0 +1,55 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.scoring import BaseScorer, register_scorer +from fairseq.scoring.tokenizer import EvaluationTokenizer + + +@register_scorer("wer") +class WerScorer(BaseScorer): + def __init__(self, args): + super().__init__(args) + self.reset() + try: + import editdistance as ed + except ImportError: + raise ImportError("Please install editdistance to use WER scorer") + self.ed = ed + self.tokenizer = EvaluationTokenizer( + tokenizer_type=self.args.wer_tokenizer, + lowercase=self.args.wer_lowercase, + punctuation_removal=self.args.wer_remove_punct, + character_tokenization=self.args.wer_char_level, + ) + + @staticmethod + def add_args(parser): + # fmt: off + parser.add_argument('--wer-tokenizer', type=str, default='none', + choices=EvaluationTokenizer.ALL_TOKENIZER_TYPES, + help='sacreBLEU tokenizer to use for evaluation') + parser.add_argument('--wer-remove-punct', action='store_true', + help='remove punctuation') + parser.add_argument('--wer-char-level', action='store_true', + help='evaluate at character level') + parser.add_argument('--wer-lowercase', action='store_true', + help='lowercasing') + # fmt: on + + def reset(self): + self.distance = 0 + self.ref_length = 0 + + def add_string(self, ref, pred): + ref_items = self.tokenizer.tokenize(ref).split() + pred_items = self.tokenizer.tokenize(pred).split() + self.distance += self.ed.eval(ref_items, pred_items) + self.ref_length += len(ref_items) + + def result_string(self): + return f"WER: {self.score():.2f}" + + def score(self): + return 100.0 * self.distance / self.ref_length if self.ref_length > 0 else 0 diff --git a/fairseq-tools/fairseq/fairseq/search.py b/fairseq-tools/fairseq/fairseq/search.py new file mode 100644 index 00000000..d5ea68b4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/search.py @@ -0,0 +1,814 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import List, Optional + +import torch +import torch.nn as nn +from fairseq.token_generation_constraints import ( + ConstraintState, + OrderedConstraintState, + UnorderedConstraintState, +) +from torch import Tensor + + +class Search(nn.Module): + def __init__(self, tgt_dict): + super().__init__() + self.pad = tgt_dict.pad() + self.unk = tgt_dict.unk() + self.eos = tgt_dict.eos() + self.vocab_size = len(tgt_dict) + self.src_lengths = torch.tensor(-1) + self.supports_constraints = False + self.stop_on_max_len = False + + def step( + self, step, lprobs, scores, prev_output_tokens=None, original_batch_idxs=None + ): + """Take a single search step. + + Args: + step: the current search step, starting at 0 + lprobs: (bsz x input_beam_size x vocab_size) + the model's log-probabilities over the vocabulary at the current step + scores: (bsz x input_beam_size x step) + the historical model scores of each hypothesis up to this point + prev_output_tokens: (bsz x step) + the previously generated oputput tokens + original_batch_idxs: (bsz) + the tensor with the batch indices, in the range [0, bsz) + this is useful in case there has been applied a re-ordering + and we need to know the orignal indices + + Return: A tuple of (scores, indices, beams) where: + scores: (bsz x output_beam_size) + the scores of the chosen elements; output_beam_size can be + larger than input_beam_size, e.g., we may return + 2*input_beam_size to account for EOS + indices: (bsz x output_beam_size) + the indices of the chosen elements + beams: (bsz x output_beam_size) + the hypothesis ids of the chosen elements, in the range [0, input_beam_size) + """ + raise NotImplementedError + + @torch.jit.export + def set_src_lengths(self, src_lengths): + self.src_lengths = src_lengths + + @torch.jit.export + def init_constraints(self, batch_constraints: Optional[Tensor], beam_size: int): + """Initialize constraint states for constrained decoding (if supported). + + Args: + batch_constraints: (torch.Tensor, optional) + the list of constraints, in packed form + beam_size: (int) + the beam size + Returns: + *encoder_out* rearranged according to *new_order* + """ + pass + + def prune_sentences(self, batch_idxs: Tensor): + """ + Removes constraint states for completed sentences (if supported). + This is called from sequence_generator._generate() when sentences are + deleted from the batch. + + Args: + batch_idxs: Indices of *sentences* whose constraint state should be *kept*. + """ + pass + + def update_constraints(self, active_hypos: Tensor): + """ + Updates the constraint states by selecting the beam items that are retained. + This is called at each time step of sequence_generator._generate() when + the set of 2 * {beam_size} candidate hypotheses are reduced to the beam size. + + Args: + active_hypos: (batch size, beam size) + list of integers denoting, for each sentence, which beam candidate items + should be kept. + """ + pass + + +class BeamSearch(Search): + def __init__(self, tgt_dict): + super().__init__(tgt_dict) + self.constraint_states = None + + @torch.jit.export + def step( + self, + step: int, + lprobs, + scores: Optional[Tensor], + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + bsz, beam_size, vocab_size = lprobs.size() + + if step == 0: + # at the first step all hypotheses are equally likely, so use + # only the first beam + lprobs = lprobs[:, ::beam_size, :].contiguous() + else: + # make probs contain cumulative scores for each hypothesis + assert scores is not None + lprobs = lprobs + scores[:, :, step - 1].unsqueeze(-1) + + top_prediction = torch.topk( + lprobs.view(bsz, -1), + k=min( + # Take the best 2 x beam_size predictions. We'll choose the first + # beam_size of these which don't predict eos to continue with. + beam_size * 2, + lprobs.view(bsz, -1).size(1) - 1, # -1 so we never select pad + ), + ) + scores_buf = top_prediction[0] + indices_buf = top_prediction[1] + # Project back into relative indices and beams + beams_buf = indices_buf // vocab_size + indices_buf = indices_buf.fmod(vocab_size) + + # At this point, beams_buf and indices_buf are single-dim and contain relative indices + return scores_buf, indices_buf, beams_buf + + +class PrefixConstrainedBeamSearch(Search): + def __init__(self, tgt_dict, prefix_allowed_tokens_fn): + super().__init__(tgt_dict) + self.prefix_allowed_tokens_fn = prefix_allowed_tokens_fn + self.stop_on_max_len = True + + @torch.jit.export + def apply_mask(self, x, prev_output_tokens, original_batch_idxs): + beam_size = x.shape[0] // original_batch_idxs.shape[0] + original_batch_idxs = ( + original_batch_idxs.unsqueeze(-1).repeat((1, beam_size)).flatten().tolist() + ) + + mask = torch.full_like(x, -math.inf) + for sent_i, (sent, batch_i) in enumerate( + zip(prev_output_tokens, original_batch_idxs) + ): + mask[sent_i, :, self.prefix_allowed_tokens_fn(batch_i, sent)] = 0 + + return mask + + @torch.jit.export + def step( + self, + step: int, + lprobs: Tensor, + scores: Tensor, + prev_output_tokens: Tensor, + original_batch_idxs: Tensor, + ): + bsz, beam_size, vocab_size = lprobs.size() + + lprobs += self.apply_mask( + lprobs.view(bsz * beam_size, 1, vocab_size), + prev_output_tokens, + original_batch_idxs, + ).view(bsz, beam_size, vocab_size) + + if step == 0: + # at the first step all hypotheses are equally likely, so use + # only the first beam + lprobs = lprobs[:, ::beam_size, :].contiguous() + else: + # make probs contain cumulative scores for each hypothesis + assert scores is not None + lprobs = lprobs + scores[:, :, step - 1].unsqueeze(-1) + + top_prediction = torch.topk( + lprobs.view(bsz, -1), + k=min( + # Take the best beam_size predictions. We'll choose the first + # beam_size of these which don't predict eos to continue with. + beam_size, + lprobs.view(bsz, -1).size(1) - 1, # -1 so we never select pad + ), + ) + scores_buf = top_prediction[0] + indices_buf = top_prediction[1] + beams_buf = indices_buf // vocab_size + indices_buf = indices_buf.fmod(vocab_size) + return scores_buf, indices_buf, beams_buf + + +class LexicallyConstrainedBeamSearch(Search): + """Implements lexically constrained beam search as described in + + Fast Lexically Constrained Decoding with Dynamic Beam + Allocation for Neural Machine Translation. Post & Vilar, + NAACL 2018. https://www.aclweb.org/anthology/N18-1119/ + + and + + Improved Lexically Constrained Decoding for Translation and + Monolingual Rewriting. Hu et al, NAACL + 2019. https://www.aclweb.org/anthology/N19-1090/ + + This is accomplished by maintaining, for each beam hypothesis, a + ConstraintState object (see constraints.py) that tracks which + constraints have been generated and using this information to + shape the beam for each input sentence. + """ + + def __init__(self, tgt_dict, representation): + super().__init__(tgt_dict) + self.representation = representation + self.vocab_size = len(tgt_dict) + self.num_cands = 0 + self.supports_constraints = True + + @torch.jit.export + def init_constraints(self, batch_constraints: Optional[Tensor], beam_size: int): + self.constraint_states = [] + for constraint_tensor in batch_constraints: + if self.representation == "ordered": + constraint_state = OrderedConstraintState.create(constraint_tensor) + elif self.representation == "unordered": + constraint_state = UnorderedConstraintState.create(constraint_tensor) + + self.constraint_states.append([constraint_state for i in range(beam_size)]) + + @torch.jit.export + def prune_sentences(self, batch_idxs: Tensor): + self.constraint_states = [ + self.constraint_states[i] for i in batch_idxs.tolist() + ] + + @torch.jit.export + def update_constraints(self, active_hypos: Tensor): + if self.constraint_states: + batch_size = active_hypos.size(0) + for sentid in range(batch_size): + self.constraint_states[sentid] = [ + self.constraint_states[sentid][i] for i in active_hypos[sentid] + ] + + @torch.jit.export + def step( + self, + step: int, + lprobs: Tensor, + scores: Optional[Tensor], + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + """ + A constrained step builds a large candidates list from the following: + - the top 2 * {beam_size} items over the whole beam + - for each item in the beam + - the top {each_k} (default 1) + - all next constraints + We then compute the constrained state of each beam item, and assign + stripe codes: 0 to the best in each bank, 1 to the 2nd-best, and so + on. We then sort by (stripe, score), and truncate the list at + 2 * beam size. + + Args: + step: the decoder step + lprobs: (batch size, beam size, target vocab) + the target-vocab distributions for each item in the beam. + Retrun: A tuple of (scores, indices, beams, constraints) where: + scores: (batch, output beam size) + the scores of the chosen elements + indices: (batch, output beam size) + the target vocab indices of the chosen elements + beams: (batch, output beam size) + the 0-indexed hypothesis ids of the chosen elements + constraints: (batch, output beam size) + the new constraint states + """ + each_k = 1 + device = lprobs.device + + batch_size, beam_size, vocab_size = lprobs.size() + + self.num_cands = min( + # Just take the k-best. We'll get another k from the 1-best from each + # row, plus more from the constraints + beam_size * 2, + lprobs.view(batch_size, -1).size(1) - 1, # -1 so we never select pad + ) + + # STEP 0: Preliminary. Prevent EOS for unfinished hyps across all batch items + constraint_states = self.constraint_states + if constraint_states and step > 0: + not_finished_indices = [] + for sentno, sent_constraints in enumerate(constraint_states): + for beamno, state in enumerate(sent_constraints): + index = sentno * beam_size + beamno + if not state.finished: + not_finished_indices.append(index) + not_finished_indices = torch.tensor(not_finished_indices) + if not_finished_indices.numel() > 0: + lprobs.view(batch_size * beam_size, -1)[ + not_finished_indices, self.eos + ] = -math.inf + + if step == 0: + # at the first step all hypotheses are equally likely, so use + # only the first beam entry for each batch item + lprobs = lprobs[:, ::beam_size, :].contiguous() + else: + # make probs contain cumulative scores for each hypothesis + assert scores is not None + lprobs = lprobs + scores[:, :, step - 1].unsqueeze(-1) + + top_prediction = torch.topk( + lprobs.view(batch_size, -1), + self.num_cands, + ) + scores_buf, indices_buf = top_prediction + # Project back into relative indices and beams + beams_buf = indices_buf // vocab_size + indices_buf = indices_buf.fmod(vocab_size) + + # Short circuit if there are no constraints in this batch + if not constraint_states: + return scores_buf, indices_buf, beams_buf + + # STEP 1: get top-1 from each hypothesis across all sentences in the batch + if step > 0: + top_scores, top_indices = torch.topk( + lprobs.view(batch_size * beam_size, -1), + k=each_k, + dim=1, + ) + top_scores = top_scores.view(batch_size, -1) + top_indices = top_indices.view(batch_size, -1) + scores_buf = torch.cat((scores_buf, top_scores), dim=1) + indices_buf = torch.cat((indices_buf, top_indices), dim=1) + new_beams = torch.arange(0, beam_size, device=device).repeat(batch_size, 1) + beams_buf = torch.cat((beams_buf, new_beams), dim=1) + + # Now, process sentences in the batch one by one. + new_scores_buf = torch.zeros((batch_size, 2 * beam_size), device=device) + new_indices_buf = torch.zeros((batch_size, 2 * beam_size), device=device).long() + new_beams_buf = torch.zeros((batch_size, 2 * beam_size), device=device).long() + for sentno, states in enumerate(constraint_states): + scores, indices, beams, new_states = self.step_sentence( + step, + sentno, + lprobs[sentno], + constraint_states[sentno], + beams_buf[sentno].clone(), + indices_buf[sentno].clone(), + scores_buf[sentno].clone(), + ) + new_scores_buf[sentno] = scores + new_indices_buf[sentno] = indices + new_beams_buf[sentno] = beams + self.constraint_states[sentno] = new_states + + return new_scores_buf, new_indices_buf, new_beams_buf + + @torch.jit.export + def step_sentence( + self, + step: int, + sentno: int, + lprobs: Tensor, + constraint_states: List[List[ConstraintState]], + beams_buf: Tensor, + indices_buf: Tensor, + scores_buf: Tensor, + ): + """Does per-sentence processing. Adds all constraints for each + hypothesis to the list of candidates; then removes duplicates, + sorts, and dynamically stripes across the banks. All tensor inputs + are collapsed to those pertaining to a single input sentence. + """ + device = lprobs.device + + # STEP 2: Add all constraints for each beam item + for beamno, state in enumerate(constraint_states): + next_tokens = torch.tensor(list(state.next_tokens()), device=device).long() + if next_tokens.numel() != 0: + indices_buf = torch.cat((indices_buf, next_tokens)) + next_beams = ( + torch.tensor(beamno, device=device) + .repeat(next_tokens.size(0)) + .long() + ) + beams_buf = torch.cat((beams_buf, next_beams)) + next_values = lprobs[beamno].take(next_tokens.view(-1)) + scores_buf = torch.cat((scores_buf, next_values)) + + # At the 0th time step, there is just one beam item + if step == 0: + break + + # STEP 3: Compute the "bank" for each candidate. This is the + # number of constraints it's generated. We need this so that + # we can do round-robin allocation of the beam across these + # banks. If C is the number of constraints, we select the best + # item in bank C, then the best in bank C-1, etc, followed by + # the 2nd-best in bank C, the 2nd-best in bank C-1, etc, and so + # on, until the maximum beam size. We accomplish this by + # creating a sort key and striping across the banks. + + # Compute the new states for all candidates + cands_size = indices_buf.size(0) + constraint_states = [ + constraint_states[beams_buf[i]].advance(indices_buf[i]) + for i in range(cands_size) + ] + + banks = torch.tensor([state.bank for state in constraint_states], device=device) + + # STEP 4: Sort + num_constraint_tokens = len(state.tokens) + + # Sort by keys (bank, score) (i.e., sort banks together, and scores + # within banks). AFAIK pytorch doesn't support either stable sort or + # multi-key sorting, so we have to hack this. + MAX_SCORE = -100 + sort_key = (num_constraint_tokens - banks) * MAX_SCORE + scores_buf + sort_values, sort_indices = sort_key.sort(dim=0, descending=True) + scores_buf = scores_buf[sort_indices] + indices_buf = indices_buf[sort_indices] + beams_buf = beams_buf[sort_indices] + banks = banks[sort_indices] + + # Sort the constraints to follow suit + constraint_states = [constraint_states[i] for i in sort_indices] + + # STEP 5: Remove duplicates. The topk calls (overall and + # per-row) plus the per-row generation of constraints will + # produce duplicates. Here we remove them. + + def roll(t): + """Rolls a 1d tensor left by 1. + + [0, 1, 2, 3, 4] becomes [4, 0, 1, 2, 3] + """ + return torch.cat((t[-1].unsqueeze(0), t[0:-1]), dim=0) + + # We map candidates (beam, token_id) to a single dimension. + # This is then shifted by 1. We can then easily identify + # duplicates and create a mask that identifies unique + # extensions. + uniques_mask = beams_buf * (self.vocab_size + 1) + indices_buf + uniques_mask = roll(uniques_mask) != uniques_mask + + # Use the mask to pare down the data structures + scores_buf = torch.masked_select(scores_buf, uniques_mask) + indices_buf = torch.masked_select(indices_buf, uniques_mask) + beams_buf = torch.masked_select(beams_buf, uniques_mask) + banks = torch.masked_select(banks, uniques_mask) + i = 1 + for mask in uniques_mask[1:]: + if not mask: + constraint_states.pop(i) + i += mask + + # STEP 6: Assign IDs round-robin across banks, sort, and + # truncate. Now that the candidates are sorted by (bank, + # score) and uniqed, we dynamically allocate the {beam_size} + # beam by striping across the candidates. These stripes will + # be used as sort keys to do round-robin selection. This is + # accomplished in a single pass with offsets. Sorting by + # highest-banks (furthest-along hypotheses) first ensures + # progress through the constraints. + # + # e.g., BANKS: 3 3 3 2 2 2 2 1 1 1 0 0 + # OLD STRIPES: 0 1 2 0 1 2 3 0 1 2 0 1 + # NEW STRIPES: 0 1+4 2+8 0+1 1+5 2+9 3+11 0+2 1+6 2+10 0+3 1+7 + # = 0 5 10 1 6 11 13 2 7 12 3 8 + # + # Sorting by this then gives the following banks: + # + # 3 2 1 0 3 2 1 0 3 2 1 2 + # + # We'll take the top {beam_size} of these. + stripe_offsets = [offset * (len(banks) + 1) for offset in range(len(banks) + 1)] + stripes = torch.zeros_like(banks) + cur_bank_count = -1 + cur_bank = banks[0] + for i, bank in enumerate(banks): + if bank != cur_bank: + cur_bank_count = 0 + cur_bank = bank + else: + cur_bank_count += 1 + stripes[i] = num_constraint_tokens - bank + stripe_offsets[cur_bank_count] + + # STEP 7: Sort by the stripes values + sort_values, sort_indices = stripes.sort(dim=0) + scores_buf = scores_buf[sort_indices] + indices_buf = indices_buf[sort_indices] + beams_buf = beams_buf[sort_indices] + constraint_states = [constraint_states[i] for i in sort_indices] + + # STEP 8: Truncate to the candidates size! + scores_buf = scores_buf[: self.num_cands] + indices_buf = indices_buf[: self.num_cands] + beams_buf = beams_buf[: self.num_cands] + + return scores_buf, indices_buf, beams_buf, constraint_states + + +class LengthConstrainedBeamSearch(Search): + def __init__(self, tgt_dict, min_len_a, min_len_b, max_len_a, max_len_b): + super().__init__(tgt_dict) + self.min_len_a = min_len_a + self.min_len_b = min_len_b + self.max_len_a = max_len_a + self.max_len_b = max_len_b + self.beam = BeamSearch(tgt_dict) + self.needs_src_lengths = True + + def step( + self, + step: int, + lprobs, + scores, + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + min_lens = self.min_len_a * self.src_lengths + self.min_len_b + max_lens = self.max_len_a * self.src_lengths + self.max_len_b + lprobs[step < min_lens, :, self.eos] = -math.inf + lprobs[step >= max_lens, :, self.eos] = 0 + return self.beam.step(step, lprobs, scores) + + +class DiverseBeamSearch(Search): + """Diverse Beam Search. + + See "Diverse Beam Search: Decoding Diverse Solutions from Neural Sequence + Models" for details. + + We only implement the Hamming Diversity penalty here, which performed best + in the original paper. + """ + + def __init__(self, tgt_dict, num_groups, diversity_strength): + super().__init__(tgt_dict) + self.num_groups = num_groups + self.diversity_strength = -diversity_strength + self.beam = BeamSearch(tgt_dict) + + @torch.jit.export + def step( + self, + step: int, + lprobs, + scores, + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + bsz, beam_size, vocab_size = lprobs.size() + if beam_size % self.num_groups != 0: + raise ValueError( + "DiverseBeamSearch requires --beam to be divisible by the number of groups" + ) + + # initialize diversity penalty + diversity_buf = torch.zeros(lprobs[:, 0, :].size()).to(lprobs) + + scores_G, indices_G, beams_G = [], [], [] + for g in range(self.num_groups): + lprobs_g = lprobs[:, g :: self.num_groups, :] + scores_g = scores[:, g :: self.num_groups, :] if step > 0 else None + + # apply diversity penalty + if g > 0: + lprobs_g = torch.add( + lprobs_g, + other=diversity_buf.unsqueeze(1), + alpha=self.diversity_strength, + ) + else: + lprobs_g = lprobs_g.contiguous() + + scores_buf, indices_buf, beams_buf = self.beam.step( + step, lprobs_g, scores_g + ) + beams_buf.mul_(self.num_groups).add_(g) + + scores_G.append(scores_buf.clone()) + indices_G.append(indices_buf.clone()) + beams_G.append(beams_buf.clone()) + + # update diversity penalty + diversity_buf.scatter_add_( + 1, indices_buf, torch.ones(indices_buf.size()).to(diversity_buf) + ) + + # interleave results from different groups + scores_buf = torch.stack(scores_G, dim=2).view(bsz, -1) + indices_buf = torch.stack(indices_G, dim=2).view(bsz, -1) + beams_buf = torch.stack(beams_G, dim=2).view(bsz, -1) + return scores_buf, indices_buf, beams_buf + + +class Sampling(Search): + sampling_topk: int + sampling_topp: float + + def __init__(self, tgt_dict, sampling_topk=-1, sampling_topp=-1.0): + super().__init__(tgt_dict) + self.sampling_topk = sampling_topk + self.sampling_topp = sampling_topp + + def _sample_topp(self, lprobs): + """Sample among the smallest set of elements whose cumulative probability mass exceeds p. + + See `"The Curious Case of Neural Text Degeneration" + (Holtzman et al., 2019) <https://arxiv.org/abs/1904.09751>`_. + + Args: + lprobs: (bsz x input_beam_size x vocab_size) + the model's log-probabilities over the vocabulary at the current step + + Return: A tuple of (trimed_probs, truncated_indices) where: + trimed_probs: (bsz x input_beam_size x ?) + the model's probabilities over the elements selected to sample from. The + width of the third dimension is determined by top-P. + truncated_indices: (bsz x input_beam_size x ?) + the indices of the chosen elements. + """ + probs = lprobs.exp_() + + # sort the last dimension (vocab dimension) in descending order + sorted_probs, sorted_indices = probs.sort(descending=True) + + # compute a mask to indicate the words to be included in the top-P set. + cumsum_probs = sorted_probs.cumsum(dim=2) + mask = cumsum_probs.lt(self.sampling_topp) + + # note that mask was computed by 'lt'. One more word needs to be included + # so that the cumulative probability mass can exceed p. + cumsum_mask = mask.cumsum(dim=2) + last_included = cumsum_mask[:, :, -1:] + last_included.clamp_(0, mask.size()[2] - 1) + mask = mask.scatter_(2, last_included, 1) + + # truncate unnecessary dims. + max_dim = last_included.max() + truncated_mask = mask[:, :, : max_dim + 1] + truncated_probs = sorted_probs[:, :, : max_dim + 1] + truncated_indices = sorted_indices[:, :, : max_dim + 1] + + # trim the words that are not in top-P by setting their probabilities + # to 0, so that they would not be sampled later. + trim_mask = ~truncated_mask + trimed_probs = truncated_probs.masked_fill_(trim_mask, 0) + return trimed_probs, truncated_indices + + @torch.jit.export + def step( + self, + step: int, + lprobs, + scores, + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + bsz, beam_size, vocab_size = lprobs.size() + + if step == 0: + # at the first step all hypotheses are equally likely, so use + # only the first beam + lprobs = lprobs[:, ::beam_size, :].contiguous() + + if self.sampling_topp > 0: + # only sample from the smallest set of words whose cumulative probability mass exceeds p + probs, top_indices = self._sample_topp(lprobs) + elif self.sampling_topk > 0: + # only sample from top-k candidates + lprobs, top_indices = lprobs.topk(self.sampling_topk) + probs = lprobs.exp_() + else: + probs = lprobs.exp_() + + # dummy data to be consistent with true branch for type check + top_indices = torch.empty(0).to(probs) + # sample + if step == 0: + indices_buf = torch.multinomial( + probs.view(bsz, -1), + beam_size, + replacement=True, + ).view(bsz, beam_size) + else: + indices_buf = torch.multinomial( + probs.view(bsz * beam_size, -1), + 1, + replacement=True, + ).view(bsz, beam_size) + + if step == 0: + # expand to beam size + probs = probs.expand(bsz, beam_size, -1) + + # gather scores + scores_buf = torch.gather(probs, dim=2, index=indices_buf.unsqueeze(-1)) + scores_buf = scores_buf.log_().view(bsz, -1) + + # remap indices if using top-k or top-P sampling + if self.sampling_topk > 0 or self.sampling_topp > 0: + indices_buf = torch.gather( + top_indices.expand(bsz, beam_size, -1), + dim=2, + index=indices_buf.unsqueeze(-1), + ).squeeze(2) + + if step == 0: + beams_buf = indices_buf.new_zeros(bsz, beam_size) + else: + beams_buf = torch.arange(0, beam_size).to(indices_buf).repeat(bsz, 1) + # make scores cumulative + scores_buf.add_( + torch.gather(scores[:, :, step - 1], dim=1, index=beams_buf) + ) + + return scores_buf, indices_buf, beams_buf + + +class DiverseSiblingsSearch(Search): + """ + Beam search with diverse siblings. + + See "A Simple, Fast Diverse Decoding Algorithm for Neural Generation" for details. + https://arxiv.org/abs/1611.08562 + + 1/ Calculate hypotheses for each beam + 2/ Intra-sibling ordering + 3/ Rewrite scores + 4/ Choose top K hypotheses + + if diversity_rate == 0 is equivalent to BeamSearch + """ + + def __init__(self, tgt_dict, diversity_rate): + super().__init__(tgt_dict) + self.diversity_rate = diversity_rate + self.beam = BeamSearch(tgt_dict) + + def step( + self, + step: int, + lprobs, + scores, + prev_output_tokens: Optional[Tensor] = None, + original_batch_idxs: Optional[Tensor] = None, + ): + bsz, beam_size, vocab_size = lprobs.size() + k = min( + # Take the best 2 x beam_size predictions. We'll choose the first + # beam_size of these which don't predict eos to continue with. + beam_size * 2, + lprobs.view(bsz, -1).size(1) - 1, # -1 so we never select pad + ) + s_list: List[Tensor] + i_list: List[Tensor] + s_list = [torch.empty(0).to(lprobs) for i in range(beam_size)] + i_list = [torch.LongTensor().to(device=lprobs.device) for i in range(beam_size)] + sibling_score = torch.arange(1, k + 1).to(lprobs) * self.diversity_rate + + if step == 0: + return self.beam.step(step, lprobs, scores) + lprobs.add_(scores[:, :, step - 1].unsqueeze(-1)) + + # 1/ Calculate hypotheses for each beam + for i in range(beam_size): + torch.topk(lprobs[:, i, :].view(bsz, -1), k, out=(s_list[i], i_list[i])) + i_list[i].fmod_(vocab_size) + + # 2/ Intra-sibling ordering by default from topk + 3/ Rewrite scores + s_list[i].sub_(sibling_score) + + # 4/ Choose top K hypotheses + indices = torch.stack(i_list, dim=1).view(bsz, -1) + + final_scores = torch.empty(0).to(lprobs) + final_indices = torch.LongTensor().to(device=lprobs.device) + final_beams = torch.LongTensor().to(device=lprobs.device) + (final_scores, final_indices) = torch.topk( + torch.stack(s_list, dim=1).view(bsz, -1), + k, + ) + + final_beams = final_indices // k + + for i in range(bsz): + final_indices[i] = indices[i][final_indices[i]] + + return final_scores, final_indices, final_beams diff --git a/fairseq-tools/fairseq/fairseq/sequence_generator.py b/fairseq-tools/fairseq/fairseq/sequence_generator.py new file mode 100644 index 00000000..ddfb6785 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/sequence_generator.py @@ -0,0 +1,1008 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import math +from typing import Dict, List, Optional + +import torch +import torch.nn as nn +from fairseq import search, utils +from fairseq.data import data_utils +from fairseq.models import FairseqIncrementalDecoder +from fairseq.models.fairseq_encoder import EncoderOut +from torch import Tensor + + +class SequenceGenerator(nn.Module): + def __init__( + self, + models, + tgt_dict, + beam_size=1, + max_len_a=0, + max_len_b=200, + min_len=1, + normalize_scores=True, + len_penalty=1.0, + unk_penalty=0.0, + temperature=1.0, + match_source_len=False, + no_repeat_ngram_size=0, + search_strategy=None, + eos=None, + symbols_to_strip_from_output=None, + lm_model=None, + lm_weight=1.0, + ): + """Generates translations of a given source sentence. + + Args: + models (List[~fairseq.models.FairseqModel]): ensemble of models, + currently support fairseq.models.TransformerModel for scripting + beam_size (int, optional): beam width (default: 1) + max_len_a/b (int, optional): generate sequences of maximum length + ax + b, where x is the source length + min_len (int, optional): the minimum length of the generated output + (not including end-of-sentence) + normalize_scores (bool, optional): normalize scores by the length + of the output (default: True) + len_penalty (float, optional): length penalty, where <1.0 favors + shorter, >1.0 favors longer sentences (default: 1.0) + unk_penalty (float, optional): unknown word penalty, where <0 + produces more unks, >0 produces fewer (default: 0.0) + temperature (float, optional): temperature, where values + >1.0 produce more uniform samples and values <1.0 produce + sharper samples (default: 1.0) + match_source_len (bool, optional): outputs should match the source + length (default: False) + """ + super().__init__() + if isinstance(models, EnsembleModel): + self.model = models + else: + self.model = EnsembleModel(models) + self.tgt_dict = tgt_dict + self.pad = tgt_dict.pad() + self.unk = tgt_dict.unk() + self.eos = tgt_dict.eos() if eos is None else eos + self.symbols_to_strip_from_output = ( + symbols_to_strip_from_output.union({self.eos}) + if symbols_to_strip_from_output is not None + else {self.eos} + ) + self.vocab_size = len(tgt_dict) + self.beam_size = beam_size + # the max beam size is the dictionary size - 1, since we never select pad + self.beam_size = min(beam_size, self.vocab_size - 1) + self.max_len_a = max_len_a + self.max_len_b = max_len_b + self.min_len = min_len + + self.normalize_scores = normalize_scores + self.len_penalty = len_penalty + self.unk_penalty = unk_penalty + self.temperature = temperature + self.match_source_len = match_source_len + self.no_repeat_ngram_size = no_repeat_ngram_size + assert temperature > 0, "--temperature must be greater than 0" + + self.search = ( + search.BeamSearch(tgt_dict) if search_strategy is None else search_strategy + ) + # We only need to set src_lengths in LengthConstrainedBeamSearch. + # As a module attribute, setting it would break in multithread + # settings when the model is shared. + self.should_set_src_lengths = ( + hasattr(self.search, "needs_src_lengths") and self.search.needs_src_lengths + ) + + self.model.eval() + + self.lm_model = lm_model + self.lm_weight = lm_weight + if self.lm_model is not None: + self.lm_model.eval() + + def cuda(self): + self.model.cuda() + return self + + @torch.no_grad() + def forward( + self, + sample: Dict[str, Dict[str, Tensor]], + prefix_tokens: Optional[Tensor] = None, + bos_token: Optional[int] = None, + ): + """Generate a batch of translations. + + Args: + sample (dict): batch + prefix_tokens (torch.LongTensor, optional): force decoder to begin + with these tokens + bos_token (int, optional): beginning of sentence token + (default: self.eos) + """ + return self._generate(sample, prefix_tokens, bos_token=bos_token) + + # TODO(myleott): unused, deprecate after pytorch-translate migration + def generate_batched_itr(self, data_itr, beam_size=None, cuda=False, timer=None): + """Iterate over a batched dataset and yield individual translations. + Args: + cuda (bool, optional): use GPU for generation + timer (StopwatchMeter, optional): time generations + """ + for sample in data_itr: + s = utils.move_to_cuda(sample) if cuda else sample + if "net_input" not in s: + continue + input = s["net_input"] + # model.forward normally channels prev_output_tokens into the decoder + # separately, but SequenceGenerator directly calls model.encoder + encoder_input = { + k: v for k, v in input.items() if k != "prev_output_tokens" + } + if timer is not None: + timer.start() + with torch.no_grad(): + hypos = self.generate(encoder_input) + if timer is not None: + timer.stop(sum(len(h[0]["tokens"]) for h in hypos)) + for i, id in enumerate(s["id"].data): + # remove padding + src = utils.strip_pad(input["src_tokens"].data[i, :], self.pad) + ref = ( + utils.strip_pad(s["target"].data[i, :], self.pad) + if s["target"] is not None + else None + ) + yield id, src, ref, hypos[i] + + @torch.no_grad() + def generate(self, models, sample: Dict[str, Dict[str, Tensor]], **kwargs): + """Generate translations. Match the api of other fairseq generators. + + Args: + models (List[~fairseq.models.FairseqModel]): ensemble of models + sample (dict): batch + prefix_tokens (torch.LongTensor, optional): force decoder to begin + with these tokens + constraints (torch.LongTensor, optional): force decoder to include + the list of constraints + bos_token (int, optional): beginning of sentence token + (default: self.eos) + """ + return self._generate(sample, **kwargs) + + def _generate( + self, + sample: Dict[str, Dict[str, Tensor]], + prefix_tokens: Optional[Tensor] = None, + constraints: Optional[Tensor] = None, + bos_token: Optional[int] = None, + ): + incremental_states = torch.jit.annotate( + List[Dict[str, Dict[str, Optional[Tensor]]]], + [ + torch.jit.annotate(Dict[str, Dict[str, Optional[Tensor]]], {}) + for i in range(self.model.models_size) + ], + ) + net_input = sample["net_input"] + + if "src_tokens" in net_input: + src_tokens = net_input["src_tokens"] + # length of the source text being the character length except EndOfSentence and pad + src_lengths = ( + (src_tokens.ne(self.eos) & src_tokens.ne(self.pad)).long().sum(dim=1) + ) + elif "source" in net_input: + src_tokens = net_input["source"] + src_lengths = ( + net_input["padding_mask"].size(-1) - net_input["padding_mask"].sum(-1) + if net_input["padding_mask"] is not None + else torch.tensor(src_tokens.size(-1)).to(src_tokens) + ) + else: + raise Exception("expected src_tokens or source in net input") + + # bsz: total number of sentences in beam + # Note that src_tokens may have more than 2 dimenions (i.e. audio features) + bsz, src_len = src_tokens.size()[:2] + beam_size = self.beam_size + + if constraints is not None and not self.search.supports_constraints: + raise NotImplementedError( + "Target-side constraints were provided, but search method doesn't support them" + ) + + # Initialize constraints, when active + self.search.init_constraints(constraints, beam_size) + + max_len: int = -1 + if self.match_source_len: + max_len = src_lengths.max().item() + else: + max_len = min( + int(self.max_len_a * src_len + self.max_len_b), + # exclude the EOS marker + self.model.max_decoder_positions() - 1, + ) + assert ( + self.min_len <= max_len + ), "min_len cannot be larger than max_len, please adjust these!" + # compute the encoder output for each beam + encoder_outs = self.model.forward_encoder(net_input) + + # placeholder of indices for bsz * beam_size to hold tokens and accumulative scores + new_order = torch.arange(bsz).view(-1, 1).repeat(1, beam_size).view(-1) + new_order = new_order.to(src_tokens.device).long() + encoder_outs = self.model.reorder_encoder_out(encoder_outs, new_order) + # ensure encoder_outs is a List. + assert encoder_outs is not None + + # initialize buffers + scores = ( + torch.zeros(bsz * beam_size, max_len + 1).to(src_tokens).float() + ) # +1 for eos; pad is never chosen for scoring + tokens = ( + torch.zeros(bsz * beam_size, max_len + 2) + .to(src_tokens) + .long() + .fill_(self.pad) + ) # +2 for eos and pad + tokens[:, 0] = self.eos if bos_token is None else bos_token + attn: Optional[Tensor] = None + + # A list that indicates candidates that should be ignored. + # For example, suppose we're sampling and have already finalized 2/5 + # samples. Then cands_to_ignore would mark 2 positions as being ignored, + # so that we only finalize the remaining 3 samples. + cands_to_ignore = ( + torch.zeros(bsz, beam_size).to(src_tokens).eq(-1) + ) # forward and backward-compatible False mask + + # list of completed sentences + finalized = torch.jit.annotate( + List[List[Dict[str, Tensor]]], + [torch.jit.annotate(List[Dict[str, Tensor]], []) for i in range(bsz)], + ) # contains lists of dictionaries of infomation about the hypothesis being finalized at each step + + finished = [ + False for i in range(bsz) + ] # a boolean array indicating if the sentence at the index is finished or not + num_remaining_sent = bsz # number of sentences remaining + + # number of candidate hypos per step + cand_size = 2 * beam_size # 2 x beam size in case half are EOS + + # offset arrays for converting between different indexing schemes + bbsz_offsets = (torch.arange(0, bsz) * beam_size).unsqueeze(1).type_as(tokens) + cand_offsets = torch.arange(0, cand_size).type_as(tokens) + + reorder_state: Optional[Tensor] = None + batch_idxs: Optional[Tensor] = None + + original_batch_idxs: Optional[Tensor] = None + if "id" in sample and isinstance(sample["id"], Tensor): + original_batch_idxs = sample["id"] + else: + original_batch_idxs = torch.arange(0, bsz).type_as(tokens) + + for step in range(max_len + 1): # one extra step for EOS marker + # reorder decoder internal states based on the prev choice of beams + # print(f'step: {step}') + if reorder_state is not None: + if batch_idxs is not None: + # update beam indices to take into account removed sentences + corr = batch_idxs - torch.arange(batch_idxs.numel()).type_as( + batch_idxs + ) + reorder_state.view(-1, beam_size).add_( + corr.unsqueeze(-1) * beam_size + ) + original_batch_idxs = original_batch_idxs[batch_idxs] + self.model.reorder_incremental_state(incremental_states, reorder_state) + encoder_outs = self.model.reorder_encoder_out( + encoder_outs, reorder_state + ) + + lprobs, avg_attn_scores = self.model.forward_decoder( + tokens[:, : step + 1], + encoder_outs, + incremental_states, + self.temperature, + ) + + if self.lm_model is not None: + lm_out = self.lm_model(tokens[:, : step + 1]) + probs = self.lm_model.get_normalized_probs( + lm_out, log_probs=True, sample=None + ) + probs = probs[:, -1, :] * self.lm_weight + lprobs += probs + + lprobs[lprobs != lprobs] = torch.tensor(-math.inf).to(lprobs) + + lprobs[:, self.pad] = -math.inf # never select pad + lprobs[:, self.unk] -= self.unk_penalty # apply unk penalty + + # handle max length constraint + if step >= max_len: + lprobs[:, : self.eos] = -math.inf + lprobs[:, self.eos + 1 :] = -math.inf + + # handle prefix tokens (possibly with different lengths) + if ( + prefix_tokens is not None + and step < prefix_tokens.size(1) + and step < max_len + ): + lprobs, tokens, scores = self._prefix_tokens( + step, lprobs, scores, tokens, prefix_tokens, beam_size + ) + elif step < self.min_len: + # minimum length constraint (does not apply if using prefix_tokens) + lprobs[:, self.eos] = -math.inf + + # Record attention scores, only support avg_attn_scores is a Tensor + if avg_attn_scores is not None: + if attn is None: + attn = torch.empty( + bsz * beam_size, avg_attn_scores.size(1), max_len + 2 + ).to(scores) + attn[:, :, step + 1].copy_(avg_attn_scores) + + scores = scores.type_as(lprobs) + eos_bbsz_idx = torch.empty(0).to( + tokens + ) # indices of hypothesis ending with eos (finished sentences) + eos_scores = torch.empty(0).to( + scores + ) # scores of hypothesis ending with eos (finished sentences) + + if self.should_set_src_lengths: + self.search.set_src_lengths(src_lengths) + + if self.no_repeat_ngram_size > 0: + lprobs = self._no_repeat_ngram(tokens, lprobs, bsz, beam_size, step) + + # Shape: (batch, cand_size) + cand_scores, cand_indices, cand_beams = self.search.step( + step, + lprobs.view(bsz, -1, self.vocab_size), + scores.view(bsz, beam_size, -1)[:, :, :step], + tokens[:, : step + 1], + original_batch_idxs, + ) + + # cand_bbsz_idx contains beam indices for the top candidate + # hypotheses, with a range of values: [0, bsz*beam_size), + # and dimensions: [bsz, cand_size] + cand_bbsz_idx = cand_beams.add(bbsz_offsets) + + # finalize hypotheses that end in eos + # Shape of eos_mask: (batch size, beam size) + eos_mask = cand_indices.eq(self.eos) & cand_scores.ne(-math.inf) + eos_mask[:, :beam_size][cands_to_ignore] = torch.tensor(0).to(eos_mask) + + # only consider eos when it's among the top beam_size indices + # Now we know what beam item(s) to finish + # Shape: 1d list of absolute-numbered + eos_bbsz_idx = torch.masked_select( + cand_bbsz_idx[:, :beam_size], mask=eos_mask[:, :beam_size] + ) + + finalized_sents: List[int] = [] + if eos_bbsz_idx.numel() > 0: + eos_scores = torch.masked_select( + cand_scores[:, :beam_size], mask=eos_mask[:, :beam_size] + ) + + finalized_sents = self.finalize_hypos( + step, + eos_bbsz_idx, + eos_scores, + tokens, + scores, + finalized, + finished, + beam_size, + attn, + src_lengths, + max_len, + ) + num_remaining_sent -= len(finalized_sents) + + assert num_remaining_sent >= 0 + if num_remaining_sent == 0: + break + if self.search.stop_on_max_len and step >= max_len: + break + assert step < max_len + + # Remove finalized sentences (ones for which {beam_size} + # finished hypotheses have been generated) from the batch. + if len(finalized_sents) > 0: + new_bsz = bsz - len(finalized_sents) + + # construct batch_idxs which holds indices of batches to keep for the next pass + batch_mask = torch.ones( + bsz, dtype=torch.bool, device=cand_indices.device + ) + batch_mask[finalized_sents] = False + # TODO replace `nonzero(as_tuple=False)` after TorchScript supports it + batch_idxs = torch.arange( + bsz, device=cand_indices.device + ).masked_select(batch_mask) + + # Choose the subset of the hypothesized constraints that will continue + self.search.prune_sentences(batch_idxs) + + eos_mask = eos_mask[batch_idxs] + cand_beams = cand_beams[batch_idxs] + bbsz_offsets.resize_(new_bsz, 1) + cand_bbsz_idx = cand_beams.add(bbsz_offsets) + cand_scores = cand_scores[batch_idxs] + cand_indices = cand_indices[batch_idxs] + + if prefix_tokens is not None: + prefix_tokens = prefix_tokens[batch_idxs] + src_lengths = src_lengths[batch_idxs] + cands_to_ignore = cands_to_ignore[batch_idxs] + + scores = scores.view(bsz, -1)[batch_idxs].view(new_bsz * beam_size, -1) + tokens = tokens.view(bsz, -1)[batch_idxs].view(new_bsz * beam_size, -1) + if attn is not None: + attn = attn.view(bsz, -1)[batch_idxs].view( + new_bsz * beam_size, attn.size(1), -1 + ) + bsz = new_bsz + else: + batch_idxs = None + + # Set active_mask so that values > cand_size indicate eos hypos + # and values < cand_size indicate candidate active hypos. + # After, the min values per row are the top candidate active hypos + + # Rewrite the operator since the element wise or is not supported in torchscript. + + eos_mask[:, :beam_size] = ~((~cands_to_ignore) & (~eos_mask[:, :beam_size])) + active_mask = torch.add( + eos_mask.type_as(cand_offsets) * cand_size, + cand_offsets[: eos_mask.size(1)], + ) + + # get the top beam_size active hypotheses, which are just + # the hypos with the smallest values in active_mask. + # {active_hypos} indicates which {beam_size} hypotheses + # from the list of {2 * beam_size} candidates were + # selected. Shapes: (batch size, beam size) + new_cands_to_ignore, active_hypos = torch.topk( + active_mask, k=beam_size, dim=1, largest=False + ) + + # update cands_to_ignore to ignore any finalized hypos. + cands_to_ignore = new_cands_to_ignore.ge(cand_size)[:, :beam_size] + # Make sure there is at least one active item for each sentence in the batch. + assert (~cands_to_ignore).any(dim=1).all() + + # update cands_to_ignore to ignore any finalized hypos + + # {active_bbsz_idx} denotes which beam number is continued for each new hypothesis (a beam + # can be selected more than once). + active_bbsz_idx = torch.gather(cand_bbsz_idx, dim=1, index=active_hypos) + active_scores = torch.gather(cand_scores, dim=1, index=active_hypos) + + active_bbsz_idx = active_bbsz_idx.view(-1) + active_scores = active_scores.view(-1) + + # copy tokens and scores for active hypotheses + + # Set the tokens for each beam (can select the same row more than once) + tokens[:, : step + 1] = torch.index_select( + tokens[:, : step + 1], dim=0, index=active_bbsz_idx + ) + # Select the next token for each of them + tokens.view(bsz, beam_size, -1)[:, :, step + 1] = torch.gather( + cand_indices, dim=1, index=active_hypos + ) + if step > 0: + scores[:, :step] = torch.index_select( + scores[:, :step], dim=0, index=active_bbsz_idx + ) + scores.view(bsz, beam_size, -1)[:, :, step] = torch.gather( + cand_scores, dim=1, index=active_hypos + ) + + # Update constraints based on which candidates were selected for the next beam + self.search.update_constraints(active_hypos) + + # copy attention for active hypotheses + if attn is not None: + attn[:, :, : step + 2] = torch.index_select( + attn[:, :, : step + 2], dim=0, index=active_bbsz_idx + ) + + # reorder incremental state in decoder + reorder_state = active_bbsz_idx + + # sort by score descending + for sent in range(len(finalized)): + scores = torch.tensor( + [float(elem["score"].item()) for elem in finalized[sent]] + ) + _, sorted_scores_indices = torch.sort(scores, descending=True) + finalized[sent] = [finalized[sent][ssi] for ssi in sorted_scores_indices] + finalized[sent] = torch.jit.annotate( + List[Dict[str, Tensor]], finalized[sent] + ) + return finalized + + def _prefix_tokens( + self, step: int, lprobs, scores, tokens, prefix_tokens, beam_size: int + ): + """Handle prefix tokens""" + prefix_toks = prefix_tokens[:, step].unsqueeze(-1).repeat(1, beam_size).view(-1) + prefix_lprobs = lprobs.gather(-1, prefix_toks.unsqueeze(-1)) + prefix_mask = prefix_toks.ne(self.pad) + lprobs[prefix_mask] = torch.tensor(-math.inf).to(lprobs) + lprobs[prefix_mask] = lprobs[prefix_mask].scatter( + -1, prefix_toks[prefix_mask].unsqueeze(-1), prefix_lprobs[prefix_mask] + ) + # if prefix includes eos, then we should make sure tokens and + # scores are the same across all beams + eos_mask = prefix_toks.eq(self.eos) + if eos_mask.any(): + # validate that the first beam matches the prefix + first_beam = tokens[eos_mask].view(-1, beam_size, tokens.size(-1))[ + :, 0, 1 : step + 1 + ] + eos_mask_batch_dim = eos_mask.view(-1, beam_size)[:, 0] + target_prefix = prefix_tokens[eos_mask_batch_dim][:, :step] + assert (first_beam == target_prefix).all() + + # copy tokens, scores and lprobs from the first beam to all beams + tokens = self.replicate_first_beam(tokens, eos_mask_batch_dim, beam_size) + scores = self.replicate_first_beam(scores, eos_mask_batch_dim, beam_size) + lprobs = self.replicate_first_beam(lprobs, eos_mask_batch_dim, beam_size) + return lprobs, tokens, scores + + def replicate_first_beam(self, tensor, mask, beam_size: int): + tensor = tensor.view(-1, beam_size, tensor.size(-1)) + tensor[mask] = tensor[mask][:, :1, :] + return tensor.view(-1, tensor.size(-1)) + + def finalize_hypos( + self, + step: int, + bbsz_idx, + eos_scores, + tokens, + scores, + finalized: List[List[Dict[str, Tensor]]], + finished: List[bool], + beam_size: int, + attn: Optional[Tensor], + src_lengths, + max_len: int, + ): + """Finalize hypothesis, store finalized information in `finalized`, and change `finished` accordingly. + A sentence is finalized when {beam_size} finished items have been collected for it. + + Returns number of sentences (not beam items) being finalized. + These will be removed from the batch and not processed further. + Args: + bbsz_idx (Tensor): + """ + assert bbsz_idx.numel() == eos_scores.numel() + + # clone relevant token and attention tensors. + # tokens is (batch * beam, max_len). So the index_select + # gets the newly EOS rows, then selects cols 1..{step + 2} + tokens_clone = tokens.index_select(0, bbsz_idx)[ + :, 1 : step + 2 + ] # skip the first index, which is EOS + + tokens_clone[:, step] = self.eos + attn_clone = ( + attn.index_select(0, bbsz_idx)[:, :, 1 : step + 2] + if attn is not None + else None + ) + + # compute scores per token position + pos_scores = scores.index_select(0, bbsz_idx)[:, : step + 1] + pos_scores[:, step] = eos_scores + # convert from cumulative to per-position scores + pos_scores[:, 1:] = pos_scores[:, 1:] - pos_scores[:, :-1] + + # normalize sentence-level scores + if self.normalize_scores: + eos_scores /= (step + 1) ** self.len_penalty + + # cum_unfin records which sentences in the batch are finished. + # It helps match indexing between (a) the original sentences + # in the batch and (b) the current, possibly-reduced set of + # sentences. + cum_unfin: List[int] = [] + prev = 0 + for f in finished: + if f: + prev += 1 + else: + cum_unfin.append(prev) + + # set() is not supported in script export + + # The keys here are of the form "{sent}_{unfin_idx}", where + # "unfin_idx" is the index in the current (possibly reduced) + # list of sentences, and "sent" is the index in the original, + # unreduced batch + sents_seen: Dict[str, Optional[Tensor]] = {} + + # For every finished beam item + for i in range(bbsz_idx.size()[0]): + idx = bbsz_idx[i] + score = eos_scores[i] + # sentence index in the current (possibly reduced) batch + unfin_idx = idx // beam_size + # sentence index in the original (unreduced) batch + sent = unfin_idx + cum_unfin[unfin_idx] + # print(f"{step} FINISHED {idx} {score} {sent}={unfin_idx} {cum_unfin}") + # Cannot create dict for key type '(int, int)' in torchscript. + # The workaround is to cast int to string + seen = str(sent.item()) + "_" + str(unfin_idx.item()) + if seen not in sents_seen: + sents_seen[seen] = None + + if self.match_source_len and step > src_lengths[unfin_idx]: + score = torch.tensor(-math.inf).to(score) + + # An input sentence (among those in a batch) is finished when + # beam_size hypotheses have been collected for it + if len(finalized[sent]) < beam_size: + if attn_clone is not None: + # remove padding tokens from attn scores + hypo_attn = attn_clone[i] + else: + hypo_attn = torch.empty(0) + + finalized[sent].append( + { + "tokens": tokens_clone[i], + "score": score, + "attention": hypo_attn, # src_len x tgt_len + "alignment": torch.empty(0), + "positional_scores": pos_scores[i], + } + ) + + newly_finished: List[int] = [] + + for seen in sents_seen.keys(): + # check termination conditions for this sentence + sent: int = int(float(seen.split("_")[0])) + unfin_idx: int = int(float(seen.split("_")[1])) + + if not finished[sent] and self.is_finished( + step, unfin_idx, max_len, len(finalized[sent]), beam_size + ): + finished[sent] = True + newly_finished.append(unfin_idx) + + return newly_finished + + def is_finished( + self, + step: int, + unfin_idx: int, + max_len: int, + finalized_sent_len: int, + beam_size: int, + ): + """ + Check whether decoding for a sentence is finished, which + occurs when the list of finalized sentences has reached the + beam size, or when we reach the maximum length. + """ + assert finalized_sent_len <= beam_size + if finalized_sent_len == beam_size or step == max_len: + return True + return False + + def calculate_banned_tokens( + self, + tokens, + step: int, + gen_ngrams: List[Dict[str, List[int]]], + no_repeat_ngram_size: int, + bbsz_idx: int, + ): + tokens_list: List[int] = tokens[ + bbsz_idx, step + 2 - no_repeat_ngram_size : step + 1 + ].tolist() + # before decoding the next token, prevent decoding of ngrams that have already appeared + ngram_index = ",".join([str(x) for x in tokens_list]) + return gen_ngrams[bbsz_idx].get(ngram_index, torch.jit.annotate(List[int], [])) + + def transpose_list(self, l: List[List[int]]): + # GeneratorExp aren't supported in TS so ignoring the lint + min_len = min([len(x) for x in l]) # noqa + l2 = [[row[i] for row in l] for i in range(min_len)] + return l2 + + def _no_repeat_ngram(self, tokens, lprobs, bsz: int, beam_size: int, step: int): + # for each beam and batch sentence, generate a list of previous ngrams + gen_ngrams: List[Dict[str, List[int]]] = [ + torch.jit.annotate(Dict[str, List[int]], {}) + for bbsz_idx in range(bsz * beam_size) + ] + cpu_tokens = tokens.cpu() + for bbsz_idx in range(bsz * beam_size): + gen_tokens: List[int] = cpu_tokens[bbsz_idx].tolist() + for ngram in self.transpose_list( + [gen_tokens[i:] for i in range(self.no_repeat_ngram_size)] + ): + key = ",".join([str(x) for x in ngram[:-1]]) + gen_ngrams[bbsz_idx][key] = gen_ngrams[bbsz_idx].get( + key, torch.jit.annotate(List[int], []) + ) + [ngram[-1]] + + if step + 2 - self.no_repeat_ngram_size >= 0: + # no banned tokens if we haven't generated no_repeat_ngram_size tokens yet + banned_tokens = [ + self.calculate_banned_tokens( + tokens, step, gen_ngrams, self.no_repeat_ngram_size, bbsz_idx + ) + for bbsz_idx in range(bsz * beam_size) + ] + else: + banned_tokens = [ + torch.jit.annotate(List[int], []) for bbsz_idx in range(bsz * beam_size) + ] + for bbsz_idx in range(bsz * beam_size): + lprobs[bbsz_idx][ + torch.tensor(banned_tokens[bbsz_idx]).long() + ] = torch.tensor(-math.inf).to(lprobs) + return lprobs + + +class EnsembleModel(nn.Module): + """A wrapper around an ensemble of models.""" + + def __init__(self, models): + super().__init__() + self.models_size = len(models) + # method '__len__' is not supported in ModuleList for torch script + self.single_model = models[0] + self.models = nn.ModuleList(models) + + self.has_incremental: bool = False + if all( + hasattr(m, "decoder") and isinstance(m.decoder, FairseqIncrementalDecoder) + for m in models + ): + self.has_incremental = True + + def forward(self): + pass + + def has_encoder(self): + return hasattr(self.single_model, "encoder") + + def has_incremental_states(self): + return self.has_incremental + + def max_decoder_positions(self): + return min([m.max_decoder_positions() for m in self.models]) + + @torch.jit.export + def forward_encoder(self, net_input: Dict[str, Tensor]): + if not self.has_encoder(): + return None + return [model.encoder.forward_torchscript(net_input) for model in self.models] + + @torch.jit.export + def forward_decoder( + self, + tokens, + encoder_outs: List[EncoderOut], + incremental_states: List[Dict[str, Dict[str, Optional[Tensor]]]], + temperature: float = 1.0, + ): + log_probs = [] + avg_attn: Optional[Tensor] = None + encoder_out: Optional[EncoderOut] = None + for i, model in enumerate(self.models): + if self.has_encoder(): + encoder_out = encoder_outs[i] + # decode each model + if self.has_incremental_states(): + decoder_out = model.decoder.forward( + tokens, + encoder_out=encoder_out, + incremental_state=incremental_states[i], + ) + else: + decoder_out = model.decoder.forward(tokens, encoder_out=encoder_out) + + attn: Optional[Tensor] = None + decoder_len = len(decoder_out) + if decoder_len > 1 and decoder_out[1] is not None: + if isinstance(decoder_out[1], Tensor): + attn = decoder_out[1] + else: + attn_holder = decoder_out[1]["attn"] + if isinstance(attn_holder, Tensor): + attn = attn_holder + elif attn_holder is not None: + attn = attn_holder[0] + if attn is not None: + attn = attn[:, -1, :] + + decoder_out_tuple = ( + decoder_out[0][:, -1:, :].div_(temperature), + None if decoder_len <= 1 else decoder_out[1], + ) + + probs = model.get_normalized_probs( + decoder_out_tuple, log_probs=True, sample=None + ) + probs = probs[:, -1, :] + if self.models_size == 1: + return probs, attn + + log_probs.append(probs) + if attn is not None: + if avg_attn is None: + avg_attn = attn + else: + avg_attn.add_(attn) + + avg_probs = torch.logsumexp(torch.stack(log_probs, dim=0), dim=0) - math.log( + self.models_size + ) + + if avg_attn is not None: + avg_attn.div_(self.models_size) + return avg_probs, avg_attn + + @torch.jit.export + def reorder_encoder_out(self, encoder_outs: Optional[List[EncoderOut]], new_order): + """ + Reorder encoder output according to *new_order*. + + Args: + encoder_out: output from the ``forward()`` method + new_order (LongTensor): desired order + + Returns: + *encoder_out* rearranged according to *new_order* + """ + new_outs: List[EncoderOut] = [] + if not self.has_encoder(): + return new_outs + for i, model in enumerate(self.models): + assert encoder_outs is not None + new_outs.append( + model.encoder.reorder_encoder_out(encoder_outs[i], new_order) + ) + return new_outs + + @torch.jit.export + def reorder_incremental_state( + self, + incremental_states: List[Dict[str, Dict[str, Optional[Tensor]]]], + new_order, + ): + if not self.has_incremental_states(): + return + for i, model in enumerate(self.models): + model.decoder.reorder_incremental_state_scripting( + incremental_states[i], new_order + ) + + +class SequenceGeneratorWithAlignment(SequenceGenerator): + def __init__(self, models, tgt_dict, left_pad_target=False, **kwargs): + """Generates translations of a given source sentence. + + Produces alignments following "Jointly Learning to Align and + Translate with Transformer Models" (Garg et al., EMNLP 2019). + + Args: + left_pad_target (bool, optional): Whether or not the + hypothesis should be left padded or not when they are + teacher forced for generating alignments. + """ + super().__init__(EnsembleModelWithAlignment(models), tgt_dict, **kwargs) + self.left_pad_target = left_pad_target + + @torch.no_grad() + def generate(self, models, sample, **kwargs): + finalized = super()._generate(sample, **kwargs) + + src_tokens = sample["net_input"]["src_tokens"] + bsz = src_tokens.shape[0] + beam_size = self.beam_size + ( + src_tokens, + src_lengths, + prev_output_tokens, + tgt_tokens, + ) = self._prepare_batch_for_alignment(sample, finalized) + if any(getattr(m, "full_context_alignment", False) for m in self.model.models): + attn = self.model.forward_align(src_tokens, src_lengths, prev_output_tokens) + else: + attn = [ + finalized[i // beam_size][i % beam_size]["attention"].transpose(1, 0) + for i in range(bsz * beam_size) + ] + + if src_tokens.device != "cpu": + src_tokens = src_tokens.to("cpu") + tgt_tokens = tgt_tokens.to("cpu") + attn = [i.to("cpu") for i in attn] + + # Process the attn matrix to extract hard alignments. + for i in range(bsz * beam_size): + alignment = utils.extract_hard_alignment( + attn[i], src_tokens[i], tgt_tokens[i], self.pad, self.eos + ) + finalized[i // beam_size][i % beam_size]["alignment"] = alignment + return finalized + + def _prepare_batch_for_alignment(self, sample, hypothesis): + src_tokens = sample["net_input"]["src_tokens"] + bsz = src_tokens.shape[0] + src_tokens = ( + src_tokens[:, None, :] + .expand(-1, self.beam_size, -1) + .contiguous() + .view(bsz * self.beam_size, -1) + ) + src_lengths = sample["net_input"]["src_lengths"] + src_lengths = ( + src_lengths[:, None] + .expand(-1, self.beam_size) + .contiguous() + .view(bsz * self.beam_size) + ) + prev_output_tokens = data_utils.collate_tokens( + [beam["tokens"] for example in hypothesis for beam in example], + self.pad, + self.eos, + self.left_pad_target, + move_eos_to_beginning=True, + ) + tgt_tokens = data_utils.collate_tokens( + [beam["tokens"] for example in hypothesis for beam in example], + self.pad, + self.eos, + self.left_pad_target, + move_eos_to_beginning=False, + ) + return src_tokens, src_lengths, prev_output_tokens, tgt_tokens + + +class EnsembleModelWithAlignment(EnsembleModel): + """A wrapper around an ensemble of models.""" + + def __init__(self, models): + super().__init__(models) + + def forward_align(self, src_tokens, src_lengths, prev_output_tokens): + avg_attn = None + for model in self.models: + decoder_out = model(src_tokens, src_lengths, prev_output_tokens) + attn = decoder_out[1]["attn"][0] + if avg_attn is None: + avg_attn = attn + else: + avg_attn.add_(attn) + if len(self.models) > 1: + avg_attn.div_(len(self.models)) + return avg_attn diff --git a/fairseq-tools/fairseq/fairseq/sequence_scorer.py b/fairseq-tools/fairseq/fairseq/sequence_scorer.py new file mode 100644 index 00000000..411d4df4 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/sequence_scorer.py @@ -0,0 +1,153 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys + +import torch +from fairseq import utils + + +class SequenceScorer(object): + """Scores the target for a given source sentence.""" + + def __init__( + self, + tgt_dict, + softmax_batch=None, + compute_alignment=False, + eos=None, + symbols_to_strip_from_output=None, + ): + self.pad = tgt_dict.pad() + self.eos = tgt_dict.eos() if eos is None else eos + self.softmax_batch = softmax_batch or sys.maxsize + assert self.softmax_batch > 0 + self.compute_alignment = compute_alignment + self.symbols_to_strip_from_output = ( + symbols_to_strip_from_output.union({self.eos}) + if symbols_to_strip_from_output is not None + else {self.eos} + ) + + @torch.no_grad() + def generate(self, models, sample, **kwargs): + """Score a batch of translations.""" + net_input = sample["net_input"] + + def batch_for_softmax(dec_out, target): + # assumes decoder_out[0] is the only thing needed (may not be correct for future models!) + first, rest = dec_out[0], dec_out[1:] + bsz, tsz, dim = first.shape + if bsz * tsz < self.softmax_batch: + yield dec_out, target, True + else: + flat = first.contiguous().view(1, -1, dim) + flat_tgt = target.contiguous().view(flat.shape[:-1]) + s = 0 + while s < flat.size(1): + e = s + self.softmax_batch + yield (flat[:, s:e],) + rest, flat_tgt[:, s:e], False + s = e + + def gather_target_probs(probs, target): + probs = probs.gather( + dim=2, + index=target.unsqueeze(-1), + ) + return probs + + orig_target = sample["target"] + + # compute scores for each model in the ensemble + avg_probs = None + avg_attn = None + for model in models: + model.eval() + decoder_out = model(**net_input) + attn = decoder_out[1] if len(decoder_out) > 1 else None + if type(attn) is dict: + attn = attn.get("attn", None) + + batched = batch_for_softmax(decoder_out, orig_target) + probs, idx = None, 0 + for bd, tgt, is_single in batched: + sample["target"] = tgt + curr_prob = model.get_normalized_probs( + bd, log_probs=len(models) == 1, sample=sample + ).data + if is_single: + probs = gather_target_probs(curr_prob, orig_target) + else: + if probs is None: + probs = curr_prob.new(orig_target.numel()) + step = curr_prob.size(0) * curr_prob.size(1) + end = step + idx + tgt_probs = gather_target_probs( + curr_prob.view(tgt.shape + (curr_prob.size(-1),)), tgt + ) + probs[idx:end] = tgt_probs.view(-1) + idx = end + sample["target"] = orig_target + + probs = probs.view(sample["target"].shape) + + if avg_probs is None: + avg_probs = probs + else: + avg_probs.add_(probs) + if attn is not None: + if torch.is_tensor(attn): + attn = attn.data + else: + attn = attn[0] + if avg_attn is None: + avg_attn = attn + else: + avg_attn.add_(attn) + if len(models) > 1: + avg_probs.div_(len(models)) + avg_probs.log_() + if avg_attn is not None: + avg_attn.div_(len(models)) + + bsz = avg_probs.size(0) + hypos = [] + start_idxs = sample["start_indices"] if "start_indices" in sample else [0] * bsz + for i in range(bsz): + # remove padding from ref + ref = ( + utils.strip_pad(sample["target"][i, start_idxs[i] :], self.pad) + if sample["target"] is not None + else None + ) + tgt_len = ref.numel() + avg_probs_i = avg_probs[i][start_idxs[i] : start_idxs[i] + tgt_len] + score_i = avg_probs_i.sum() / tgt_len + if avg_attn is not None: + avg_attn_i = avg_attn[i] + if self.compute_alignment: + alignment = utils.extract_hard_alignment( + avg_attn_i, + sample["net_input"]["src_tokens"][i], + sample["target"][i], + self.pad, + self.eos, + ) + else: + alignment = None + else: + avg_attn_i = alignment = None + hypos.append( + [ + { + "tokens": ref, + "score": score_i, + "attention": avg_attn_i, + "alignment": alignment, + "positional_scores": avg_probs_i, + } + ] + ) + return hypos diff --git a/fairseq-tools/fairseq/fairseq/tasks/__init__.py b/fairseq-tools/fairseq/fairseq/tasks/__init__.py new file mode 100644 index 00000000..e0abce25 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/__init__.py @@ -0,0 +1,106 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +"""isort:skip_file""" + +import argparse +import importlib +import os +from argparse import Namespace +from typing import Union + +from fairseq.dataclass import FairseqDataclass +from omegaconf import DictConfig + +from .fairseq_task import FairseqTask, LegacyFairseqTask # noqa + + +# register dataclass +TASK_DATACLASS_REGISTRY = {} +TASK_REGISTRY = {} +TASK_CLASS_NAMES = set() + + +def setup_task(task_cfg: Union[DictConfig, Namespace], **kwargs): + if isinstance(task_cfg, DictConfig): + return TASK_REGISTRY[task_cfg._name].setup_task(task_cfg, **kwargs) + return TASK_REGISTRY[task_cfg.task].setup_task(task_cfg, **kwargs) + + +def register_task(name, dataclass=None): + """ + New tasks can be added to fairseq with the + :func:`~fairseq.tasks.register_task` function decorator. + + For example:: + + @register_task('classification') + class ClassificationTask(FairseqTask): + (...) + + .. note:: + + All Tasks must implement the :class:`~fairseq.tasks.FairseqTask` + interface. + + Args: + name (str): the name of the task + """ + + def register_task_cls(cls): + if name in TASK_REGISTRY: + raise ValueError("Cannot register duplicate task ({})".format(name)) + if not issubclass(cls, FairseqTask): + raise ValueError( + "Task ({}: {}) must extend FairseqTask".format(name, cls.__name__) + ) + if cls.__name__ in TASK_CLASS_NAMES: + raise ValueError( + "Cannot register task with duplicate class name ({})".format( + cls.__name__ + ) + ) + TASK_REGISTRY[name] = cls + TASK_CLASS_NAMES.add(cls.__name__) + + if dataclass is not None and not issubclass(dataclass, FairseqDataclass): + raise ValueError( + "Dataclass {} must extend FairseqDataclass".format(dataclass) + ) + + cls.__dataclass = dataclass + TASK_DATACLASS_REGISTRY[name] = dataclass + + return cls + + return register_task_cls + + +def get_task(name): + return TASK_REGISTRY[name] + + +# automatically import any Python files in the tasks/ directory +tasks_dir = os.path.dirname(__file__) +for file in os.listdir(tasks_dir): + path = os.path.join(tasks_dir, file) + if ( + not file.startswith("_") + and not file.startswith(".") + and (file.endswith(".py") or os.path.isdir(path)) + ): + task_name = file[: file.find(".py")] if file.endswith(".py") else file + module = importlib.import_module("fairseq.tasks." + task_name) + + # expose `task_parser` for sphinx + if task_name in TASK_REGISTRY: + parser = argparse.ArgumentParser(add_help=False) + group_task = parser.add_argument_group("Task name") + # fmt: off + group_task.add_argument('--task', metavar=task_name, + help='Enable this task with: ``--task=' + task_name + '``') + # fmt: on + group_args = parser.add_argument_group("Additional command-line arguments") + TASK_REGISTRY[task_name].add_args(group_args) + globals()[task_name + "_parser"] = parser diff --git a/fairseq-tools/fairseq/fairseq/tasks/audio_pretraining.py b/fairseq-tools/fairseq/fairseq/tasks/audio_pretraining.py new file mode 100644 index 00000000..ff2342af --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/audio_pretraining.py @@ -0,0 +1,146 @@ +# Copyright (c) 2017-present, Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the license found in the LICENSE file in +# the root directory of this source tree. An additional grant of patent rights +# can be found in the PATENTS file in the same directory. + +import os +import sys + +from fairseq.data import AddTargetDataset, Dictionary, FileAudioDataset + +from . import LegacyFairseqTask, register_task + + +class LabelEncoder(object): + def __init__(self, dictionary): + self.dictionary = dictionary + + def __call__(self, label): + return self.dictionary.encode_line( + label, append_eos=False, add_if_not_exist=False + ) + + +@register_task("audio_pretraining") +class AudioPretrainingTask(LegacyFairseqTask): + """""" + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("data", help="path to data directory") + parser.add_argument( + "--sample-rate", + default=16000, + type=int, + help="target sample rate. audio files will be up/down sampled to this rate", + ) + parser.add_argument( + "--normalize", + action="store_true", + help="if set, normalizes input to have 0 mean and unit variance", + ) + parser.add_argument( + "--max-sample-size", + default=None, + type=int, + help="max sample size to crop to for batching. default = min sample length", + ) + parser.add_argument( + "--min-sample-size", + default=None, + type=int, + help="min sample size to crop to for batching. default = same as --max-sample-size", + ) + + parser.add_argument( + "--enable-padding", + action="store_true", + help="pad shorter samples instead of cropping", + ) + + parser.add_argument( + "--labels", + type=str, + default=None, + help="extension of the label file to load, if any", + ) + + def __init__(self, args, source_dictionary=None): + super().__init__(args) + self._target_dictionary = None + self._source_dictionary = source_dictionary + self.is_ctc = args.criterion == "ctc" + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task (e.g., load dictionaries). + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + return cls(args) + + def load_dataset(self, split, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + manifest = os.path.join(self.args.data, "{}.tsv".format(split)) + self.datasets[split] = FileAudioDataset( + manifest, + sample_rate=self.args.sample_rate, + max_sample_size=self.args.max_sample_size, + min_sample_size=self.args.max_sample_size, + min_length=self.args.min_sample_size, + pad=self.args.labels is not None or self.args.enable_padding, + normalize=self.args.normalize, + ) + + if self.args.labels: + dict_path = os.path.join(self.args.data, f"dict.{self.args.labels}.txt") + self._target_dictionary = Dictionary.load(dict_path) + label_path = os.path.join(self.args.data, f"{split}.{self.args.labels}") + labels = [] + with open(label_path, "r") as f: + for line in f: + labels.append(line) + + process_label = LabelEncoder(self.target_dictionary) + + self.datasets[split] = AddTargetDataset( + self.datasets[split], + labels, + pad=self.target_dictionary.pad(), + eos=self.target_dictionary.eos(), + batch_targets=True, + process_label=process_label, + add_to_input=not self.is_ctc, + ) + + @property + def source_dictionary(self): + return self._source_dictionary + + @property + def target_dictionary(self): + """Return the :class:`~fairseq.data.Dictionary` for the language + model.""" + return self._target_dictionary + + def max_positions(self): + """Maximum input length supported by the encoder.""" + return (sys.maxsize, sys.maxsize) + + def filter_indices_by_size( + self, + indices, + dataset, + max_positions=None, + ignore_invalid_inputs=False, + ): + # we do not need to filter by size in this task as dataloaders take care of this + return indices diff --git a/fairseq-tools/fairseq/fairseq/tasks/cross_lingual_lm.py b/fairseq-tools/fairseq/fairseq/tasks/cross_lingual_lm.py new file mode 100644 index 00000000..8f8fe7e2 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/cross_lingual_lm.py @@ -0,0 +1,191 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import itertools +import logging +import os +from collections import OrderedDict + +import numpy as np +from fairseq import tokenizer, utils +from fairseq.data import ConcatDataset, Dictionary, TokenBlockDataset, data_utils +from fairseq.data.legacy.masked_lm_dataset import MaskedLMDataset +from fairseq.data.legacy.masked_lm_dictionary import MaskedLMDictionary +from fairseq.data.multi_corpus_sampled_dataset import MultiCorpusSampledDataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("cross_lingual_lm") +class CrossLingualLMTask(LegacyFairseqTask): + """ + Task for training cross-lingual language models. + + For more details look at: https://arxiv.org/pdf/1901.07291.pdf + + Args: + dictionary (Dictionary): the dictionary for the input of the task + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", + help="colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner", + ) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments" " per sample", + ) + parser.add_argument( + "--monolingual-langs", + default="en", + type=str, + help="comma separated list of languages for which we" + " want to train XLM on", + ) + parser.add_argument( + "--shuffle", + action="store_true", + help="shuffle each monolingual dataset while" " training", + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + self.distributed_world_size = args.distributed_world_size + self.langs2id = self._lang_to_id(args.monolingual_langs) + + def _lang_to_id(self, languages: str): + """ + Build a map from languages to ids. These ids are used as segment labels + for cross-lingual LM training. + """ + lang2id = {} + langs = [l.strip() for l in languages.split(",")] + for id, lang in enumerate(langs): + lang2id[lang] = id + return lang2id + + @classmethod + def load_dictionary(cls, filename): + return MaskedLMDictionary.load(filename) + + @classmethod + def build_dictionary( + cls, filenames, workers=1, threshold=-1, nwords=-1, padding_factor=8 + ): + d = MaskedLMDictionary() + for filename in filenames: + Dictionary.add_file_to_dictionary( + filename, d, tokenizer.tokenize_line, workers + ) + d.finalize(threshold=threshold, nwords=nwords, padding_factor=padding_factor) + return d + + @property + def target_dictionary(self): + return self.dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task.""" + dictionary = MaskedLMDictionary.load(os.path.join(args.data, "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + return cls(args, dictionary) + + def _load_single_lang_dataset(self, split, epoch): + loaded_datasets = [] + + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + for k in itertools.count(): + split_k = split + (str(k) if k > 0 else "") + path = os.path.join(data_path, split_k) + + ds = data_utils.load_indexed_dataset( + path, self.dictionary, self.args.dataset_impl + ) + if ds is None: + if k > 0: + break + else: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, data_path) + ) + + # Since we append each block with the classification_token, + # we need to effectively create blocks of length + # tokens_per_sample-1 + loaded_datasets.append( + TokenBlockDataset( + ds, + ds.sizes, + self.args.tokens_per_sample - 1, + pad=self.dictionary.pad(), + eos=self.dictionary.eos(), + ) + ) + + logger.info( + "{} {} {} examples".format(data_path, split_k, len(loaded_datasets[-1])) + ) + + if len(loaded_datasets) == 1: + dataset = loaded_datasets[0] + sizes = dataset.sizes + else: + dataset = ConcatDataset(loaded_datasets) + sizes = np.concatenate([ds.sizes for ds in loaded_datasets]) + + return dataset, sizes + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + dataset_map = OrderedDict() + + for lang in self.langs2id.keys(): + # Datasets are expected to be in "split.lang" format (Eg: train.en) + language_split = "{}.{}".format(split, lang) + + block_dataset, sizes = self._load_single_lang_dataset( + split=language_split, epoch=epoch + ) + + dataset_map[lang] = MaskedLMDataset( + dataset=block_dataset, + sizes=sizes, + vocab=self.dictionary, + pad_idx=self.dictionary.pad(), + mask_idx=self.dictionary.mask(), + classif_token_idx=self.dictionary.eos(), + sep_token_idx=self.dictionary.eos(), + shuffle=getattr(self.args, "shuffle", False), + has_pairs=False, + segment_id=self.langs2id[lang], + seed=self.seed, + ) + + self.datasets[split] = MultiCorpusSampledDataset(dataset_map) + logger.info( + "{} {} {} examples".format( + utils.split_paths(self.args.data)[epoch - 1], + split, + len(self.datasets[split]), + ) + ) diff --git a/fairseq-tools/fairseq/fairseq/tasks/denoising.py b/fairseq-tools/fairseq/fairseq/tasks/denoising.py new file mode 100644 index 00000000..3e88bf0e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/denoising.py @@ -0,0 +1,210 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os + +from fairseq import utils +from fairseq.data import ( + AppendTokenDataset, + DenoisingDataset, + Dictionary, + PrependTokenDataset, + StripTokenDataset, + TokenBlockDataset, + data_utils, +) +from fairseq.data.encoders.utils import get_whole_word_mask +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("denoising") +class DenoisingTask(LegacyFairseqTask): + """ + Denoising task for applying sequence to sequence denoising. (ie. BART) + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("data", help="path to data directory") + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments" + " per sample for dataset", + ) + parser.add_argument( + "--sample-break-mode", + default="complete_doc", + type=str, + help="mode for breaking sentence", + ) + parser.add_argument( + "--mask", + default=0.0, + type=float, + help="fraction of words/subwords that will be masked", + ) + parser.add_argument( + "--mask-random", + default=0.0, + type=float, + help="instead of using [MASK], use random token this often", + ) + parser.add_argument( + "--insert", + default=0.0, + type=float, + help="insert this percentage of additional random tokens", + ) + parser.add_argument( + "--permute", + default=0.0, + type=float, + help="take this proportion of subwords and permute them", + ) + parser.add_argument( + "--rotate", + default=0.5, + type=float, + help="rotate this proportion of inputs", + ) + parser.add_argument( + "--poisson-lambda", + default=3.0, + type=float, + help="randomly shuffle sentences for this proportion of inputs", + ) + parser.add_argument( + "--permute-sentences", + default=0.0, + type=float, + help="shuffle this proportion of sentences in all inputs", + ) + parser.add_argument( + "--mask-length", + default="subword", + type=str, + choices=["subword", "word", "span-poisson"], + help="mask length to choose", + ) + parser.add_argument( + "--replace-length", + default=-1, + type=int, + help="when masking N tokens, replace with 0, 1, or N tokens (use -1 for N)", + ) + parser.add_argument( + "--max-source-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the source sequence", + ) + parser.add_argument( + "--max-target-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the target sequence", + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + # add mask token + self.mask_idx = self.dictionary.add_symbol("<mask>") + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task.""" + dictionary = Dictionary.load(os.path.join(args.data, "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + if not hasattr(args, "shuffle_instance"): + args.shuffle_instance = False + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + split_path = os.path.join(data_path, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + self.dictionary, + self.args.dataset_impl, + combine=combine, + ) + if dataset is None: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, split_path) + ) + + dataset = StripTokenDataset(dataset, self.dictionary.eos()) + + # create continuous blocks of tokens + dataset = TokenBlockDataset( + dataset, + dataset.sizes, + self.args.tokens_per_sample - 2, # one less for <s> and one for </s> + pad=self.dictionary.pad(), + eos=self.dictionary.eos(), + break_mode=self.args.sample_break_mode, + document_sep_len=0, + ) + + # prepend beginning-of-sentence token (<s>, equiv. to [CLS] in BERT) + dataset = PrependTokenDataset(dataset, self.source_dictionary.bos()) + dataset = AppendTokenDataset(dataset, self.source_dictionary.eos()) + + mask_whole_words = ( + get_whole_word_mask(self.args, self.source_dictionary) + if self.args.mask_length != "subword" + else None + ) + + self.datasets[split] = DenoisingDataset( + dataset, + dataset.sizes, + self.dictionary, + self.mask_idx, + mask_whole_words, + shuffle=self.args.shuffle_instance, + seed=self.seed, + args=self.args, + ) + logger.info( + "Split: {0}, Loaded {1} samples of denoising_dataset".format( + split, + len(self.datasets[split]), + ) + ) + + def max_positions(self): + """Return the max sentence length allowed by the task.""" + return (self.args.max_source_positions, self.args.max_target_positions) + + @property + def source_dictionary(self): + """Return the source :class:`~fairseq.data.Dictionary`.""" + return self.dictionary + + @property + def target_dictionary(self): + """Return the target :class:`~fairseq.data.Dictionary`.""" + return self.dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/fairseq_task.py b/fairseq-tools/fairseq/fairseq/tasks/fairseq_task.py new file mode 100644 index 00000000..0a96aeb1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/fairseq_task.py @@ -0,0 +1,566 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +import warnings +from argparse import Namespace + +import torch +from fairseq import metrics, search, tokenizer, utils +from fairseq.data import Dictionary, FairseqDataset, data_utils, encoders, iterators +from fairseq.dataclass.utils import gen_parser_from_dataclass + + +logger = logging.getLogger(__name__) + + +class FairseqTask(object): + """ + Tasks store dictionaries and provide helpers for loading/iterating over + Datasets, initializing the Model/Criterion and calculating the loss. + """ + + @classmethod + def add_args(cls, parser): + """Add task-specific arguments to the parser.""" + dc = getattr(cls, "__dataclass", None) + if dc is not None: + gen_parser_from_dataclass(parser, dc()) + + @staticmethod + def logging_outputs_can_be_summed(criterion) -> bool: + """ + Whether the logging outputs returned by `train_step` and `valid_step` can + be summed across workers prior to calling `aggregate_logging_outputs`. + Setting this to True will improves distributed training speed. + """ + return criterion.logging_outputs_can_be_summed() + + def __init__(self, args): + self.args = args + self.datasets = {} + self.dataset_to_epoch_iter = {} + + @classmethod + def load_dictionary(cls, filename): + """Load the dictionary from the filename + + Args: + filename (str): the filename + """ + return Dictionary.load(filename) + + @classmethod + def build_dictionary( + cls, filenames, workers=1, threshold=-1, nwords=-1, padding_factor=8 + ): + """Build the dictionary + + Args: + filenames (list): list of filenames + workers (int): number of concurrent workers + threshold (int): defines the minimum word count + nwords (int): defines the total number of words in the final dictionary, + including special symbols + padding_factor (int): can be used to pad the dictionary size to be a + multiple of 8, which is important on some hardware (e.g., Nvidia + Tensor Cores). + """ + d = Dictionary() + for filename in filenames: + Dictionary.add_file_to_dictionary( + filename, d, tokenizer.tokenize_line, workers + ) + d.finalize(threshold=threshold, nwords=nwords, padding_factor=padding_factor) + return d + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task (e.g., load dictionaries). + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + return cls(args, **kwargs) + + def has_sharded_data(self, split): + return os.pathsep in getattr(self.args, "data", "") + + def load_dataset(self, split, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + raise NotImplementedError + + def dataset(self, split): + """ + Return a loaded dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + + Returns: + a :class:`~fairseq.data.FairseqDataset` corresponding to *split* + """ + from fairseq.data import FairseqDataset + + if split not in self.datasets: + raise KeyError("Dataset not loaded: " + split) + if not isinstance(self.datasets[split], FairseqDataset): + raise TypeError("Datasets are expected to be of type FairseqDataset") + return self.datasets[split] + + def filter_indices_by_size( + self, indices, dataset, max_positions=None, ignore_invalid_inputs=False + ): + """ + Filter examples that are too large + + Args: + indices (np.array): original array of sample indices + dataset (~fairseq.data.FairseqDataset): dataset to batch + max_positions (optional): max sentence length supported by the + model (default: None). + ignore_invalid_inputs (bool, optional): don't raise Exception for + sentences that are too long (default: False). + Returns: + np.array: array of filtered sample indices + """ + indices, ignored = dataset.filter_indices_by_size(indices, max_positions) + if len(ignored) > 0: + if not ignore_invalid_inputs: + raise Exception( + ( + "Size of sample #{} is invalid (={}) since max_positions={}, " + "skip this example with --skip-invalid-size-inputs-valid-test" + ).format(ignored[0], dataset.size(ignored[0]), max_positions) + ) + logger.warning( + ( + "{} samples have invalid sizes and will be skipped, " + "max_positions={}, first few sample ids={}" + ).format(len(ignored), max_positions, ignored[:10]) + ) + return indices + + def can_reuse_epoch_itr(self, dataset): + # We can reuse the epoch iterator across epochs as long as the dataset + # hasn't disabled it. We default to ``False`` here, although in practice + # this will be ``True`` for most datasets that inherit from + # ``FairseqDataset`` due to the base implementation there. + return getattr(dataset, "can_reuse_epoch_itr_across_epochs", False) + + def get_batch_iterator( + self, + dataset, + max_tokens=None, + max_sentences=None, + max_positions=None, + ignore_invalid_inputs=False, + required_batch_size_multiple=1, + seed=1, + num_shards=1, + shard_id=0, + num_workers=0, + epoch=1, + data_buffer_size=0, + disable_iterator_cache=False, + ): + """ + Get an iterator that yields batches of data from the given dataset. + + Args: + dataset (~fairseq.data.FairseqDataset): dataset to batch + max_tokens (int, optional): max number of tokens in each batch + (default: None). + max_sentences (int, optional): max number of sentences in each + batch (default: None). + max_positions (optional): max sentence length supported by the + model (default: None). + ignore_invalid_inputs (bool, optional): don't raise Exception for + sentences that are too long (default: False). + required_batch_size_multiple (int, optional): require batch size to + be a multiple of N (default: 1). + seed (int, optional): seed for random number generator for + reproducibility (default: 1). + num_shards (int, optional): shard the data iterator into N + shards (default: 1). + shard_id (int, optional): which shard of the data iterator to + return (default: 0). + num_workers (int, optional): how many subprocesses to use for data + loading. 0 means the data will be loaded in the main process + (default: 0). + epoch (int, optional): the epoch to start the iterator from + (default: 1). + data_buffer_size (int, optional): number of batches to + preload (default: 0). + disable_iterator_cache (bool, optional): don't cache the + EpochBatchIterator (ignores `FairseqTask::can_reuse_epoch_itr`) + (default: False). + Returns: + ~fairseq.iterators.EpochBatchIterator: a batched iterator over the + given dataset split + """ + can_reuse_epoch_itr = not disable_iterator_cache and self.can_reuse_epoch_itr( + dataset + ) + if can_reuse_epoch_itr and dataset in self.dataset_to_epoch_iter: + logger.debug("reusing EpochBatchIterator for epoch {}".format(epoch)) + return self.dataset_to_epoch_iter[dataset] + + assert isinstance(dataset, FairseqDataset) + + # initialize the dataset with the correct starting epoch + dataset.set_epoch(epoch) + + # get indices ordered by example size + with data_utils.numpy_seed(seed): + indices = dataset.ordered_indices() + + # filter examples that are too large + if max_positions is not None: + indices = self.filter_indices_by_size( + indices, dataset, max_positions, ignore_invalid_inputs + ) + + # create mini-batches with given size constraints + batch_sampler = dataset.batch_by_size( + indices, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + ) + + # return a reusable, sharded iterator + epoch_iter = iterators.EpochBatchIterator( + dataset=dataset, + collate_fn=dataset.collater, + batch_sampler=batch_sampler, + seed=seed, + num_shards=num_shards, + shard_id=shard_id, + num_workers=num_workers, + epoch=epoch, + buffer_size=data_buffer_size, + ) + + if can_reuse_epoch_itr: + self.dataset_to_epoch_iter[dataset] = epoch_iter + + return epoch_iter + + def build_model(self, args): + """ + Build the :class:`~fairseq.models.BaseFairseqModel` instance for this + task. + + Args: + args (argparse.Namespace): parsed command-line arguments + + Returns: + a :class:`~fairseq.models.BaseFairseqModel` instance + """ + from fairseq import models, quantization_utils + + model = models.build_model(args, self) + if getattr(args, "tpu", False): + model.prepare_for_tpu_() + model = quantization_utils.quantize_model_scalar(model, args) + return model + + def build_criterion(self, args): + """ + Build the :class:`~fairseq.criterions.FairseqCriterion` instance for + this task. + + Args: + args (argparse.Namespace): parsed command-line arguments + + Returns: + a :class:`~fairseq.criterions.FairseqCriterion` instance + """ + from fairseq import criterions + + return criterions.build_criterion(args, self) + + def build_generator( + self, models, args, seq_gen_cls=None, extra_gen_cls_kwargs=None + ): + if getattr(args, "score_reference", False): + from fairseq.sequence_scorer import SequenceScorer + + return SequenceScorer( + self.target_dictionary, + compute_alignment=getattr(args, "print_alignment", False), + ) + + from fairseq.sequence_generator import ( + SequenceGenerator, + SequenceGeneratorWithAlignment, + ) + + # Choose search strategy. Defaults to Beam Search. + sampling = getattr(args, "sampling", False) + sampling_topk = getattr(args, "sampling_topk", -1) + sampling_topp = getattr(args, "sampling_topp", -1.0) + diverse_beam_groups = getattr(args, "diverse_beam_groups", -1) + diverse_beam_strength = getattr(args, "diverse_beam_strength", 0.5) + match_source_len = getattr(args, "match_source_len", False) + diversity_rate = getattr(args, "diversity_rate", -1) + constrained = getattr(args, "constraints", False) + prefix_allowed_tokens_fn = getattr(args, "prefix_allowed_tokens_fn", None) + if ( + sum( + int(cond) + for cond in [ + sampling, + diverse_beam_groups > 0, + match_source_len, + diversity_rate > 0, + ] + ) + > 1 + ): + raise ValueError("Provided Search parameters are mutually exclusive.") + assert sampling_topk < 0 or sampling, "--sampling-topk requires --sampling" + assert sampling_topp < 0 or sampling, "--sampling-topp requires --sampling" + + if sampling: + search_strategy = search.Sampling( + self.target_dictionary, sampling_topk, sampling_topp + ) + elif diverse_beam_groups > 0: + search_strategy = search.DiverseBeamSearch( + self.target_dictionary, diverse_beam_groups, diverse_beam_strength + ) + elif match_source_len: + # this is useful for tagging applications where the output + # length should match the input length, so we hardcode the + # length constraints for simplicity + search_strategy = search.LengthConstrainedBeamSearch( + self.target_dictionary, + min_len_a=1, + min_len_b=0, + max_len_a=1, + max_len_b=0, + ) + elif diversity_rate > -1: + search_strategy = search.DiverseSiblingsSearch( + self.target_dictionary, diversity_rate + ) + elif constrained: + search_strategy = search.LexicallyConstrainedBeamSearch( + self.target_dictionary, args.constraints + ) + elif prefix_allowed_tokens_fn: + search_strategy = search.PrefixConstrainedBeamSearch( + self.target_dictionary, prefix_allowed_tokens_fn + ) + else: + search_strategy = search.BeamSearch(self.target_dictionary) + + if seq_gen_cls is None: + if getattr(args, "print_alignment", False): + seq_gen_cls = SequenceGeneratorWithAlignment + else: + seq_gen_cls = SequenceGenerator + extra_gen_cls_kwargs = extra_gen_cls_kwargs or {} + return seq_gen_cls( + models, + self.target_dictionary, + beam_size=getattr(args, "beam", 5), + max_len_a=getattr(args, "max_len_a", 0), + max_len_b=getattr(args, "max_len_b", 200), + min_len=getattr(args, "min_len", 1), + normalize_scores=(not getattr(args, "unnormalized", False)), + len_penalty=getattr(args, "lenpen", 1), + unk_penalty=getattr(args, "unkpen", 0), + temperature=getattr(args, "temperature", 1.0), + match_source_len=getattr(args, "match_source_len", False), + no_repeat_ngram_size=getattr(args, "no_repeat_ngram_size", 0), + search_strategy=search_strategy, + **extra_gen_cls_kwargs, + ) + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + """ + Do forward and backward, and return the loss as computed by *criterion* + for the given *model* and *sample*. + + Args: + sample (dict): the mini-batch. The format is defined by the + :class:`~fairseq.data.FairseqDataset`. + model (~fairseq.models.BaseFairseqModel): the model + criterion (~fairseq.criterions.FairseqCriterion): the criterion + optimizer (~fairseq.optim.FairseqOptimizer): the optimizer + update_num (int): the current update + ignore_grad (bool): multiply loss by 0 if this is set to True + + Returns: + tuple: + - the loss + - the sample size, which is used as the denominator for the + gradient + - logging outputs to display while training + """ + model.train() + model.set_num_updates(update_num) + with torch.autograd.profiler.record_function("forward"): + loss, sample_size, logging_output = criterion(model, sample) + if ignore_grad: + loss *= 0 + with torch.autograd.profiler.record_function("backward"): + optimizer.backward(loss) + return loss, sample_size, logging_output + + def valid_step(self, sample, model, criterion): + model.eval() + with torch.no_grad(): + loss, sample_size, logging_output = criterion(model, sample) + return loss, sample_size, logging_output + + def inference_step( + self, generator, models, sample, prefix_tokens=None, constraints=None + ): + with torch.no_grad(): + return generator.generate( + models, sample, prefix_tokens=prefix_tokens, constraints=constraints + ) + + def begin_epoch(self, epoch, model): + """Hook function called before the start of each epoch.""" + pass + + def begin_valid_epoch(self, epoch, model): + """Hook function called before the start of each validation epoch.""" + pass + + def aggregate_logging_outputs(self, logging_outputs, criterion): + """[deprecated] Aggregate logging outputs from data parallel training.""" + utils.deprecation_warning( + "The aggregate_logging_outputs API is deprecated. " + "Please use the reduce_metrics API instead." + ) + with metrics.aggregate() as agg: + self.reduce_metrics(logging_outputs, criterion) + return agg.get_smoothed_values() + + def reduce_metrics(self, logging_outputs, criterion): + """Aggregate logging outputs from data parallel training.""" + # backward compatibility for tasks that override aggregate_logging_outputs + base_func = FairseqTask.aggregate_logging_outputs + self_func = getattr(self, "aggregate_logging_outputs").__func__ + if self_func is not base_func: + utils.deprecation_warning( + "Tasks should implement the reduce_metrics API. " + "Falling back to deprecated aggregate_logging_outputs API." + ) + agg_logging_outputs = self.aggregate_logging_outputs( + logging_outputs, criterion + ) + for k, v in agg_logging_outputs.items(): + metrics.log_scalar(k, v) + return + + if not any("ntokens" in log for log in logging_outputs): + warnings.warn( + "ntokens not found in Criterion logging outputs, cannot log wpb or wps" + ) + else: + ntokens = sum(log.get("ntokens", 0) for log in logging_outputs) + metrics.log_scalar("wpb", ntokens, priority=180, round=1) + metrics.log_speed("wps", ntokens, priority=90, round=1) + + if not any("nsentences" in log for log in logging_outputs): + warnings.warn( + "nsentences not found in Criterion logging outputs, cannot log bsz" + ) + else: + nsentences = sum(log.get("nsentences", 0) for log in logging_outputs) + metrics.log_scalar("bsz", nsentences, priority=190, round=1) + + criterion.__class__.reduce_metrics(logging_outputs) + + def max_positions(self): + """Return the max input length allowed by the task.""" + return None + + @property + def source_dictionary(self): + """Return the source :class:`~fairseq.data.Dictionary` (if applicable + for this task).""" + raise NotImplementedError + + @property + def target_dictionary(self): + """Return the target :class:`~fairseq.data.Dictionary` (if applicable + for this task).""" + raise NotImplementedError + + def build_tokenizer(self, args): + """Build the pre-tokenizer for this task.""" + return encoders.build_tokenizer(args) + + def build_bpe(self, args): + """Build the tokenizer for this task.""" + return encoders.build_bpe(args) + + +class LegacyFairseqTask(FairseqTask): + def __init__(self, args: Namespace): + self.args = args + self.datasets = {} + self.dataset_to_epoch_iter = {} + + @classmethod + def setup_task(cls, args: Namespace, **kwargs): + """Setup the task (e.g., load dictionaries). + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + return cls(args, **kwargs) + + def has_sharded_data(self, split): + return os.pathsep in getattr(self.args, "data", "") + + def build_model(self, args: Namespace): + """ + Build the :class:`~fairseq.models.BaseFairseqModel` instance for this + task. + + Args: + args (argparse.Namespace): parsed command-line arguments + + Returns: + a :class:`~fairseq.models.BaseFairseqModel` instance + """ + from fairseq import models, quantization_utils + + model = models.build_model(args, self) + if getattr(args, "tpu", False): + model.prepare_for_tpu_() + model = quantization_utils.quantize_model_scalar(model, args) + return model + + def build_criterion(self, args: Namespace): + """ + Build the :class:`~fairseq.criterions.FairseqCriterion` instance for + this task. + + Args: + args (argparse.Namespace): parsed command-line arguments + + Returns: + a :class:`~fairseq.criterions.FairseqCriterion` instance + """ + from fairseq import criterions + + return criterions.build_criterion(args, self) diff --git a/fairseq-tools/fairseq/fairseq/tasks/language_modeling.py b/fairseq-tools/fairseq/fairseq/tasks/language_modeling.py new file mode 100644 index 00000000..8792c648 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/language_modeling.py @@ -0,0 +1,327 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +from dataclasses import dataclass, field +from typing import Optional + +import numpy as np +import torch +from fairseq import utils +from fairseq.data import ( + AppendTokenDataset, + Dictionary, + IdDataset, + MonolingualDataset, + NestedDictionaryDataset, + NumelDataset, + PadDataset, + PrependTokenDataset, + StripTokenDataset, + TokenBlockDataset, + TruncatedDictionary, + data_utils, +) +from fairseq.data.indexed_dataset import get_available_dataset_impl +from fairseq.data.shorten_dataset import maybe_shorten_dataset +from fairseq.dataclass import ChoiceEnum, FairseqDataclass +from fairseq.tasks import FairseqTask, register_task +from omegaconf import II + + +SAMPLE_BREAK_MODE_CHOICES = ChoiceEnum(["none", "complete", "complete_doc", "eos"]) +SHORTEN_METHOD_CHOICES = ChoiceEnum(["none", "truncate", "random_crop"]) +logger = logging.getLogger(__name__) + + +@dataclass +class LanguageModelingConfig(FairseqDataclass): + # TODO common var add to parent + data: Optional[str] = field( + default=None, metadata={"help": "path to data directory"} + ) + sample_break_mode: SAMPLE_BREAK_MODE_CHOICES = field( + default="none", + metadata={ + "help": 'If omitted or "none", fills each sample with tokens-per-sample ' + 'tokens. If set to "complete", splits samples only at the end ' + "of sentence, but may include multiple sentences per sample. " + '"complete_doc" is similar but respects doc boundaries. ' + 'If set to "eos", includes only one sentence per sample.' + }, + ) + tokens_per_sample: int = field( + default=1024, + metadata={"help": "max number of tokens per sample for LM dataset"}, + ) + output_dictionary_size: int = field( + default=-1, metadata={"help": "limit the size of output dictionary"} + ) + self_target: bool = field(default=False, metadata={"help": "include self target"}) + future_target: bool = field( + default=False, metadata={"help": "include future target"} + ) + past_target: bool = field(default=False, metadata={"help": "include past target"}) + add_bos_token: bool = field( + default=False, metadata={"help": "prepend beginning of sentence token (<s>)"} + ) + max_target_positions: Optional[int] = field( + default=None, metadata={"help": "max number of tokens in the target sequence"} + ) + shorten_method: SHORTEN_METHOD_CHOICES = field( + default="none", + metadata={ + "help": "if not none, shorten sequences that exceed --tokens-per-sample" + }, + ) + shorten_data_split_list: str = field( + default="", + metadata={ + "help": "comma-separated list of dataset splits to apply shortening to, " + 'e.g., "train,valid" (default: all dataset splits)' + }, + ) + # TODO common vars below add to parent + seed: int = II("params.common.seed") + dataset_impl: Optional[ChoiceEnum(get_available_dataset_impl())] = II( + "params.dataset.dataset_impl" + ) + data_buffer_size: int = II("params.dataset.data_buffer_size") + tpu: bool = II("params.common.tpu") + + +@register_task("language_modeling", dataclass=LanguageModelingConfig) +class LanguageModelingTask(FairseqTask): + """ + Train a language model. + + Args: + dictionary (~fairseq.data.Dictionary): the dictionary for the input of + the language model + output_dictionary (~fairseq.data.Dictionary): the dictionary for the + output of the language model. In most cases it will be the same as + *dictionary*, but could possibly be a more limited version of the + dictionary (if ``--output-dictionary-size`` is used). + targets (List[str]): list of the target types that the language model + should predict. Can be one of "self", "future", and "past". + Defaults to "future". + + .. note:: + + The language modeling task is compatible with :mod:`fairseq-train`, + :mod:`fairseq-generate`, :mod:`fairseq-interactive` and + :mod:`fairseq-eval-lm`. + + The language modeling task provides the following additional command-line + arguments: + + .. argparse:: + :ref: fairseq.tasks.language_modeling_parser + :prog: + """ + + def __init__(self, args, dictionary, output_dictionary=None, targets=None): + super().__init__(args) + self.dictionary = dictionary + self.output_dictionary = output_dictionary or dictionary + + if targets is None: + targets = ["future"] + self.targets = targets + + @classmethod + def setup_dictionary(cls, args, **kwargs): + dictionary = None + output_dictionary = None + if args.data: + paths = utils.split_paths(args.data) + assert len(paths) > 0 + dictionary = Dictionary.load(os.path.join(paths[0], "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + output_dictionary = dictionary + if args.output_dictionary_size >= 0: + output_dictionary = TruncatedDictionary( + dictionary, args.output_dictionary_size + ) + return (dictionary, output_dictionary) + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task (e.g., load dictionaries). + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + dictionary, output_dictionary = cls.setup_dictionary(args, **kwargs) + + # upgrade old checkpoints + if hasattr(args, "exclude_self_target"): + args.self_target = not args.exclude_self_target + + targets = [] + if getattr(args, "self_target", False): + targets.append("self") + if getattr(args, "future_target", False): + targets.append("future") + if getattr(args, "past_target", False): + targets.append("past") + if len(targets) == 0: + # standard language modeling + targets = ["future"] + + return cls(args, dictionary, output_dictionary, targets=targets) + + def build_model(self, args): + model = super().build_model(args) + + for target in self.targets: + if target not in model.supported_targets: + raise ValueError( + "Unsupported language modeling target: {}".format(target) + ) + + return model + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + + data_path = paths[(epoch - 1) % len(paths)] + split_path = os.path.join(data_path, split) + + dataset = data_utils.load_indexed_dataset( + split_path, self.dictionary, self.args.dataset_impl, combine=combine + ) + if dataset is None: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, split_path) + ) + + dataset = maybe_shorten_dataset( + dataset, + split, + self.args.shorten_data_split_list, + self.args.shorten_method, + self.args.tokens_per_sample, + self.args.seed, + ) + + dataset = TokenBlockDataset( + dataset, + dataset.sizes, + self.args.tokens_per_sample, + pad=self.dictionary.pad(), + eos=self.dictionary.eos(), + break_mode=self.args.sample_break_mode, + include_targets=True, + ) + + add_eos_for_other_targets = ( + self.args.sample_break_mode is not None + and self.args.sample_break_mode != "none" + ) + + self.datasets[split] = self._initialize_dataset( + dataset=dataset, + sizes=dataset.sizes, + src_vocab=self.dictionary, + tgt_vocab=self.output_dictionary, + add_eos_for_other_targets=add_eos_for_other_targets, + shuffle=True, + targets=self.targets, + add_bos_token=self.args.add_bos_token, + ) + + def _initialize_dataset(self, **kwargs): + return MonolingualDataset(**kwargs) + + def build_dataset_for_inference(self, src_tokens, src_lengths, **kwargs): + """ + Generate batches for inference. We prepend an eos token to src_tokens + (or bos if `--add-bos-token` is set) and we append a <pad> to target. + This is convenient both for generation with a prefix and LM scoring. + """ + dataset = StripTokenDataset( + TokenBlockDataset( + src_tokens, + src_lengths, + block_size=None, # ignored for "eos" break mode + pad=self.source_dictionary.pad(), + eos=self.source_dictionary.eos(), + break_mode="eos", + ), + # remove eos from (end of) target sequence + self.source_dictionary.eos(), + ) + src_dataset = PrependTokenDataset( + dataset, + token=( + self.source_dictionary.bos() + if getattr(self.args, "add_bos_token", False) + else self.source_dictionary.eos() + ), + ) + tgt_dataset = AppendTokenDataset(dataset, token=self.source_dictionary.pad()) + return NestedDictionaryDataset( + { + "id": IdDataset(), + "net_input": { + "src_tokens": PadDataset( + src_dataset, + pad_idx=self.source_dictionary.pad(), + left_pad=False, + ), + "src_lengths": NumelDataset(src_dataset, reduce=False), + }, + "target": PadDataset( + tgt_dataset, pad_idx=self.source_dictionary.pad(), left_pad=False + ), + }, + sizes=[np.array(src_lengths)], + ) + + def inference_step( + self, generator, models, sample, prefix_tokens=None, constraints=None + ): + with torch.no_grad(): + # Generation will always be conditioned on bos_token + if getattr(self.args, "add_bos_token", False): + bos_token = self.source_dictionary.bos() + else: + bos_token = self.source_dictionary.eos() + + if constraints is not None: + raise NotImplementedError( + "Constrained decoding with the language_modeling task is not supported" + ) + + # SequenceGenerator doesn't use src_tokens directly, we need to + # pass the `prefix_tokens` argument instead + if prefix_tokens is None and sample["net_input"]["src_tokens"].nelement(): + prefix_tokens = sample["net_input"]["src_tokens"] + if prefix_tokens[:, 0].eq(bos_token).all(): + prefix_tokens = prefix_tokens[:, 1:] + + return generator.generate( + models, sample, prefix_tokens=prefix_tokens, bos_token=bos_token + ) + + @property + def source_dictionary(self): + """Return the :class:`~fairseq.data.Dictionary` for the language + model.""" + return self.dictionary + + @property + def target_dictionary(self): + """Return the :class:`~fairseq.data.Dictionary` for the language + model.""" + return self.output_dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/legacy_masked_lm.py b/fairseq-tools/fairseq/fairseq/tasks/legacy_masked_lm.py new file mode 100644 index 00000000..97549765 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/legacy_masked_lm.py @@ -0,0 +1,152 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import itertools +import logging +import os + +import numpy as np +from fairseq import tokenizer, utils +from fairseq.data import ConcatDataset, Dictionary, data_utils, indexed_dataset +from fairseq.data.legacy.block_pair_dataset import BlockPairDataset +from fairseq.data.legacy.masked_lm_dataset import MaskedLMDataset +from fairseq.data.legacy.masked_lm_dictionary import BertDictionary +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("legacy_masked_lm") +class LegacyMaskedLMTask(LegacyFairseqTask): + """ + Task for training Masked LM (BERT) model. + Args: + dictionary (Dictionary): the dictionary for the input of the task + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", + help="colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner", + ) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments" + " per sample for BERT dataset", + ) + parser.add_argument( + "--break-mode", default="doc", type=str, help="mode for breaking sentence" + ) + parser.add_argument("--shuffle-dataset", action="store_true", default=False) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + @classmethod + def load_dictionary(cls, filename): + return BertDictionary.load(filename) + + @classmethod + def build_dictionary( + cls, filenames, workers=1, threshold=-1, nwords=-1, padding_factor=8 + ): + d = BertDictionary() + for filename in filenames: + Dictionary.add_file_to_dictionary( + filename, d, tokenizer.tokenize_line, workers + ) + d.finalize(threshold=threshold, nwords=nwords, padding_factor=padding_factor) + return d + + @property + def target_dictionary(self): + return self.dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task.""" + paths = utils.split_paths(args.data) + assert len(paths) > 0 + dictionary = BertDictionary.load(os.path.join(paths[0], "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + loaded_datasets = [] + + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + logger.info("data_path", data_path) + + for k in itertools.count(): + split_k = split + (str(k) if k > 0 else "") + path = os.path.join(data_path, split_k) + ds = indexed_dataset.make_dataset( + path, + impl=self.args.dataset_impl, + fix_lua_indexing=True, + dictionary=self.dictionary, + ) + + if ds is None: + if k > 0: + break + else: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, data_path) + ) + + with data_utils.numpy_seed(self.seed + k): + loaded_datasets.append( + BlockPairDataset( + ds, + self.dictionary, + ds.sizes, + self.args.tokens_per_sample, + break_mode=self.args.break_mode, + doc_break_size=1, + ) + ) + + logger.info( + "{} {} {} examples".format(data_path, split_k, len(loaded_datasets[-1])) + ) + + if not combine: + break + + if len(loaded_datasets) == 1: + dataset = loaded_datasets[0] + sizes = dataset.sizes + else: + dataset = ConcatDataset(loaded_datasets) + sizes = np.concatenate([ds.sizes for ds in loaded_datasets]) + + self.datasets[split] = MaskedLMDataset( + dataset=dataset, + sizes=sizes, + vocab=self.dictionary, + pad_idx=self.dictionary.pad(), + mask_idx=self.dictionary.mask(), + classif_token_idx=self.dictionary.cls(), + sep_token_idx=self.dictionary.sep(), + shuffle=self.args.shuffle_dataset, + seed=self.seed, + ) diff --git a/fairseq-tools/fairseq/fairseq/tasks/masked_lm.py b/fairseq-tools/fairseq/fairseq/tasks/masked_lm.py new file mode 100644 index 00000000..56086f5e --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/masked_lm.py @@ -0,0 +1,247 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os + +import numpy as np +from fairseq import utils +from fairseq.data import ( + Dictionary, + IdDataset, + MaskTokensDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + PrependTokenDataset, + RightPadDataset, + SortDataset, + TokenBlockDataset, + data_utils, +) +from fairseq.data.encoders.utils import get_whole_word_mask +from fairseq.data.shorten_dataset import maybe_shorten_dataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("masked_lm") +class MaskedLMTask(LegacyFairseqTask): + """Task for training masked language models (e.g., BERT, RoBERTa).""" + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", + help="colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner", + ) + parser.add_argument( + "--sample-break-mode", + default="complete", + choices=["none", "complete", "complete_doc", "eos"], + help='If omitted or "none", fills each sample with tokens-per-sample ' + 'tokens. If set to "complete", splits samples only at the end ' + "of sentence, but may include multiple sentences per sample. " + '"complete_doc" is similar but respects doc boundaries. ' + 'If set to "eos", includes only one sentence per sample.', + ) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments " + "per sample for BERT dataset", + ) + parser.add_argument( + "--mask-prob", + default=0.15, + type=float, + help="probability of replacing a token with mask", + ) + parser.add_argument( + "--leave-unmasked-prob", + default=0.1, + type=float, + help="probability that a masked token is unmasked", + ) + parser.add_argument( + "--random-token-prob", + default=0.1, + type=float, + help="probability of replacing a token with a random token", + ) + parser.add_argument( + "--freq-weighted-replacement", + default=False, + action="store_true", + help="sample random replacement words based on word frequencies", + ) + parser.add_argument( + "--mask-whole-words", + default=False, + action="store_true", + help="mask whole words; you may also want to set --bpe", + ) + parser.add_argument( + "--shorten-method", + default="none", + choices=["none", "truncate", "random_crop"], + help="if not none, shorten sequences that exceed --tokens-per-sample", + ) + parser.add_argument( + "--shorten-data-split-list", + default="", + help="comma-separated list of dataset splits to apply shortening to, " + 'e.g., "train,valid" (default: all dataset splits)', + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + # add mask token + self.mask_idx = dictionary.add_symbol("<mask>") + + @classmethod + def setup_task(cls, args, **kwargs): + paths = utils.split_paths(args.data) + assert len(paths) > 0 + dictionary = Dictionary.load(os.path.join(paths[0], "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + return cls(args, dictionary) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + split_path = os.path.join(data_path, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + self.source_dictionary, + self.args.dataset_impl, + combine=combine, + ) + if dataset is None: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, split_path) + ) + + dataset = maybe_shorten_dataset( + dataset, + split, + self.args.shorten_data_split_list, + self.args.shorten_method, + self.args.tokens_per_sample, + self.args.seed, + ) + + # create continuous blocks of tokens + dataset = TokenBlockDataset( + dataset, + dataset.sizes, + self.args.tokens_per_sample - 1, # one less for <s> + pad=self.source_dictionary.pad(), + eos=self.source_dictionary.eos(), + break_mode=self.args.sample_break_mode, + ) + logger.info("loaded {} blocks from: {}".format(len(dataset), split_path)) + + # prepend beginning-of-sentence token (<s>, equiv. to [CLS] in BERT) + dataset = PrependTokenDataset(dataset, self.source_dictionary.bos()) + + # create masked input and targets + mask_whole_words = ( + get_whole_word_mask(self.args, self.source_dictionary) + if self.args.mask_whole_words + else None + ) + + src_dataset, tgt_dataset = MaskTokensDataset.apply_mask( + dataset, + self.source_dictionary, + pad_idx=self.source_dictionary.pad(), + mask_idx=self.mask_idx, + seed=self.args.seed, + mask_prob=self.args.mask_prob, + leave_unmasked_prob=self.args.leave_unmasked_prob, + random_token_prob=self.args.random_token_prob, + freq_weighted_replacement=self.args.freq_weighted_replacement, + mask_whole_words=mask_whole_words, + ) + + with data_utils.numpy_seed(self.args.seed + epoch): + shuffle = np.random.permutation(len(src_dataset)) + + self.datasets[split] = SortDataset( + NestedDictionaryDataset( + { + "id": IdDataset(), + "net_input": { + "src_tokens": RightPadDataset( + src_dataset, + pad_idx=self.source_dictionary.pad(), + ), + "src_lengths": NumelDataset(src_dataset, reduce=False), + }, + "target": RightPadDataset( + tgt_dataset, + pad_idx=self.source_dictionary.pad(), + ), + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(src_dataset, reduce=True), + }, + sizes=[src_dataset.sizes], + ), + sort_order=[ + shuffle, + src_dataset.sizes, + ], + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, sort=True): + src_dataset = RightPadDataset( + TokenBlockDataset( + src_tokens, + src_lengths, + self.args.tokens_per_sample - 1, # one less for <s> + pad=self.source_dictionary.pad(), + eos=self.source_dictionary.eos(), + break_mode="eos", + ), + pad_idx=self.source_dictionary.pad(), + ) + src_dataset = PrependTokenDataset(src_dataset, self.source_dictionary.bos()) + src_dataset = NestedDictionaryDataset( + { + "id": IdDataset(), + "net_input": { + "src_tokens": src_dataset, + "src_lengths": NumelDataset(src_dataset, reduce=False), + }, + }, + sizes=src_lengths, + ) + if sort: + src_dataset = SortDataset(src_dataset, sort_order=[src_lengths]) + return src_dataset + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/multilingual_denoising.py b/fairseq-tools/fairseq/fairseq/tasks/multilingual_denoising.py new file mode 100644 index 00000000..d1c91491 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/multilingual_denoising.py @@ -0,0 +1,254 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os + +import numpy as np +from fairseq.data import ( + AppendTokenDataset, + ConcatDataset, + DenoisingDataset, + Dictionary, + PrependTokenDataset, + ResamplingDataset, + SortDataset, + TokenBlockDataset, + data_utils, +) +from fairseq.data.encoders.utils import get_whole_word_mask +from fairseq.tasks import register_task + +from .denoising import DenoisingTask + + +logger = logging.getLogger(__name__) + + +@register_task("multilingual_denoising") +class MultilingualDenoisingTask(DenoisingTask): + @staticmethod + def add_args(parser): + DenoisingTask.add_args(parser) + parser.add_argument( + "--multilang-sampling-alpha", + type=float, + default=1.0, + help="smoothing alpha for sample ratios across multiple datasets", + ) + parser.add_argument("--add-lang-token", default=False, action="store_true") + parser.add_argument( + "--langs", type=str, help="language ids we are considering", default=None + ) + parser.add_argument( + "--no-whole-word-mask-langs", + type=str, + default="", + metavar="N", + help="languages without spacing between words dont support whole word masking", + ) + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task.""" + paths = args.data.split(":") + assert len(paths) > 0 + dictionary = Dictionary.load(os.path.join(paths[0], "dict.txt")) + + data_path = paths[0] + if args.langs is None: + languages = sorted( + [ + name + for name in os.listdir(data_path) + if os.path.isdir(os.path.join(data_path, name)) + ] + ) + else: + languages = args.langs.split(",") + + if args.add_lang_token: + for lang in languages: + dictionary.add_symbol("[{}]".format(lang)) + + logger.info("dictionary: {} types".format(len(dictionary))) + if not hasattr(args, "shuffle_instance"): + args.shuffle_instance = False + return cls(args, dictionary) + + def __init__(self, args, dictionary): + super().__init__(args, dictionary) + self.dictionary = dictionary + self.seed = args.seed + + # add mask token + self.mask_idx = self.dictionary.add_symbol("<mask>") + self.langs = args.langs + self.args = args + + def _get_sample_prob(self, dataset_lens): + """ + Get smoothed sampling porbability by languages. This helps low resource + languages by upsampling them. + """ + prob = dataset_lens / dataset_lens.sum() + smoothed_prob = prob ** self.args.multilang_sampling_alpha + smoothed_prob = smoothed_prob / smoothed_prob.sum() + return smoothed_prob + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = self.args.data.split(":") + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + split_path = os.path.join(data_path, split) + + if self.langs is None: + languages = sorted( + [ + name + for name in os.listdir(data_path) + if os.path.isdir(os.path.join(data_path, name)) + ] + ) + else: + languages = self.langs.split(",") + for name in languages: + p = os.path.join(data_path, name) + assert os.path.exists(p), "data not found: {}".format(p) + + logger.info("Training on {0} languages: {1}".format(len(languages), languages)) + logger.info( + "Language to id mapping: ", {lang: id for id, lang in enumerate(languages)} + ) + + mask_whole_words = get_whole_word_mask(self.args, self.dictionary) + language_without_segmentations = self.args.no_whole_word_mask_langs.split(",") + lang_datasets = [] + for language in languages: + split_path = os.path.join(data_path, language, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + self.source_dictionary, + self.args.dataset_impl, + combine=combine, + ) + if dataset is None: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, split_path) + ) + + end_token = ( + self.source_dictionary.index("[{}]".format(language)) + if self.args.add_lang_token + else self.source_dictionary.eos() + ) + + # create continuous blocks of tokens + dataset = TokenBlockDataset( + dataset, + dataset.sizes, + self.args.tokens_per_sample - 2, # one less for <s> + pad=self.source_dictionary.pad(), + eos=end_token, + break_mode=self.args.sample_break_mode, + ) + logger.info("loaded {} blocks from: {}".format(len(dataset), split_path)) + + # prepend beginning-of-sentence token (<s>, equiv. to [CLS] in BERT) + dataset = PrependTokenDataset(dataset, self.source_dictionary.bos()) + dataset = AppendTokenDataset(dataset, end_token) + + lang_mask_whole_words = ( + mask_whole_words + if language not in language_without_segmentations + else None + ) + lang_dataset = DenoisingDataset( + dataset, + dataset.sizes, + self.dictionary, + self.mask_idx, + lang_mask_whole_words, + shuffle=self.args.shuffle_instance, + seed=self.seed, + args=self.args, + eos=None + if not self.args.add_lang_token + else self.source_dictionary.index("[{}]".format(language)), + ) + lang_datasets.append(lang_dataset) + + dataset_lengths = np.array( + [len(d) for d in lang_datasets], + dtype=float, + ) + logger.info( + "loaded total {} blocks for all languages".format( + int(dataset_lengths.sum()), + ) + ) + if split == self.args.train_subset: + # For train subset, additionally up or down sample languages. + sample_probs = self._get_sample_prob(dataset_lengths) + logger.info( + "Sample probability by language: {}".format( + { + lang: "{0:.4f}".format(sample_probs[id]) + for id, lang in enumerate(languages) + } + ) + ) + size_ratio = (sample_probs * dataset_lengths.sum()) / dataset_lengths + logger.info( + "Up/Down Sampling ratio by language: {}".format( + { + lang: "{0:.2f}".format(size_ratio[id]) + for id, lang in enumerate(languages) + } + ) + ) + + resampled_lang_datasets = [ + ResamplingDataset( + lang_datasets[i], + size_ratio=size_ratio[i], + seed=self.args.seed, + epoch=epoch, + replace=size_ratio[i] >= 1.0, + ) + for i, d in enumerate(lang_datasets) + ] + dataset = ConcatDataset( + resampled_lang_datasets, + ) + else: + dataset = ConcatDataset(lang_datasets) + lang_splits = [split] + for lang_id, lang_dataset in enumerate(lang_datasets): + split_name = split + "_" + languages[lang_id] + lang_splits.append(split_name) + self.datasets[split_name] = lang_dataset + + if split in self.args.valid_subset: + self.args.valid_subset = self.args.valid_subset.replace( + split, ",".join(lang_splits) + ) + + with data_utils.numpy_seed(self.args.seed + epoch): + shuffle = np.random.permutation(len(dataset)) + + self.datasets[split] = SortDataset( + dataset, + sort_order=[ + shuffle, + dataset.sizes, + ], + ) diff --git a/fairseq-tools/fairseq/fairseq/tasks/multilingual_masked_lm.py b/fairseq-tools/fairseq/fairseq/tasks/multilingual_masked_lm.py new file mode 100644 index 00000000..9e6ce4b8 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/multilingual_masked_lm.py @@ -0,0 +1,338 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os + +import numpy as np +import torch +from fairseq import utils +from fairseq.data import ( + ConcatDataset, + Dictionary, + IdDataset, + MaskTokensDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + PadDataset, + PrependTokenDataset, + RawLabelDataset, + ResamplingDataset, + SortDataset, + TokenBlockDataset, + data_utils, + encoders, +) +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("multilingual_masked_lm") +class MultiLingualMaskedLMTask(LegacyFairseqTask): + """Task for training masked language models (e.g., BERT, RoBERTa).""" + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument( + "data", + help="colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner", + ) + parser.add_argument( + "--sample-break-mode", + default="complete", + choices=["none", "complete", "complete_doc", "eos"], + help='If omitted or "none", fills each sample with tokens-per-sample ' + 'tokens. If set to "complete", splits samples only at the end ' + "of sentence, but may include multiple sentences per sample. " + '"complete_doc" is similar but respects doc boundaries. ' + 'If set to "eos", includes only one sentence per sample.', + ) + parser.add_argument( + "--tokens-per-sample", + default=512, + type=int, + help="max number of total tokens over all segments " + "per sample for BERT dataset", + ) + parser.add_argument( + "--mask-prob", + default=0.15, + type=float, + help="probability of replacing a token with mask", + ) + parser.add_argument( + "--leave-unmasked-prob", + default=0.1, + type=float, + help="probability that a masked token is unmasked", + ) + parser.add_argument( + "--random-token-prob", + default=0.1, + type=float, + help="probability of replacing a token with a random token", + ) + parser.add_argument( + "--freq-weighted-replacement", + action="store_true", + help="sample random replacement words based on word frequencies", + ) + parser.add_argument( + "--mask-whole-words", + default=False, + action="store_true", + help="mask whole words; you may also want to set --bpe", + ) + parser.add_argument( + "--multilang-sampling-alpha", + type=float, + default=1.0, + help="smoothing alpha for sample rations across multiple datasets", + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + self.seed = args.seed + + # add mask token + self.mask_idx = dictionary.add_symbol("<mask>") + + @classmethod + def setup_task(cls, args, **kwargs): + paths = utils.split_paths(args.data) + assert len(paths) > 0 + dictionary = Dictionary.load(os.path.join(paths[0], "dict.txt")) + logger.info("dictionary: {} types".format(len(dictionary))) + return cls(args, dictionary) + + def _get_whole_word_mask(self): + # create masked input and targets + if self.args.mask_whole_words: + bpe = encoders.build_bpe(self.args) + if bpe is not None: + + def is_beginning_of_word(i): + if i < self.source_dictionary.nspecial: + # special elements are always considered beginnings + return True + tok = self.source_dictionary[i] + if tok.startswith("madeupword"): + return True + try: + return bpe.is_beginning_of_word(tok) + except ValueError: + return True + + mask_whole_words = torch.ByteTensor( + list(map(is_beginning_of_word, range(len(self.source_dictionary)))) + ) + else: + mask_whole_words = None + return mask_whole_words + + def _get_sample_prob(self, dataset_lens): + """ + Get smoothed sampling porbability by languages. This helps low resource + languages by upsampling them. + """ + prob = dataset_lens / dataset_lens.sum() + smoothed_prob = prob ** self.args.multilang_sampling_alpha + smoothed_prob = smoothed_prob / smoothed_prob.sum() + return smoothed_prob + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + languages = sorted( + name + for name in os.listdir(data_path) + if os.path.isdir(os.path.join(data_path, name)) + ) + + logger.info("Training on {0} languages: {1}".format(len(languages), languages)) + logger.info( + "Language to id mapping: ", {lang: id for id, lang in enumerate(languages)} + ) + + mask_whole_words = self._get_whole_word_mask() + lang_datasets = [] + for lang_id, language in enumerate(languages): + split_path = os.path.join(data_path, language, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + self.source_dictionary, + self.args.dataset_impl, + combine=combine, + ) + if dataset is None: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, split_path) + ) + + # create continuous blocks of tokens + dataset = TokenBlockDataset( + dataset, + dataset.sizes, + self.args.tokens_per_sample - 1, # one less for <s> + pad=self.source_dictionary.pad(), + eos=self.source_dictionary.eos(), + break_mode=self.args.sample_break_mode, + ) + logger.info("loaded {} blocks from: {}".format(len(dataset), split_path)) + + # prepend beginning-of-sentence token (<s>, equiv. to [CLS] in BERT) + dataset = PrependTokenDataset(dataset, self.source_dictionary.bos()) + + src_dataset, tgt_dataset = MaskTokensDataset.apply_mask( + dataset, + self.source_dictionary, + pad_idx=self.source_dictionary.pad(), + mask_idx=self.mask_idx, + seed=self.args.seed, + mask_prob=self.args.mask_prob, + leave_unmasked_prob=self.args.leave_unmasked_prob, + random_token_prob=self.args.random_token_prob, + freq_weighted_replacement=self.args.freq_weighted_replacement, + mask_whole_words=mask_whole_words, + ) + + lang_dataset = NestedDictionaryDataset( + { + "net_input": { + "src_tokens": PadDataset( + src_dataset, + pad_idx=self.source_dictionary.pad(), + left_pad=False, + ), + "src_lengths": NumelDataset(src_dataset, reduce=False), + }, + "target": PadDataset( + tgt_dataset, + pad_idx=self.source_dictionary.pad(), + left_pad=False, + ), + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(src_dataset, reduce=True), + "lang_id": RawLabelDataset([lang_id] * src_dataset.sizes.shape[0]), + }, + sizes=[src_dataset.sizes], + ) + lang_datasets.append(lang_dataset) + + dataset_lengths = np.array( + [len(d) for d in lang_datasets], + dtype=float, + ) + logger.info( + "loaded total {} blocks for all languages".format( + dataset_lengths.sum(), + ) + ) + if split == self.args.train_subset: + # For train subset, additionally up or down sample languages. + sample_probs = self._get_sample_prob(dataset_lengths) + logger.info( + "Sample probability by language: ", + { + lang: "{0:.4f}".format(sample_probs[id]) + for id, lang in enumerate(languages) + }, + ) + size_ratio = (sample_probs * dataset_lengths.sum()) / dataset_lengths + logger.info( + "Up/Down Sampling ratio by language: ", + { + lang: "{0:.2f}".format(size_ratio[id]) + for id, lang in enumerate(languages) + }, + ) + + resampled_lang_datasets = [ + ResamplingDataset( + lang_datasets[i], + size_ratio=size_ratio[i], + seed=self.args.seed, + epoch=epoch, + replace=size_ratio[i] >= 1.0, + ) + for i, d in enumerate(lang_datasets) + ] + dataset = ConcatDataset(resampled_lang_datasets) + else: + dataset = ConcatDataset(lang_datasets) + lang_splits = [split] + for lang_id, lang_dataset in enumerate(lang_datasets): + split_name = split + "_" + languages[lang_id] + lang_splits.append(split_name) + self.datasets[split_name] = lang_dataset + + # [TODO]: This is hacky for now to print validation ppl for each + # language individually. Maybe need task API changes to allow it + # in more generic ways. + if split in self.args.valid_subset: + self.args.valid_subset = self.args.valid_subset.replace( + split, ",".join(lang_splits) + ) + + with data_utils.numpy_seed(self.args.seed + epoch): + shuffle = np.random.permutation(len(dataset)) + + self.datasets[split] = SortDataset( + dataset, + sort_order=[ + shuffle, + dataset.sizes, + ], + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, sort=True): + src_dataset = PadDataset( + TokenBlockDataset( + src_tokens, + src_lengths, + self.args.tokens_per_sample - 1, # one less for <s> + pad=self.source_dictionary.pad(), + eos=self.source_dictionary.eos(), + break_mode="eos", + ), + pad_idx=self.source_dictionary.pad(), + left_pad=False, + ) + src_dataset = PrependTokenDataset(src_dataset, self.source_dictionary.bos()) + src_dataset = NestedDictionaryDataset( + { + "id": IdDataset(), + "net_input": { + "src_tokens": src_dataset, + "src_lengths": NumelDataset(src_dataset, reduce=False), + }, + }, + sizes=src_lengths, + ) + if sort: + src_dataset = SortDataset(src_dataset, sort_order=[src_lengths]) + return src_dataset + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/multilingual_translation.py b/fairseq-tools/fairseq/fairseq/tasks/multilingual_translation.py new file mode 100644 index 00000000..f6cb17f1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/multilingual_translation.py @@ -0,0 +1,449 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import logging +import os +from collections import OrderedDict + +import torch +from fairseq import metrics, options, utils +from fairseq.data import ( + Dictionary, + LanguagePairDataset, + RoundRobinZipDatasets, + TransformEosLangPairDataset, +) +from fairseq.models import FairseqMultiModel +from fairseq.tasks.translation import load_langpair_dataset + +from . import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +def _lang_token(lang: str): + return "__{}__".format(lang) + + +def _lang_token_index(dic: Dictionary, lang: str): + """Return language token index.""" + idx = dic.index(_lang_token(lang)) + assert idx != dic.unk_index, "cannot find language token for lang {}".format(lang) + return idx + + +@register_task("multilingual_translation") +class MultilingualTranslationTask(LegacyFairseqTask): + """A task for training multiple translation models simultaneously. + + We iterate round-robin over batches from multiple language pairs, ordered + according to the `--lang-pairs` argument. + + The training loop is roughly: + + for i in range(len(epoch)): + for lang_pair in args.lang_pairs: + batch = next_batch_for_lang_pair(lang_pair) + loss = criterion(model_for_lang_pair(lang_pair), batch) + loss.backward() + optimizer.step() + + In practice, `next_batch_for_lang_pair` is abstracted in a FairseqDataset + (e.g., `RoundRobinZipDatasets`) and `model_for_lang_pair` is a model that + implements the `FairseqMultiModel` interface. + + During inference it is required to specify a single `--source-lang` and + `--target-lang`, which indicates the inference langauge direction. + `--lang-pairs`, `--encoder-langtok`, `--decoder-langtok` have to be set to + the same value as training. + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + parser.add_argument('data', metavar='DIR', help='path to data directory') + parser.add_argument('--lang-pairs', default=None, metavar='PAIRS', + help='comma-separated list of language pairs (in training order): en-de,en-fr,de-fr') + parser.add_argument('-s', '--source-lang', default=None, metavar='SRC', + help='source language (only needed for inference)') + parser.add_argument('-t', '--target-lang', default=None, metavar='TARGET', + help='target language (only needed for inference)') + parser.add_argument('--left-pad-source', default='True', type=str, metavar='BOOL', + help='pad the source on the left (default: True)') + parser.add_argument('--left-pad-target', default='False', type=str, metavar='BOOL', + help='pad the target on the left (default: False)') + parser.add_argument('--max-source-positions', default=1024, type=int, metavar='N', + help='max number of tokens in the source sequence') + parser.add_argument('--max-target-positions', default=1024, type=int, metavar='N', + help='max number of tokens in the target sequence') + parser.add_argument('--upsample-primary', default=1, type=int, + help='amount to upsample primary dataset') + parser.add_argument('--encoder-langtok', default=None, type=str, choices=['src', 'tgt'], + metavar='SRCTGT', + help='replace beginning-of-sentence in source sentence with source or target ' + 'language token. (src/tgt)') + parser.add_argument('--decoder-langtok', action='store_true', + help='replace beginning-of-sentence in target sentence with target language token') + # fmt: on + + def __init__(self, args, dicts, training): + super().__init__(args) + self.dicts = dicts + self.training = training + if training: + self.lang_pairs = args.lang_pairs + else: + self.lang_pairs = ["{}-{}".format(args.source_lang, args.target_lang)] + # eval_lang_pairs for multilingual translation is usually all of the + # lang_pairs. However for other multitask settings or when we want to + # optimize for certain languages we want to use a different subset. Thus + # the eval_lang_pairs class variable is provided for classes that extend + # this class. + self.eval_lang_pairs = self.lang_pairs + # model_lang_pairs will be used to build encoder-decoder model pairs in + # models.build_model(). This allows multitask type of sub-class can + # build models other than the input lang_pairs + self.model_lang_pairs = self.lang_pairs + self.langs = list(dicts.keys()) + + @classmethod + def setup_task(cls, args, **kwargs): + dicts, training = cls.prepare(args, **kwargs) + return cls(args, dicts, training) + + @classmethod + def prepare(cls, args, **kargs): + args.left_pad_source = utils.eval_bool(args.left_pad_source) + args.left_pad_target = utils.eval_bool(args.left_pad_target) + + if args.lang_pairs is None: + raise ValueError( + "--lang-pairs is required. List all the language pairs in the training objective." + ) + if isinstance(args.lang_pairs, str): + args.lang_pairs = args.lang_pairs.split(",") + sorted_langs = sorted( + list({x for lang_pair in args.lang_pairs for x in lang_pair.split("-")}) + ) + if args.source_lang is not None or args.target_lang is not None: + training = False + else: + training = True + + # load dictionaries + dicts = OrderedDict() + for lang in sorted_langs: + paths = utils.split_paths(args.data) + assert len(paths) > 0 + dicts[lang] = cls.load_dictionary( + os.path.join(paths[0], "dict.{}.txt".format(lang)) + ) + if len(dicts) > 0: + assert dicts[lang].pad() == dicts[sorted_langs[0]].pad() + assert dicts[lang].eos() == dicts[sorted_langs[0]].eos() + assert dicts[lang].unk() == dicts[sorted_langs[0]].unk() + if args.encoder_langtok is not None or args.decoder_langtok: + for lang_to_add in sorted_langs: + dicts[lang].add_symbol(_lang_token(lang_to_add)) + logger.info("[{}] dictionary: {} types".format(lang, len(dicts[lang]))) + return dicts, training + + def get_encoder_langtok(self, src_lang, tgt_lang): + if self.args.encoder_langtok is None: + return self.dicts[src_lang].eos() + if self.args.encoder_langtok == "src": + return _lang_token_index(self.dicts[src_lang], src_lang) + else: + return _lang_token_index(self.dicts[src_lang], tgt_lang) + + def get_decoder_langtok(self, tgt_lang): + if not self.args.decoder_langtok: + return self.dicts[tgt_lang].eos() + return _lang_token_index(self.dicts[tgt_lang], tgt_lang) + + def alter_dataset_langtok( + self, + lang_pair_dataset, + src_eos=None, + src_lang=None, + tgt_eos=None, + tgt_lang=None, + ): + if self.args.encoder_langtok is None and not self.args.decoder_langtok: + return lang_pair_dataset + + new_src_eos = None + if ( + self.args.encoder_langtok is not None + and src_eos is not None + and src_lang is not None + and tgt_lang is not None + ): + new_src_eos = self.get_encoder_langtok(src_lang, tgt_lang) + else: + src_eos = None + + new_tgt_bos = None + if self.args.decoder_langtok and tgt_eos is not None and tgt_lang is not None: + new_tgt_bos = self.get_decoder_langtok(tgt_lang) + else: + tgt_eos = None + + return TransformEosLangPairDataset( + lang_pair_dataset, + src_eos=src_eos, + new_src_eos=new_src_eos, + tgt_bos=tgt_eos, + new_tgt_bos=new_tgt_bos, + ) + + def load_dataset(self, split, epoch=1, **kwargs): + """Load a dataset split.""" + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + def language_pair_dataset(lang_pair): + src, tgt = lang_pair.split("-") + langpair_dataset = load_langpair_dataset( + data_path, + split, + src, + self.dicts[src], + tgt, + self.dicts[tgt], + combine=True, + dataset_impl=self.args.dataset_impl, + upsample_primary=self.args.upsample_primary, + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + max_source_positions=self.args.max_source_positions, + max_target_positions=self.args.max_target_positions, + ) + return self.alter_dataset_langtok( + langpair_dataset, + src_eos=self.dicts[src].eos(), + src_lang=src, + tgt_eos=self.dicts[tgt].eos(), + tgt_lang=tgt, + ) + + self.datasets[split] = RoundRobinZipDatasets( + OrderedDict( + [ + (lang_pair, language_pair_dataset(lang_pair)) + for lang_pair in self.lang_pairs + ] + ), + eval_key=None + if self.training + else "%s-%s" % (self.args.source_lang, self.args.target_lang), + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, constraints=None): + if constraints is not None: + raise NotImplementedError( + "Constrained decoding with the multilingual_translation task is not supported" + ) + + lang_pair = "%s-%s" % (self.args.source_lang, self.args.target_lang) + return RoundRobinZipDatasets( + OrderedDict( + [ + ( + lang_pair, + self.alter_dataset_langtok( + LanguagePairDataset( + src_tokens, src_lengths, self.source_dictionary + ), + src_eos=self.source_dictionary.eos(), + src_lang=self.args.source_lang, + tgt_eos=self.target_dictionary.eos(), + tgt_lang=self.args.target_lang, + ), + ) + ] + ), + eval_key=lang_pair, + ) + + def build_model(self, args): + def check_args(): + messages = [] + if ( + len(set(self.args.lang_pairs).symmetric_difference(args.lang_pairs)) + != 0 + ): + messages.append( + "--lang-pairs should include all the language pairs {}.".format( + args.lang_pairs + ) + ) + if self.args.encoder_langtok != args.encoder_langtok: + messages.append( + "--encoder-langtok should be {}.".format(args.encoder_langtok) + ) + if self.args.decoder_langtok != args.decoder_langtok: + messages.append( + "--decoder-langtok should {} be set.".format( + "" if args.decoder_langtok else "not" + ) + ) + + if len(messages) > 0: + raise ValueError(" ".join(messages)) + + # Check if task args are consistant with model args + check_args() + + from fairseq import models + + model = models.build_model(args, self) + if not isinstance(model, FairseqMultiModel): + raise ValueError( + "MultilingualTranslationTask requires a FairseqMultiModel architecture" + ) + return model + + def _per_lang_pair_train_loss( + self, lang_pair, model, update_num, criterion, sample, optimizer, ignore_grad + ): + loss, sample_size, logging_output = criterion( + model.models[lang_pair], sample[lang_pair] + ) + if ignore_grad: + loss *= 0 + optimizer.backward(loss) + return loss, sample_size, logging_output + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + model.train() + from collections import defaultdict + + agg_loss, agg_sample_size, agg_logging_output = 0.0, 0.0, defaultdict(float) + curr_lang_pairs = [ + lang_pair + for lang_pair in self.model_lang_pairs + if sample[lang_pair] is not None and len(sample[lang_pair]) != 0 + ] + + for idx, lang_pair in enumerate(curr_lang_pairs): + + def maybe_no_sync(): + if ( + self.args.distributed_world_size > 1 + and hasattr(model, "no_sync") + and idx < len(curr_lang_pairs) - 1 + ): + return model.no_sync() + else: + return contextlib.ExitStack() # dummy contextmanager + + with maybe_no_sync(): + loss, sample_size, logging_output = self._per_lang_pair_train_loss( + lang_pair, + model, + update_num, + criterion, + sample, + optimizer, + ignore_grad, + ) + agg_loss += loss.detach().item() + # TODO make summing of the sample sizes configurable + agg_sample_size += sample_size + for k in logging_output: + agg_logging_output[k] += logging_output[k] + agg_logging_output[f"{lang_pair}:{k}"] += logging_output[k] + return agg_loss, agg_sample_size, agg_logging_output + + def _per_lang_pair_valid_loss(self, lang_pair, model, criterion, sample): + return criterion(model.models[lang_pair], sample[lang_pair]) + + def valid_step(self, sample, model, criterion): + model.eval() + with torch.no_grad(): + from collections import defaultdict + + agg_loss, agg_sample_size, agg_logging_output = 0.0, 0.0, defaultdict(float) + for lang_pair in self.eval_lang_pairs: + if ( + lang_pair not in sample + or sample[lang_pair] is None + or len(sample[lang_pair]) == 0 + ): + continue + loss, sample_size, logging_output = self._per_lang_pair_valid_loss( + lang_pair, model, criterion, sample + ) + agg_loss += loss.data.item() + # TODO make summing of the sample sizes configurable + agg_sample_size += sample_size + for k in logging_output: + agg_logging_output[k] += logging_output[k] + agg_logging_output[f"{lang_pair}:{k}"] += logging_output[k] + return agg_loss, agg_sample_size, agg_logging_output + + def inference_step( + self, generator, models, sample, prefix_tokens=None, constraints=None + ): + with torch.no_grad(): + if self.args.decoder_langtok: + bos_token = _lang_token_index( + self.target_dictionary, self.args.target_lang + ) + else: + bos_token = self.target_dictionary.eos() + return generator.generate( + models, + sample, + prefix_tokens=prefix_tokens, + constraints=constraints, + bos_token=bos_token, + ) + + def reduce_metrics(self, logging_outputs, criterion): + with metrics.aggregate(): + # pass 'sample_size', 'nsentences', 'ntokens' stats to fairseq_task + super().reduce_metrics(logging_outputs, criterion) + for k in ["sample_size", "nsentences", "ntokens"]: + metrics.log_scalar(k, sum(l[k] for l in logging_outputs)) + + @property + def source_dictionary(self): + if self.training: + return next(iter(self.dicts.values())) + else: + return self.dicts[self.args.source_lang] + + @property + def target_dictionary(self): + if self.training: + return next(iter(self.dicts.values())) + else: + return self.dicts[self.args.target_lang] + + def max_positions(self): + """Return the max sentence length allowed by the task.""" + if len(self.datasets.values()) == 0: + return { + "%s-%s" + % (self.args.source_lang, self.args.target_lang): ( + self.args.max_source_positions, + self.args.max_target_positions, + ) + } + return OrderedDict( + [ + (key, (self.args.max_source_positions, self.args.max_target_positions)) + for split in self.datasets.keys() + for key in self.datasets[split].datasets.keys() + ] + ) diff --git a/fairseq-tools/fairseq/fairseq/tasks/semisupervised_translation.py b/fairseq-tools/fairseq/fairseq/tasks/semisupervised_translation.py new file mode 100644 index 00000000..b2f9bf9a --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/semisupervised_translation.py @@ -0,0 +1,485 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +from collections import OrderedDict + +from fairseq import utils +from fairseq.data import ( + BacktranslationDataset, + IndexedCachedDataset, + IndexedDataset, + IndexedRawTextDataset, + LanguagePairDataset, + NoisingDataset, + RoundRobinZipDatasets, + data_utils, + indexed_dataset, +) +from fairseq.models import FairseqMultiModel +from fairseq.sequence_generator import SequenceGenerator + +from . import register_task +from .multilingual_translation import MultilingualTranslationTask + + +logger = logging.getLogger(__name__) + + +def _get_bt_dataset_key(lang_pair): + return "bt:" + lang_pair + + +def _get_denoising_dataset_key(lang_pair): + return "denoising:" + lang_pair + + +# ported from UnsupervisedMT +def parse_lambda_config(x): + """ + Parse the configuration of lambda coefficient (for scheduling). + x = "3" # lambda will be a constant equal to x + x = "0:1,1000:0" # lambda will start from 1 and linearly decrease + # to 0 during the first 1000 iterations + x = "0:0,1000:0,2000:1" # lambda will be equal to 0 for the first 1000 + # iterations, then will linearly increase to 1 until iteration 2000 + """ + split = x.split(",") + if len(split) == 1: + return float(x), None + else: + split = [s.split(os.pathsep) for s in split] + assert all(len(s) == 2 for s in split) + assert all(k.isdigit() for k, _ in split) + assert all( + int(split[i][0]) < int(split[i + 1][0]) for i in range(len(split) - 1) + ) + return float(split[0][1]), [(int(k), float(v)) for k, v in split] + + +@register_task("semisupervised_translation") +class SemisupervisedTranslationTask(MultilingualTranslationTask): + """A task for training multiple translation models simultaneously. + + We iterate round-robin over batches from multiple language pairs, ordered + according to the `--lang-pairs` argument. + + The training loop is roughly: + + for i in range(len(epoch)): + for lang_pair in args.lang_pairs: + batch = next_batch_for_lang_pair(lang_pair) + loss = criterion(model_for_lang_pair(lang_pair), batch) + loss.backward() + optimizer.step() + + In practice, `next_batch_for_lang_pair` is abstracted in a FairseqDataset + (e.g., `RoundRobinZipDatasets`) and `model_for_lang_pair` is a model that + implements the `FairseqMultiModel` interface. + + During inference it is required to specify a single `--source-lang` and + `--target-lang`, instead of `--lang-pairs`. + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + MultilingualTranslationTask.add_args(parser) + parser.add_argument('--lambda-parallel-config', default="1.0", type=str, metavar='CONFIG', + help='cross-entropy reconstruction coefficient (parallel data). ' + 'use fixed weight during training if set to floating point number. ' + 'use piecewise linear function over number of updates to schedule the ' + 'weight with the format: w0:step0,w1:step1,...') + parser.add_argument('--lambda-denoising-config', default="0.0", type=str, metavar='CONFIG', + help='Cross-entropy reconstruction coefficient (denoising autoencoding)' + 'use fixed weight during training if set to floating point number. ' + 'use piecewise linear function over number of updates to schedule the ' + 'weight with the format: w0:step0,w1:step1,...') + parser.add_argument('--lambda-otf-bt-config', default="0.0", type=str, metavar='CONFIG', + help='cross-entropy reconstruction coefficient (on-the-fly back-translation parallel data)' + 'use fixed weight during training if set to floating point number. ' + 'use piecewise linear function over number of updates to schedule the ' + 'weight with the format: w0:step0,w1:step1,...') + parser.add_argument('--bt-max-len-a', default=1.1, type=float, metavar='N', + help='generate back-translated sequences of maximum length ax + b, where x is the ' + 'source length') + parser.add_argument('--bt-max-len-b', default=10.0, type=float, metavar='N', + help='generate back-translated sequences of maximum length ax + b, where x is the ' + 'source length') + parser.add_argument('--bt-beam-size', default=1, type=int, metavar='N', + help='beam size used in beam search of online back-translation') + parser.add_argument('--max-word-shuffle-distance', default=3.0, type=float, metavar='N', + help='maximum word shuffle distance for denoising autoencoding data generation') + parser.add_argument('--word-dropout-prob', default=0.1, type=float, metavar='N', + help='word dropout probability for denoising autoencoding data generation') + parser.add_argument('--word-blanking-prob', default=0.2, type=float, metavar='N', + help='word blanking probability for denoising autoencoding data generation') + # fmt: on + + def __init__(self, args, dicts, training): + super().__init__(args, dicts, training) + self.lambda_parallel, self.lambda_parallel_steps = parse_lambda_config( + args.lambda_parallel_config + ) + self.lambda_otf_bt, self.lambda_otf_bt_steps = parse_lambda_config( + args.lambda_otf_bt_config + ) + self.lambda_denoising, self.lambda_denoising_steps = parse_lambda_config( + args.lambda_denoising_config + ) + if self.lambda_denoising > 0.0 or self.lambda_denoising_steps is not None: + denoising_lang_pairs = [ + "%s-%s" % (tgt, tgt) + for tgt in {lang_pair.split("-")[1] for lang_pair in args.lang_pairs} + ] + self.model_lang_pairs = self.model_lang_pairs + denoising_lang_pairs + self.backtranslate_datasets = {} + self.backtranslators = {} + + @classmethod + def setup_task(cls, args, **kwargs): + dicts, training = MultilingualTranslationTask.prepare(args, **kwargs) + return cls(args, dicts, training) + + def load_dataset(self, split, epoch=1, **kwargs): + """Load a dataset split.""" + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + def split_exists(split, src, tgt, lang): + if src is not None: + filename = os.path.join( + data_path, "{}.{}-{}.{}".format(split, src, tgt, lang) + ) + else: + filename = os.path.join( + data_path, "{}.{}-None.{}".format(split, src, tgt) + ) + return indexed_dataset.dataset_exists(filename, impl=self.args.dataset_impl) + + def load_indexed_dataset(path, dictionary): + return data_utils.load_indexed_dataset( + path, dictionary, self.args.dataset_impl + ) + + # load parallel datasets + src_datasets, tgt_datasets = {}, {} + if ( + self.lambda_parallel > 0.0 + or self.lambda_parallel_steps is not None + or not split.startswith("train") + ): + for lang_pair in self.lang_pairs: + src, tgt = lang_pair.split("-") + if split_exists(split, src, tgt, src): + prefix = os.path.join( + data_path, "{}.{}-{}.".format(split, src, tgt) + ) + elif split_exists(split, tgt, src, src): + prefix = os.path.join( + data_path, "{}.{}-{}.".format(split, tgt, src) + ) + else: + continue + src_datasets[lang_pair] = load_indexed_dataset( + prefix + src, self.dicts[src] + ) + tgt_datasets[lang_pair] = load_indexed_dataset( + prefix + tgt, self.dicts[tgt] + ) + logger.info( + "parallel-{} {} {} examples".format( + data_path, split, len(src_datasets[lang_pair]) + ) + ) + if len(src_datasets) == 0: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, data_path) + ) + + # back translation datasets + backtranslate_datasets = {} + if ( + self.lambda_otf_bt > 0.0 or self.lambda_otf_bt_steps is not None + ) and split.startswith("train"): + for lang_pair in self.lang_pairs: + src, tgt = lang_pair.split("-") + if not split_exists(split, tgt, None, tgt): + raise FileNotFoundError( + "Dataset not found: backtranslation {} ({})".format( + split, data_path + ) + ) + filename = os.path.join( + data_path, "{}.{}-None.{}".format(split, tgt, tgt) + ) + dataset = load_indexed_dataset(filename, self.dicts[tgt]) + lang_pair_dataset_tgt = LanguagePairDataset( + dataset, + dataset.sizes, + self.dicts[tgt], + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + ) + lang_pair_dataset = LanguagePairDataset( + dataset, + dataset.sizes, + src_dict=self.dicts[src], + tgt=dataset, + tgt_sizes=dataset.sizes, + tgt_dict=self.dicts[tgt], + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + ) + backtranslate_datasets[lang_pair] = BacktranslationDataset( + tgt_dataset=self.alter_dataset_langtok( + lang_pair_dataset_tgt, + src_eos=self.dicts[tgt].eos(), + src_lang=tgt, + tgt_lang=src, + ), + backtranslation_fn=self.backtranslators[lang_pair], + src_dict=self.dicts[src], + tgt_dict=self.dicts[tgt], + output_collater=self.alter_dataset_langtok( + lang_pair_dataset=lang_pair_dataset, + src_eos=self.dicts[src].eos(), + src_lang=src, + tgt_eos=self.dicts[tgt].eos(), + tgt_lang=tgt, + ).collater, + ) + logger.info( + "backtranslate-{}: {} {} {} examples".format( + tgt, + data_path, + split, + len(backtranslate_datasets[lang_pair]), + ) + ) + self.backtranslate_datasets[lang_pair] = backtranslate_datasets[ + lang_pair + ] + + # denoising autoencoder + noising_datasets = {} + if ( + self.lambda_denoising > 0.0 or self.lambda_denoising_steps is not None + ) and split.startswith("train"): + for lang_pair in self.lang_pairs: + _, tgt = lang_pair.split("-") + if not split_exists(split, tgt, None, tgt): + continue + filename = os.path.join( + data_path, "{}.{}-None.{}".format(split, tgt, tgt) + ) + tgt_dataset1 = load_indexed_dataset(filename, self.dicts[tgt]) + tgt_dataset2 = load_indexed_dataset(filename, self.dicts[tgt]) + noising_dataset = NoisingDataset( + tgt_dataset1, + self.dicts[tgt], + seed=1, + max_word_shuffle_distance=self.args.max_word_shuffle_distance, + word_dropout_prob=self.args.word_dropout_prob, + word_blanking_prob=self.args.word_blanking_prob, + ) + noising_datasets[lang_pair] = self.alter_dataset_langtok( + LanguagePairDataset( + noising_dataset, + tgt_dataset1.sizes, + self.dicts[tgt], + tgt_dataset2, + tgt_dataset2.sizes, + self.dicts[tgt], + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + ), + src_eos=self.dicts[tgt].eos(), + src_lang=tgt, + tgt_eos=self.dicts[tgt].eos(), + tgt_lang=tgt, + ) + logger.info( + "denoising-{}: {} {} {} examples".format( + tgt, + data_path, + split, + len(noising_datasets[lang_pair]), + ) + ) + + def language_pair_dataset(lang_pair): + src, tgt = lang_pair.split("-") + src_dataset, tgt_dataset = src_datasets[lang_pair], tgt_datasets[lang_pair] + return self.alter_dataset_langtok( + LanguagePairDataset( + src_dataset, + src_dataset.sizes, + self.dicts[src], + tgt_dataset, + tgt_dataset.sizes, + self.dicts[tgt], + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + ), + self.dicts[src].eos(), + src, + self.dicts[tgt].eos(), + tgt, + ) + + self.datasets[split] = RoundRobinZipDatasets( + OrderedDict( + [ + (lang_pair, language_pair_dataset(lang_pair)) + for lang_pair in src_datasets.keys() + ] + + [ + (_get_bt_dataset_key(lang_pair), dataset) + for lang_pair, dataset in backtranslate_datasets.items() + ] + + [ + (_get_denoising_dataset_key(lang_pair), dataset) + for lang_pair, dataset in noising_datasets.items() + ] + ), + eval_key=None + if self.training + else "%s-%s" % (self.args.source_lang, self.args.target_lang), + ) + + def build_model(self, args): + from fairseq import models + + model = models.build_model(args, self) + if not isinstance(model, FairseqMultiModel): + raise ValueError( + "SemisupervisedTranslationTask requires a FairseqMultiModel architecture" + ) + + # create SequenceGenerator for each model that has backtranslation dependency on it + self.sequence_generators = {} + if ( + self.lambda_otf_bt > 0.0 or self.lambda_otf_bt_steps is not None + ) and self.training: + for lang_pair in self.lang_pairs: + src, tgt = lang_pair.split("-") + key = "{}-{}".format(tgt, src) + self.sequence_generators[key] = SequenceGenerator( + [model.models[key]], + tgt_dict=self.dicts[src], + beam_size=args.bt_beam_size, + max_len_a=args.bt_max_len_a, + max_len_b=args.bt_max_len_b, + ) + decoder_lang_tok_idx = self.get_decoder_langtok(src) + + def backtranslate_fn( + sample, + model=model.models[key], + bos_token=decoder_lang_tok_idx, + sequence_generator=self.sequence_generators[key], + ): + return sequence_generator.generate( + [model], + sample, + bos_token=bos_token, + ) + + self.backtranslators[lang_pair] = backtranslate_fn + + return model + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + model.train() + + if update_num > 0: + self.update_step(update_num) + + agg_loss, agg_sample_size, agg_logging_output = 0.0, 0.0, {} + + def forward_backward(model, samples, logging_output_key, weight): + nonlocal agg_loss, agg_sample_size, agg_logging_output + if samples is None or len(samples) == 0: + return + loss, sample_size, logging_output = criterion(model, samples) + if ignore_grad: + loss *= 0 + else: + loss *= weight + optimizer.backward(loss) + agg_loss += loss.detach().item() + # TODO make summing of the sample sizes configurable + agg_sample_size += sample_size + for k in logging_output: + agg_logging_output[k] += logging_output[k] + agg_logging_output[logging_output_key] += logging_output[k] + + if self.lambda_parallel > 0.0: + for lang_pair in self.lang_pairs: + forward_backward( + model.models[lang_pair], + sample[lang_pair], + lang_pair, + self.lambda_parallel, + ) + + if self.lambda_otf_bt > 0.0: + for lang_pair in self.lang_pairs: + sample_key = _get_bt_dataset_key(lang_pair) + forward_backward( + model.models[lang_pair], + sample[sample_key], + sample_key, + self.lambda_otf_bt, + ) + + if self.lambda_denoising > 0.0: + for lang_pair in self.lang_pairs: + _, tgt = lang_pair.split("-") + sample_key = _get_denoising_dataset_key(lang_pair) + forward_backward( + model.models["{0}-{0}".format(tgt)], + sample[sample_key], + sample_key, + self.lambda_denoising, + ) + + return agg_loss, agg_sample_size, agg_logging_output + + def update_step(self, num_updates): + def lambda_step_func(config, n_iter): + """ + Update a lambda value according to its schedule configuration. + """ + ranges = [ + i + for i in range(len(config) - 1) + if config[i][0] <= n_iter < config[i + 1][0] + ] + if len(ranges) == 0: + assert n_iter >= config[-1][0] + return config[-1][1] + assert len(ranges) == 1 + i = ranges[0] + x_a, y_a = config[i] + x_b, y_b = config[i + 1] + return y_a + (n_iter - x_a) * float(y_b - y_a) / float(x_b - x_a) + + if self.lambda_parallel_steps is not None: + self.lambda_parallel = lambda_step_func( + self.lambda_parallel_steps, num_updates + ) + if self.lambda_denoising_steps is not None: + self.lambda_denoising = lambda_step_func( + self.lambda_denoising_steps, num_updates + ) + if self.lambda_otf_bt_steps is not None: + self.lambda_otf_bt = lambda_step_func(self.lambda_otf_bt_steps, num_updates) diff --git a/fairseq-tools/fairseq/fairseq/tasks/sentence_prediction.py b/fairseq-tools/fairseq/fairseq/tasks/sentence_prediction.py new file mode 100644 index 00000000..2df6ee54 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/sentence_prediction.py @@ -0,0 +1,281 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +import logging +import os + +import numpy as np +from fairseq import utils +from fairseq.data import ( + ConcatSentencesDataset, + Dictionary, + IdDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + OffsetTokensDataset, + PrependTokenDataset, + RawLabelDataset, + RightPadDataset, + RollDataset, + SortDataset, + StripTokenDataset, + data_utils, +) +from fairseq.data.shorten_dataset import maybe_shorten_dataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("sentence_prediction") +class SentencePredictionTask(LegacyFairseqTask): + """ + Sentence (or sentence pair) prediction (classification or regression) task. + + Args: + dictionary (Dictionary): the dictionary for the input of the task + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("data", metavar="FILE", help="file prefix for data") + parser.add_argument( + "--num-classes", + type=int, + default=-1, + help="number of classes or regression targets", + ) + parser.add_argument( + "--init-token", + type=int, + default=None, + help="add token at the beginning of each batch item", + ) + parser.add_argument( + "--separator-token", + type=int, + default=None, + help="add separator token between inputs", + ) + parser.add_argument("--regression-target", action="store_true", default=False) + parser.add_argument("--no-shuffle", action="store_true", default=False) + parser.add_argument( + "--shorten-method", + default="none", + choices=["none", "truncate", "random_crop"], + help="if not none, shorten sequences that exceed --tokens-per-sample", + ) + parser.add_argument( + "--shorten-data-split-list", + default="", + help="comma-separated list of dataset splits to apply shortening to, " + 'e.g., "train,valid" (default: all dataset splits)', + ) + parser.add_argument( + "--add-prev-output-tokens", + action="store_true", + default=False, + help="add prev_output_tokens to sample, used for encoder-decoder arch", + ) + + def __init__(self, args, data_dictionary, label_dictionary): + super().__init__(args) + self.dictionary = data_dictionary + self._label_dictionary = label_dictionary + if not hasattr(args, "max_positions"): + self._max_positions = ( + args.max_source_positions, + args.max_target_positions, + ) + else: + self._max_positions = args.max_positions + args.tokens_per_sample = self._max_positions + + @classmethod + def load_dictionary(cls, args, filename, source=True): + """Load the dictionary from the filename + + Args: + filename (str): the filename + """ + dictionary = Dictionary.load(filename) + dictionary.add_symbol("<mask>") + return dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + assert args.num_classes > 0, "Must set --num-classes" + + # load data dictionary + data_dict = cls.load_dictionary( + args, + os.path.join(args.data, "input0", "dict.txt"), + source=True, + ) + logger.info("[input] dictionary: {} types".format(len(data_dict))) + + label_dict = None + if not args.regression_target: + # load label dictionary + label_dict = cls.load_dictionary( + args, + os.path.join(args.data, "label", "dict.txt"), + source=False, + ) + logger.info("[label] dictionary: {} types".format(len(label_dict))) + else: + label_dict = data_dict + return cls(args, data_dict, label_dict) + + def load_dataset(self, split, combine=False, **kwargs): + """Load a given dataset split (e.g., train, valid, test).""" + + def get_path(type, split): + return os.path.join(self.args.data, type, split) + + def make_dataset(type, dictionary): + split_path = get_path(type, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + dictionary, + self.args.dataset_impl, + combine=combine, + ) + return dataset + + input0 = make_dataset("input0", self.source_dictionary) + assert input0 is not None, "could not find dataset: {}".format( + get_path(type, split) + ) + input1 = make_dataset("input1", self.source_dictionary) + + if self.args.init_token is not None: + input0 = PrependTokenDataset(input0, self.args.init_token) + + if input1 is None: + src_tokens = input0 + else: + if self.args.separator_token is not None: + input1 = PrependTokenDataset(input1, self.args.separator_token) + + src_tokens = ConcatSentencesDataset(input0, input1) + + with data_utils.numpy_seed(self.args.seed): + shuffle = np.random.permutation(len(src_tokens)) + + src_tokens = maybe_shorten_dataset( + src_tokens, + split, + self.args.shorten_data_split_list, + self.args.shorten_method, + self.max_positions(), + self.args.seed, + ) + + dataset = { + "id": IdDataset(), + "net_input": { + "src_tokens": RightPadDataset( + src_tokens, + pad_idx=self.source_dictionary.pad(), + ), + "src_lengths": NumelDataset(src_tokens, reduce=False), + }, + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(src_tokens, reduce=True), + } + + if self.args.add_prev_output_tokens: + prev_tokens_dataset = RightPadDataset( + RollDataset(src_tokens, 1), + pad_idx=self.dictionary.pad(), + ) + dataset["net_input"].update( + prev_output_tokens=prev_tokens_dataset, + ) + + if not self.args.regression_target: + label_dataset = make_dataset("label", self.label_dictionary) + if label_dataset is not None: + dataset.update( + target=OffsetTokensDataset( + StripTokenDataset( + label_dataset, + id_to_strip=self.label_dictionary.eos(), + ), + offset=-self.label_dictionary.nspecial, + ) + ) + else: + label_path = "{0}.label".format(get_path("label", split)) + if os.path.exists(label_path): + + def parse_regression_target(i, line): + values = line.split() + assert ( + len(values) == self.args.num_classes + ), f'expected num_classes={self.args.num_classes} regression target values on line {i}, found: "{line}"' + return [float(x) for x in values] + + with open(label_path) as h: + dataset.update( + target=RawLabelDataset( + [ + parse_regression_target(i, line.strip()) + for i, line in enumerate(h.readlines()) + ] + ) + ) + + nested_dataset = NestedDictionaryDataset( + dataset, + sizes=[src_tokens.sizes], + ) + + if self.args.no_shuffle: + dataset = nested_dataset + else: + dataset = SortDataset( + nested_dataset, + # shuffle + sort_order=[shuffle], + ) + + logger.info("Loaded {0} with #samples: {1}".format(split, len(dataset))) + + self.datasets[split] = dataset + return self.datasets[split] + + def build_model(self, args): + from fairseq import models + + model = models.build_model(args, self) + + model.register_classification_head( + getattr(args, "classification_head_name", "sentence_classification_head"), + num_classes=self.args.num_classes, + ) + + return model + + def max_positions(self): + return self._max_positions + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary + + @property + def label_dictionary(self): + return self._label_dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/sentence_ranking.py b/fairseq-tools/fairseq/fairseq/tasks/sentence_ranking.py new file mode 100644 index 00000000..bed44f34 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/sentence_ranking.py @@ -0,0 +1,219 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os + +import numpy as np +from fairseq import utils +from fairseq.data import ( + ConcatSentencesDataset, + Dictionary, + IdDataset, + NestedDictionaryDataset, + NumelDataset, + NumSamplesDataset, + PrependTokenDataset, + RawLabelDataset, + RightPadDataset, + SortDataset, + TruncateDataset, + data_utils, +) +from fairseq.data.shorten_dataset import maybe_shorten_dataset +from fairseq.tasks import LegacyFairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("sentence_ranking") +class SentenceRankingTask(LegacyFairseqTask): + """ + Ranking task on multiple sentences. + + Args: + dictionary (Dictionary): the dictionary for the input of the task + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + parser.add_argument("data", metavar="FILE", help="file prefix for data") + parser.add_argument( + "--num-classes", type=int, help="number of sentences to be ranked" + ) + parser.add_argument( + "--init-token", + type=int, + help="add token at the beginning of each batch item", + ) + parser.add_argument( + "--separator-token", type=int, help="add separator token between inputs" + ) + parser.add_argument("--no-shuffle", action="store_true") + parser.add_argument( + "--shorten-method", + default="none", + choices=["none", "truncate", "random_crop"], + help="if not none, shorten sequences that exceed --tokens-per-sample", + ) + parser.add_argument( + "--shorten-data-split-list", + default="", + help="comma-separated list of dataset splits to apply shortening to, " + 'e.g., "train,valid" (default: all dataset splits)', + ) + parser.add_argument( + "--max-option-length", type=int, help="max length for each option" + ) + + def __init__(self, args, dictionary): + super().__init__(args) + self.dictionary = dictionary + + @classmethod + def load_dictionary(cls, args, filename, source=True): + """Load the dictionary from the filename + + Args: + filename (str): the filename + """ + dictionary = Dictionary.load(filename) + dictionary.add_symbol("<mask>") + return dictionary + + @classmethod + def setup_task(cls, args, **kwargs): + assert ( + args.criterion == "sentence_ranking" + ), "Must set --criterion=sentence_ranking" + + # load data dictionary + data_dict = cls.load_dictionary( + args, + os.path.join(args.data, "input0", "dict.txt"), + source=True, + ) + logger.info("[input] dictionary: {} types".format(len(data_dict))) + return SentenceRankingTask(args, data_dict) + + def load_dataset(self, split, combine=False, **kwargs): + """Load a given dataset split (e.g., train, valid, test).""" + + def get_path(type, split): + return os.path.join(self.args.data, type, split) + + def make_dataset(type, dictionary): + split_path = get_path(type, split) + + dataset = data_utils.load_indexed_dataset( + split_path, + self.source_dictionary, + self.args.dataset_impl, + combine=combine, + ) + return dataset + + input0 = make_dataset("input0", self.source_dictionary) + input_options = [ + make_dataset("input{idx}".format(idx=idx + 1), self.source_dictionary) + for idx in range(self.args.num_classes) + ] + + if self.args.separator_token is not None: + input0 = PrependTokenDataset(input0, self.args.separator_token) + + src_tokens = [] + for input_option in input_options: + if self.args.init_token is not None: + input_option = PrependTokenDataset(input_option, self.args.init_token) + if self.args.max_option_length is not None: + input_option = TruncateDataset( + input_option, self.args.max_option_length + ) + src_token = ConcatSentencesDataset(input_option, input0) + src_token = maybe_shorten_dataset( + src_token, + split, + self.args.shorten_data_split_list, + self.args.shorten_method, + self.args.max_positions, + self.args.seed, + ) + src_tokens.append(src_token) + + with data_utils.numpy_seed(self.args.seed): + shuffle = np.random.permutation(len(src_tokens[0])) + + dataset = { + "id": IdDataset(), + "nsentences": NumSamplesDataset(), + "ntokens": NumelDataset(src_tokens[0], reduce=True), + } + + for src_token_idx in range(len(src_tokens)): + dataset.update( + { + "net_input{idx}".format(idx=src_token_idx + 1): { + "src_tokens": RightPadDataset( + src_tokens[src_token_idx], + pad_idx=self.source_dictionary.pad(), + ), + "src_lengths": NumelDataset( + src_tokens[src_token_idx], reduce=False + ), + } + } + ) + + label_path = "{}.label".format(get_path("label", split)) + if os.path.exists(label_path): + with open(label_path) as h: + dataset.update( + target=RawLabelDataset([int(x.strip()) for x in h.readlines()]) + ) + + nested_dataset = NestedDictionaryDataset( + dataset, + sizes=[np.maximum.reduce([src_token.sizes for src_token in src_tokens])], + ) + + if self.args.no_shuffle: + dataset = nested_dataset + else: + dataset = SortDataset( + nested_dataset, + # shuffle + sort_order=[shuffle], + ) + + logger.info("Loaded {0} with #samples: {1}".format(split, len(dataset))) + + self.datasets[split] = dataset + return self.datasets[split] + + def build_model(self, args): + from fairseq import models + + model = models.build_model(args, self) + + model.register_classification_head( + getattr(args, "ranking_head_name", "sentence_classification_head"), + num_classes=1, + ) + + return model + + def max_positions(self): + return self.args.max_positions + + @property + def source_dictionary(self): + return self.dictionary + + @property + def target_dictionary(self): + return self.dictionary diff --git a/fairseq-tools/fairseq/fairseq/tasks/speech_to_text.py b/fairseq-tools/fairseq/fairseq/tasks/speech_to_text.py new file mode 100644 index 00000000..c6280308 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/speech_to_text.py @@ -0,0 +1,143 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os.path as op +from argparse import Namespace + +from fairseq.data import Dictionary, encoders +from fairseq.data.audio.speech_to_text_dataset import ( + S2TDataConfig, + SpeechToTextDataset, + SpeechToTextDatasetCreator, +) +from fairseq.tasks import FairseqTask, register_task + + +logger = logging.getLogger(__name__) + + +@register_task("speech_to_text") +class SpeechToTextTask(FairseqTask): + @staticmethod + def add_args(parser): + parser.add_argument("data", help="manifest root path") + parser.add_argument( + "--config-yaml", + type=str, + default="config.yaml", + help="Configuration YAML filename (under manifest root)", + ) + parser.add_argument( + "--max-source-positions", + default=6000, + type=int, + metavar="N", + help="max number of tokens in the source sequence", + ) + parser.add_argument( + "--max-target-positions", + default=1024, + type=int, + metavar="N", + help="max number of tokens in the target sequence", + ) + + def __init__(self, args, tgt_dict): + super().__init__(args) + self.tgt_dict = tgt_dict + self.data_cfg = S2TDataConfig(op.join(args.data, args.config_yaml)) + + @classmethod + def setup_task(cls, args, **kwargs): + data_cfg = S2TDataConfig(op.join(args.data, args.config_yaml)) + dict_path = op.join(args.data, data_cfg.vocab_filename) + if not op.isfile(dict_path): + raise FileNotFoundError(f"Dict not found: {dict_path}") + tgt_dict = Dictionary.load(dict_path) + logger.info( + f"dictionary size ({data_cfg.vocab_filename}): " f"{len(tgt_dict):,}" + ) + + if getattr(args, "train_subset", None) is not None: + if not all(s.startswith("train") for s in args.train_subset.split(",")): + raise ValueError('Train splits should be named like "train*".') + return cls(args, tgt_dict) + + def build_criterion(self, args): + from fairseq import criterions + + if self.data_cfg.prepend_tgt_lang_tag and args.ignore_prefix_size != 1: + raise ValueError( + 'Please set "--ignore-prefix-size 1" since ' + "target language ID token is prepended as BOS." + ) + return criterions.build_criterion(args, self) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + is_train_split = split.startswith("train") + pre_tokenizer = self.build_tokenizer(self.args) + bpe_tokenizer = self.build_bpe(self.args) + self.datasets[split] = SpeechToTextDatasetCreator.from_tsv( + self.args.data, + self.data_cfg, + split, + self.tgt_dict, + pre_tokenizer, + bpe_tokenizer, + is_train_split=is_train_split, + epoch=epoch, + seed=self.args.seed, + ) + + @property + def target_dictionary(self): + return self.tgt_dict + + @property + def source_dictionary(self): + return None + + def max_positions(self): + return self.args.max_source_positions, self.args.max_target_positions + + def build_model(self, args): + args.input_feat_per_channel = self.data_cfg.input_feat_per_channel + args.input_channels = self.data_cfg.input_channels + return super(SpeechToTextTask, self).build_model(args) + + def build_generator( + self, + models, + args, + seq_gen_cls=None, + extra_gen_cls_kwargs=None, + ): + if self.data_cfg.prepend_tgt_lang_tag and args.prefix_size != 1: + raise ValueError( + 'Please set "--prefix-size 1" since ' + "target language ID token is prepended as BOS." + ) + lang_token_ids = { + i + for s, i in self.tgt_dict.indices.items() + if SpeechToTextDataset.is_lang_tag(s) + } + extra_gen_cls_kwargs = {"symbols_to_strip_from_output": lang_token_ids} + return super().build_generator( + models, args, seq_gen_cls=None, extra_gen_cls_kwargs=extra_gen_cls_kwargs + ) + + def build_tokenizer(self, args): + logger.info(f"pre-tokenizer: {self.data_cfg.pre_tokenizer}") + return encoders.build_tokenizer(Namespace(**self.data_cfg.pre_tokenizer)) + + def build_bpe(self, args): + logger.info(f"tokenizer: {self.data_cfg.bpe_tokenizer}") + return encoders.build_bpe(Namespace(**self.data_cfg.bpe_tokenizer)) + + @classmethod + def build_dataset_for_inference(cls, audio_paths, n_frames): + return SpeechToTextDataset("interactive", False, {}, audio_paths, n_frames) diff --git a/fairseq-tools/fairseq/fairseq/tasks/translation.py b/fairseq-tools/fairseq/fairseq/tasks/translation.py new file mode 100644 index 00000000..79007a6d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/translation.py @@ -0,0 +1,448 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import itertools +import json +import logging +import os +from argparse import Namespace + +import numpy as np +from fairseq import metrics, options, utils +from fairseq.data import ( + AppendTokenDataset, + ConcatDataset, + LanguagePairDataset, + PrependTokenDataset, + StripTokenDataset, + TruncateDataset, + data_utils, + encoders, + indexed_dataset, +) +from fairseq.tasks import LegacyFairseqTask, register_task + + +EVAL_BLEU_ORDER = 4 + + +logger = logging.getLogger(__name__) + + +def load_langpair_dataset( + data_path, + split, + src, + src_dict, + tgt, + tgt_dict, + combine, + dataset_impl, + upsample_primary, + left_pad_source, + left_pad_target, + max_source_positions, + max_target_positions, + prepend_bos=False, + load_alignments=False, + truncate_source=False, + append_source_id=False, + num_buckets=0, + shuffle=True, + pad_to_multiple=1, +): + def split_exists(split, src, tgt, lang, data_path): + filename = os.path.join(data_path, "{}.{}-{}.{}".format(split, src, tgt, lang)) + return indexed_dataset.dataset_exists(filename, impl=dataset_impl) + + src_datasets = [] + tgt_datasets = [] + + for k in itertools.count(): + split_k = split + (str(k) if k > 0 else "") + + # infer langcode + if split_exists(split_k, src, tgt, src, data_path): + prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, src, tgt)) + elif split_exists(split_k, tgt, src, src, data_path): + prefix = os.path.join(data_path, "{}.{}-{}.".format(split_k, tgt, src)) + else: + if k > 0: + break + else: + raise FileNotFoundError( + "Dataset not found: {} ({})".format(split, data_path) + ) + + src_dataset = data_utils.load_indexed_dataset( + prefix + src, src_dict, dataset_impl + ) + if truncate_source: + src_dataset = AppendTokenDataset( + TruncateDataset( + StripTokenDataset(src_dataset, src_dict.eos()), + max_source_positions - 1, + ), + src_dict.eos(), + ) + src_datasets.append(src_dataset) + + tgt_dataset = data_utils.load_indexed_dataset( + prefix + tgt, tgt_dict, dataset_impl + ) + if tgt_dataset is not None: + tgt_datasets.append(tgt_dataset) + + logger.info( + "{} {} {}-{} {} examples".format( + data_path, split_k, src, tgt, len(src_datasets[-1]) + ) + ) + + if not combine: + break + + assert len(src_datasets) == len(tgt_datasets) or len(tgt_datasets) == 0 + + if len(src_datasets) == 1: + src_dataset = src_datasets[0] + tgt_dataset = tgt_datasets[0] if len(tgt_datasets) > 0 else None + else: + sample_ratios = [1] * len(src_datasets) + sample_ratios[0] = upsample_primary + src_dataset = ConcatDataset(src_datasets, sample_ratios) + if len(tgt_datasets) > 0: + tgt_dataset = ConcatDataset(tgt_datasets, sample_ratios) + else: + tgt_dataset = None + + if prepend_bos: + assert hasattr(src_dict, "bos_index") and hasattr(tgt_dict, "bos_index") + src_dataset = PrependTokenDataset(src_dataset, src_dict.bos()) + if tgt_dataset is not None: + tgt_dataset = PrependTokenDataset(tgt_dataset, tgt_dict.bos()) + + eos = None + if append_source_id: + src_dataset = AppendTokenDataset( + src_dataset, src_dict.index("[{}]".format(src)) + ) + if tgt_dataset is not None: + tgt_dataset = AppendTokenDataset( + tgt_dataset, tgt_dict.index("[{}]".format(tgt)) + ) + eos = tgt_dict.index("[{}]".format(tgt)) + + align_dataset = None + if load_alignments: + align_path = os.path.join(data_path, "{}.align.{}-{}".format(split, src, tgt)) + if indexed_dataset.dataset_exists(align_path, impl=dataset_impl): + align_dataset = data_utils.load_indexed_dataset( + align_path, None, dataset_impl + ) + + tgt_dataset_sizes = tgt_dataset.sizes if tgt_dataset is not None else None + return LanguagePairDataset( + src_dataset, + src_dataset.sizes, + src_dict, + tgt_dataset, + tgt_dataset_sizes, + tgt_dict, + left_pad_source=left_pad_source, + left_pad_target=left_pad_target, + align_dataset=align_dataset, + eos=eos, + num_buckets=num_buckets, + shuffle=shuffle, + pad_to_multiple=pad_to_multiple, + ) + + +@register_task("translation") +class TranslationTask(LegacyFairseqTask): + """ + Translate from one (source) language to another (target) language. + + Args: + src_dict (~fairseq.data.Dictionary): dictionary for the source language + tgt_dict (~fairseq.data.Dictionary): dictionary for the target language + + .. note:: + + The translation task is compatible with :mod:`fairseq-train`, + :mod:`fairseq-generate` and :mod:`fairseq-interactive`. + + The translation task provides the following additional command-line + arguments: + + .. argparse:: + :ref: fairseq.tasks.translation_parser + :prog: + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + parser.add_argument('data', help='colon separated path to data directories list, \ + will be iterated upon during epochs in round-robin manner; \ + however, valid and test data are always in the first directory to \ + avoid the need for repeating them in all directories') + parser.add_argument('-s', '--source-lang', default=None, metavar='SRC', + help='source language') + parser.add_argument('-t', '--target-lang', default=None, metavar='TARGET', + help='target language') + parser.add_argument('--load-alignments', action='store_true', + help='load the binarized alignments') + parser.add_argument('--left-pad-source', default='True', type=str, metavar='BOOL', + help='pad the source on the left') + parser.add_argument('--left-pad-target', default='False', type=str, metavar='BOOL', + help='pad the target on the left') + parser.add_argument('--max-source-positions', default=1024, type=int, metavar='N', + help='max number of tokens in the source sequence') + parser.add_argument('--max-target-positions', default=1024, type=int, metavar='N', + help='max number of tokens in the target sequence') + parser.add_argument('--upsample-primary', default=1, type=int, + help='amount to upsample primary dataset') + parser.add_argument('--truncate-source', action='store_true', default=False, + help='truncate source to max-source-positions') + parser.add_argument('--num-batch-buckets', default=0, type=int, metavar='N', + help='if >0, then bucket source and target lengths into N ' + 'buckets and pad accordingly; this is useful on TPUs ' + 'to minimize the number of compilations') + + # options for reporting BLEU during validation + parser.add_argument('--eval-bleu', action='store_true', + help='evaluation with BLEU scores') + parser.add_argument('--eval-bleu-detok', type=str, default="space", + help='detokenize before computing BLEU (e.g., "moses"); ' + 'required if using --eval-bleu; use "space" to ' + 'disable detokenization; see fairseq.data.encoders ' + 'for other options') + parser.add_argument('--eval-bleu-detok-args', type=str, metavar='JSON', + help='args for building the tokenizer, if needed') + parser.add_argument('--eval-tokenized-bleu', action='store_true', default=False, + help='compute tokenized BLEU instead of sacrebleu') + parser.add_argument('--eval-bleu-remove-bpe', nargs='?', const='@@ ', default=None, + help='remove BPE before computing BLEU') + parser.add_argument('--eval-bleu-args', type=str, metavar='JSON', + help='generation args for BLUE scoring, ' + 'e.g., \'{"beam": 4, "lenpen": 0.6}\'') + parser.add_argument('--eval-bleu-print-samples', action='store_true', + help='print sample generations during validation') + # fmt: on + + def __init__(self, args, src_dict, tgt_dict): + super().__init__(args) + self.src_dict = src_dict + self.tgt_dict = tgt_dict + + @classmethod + def setup_task(cls, args, **kwargs): + """Setup the task (e.g., load dictionaries). + + Args: + args (argparse.Namespace): parsed command-line arguments + """ + args.left_pad_source = utils.eval_bool(args.left_pad_source) + args.left_pad_target = utils.eval_bool(args.left_pad_target) + + paths = utils.split_paths(args.data) + assert len(paths) > 0 + # find language pair automatically + if args.source_lang is None or args.target_lang is None: + args.source_lang, args.target_lang = data_utils.infer_language_pair( + paths[0] + ) + if args.source_lang is None or args.target_lang is None: + raise Exception( + "Could not infer language pair, please provide it explicitly" + ) + + # load dictionaries + src_dict = cls.load_dictionary( + os.path.join(paths[0], "dict.{}.txt".format(args.source_lang)) + ) + tgt_dict = cls.load_dictionary( + os.path.join(paths[0], "dict.{}.txt".format(args.target_lang)) + ) + assert src_dict.pad() == tgt_dict.pad() + assert src_dict.eos() == tgt_dict.eos() + assert src_dict.unk() == tgt_dict.unk() + logger.info("[{}] dictionary: {} types".format(args.source_lang, len(src_dict))) + logger.info("[{}] dictionary: {} types".format(args.target_lang, len(tgt_dict))) + + return cls(args, src_dict, tgt_dict) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + if split != getattr(self.args, "train_subset", None): + # if not training data set, use the first shard for valid and test + paths = paths[:1] + data_path = paths[(epoch - 1) % len(paths)] + + # infer langcode + src, tgt = self.args.source_lang, self.args.target_lang + + self.datasets[split] = load_langpair_dataset( + data_path, + split, + src, + self.src_dict, + tgt, + self.tgt_dict, + combine=combine, + dataset_impl=self.args.dataset_impl, + upsample_primary=self.args.upsample_primary, + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + max_source_positions=self.args.max_source_positions, + max_target_positions=self.args.max_target_positions, + load_alignments=self.args.load_alignments, + truncate_source=self.args.truncate_source, + num_buckets=self.args.num_batch_buckets, + shuffle=(split != "test"), + pad_to_multiple=self.args.required_seq_len_multiple, + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, constraints=None): + return LanguagePairDataset( + src_tokens, + src_lengths, + self.source_dictionary, + tgt_dict=self.target_dictionary, + constraints=constraints, + ) + + def build_model(self, args): + model = super().build_model(args) + if getattr(args, "eval_bleu", False): + assert getattr(args, "eval_bleu_detok", None) is not None, ( + "--eval-bleu-detok is required if using --eval-bleu; " + "try --eval-bleu-detok=moses (or --eval-bleu-detok=space " + "to disable detokenization, e.g., when using sentencepiece)" + ) + detok_args = json.loads(getattr(args, "eval_bleu_detok_args", "{}") or "{}") + self.tokenizer = encoders.build_tokenizer( + Namespace( + tokenizer=getattr(args, "eval_bleu_detok", None), **detok_args + ) + ) + + gen_args = json.loads(getattr(args, "eval_bleu_args", "{}") or "{}") + self.sequence_generator = self.build_generator( + [model], Namespace(**gen_args) + ) + return model + + def valid_step(self, sample, model, criterion): + loss, sample_size, logging_output = super().valid_step(sample, model, criterion) + if self.args.eval_bleu: + bleu = self._inference_with_bleu(self.sequence_generator, sample, model) + logging_output["_bleu_sys_len"] = bleu.sys_len + logging_output["_bleu_ref_len"] = bleu.ref_len + # we split counts into separate entries so that they can be + # summed efficiently across workers using fast-stat-sync + assert len(bleu.counts) == EVAL_BLEU_ORDER + for i in range(EVAL_BLEU_ORDER): + logging_output["_bleu_counts_" + str(i)] = bleu.counts[i] + logging_output["_bleu_totals_" + str(i)] = bleu.totals[i] + return loss, sample_size, logging_output + + def reduce_metrics(self, logging_outputs, criterion): + super().reduce_metrics(logging_outputs, criterion) + if self.args.eval_bleu: + + def sum_logs(key): + return sum(log.get(key, 0) for log in logging_outputs) + + counts, totals = [], [] + for i in range(EVAL_BLEU_ORDER): + counts.append(sum_logs("_bleu_counts_" + str(i))) + totals.append(sum_logs("_bleu_totals_" + str(i))) + + if max(totals) > 0: + # log counts as numpy arrays -- log_scalar will sum them correctly + metrics.log_scalar("_bleu_counts", np.array(counts)) + metrics.log_scalar("_bleu_totals", np.array(totals)) + metrics.log_scalar("_bleu_sys_len", sum_logs("_bleu_sys_len")) + metrics.log_scalar("_bleu_ref_len", sum_logs("_bleu_ref_len")) + + def compute_bleu(meters): + import inspect + import sacrebleu + + fn_sig = inspect.getfullargspec(sacrebleu.compute_bleu)[0] + if "smooth_method" in fn_sig: + smooth = {"smooth_method": "exp"} + else: + smooth = {"smooth": "exp"} + bleu = sacrebleu.compute_bleu( + correct=meters["_bleu_counts"].sum, + total=meters["_bleu_totals"].sum, + sys_len=meters["_bleu_sys_len"].sum, + ref_len=meters["_bleu_ref_len"].sum, + **smooth + ) + return round(bleu.score, 2) + + metrics.log_derived("bleu", compute_bleu) + + def max_positions(self): + """Return the max sentence length allowed by the task.""" + return (self.args.max_source_positions, self.args.max_target_positions) + + @property + def source_dictionary(self): + """Return the source :class:`~fairseq.data.Dictionary`.""" + return self.src_dict + + @property + def target_dictionary(self): + """Return the target :class:`~fairseq.data.Dictionary`.""" + return self.tgt_dict + + def _inference_with_bleu(self, generator, sample, model): + import sacrebleu + + def decode(toks, escape_unk=False): + s = self.tgt_dict.string( + toks.int().cpu(), + self.args.eval_bleu_remove_bpe, + # The default unknown string in fairseq is `<unk>`, but + # this is tokenized by sacrebleu as `< unk >`, inflating + # BLEU scores. Instead, we use a somewhat more verbose + # alternative that is unlikely to appear in the real + # reference, but doesn't get split into multiple tokens. + unk_string=("UNKNOWNTOKENINREF" if escape_unk else "UNKNOWNTOKENINHYP"), + ) + if self.tokenizer: + s = self.tokenizer.decode(s) + return s + + gen_out = self.inference_step(generator, [model], sample, prefix_tokens=None) + hyps, refs = [], [] + for i in range(len(gen_out)): + hyps.append(decode(gen_out[i][0]["tokens"])) + refs.append( + decode( + utils.strip_pad(sample["target"][i], self.tgt_dict.pad()), + escape_unk=True, # don't count <unk> as matches to the hypo + ) + ) + if self.args.eval_bleu_print_samples: + logger.info("example hypothesis: " + hyps[0]) + logger.info("example reference: " + refs[0]) + if self.args.eval_tokenized_bleu: + return sacrebleu.corpus_bleu(hyps, [refs], tokenize="none") + else: + return sacrebleu.corpus_bleu(hyps, [refs]) diff --git a/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_bart.py b/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_bart.py new file mode 100644 index 00000000..8710b7fe --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_bart.py @@ -0,0 +1,132 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import torch +from fairseq import utils +from fairseq.data import LanguagePairDataset + +from . import register_task +from .translation import TranslationTask, load_langpair_dataset + + +@register_task("translation_from_pretrained_bart") +class TranslationFromPretrainedBARTTask(TranslationTask): + """ + Translate from source language to target language with a model initialized with a multilingual pretrain. + + Args: + src_dict (~fairseq.data.Dictionary): dictionary for the source language + tgt_dict (~fairseq.data.Dictionary): dictionary for the target language + + .. note:: + + The translation task is compatible with :mod:`fairseq-train`, + :mod:`fairseq-generate` and :mod:`fairseq-interactive`. + + The translation task provides the following additional command-line + arguments: + + .. argparse:: + :ref: fairseq.tasks.translation_parser + :prog: + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + TranslationTask.add_args(parser) + parser.add_argument('--langs', required=True, metavar='LANG', + help='comma-separated list of monolingual language, ' + 'for example, "en,de,fr". These should match the ' + 'langs from pretraining (and be in the same order). ' + 'You should always add all pretraining language idx ' + 'during finetuning.') + parser.add_argument('--prepend-bos', action='store_true', + help='prepend bos token to each sentence, which matches ' + 'mBART pretraining') + # fmt: on + + def __init__(self, args, src_dict, tgt_dict): + super().__init__(args, src_dict, tgt_dict) + self.langs = args.langs.split(",") + for d in [src_dict, tgt_dict]: + for l in self.langs: + d.add_symbol("[{}]".format(l)) + d.add_symbol("<mask>") + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + # infer langcode + src, tgt = self.args.source_lang, self.args.target_lang + + self.datasets[split] = load_langpair_dataset( + data_path, + split, + src, + self.src_dict, + tgt, + self.tgt_dict, + combine=combine, + dataset_impl=self.args.dataset_impl, + upsample_primary=self.args.upsample_primary, + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + max_source_positions=getattr(self.args, "max_source_positions", 1024), + max_target_positions=getattr(self.args, "max_target_positions", 1024), + load_alignments=self.args.load_alignments, + prepend_bos=getattr(self.args, "prepend_bos", False), + append_source_id=True, + ) + + def build_generator(self, models, args, **unused): + if getattr(args, "score_reference", False): + from fairseq.sequence_scorer import SequenceScorer + + return SequenceScorer( + self.target_dictionary, + eos=self.tgt_dict.index("[{}]".format(self.args.target_lang)), + ) + else: + from fairseq.sequence_generator import SequenceGenerator + + return SequenceGenerator( + models, + self.target_dictionary, + beam_size=getattr(args, "beam", 5), + max_len_a=getattr(args, "max_len_a", 0), + max_len_b=getattr(args, "max_len_b", 200), + min_len=getattr(args, "min_len", 1), + normalize_scores=(not getattr(args, "unnormalized", False)), + len_penalty=getattr(args, "lenpen", 1), + unk_penalty=getattr(args, "unkpen", 0), + temperature=getattr(args, "temperature", 1.0), + match_source_len=getattr(args, "match_source_len", False), + no_repeat_ngram_size=getattr(args, "no_repeat_ngram_size", 0), + eos=self.tgt_dict.index("[{}]".format(self.args.target_lang)), + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, constraints=None): + src_lang_id = self.source_dictionary.index("[{}]".format(self.args.source_lang)) + source_tokens = [] + for s_t in src_tokens: + s_t = torch.cat([s_t, s_t.new(1).fill_(src_lang_id)]) + source_tokens.append(s_t) + dataset = LanguagePairDataset( + source_tokens, + src_lengths, + self.source_dictionary, + tgt_dict=self.target_dictionary, + constraints=constraints, + ) + return dataset diff --git a/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_xlm.py b/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_xlm.py new file mode 100644 index 00000000..347a6ecc --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/translation_from_pretrained_xlm.py @@ -0,0 +1,31 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from fairseq.data.legacy.masked_lm_dictionary import MaskedLMDictionary +from fairseq.tasks.translation import TranslationTask + +from . import register_task + + +@register_task("translation_from_pretrained_xlm") +class TranslationFromPretrainedXLMTask(TranslationTask): + """ + Same as TranslationTask except use the MaskedLMDictionary class so that + we can load data that was binarized with the MaskedLMDictionary class. + + This task should be used for the entire training pipeline when we want to + train an NMT model from a pretrained XLM checkpoint: binarizing NMT data, + training NMT with the pretrained XLM checkpoint, and subsequent evaluation + of that trained model. + """ + + @classmethod + def load_dictionary(cls, filename): + """Load the masked LM dictionary from the filename + + Args: + filename (str): the filename + """ + return MaskedLMDictionary.load(filename) diff --git a/fairseq-tools/fairseq/fairseq/tasks/translation_lev.py b/fairseq-tools/fairseq/fairseq/tasks/translation_lev.py new file mode 100644 index 00000000..46787749 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/translation_lev.py @@ -0,0 +1,189 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os + +import torch +from fairseq import utils +from fairseq.data import LanguagePairDataset +from fairseq.tasks import register_task +from fairseq.tasks.translation import TranslationTask, load_langpair_dataset +from fairseq.utils import new_arange + + +@register_task("translation_lev") +class TranslationLevenshteinTask(TranslationTask): + """ + Translation (Sequence Generation) task for Levenshtein Transformer + See `"Levenshtein Transformer" <https://arxiv.org/abs/1905.11006>`_. + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + TranslationTask.add_args(parser) + parser.add_argument( + '--noise', + default='random_delete', + choices=['random_delete', 'random_mask', 'no_noise', 'full_mask']) + # fmt: on + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + paths = utils.split_paths(self.args.data) + assert len(paths) > 0 + data_path = paths[(epoch - 1) % len(paths)] + + # infer langcode + src, tgt = self.args.source_lang, self.args.target_lang + + self.datasets[split] = load_langpair_dataset( + data_path, + split, + src, + self.src_dict, + tgt, + self.tgt_dict, + combine=combine, + dataset_impl=self.args.dataset_impl, + upsample_primary=self.args.upsample_primary, + left_pad_source=self.args.left_pad_source, + left_pad_target=self.args.left_pad_target, + max_source_positions=self.args.max_source_positions, + max_target_positions=self.args.max_target_positions, + prepend_bos=True, + ) + + def inject_noise(self, target_tokens): + def _random_delete(target_tokens): + pad = self.tgt_dict.pad() + bos = self.tgt_dict.bos() + eos = self.tgt_dict.eos() + + max_len = target_tokens.size(1) + target_mask = target_tokens.eq(pad) + target_score = target_tokens.clone().float().uniform_() + target_score.masked_fill_( + target_tokens.eq(bos) | target_tokens.eq(eos), 0.0 + ) + target_score.masked_fill_(target_mask, 1) + target_score, target_rank = target_score.sort(1) + target_length = target_mask.size(1) - target_mask.float().sum( + 1, keepdim=True + ) + + # do not delete <bos> and <eos> (we assign 0 score for them) + target_cutoff = ( + 2 + + ( + (target_length - 2) + * target_score.new_zeros(target_score.size(0), 1).uniform_() + ).long() + ) + target_cutoff = target_score.sort(1)[1] >= target_cutoff + + prev_target_tokens = ( + target_tokens.gather(1, target_rank) + .masked_fill_(target_cutoff, pad) + .gather(1, target_rank.masked_fill_(target_cutoff, max_len).sort(1)[1]) + ) + prev_target_tokens = prev_target_tokens[ + :, : prev_target_tokens.ne(pad).sum(1).max() + ] + + return prev_target_tokens + + def _random_mask(target_tokens): + pad = self.tgt_dict.pad() + bos = self.tgt_dict.bos() + eos = self.tgt_dict.eos() + unk = self.tgt_dict.unk() + + target_masks = ( + target_tokens.ne(pad) & target_tokens.ne(bos) & target_tokens.ne(eos) + ) + target_score = target_tokens.clone().float().uniform_() + target_score.masked_fill_(~target_masks, 2.0) + target_length = target_masks.sum(1).float() + target_length = target_length * target_length.clone().uniform_() + target_length = target_length + 1 # make sure to mask at least one token. + + _, target_rank = target_score.sort(1) + target_cutoff = new_arange(target_rank) < target_length[:, None].long() + prev_target_tokens = target_tokens.masked_fill( + target_cutoff.scatter(1, target_rank, target_cutoff), unk + ) + return prev_target_tokens + + def _full_mask(target_tokens): + pad = self.tgt_dict.pad() + bos = self.tgt_dict.bos() + eos = self.tgt_dict.eos() + unk = self.tgt_dict.unk() + + target_mask = ( + target_tokens.eq(bos) | target_tokens.eq(eos) | target_tokens.eq(pad) + ) + return target_tokens.masked_fill(~target_mask, unk) + + if self.args.noise == "random_delete": + return _random_delete(target_tokens) + elif self.args.noise == "random_mask": + return _random_mask(target_tokens) + elif self.args.noise == "full_mask": + return _full_mask(target_tokens) + elif self.args.noise == "no_noise": + return target_tokens + else: + raise NotImplementedError + + def build_generator(self, models, args, **unused): + # add models input to match the API for SequenceGenerator + from fairseq.iterative_refinement_generator import IterativeRefinementGenerator + + return IterativeRefinementGenerator( + self.target_dictionary, + eos_penalty=getattr(args, "iter_decode_eos_penalty", 0.0), + max_iter=getattr(args, "iter_decode_max_iter", 10), + beam_size=getattr(args, "iter_decode_with_beam", 1), + reranking=getattr(args, "iter_decode_with_external_reranker", False), + decoding_format=getattr(args, "decoding_format", None), + adaptive=not getattr(args, "iter_decode_force_max_iter", False), + retain_history=getattr(args, "retain_iter_history", False), + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, constraints=None): + if constraints is not None: + # Though see Susanto et al. (ACL 2020): https://www.aclweb.org/anthology/2020.acl-main.325/ + raise NotImplementedError( + "Constrained decoding with the translation_lev task is not supported" + ) + + return LanguagePairDataset( + src_tokens, src_lengths, self.source_dictionary, append_bos=True + ) + + def train_step( + self, sample, model, criterion, optimizer, update_num, ignore_grad=False + ): + model.train() + sample["prev_target"] = self.inject_noise(sample["target"]) + loss, sample_size, logging_output = criterion(model, sample) + if ignore_grad: + loss *= 0 + optimizer.backward(loss) + return loss, sample_size, logging_output + + def valid_step(self, sample, model, criterion): + model.eval() + with torch.no_grad(): + sample["prev_target"] = self.inject_noise(sample["target"]) + loss, sample_size, logging_output = criterion(model, sample) + return loss, sample_size, logging_output diff --git a/fairseq-tools/fairseq/fairseq/tasks/translation_multi_simple_epoch.py b/fairseq-tools/fairseq/fairseq/tasks/translation_multi_simple_epoch.py new file mode 100644 index 00000000..95a2d162 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tasks/translation_multi_simple_epoch.py @@ -0,0 +1,414 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import datetime +import logging +import time + +import torch +from fairseq.data import ( + FairseqDataset, + LanguagePairDataset, + ListDataset, + data_utils, + iterators, +) +from fairseq.data.multilingual.multilingual_data_manager import ( + MultilingualDatasetManager, +) +from fairseq.data.multilingual.sampling_method import SamplingMethod +from fairseq.tasks import LegacyFairseqTask, register_task +from fairseq.utils import FileContentsAction + + +### +def get_time_gap(s, e): + return ( + datetime.datetime.fromtimestamp(e) - datetime.datetime.fromtimestamp(s) + ).__str__() + + +### + + +logger = logging.getLogger(__name__) + + +@register_task("translation_multi_simple_epoch") +class TranslationMultiSimpleEpochTask(LegacyFairseqTask): + """ + Translate from one (source) language to another (target) language. + + Args: + langs (List[str]): a list of languages that are being supported + dicts (Dict[str, fairseq.data.Dictionary]): mapping from supported languages to their dictionaries + training (bool): whether the task should be configured for training or not + + .. note:: + + The translation task is compatible with :mod:`fairseq-train`, + :mod:`fairseq-generate` and :mod:`fairseq-interactive`. + + The translation task provides the following additional command-line + arguments: + + .. argparse:: + :ref: fairseq.tasks.translation_parser + :prog: + """ + + @staticmethod + def add_args(parser): + """Add task-specific arguments to the parser.""" + # fmt: off + parser.add_argument('-s', '--source-lang', default=None, metavar='SRC', + help='inference source language') + parser.add_argument('-t', '--target-lang', default=None, metavar='TARGET', + help='inference target language') + parser.add_argument('--lang-pairs', default=None, metavar='PAIRS', + help='comma-separated list of language pairs (in training order): en-de,en-fr,de-fr', + action=FileContentsAction) + parser.add_argument('--keep-inference-langtok', action='store_true', + help='keep language tokens in inference output (e.g. for analysis or debugging)') + + SamplingMethod.add_arguments(parser) + MultilingualDatasetManager.add_args(parser) + # fmt: on + + def __init__(self, args, langs, dicts, training): + super().__init__(args) + self.langs = langs + self.dicts = dicts + self.training = training + if training: + self.lang_pairs = args.lang_pairs + else: + self.lang_pairs = ["{}-{}".format(args.source_lang, args.target_lang)] + # eval_lang_pairs for multilingual translation is usually all of the + # lang_pairs. However for other multitask settings or when we want to + # optimize for certain languages we want to use a different subset. Thus + # the eval_lang_pairs class variable is provided for classes that extend + # this class. + self.eval_lang_pairs = self.lang_pairs + # model_lang_pairs will be used to build encoder-decoder model pairs in + # models.build_model(). This allows multitask type of sub-class can + # build models other than the input lang_pairs + self.model_lang_pairs = self.lang_pairs + self.sampling_method = SamplingMethod.build_sampler(args, self) + self.data_manager = MultilingualDatasetManager.setup_data_manager( + args, self.lang_pairs, langs, dicts, self.sampling_method + ) + + @classmethod + def setup_task(cls, args, **kwargs): + langs, dicts, training = MultilingualDatasetManager.prepare( + cls.load_dictionary, args, **kwargs + ) + dict0 = None + for _, lang_dict in dicts.items(): + if dict0 is None: + dict0 = lang_dict + else: + assert ( + dict0 == lang_dict + ), "Diffrent dictionary are specified for different languages; " + "TranslationMultiSimpleEpochTask only supports one shared dictionary across all languages" + return cls(args, langs, dicts, training) + + def has_sharded_data(self, split): + return self.data_manager.has_sharded_data(split) + + def load_dataset(self, split, epoch=1, combine=False, **kwargs): + """Load a given dataset split. + + Args: + split (str): name of the split (e.g., train, valid, test) + """ + if split in self.datasets: + dataset = self.datasets[split] + if self.has_sharded_data(split) and dataset.load_next_shard: + shard_epoch = dataset.shard_epoch + else: + # no need to load next shard so skip loading + # also this avoid always loading from beginning of the data + return + else: + # estimate the shard epoch from virtual data size and virtual epoch size + shard_epoch = self.data_manager.estimate_global_pass_epoch(epoch) + logger.info(f"loading data for {split} epoch={epoch}/{shard_epoch}") + logger.info(f"mem usage: {data_utils.get_mem_usage()}") + if split in self.datasets: + del self.datasets[split] + logger.info("old dataset deleted manually") + logger.info(f"mem usage: {data_utils.get_mem_usage()}") + self.datasets[split] = self.data_manager.load_sampled_multi_epoch_dataset( + split, + self.training, + epoch=epoch, + combine=combine, + shard_epoch=shard_epoch, + **kwargs, + ) + + def build_dataset_for_inference(self, src_tokens, src_lengths, constraints=None): + if constraints is not None: + raise NotImplementedError( + "Constrained decoding with the multilingual_translation task is not supported" + ) + + src_data = ListDataset(src_tokens, src_lengths) + dataset = LanguagePairDataset(src_data, src_lengths, self.source_dictionary) + src_langtok_spec, tgt_langtok_spec = self.args.langtoks["main"] + if self.args.lang_tok_replacing_bos_eos: + dataset = self.data_manager.alter_dataset_langtok( + dataset, + src_eos=self.source_dictionary.eos(), + src_lang=self.args.source_lang, + tgt_eos=self.target_dictionary.eos(), + tgt_lang=self.args.target_lang, + src_langtok_spec=src_langtok_spec, + tgt_langtok_spec=tgt_langtok_spec, + ) + else: + dataset.src = self.data_manager.src_dataset_tranform_func( + self.args.source_lang, + self.args.target_lang, + dataset=dataset.src, + spec=src_langtok_spec, + ) + return dataset + + def build_generator( + self, + models, + args, + seq_gen_cls=None, + extra_gen_cls_kwargs=None, + ): + if not getattr(args, "keep_inference_langtok", False): + _, tgt_langtok_spec = self.args.langtoks["main"] + if tgt_langtok_spec: + tgt_lang_tok = self.data_manager.get_decoder_langtok( + self.args.target_lang, tgt_langtok_spec + ) + extra_gen_cls_kwargs = extra_gen_cls_kwargs or {} + extra_gen_cls_kwargs["symbols_to_strip_from_output"] = {tgt_lang_tok} + + return super().build_generator( + models, args, seq_gen_cls=None, extra_gen_cls_kwargs=extra_gen_cls_kwargs + ) + + def build_model(self, args): + return super().build_model(args) + + def valid_step(self, sample, model, criterion): + loss, sample_size, logging_output = super().valid_step(sample, model, criterion) + return loss, sample_size, logging_output + + def inference_step( + self, generator, models, sample, prefix_tokens=None, constraints=None + ): + with torch.no_grad(): + _, tgt_langtok_spec = self.args.langtoks["main"] + if not self.args.lang_tok_replacing_bos_eos: + if prefix_tokens is None and tgt_langtok_spec: + tgt_lang_tok = self.data_manager.get_decoder_langtok( + self.args.target_lang, tgt_langtok_spec + ) + src_tokens = sample["net_input"]["src_tokens"] + bsz = src_tokens.size(0) + prefix_tokens = ( + torch.LongTensor([[tgt_lang_tok]]).expand(bsz, 1).to(src_tokens) + ) + return generator.generate( + models, + sample, + prefix_tokens=prefix_tokens, + constraints=constraints, + ) + else: + return generator.generate( + models, + sample, + prefix_tokens=prefix_tokens, + bos_token=self.data_manager.get_decoder_langtok( + self.args.target_lang, tgt_langtok_spec + ) + if tgt_langtok_spec + else self.target_dictionary.eos(), + ) + + def reduce_metrics(self, logging_outputs, criterion): + super().reduce_metrics(logging_outputs, criterion) + + def max_positions(self): + """Return the max sentence length allowed by the task.""" + return (self.args.max_source_positions, self.args.max_target_positions) + + @property + def source_dictionary(self): + return next(iter(self.dicts.values())) + + @property + def target_dictionary(self): + return next(iter(self.dicts.values())) + + def create_batch_sampler_func( + self, + max_positions, + ignore_invalid_inputs, + max_tokens, + max_sentences, + required_batch_size_multiple=1, + seed=1, + ): + def construct_batch_sampler(dataset, epoch): + splits = [ + s for s, _ in self.datasets.items() if self.datasets[s] == dataset + ] + split = splits[0] if len(splits) > 0 else None + # NEW implementation + if epoch is not None: + # initialize the dataset with the correct starting epoch + dataset.set_epoch(epoch) + + # get indices ordered by example size + start_time = time.time() + logger.info(f"start batch sampler: mem usage: {data_utils.get_mem_usage()}") + + with data_utils.numpy_seed(seed): + indices = dataset.ordered_indices() + logger.info( + f"[{split}] @batch_sampler order indices time: {get_time_gap(start_time, time.time())}" + ) + logger.info(f"mem usage: {data_utils.get_mem_usage()}") + + # filter examples that are too large + if max_positions is not None: + my_time = time.time() + indices = self.filter_indices_by_size( + indices, dataset, max_positions, ignore_invalid_inputs + ) + logger.info( + f"[{split}] @batch_sampler filter_by_size time: {get_time_gap(my_time, time.time())}" + ) + logger.info(f"mem usage: {data_utils.get_mem_usage()}") + + # create mini-batches with given size constraints + my_time = time.time() + batch_sampler = dataset.batch_by_size( + indices, + max_tokens=max_tokens, + max_sentences=max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + ) + + logger.info( + f"[{split}] @batch_sampler batch_by_size time: {get_time_gap(my_time, time.time())}" + ) + logger.info( + f"[{split}] per epoch batch_sampler set-up time: {get_time_gap(start_time, time.time())}" + ) + logger.info(f"mem usage: {data_utils.get_mem_usage()}") + + return batch_sampler + + return construct_batch_sampler + + # we need to override get_batch_iterator because we want to reset the epoch iterator each time + def get_batch_iterator( + self, + dataset, + max_tokens=None, + max_sentences=None, + max_positions=None, + ignore_invalid_inputs=False, + required_batch_size_multiple=1, + seed=1, + num_shards=1, + shard_id=0, + num_workers=0, + epoch=1, + data_buffer_size=0, + disable_iterator_cache=False, + ): + """ + Get an iterator that yields batches of data from the given dataset. + + Args: + dataset (~fairseq.data.FairseqDataset): dataset to batch + max_tokens (int, optional): max number of tokens in each batch + (default: None). + max_sentences (int, optional): max number of sentences in each + batch (default: None). + max_positions (optional): max sentence length supported by the + model (default: None). + ignore_invalid_inputs (bool, optional): don't raise Exception for + sentences that are too long (default: False). + required_batch_size_multiple (int, optional): require batch size to + be a multiple of N (default: 1). + seed (int, optional): seed for random number generator for + reproducibility (default: 1). + num_shards (int, optional): shard the data iterator into N + shards (default: 1). + shard_id (int, optional): which shard of the data iterator to + return (default: 0). + num_workers (int, optional): how many subprocesses to use for data + loading. 0 means the data will be loaded in the main process + (default: 0). + epoch (int, optional): the epoch to start the iterator from + (default: 0). + data_buffer_size (int, optional): number of batches to + preload (default: 0). + disable_iterator_cache (bool, optional): don't cache the + EpochBatchIterator (ignores `FairseqTask::can_reuse_epoch_itr`) + (default: False). + Returns: + ~fairseq.iterators.EpochBatchIterator: a batched iterator over the + given dataset split + """ + # initialize the dataset with the correct starting epoch + assert isinstance(dataset, FairseqDataset) + if dataset in self.dataset_to_epoch_iter: + return self.dataset_to_epoch_iter[dataset] + if self.args.sampling_method == "RoundRobin": + batch_iter = super().get_batch_iterator( + dataset, + max_tokens=max_tokens, + max_sentences=max_sentences, + max_positions=max_positions, + ignore_invalid_inputs=ignore_invalid_inputs, + required_batch_size_multiple=required_batch_size_multiple, + seed=seed, + num_shards=num_shards, + shard_id=shard_id, + num_workers=num_workers, + epoch=epoch, + data_buffer_size=data_buffer_size, + disable_iterator_cache=disable_iterator_cache, + ) + self.dataset_to_epoch_iter[dataset] = batch_iter + return batch_iter + + construct_batch_sampler = self.create_batch_sampler_func( + max_positions, + ignore_invalid_inputs, + max_tokens, + max_sentences, + required_batch_size_multiple=required_batch_size_multiple, + seed=seed, + ) + + epoch_iter = iterators.EpochBatchIterator( + dataset=dataset, + collate_fn=dataset.collater, + batch_sampler=construct_batch_sampler, + seed=seed, + num_shards=num_shards, + shard_id=shard_id, + num_workers=num_workers, + epoch=epoch, + ) + return epoch_iter diff --git a/fairseq-tools/fairseq/fairseq/token_generation_constraints.py b/fairseq-tools/fairseq/fairseq/token_generation_constraints.py new file mode 100644 index 00000000..e708dc51 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/token_generation_constraints.py @@ -0,0 +1,506 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +"""Implements tracking of constraints for a beam item. + +A list of constraints is given as a list of one or more token +sequences, each of length at least one token. For example, for an input sentence + +> Die maschinelle Übersetzung ist schwer zu kontrollieren. + +We could have the constraints: +* to influence +* hard + +There are two implementations: +* OrderedConstraintState: Tracks progress through an ordered list of multitoken constraints. +* UnorderedConstraintState: Tracks progress through an unordered list of multitoken constraints. + +The difference is that in the first, the constraints are assumed to be +in order; the algorithm will permit zero or more tokens between them. +In the second, the constraints are not ordered, so many orderings will +be explored. + +The same sequence can be present any number of times, and will appear +that many times in the output. +""" + +from collections import Counter +from typing import List, Optional, Set, Tuple + +import torch + + +class ConstraintState: + def __init__(self): + pass + + +def pack_constraints(batch_constraints: List[List[torch.Tensor]]) -> torch.Tensor: + """Takes a list of list of constraints in tensor form (a list of + tensor constraints for each sentence) and transforms it into a + packed Tensor. For example, here is a batch of size 3 with 3, 0, + and 1 constraints: + + [ [ [3 1 2], [3], [4 5 6 7], ] + [], + [ [1 8 9 10 1 4 11 12], ] + ] + + Its corresponding packed structure is: + + [ [ 3 3 1 2 0 3 0 4 5 6 7 0], + [ 0 0 0 0 0 0 0 0 0 0 0 0], + [ 1 1 8 9 10 1 4 11 12 0 0 0] ] + + The packed tensor has shape (batch size, maxlen), where + maxlen is defined below. Each row contains concatenated + constraint tokens for that sentence, with 0 appended after + each constraint. The first item in each row is the number + of constraints for that sentence. So maxlen is the maximum + of + + (number of constraints) + (sum length of constraints) + 1. + + across all sentences in the batch. + """ + # The maximum word length of concatenated constraints for any sentence + max_constraints_len = 1 + for sentence_constraints in batch_constraints: + if len(sentence_constraints): + # number of constraints, plus sum of constrain lens, plus a zero after each + constraints_len = ( + 1 + + sum([c.size(0) for c in sentence_constraints]) + + len(sentence_constraints) + ) + max_constraints_len = max(max_constraints_len, constraints_len) + + batch_size = len(batch_constraints) + constraints_tensor = torch.zeros((batch_size, max_constraints_len)).long() + for i, sentence_constraints in enumerate(batch_constraints): + constraints_tensor[i, 0] = len(sentence_constraints) + offset = 1 + for j, constraint in enumerate(sentence_constraints): + this_len = constraint.size(0) + constraints_tensor[i, offset : offset + this_len] = constraint + offset += this_len + 1 + + return constraints_tensor.long() + + +def unpack_constraints(constraint_tensor: torch.Tensor) -> List[torch.Tensor]: + """ + Transforms *one row* of a packed constraint tensor (e.g., for one + sentence in the batch) into a list of constraint tensors. + """ + constraint_list = [] + num_constraints = constraint_tensor[0] + constraints = constraint_tensor.tolist() + offset = 1 + for i in range(num_constraints): + where = constraints.index(0, offset) + constraint_list.append(constraint_tensor[offset:where]) + offset = where + 1 + + return constraint_list + + +class ConstraintNode: + """ + Represents a node in a trie managing unordered constraints. + """ + + def __init__(self, token: int = None, parent=None): + # The token associate with this node (None for the root) + self.token = int(token) if token is not None else None + # The parent (None at the root) + self.parent = parent + # Whether this node is a completed constraint + self.terminal = 0 + # List of child nodes + self.children = {} + + # The cumulative number of constraints from this point in the + # trie forward + self.num_constraints = 0 + + @property + def id(self): + return self.token + + def __str__(self): + term = self.terminal != 0 + return f"[{self.token}].{term}#{self.num_constraints}" + + def __getitem__(self, key: int): + return self.children.get(key, None) + + def next_tokens(self) -> Set[int]: + """The set of child labels.""" + return set(self.children.keys()) + + @staticmethod + def create(constraints: List[List[int]]): + root = ConstraintNode() + for sequence in constraints: + root.add_sequence(sequence) + + return root + + @staticmethod + def print_graph(node: "ConstraintNode"): + if len(node.children) == 0: + return str(node) + else: + s = f"({node}" + for child in node.children.values(): + s += " " + ConstraintNode.print_graph(child) + s += ")" + return s + + def token_counts(self) -> Counter: + """Returns a counter of the number of times each token is used + in a constraint. + """ + token_counts = Counter() + kids = list(self.children.values()) + while len(kids) > 0: + kid = kids.pop() + token_counts[kid.id] += kid.num_constraints + kids += list(kid.children.values()) + + return token_counts + + def tokens(self) -> Set[int]: + """Returns the set of tokens in constraints.""" + return set(self.token_counts().keys()) + + def add_sequence(self, sequence: List[int]): + """Adds a constraint, represented as a list of integers, to + the trie.""" + assert len(sequence) > 0 + + token = int(sequence[0]) + if token not in self.children: + self.children[token] = ConstraintNode(token, parent=self) + + node = self.children[token] + if len(sequence) == 1: + node.terminal += 1 + node.num_constraints += 1 + parent = node.parent + while parent is not None: + parent.num_constraints += 1 + parent = parent.parent + else: + node.add_sequence(sequence[1:]) + + +class UnorderedConstraintState(ConstraintState): + """ + Records progress through the set of constraints for each item in the beam + using a trie. + """ + + def __init__(self, node: ConstraintNode, copy_from: "ConstraintState" = None): + self.node = node + + if copy_from is None: + # The root node + self.root = node + # The set of states in the graph that have been completed + self.completed = Counter() + # The... + self.generated = Counter() + # The list of tokens we need to generate + self.needed_tokens = self.root.tokens() + else: + self.completed = Counter(copy_from.completed) + self.generated = Counter(copy_from.generated) + self.root = copy_from.root + + # Mark the node as generated + if self.node != self.root: + self.generated[node] += 1 + + @staticmethod + def create(constraint_tensor: torch.Tensor): + constraint_list = unpack_constraints(constraint_tensor) + constraint_trie_root = ConstraintNode.create(constraint_list) + return UnorderedConstraintState(constraint_trie_root) + + def __str__(self): + gen_str = ",".join([str(node) for node in self.generated]) + return f"{self.name}/{self.bank}({gen_str})x{self.num_completed}" + + def __copy__(self): + copied_state = UnorderedConstraintState(self.node, copy_from=self) + return copied_state + + def copy(self): + return self.__copy__() + + @property + def name(self): + if self.node.id is None: + return "ROOT" + else: + return str(self.node.id) + + @property + def is_root(self): + return self.node == self.root + + @property + def bank(self): + return sum(self.generated.values()) + + @property + def num_completed(self): + """The number of constraints (not constraint tokens) that are completed. + In addition to the already-completed states, we need to account for the + current state, which might get marked as completed when another token + is generated. + """ + in_final = self.node.terminal and self.completed[self.node] < self.node.terminal + return sum(self.completed.values()) + in_final + + @property + def finished(self): + return self.root.num_constraints - self.num_completed == 0 + + @property + def token_counts(self): + return self.root.token_counts() + + @property + def tokens(self): + return self.root.tokens() + + @property + def num_constraint_tokens(self): + return sum(self.token_counts.values()) + + def next_tokens(self) -> Set[int]: + """Returns the list of tokens that could come next. + These are (a) all tokens extending the root state and, for + non-root states, additionally all tokens extending the current + state.""" + + if self.node != self.root: + return self.root.next_tokens().union(self.node.next_tokens()) + else: + return self.root.next_tokens() + + def advance(self, token: int): + """Reads in a token and advances the state. Here's how it works. + + We can advance to the next state if: + - there is a matching child + - its path isn't blocked + + A path is blocked when all constraints that are descendants of + that node have already been generated, in the current state. + + If we are not able to advance from the current state, we "fall + off the graph" and return to the root state. There, we again + try to advance, checking the same criteria. + + In any case, when falling off the graph, we need to do some + bookkeeping. We: + - check whether any constraints were met (all prefixes of + current state) + - if one is found, mark it as completed + - adjust visited nodes accordingly + """ + token = int(token) + + next_state = None + child = self.node[token] + if child is not None and self.generated[child] < child.num_constraints: + next_state = UnorderedConstraintState(child, copy_from=self) + + def rewind(): + """If we're mid-trie and an "illegal" token is chosen next, we need + to reset our state to the root state. However, along the way, we need + to check whether a prefix of the current trie state represents a state + we could mark as completed. + """ + node = self.node + while node != self.root: + if node.terminal and self.completed[node] < node.terminal: + next_state.completed[node] += 1 + return + + next_state.generated[node] -= 1 + node = node.parent + + # Fall off the graph, check the root + if next_state is None and token in self.root.next_tokens(): + child = self.root[token] + # We can only traverse this edge if it's not saturated + if self.generated[child] < child.num_constraints: + next_state = UnorderedConstraintState(child, copy_from=self) + else: + next_state = UnorderedConstraintState(self.root, copy_from=self) + + # Rewind + rewind() + + elif next_state is None: + next_state = UnorderedConstraintState(self.root, copy_from=self) + # Rewind + rewind() + + return next_state + + +class ConstraintSequence: + def __init__(self, sequences: List[List[int]]): + """Represents a set of possibly multitoken constraints by + concatenating them and internally recording the end points. + """ + self.sequences = [] + self.endpoints = [] + self.num_tokens = 0 + self.tokens = set() + for sequence in sequences: + for token in sequence: + self.tokens.add(token) + self.num_tokens += len(sequence) + self.endpoints += [False for x in range(len(sequence) - 1)] + [True] + self.sequences += sequence + + def __getitem__(self, key: int): + return self.sequences[key] + + def __len__(self): + return len(self.sequences) + + def __str__(self): + return str(self.sequences) + + +class OrderedConstraintState(ConstraintState): + """ + Records progress through the set of linear nonbranching constraints with gaps. + """ + + def __init__(self, sequence: ConstraintSequence, state: int = -1): + self.sequence = sequence + self.state = state + + @staticmethod + def create(constraint_tensor: torch.Tensor): + constraint_list = unpack_constraints(constraint_tensor) + return OrderedConstraintState(ConstraintSequence(constraint_list), -1) + + def __str__(self): + return f"{self.state}/{self.bank}x{self.num_completed}" + + def __copy__(self): + return OrderedConstraintState(self.sequence, self.state) + + def copy(self): + return self.__copy__() + + @property + def num_completed(self): + if self.state == -1: + return 0 + count = len( + list(filter(lambda x: x, self.sequence.endpoints[0 : self.state + 1])) + ) + return count + + @property + def is_root(self): + return self.state == -1 + + @property + def name(self): + if self.state == -1: + return "ROOT" + else: + return str(self.sequence[self.state]) + + @property + def bank(self) -> int: + return self.state + 1 + + @property + def finished(self): + return self.state + 1 == len(self.sequence) + + @property + def token_counts(self): + return self.sequence.token_counts() + + @property + def tokens(self): + return self.sequence.tokens + + @property + def num_constraint_tokens(self): + return sum(self.token_counts.values()) + + def next_tokens(self) -> Set[int]: + """Returns the list of tokens that could come next. + These are (a) all tokens extending the root state and, for + non-root states, additionally all tokens extending the current + state.""" + + tokens = set() + if self.state > 0: + tokens.add(self.sequence[0]) + if not self.finished: + tokens.add(self.sequence[self.state + 1]) + return tokens + + def advance(self, token: int): + """Reads in a token and advances the state. Here's how it works. + + We can advance to the next state if: + - there is a matching child + - its path isn't blocked + + A path is blocked when all constraints that are descendants of + that node have already been generated, in the current state. + + If we are not able to advance from the current state, we "fall + off the graph" and return to the root state. There, we again + try to advance, checking the same criteria. + + In any case, when falling off the graph, we need to do some + bookkeeping. We: + - check whether any constraints were met (all prefixes of + current state) + - if one is found, mark it as completed + - adjust visited nodes accordingly + """ + token = int(token) + # print(f"{self} ADVANCE({token}) {self.sequence} -> ", end="") + + if self.finished: + # Accept anything + next_state = self.copy() + + elif self.sequence[self.state + 1] == token: + # Advance to the next token + next_state = OrderedConstraintState(self.sequence, self.state + 1) + + elif self.sequence.endpoints[self.state]: + # Accept anything between constraints (*) + next_state = self.copy() + + elif token == self.sequence[0]: + # Start over having generated the first token + next_state = OrderedConstraintState(self.sequence, 0) + else: + # Start over from the root + next_state = OrderedConstraintState(self.sequence, -1) + + return next_state diff --git a/fairseq-tools/fairseq/fairseq/tokenizer.py b/fairseq-tools/fairseq/fairseq/tokenizer.py new file mode 100644 index 00000000..42131f7b --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/tokenizer.py @@ -0,0 +1,15 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import re + + +SPACE_NORMALIZER = re.compile(r"\s+") + + +def tokenize_line(line): + line = SPACE_NORMALIZER.sub(" ", line) + line = line.strip() + return line.split() diff --git a/fairseq-tools/fairseq/fairseq/trainer.py b/fairseq-tools/fairseq/fairseq/trainer.py new file mode 100644 index 00000000..8e423d25 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/trainer.py @@ -0,0 +1,1141 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. + +""" +Train a network across multiple GPUs. +""" + +import contextlib +import logging +import sys +import time +from itertools import chain +from typing import Any, Dict, List + +import torch +from fairseq import checkpoint_utils, distributed_utils, models, optim, utils +from fairseq.file_io import PathManager +from fairseq.logging import meters, metrics +from fairseq.nan_detector import NanDetector +from fairseq.optim import lr_scheduler + + +logger = logging.getLogger(__name__) + + +class Trainer(object): + """Main class for data parallel training. + + This class supports synchronous distributed data parallel training, + where multiple workers each have a full model replica and gradients + are accumulated across workers before each update. We use + :class:`~torch.nn.parallel.DistributedDataParallel` to handle + communication of the gradients across workers. + """ + + def __init__(self, args, task, model, criterion, quantizer=None): + self.args = args + self.task = task + + # catalog shared parameters + shared_params = _catalog_shared_params(model) + + self.tpu = getattr(args, "tpu", False) + self.cuda = torch.cuda.is_available() and not args.cpu and not self.tpu + if self.cuda: + self.device = torch.device("cuda") + elif self.tpu: + self.device = utils.get_tpu_device(args) + else: + self.device = torch.device("cpu") + + # copy model and criterion to current device/dtype + self._criterion = criterion + self._model = model + if self.tpu: + import torch_xla.core.xla_model as xm + + self._model = xm.send_cpu_data_to_device(self._model, self.device) + if args.fp16: + self._criterion = self._criterion.half() + self._model = self._model.half() + elif args.bf16: + self._criterion = self._criterion.to(dtype=torch.bfloat16) + self._model = self._model.to(dtype=torch.bfloat16) + if not args.pipeline_model_parallel: + self._criterion = self._criterion.to(device=self.device) + self._model = self._model.to(device=self.device) + self.pipeline_model_parallel = args.pipeline_model_parallel + self.last_device = None + if self.cuda and self.pipeline_model_parallel: + self.last_device = torch.device(args.pipeline_devices[-1]) + + # check that shared parameters are preserved after device transfer + for shared_param in shared_params: + ref = _get_module_by_path(self._model, shared_param[0]) + for path in shared_param[1:]: + logger.info( + "detected shared parameter: {} <- {}".format(shared_param[0], path) + ) + _set_module_by_path(self._model, path, ref) + + self._dummy_batch = None # indicates we don't have a dummy batch at first + self._lr_scheduler = None + self._num_updates = 0 + self._num_xla_compiles = 0 # for TPUs + self._optim_history = None + self._optimizer = None + self._warn_once = set() + self._wrapped_criterion = None + self._wrapped_model = None + + # TODO(myleott): support tpu + if self.cuda and self.data_parallel_world_size > 1: + self._grad_norm_buf = torch.cuda.FloatTensor(self.data_parallel_world_size) + else: + self._grad_norm_buf = None + + self.quantizer = quantizer + if self.quantizer is not None: + self.quantizer.set_trainer(self) + + # get detailed cuda environment + if self.cuda: + self.cuda_env = utils.CudaEnvironment() + if self.data_parallel_world_size > 1: + self.cuda_env_arr = distributed_utils.all_gather_list(self.cuda_env) + else: + self.cuda_env_arr = [self.cuda_env] + if self.data_parallel_rank == 0: + utils.CudaEnvironment.pretty_print_cuda_env_list(self.cuda_env_arr) + else: + self.cuda_env = None + self.cuda_env_arr = None + + metrics.log_start_time("wall", priority=790, round=0) + + self._start_time = time.time() + self._previous_training_time = 0 + self._cumulative_training_time = None + + def reinitialize(self): + """Reinitialize the Trainer, typically after model params change.""" + self._lr_scheduler = None + self._optimizer = None + self._wrapped_criterion = None + self._wrapped_model = None + + @property + def data_parallel_world_size(self): + return self.args.distributed_world_size + + @property + def data_parallel_process_group(self): + if self.tpu: + return ("tpu", None) + else: + return None + + @property + def data_parallel_rank(self): + return self.args.distributed_rank + + @property + def is_data_parallel_master(self): + return distributed_utils.is_master(self.args) + + @property + def criterion(self): + if self._wrapped_criterion is None: + if ( + utils.has_parameters(self._criterion) + and self.data_parallel_world_size > 1 + and not self.args.use_bmuf + and not self.tpu + ): + self._wrapped_criterion = models.DistributedFairseqModel( + self.args, + self._criterion, + process_group=self.data_parallel_process_group, + ) + else: + self._wrapped_criterion = self._criterion + return self._wrapped_criterion + + @property + def model(self): + if self._wrapped_model is None: + if ( + self.data_parallel_world_size > 1 + and not self.args.use_bmuf + and not self.tpu + ): + self._wrapped_model = models.DistributedFairseqModel( + self.args, + self._model, + process_group=self.data_parallel_process_group, + ) + else: + self._wrapped_model = self._model + return self._wrapped_model + + @property + def optimizer(self): + if self._optimizer is None: + self._build_optimizer() + return self._optimizer + + @property + def lr_scheduler(self): + if self._lr_scheduler is None: + self._build_optimizer() # this will initialize self._lr_scheduler + return self._lr_scheduler + + def _build_optimizer(self): + params = list( + filter( + lambda p: p.requires_grad, + chain(self.model.parameters(), self.criterion.parameters()), + ) + ) + + if self.args.fp16 or self.args.bf16: + if self.cuda and torch.cuda.get_device_capability(0)[0] < 7: + logger.info( + "NOTE: your device does NOT support faster training with --fp16, " + "please switch to FP32 which is likely to be faster" + ) + if self.args.memory_efficient_fp16 or self.args.memory_efficient_bf16: + self._optimizer = optim.MemoryEfficientFP16Optimizer.build_optimizer( + self.args, params + ) + else: + self._optimizer = optim.FP16Optimizer.build_optimizer(self.args, params) + else: + if self.cuda and torch.cuda.get_device_capability(0)[0] >= 7: + logger.info("NOTE: your device may support faster training with --fp16") + self._optimizer = optim.build_optimizer(self.args, params) + + if self.args.use_bmuf: + self._optimizer = optim.FairseqBMUF(self.args, self._optimizer) + + if self.args.zero_sharding == "os": + if ( + self.args.fp16 + and not self.args.memory_efficient_fp16 + and not self.args.memory_efficient_bf16 + ) and not self.args.fp16_no_flatten_grads: + raise ValueError( + "ZeRO is incomptabile with fp16 and flattened grads. " + "Please use --fp16-no-flatten-grads" + ) + else: + optim.shard_( + self.args, self._optimizer, self.data_parallel_process_group + ) + + # We should initialize the learning rate scheduler immediately after + # building the optimizer, so that the initial learning rate is set. + self._lr_scheduler = lr_scheduler.build_lr_scheduler(self.args, self.optimizer) + self._lr_scheduler.step_update(0) + + def consolidate_optimizer(self): + """For OSS, we need to consolidate the state dict.""" + if hasattr(self.optimizer.optimizer, "consolidate_state_dict"): + self.optimizer.optimizer.consolidate_state_dict() + + def save_checkpoint(self, filename, extra_state): + """Save all training state in a checkpoint file.""" + if self.is_data_parallel_master: # only save one checkpoint + extra_state["metrics"] = metrics.state_dict() + extra_state["previous_training_time"] = self.cumulative_training_time() + checkpoint_utils.save_state( + filename, + self.args, + self.get_model().state_dict(), + self.get_criterion(), + self.optimizer, + self.lr_scheduler, + self.get_num_updates(), + self._optim_history, + extra_state, + ) + + def load_checkpoint( + self, + filename, + reset_optimizer=False, + reset_lr_scheduler=False, + optimizer_overrides=None, + reset_meters=False, + ): + """Load all training state from a checkpoint file.""" + extra_state, self._optim_history, last_optim_state = None, [], None + + bexists = PathManager.isfile(filename) + if bexists: + state = checkpoint_utils.load_checkpoint_to_cpu(filename) + + # load model parameters + try: + self.get_model().load_state_dict( + state["model"], strict=True, args=self.args + ) + if utils.has_parameters(self.get_criterion()): + self.get_criterion().load_state_dict( + state["criterion"], strict=True + ) + except Exception: + raise Exception( + "Cannot load model parameters from checkpoint {}; " + "please ensure that the architectures match.".format(filename) + ) + + extra_state = state["extra_state"] + self._optim_history = state["optimizer_history"] + last_optim_state = state.get("last_optimizer_state", None) + + if last_optim_state is not None and not reset_optimizer: + # rebuild optimizer after loading model, since params may have changed + self._build_optimizer() + + # only reload optimizer and lr_scheduler if they match + last_optim = self._optim_history[-1] + assert ( + last_optim["criterion_name"] == self.get_criterion().__class__.__name__ + ), "Criterion does not match; please reset the optimizer (--reset-optimizer)." + assert ( + last_optim["optimizer_name"] == self.optimizer.__class__.__name__ + ), "Optimizer does not match; please reset the optimizer (--reset-optimizer)." + + if not reset_lr_scheduler: + self.lr_scheduler.load_state_dict(last_optim["lr_scheduler_state"]) + self.optimizer.load_state_dict(last_optim_state, optimizer_overrides) + + self.set_num_updates(last_optim["num_updates"]) + + if extra_state is not None: + epoch = extra_state["train_iterator"]["epoch"] + logger.info( + "loaded checkpoint {} (epoch {} @ {} updates)".format( + filename, epoch, self.get_num_updates() + ) + ) + + if "previous_training_time" in extra_state: + self._previous_training_time = extra_state["previous_training_time"] + self._start_time = time.time() + + self.lr_step(epoch) + + if "metrics" in extra_state and not reset_meters: + metrics.load_state_dict(extra_state["metrics"]) + + # reset TimeMeters, since their start times don't make sense anymore + for meter in metrics.get_meters("default"): + if isinstance(meter, meters.TimeMeter): + meter.reset() + else: + logger.info("no existing checkpoint found {}".format(filename)) + + return extra_state + + def get_train_iterator( + self, + epoch, + combine=True, + load_dataset=True, + data_selector=None, + shard_batch_itr=True, + disable_iterator_cache=False, + ): + """Return an EpochBatchIterator over the training set for a given epoch.""" + if load_dataset: + logger.info("loading train data for epoch {}".format(epoch)) + self.task.load_dataset( + self.args.train_subset, + epoch=epoch, + combine=combine, + data_selector=data_selector, + ) + batch_iterator = self.task.get_batch_iterator( + dataset=self.task.dataset(self.args.train_subset), + max_tokens=self.args.max_tokens, + max_sentences=self.args.batch_size, + max_positions=utils.resolve_max_positions( + self.task.max_positions(), + self.model.max_positions(), + self.args.max_tokens, + ), + ignore_invalid_inputs=True, + required_batch_size_multiple=self.args.required_batch_size_multiple, + seed=self.args.seed, + num_shards=self.data_parallel_world_size if shard_batch_itr else 1, + shard_id=self.data_parallel_rank if shard_batch_itr else 0, + num_workers=self.args.num_workers, + epoch=epoch, + data_buffer_size=self.args.data_buffer_size, + disable_iterator_cache=disable_iterator_cache, + ) + self.reset_dummy_batch(batch_iterator.first_batch) + return batch_iterator + + def get_valid_iterator( + self, + subset, + disable_iterator_cache=False, + ): + """Return an EpochBatchIterator over given validation subset for a given epoch.""" + batch_iterator = self.task.get_batch_iterator( + dataset=self.task.dataset(subset), + max_tokens=self.args.max_tokens_valid, + max_sentences=self.args.batch_size_valid, + max_positions=utils.resolve_max_positions( + self.task.max_positions(), + self.model.max_positions(), + ), + ignore_invalid_inputs=self.args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=self.args.required_batch_size_multiple, + seed=self.args.seed, + num_shards=self.data_parallel_world_size, + shard_id=self.data_parallel_rank, + num_workers=self.args.num_workers, + data_buffer_size=self.args.data_buffer_size, + disable_iterator_cache=disable_iterator_cache, + ) + self.reset_dummy_batch(batch_iterator.first_batch) + return batch_iterator + + def begin_epoch(self, epoch): + """Called at the beginning of each epoch.""" + logger.info("begin training epoch {}".format(epoch)) + + self.lr_step_begin_epoch(epoch) + + if self.quantizer is not None: + self.quantizer.begin_epoch(epoch) + + # task specific setup per epoch + self.task.begin_epoch(epoch, self.get_model()) + + if self.tpu: + import torch_xla.core.xla_model as xm + + xm.rendezvous("begin_epoch") # wait for all workers + xm.mark_step() + + def begin_valid_epoch(self, epoch): + """Called at the beginning of each validation epoch.""" + + # task specific setup per validation epoch + self.task.begin_valid_epoch(epoch, self.get_model()) + + def reset_dummy_batch(self, batch): + self._dummy_batch = batch + + @metrics.aggregate("train") + def train_step(self, samples, raise_oom=False): + """Do forward, backward and parameter update.""" + self._set_seed() + self.model.train() + self.criterion.train() + self.zero_grad() + + metrics.log_start_time("train_wall", priority=800, round=0) + + # forward and backward pass + logging_outputs, sample_size, ooms = [], 0, 0 + for i, sample in enumerate(samples): + sample = self._prepare_sample(sample) + if sample is None: + # when sample is None, run forward/backward on a dummy batch + # and ignore the resulting gradients + sample = self._prepare_sample(self._dummy_batch) + is_dummy_batch = True + else: + if self._dummy_batch == "DUMMY": + self._dummy_batch = sample + is_dummy_batch = False + + def maybe_no_sync(): + """ + Whenever *samples* contains more than one mini-batch, we + want to accumulate gradients locally and only call + all-reduce in the last backwards pass. + """ + if ( + self.data_parallel_world_size > 1 + and hasattr(self.model, "no_sync") + and i < len(samples) - 1 + ): + return self.model.no_sync() + else: + return contextlib.ExitStack() # dummy contextmanager + + try: + with maybe_no_sync(): + # forward and backward + loss, sample_size_i, logging_output = self.task.train_step( + sample=sample, + model=self.model, + criterion=self.criterion, + optimizer=self.optimizer, + update_num=self.get_num_updates(), + ignore_grad=is_dummy_batch, + ) + del loss + + logging_outputs.append(logging_output) + sample_size += sample_size_i + + # emptying the CUDA cache after the first step can + # reduce the chance of OOM + if self.cuda and self.get_num_updates() == 0: + torch.cuda.empty_cache() + except RuntimeError as e: + if "out of memory" in str(e): + self._log_oom(e) + if raise_oom: + raise e + logger.warning( + "attempting to recover from OOM in forward/backward pass" + ) + ooms += 1 + self.zero_grad() + if self.cuda: + torch.cuda.empty_cache() + if self.args.distributed_world_size == 1: + return None + else: + raise e + + if self.tpu and i < len(samples) - 1: + # tpu-comment: every XLA operation before marking step is + # appended to the IR graph, and processing too many batches + # before marking step can lead to OOM errors. + # To handle gradient accumulation use case, we explicitly + # mark step here for every forward pass without a backward pass + import torch_xla.core.xla_model as xm + + xm.mark_step() + + if is_dummy_batch: + if torch.is_tensor(sample_size): + sample_size.zero_() + else: + sample_size *= 0.0 + + if torch.is_tensor(sample_size): + sample_size = sample_size.float() + else: + sample_size = float(sample_size) + + # gather logging outputs from all replicas + if self._sync_stats(): + train_time = self._local_cumulative_training_time() + logging_outputs, ( + sample_size, + ooms, + total_train_time, + ) = self._aggregate_logging_outputs( + logging_outputs, + sample_size, + ooms, + train_time, + ignore=is_dummy_batch, + ) + self._cumulative_training_time = ( + total_train_time / self.data_parallel_world_size + ) + + if hasattr(self.model, "all_reduce"): + self.model.all_reduce() + + overflow = False + try: + if self.tpu and self.data_parallel_world_size > 1: + import torch_xla.core.xla_model as xm + + gradients = xm._fetch_gradients(self.optimizer.optimizer) + xm.all_reduce( + "sum", gradients, scale=1.0 / self.data_parallel_world_size + ) + + with torch.autograd.profiler.record_function("multiply-grads"): + # multiply gradients by (# GPUs / sample_size) since DDP + # already normalizes by the number of GPUs. Thus we get + # (sum_of_gradients / sample_size). + if not self.args.use_bmuf: + self.optimizer.multiply_grads( + self.data_parallel_world_size / sample_size + ) + elif sample_size > 0: # BMUF needs to check sample size + num = self.data_parallel_world_size if self._sync_stats() else 1 + self.optimizer.multiply_grads(num / sample_size) + + with torch.autograd.profiler.record_function("clip-grads"): + # clip grads + grad_norm = self.clip_grad_norm(self.args.clip_norm) + + # check that grad norms are consistent across workers + # on tpu check tensor is slow + if not self.tpu: + if ( + not self.args.use_bmuf + and self.args.distributed_wrapper != "SlowMo" + ): + self._check_grad_norms(grad_norm) + if not torch.isfinite(grad_norm).all(): + # check local gradnorm single GPU case, trigger NanDetector + raise FloatingPointError("gradients are Nan/Inf") + + with torch.autograd.profiler.record_function("optimizer"): + # take an optimization step + self.optimizer.step() + + except FloatingPointError: + # re-run the forward and backward pass with hooks attached to print + # out where it fails + with NanDetector(self.get_model()): + self.task.train_step( + sample, + self.model, + self.criterion, + self.optimizer, + self.get_num_updates(), + ignore_grad=False, + ) + raise + except OverflowError as e: + overflow = True + logger.info("NOTE: overflow detected, " + str(e)) + grad_norm = torch.tensor(0.0).cuda() + self.zero_grad() + except RuntimeError as e: + if "out of memory" in str(e): + self._log_oom(e) + logger.error("OOM during optimization, irrecoverable") + raise e + + # Some distributed wrappers (e.g., SlowMo) need access to the optimizer after the step + if hasattr(self.model, "perform_additional_optimizer_actions"): + if hasattr(self.optimizer, "fp32_params"): + self.model.perform_additional_optimizer_actions( + self.optimizer.optimizer, self.optimizer.fp32_params + ) + else: + self.model.perform_additional_optimizer_actions( + self.optimizer.optimizer + ) + + if not overflow or self.args.distributed_wrapper == "SlowMo": + self.set_num_updates(self.get_num_updates() + 1) + + if self.tpu: + # mark step on TPUs + import torch_xla.core.xla_model as xm + + xm.mark_step() + + # only log stats every log_interval steps + # this causes wps to be misreported when log_interval > 1 + logging_output = {} + if self.get_num_updates() % self.args.log_interval == 0: + # log memory usage + mem_info = xm.get_memory_info(self.device) + gb_free = mem_info["kb_free"] / 1024 / 1024 + gb_total = mem_info["kb_total"] / 1024 / 1024 + metrics.log_scalar( + "gb_free", + gb_free, + priority=1500, + round=1, + weight=0, + ) + metrics.log_scalar( + "gb_total", + gb_total, + priority=1600, + round=1, + weight=0, + ) + + logging_output = self._reduce_and_log_stats( + logging_outputs, + sample_size, + grad_norm, + ) + + # log whenever there's an XLA compilation, since these + # slow down training and may indicate opportunities for + # optimization + self._check_xla_compilation() + else: + # log stats + logging_output = self._reduce_and_log_stats( + logging_outputs, + sample_size, + grad_norm, + ) + + # clear CUDA cache to reduce memory fragmentation + if ( + self.cuda + and self.args.empty_cache_freq > 0 + and ( + (self.get_num_updates() + self.args.empty_cache_freq - 1) + % self.args.empty_cache_freq + ) + == 0 + ): + torch.cuda.empty_cache() + + if self.args.fp16: + metrics.log_scalar( + "loss_scale", + self.optimizer.scaler.loss_scale, + priority=700, + round=4, + weight=0, + ) + + metrics.log_stop_time("train_wall") + return logging_output + + @metrics.aggregate("valid") + def valid_step(self, sample, raise_oom=False): + """Do forward pass in evaluation mode.""" + if self.tpu: + import torch_xla.core.xla_model as xm + + xm.rendezvous("valid_step") # wait for all workers + xm.mark_step() + + with torch.no_grad(): + self.model.eval() + self.criterion.eval() + + sample = self._prepare_sample(sample) + if sample is None: + sample = self._prepare_sample(self._dummy_batch) + is_dummy_batch = True + else: + if self._dummy_batch == "DUMMY": + self._dummy_batch = sample + is_dummy_batch = False + + try: + _loss, sample_size, logging_output = self.task.valid_step( + sample, self.model, self.criterion + ) + except RuntimeError as e: + if "out of memory" in str(e): + self._log_oom(e) + if not raise_oom: + logger.warning( + "ran out of memory in validation step, retrying batch" + ) + for p in self.model.parameters(): + if p.grad is not None: + p.grad = None # free some memory + if self.cuda: + torch.cuda.empty_cache() + return self.valid_step(sample, raise_oom=True) + raise e + + logging_outputs = [logging_output] + if is_dummy_batch: + if torch.is_tensor(sample_size): + sample_size.zero_() + else: + sample_size *= 0.0 + + # gather logging outputs from all replicas + if self.data_parallel_world_size > 1: + logging_outputs, (sample_size,) = self._aggregate_logging_outputs( + logging_outputs, + sample_size, + ignore=is_dummy_batch, + ) + + # log validation stats + logging_output = self._reduce_and_log_stats(logging_outputs, sample_size) + + return logging_output + + def zero_grad(self): + self.optimizer.zero_grad() + + def lr_step_begin_epoch(self, epoch): + """Adjust the learning rate at the beginning of the epoch.""" + self.lr_scheduler.step_begin_epoch(epoch) + # prefer updating the LR based on the number of steps + return self.lr_step_update() + + def lr_step(self, epoch, val_loss=None): + """Adjust the learning rate at the end of the epoch.""" + self.lr_scheduler.step(epoch, val_loss) + # prefer updating the LR based on the number of steps + return self.lr_step_update() + + def lr_step_update(self): + """Update the learning rate after each update.""" + new_lr = self.lr_scheduler.step_update(self.get_num_updates()) + metrics.log_scalar("lr", new_lr, weight=0, priority=300) + return new_lr + + def get_lr(self): + """Get the current learning rate.""" + return self.optimizer.get_lr() + + def get_model(self): + """Get the (non-wrapped) model instance.""" + return self._model + + def get_criterion(self): + """Get the (non-wrapped) criterion instance.""" + return self._criterion + + def get_meter(self, name): + """[deprecated] Get a specific meter by name.""" + from fairseq import meters + + if "get_meter" not in self._warn_once: + self._warn_once.add("get_meter") + utils.deprecation_warning( + "Trainer.get_meter is deprecated. Please use fairseq.metrics instead." + ) + + train_meters = metrics.get_meters("train") + if train_meters is None: + train_meters = {} + + if name == "train_loss" and "loss" in train_meters: + return train_meters["loss"] + elif name == "train_nll_loss": + # support for legacy train.py, which assumed this meter is + # always initialized + m = train_meters.get("nll_loss", None) + return m or meters.AverageMeter() + elif name == "wall": + # support for legacy train.py, which assumed this meter is + # always initialized + m = metrics.get_meter("default", "wall") + return m or meters.TimeMeter() + elif name == "wps": + m = metrics.get_meter("train", "wps") + return m or meters.TimeMeter() + elif name in {"valid_loss", "valid_nll_loss"}: + # support for legacy train.py, which assumed these meters + # are always initialized + k = name[len("valid_") :] + m = metrics.get_meter("valid", k) + return m or meters.AverageMeter() + elif name == "oom": + return meters.AverageMeter() + elif name in train_meters: + return train_meters[name] + return None + + def get_num_updates(self): + """Get the number of parameters updates.""" + return self._num_updates + + def set_num_updates(self, num_updates): + """Set the number of parameters updates.""" + self._num_updates = num_updates + self.lr_step_update() + if self.quantizer: + self.quantizer.step_update(self._num_updates) + metrics.log_scalar("num_updates", self._num_updates, weight=0, priority=200) + + def clip_grad_norm(self, clip_norm): + return self.optimizer.clip_grad_norm(clip_norm, aggregate_norm_fn=None) + + def cumulative_training_time(self): + if self._cumulative_training_time is None: + # single GPU + return self._local_cumulative_training_time() + else: + return self._cumulative_training_time + + def _local_cumulative_training_time(self): + """Aggregate training time in seconds.""" + return time.time() - self._start_time + self._previous_training_time + + def _prepare_sample(self, sample): + if sample == "DUMMY": + raise Exception( + "Trying to use an uninitialized 'dummy' batch. This usually indicates " + "that the total number of batches is smaller than the number of " + "participating GPUs. Try reducing the batch size or using fewer GPUs." + ) + + if sample is None or len(sample) == 0: + return None + + if self.cuda: + if self.pipeline_model_parallel: + if "target" in sample: + sample["target"] = utils.move_to_cuda( + sample["target"], device=self.last_device + ) + else: + sample = utils.move_to_cuda(sample) + + def apply_half(t): + if t.dtype is torch.float32: + return t.half() + return t + + def apply_bfloat16(t): + if t.dtype is torch.float32: + return t.to(dtype=torch.bfloat16) + return t + + if self.args.fp16: + sample = utils.apply_to_sample(apply_half, sample) + + if self.args.bf16: + sample = utils.apply_to_sample(apply_bfloat16, sample) + + return sample + + def _set_seed(self): + # Set seed based on args.seed and the update number so that we get + # reproducible results when resuming from checkpoints + seed = self.args.seed + self.get_num_updates() + utils.set_torch_seed(seed) + + def _sync_stats(self): + # Return True if it's using multiple GPUs and DDP or multiple GPUs with + # BMUF and it's a bmuf sync with warmup iterations completed before. + if self.data_parallel_world_size == 1: + return False + elif self.args.use_bmuf: + return (self.get_num_updates() + 1) % self.args.global_sync_iter == 0 and ( + self.get_num_updates() + 1 + ) > self.args.warmup_iterations + else: + return True + + def _log_oom(self, exc): + msg = "OOM: Ran out of memory with exception: {}".format(exc) + logger.warning(msg) + if torch.cuda.is_available() and hasattr(torch.cuda, "memory_summary"): + for device_idx in range(torch.cuda.device_count()): + logger.warning(torch.cuda.memory_summary(device=device_idx)) + sys.stderr.flush() + + def _aggregate_logging_outputs( + self, + logging_outputs: List[Dict[str, Any]], + *extra_stats_to_sum, + ignore=False, + ): + if self.task.__class__.logging_outputs_can_be_summed(self.get_criterion()): + return self._fast_stat_sync_sum( + logging_outputs, *extra_stats_to_sum, ignore=ignore + ) + else: + return self._all_gather_list_sync( + logging_outputs, *extra_stats_to_sum, ignore=ignore + ) + + def _all_gather_list_sync( + self, + logging_outputs: List[Dict[str, Any]], + *extra_stats_to_sum, + ignore=False, + ): + """ + Sync logging outputs across workers. all_gather_list_sync is + suitable when logging outputs are complex types. + """ + if self.tpu: + raise NotImplementedError + if ignore: + logging_outputs = [] + results = list( + zip( + *distributed_utils.all_gather_list( + [logging_outputs] + list(extra_stats_to_sum), + max_size=getattr(self.args, "all_gather_list_size", 16384), + group=self.data_parallel_process_group, + ) + ) + ) + logging_outputs, extra_stats_to_sum = results[0], results[1:] + logging_outputs = list(chain.from_iterable(logging_outputs)) + extra_stats_to_sum = [sum(s) for s in extra_stats_to_sum] + return logging_outputs, extra_stats_to_sum + + def _fast_stat_sync_sum( + self, + logging_outputs: List[Dict[str, Any]], + *extra_stats_to_sum, + ignore=False, + ): + """ + Sync logging outputs across workers. fast_stat_sync_sum is + faster than all_gather_list_sync, but is only suitable when + logging outputs are scalars and can be summed. Note that + *logging_outputs* cannot contain any nested dicts/lists. + """ + data = {} + for i, stat in enumerate(extra_stats_to_sum): + data["extra_stats_" + str(i)] = stat + if len(logging_outputs) > 0: + log_keys = list(logging_outputs[0].keys()) + for k in log_keys: + if not ignore: + v = sum(log[k] for log in logging_outputs if k in log) + else: + v = logging_outputs[0][k] + v = torch.zeros_like(v) if torch.is_tensor(v) else 0 + data["logging_outputs_" + k] = v + else: + log_keys = None + + data = distributed_utils.all_reduce_dict( + data, device=self.device, group=self.data_parallel_process_group + ) + + extra_stats_to_sum = [ + data["extra_stats_" + str(i)] for i in range(len(extra_stats_to_sum)) + ] + if log_keys is not None: + logging_outputs = [{k: data["logging_outputs_" + k] for k in log_keys}] + else: + logging_outputs = [] + return logging_outputs, extra_stats_to_sum + + def _check_grad_norms(self, grad_norm): + """Check that grad norms are consistent across workers.""" + if self._grad_norm_buf is not None: + self._grad_norm_buf.zero_() + self._grad_norm_buf[self.data_parallel_rank] = grad_norm + distributed_utils.all_reduce( + self._grad_norm_buf, group=self.data_parallel_process_group + ) + + def is_consistent(tensor): + max_abs_diff = torch.max(torch.abs(tensor - tensor[0])) + return ( + torch.isfinite(tensor).all() + or (max_abs_diff / (tensor[0] + 1e-6) < 1e-6).all() + ) + + if not is_consistent(self._grad_norm_buf): + pretty_detail = "\n".join( + "rank {:3d} = {:.8f}".format(r, n) + for r, n in enumerate(self._grad_norm_buf.tolist()) + ) + error_detail = "grad_norm across the workers:\n{}\n".format( + pretty_detail + ) + # use FloatingPointError to trigger NanDetector + raise FloatingPointError( + "Fatal error: gradients are inconsistent between workers. " + "Try --ddp-backend=no_c10d. " + "Or are you mixing up different generation of GPUs in training?" + + "\n" + + "-" * 80 + + "\n{}\n".format(error_detail) + + "-" * 80 + ) + + def _reduce_and_log_stats(self, logging_outputs, sample_size, grad_norm=None): + if grad_norm is not None: + metrics.log_speed("ups", 1.0, priority=100, round=2) + metrics.log_scalar("gnorm", grad_norm, priority=400, round=3) + if self.args.clip_norm > 0: + metrics.log_scalar( + "clip", + torch.where( + grad_norm > self.args.clip_norm, + grad_norm.new_tensor(100), + grad_norm.new_tensor(0), + ), + priority=500, + round=1, + ) + + with metrics.aggregate() as agg: + if logging_outputs is not None: + self.task.reduce_metrics(logging_outputs, self.get_criterion()) + del logging_outputs + + # extra warning for criterions that don't properly log a loss value + if "loss" not in agg: + if "loss" not in self._warn_once: + self._warn_once.add("loss") + logger.warning( + "Criterion.reduce_metrics did not log a 'loss' value, " + "which may break some functionality" + ) + metrics.log_scalar("loss", -1) + + # support legacy interface + if self.tpu: + logging_output = {} + else: + logging_output = agg.get_smoothed_values() + logging_output["sample_size"] = sample_size + for key_to_delete in ["ppl", "wps", "wpb", "bsz"]: + if key_to_delete in logging_output: + del logging_output[key_to_delete] + return logging_output + + def _check_xla_compilation(self): + import torch_xla.debug.metrics as met + + compile_stats = met.metric_data("CompileTime") + if compile_stats is None: + return + num_xla_compiles = compile_stats[0] + if num_xla_compiles > self._num_xla_compiles: + logger.warning( + "XLA compilation detected on device #{}; too many of these can lead " + "to slow training, but we expect a few in the beginning".format( + self.args.distributed_rank + ) + ) + self._num_xla_compiles = num_xla_compiles + + +def _catalog_shared_params(module, memo=None, prefix=""): + if memo is None: + first_call = True + memo = {} + else: + first_call = False + for name, param in module._parameters.items(): + param_prefix = prefix + ("." if prefix else "") + name + if param not in memo: + memo[param] = [] + memo[param].append(param_prefix) + for name, m in module._modules.items(): + if m is None: + continue + submodule_prefix = prefix + ("." if prefix else "") + name + _catalog_shared_params(m, memo, submodule_prefix) + if first_call: + return [x for x in memo.values() if len(x) > 1] + + +def _get_module_by_path(module, path): + path = path.split(".") + for name in path: + module = getattr(module, name) + return module + + +def _set_module_by_path(module, path, value): + path = path.split(".") + for name in path[:-1]: + module = getattr(module, name) + setattr(module, path[-1], value) diff --git a/fairseq-tools/fairseq/fairseq/utils.py b/fairseq-tools/fairseq/fairseq/utils.py new file mode 100644 index 00000000..8ea8a757 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq/utils.py @@ -0,0 +1,701 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import contextlib +import copy +import importlib +import logging +import os +import sys +import tempfile +import warnings +from itertools import accumulate +from typing import Callable, Dict, List, Optional + +import torch +import torch.nn.functional as F +from fairseq.data import iterators +from fairseq.file_io import PathManager +from fairseq.logging.meters import safe_round +from fairseq.modules import gelu, gelu_accurate +from fairseq.modules.multihead_attention import MultiheadAttention +from torch import Tensor + + +try: + from amp_C import multi_tensor_l2norm + + multi_tensor_l2norm_available = True +except ImportError: + multi_tensor_l2norm_available = False + + +logger = logging.getLogger(__name__) + + +MANIFOLD_PATH_SEP = "|" + + +class FileContentsAction(argparse.Action): + def __init__(self, option_strings, dest, nargs=None, **kwargs): + if nargs is not None: + raise ValueError("nargs not allowed") + super(FileContentsAction, self).__init__(option_strings, dest, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + if PathManager.isfile(values): + with PathManager.open(values) as f: + argument = f.read().strip() + else: + argument = values + setattr(namespace, self.dest, argument) + + +def split_paths(paths: str) -> List[str]: + return ( + paths.split(os.pathsep) + if "://" not in paths + else paths.split(MANIFOLD_PATH_SEP) + ) + + +def load_ensemble_for_inference(filenames, task, model_arg_overrides=None): + from fairseq import checkpoint_utils + + deprecation_warning( + "utils.load_ensemble_for_inference is deprecated. " + "Please use checkpoint_utils.load_model_ensemble instead." + ) + return checkpoint_utils.load_model_ensemble( + filenames, arg_overrides=model_arg_overrides, task=task + ) + + +def apply_to_sample(f, sample): + if hasattr(sample, "__len__") and len(sample) == 0: + return {} + + def _apply(x): + if torch.is_tensor(x): + return f(x) + elif isinstance(x, dict): + return {key: _apply(value) for key, value in x.items()} + elif isinstance(x, list): + return [_apply(x) for x in x] + elif isinstance(x, tuple): + return tuple(_apply(x) for x in x) + elif isinstance(x, set): + return {_apply(x) for x in x} + else: + return x + + return _apply(sample) + + +def move_to_cuda(sample, device=None): + device = device or torch.cuda.current_device() + + def _move_to_cuda(tensor): + # non_blocking is ignored if tensor is not pinned, so we can always set + # to True (see github.com/PyTorchLightning/pytorch-lightning/issues/620) + return tensor.cuda(device=device, non_blocking=True) + + return apply_to_sample(_move_to_cuda, sample) + + +def move_to_cpu(sample): + def _move_to_cpu(tensor): + # PyTorch has poor support for half tensors (float16) on CPU. + # Move any such tensors to float32. + if tensor.dtype in {torch.bfloat16, torch.float16}: + tensor = tensor.to(dtype=torch.float32) + return tensor.cpu() + + return apply_to_sample(_move_to_cpu, sample) + + +def get_incremental_state( + module: MultiheadAttention, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, +) -> Optional[Dict[str, Optional[Tensor]]]: + """Helper for getting incremental state for an nn.Module.""" + return module.get_incremental_state(incremental_state, key) + + +def set_incremental_state( + module: MultiheadAttention, + incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]], + key: str, + value: Dict[str, Optional[Tensor]], +) -> Optional[Dict[str, Dict[str, Optional[Tensor]]]]: + """Helper for setting incremental state for an nn.Module.""" + if incremental_state is not None: + result = module.set_incremental_state(incremental_state, key, value) + if result is not None: + incremental_state = result + return incremental_state + + +def load_align_dict(replace_unk): + if replace_unk is None: + align_dict = None + elif isinstance(replace_unk, str) and len(replace_unk) > 0: + # Load alignment dictionary for unknown word replacement if it was passed as an argument. + align_dict = {} + with open(replace_unk, "r") as f: + for line in f: + cols = line.split() + align_dict[cols[0]] = cols[1] + else: + # No alignment dictionary provided but we still want to perform unknown word replacement by copying the + # original source word. + align_dict = {} + return align_dict + + +def print_embed_overlap(embed_dict, vocab_dict): + embed_keys = set(embed_dict.keys()) + vocab_keys = set(vocab_dict.symbols) + overlap = len(embed_keys & vocab_keys) + logger.info("found {}/{} types in embedding file".format(overlap, len(vocab_dict))) + + +def parse_embedding(embed_path): + """Parse embedding text file into a dictionary of word and embedding tensors. + + The first line can have vocabulary size and dimension. The following lines + should contain word and embedding separated by spaces. + + Example: + 2 5 + the -0.0230 -0.0264 0.0287 0.0171 0.1403 + at -0.0395 -0.1286 0.0275 0.0254 -0.0932 + """ + embed_dict = {} + with open(embed_path) as f_embed: + next(f_embed) # skip header + for line in f_embed: + pieces = line.rstrip().split(" ") + embed_dict[pieces[0]] = torch.Tensor( + [float(weight) for weight in pieces[1:]] + ) + return embed_dict + + +def load_embedding(embed_dict, vocab, embedding): + for idx in range(len(vocab)): + token = vocab[idx] + if token in embed_dict: + embedding.weight.data[idx] = embed_dict[token] + return embedding + + +def replace_unk(hypo_str, src_str, alignment, align_dict, unk): + from fairseq import tokenizer + + # Tokens are strings here + hypo_tokens = tokenizer.tokenize_line(hypo_str) + # TODO: Very rare cases where the replacement is '<eos>' should be handled gracefully + src_tokens = tokenizer.tokenize_line(src_str) + ["<eos>"] + for i, ht in enumerate(hypo_tokens): + if ht == unk: + src_token = src_tokens[alignment[i]] + # Either take the corresponding value in the aligned dictionary or just copy the original value. + hypo_tokens[i] = align_dict.get(src_token, src_token) + return " ".join(hypo_tokens) + + +def post_process_prediction( + hypo_tokens, + src_str, + alignment, + align_dict, + tgt_dict, + remove_bpe=None, + extra_symbols_to_ignore=None, +): + hypo_str = tgt_dict.string( + hypo_tokens, remove_bpe, extra_symbols_to_ignore=extra_symbols_to_ignore + ) + if align_dict is not None: + hypo_str = replace_unk( + hypo_str, src_str, alignment, align_dict, tgt_dict.unk_string() + ) + if align_dict is not None or remove_bpe is not None: + # Convert back to tokens for evaluating with unk replacement or without BPE + # Note that the dictionary can be modified inside the method. + hypo_tokens = tgt_dict.encode_line(hypo_str, add_if_not_exist=True) + return hypo_tokens, hypo_str, alignment + + +def make_positions(tensor, padding_idx: int, onnx_trace: bool = False): + """Replace non-padding symbols with their position numbers. + + Position numbers begin at padding_idx+1. Padding symbols are ignored. + """ + # The series of casts and type-conversions here are carefully + # balanced to both work with ONNX export and XLA. In particular XLA + # prefers ints, cumsum defaults to output longs, and ONNX doesn't know + # how to handle the dtype kwarg in cumsum. + mask = tensor.ne(padding_idx).int() + return (torch.cumsum(mask, dim=1).type_as(mask) * mask).long() + padding_idx + + +def strip_pad(tensor, pad): + return tensor[tensor.ne(pad)] + + +def buffered_arange(max): + if not hasattr(buffered_arange, "buf"): + buffered_arange.buf = torch.LongTensor() + if max > buffered_arange.buf.numel(): + buffered_arange.buf.resize_(max) + torch.arange(max, out=buffered_arange.buf) + return buffered_arange.buf[:max] + + +def convert_padding_direction( + src_tokens, padding_idx, right_to_left: bool = False, left_to_right: bool = False +): + assert right_to_left ^ left_to_right + pad_mask = src_tokens.eq(padding_idx) + if not pad_mask.any(): + # no padding, return early + return src_tokens + if left_to_right and not pad_mask[:, 0].any(): + # already right padded + return src_tokens + if right_to_left and not pad_mask[:, -1].any(): + # already left padded + return src_tokens + max_len = src_tokens.size(1) + buffered = torch.empty(0).long() + if max_len > 0: + torch.arange(max_len, out=buffered) + range = buffered.type_as(src_tokens).expand_as(src_tokens) + num_pads = pad_mask.long().sum(dim=1, keepdim=True) + if right_to_left: + index = torch.remainder(range - num_pads, max_len) + else: + index = torch.remainder(range + num_pads, max_len) + return src_tokens.gather(1, index) + + +def item(tensor): + if hasattr(tensor, "item"): + return tensor.item() + if hasattr(tensor, "__getitem__"): + return tensor[0] + return tensor + + +def multi_tensor_total_norm(grads, chunk_size=2048 * 32) -> torch.Tensor: + per_device_grads = {} + norms = [] + for grad in grads: + device = grad.device + cur_device_grads = per_device_grads.get(device) + if cur_device_grads is None: + cur_device_grads = [] + per_device_grads[device] = cur_device_grads + cur_device_grads.append(grad) + for device in per_device_grads.keys(): + cur_device_grads = per_device_grads[device] + if device.type == "cuda": + # TODO(msb) return has_inf + has_inf = torch.zeros((1, 1), dtype=torch.int, device=device) + with torch.cuda.device(device): + norm = multi_tensor_l2norm( + chunk_size, has_inf, [cur_device_grads], False + ) + norms.append(norm[0].to(torch.cuda.current_device())) + else: + norms += [torch.norm(g, p=2, dtype=torch.float32) for g in cur_device_grads] + total_norm = torch.norm(torch.stack(norms)) + return total_norm + + +@torch.no_grad() +def clip_grad_norm_(params, max_norm, aggregate_norm_fn=None) -> torch.Tensor: + if isinstance(params, torch.Tensor): + params = [params] + params = list(params) + grads = [p.grad.detach() for p in filter(lambda p: p.grad is not None, params)] + if len(grads) == 0: + if len(params) > 0: + return params[0].new_tensor(0.0) + else: + return torch.tensor(0.0) + + if len(grads) == 1: + total_norm = torch.norm(grads[0], p=2, dtype=torch.float32) + else: + if multi_tensor_l2norm_available: + total_norm = multi_tensor_total_norm(grads) + else: + if torch.cuda.is_available(): + warnings.warn( + "amp_C fused kernels unavailable, disabling multi_tensor_l2norm; " + "you may get better performance by installing NVIDIA's apex library" + ) + device = torch.cuda.current_device() + elif grads[0].device.type == "xla": + device = grads[0].device + else: + device = torch.device("cpu") + total_norm = torch.norm( + torch.stack( + [torch.norm(g, p=2, dtype=torch.float32).to(device) for g in grads] + ) + ) + + if aggregate_norm_fn is not None: + total_norm = aggregate_norm_fn(total_norm) + + if max_norm > 0: + max_norm = float(max_norm) + clip_coef = (max_norm / (total_norm + 1e-6)).clamp_(max=1) + for g in grads: + g.mul_(clip_coef) + return total_norm + + +def fill_with_neg_inf(t): + """FP16-compatible function that fills a tensor with -inf.""" + return t.float().fill_(float("-inf")).type_as(t) + + +def _match_types(arg1, arg2): + """Convert the numerical argument to the same type as the other argument""" + + def upgrade(arg_number, arg_structure): + if isinstance(arg_structure, tuple): + return tuple([arg_number] * len(arg_structure)) + elif isinstance(arg_structure, dict): + arg = copy.deepcopy(arg_structure) + for k in arg: + arg[k] = upgrade(arg_number, arg_structure[k]) + return arg + else: + return arg_number + + if isinstance(arg1, float) or isinstance(arg1, int): + return upgrade(arg1, arg2), arg2 + elif isinstance(arg2, float) or isinstance(arg2, int): + return arg1, upgrade(arg2, arg1) + + return arg1, arg2 + + +def resolve_max_positions(*args): + """Resolve max position constraints from multiple sources.""" + + def map_value_update(d1, d2): + updated_value = copy.deepcopy(d1) + for key in d2: + if key not in updated_value: + updated_value[key] = d2[key] + else: + updated_value[key] = min(d1[key], d2[key]) + return updated_value + + def nullsafe_min(l): + minim = None + for item in l: + if minim is None: + minim = item + elif item is not None and item < minim: + minim = item + return minim + + max_positions = None + for arg in args: + if max_positions is None: + max_positions = arg + elif arg is not None: + max_positions, arg = _match_types(max_positions, arg) + if isinstance(arg, float) or isinstance(arg, int): + max_positions = min(max_positions, arg) + elif isinstance(arg, dict): + max_positions = map_value_update(max_positions, arg) + else: + max_positions = tuple(map(nullsafe_min, zip(max_positions, arg))) + + return max_positions + + +def import_user_module(args): + module_path = getattr(args, "user_dir", None) + if module_path is not None: + module_path = os.path.abspath(args.user_dir) + if not os.path.exists(module_path): + fairseq_rel_path = os.path.join(os.path.dirname(__file__), args.user_dir) + if os.path.exists(fairseq_rel_path): + module_path = fairseq_rel_path + else: + fairseq_rel_path = os.path.join( + os.path.dirname(__file__), "..", args.user_dir + ) + if os.path.exists(fairseq_rel_path): + module_path = fairseq_rel_path + else: + raise FileNotFoundError(module_path) + + # ensure that user modules are only imported once + import_user_module.memo = getattr(import_user_module, "memo", set()) + if module_path not in import_user_module.memo: + import_user_module.memo.add(module_path) + + module_parent, module_name = os.path.split(module_path) + if module_name not in sys.modules: + sys.path.insert(0, module_parent) + importlib.import_module(module_name) + else: + raise ImportError( + "Failed to import --user-dir={} because the corresponding module name " + "({}) is not globally unique. Please rename the directory to " + "something unique and try again.".format(module_path, module_name) + ) + + +def softmax(x, dim: int, onnx_trace: bool = False): + if onnx_trace: + return F.softmax(x.float(), dim=dim) + else: + return F.softmax(x, dim=dim, dtype=torch.float32) + + +def log_softmax(x, dim: int, onnx_trace: bool = False): + if onnx_trace: + return F.log_softmax(x.float(), dim=dim) + else: + return F.log_softmax(x, dim=dim, dtype=torch.float32) + + +def get_perplexity(loss, round=2, base=2): + if loss is None: + return 0.0 + try: + return safe_round(base ** loss, round) + except OverflowError: + return float("inf") + + +def deprecation_warning(message, stacklevel=3): + # don't use DeprecationWarning, since it's ignored by default + warnings.warn(message, stacklevel=stacklevel) + + +def get_activation_fn(activation: str) -> Callable: + """ Returns the activation function corresponding to `activation` """ + if activation == "relu": + return F.relu + elif activation == "gelu": + return gelu + elif activation == "gelu_fast": + deprecation_warning( + "--activation-fn=gelu_fast has been renamed to gelu_accurate" + ) + return gelu_accurate + elif activation == "gelu_accurate": + return gelu_accurate + elif activation == "tanh": + return torch.tanh + elif activation == "linear": + return lambda x: x + else: + raise RuntimeError("--activation-fn {} not supported".format(activation)) + + +def get_available_activation_fns() -> List: + return [ + "relu", + "gelu", + "gelu_fast", # deprecated + "gelu_accurate", + "tanh", + "linear", + ] + + +@contextlib.contextmanager +def model_eval(model): + is_training = model.training + model.eval() + yield + model.train(is_training) + + +def has_parameters(module): + try: + next(module.parameters()) + return True + except StopIteration: + return False + + +def set_torch_seed(seed): + # Set seed based on args.seed and the update number so that we get + # reproducible results when resuming from checkpoints + assert isinstance(seed, int) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + + +@contextlib.contextmanager +def with_torch_seed(seed): + assert isinstance(seed, int) + rng_state = torch.get_rng_state() + cuda_rng_state = torch.cuda.get_rng_state() + set_torch_seed(seed) + yield + torch.set_rng_state(rng_state) + torch.cuda.set_rng_state(cuda_rng_state) + + +def parse_alignment(line): + """ + Parses a single line from the alingment file. + + Args: + line (str): String containing the alignment of the format: + <src_idx_1>-<tgt_idx_1> <src_idx_2>-<tgt_idx_2> .. + <src_idx_m>-<tgt_idx_m>. All indices are 0 indexed. + + Returns: + torch.IntTensor: packed alignments of shape (2 * m). + """ + alignments = line.strip().split() + parsed_alignment = torch.IntTensor(2 * len(alignments)) + for idx, alignment in enumerate(alignments): + src_idx, tgt_idx = alignment.split("-") + parsed_alignment[2 * idx] = int(src_idx) + parsed_alignment[2 * idx + 1] = int(tgt_idx) + return parsed_alignment + + +def get_token_to_word_mapping(tokens, exclude_list): + n = len(tokens) + word_start = [int(token not in exclude_list) for token in tokens] + word_idx = list(accumulate(word_start)) + token_to_word = {i: word_idx[i] for i in range(n)} + return token_to_word + + +def extract_hard_alignment(attn, src_sent, tgt_sent, pad, eos): + tgt_valid = ( + ((tgt_sent != pad) & (tgt_sent != eos)).nonzero(as_tuple=False).squeeze(dim=-1) + ) + src_invalid = ( + ((src_sent == pad) | (src_sent == eos)).nonzero(as_tuple=False).squeeze(dim=-1) + ) + src_token_to_word = get_token_to_word_mapping(src_sent, [eos, pad]) + tgt_token_to_word = get_token_to_word_mapping(tgt_sent, [eos, pad]) + alignment = [] + if len(tgt_valid) != 0 and len(src_invalid) < len(src_sent): + attn_valid = attn[tgt_valid] + attn_valid[:, src_invalid] = float("-inf") + _, src_indices = attn_valid.max(dim=1) + for tgt_idx, src_idx in zip(tgt_valid, src_indices): + alignment.append( + ( + src_token_to_word[src_idx.item()] - 1, + tgt_token_to_word[tgt_idx.item()] - 1, + ) + ) + return alignment + + +def new_arange(x, *size): + """ + Return a Tensor of `size` filled with a range function on the device of x. + If size is empty, using the size of the variable x. + """ + if len(size) == 0: + size = x.size() + return torch.arange(size[-1], device=x.device).expand(*size).contiguous() + + +def get_tpu_device(args): + import torch_xla.core.xla_model as xm + + return xm.xla_device() + + +def tpu_data_loader(itr): + import torch_xla.core.xla_model as xm + import torch_xla.distributed.parallel_loader as pl + + xm.rendezvous("tpu_data_loader") # wait for all workers + xm.mark_step() + device = xm.xla_device() + return iterators.CountingIterator( + pl.ParallelLoader(itr, [device]).per_device_loader(device), + start=getattr(itr, "n", 0), + total=len(itr), + ) + + +class CudaEnvironment(object): + def __init__(self): + cur_device = torch.cuda.current_device() + prop = torch.cuda.get_device_properties("cuda:{}".format(cur_device)) + self.name = prop.name + self.major = prop.major + self.minor = prop.minor + self.total_memory_in_GB = prop.total_memory / 1024 / 1024 / 1024 + + @staticmethod + def pretty_print_cuda_env_list(cuda_env_list): + """ + Given a list of CudaEnviorments, pretty print them + """ + num_workers = len(cuda_env_list) + center = "CUDA enviroments for all {} workers".format(num_workers) + banner_len = 40 - len(center) // 2 + first_line = "*" * banner_len + center + "*" * banner_len + logger.info(first_line) + for r, env in enumerate(cuda_env_list): + logger.info( + "rank {:3d}: ".format(r) + + "capabilities = {:2d}.{:<2d} ; ".format(env.major, env.minor) + + "total memory = {:.3f} GB ; ".format(env.total_memory_in_GB) + + "name = {:40s}".format(env.name) + ) + logger.info(first_line) + + +def csv_str_list(x): + return x.split(",") + + +def eval_str_list(x, type=float): + if x is None: + return None + if isinstance(x, str): + x = eval(x) + try: + return list(map(type, x)) + except TypeError: + return [type(x)] + + +def eval_str_dict(x, type=dict): + if x is None: + return None + if isinstance(x, str): + x = eval(x) + return x + + +def eval_bool(x, default=False): + if x is None: + return default + try: + return bool(eval(x)) + except TypeError: + return default diff --git a/fairseq-tools/fairseq/fairseq_cli/__init__.py b/fairseq-tools/fairseq/fairseq_cli/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/fairseq_cli/eval_lm.py b/fairseq-tools/fairseq/fairseq_cli/eval_lm.py new file mode 100644 index 00000000..9a4ff8ee --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/eval_lm.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" +Evaluate the perplexity of a trained language model. +""" + +import logging +import math +import os + +import torch +from fairseq import checkpoint_utils, distributed_utils, options, tasks, utils +from fairseq.data import LMContextWindowDataset +from fairseq.logging import progress_bar +from fairseq.logging.meters import StopwatchMeter, TimeMeter +from fairseq.sequence_scorer import SequenceScorer + + +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), +) +logger = logging.getLogger("fairseq_cli.eval_lm") + + +class WordStat(object): + def __init__(self, word, is_bpe): + self.word = word + self.is_bpe = is_bpe + self.log_prob = 0 + self.next_word_prob = 0 + self.count = 0 + self.missing_next_words = 0 + + def add(self, log_prob, next_word_prob): + """increments counters for the sum of log probs of current word and next + word (given context ending at current word). Since the next word might be at the end of the example, + or it might be not counted because it is not an ending subword unit, + also keeps track of how many of those we have seen""" + if next_word_prob is not None: + self.next_word_prob += next_word_prob + else: + self.missing_next_words += 1 + self.log_prob += log_prob + self.count += 1 + + def __str__(self): + return "{}\t{}\t{}\t{}\t{}\t{}".format( + self.word, + self.count, + self.log_prob, + self.is_bpe, + self.next_word_prob, + self.count - self.missing_next_words, + ) + + +def main(parsed_args, **unused_kwargs): + assert parsed_args.path is not None, "--path required for evaluation!" + + if torch.cuda.is_available() and not parsed_args.cpu: + torch.cuda.set_device(parsed_args.device_id) + + utils.import_user_module(parsed_args) + + logger.info(parsed_args) + + use_cuda = torch.cuda.is_available() and not parsed_args.cpu + + task = tasks.setup_task(parsed_args) + + # Load ensemble + logger.info("loading model(s) from {}".format(parsed_args.path)) + models, args = checkpoint_utils.load_model_ensemble( + parsed_args.path.split(os.pathsep), + arg_overrides=eval(parsed_args.model_overrides), + task=task, + suffix=getattr(parsed_args, "checkpoint_suffix", ""), + strict=(parsed_args.checkpoint_shard_count == 1), + num_shards=parsed_args.checkpoint_shard_count, + ) + + for arg in vars(parsed_args).keys(): + if arg not in { + "self_target", + "future_target", + "past_target", + "tokens_per_sample", + "output_size_dictionary", + "add_bos_token", + }: + setattr(args, arg, getattr(parsed_args, arg)) + + # reduce tokens per sample by the required context window size + args.tokens_per_sample -= args.context_window + task = tasks.setup_task(args) + + # Load dataset splits + task.load_dataset(args.gen_subset) + dataset = task.dataset(args.gen_subset) + if args.context_window > 0: + dataset = LMContextWindowDataset( + dataset=dataset, + tokens_per_sample=args.tokens_per_sample, + context_window=args.context_window, + pad_idx=task.source_dictionary.pad(), + ) + logger.info("{} {} {} examples".format(args.data, args.gen_subset, len(dataset))) + + # Optimize ensemble for generation and set the source and dest dicts on the model (required by scorer) + for model in models: + if args.fp16: + model.half() + if use_cuda and not args.pipeline_model_parallel: + model.cuda() + model.prepare_for_inference_(args) + + assert len(models) > 0 + + logger.info( + "num. model params: {}".format(sum(p.numel() for p in models[0].parameters())) + ) + + itr = task.get_batch_iterator( + dataset=dataset, + max_tokens=args.max_tokens or 36000, + max_sentences=args.batch_size, + max_positions=utils.resolve_max_positions( + *[model.max_positions() for model in models] + ), + ignore_invalid_inputs=True, + num_shards=args.num_shards, + shard_id=args.shard_id, + num_workers=args.num_workers, + data_buffer_size=args.data_buffer_size, + ).next_epoch_itr(shuffle=False) + progress = progress_bar.progress_bar( + itr, + log_format=args.log_format, + log_interval=args.log_interval, + default_log_format=("tqdm" if not args.no_progress_bar else "none"), + ) + + gen_timer = StopwatchMeter() + scorer = SequenceScorer(task.target_dictionary, args.softmax_batch) + + score_sum = 0.0 + count = 0 + + if args.remove_bpe is not None: + if args.remove_bpe == "sentencepiece": + raise NotImplementedError + else: + bpe_cont = args.remove_bpe.rstrip() + bpe_toks = { + i + for i in range(len(task.source_dictionary)) + if task.source_dictionary[i].endswith(bpe_cont) + } + bpe_len = len(bpe_cont) + else: + bpe_toks = None + bpe_len = 0 + + word_stats = dict() + + wps_meter = TimeMeter() + + for sample in progress: + if "net_input" not in sample: + continue + + sample = utils.move_to_cuda(sample) if use_cuda else sample + + gen_timer.start() + hypos = scorer.generate(models, sample) + gen_timer.stop(sample["ntokens"]) + + for i, hypos_i in enumerate(hypos): + hypo = hypos_i[0] + sample_id = sample["id"][i] + + tokens = hypo["tokens"] + tgt_len = tokens.numel() + pos_scores = hypo["positional_scores"].float() + + if getattr(args, "add_bos_token", False): + assert hypo["tokens"][0].item() == task.target_dictionary.bos() + tokens = tokens[1:] + pos_scores = pos_scores[1:] + + skipped_toks = 0 + if bpe_toks is not None: + for i in range(tgt_len - 1): + if tokens[i].item() in bpe_toks: + skipped_toks += 1 + pos_scores[i + 1] += pos_scores[i] + pos_scores[i] = 0 + + inf_scores = pos_scores.eq(float("inf")) | pos_scores.eq(float("-inf")) + if inf_scores.any(): + logger.info( + "skipping tokens with inf scores:", + task.target_dictionary.string(tokens[inf_scores.nonzero()]), + ) + pos_scores = pos_scores[(~inf_scores).nonzero()] + score_sum += pos_scores.sum().cpu() + count += pos_scores.numel() - skipped_toks + + if args.output_word_probs or args.output_word_stats: + w = "" + word_prob = [] + is_bpe = False + for i in range(len(tokens)): + w_ind = tokens[i].item() + w += task.source_dictionary[w_ind] + if bpe_toks is not None and w_ind in bpe_toks: + w = w[:-bpe_len] + is_bpe = True + else: + word_prob.append((w, pos_scores[i].item())) + + next_prob = None + ind = i + 1 + while ind < len(tokens): + if pos_scores[ind].item() != 0: + next_prob = pos_scores[ind] + break + ind += 1 + + word_stats.setdefault(w, WordStat(w, is_bpe)).add( + pos_scores[i].item(), next_prob + ) + is_bpe = False + w = "" + if args.output_word_probs: + logger.info( + str(int(sample_id)) + + " " + + ( + "\t".join( + "{} [{:2f}]".format(x[0], x[1]) for x in word_prob + ) + ) + ) + + wps_meter.update(sample["ntokens"]) + progress.log({"wps": round(wps_meter.avg)}) + + avg_nll_loss = -score_sum / count / math.log(2) # convert to base 2 + logger.info( + "Evaluated {} tokens in {:.1f}s ({:.2f} tokens/s)".format( + gen_timer.n, gen_timer.sum, 1.0 / gen_timer.avg + ) + ) + logger.info( + "Loss (base 2): {:.4f}, Perplexity: {:.2f}".format( + avg_nll_loss, 2 ** avg_nll_loss + ) + ) + + if args.output_word_stats: + for ws in sorted(word_stats.values(), key=lambda x: x.count, reverse=True): + logger.info(ws) + + +def cli_main(): + parser = options.get_eval_lm_parser() + args = options.parse_args_and_arch(parser) + distributed_utils.call_main(args, main) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/generate.py b/fairseq-tools/fairseq/fairseq_cli/generate.py new file mode 100644 index 00000000..8ddf981c --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/generate.py @@ -0,0 +1,383 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Translate pre-processed data with a trained model. +""" + +import ast +import logging +import math +import os +import sys +from itertools import chain + +import numpy as np +import torch +from fairseq import checkpoint_utils, options, scoring, tasks, utils +from fairseq.logging import progress_bar +from fairseq.logging.meters import StopwatchMeter, TimeMeter + + +def main(args): + assert args.path is not None, "--path required for generation!" + assert ( + not args.sampling or args.nbest == args.beam + ), "--sampling requires --nbest to be equal to --beam" + assert ( + args.replace_unk is None or args.dataset_impl == "raw" + ), "--replace-unk requires a raw text dataset (--dataset-impl=raw)" + + if args.results_path is not None: + os.makedirs(args.results_path, exist_ok=True) + output_path = os.path.join( + args.results_path, "generate-{}.txt".format(args.gen_subset) + ) + with open(output_path, "w", buffering=1, encoding="utf-8") as h: + return _main(args, h) + else: + return _main(args, sys.stdout) + + +def get_symbols_to_strip_from_output(generator): + if hasattr(generator, "symbols_to_strip_from_output"): + return generator.symbols_to_strip_from_output + else: + return {generator.eos} + + +def _main(args, output_file): + logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), + stream=output_file, + ) + logger = logging.getLogger("fairseq_cli.generate") + + utils.import_user_module(args) + + if args.max_tokens is None and args.batch_size is None: + args.max_tokens = 12000 + logger.info(args) + + # Fix seed for stochastic decoding + if args.seed is not None and not args.no_seed_provided: + np.random.seed(args.seed) + utils.set_torch_seed(args.seed) + + use_cuda = torch.cuda.is_available() and not args.cpu + + # Load dataset splits + task = tasks.setup_task(args) + task.load_dataset(args.gen_subset) + + # Set dictionaries + try: + src_dict = getattr(task, "source_dictionary", None) + except NotImplementedError: + src_dict = None + tgt_dict = task.target_dictionary + + overrides = ast.literal_eval(args.model_overrides) + + # Load ensemble + logger.info("loading model(s) from {}".format(args.path)) + models, _model_args = checkpoint_utils.load_model_ensemble( + utils.split_paths(args.path), + arg_overrides=overrides, + task=task, + suffix=getattr(args, "checkpoint_suffix", ""), + strict=(args.checkpoint_shard_count == 1), + num_shards=args.checkpoint_shard_count, + ) + + if args.lm_path is not None: + overrides["data"] = args.data + + try: + lms, _ = checkpoint_utils.load_model_ensemble( + [args.lm_path], + arg_overrides=overrides, + task=None, + ) + except: + logger.warning( + f"Failed to load language model! Please make sure that the language model dict is the same " + f"as target dict and is located in the data dir ({args.data})" + ) + raise + + assert len(lms) == 1 + else: + lms = [None] + + # Optimize ensemble for generation + for model in chain(models, lms): + if model is None: + continue + if args.fp16: + model.half() + if use_cuda and not args.pipeline_model_parallel: + model.cuda() + model.prepare_for_inference_(args) + + # Load alignment dictionary for unknown word replacement + # (None if no unknown word replacement, empty if no path to align dictionary) + align_dict = utils.load_align_dict(args.replace_unk) + + # Load dataset (possibly sharded) + itr = task.get_batch_iterator( + dataset=task.dataset(args.gen_subset), + max_tokens=args.max_tokens, + max_sentences=args.batch_size, + max_positions=utils.resolve_max_positions( + task.max_positions(), *[model.max_positions() for model in models] + ), + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=args.required_batch_size_multiple, + num_shards=args.num_shards, + shard_id=args.shard_id, + num_workers=args.num_workers, + data_buffer_size=args.data_buffer_size, + ).next_epoch_itr(shuffle=False) + progress = progress_bar.progress_bar( + itr, + log_format=args.log_format, + log_interval=args.log_interval, + default_log_format=("tqdm" if not args.no_progress_bar else "none"), + ) + + # Initialize generator + gen_timer = StopwatchMeter() + + extra_gen_cls_kwargs = {"lm_model": lms[0], "lm_weight": args.lm_weight} + generator = task.build_generator( + models, args, extra_gen_cls_kwargs=extra_gen_cls_kwargs + ) + + # Handle tokenization and BPE + tokenizer = task.build_tokenizer(args) + bpe = task.build_bpe(args) + + def decode_fn(x): + if bpe is not None: + x = bpe.decode(x) + if tokenizer is not None: + x = tokenizer.decode(x) + return x + + scorer = scoring.build_scorer(args, tgt_dict) + + num_sentences = 0 + has_target = True + wps_meter = TimeMeter() + for sample in progress: + sample = utils.move_to_cuda(sample) if use_cuda else sample + if "net_input" not in sample: + continue + + prefix_tokens = None + if args.prefix_size > 0: + prefix_tokens = sample["target"][:, : args.prefix_size] + + constraints = None + if "constraints" in sample: + constraints = sample["constraints"] + + gen_timer.start() + hypos = task.inference_step( + generator, + models, + sample, + prefix_tokens=prefix_tokens, + constraints=constraints, + ) + num_generated_tokens = sum(len(h[0]["tokens"]) for h in hypos) + gen_timer.stop(num_generated_tokens) + + for i, sample_id in enumerate(sample["id"].tolist()): + has_target = sample["target"] is not None + + # Remove padding + if "src_tokens" in sample["net_input"]: + src_tokens = utils.strip_pad( + sample["net_input"]["src_tokens"][i, :], tgt_dict.pad() + ) + else: + src_tokens = None + + target_tokens = None + if has_target: + target_tokens = ( + utils.strip_pad(sample["target"][i, :], tgt_dict.pad()).int().cpu() + ) + + # Either retrieve the original sentences or regenerate them from tokens. + if align_dict is not None: + src_str = task.dataset(args.gen_subset).src.get_original_text(sample_id) + target_str = task.dataset(args.gen_subset).tgt.get_original_text( + sample_id + ) + else: + if src_dict is not None: + src_str = src_dict.string(src_tokens, args.remove_bpe) + else: + src_str = "" + if has_target: + target_str = tgt_dict.string( + target_tokens, + args.remove_bpe, + escape_unk=True, + extra_symbols_to_ignore=get_symbols_to_strip_from_output( + generator + ), + ) + + src_str = decode_fn(src_str) + if has_target: + target_str = decode_fn(target_str) + + if not args.quiet: + if src_dict is not None: + print("S-{}\t{}".format(sample_id, src_str), file=output_file) + if has_target: + print("T-{}\t{}".format(sample_id, target_str), file=output_file) + + # Process top predictions + for j, hypo in enumerate(hypos[i][: args.nbest]): + hypo_tokens, hypo_str, alignment = utils.post_process_prediction( + hypo_tokens=hypo["tokens"].int().cpu(), + src_str=src_str, + alignment=hypo["alignment"], + align_dict=align_dict, + tgt_dict=tgt_dict, + remove_bpe=args.remove_bpe, + extra_symbols_to_ignore=get_symbols_to_strip_from_output(generator), + ) + detok_hypo_str = decode_fn(hypo_str) + if not args.quiet: + score = hypo["score"] / math.log(2) # convert to base 2 + # original hypothesis (after tokenization and BPE) + print( + "H-{}\t{}\t{}".format(sample_id, score, hypo_str), + file=output_file, + ) + # detokenized hypothesis + print( + "D-{}\t{}\t{}".format(sample_id, score, detok_hypo_str), + file=output_file, + ) + print( + "P-{}\t{}".format( + sample_id, + " ".join( + map( + lambda x: "{:.4f}".format(x), + # convert from base e to base 2 + hypo["positional_scores"] + .div_(math.log(2)) + .tolist(), + ) + ), + ), + file=output_file, + ) + + if args.print_alignment: + print( + "A-{}\t{}".format( + sample_id, + " ".join( + [ + "{}-{}".format(src_idx, tgt_idx) + for src_idx, tgt_idx in alignment + ] + ), + ), + file=output_file, + ) + + if args.print_step: + print( + "I-{}\t{}".format(sample_id, hypo["steps"]), + file=output_file, + ) + + if getattr(args, "retain_iter_history", False): + for step, h in enumerate(hypo["history"]): + _, h_str, _ = utils.post_process_prediction( + hypo_tokens=h["tokens"].int().cpu(), + src_str=src_str, + alignment=None, + align_dict=None, + tgt_dict=tgt_dict, + remove_bpe=None, + ) + print( + "E-{}_{}\t{}".format(sample_id, step, h_str), + file=output_file, + ) + + # Score only the top hypothesis + if has_target and j == 0: + if align_dict is not None or args.remove_bpe is not None: + # Convert back to tokens for evaluation with unk replacement and/or without BPE + target_tokens = tgt_dict.encode_line( + target_str, add_if_not_exist=True + ) + hypo_tokens = tgt_dict.encode_line( + detok_hypo_str, add_if_not_exist=True + ) + if hasattr(scorer, "add_string"): + scorer.add_string(target_str, detok_hypo_str) + else: + scorer.add(target_tokens, hypo_tokens) + + wps_meter.update(num_generated_tokens) + progress.log({"wps": round(wps_meter.avg)}) + num_sentences += ( + sample["nsentences"] if "nsentences" in sample else sample["id"].numel() + ) + + logger.info("NOTE: hypothesis and token scores are output in base 2") + logger.info( + "Translated {} sentences ({} tokens) in {:.1f}s ({:.2f} sentences/s, {:.2f} tokens/s)".format( + num_sentences, + gen_timer.n, + gen_timer.sum, + num_sentences / gen_timer.sum, + 1.0 / gen_timer.avg, + ) + ) + if has_target: + if args.bpe and not args.sacrebleu: + if args.remove_bpe: + logger.warning( + "BLEU score is being computed by splitting detokenized string on spaces, this is probably not what you want. Use --sacrebleu for standard 13a BLEU tokenization" + ) + else: + logger.warning( + "If you are using BPE on the target side, the BLEU score is computed on BPE tokens, not on proper words. Use --sacrebleu for standard 13a BLEU tokenization" + ) + # use print to be consistent with other main outputs: S-, H-, T-, D- and so on + print( + "Generate {} with beam={}: {}".format( + args.gen_subset, args.beam, scorer.result_string() + ), + file=output_file, + ) + + return scorer + + +def cli_main(): + parser = options.get_generation_parser() + args = options.parse_args_and_arch(parser) + main(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/interactive.py b/fairseq-tools/fairseq/fairseq_cli/interactive.py new file mode 100644 index 00000000..de3893a3 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/interactive.py @@ -0,0 +1,311 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Translate raw text with a trained model. Batches data on-the-fly. +""" + +import fileinput +import logging +import math +import os +import sys +import time +from collections import namedtuple + +import numpy as np +import torch +from fairseq import checkpoint_utils, distributed_utils, options, tasks, utils +from fairseq.data import encoders +from fairseq.token_generation_constraints import pack_constraints, unpack_constraints +from fairseq_cli.generate import get_symbols_to_strip_from_output + + +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), + stream=sys.stdout, +) +logger = logging.getLogger("fairseq_cli.interactive") + + +Batch = namedtuple("Batch", "ids src_tokens src_lengths constraints") +Translation = namedtuple("Translation", "src_str hypos pos_scores alignments") + + +def buffered_read(input, buffer_size): + buffer = [] + with fileinput.input(files=[input], openhook=fileinput.hook_encoded("utf-8")) as h: + for src_str in h: + buffer.append(src_str.strip()) + if len(buffer) >= buffer_size: + yield buffer + buffer = [] + + if len(buffer) > 0: + yield buffer + + +def make_batches(lines, args, task, max_positions, encode_fn): + def encode_fn_target(x): + return encode_fn(x) + + if args.constraints: + # Strip (tab-delimited) contraints, if present, from input lines, + # store them in batch_constraints + batch_constraints = [list() for _ in lines] + for i, line in enumerate(lines): + if "\t" in line: + lines[i], *batch_constraints[i] = line.split("\t") + + # Convert each List[str] to List[Tensor] + for i, constraint_list in enumerate(batch_constraints): + batch_constraints[i] = [ + task.target_dictionary.encode_line( + encode_fn_target(constraint), + append_eos=False, + add_if_not_exist=False, + ) + for constraint in constraint_list + ] + + tokens = [ + task.source_dictionary.encode_line( + encode_fn(src_str), add_if_not_exist=False + ).long() + for src_str in lines + ] + + if args.constraints: + constraints_tensor = pack_constraints(batch_constraints) + else: + constraints_tensor = None + + lengths = [t.numel() for t in tokens] + itr = task.get_batch_iterator( + dataset=task.build_dataset_for_inference( + tokens, lengths, constraints=constraints_tensor + ), + max_tokens=args.max_tokens, + max_sentences=args.batch_size, + max_positions=max_positions, + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + ).next_epoch_itr(shuffle=False) + for batch in itr: + ids = batch["id"] + src_tokens = batch["net_input"]["src_tokens"] + src_lengths = batch["net_input"]["src_lengths"] + constraints = batch.get("constraints", None) + + yield Batch( + ids=ids, + src_tokens=src_tokens, + src_lengths=src_lengths, + constraints=constraints, + ) + + +def main(args): + start_time = time.time() + total_translate_time = 0 + + utils.import_user_module(args) + + if args.buffer_size < 1: + args.buffer_size = 1 + if args.max_tokens is None and args.batch_size is None: + args.batch_size = 1 + + assert ( + not args.sampling or args.nbest == args.beam + ), "--sampling requires --nbest to be equal to --beam" + assert ( + not args.batch_size or args.batch_size <= args.buffer_size + ), "--batch-size cannot be larger than --buffer-size" + + logger.info(args) + + # Fix seed for stochastic decoding + if args.seed is not None and not args.no_seed_provided: + np.random.seed(args.seed) + utils.set_torch_seed(args.seed) + + use_cuda = torch.cuda.is_available() and not args.cpu + + # Setup task, e.g., translation + task = tasks.setup_task(args) + + # Load ensemble + logger.info("loading model(s) from {}".format(args.path)) + models, _model_args = checkpoint_utils.load_model_ensemble( + args.path.split(os.pathsep), + arg_overrides=eval(args.model_overrides), + task=task, + suffix=getattr(args, "checkpoint_suffix", ""), + strict=(args.checkpoint_shard_count == 1), + num_shards=args.checkpoint_shard_count, + ) + + # Set dictionaries + src_dict = task.source_dictionary + tgt_dict = task.target_dictionary + + # Optimize ensemble for generation + for model in models: + if args.fp16: + model.half() + if use_cuda and not args.pipeline_model_parallel: + model.cuda() + model.prepare_for_inference_(args) + + # Initialize generator + generator = task.build_generator(models, args) + + # Handle tokenization and BPE + tokenizer = encoders.build_tokenizer(args) + bpe = encoders.build_bpe(args) + + def encode_fn(x): + if tokenizer is not None: + x = tokenizer.encode(x) + if bpe is not None: + x = bpe.encode(x) + return x + + def decode_fn(x): + if bpe is not None: + x = bpe.decode(x) + if tokenizer is not None: + x = tokenizer.decode(x) + return x + + # Load alignment dictionary for unknown word replacement + # (None if no unknown word replacement, empty if no path to align dictionary) + align_dict = utils.load_align_dict(args.replace_unk) + + max_positions = utils.resolve_max_positions( + task.max_positions(), *[model.max_positions() for model in models] + ) + + if args.constraints: + logger.warning( + "NOTE: Constrained decoding currently assumes a shared subword vocabulary." + ) + + if args.buffer_size > 1: + logger.info("Sentence buffer size: %s", args.buffer_size) + logger.info("NOTE: hypothesis and token scores are output in base 2") + logger.info("Type the input sentence and press return:") + start_id = 0 + for inputs in buffered_read(args.input, args.buffer_size): + results = [] + for batch in make_batches(inputs, args, task, max_positions, encode_fn): + bsz = batch.src_tokens.size(0) + src_tokens = batch.src_tokens + src_lengths = batch.src_lengths + constraints = batch.constraints + if use_cuda: + src_tokens = src_tokens.cuda() + src_lengths = src_lengths.cuda() + if constraints is not None: + constraints = constraints.cuda() + + sample = { + "net_input": { + "src_tokens": src_tokens, + "src_lengths": src_lengths, + }, + } + translate_start_time = time.time() + translations = task.inference_step( + generator, models, sample, constraints=constraints + ) + translate_time = time.time() - translate_start_time + total_translate_time += translate_time + list_constraints = [[] for _ in range(bsz)] + if args.constraints: + list_constraints = [unpack_constraints(c) for c in constraints] + for i, (id, hypos) in enumerate(zip(batch.ids.tolist(), translations)): + src_tokens_i = utils.strip_pad(src_tokens[i], tgt_dict.pad()) + constraints = list_constraints[i] + results.append( + ( + start_id + id, + src_tokens_i, + hypos, + { + "constraints": constraints, + "time": translate_time / len(translations), + }, + ) + ) + + # sort output to match input order + for id_, src_tokens, hypos, info in sorted(results, key=lambda x: x[0]): + if src_dict is not None: + src_str = src_dict.string(src_tokens, args.remove_bpe) + print("S-{}\t{}".format(id_, src_str)) + print("W-{}\t{:.3f}\tseconds".format(id_, info["time"])) + for constraint in info["constraints"]: + print( + "C-{}\t{}".format( + id_, tgt_dict.string(constraint, args.remove_bpe) + ) + ) + + # Process top predictions + for hypo in hypos[: min(len(hypos), args.nbest)]: + hypo_tokens, hypo_str, alignment = utils.post_process_prediction( + hypo_tokens=hypo["tokens"].int().cpu(), + src_str=src_str, + alignment=hypo["alignment"], + align_dict=align_dict, + tgt_dict=tgt_dict, + remove_bpe=args.remove_bpe, + extra_symbols_to_ignore=get_symbols_to_strip_from_output(generator), + ) + detok_hypo_str = decode_fn(hypo_str) + score = hypo["score"] / math.log(2) # convert to base 2 + # original hypothesis (after tokenization and BPE) + print("H-{}\t{}\t{}".format(id_, score, hypo_str)) + # detokenized hypothesis + print("D-{}\t{}\t{}".format(id_, score, detok_hypo_str)) + print( + "P-{}\t{}".format( + id_, + " ".join( + map( + lambda x: "{:.4f}".format(x), + # convert from base e to base 2 + hypo["positional_scores"].div_(math.log(2)).tolist(), + ) + ), + ) + ) + if args.print_alignment: + alignment_str = " ".join( + ["{}-{}".format(src, tgt) for src, tgt in alignment] + ) + print("A-{}\t{}".format(id_, alignment_str)) + + # update running id_ counter + start_id += len(inputs) + + logger.info( + "Total time: {:.3f} seconds; translation time: {:.3f}".format( + time.time() - start_time, total_translate_time + ) + ) + + +def cli_main(): + parser = options.get_interactive_generation_parser() + args = options.parse_args_and_arch(parser) + distributed_utils.call_main(args, main) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/preprocess.py b/fairseq-tools/fairseq/fairseq_cli/preprocess.py new file mode 100644 index 00000000..fa77da8d --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/preprocess.py @@ -0,0 +1,398 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Data pre-processing: build vocabularies and binarize training data. +""" + +import logging +import os +import shutil +import sys +from collections import Counter +from itertools import zip_longest +from multiprocessing import Pool + +from fairseq import options, tasks, utils +from fairseq.binarizer import Binarizer +from fairseq.data import indexed_dataset + + +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), + stream=sys.stdout, +) +logger = logging.getLogger("fairseq_cli.preprocess") + + +def main(args): + utils.import_user_module(args) + + os.makedirs(args.destdir, exist_ok=True) + + logger.addHandler( + logging.FileHandler( + filename=os.path.join(args.destdir, "preprocess.log"), + ) + ) + logger.info(args) + + task = tasks.get_task(args.task) + + def train_path(lang): + return "{}{}".format(args.trainpref, ("." + lang) if lang else "") + + def file_name(prefix, lang): + fname = prefix + if lang is not None: + fname += ".{lang}".format(lang=lang) + return fname + + def dest_path(prefix, lang): + return os.path.join(args.destdir, file_name(prefix, lang)) + + def dict_path(lang): + return dest_path("dict", lang) + ".txt" + + def build_dictionary(filenames, src=False, tgt=False): + assert src ^ tgt + return task.build_dictionary( + filenames, + workers=args.workers, + threshold=args.thresholdsrc if src else args.thresholdtgt, + nwords=args.nwordssrc if src else args.nwordstgt, + padding_factor=args.padding_factor, + ) + + target = not args.only_source + + if not args.srcdict and os.path.exists(dict_path(args.source_lang)): + raise FileExistsError(dict_path(args.source_lang)) + if target and not args.tgtdict and os.path.exists(dict_path(args.target_lang)): + raise FileExistsError(dict_path(args.target_lang)) + + if args.joined_dictionary: + assert ( + not args.srcdict or not args.tgtdict + ), "cannot use both --srcdict and --tgtdict with --joined-dictionary" + + if args.srcdict: + src_dict = task.load_dictionary(args.srcdict) + elif args.tgtdict: + src_dict = task.load_dictionary(args.tgtdict) + else: + assert ( + args.trainpref + ), "--trainpref must be set if --srcdict is not specified" + src_dict = build_dictionary( + {train_path(lang) for lang in [args.source_lang, args.target_lang]}, + src=True, + ) + tgt_dict = src_dict + else: + if args.srcdict: + src_dict = task.load_dictionary(args.srcdict) + else: + assert ( + args.trainpref + ), "--trainpref must be set if --srcdict is not specified" + src_dict = build_dictionary([train_path(args.source_lang)], src=True) + + if target: + if args.tgtdict: + tgt_dict = task.load_dictionary(args.tgtdict) + else: + assert ( + args.trainpref + ), "--trainpref must be set if --tgtdict is not specified" + tgt_dict = build_dictionary([train_path(args.target_lang)], tgt=True) + else: + tgt_dict = None + + src_dict.save(dict_path(args.source_lang)) + if target and tgt_dict is not None: + tgt_dict.save(dict_path(args.target_lang)) + + def make_binary_dataset(vocab, input_prefix, output_prefix, lang, num_workers): + logger.info("[{}] Dictionary: {} types".format(lang, len(vocab))) + n_seq_tok = [0, 0] + replaced = Counter() + + def merge_result(worker_result): + replaced.update(worker_result["replaced"]) + n_seq_tok[0] += worker_result["nseq"] + n_seq_tok[1] += worker_result["ntok"] + + input_file = "{}{}".format( + input_prefix, ("." + lang) if lang is not None else "" + ) + offsets = Binarizer.find_offsets(input_file, num_workers) + pool = None + if num_workers > 1: + pool = Pool(processes=num_workers - 1) + for worker_id in range(1, num_workers): + prefix = "{}{}".format(output_prefix, worker_id) + pool.apply_async( + binarize, + ( + args, + input_file, + vocab, + prefix, + lang, + offsets[worker_id], + offsets[worker_id + 1], + ), + callback=merge_result, + ) + pool.close() + + ds = indexed_dataset.make_builder( + dataset_dest_file(args, output_prefix, lang, "bin"), + impl=args.dataset_impl, + vocab_size=len(vocab), + ) + merge_result( + Binarizer.binarize( + input_file, vocab, lambda t: ds.add_item(t), offset=0, end=offsets[1] + ) + ) + if num_workers > 1: + pool.join() + for worker_id in range(1, num_workers): + prefix = "{}{}".format(output_prefix, worker_id) + temp_file_path = dataset_dest_prefix(args, prefix, lang) + ds.merge_file_(temp_file_path) + os.remove(indexed_dataset.data_file_path(temp_file_path)) + os.remove(indexed_dataset.index_file_path(temp_file_path)) + + ds.finalize(dataset_dest_file(args, output_prefix, lang, "idx")) + + logger.info( + "[{}] {}: {} sents, {} tokens, {:.3}% replaced by {}".format( + lang, + input_file, + n_seq_tok[0], + n_seq_tok[1], + 100 * sum(replaced.values()) / n_seq_tok[1], + vocab.unk_word, + ) + ) + + def make_binary_alignment_dataset(input_prefix, output_prefix, num_workers): + nseq = [0] + + def merge_result(worker_result): + nseq[0] += worker_result["nseq"] + + input_file = input_prefix + offsets = Binarizer.find_offsets(input_file, num_workers) + pool = None + if num_workers > 1: + pool = Pool(processes=num_workers - 1) + for worker_id in range(1, num_workers): + prefix = "{}{}".format(output_prefix, worker_id) + pool.apply_async( + binarize_alignments, + ( + args, + input_file, + utils.parse_alignment, + prefix, + offsets[worker_id], + offsets[worker_id + 1], + ), + callback=merge_result, + ) + pool.close() + + ds = indexed_dataset.make_builder( + dataset_dest_file(args, output_prefix, None, "bin"), impl=args.dataset_impl + ) + + merge_result( + Binarizer.binarize_alignments( + input_file, + utils.parse_alignment, + lambda t: ds.add_item(t), + offset=0, + end=offsets[1], + ) + ) + if num_workers > 1: + pool.join() + for worker_id in range(1, num_workers): + prefix = "{}{}".format(output_prefix, worker_id) + temp_file_path = dataset_dest_prefix(args, prefix, None) + ds.merge_file_(temp_file_path) + os.remove(indexed_dataset.data_file_path(temp_file_path)) + os.remove(indexed_dataset.index_file_path(temp_file_path)) + + ds.finalize(dataset_dest_file(args, output_prefix, None, "idx")) + + logger.info("[alignments] {}: parsed {} alignments".format(input_file, nseq[0])) + + def make_dataset(vocab, input_prefix, output_prefix, lang, num_workers=1): + if args.dataset_impl == "raw": + # Copy original text file to destination folder + output_text_file = dest_path( + output_prefix + ".{}-{}".format(args.source_lang, args.target_lang), + lang, + ) + shutil.copyfile(file_name(input_prefix, lang), output_text_file) + else: + make_binary_dataset(vocab, input_prefix, output_prefix, lang, num_workers) + + def make_all(lang, vocab): + if args.trainpref: + make_dataset(vocab, args.trainpref, "train", lang, num_workers=args.workers) + if args.validpref: + for k, validpref in enumerate(args.validpref.split(",")): + outprefix = "valid{}".format(k) if k > 0 else "valid" + make_dataset( + vocab, validpref, outprefix, lang, num_workers=args.workers + ) + if args.testpref: + for k, testpref in enumerate(args.testpref.split(",")): + outprefix = "test{}".format(k) if k > 0 else "test" + make_dataset(vocab, testpref, outprefix, lang, num_workers=args.workers) + + def make_all_alignments(): + if args.trainpref and os.path.exists(args.trainpref + "." + args.align_suffix): + make_binary_alignment_dataset( + args.trainpref + "." + args.align_suffix, + "train.align", + num_workers=args.workers, + ) + if args.validpref and os.path.exists(args.validpref + "." + args.align_suffix): + make_binary_alignment_dataset( + args.validpref + "." + args.align_suffix, + "valid.align", + num_workers=args.workers, + ) + if args.testpref and os.path.exists(args.testpref + "." + args.align_suffix): + make_binary_alignment_dataset( + args.testpref + "." + args.align_suffix, + "test.align", + num_workers=args.workers, + ) + + make_all(args.source_lang, src_dict) + if target: + make_all(args.target_lang, tgt_dict) + if args.align_suffix: + make_all_alignments() + + logger.info("Wrote preprocessed data to {}".format(args.destdir)) + + if args.alignfile: + assert args.trainpref, "--trainpref must be set if --alignfile is specified" + src_file_name = train_path(args.source_lang) + tgt_file_name = train_path(args.target_lang) + freq_map = {} + with open(args.alignfile, "r", encoding="utf-8") as align_file: + with open(src_file_name, "r", encoding="utf-8") as src_file: + with open(tgt_file_name, "r", encoding="utf-8") as tgt_file: + for a, s, t in zip_longest(align_file, src_file, tgt_file): + si = src_dict.encode_line(s, add_if_not_exist=False) + ti = tgt_dict.encode_line(t, add_if_not_exist=False) + ai = list(map(lambda x: tuple(x.split("-")), a.split())) + for sai, tai in ai: + srcidx = si[int(sai)] + tgtidx = ti[int(tai)] + if srcidx != src_dict.unk() and tgtidx != tgt_dict.unk(): + assert srcidx != src_dict.pad() + assert srcidx != src_dict.eos() + assert tgtidx != tgt_dict.pad() + assert tgtidx != tgt_dict.eos() + + if srcidx not in freq_map: + freq_map[srcidx] = {} + if tgtidx not in freq_map[srcidx]: + freq_map[srcidx][tgtidx] = 1 + else: + freq_map[srcidx][tgtidx] += 1 + + align_dict = {} + for srcidx in freq_map.keys(): + align_dict[srcidx] = max(freq_map[srcidx], key=freq_map[srcidx].get) + + with open( + os.path.join( + args.destdir, + "alignment.{}-{}.txt".format(args.source_lang, args.target_lang), + ), + "w", + encoding="utf-8", + ) as f: + for k, v in align_dict.items(): + print("{} {}".format(src_dict[k], tgt_dict[v]), file=f) + + +def binarize(args, filename, vocab, output_prefix, lang, offset, end, append_eos=True): + ds = indexed_dataset.make_builder( + dataset_dest_file(args, output_prefix, lang, "bin"), + impl=args.dataset_impl, + vocab_size=len(vocab), + ) + + def consumer(tensor): + ds.add_item(tensor) + + res = Binarizer.binarize( + filename, vocab, consumer, append_eos=append_eos, offset=offset, end=end + ) + ds.finalize(dataset_dest_file(args, output_prefix, lang, "idx")) + return res + + +def binarize_alignments(args, filename, parse_alignment, output_prefix, offset, end): + ds = indexed_dataset.make_builder( + dataset_dest_file(args, output_prefix, None, "bin"), + impl=args.dataset_impl, + vocab_size=None, + ) + + def consumer(tensor): + ds.add_item(tensor) + + res = Binarizer.binarize_alignments( + filename, parse_alignment, consumer, offset=offset, end=end + ) + ds.finalize(dataset_dest_file(args, output_prefix, None, "idx")) + return res + + +def dataset_dest_prefix(args, output_prefix, lang): + base = "{}/{}".format(args.destdir, output_prefix) + if lang is not None: + lang_part = ".{}-{}.{}".format(args.source_lang, args.target_lang, lang) + elif args.only_source: + lang_part = "" + else: + lang_part = ".{}-{}".format(args.source_lang, args.target_lang) + + return "{}{}".format(base, lang_part) + + +def dataset_dest_file(args, output_prefix, lang, extension): + base = dataset_dest_prefix(args, output_prefix, lang) + return "{}.{}".format(base, extension) + + +def get_offsets(input_file, num_workers): + return Binarizer.find_offsets(input_file, num_workers) + + +def cli_main(): + parser = options.get_preprocessing_parser() + args = parser.parse_args() + main(args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/score.py b/fairseq-tools/fairseq/fairseq_cli/score.py new file mode 100644 index 00000000..b8354eb9 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/score.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +BLEU scoring of generated translations against reference translations. +""" + +import argparse +import os +import sys + +from fairseq.data import dictionary +from fairseq.scoring import bleu + + +def get_parser(): + parser = argparse.ArgumentParser( + description="Command-line script for BLEU scoring." + ) + # fmt: off + parser.add_argument('-s', '--sys', default='-', help='system output') + parser.add_argument('-r', '--ref', required=True, help='references') + parser.add_argument('-o', '--order', default=4, metavar='N', + type=int, help='consider ngrams up to this order') + parser.add_argument('--ignore-case', action='store_true', + help='case-insensitive scoring') + parser.add_argument('--sacrebleu', action='store_true', + help='score with sacrebleu') + parser.add_argument('--sentence-bleu', action='store_true', + help='report sentence-level BLEUs (i.e., with +1 smoothing)') + # fmt: on + return parser + + +def cli_main(): + parser = get_parser() + args = parser.parse_args() + print(args) + + assert args.sys == "-" or os.path.exists( + args.sys + ), "System output file {} does not exist".format(args.sys) + assert os.path.exists(args.ref), "Reference file {} does not exist".format(args.ref) + + dict = dictionary.Dictionary() + + def readlines(fd): + for line in fd.readlines(): + if args.ignore_case: + yield line.lower() + else: + yield line + + if args.sacrebleu: + import sacrebleu + + def score(fdsys): + with open(args.ref) as fdref: + print(sacrebleu.corpus_bleu(fdsys, [fdref])) + + elif args.sentence_bleu: + + def score(fdsys): + with open(args.ref) as fdref: + scorer = bleu.Scorer(dict.pad(), dict.eos(), dict.unk()) + for i, (sys_tok, ref_tok) in enumerate( + zip(readlines(fdsys), readlines(fdref)) + ): + scorer.reset(one_init=True) + sys_tok = dict.encode_line(sys_tok) + ref_tok = dict.encode_line(ref_tok) + scorer.add(ref_tok, sys_tok) + print(i, scorer.result_string(args.order)) + + else: + + def score(fdsys): + with open(args.ref) as fdref: + scorer = bleu.Scorer(dict.pad(), dict.eos(), dict.unk()) + for sys_tok, ref_tok in zip(readlines(fdsys), readlines(fdref)): + sys_tok = dict.encode_line(sys_tok) + ref_tok = dict.encode_line(ref_tok) + scorer.add(ref_tok, sys_tok) + print(scorer.result_string(args.order)) + + if args.sys == "-": + score(sys.stdin) + else: + with open(args.sys, "r") as f: + score(f) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/train.py b/fairseq-tools/fairseq/fairseq_cli/train.py new file mode 100644 index 00000000..cd3a93b1 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/train.py @@ -0,0 +1,356 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Train a new model on one or across multiple GPUs. +""" + +import argparse +import logging +import math +import os +import random +import sys + +import numpy as np +import torch +from fairseq import ( + checkpoint_utils, + distributed_utils, + options, + quantization_utils, + tasks, + utils, +) +from fairseq.data import iterators +from fairseq.logging import meters, metrics, progress_bar +from fairseq.model_parallel.megatron_trainer import MegatronTrainer +from fairseq.trainer import Trainer + + +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), + stream=sys.stdout, +) +logger = logging.getLogger("fairseq_cli.train") + + +def main(args): + utils.import_user_module(args) + + assert ( + args.max_tokens is not None or args.batch_size is not None + ), "Must specify batch size either with --max-tokens or --batch-size" + + metrics.reset() + + np.random.seed(args.seed) + utils.set_torch_seed(args.seed) + + if distributed_utils.is_master(args): + checkpoint_utils.verify_checkpoint_directory(args.save_dir) + + # Print args + logger.info(args) + + # Setup task, e.g., translation, language modeling, etc. + task = tasks.setup_task(args) + + # Load valid dataset (we load training data below, based on the latest checkpoint) + for valid_sub_split in args.valid_subset.split(","): + task.load_dataset(valid_sub_split, combine=False, epoch=1) + + # Build model and criterion + model = task.build_model(args) + criterion = task.build_criterion(args) + logger.info(model) + logger.info("task: {} ({})".format(args.task, task.__class__.__name__)) + logger.info("model: {} ({})".format(args.arch, model.__class__.__name__)) + logger.info( + "criterion: {} ({})".format(args.criterion, criterion.__class__.__name__) + ) + logger.info( + "num. model params: {} (num. trained: {})".format( + sum(p.numel() for p in model.parameters()), + sum(p.numel() for p in model.parameters() if p.requires_grad), + ) + ) + + # (optionally) Configure quantization + if args.quantization_config_path is not None: + quantizer = quantization_utils.Quantizer( + config_path=args.quantization_config_path, + max_epoch=args.max_epoch, + max_update=args.max_update, + ) + else: + quantizer = None + + # Build trainer + if args.model_parallel_size == 1: + trainer = Trainer(args, task, model, criterion, quantizer) + else: + trainer = MegatronTrainer(args, task, model, criterion) + + logger.info( + "training on {} devices (GPUs/TPUs)".format(args.distributed_world_size) + ) + logger.info( + "max tokens per GPU = {} and max sentences per GPU = {}".format( + args.max_tokens, args.batch_size + ) + ) + + # Load the latest checkpoint if one is available and restore the + # corresponding train iterator + extra_state, epoch_itr = checkpoint_utils.load_checkpoint( + args, + trainer, + # don't cache epoch iterators for sharded datasets + disable_iterator_cache=task.has_sharded_data("train"), + ) + + # Train until the learning rate gets too small + max_epoch = args.max_epoch or math.inf + lr = trainer.get_lr() + train_meter = meters.StopwatchMeter() + train_meter.start() + + while lr > args.min_lr and epoch_itr.next_epoch_idx <= max_epoch: + # train for one epoch + valid_losses, should_stop = train(args, trainer, task, epoch_itr) + if should_stop: + break + + # only use first validation loss to update the learning rate + lr = trainer.lr_step(epoch_itr.epoch, valid_losses[0]) + + epoch_itr = trainer.get_train_iterator( + epoch_itr.next_epoch_idx, + # sharded data: get train iterator for next epoch + load_dataset=task.has_sharded_data("train"), + # don't cache epoch iterators for sharded datasets + disable_iterator_cache=task.has_sharded_data("train"), + ) + train_meter.stop() + logger.info("done training in {:.1f} seconds".format(train_meter.sum)) + + +def should_stop_early(args, valid_loss): + # skip check if no validation was done in the current epoch + if valid_loss is None: + return False + if args.patience <= 0: + return False + + def is_better(a, b): + return a > b if args.maximize_best_checkpoint_metric else a < b + + prev_best = getattr(should_stop_early, "best", None) + if prev_best is None or is_better(valid_loss, prev_best): + should_stop_early.best = valid_loss + should_stop_early.num_runs = 0 + return False + else: + should_stop_early.num_runs += 1 + if should_stop_early.num_runs >= args.patience: + logger.info( + "early stop since valid performance hasn't improved for last {} runs".format( + args.patience + ) + ) + return True + else: + return False + + +@metrics.aggregate("train") +def train(args, trainer, task, epoch_itr): + """Train the model for one epoch and return validation losses.""" + # Initialize data iterator + itr = epoch_itr.next_epoch_itr( + fix_batches_to_gpus=args.fix_batches_to_gpus, + shuffle=(epoch_itr.next_epoch_idx > args.curriculum), + ) + update_freq = ( + args.update_freq[epoch_itr.epoch - 1] + if epoch_itr.epoch <= len(args.update_freq) + else args.update_freq[-1] + ) + itr = iterators.GroupedIterator(itr, update_freq) + if getattr(args, "tpu", False): + itr = utils.tpu_data_loader(itr) + progress = progress_bar.progress_bar( + itr, + log_format=args.log_format, + log_interval=args.log_interval, + epoch=epoch_itr.epoch, + tensorboard_logdir=( + args.tensorboard_logdir if distributed_utils.is_master(args) else None + ), + default_log_format=("tqdm" if not args.no_progress_bar else "simple"), + ) + + trainer.begin_epoch(epoch_itr.epoch) + + valid_losses = [None] + valid_subsets = args.valid_subset.split(",") + should_stop = False + num_updates = trainer.get_num_updates() + for i, samples in enumerate(progress): + with metrics.aggregate("train_inner"), torch.autograd.profiler.record_function( + "train_step-%d" % i + ): + log_output = trainer.train_step(samples) + + if log_output is not None: # not OOM, overflow, ... + # log mid-epoch stats + num_updates = trainer.get_num_updates() + if num_updates % args.log_interval == 0: + stats = get_training_stats(metrics.get_smoothed_values("train_inner")) + progress.log(stats, tag="train_inner", step=num_updates) + + # reset mid-epoch stats after each log interval + # the end-of-epoch stats will still be preserved + metrics.reset_meters("train_inner") + + end_of_epoch = not itr.has_next() + valid_losses, should_stop = validate_and_save( + args, trainer, task, epoch_itr, valid_subsets, end_of_epoch + ) + + if should_stop: + break + + # log end-of-epoch stats + logger.info("end of epoch {} (average epoch stats below)".format(epoch_itr.epoch)) + stats = get_training_stats(metrics.get_smoothed_values("train")) + progress.print(stats, tag="train", step=num_updates) + + # reset epoch-level meters + metrics.reset_meters("train") + return valid_losses, should_stop + + +def validate_and_save(args, trainer, task, epoch_itr, valid_subsets, end_of_epoch): + num_updates = trainer.get_num_updates() + max_update = args.max_update or math.inf + do_save = ( + (end_of_epoch and epoch_itr.epoch % args.save_interval == 0) + or num_updates >= max_update + or ( + args.save_interval_updates > 0 + and num_updates > 0 + and num_updates % args.save_interval_updates == 0 + and num_updates >= args.validate_after_updates + ) + ) + do_validate = ( + (not end_of_epoch and do_save) # validate during mid-epoch saves + or (end_of_epoch and epoch_itr.epoch % args.validate_interval == 0) + or num_updates >= max_update + or ( + args.validate_interval_updates > 0 + and num_updates > 0 + and num_updates % args.validate_interval_updates == 0 + ) + ) and not args.disable_validation + + # Validate + valid_losses = [None] + if do_validate: + valid_losses = validate(args, trainer, task, epoch_itr, valid_subsets) + + # Stopping conditions + should_stop = ( + should_stop_early(args, valid_losses[0]) + or num_updates >= max_update + or ( + args.stop_time_hours > 0 + and trainer.cumulative_training_time() / (60 * 60) > args.stop_time_hours + ) + ) + + # Save checkpoint + if do_save or should_stop: + logger.info("begin save checkpoint") + checkpoint_utils.save_checkpoint(args, trainer, epoch_itr, valid_losses[0]) + + return valid_losses, should_stop + + +def get_training_stats(stats): + stats["wall"] = round(metrics.get_meter("default", "wall").elapsed_time, 0) + return stats + + +def validate(args, trainer, task, epoch_itr, subsets): + """Evaluate the model on the validation set(s) and return the losses.""" + + if args.fixed_validation_seed is not None: + # set fixed seed for every validation + utils.set_torch_seed(args.fixed_validation_seed) + + trainer.begin_valid_epoch(epoch_itr.epoch) + valid_losses = [] + for subset in subsets: + logger.info('begin validation on "{}" subset'.format(subset)) + + # Initialize data iterator + itr = trainer.get_valid_iterator(subset).next_epoch_itr(shuffle=False) + if getattr(args, "tpu", False): + itr = utils.tpu_data_loader(itr) + progress = progress_bar.progress_bar( + itr, + log_format=args.log_format, + log_interval=args.log_interval, + epoch=epoch_itr.epoch, + prefix=f"valid on '{subset}' subset", + tensorboard_logdir=( + args.tensorboard_logdir if distributed_utils.is_master(args) else None + ), + default_log_format=("tqdm" if not args.no_progress_bar else "simple"), + ) + + # create a new root metrics aggregator so validation metrics + # don't pollute other aggregators (e.g., train meters) + with metrics.aggregate(new_root=True) as agg: + for sample in progress: + trainer.valid_step(sample) + + # log validation stats + stats = get_valid_stats(args, trainer, agg.get_smoothed_values()) + progress.print(stats, tag=subset, step=trainer.get_num_updates()) + + valid_losses.append(stats[args.best_checkpoint_metric]) + return valid_losses + + +def get_valid_stats(args, trainer, stats): + stats["num_updates"] = trainer.get_num_updates() + if hasattr(checkpoint_utils.save_checkpoint, "best"): + key = "best_{0}".format(args.best_checkpoint_metric) + best_function = max if args.maximize_best_checkpoint_metric else min + stats[key] = best_function( + checkpoint_utils.save_checkpoint.best, stats[args.best_checkpoint_metric] + ) + return stats + + +def cli_main(modify_parser=None): + parser = options.get_training_parser() + args = options.parse_args_and_arch(parser, modify_parser=modify_parser) + if args.profile: + with torch.cuda.profiler.profile(): + with torch.autograd.profiler.emit_nvtx(): + distributed_utils.call_main(args, main) + else: + distributed_utils.call_main(args, main) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/fairseq_cli/validate.py b/fairseq-tools/fairseq/fairseq_cli/validate.py new file mode 100644 index 00000000..df857550 --- /dev/null +++ b/fairseq-tools/fairseq/fairseq_cli/validate.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 -u +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import os +import sys +from itertools import chain + +import torch +from fairseq import checkpoint_utils, distributed_utils, options, utils +from fairseq.logging import metrics, progress_bar + + +logging.basicConfig( + format="%(asctime)s | %(levelname)s | %(name)s | %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + level=os.environ.get("LOGLEVEL", "INFO").upper(), + stream=sys.stdout, +) +logger = logging.getLogger("fairseq_cli.validate") + + +def main(args, override_args=None): + utils.import_user_module(args) + + assert ( + args.max_tokens is not None or args.batch_size is not None + ), "Must specify batch size either with --max-tokens or --batch-size" + + use_fp16 = args.fp16 + use_cuda = torch.cuda.is_available() and not args.cpu + + if use_cuda: + torch.cuda.set_device(args.device_id) + + if override_args is not None: + overrides = vars(override_args) + overrides.update(eval(getattr(override_args, "model_overrides", "{}"))) + else: + overrides = None + + # Load ensemble + logger.info("loading model(s) from {}".format(args.path)) + models, model_args, task = checkpoint_utils.load_model_ensemble_and_task( + [args.path], + arg_overrides=overrides, + suffix=getattr(args, "checkpoint_suffix", ""), + ) + model = models[0] + + # Move models to GPU + for model in models: + if use_fp16: + model.half() + if use_cuda: + model.cuda() + + # Print args + logger.info(model_args) + + # Build criterion + criterion = task.build_criterion(model_args) + criterion.eval() + + for subset in args.valid_subset.split(","): + try: + task.load_dataset(subset, combine=False, epoch=1) + dataset = task.dataset(subset) + except KeyError: + raise Exception("Cannot find dataset: " + subset) + + # Initialize data iterator + itr = task.get_batch_iterator( + dataset=dataset, + max_tokens=args.max_tokens, + max_sentences=args.batch_size, + max_positions=utils.resolve_max_positions( + task.max_positions(), + *[m.max_positions() for m in models], + ), + ignore_invalid_inputs=args.skip_invalid_size_inputs_valid_test, + required_batch_size_multiple=args.required_batch_size_multiple, + seed=args.seed, + num_shards=args.distributed_world_size, + shard_id=args.distributed_rank, + num_workers=args.num_workers, + data_buffer_size=args.data_buffer_size, + ).next_epoch_itr(shuffle=False) + progress = progress_bar.progress_bar( + itr, + log_format=args.log_format, + log_interval=args.log_interval, + prefix=f"valid on '{subset}' subset", + default_log_format=("tqdm" if not args.no_progress_bar else "simple"), + ) + + log_outputs = [] + for i, sample in enumerate(progress): + sample = utils.move_to_cuda(sample) if use_cuda else sample + _loss, _sample_size, log_output = task.valid_step(sample, model, criterion) + progress.log(log_output, step=i) + log_outputs.append(log_output) + + if args.distributed_world_size > 1: + log_outputs = distributed_utils.all_gather_list( + log_outputs, + max_size=getattr(args, "all_gather_list_size", 16384), + ) + log_outputs = list(chain.from_iterable(log_outputs)) + + with metrics.aggregate() as agg: + task.reduce_metrics(log_outputs, criterion) + log_output = agg.get_smoothed_values() + + progress.print(log_output, tag=subset, step=i) + + +def cli_main(): + parser = options.get_validation_parser() + args = options.parse_args_and_arch(parser) + + # only override args that are explicitly given on the command line + override_parser = options.get_validation_parser() + override_args = options.parse_args_and_arch(override_parser, suppress_defaults=True) + + distributed_utils.call_main(args, main, override_args=override_args) + + +if __name__ == "__main__": + cli_main() diff --git a/fairseq-tools/fairseq/hubconf.py b/fairseq-tools/fairseq/hubconf.py new file mode 100644 index 00000000..ce7d76cf --- /dev/null +++ b/fairseq-tools/fairseq/hubconf.py @@ -0,0 +1,69 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import functools +import importlib + +from fairseq.hub_utils import ( # noqa; noqa + BPEHubInterface as bpe, + TokenizerHubInterface as tokenizer, +) +from fairseq.models import MODEL_REGISTRY # noqa + + +dependencies = [ + "dataclasses", + "hydra", + "numpy", + "regex", + "requests", + "torch", +] + + +# Check for required dependencies and raise a RuntimeError if any are missing. +missing_deps = [] +for dep in dependencies: + try: + importlib.import_module(dep) + except ImportError: + # Hack: the hydra package is provided under the "hydra-core" name in + # pypi. We don't want the user mistakenly calling `pip install hydra` + # since that will install an unrelated package. + if dep == "hydra": + dep = "hydra-core" + missing_deps.append(dep) +if len(missing_deps) > 0: + raise RuntimeError("Missing dependencies: {}".format(", ".join(missing_deps))) + + +# torch.hub doesn't build Cython components, so if they are not found then try +# to build them here +try: + import fairseq.data.token_block_utils_fast # noqa +except ImportError: + try: + import cython # noqa + import os + from setuptools import sandbox + + sandbox.run_setup( + os.path.join(os.path.dirname(__file__), "setup.py"), + ["build_ext", "--inplace"], + ) + except ImportError: + print( + "Unable to build Cython components. Please make sure Cython is " + "installed if the torch.hub model you are loading depends on it." + ) + + +# automatically expose models defined in FairseqModel::hub_models +for _model_type, _cls in MODEL_REGISTRY.items(): + for model_name in _cls.hub_models().keys(): + globals()[model_name] = functools.partial( + _cls.from_pretrained, + model_name, + ) diff --git a/fairseq-tools/fairseq/pyproject.toml b/fairseq-tools/fairseq/pyproject.toml new file mode 100644 index 00000000..6d1b4c5b --- /dev/null +++ b/fairseq-tools/fairseq/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel", "cython"] +build-backend = "setuptools.build_meta" diff --git a/fairseq-tools/fairseq/roberta.py b/fairseq-tools/fairseq/roberta.py new file mode 100644 index 00000000..cfab494e --- /dev/null +++ b/fairseq-tools/fairseq/roberta.py @@ -0,0 +1,40 @@ +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from fairseq.models.roberta import RobertaModel + +roberta = RobertaModel.from_pretrained( + 'checkpoints/roberta', + checkpoint_file='checkpoint_best.pt', + data_name_or_path='RTE-bin' +) + +label_fn = lambda label: roberta.task.label_dictionary.string( + [label + roberta.task.label_dictionary.nspecial] +) +ncorrect, nsamples = 0, 0 +roberta.cuda() +roberta.eval() +with open('glue_data/RTE/dev.tsv') as fin: + fin.readline() + for index, line in enumerate(fin): + tokens = line.strip().split('\t') + sent1, sent2, target = tokens[1], tokens[2], tokens[3] + tokens = roberta.encode(sent1, sent2) + prediction = roberta.predict('sentence_classification_head', tokens).argmax().item() + prediction_label = label_fn(prediction) + ncorrect += int(prediction_label == target) + nsamples += 1 +print('| Accuracy: ', float(ncorrect)/float(nsamples)) diff --git a/fairseq-tools/fairseq/roberta.sh b/fairseq-tools/fairseq/roberta.sh new file mode 100644 index 00000000..a9e063cb --- /dev/null +++ b/fairseq-tools/fairseq/roberta.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright (c) 2023, Shanghai Iluvatar CoreX Semiconductor Co., Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +set -ex + +TOTAL_NUM_UPDATES=2036 # 10 epochs through RTE for bsz 16 +WARMUP_UPDATES=122 # 6 percent of the number of updates +LR=2e-05 # Peak LR for polynomial LR scheduler. +NUM_CLASSES=2 +MAX_SENTENCES=16 # Batch size. +ROBERTA_PATH=roberta.large/model.pt + +mkdir -p checkpoints/roberta +fairseq-train RTE-bin/ \ + --restore-file $ROBERTA_PATH \ + --max-positions 512 \ + --batch-size $MAX_SENTENCES \ + --max-tokens 4400 \ + --task sentence_prediction \ + --reset-optimizer --reset-dataloader --reset-meters \ + --required-batch-size-multiple 1 \ + --init-token 0 --separator-token 2 \ + --arch roberta_large \ + --criterion sentence_prediction \ + --num-classes $NUM_CLASSES \ + --dropout 0.1 --attention-dropout 0.1 \ + --weight-decay 0.1 --optimizer adam --adam-betas "(0.9, 0.98)" --adam-eps 1e-06 \ + --clip-norm 0.0 \ + --lr-scheduler polynomial_decay --lr $LR --total-num-update $TOTAL_NUM_UPDATES --warmup-updates $WARMUP_UPDATES \ + --fp16 --fp16-init-scale 4 --threshold-loss-scale 1 --fp16-scale-window 128 \ + --max-epoch 10 \ + --find-unused-parameters \ + --save-dir checkpoints/roberta \ + --best-checkpoint-metric accuracy --maximize-best-checkpoint-metric; diff --git a/fairseq-tools/fairseq/scripts/__init__.py b/fairseq-tools/fairseq/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/scripts/average_checkpoints.py b/fairseq-tools/fairseq/scripts/average_checkpoints.py new file mode 100644 index 00000000..c512f802 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/average_checkpoints.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import collections +import os +import re + +import torch +from fairseq.file_io import PathManager + + +def average_checkpoints(inputs): + """Loads checkpoints from inputs and returns a model with averaged weights. + + Args: + inputs: An iterable of string paths of checkpoints to load from. + + Returns: + A dict of string keys mapping to various values. The 'model' key + from the returned dict should correspond to an OrderedDict mapping + string parameter names to torch Tensors. + """ + params_dict = collections.OrderedDict() + params_keys = None + new_state = None + num_models = len(inputs) + + for fpath in inputs: + with PathManager.open(fpath, "rb") as f: + state = torch.load( + f, + map_location=( + lambda s, _: torch.serialization.default_restore_location(s, "cpu") + ), + ) + # Copies over the settings from the first checkpoint + if new_state is None: + new_state = state + + model_params = state["model"] + + model_params_keys = list(model_params.keys()) + if params_keys is None: + params_keys = model_params_keys + elif params_keys != model_params_keys: + raise KeyError( + "For checkpoint {}, expected list of params: {}, " + "but found: {}".format(f, params_keys, model_params_keys) + ) + + for k in params_keys: + p = model_params[k] + if isinstance(p, torch.HalfTensor): + p = p.float() + if k not in params_dict: + params_dict[k] = p.clone() + # NOTE: clone() is needed in case of p is a shared parameter + else: + params_dict[k] += p + + averaged_params = collections.OrderedDict() + for k, v in params_dict.items(): + averaged_params[k] = v + if averaged_params[k].is_floating_point(): + averaged_params[k].div_(num_models) + else: + averaged_params[k] //= num_models + new_state["model"] = averaged_params + return new_state + + +def last_n_checkpoints(paths, n, update_based, upper_bound=None): + assert len(paths) == 1 + path = paths[0] + if update_based: + pt_regexp = re.compile(r"checkpoint_\d+_(\d+)\.pt") + else: + pt_regexp = re.compile(r"checkpoint(\d+)\.pt") + files = PathManager.ls(path) + + entries = [] + for f in files: + m = pt_regexp.fullmatch(f) + if m is not None: + sort_key = int(m.group(1)) + if upper_bound is None or sort_key <= upper_bound: + entries.append((sort_key, m.group(0))) + if len(entries) < n: + raise Exception( + "Found {} checkpoint files but need at least {}", len(entries), n + ) + return [os.path.join(path, x[1]) for x in sorted(entries, reverse=True)[:n]] + + +def main(): + parser = argparse.ArgumentParser( + description="Tool to average the params of input checkpoints to " + "produce a new checkpoint", + ) + # fmt: off + parser.add_argument('--inputs', required=True, nargs='+', + help='Input checkpoint file paths.') + parser.add_argument('--output', required=True, metavar='FILE', + help='Write the new checkpoint containing the averaged weights to this path.') + num_group = parser.add_mutually_exclusive_group() + num_group.add_argument('--num-epoch-checkpoints', type=int, + help='if set, will try to find checkpoints with names checkpoint_xx.pt in the path specified by input, ' + 'and average last this many of them.') + num_group.add_argument('--num-update-checkpoints', type=int, + help='if set, will try to find checkpoints with names checkpoint_ee_xx.pt in the path specified by input, ' + 'and average last this many of them.') + parser.add_argument('--checkpoint-upper-bound', type=int, + help='when using --num-epoch-checkpoints, this will set an upper bound on which epoch to use, ' + 'when using --num-update-checkpoints, this will set an upper bound on which update to use' + 'e.g., with --num-epoch-checkpoints=10 --checkpoint-upper-bound=50, checkpoints 41-50 would be averaged.' + 'e.g., with --num-update-checkpoints=10 --checkpoint-upper-bound=50000, checkpoints 40500-50000 would be averaged assuming --save-interval-updates 500' + ) + # fmt: on + args = parser.parse_args() + print(args) + + num = None + is_update_based = False + if args.num_update_checkpoints is not None: + num = args.num_update_checkpoints + is_update_based = True + elif args.num_epoch_checkpoints is not None: + num = args.num_epoch_checkpoints + + assert args.checkpoint_upper_bound is None or ( + args.num_epoch_checkpoints is not None + or args.num_update_checkpoints is not None + ), "--checkpoint-upper-bound requires --num-epoch-checkpoints or --num-update-checkpoints" + assert ( + args.num_epoch_checkpoints is None or args.num_update_checkpoints is None + ), "Cannot combine --num-epoch-checkpoints and --num-update-checkpoints" + + if num is not None: + args.inputs = last_n_checkpoints( + args.inputs, + num, + is_update_based, + upper_bound=args.checkpoint_upper_bound, + ) + print("averaging checkpoints: ", args.inputs) + + new_state = average_checkpoints(args.inputs) + with PathManager.open(args.output, "wb") as f: + torch.save(new_state, f) + print("Finished writing averaged checkpoint to {}".format(args.output)) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/build_sym_alignment.py b/fairseq-tools/fairseq/scripts/build_sym_alignment.py new file mode 100644 index 00000000..0ca5c18f --- /dev/null +++ b/fairseq-tools/fairseq/scripts/build_sym_alignment.py @@ -0,0 +1,97 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Use this script in order to build symmetric alignments for your translation +dataset. +This script depends on fast_align and mosesdecoder tools. You will need to +build those before running the script. +fast_align: + github: http://github.com/clab/fast_align + instructions: follow the instructions in README.md +mosesdecoder: + github: http://github.com/moses-smt/mosesdecoder + instructions: http://www.statmt.org/moses/?n=Development.GetStarted +The script produces the following files under --output_dir: + text.joined - concatenation of lines from the source_file and the + target_file. + align.forward - forward pass of fast_align. + align.backward - backward pass of fast_align. + aligned.sym_heuristic - symmetrized alignment. +""" + +import argparse +import os +from itertools import zip_longest + + +def main(): + parser = argparse.ArgumentParser(description="symmetric alignment builer") + # fmt: off + parser.add_argument('--fast_align_dir', + help='path to fast_align build directory') + parser.add_argument('--mosesdecoder_dir', + help='path to mosesdecoder root directory') + parser.add_argument('--sym_heuristic', + help='heuristic to use for symmetrization', + default='grow-diag-final-and') + parser.add_argument('--source_file', + help='path to a file with sentences ' + 'in the source language') + parser.add_argument('--target_file', + help='path to a file with sentences ' + 'in the target language') + parser.add_argument('--output_dir', + help='output directory') + # fmt: on + args = parser.parse_args() + + fast_align_bin = os.path.join(args.fast_align_dir, "fast_align") + symal_bin = os.path.join(args.mosesdecoder_dir, "bin", "symal") + sym_fast_align_bin = os.path.join( + args.mosesdecoder_dir, "scripts", "ems", "support", "symmetrize-fast-align.perl" + ) + + # create joined file + joined_file = os.path.join(args.output_dir, "text.joined") + with open(args.source_file, "r", encoding="utf-8") as src, open( + args.target_file, "r", encoding="utf-8" + ) as tgt: + with open(joined_file, "w", encoding="utf-8") as joined: + for s, t in zip_longest(src, tgt): + print("{} ||| {}".format(s.strip(), t.strip()), file=joined) + + bwd_align_file = os.path.join(args.output_dir, "align.backward") + + # run forward alignment + fwd_align_file = os.path.join(args.output_dir, "align.forward") + fwd_fast_align_cmd = "{FASTALIGN} -i {JOINED} -d -o -v > {FWD}".format( + FASTALIGN=fast_align_bin, JOINED=joined_file, FWD=fwd_align_file + ) + assert os.system(fwd_fast_align_cmd) == 0 + + # run backward alignment + bwd_align_file = os.path.join(args.output_dir, "align.backward") + bwd_fast_align_cmd = "{FASTALIGN} -i {JOINED} -d -o -v -r > {BWD}".format( + FASTALIGN=fast_align_bin, JOINED=joined_file, BWD=bwd_align_file + ) + assert os.system(bwd_fast_align_cmd) == 0 + + # run symmetrization + sym_out_file = os.path.join(args.output_dir, "aligned") + sym_cmd = "{SYMFASTALIGN} {FWD} {BWD} {SRC} {TGT} {OUT} {HEURISTIC} {SYMAL}".format( + SYMFASTALIGN=sym_fast_align_bin, + FWD=fwd_align_file, + BWD=bwd_align_file, + SRC=args.source_file, + TGT=args.target_file, + OUT=sym_out_file, + HEURISTIC=args.sym_heuristic, + SYMAL=symal_bin, + ) + assert os.system(sym_cmd) == 0 + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/compare_namespaces.py b/fairseq-tools/fairseq/scripts/compare_namespaces.py new file mode 100644 index 00000000..bc24db62 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/compare_namespaces.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +"""Helper script to compare two argparse.Namespace objects.""" + +from argparse import Namespace # noqa + + +def main(): + + ns1 = eval(input("Namespace 1: ")) + ns2 = eval(input("Namespace 2: ")) + + def keys(ns): + ks = set() + for k in dir(ns): + if not k.startswith("_"): + ks.add(k) + return ks + + k1 = keys(ns1) + k2 = keys(ns2) + + def print_keys(ks, ns1, ns2=None): + for k in ks: + if ns2 is None: + print("{}\t{}".format(k, getattr(ns1, k, None))) + else: + print( + "{}\t{}\t{}".format(k, getattr(ns1, k, None), getattr(ns2, k, None)) + ) + + print("Keys unique to namespace 1:") + print_keys(k1 - k2, ns1) + print() + + print("Keys unique to namespace 2:") + print_keys(k2 - k1, ns2) + print() + + print("Overlapping keys with different values:") + ks = [k for k in k1 & k2 if getattr(ns1, k, "None") != getattr(ns2, k, "None")] + print_keys(ks, ns1, ns2) + print() + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/compound_split_bleu.sh b/fairseq-tools/fairseq/scripts/compound_split_bleu.sh new file mode 100644 index 00000000..1972fddc --- /dev/null +++ b/fairseq-tools/fairseq/scripts/compound_split_bleu.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +if [ $# -ne 1 ]; then + echo "usage: $0 GENERATE_PY_OUTPUT" + exit 1 +fi + +GEN=$1 + +SYS=$GEN.sys +REF=$GEN.ref + +if [ $(tail -n 1 $GEN | grep BLEU | wc -l) -ne 1 ]; then + echo "not done generating" + exit +fi + +grep ^H $GEN | awk -F '\t' '{print $NF}' | perl -ple 's{(\S)-(\S)}{$1 ##AT##-##AT## $2}g' > $SYS +grep ^T $GEN | cut -f2- | perl -ple 's{(\S)-(\S)}{$1 ##AT##-##AT## $2}g' > $REF +fairseq-score --sys $SYS --ref $REF diff --git a/fairseq-tools/fairseq/scripts/constraints/extract.py b/fairseq-tools/fairseq/scripts/constraints/extract.py new file mode 100644 index 00000000..f6155d0a --- /dev/null +++ b/fairseq-tools/fairseq/scripts/constraints/extract.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +"""Extracts random constraints from reference files.""" + +import argparse +import random +import sys + +from sacrebleu import extract_ngrams + + +def get_phrase(words, index, length): + assert index < len(words) - length + 1 + phr = " ".join(words[index : index + length]) + for i in range(index, index + length): + words.pop(index) + return phr + + +def main(args): + + if args.seed: + random.seed(args.seed) + + for line in sys.stdin: + constraints = [] + + def add_constraint(constraint): + constraints.append(constraint) + + source = line.rstrip() + if "\t" in line: + source, target = line.split("\t") + if args.add_sos: + target = f"<s> {target}" + if args.add_eos: + target = f"{target} </s>" + + if len(target.split()) >= args.len: + words = [target] + + num = args.number + + choices = {} + for i in range(num): + if len(words) == 0: + break + segmentno = random.choice(range(len(words))) + segment = words.pop(segmentno) + tokens = segment.split() + phrase_index = random.choice(range(len(tokens))) + choice = " ".join( + tokens[phrase_index : min(len(tokens), phrase_index + args.len)] + ) + for j in range( + phrase_index, min(len(tokens), phrase_index + args.len) + ): + tokens.pop(phrase_index) + if phrase_index > 0: + words.append(" ".join(tokens[0:phrase_index])) + if phrase_index + 1 < len(tokens): + words.append(" ".join(tokens[phrase_index:])) + choices[target.find(choice)] = choice + + # mask out with spaces + target = target.replace(choice, " " * len(choice), 1) + + for key in sorted(choices.keys()): + add_constraint(choices[key]) + + print(source, *constraints, sep="\t") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--number", "-n", type=int, default=1, help="number of phrases") + parser.add_argument("--len", "-l", type=int, default=1, help="phrase length") + parser.add_argument( + "--add-sos", default=False, action="store_true", help="add <s> token" + ) + parser.add_argument( + "--add-eos", default=False, action="store_true", help="add </s> token" + ) + parser.add_argument("--seed", "-s", default=0, type=int) + args = parser.parse_args() + + main(args) diff --git a/fairseq-tools/fairseq/scripts/constraints/validate.py b/fairseq-tools/fairseq/scripts/constraints/validate.py new file mode 100644 index 00000000..d531ad9f --- /dev/null +++ b/fairseq-tools/fairseq/scripts/constraints/validate.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys + + +"""Reads in a fairseq output file, and verifies that the constraints +(C- lines) are present in the output (the first H- line). Assumes that +constraints are listed prior to the first hypothesis. +""" + +constraints = [] +found = 0 +total = 0 +for line in sys.stdin: + if line.startswith("C-"): + constraints.append(line.rstrip().split("\t")[1]) + elif line.startswith("H-"): + text = line.split("\t")[2] + + for constraint in constraints: + total += 1 + if constraint in text: + found += 1 + else: + print(f"No {constraint} in {text}", file=sys.stderr) + + constraints = [] + +print(f"Found {found} / {total} = {100 * found / total:.1f}%") diff --git a/fairseq-tools/fairseq/scripts/convert_dictionary.lua b/fairseq-tools/fairseq/scripts/convert_dictionary.lua new file mode 100644 index 00000000..14ee8c99 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/convert_dictionary.lua @@ -0,0 +1,34 @@ +-- Copyright (c) Facebook, Inc. and its affiliates. +-- +-- This source code is licensed under the MIT license found in the +-- LICENSE file in the root directory of this source tree. +-- +-- Usage: convert_dictionary.lua <dict.th7> +require 'fairseq' +require 'torch' +require 'paths' + +if #arg < 1 then + print('usage: convert_dictionary.lua <dict.th7>') + os.exit(1) +end +if not paths.filep(arg[1]) then + print('error: file does not exit: ' .. arg[1]) + os.exit(1) +end + +dict = torch.load(arg[1]) +dst = paths.basename(arg[1]):gsub('.th7', '.txt') +assert(dst:match('.txt$')) + +f = io.open(dst, 'w') +for idx, symbol in ipairs(dict.index_to_symbol) do + if idx > dict.cutoff then + break + end + f:write(symbol) + f:write(' ') + f:write(dict.index_to_freq[idx]) + f:write('\n') +end +f:close() diff --git a/fairseq-tools/fairseq/scripts/convert_model.lua b/fairseq-tools/fairseq/scripts/convert_model.lua new file mode 100644 index 00000000..61b92139 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/convert_model.lua @@ -0,0 +1,108 @@ +-- Copyright (c) Facebook, Inc. and its affiliates. +-- +-- This source code is licensed under the MIT license found in the +-- LICENSE file in the root directory of this source tree. +-- +-- Usage: convert_model.lua <model_epoch1.th7> +require 'torch' +local fairseq = require 'fairseq' + +model = torch.load(arg[1]) + +function find_weight_norm(container, module) + for _, wn in ipairs(container:listModules()) do + if torch.type(wn) == 'nn.WeightNorm' and wn.modules[1] == module then + return wn + end + end +end + +function push_state(dict, key, module) + if torch.type(module) == 'nn.Linear' then + local wn = find_weight_norm(model.module, module) + assert(wn) + dict[key .. '.weight_v'] = wn.v:float() + dict[key .. '.weight_g'] = wn.g:float() + elseif torch.type(module) == 'nn.TemporalConvolutionTBC' then + local wn = find_weight_norm(model.module, module) + assert(wn) + local v = wn.v:float():view(wn.viewOut):transpose(2, 3) + dict[key .. '.weight_v'] = v + dict[key .. '.weight_g'] = wn.g:float():view(module.weight:size(3), 1, 1) + else + dict[key .. '.weight'] = module.weight:float() + end + if module.bias then + dict[key .. '.bias'] = module.bias:float() + end +end + +encoder_dict = {} +decoder_dict = {} +combined_dict = {} + +function encoder_state(encoder) + luts = encoder:findModules('nn.LookupTable') + push_state(encoder_dict, 'embed_tokens', luts[1]) + push_state(encoder_dict, 'embed_positions', luts[2]) + + fcs = encoder:findModules('nn.Linear') + assert(#fcs >= 2) + local nInputPlane = fcs[1].weight:size(1) + push_state(encoder_dict, 'fc1', table.remove(fcs, 1)) + push_state(encoder_dict, 'fc2', table.remove(fcs, #fcs)) + + for i, module in ipairs(encoder:findModules('nn.TemporalConvolutionTBC')) do + push_state(encoder_dict, 'convolutions.' .. tostring(i - 1), module) + if nInputPlane ~= module.weight:size(3) / 2 then + push_state(encoder_dict, 'projections.' .. tostring(i - 1), table.remove(fcs, 1)) + end + nInputPlane = module.weight:size(3) / 2 + end + assert(#fcs == 0) +end + +function decoder_state(decoder) + luts = decoder:findModules('nn.LookupTable') + push_state(decoder_dict, 'embed_tokens', luts[1]) + push_state(decoder_dict, 'embed_positions', luts[2]) + + fcs = decoder:findModules('nn.Linear') + local nInputPlane = fcs[1].weight:size(1) + push_state(decoder_dict, 'fc1', table.remove(fcs, 1)) + push_state(decoder_dict, 'fc2', fcs[#fcs - 1]) + push_state(decoder_dict, 'fc3', fcs[#fcs]) + + table.remove(fcs, #fcs) + table.remove(fcs, #fcs) + + for i, module in ipairs(decoder:findModules('nn.TemporalConvolutionTBC')) do + if nInputPlane ~= module.weight:size(3) / 2 then + push_state(decoder_dict, 'projections.' .. tostring(i - 1), table.remove(fcs, 1)) + end + nInputPlane = module.weight:size(3) / 2 + + local prefix = 'attention.' .. tostring(i - 1) + push_state(decoder_dict, prefix .. '.in_projection', table.remove(fcs, 1)) + push_state(decoder_dict, prefix .. '.out_projection', table.remove(fcs, 1)) + push_state(decoder_dict, 'convolutions.' .. tostring(i - 1), module) + end + assert(#fcs == 0) +end + + +_encoder = model.module.modules[2] +_decoder = model.module.modules[3] + +encoder_state(_encoder) +decoder_state(_decoder) + +for k, v in pairs(encoder_dict) do + combined_dict['encoder.' .. k] = v +end +for k, v in pairs(decoder_dict) do + combined_dict['decoder.' .. k] = v +end + + +torch.save('state_dict.t7', combined_dict) diff --git a/fairseq-tools/fairseq/scripts/count_docs.py b/fairseq-tools/fairseq/scripts/count_docs.py new file mode 100644 index 00000000..58d85af8 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/count_docs.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Count the number of documents and average number of lines and tokens per +document in a large file. Documents should be separated by a single empty line. +""" + +import argparse +import gzip +import sys + +import numpy as np + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("input") + parser.add_argument("--gzip", action="store_true") + args = parser.parse_args() + + def gopen(): + if args.gzip: + return gzip.open(args.input, "r") + else: + return open(args.input, "r", encoding="utf-8") + + num_lines = [] + num_toks = [] + with gopen() as h: + num_docs = 1 + num_lines_in_doc = 0 + num_toks_in_doc = 0 + for i, line in enumerate(h): + if len(line.strip()) == 0: # empty line indicates new document + num_docs += 1 + num_lines.append(num_lines_in_doc) + num_toks.append(num_toks_in_doc) + num_lines_in_doc = 0 + num_toks_in_doc = 0 + else: + num_lines_in_doc += 1 + num_toks_in_doc += len(line.rstrip().split()) + if i % 1000000 == 0: + print(i, file=sys.stderr, end="", flush=True) + elif i % 100000 == 0: + print(".", file=sys.stderr, end="", flush=True) + print(file=sys.stderr, flush=True) + + print("found {} docs".format(num_docs)) + print("average num lines per doc: {}".format(np.mean(num_lines))) + print("average num toks per doc: {}".format(np.mean(num_toks))) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/read_binarized.py b/fairseq-tools/fairseq/scripts/read_binarized.py new file mode 100644 index 00000000..a414095d --- /dev/null +++ b/fairseq-tools/fairseq/scripts/read_binarized.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse + +from fairseq.data import Dictionary, data_utils, indexed_dataset + + +def get_parser(): + parser = argparse.ArgumentParser( + description="writes text from binarized file to stdout" + ) + # fmt: off + parser.add_argument('--dataset-impl', help='dataset implementation', + choices=indexed_dataset.get_available_dataset_impl()) + parser.add_argument('--dict', metavar='FP', help='dictionary containing known words', default=None) + parser.add_argument('--input', metavar='FP', required=True, help='binarized file to read') + # fmt: on + + return parser + + +def main(): + parser = get_parser() + args = parser.parse_args() + + dictionary = Dictionary.load(args.dict) if args.dict is not None else None + dataset = data_utils.load_indexed_dataset( + args.input, + dictionary, + dataset_impl=args.dataset_impl, + default="lazy", + ) + + for tensor_line in dataset: + if dictionary is None: + line = " ".join([str(int(x)) for x in tensor_line]) + else: + line = dictionary.string(tensor_line) + + print(line) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/rm_pt.py b/fairseq-tools/fairseq/scripts/rm_pt.py new file mode 100644 index 00000000..6cd063d2 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/rm_pt.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import os +import re +import shutil +import sys + + +pt_regexp = re.compile(r"checkpoint(\d+|_\d+_\d+|_[a-z]+)\.pt") +pt_regexp_epoch_based = re.compile(r"checkpoint(\d+)\.pt") +pt_regexp_update_based = re.compile(r"checkpoint_\d+_(\d+)\.pt") + + +def parse_checkpoints(files): + entries = [] + for f in files: + m = pt_regexp_epoch_based.fullmatch(f) + if m is not None: + entries.append((int(m.group(1)), m.group(0))) + else: + m = pt_regexp_update_based.fullmatch(f) + if m is not None: + entries.append((int(m.group(1)), m.group(0))) + return entries + + +def last_n_checkpoints(files, n): + entries = parse_checkpoints(files) + return [x[1] for x in sorted(entries, reverse=True)[:n]] + + +def every_n_checkpoints(files, n): + entries = parse_checkpoints(files) + return [x[1] for x in sorted(sorted(entries)[::-n])] + + +def main(): + parser = argparse.ArgumentParser( + description=( + "Recursively delete checkpoint files from `root_dir`, " + "but preserve checkpoint_best.pt and checkpoint_last.pt" + ) + ) + parser.add_argument("root_dirs", nargs="*") + parser.add_argument( + "--save-last", type=int, default=0, help="number of last checkpoints to save" + ) + parser.add_argument( + "--save-every", type=int, default=0, help="interval of checkpoints to save" + ) + parser.add_argument( + "--preserve-test", + action="store_true", + help="preserve checkpoints in dirs that start with test_ prefix (default: delete them)", + ) + parser.add_argument( + "--delete-best", action="store_true", help="delete checkpoint_best.pt" + ) + parser.add_argument( + "--delete-last", action="store_true", help="delete checkpoint_last.pt" + ) + parser.add_argument( + "--no-dereference", action="store_true", help="don't dereference symlinks" + ) + args = parser.parse_args() + + files_to_desymlink = [] + files_to_preserve = [] + files_to_delete = [] + for root_dir in args.root_dirs: + for root, _subdirs, files in os.walk(root_dir): + if args.save_last > 0: + to_save = last_n_checkpoints(files, args.save_last) + else: + to_save = [] + if args.save_every > 0: + to_save += every_n_checkpoints(files, args.save_every) + for file in files: + if not pt_regexp.fullmatch(file): + continue + full_path = os.path.join(root, file) + if ( + not os.path.basename(root).startswith("test_") or args.preserve_test + ) and ( + (file == "checkpoint_last.pt" and not args.delete_last) + or (file == "checkpoint_best.pt" and not args.delete_best) + or file in to_save + ): + if os.path.islink(full_path) and not args.no_dereference: + files_to_desymlink.append(full_path) + else: + files_to_preserve.append(full_path) + else: + files_to_delete.append(full_path) + + if len(files_to_desymlink) == 0 and len(files_to_delete) == 0: + print("Nothing to do.") + sys.exit(0) + + files_to_desymlink = sorted(files_to_desymlink) + files_to_preserve = sorted(files_to_preserve) + files_to_delete = sorted(files_to_delete) + + print("Operations to perform (in order):") + if len(files_to_desymlink) > 0: + for file in files_to_desymlink: + print(" - preserve (and dereference symlink): " + file) + if len(files_to_preserve) > 0: + for file in files_to_preserve: + print(" - preserve: " + file) + if len(files_to_delete) > 0: + for file in files_to_delete: + print(" - delete: " + file) + while True: + resp = input("Continue? (Y/N): ") + if resp.strip().lower() == "y": + break + elif resp.strip().lower() == "n": + sys.exit(0) + + print("Executing...") + if len(files_to_desymlink) > 0: + for file in files_to_desymlink: + realpath = os.path.realpath(file) + print("rm " + file) + os.remove(file) + print("cp {} {}".format(realpath, file)) + shutil.copyfile(realpath, file) + if len(files_to_delete) > 0: + for file in files_to_delete: + print("rm " + file) + os.remove(file) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/sacrebleu.sh b/fairseq-tools/fairseq/scripts/sacrebleu.sh new file mode 100644 index 00000000..c10bf2b7 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/sacrebleu.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ $# -ne 4 ]; then + echo "usage: $0 TESTSET SRCLANG TGTLANG GEN" + exit 1 +fi + +TESTSET=$1 +SRCLANG=$2 +TGTLANG=$3 + +GEN=$4 + +if ! command -v sacremoses &> /dev/null +then + echo "sacremoses could not be found, please install with: pip install sacremoses" + exit +fi + +grep ^H $GEN \ +| sed 's/^H\-//' \ +| sort -n -k 1 \ +| cut -f 3 \ +| sacremoses detokenize \ +> $GEN.sorted.detok + +sacrebleu --test-set $TESTSET --language-pair "${SRCLANG}-${TGTLANG}" < $GEN.sorted.detok diff --git a/fairseq-tools/fairseq/scripts/shard_docs.py b/fairseq-tools/fairseq/scripts/shard_docs.py new file mode 100644 index 00000000..97232c3c --- /dev/null +++ b/fairseq-tools/fairseq/scripts/shard_docs.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Split a large file into shards while respecting document boundaries. Documents +should be separated by a single empty line. +""" + +import argparse +import contextlib + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("input") + parser.add_argument("--num-shards", type=int) + args = parser.parse_args() + + assert args.num_shards is not None and args.num_shards > 1 + + with open(args.input, "r", encoding="utf-8") as h: + with contextlib.ExitStack() as stack: + outputs = [ + stack.enter_context( + open(args.input + ".shard" + str(i), "w", encoding="utf-8") + ) + for i in range(args.num_shards) + ] + + doc = [] + first_doc = [True] * args.num_shards + + def output_doc(i): + if not first_doc[i]: + outputs[i].write("\n") + first_doc[i] = False + for line in doc: + outputs[i].write(line) + doc.clear() + + num_docs = 0 + for line in h: + if line.strip() == "": # empty line indicates new document + output_doc(num_docs % args.num_shards) + num_docs += 1 + else: + doc.append(line) + output_doc(num_docs % args.num_shards) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/split_train_valid_docs.py b/fairseq-tools/fairseq/scripts/split_train_valid_docs.py new file mode 100644 index 00000000..ff159785 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/split_train_valid_docs.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Split a large file into a train and valid set while respecting document +boundaries. Documents should be separated by a single empty line. +""" + +import argparse +import random +import sys + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("input") + parser.add_argument("sample_output", help="train output file") + parser.add_argument("remainder_output", help="valid output file") + parser.add_argument("-k", type=int, help="remainder size") + parser.add_argument( + "--lines", action="store_true", help="split lines instead of docs" + ) + args = parser.parse_args() + + assert args.k is not None + + sample = [] + remainder = [] + num_docs = [0] + + def update_sample(doc): + if len(sample) < args.k: + sample.append(doc.copy()) + else: + i = num_docs[0] + j = random.randrange(i + 1) + if j < args.k: + remainder.append(sample[j]) + sample[j] = doc.copy() + else: + remainder.append(doc.copy()) + num_docs[0] += 1 + doc.clear() + + with open(args.input, "r", encoding="utf-8") as h: + doc = [] + for i, line in enumerate(h): + if line.strip() == "": # empty line indicates new document + update_sample(doc) + else: + doc.append(line) + if args.lines: + update_sample(doc) + if i % 1000000 == 0: + print(i, file=sys.stderr, end="", flush=True) + elif i % 100000 == 0: + print(".", file=sys.stderr, end="", flush=True) + if len(doc) > 0: + update_sample(doc) + print(file=sys.stderr, flush=True) + + assert len(sample) == args.k + + with open(args.sample_output, "w", encoding="utf-8") as out: + first = True + for doc in sample: + if not first and not args.lines: + out.write("\n") + first = False + for line in doc: + out.write(line) + + with open(args.remainder_output, "w", encoding="utf-8") as out: + first = True + for doc in remainder: + if not first and not args.lines: + out.write("\n") + first = False + for line in doc: + out.write(line) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/spm_decode.py b/fairseq-tools/fairseq/scripts/spm_decode.py new file mode 100644 index 00000000..1c18b1d2 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/spm_decode.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import argparse + +import sentencepiece as spm + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--model", required=True, help="sentencepiece model to use for decoding" + ) + parser.add_argument("--input", required=True, help="input file to decode") + parser.add_argument("--input_format", choices=["piece", "id"], default="piece") + args = parser.parse_args() + + sp = spm.SentencePieceProcessor() + sp.Load(args.model) + + if args.input_format == "piece": + + def decode(l): + return "".join(sp.DecodePieces(l)) + + elif args.input_format == "id": + + def decode(l): + return "".join(sp.DecodeIds(l)) + + else: + raise NotImplementedError + + def tok2int(tok): + # remap reference-side <unk> (represented as <<unk>>) to 0 + return int(tok) if tok != "<<unk>>" else 0 + + with open(args.input, "r", encoding="utf-8") as h: + for line in h: + if args.input_format == "id": + print(decode(list(map(tok2int, line.rstrip().split())))) + elif args.input_format == "piece": + print(decode(line.rstrip().split())) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/spm_encode.py b/fairseq-tools/fairseq/scripts/spm_encode.py new file mode 100644 index 00000000..83facfb3 --- /dev/null +++ b/fairseq-tools/fairseq/scripts/spm_encode.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import argparse +import contextlib +import sys + +import sentencepiece as spm + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--model", required=True, help="sentencepiece model to use for encoding" + ) + parser.add_argument( + "--inputs", nargs="+", default=["-"], help="input files to filter/encode" + ) + parser.add_argument( + "--outputs", nargs="+", default=["-"], help="path to save encoded outputs" + ) + parser.add_argument("--output_format", choices=["piece", "id"], default="piece") + parser.add_argument( + "--min-len", + type=int, + metavar="N", + help="filter sentence pairs with fewer than N tokens", + ) + parser.add_argument( + "--max-len", + type=int, + metavar="N", + help="filter sentence pairs with more than N tokens", + ) + args = parser.parse_args() + + assert len(args.inputs) == len( + args.outputs + ), "number of input and output paths should match" + + sp = spm.SentencePieceProcessor() + sp.Load(args.model) + + if args.output_format == "piece": + + def encode(l): + return sp.EncodeAsPieces(l) + + elif args.output_format == "id": + + def encode(l): + return list(map(str, sp.EncodeAsIds(l))) + + else: + raise NotImplementedError + + if args.min_len is not None or args.max_len is not None: + + def valid(line): + return (args.min_len is None or len(line) >= args.min_len) and ( + args.max_len is None or len(line) <= args.max_len + ) + + else: + + def valid(lines): + return True + + with contextlib.ExitStack() as stack: + inputs = [ + stack.enter_context(open(input, "r", encoding="utf-8")) + if input != "-" + else sys.stdin + for input in args.inputs + ] + outputs = [ + stack.enter_context(open(output, "w", encoding="utf-8")) + if output != "-" + else sys.stdout + for output in args.outputs + ] + + stats = { + "num_empty": 0, + "num_filtered": 0, + } + + def encode_line(line): + line = line.strip() + if len(line) > 0: + line = encode(line) + if valid(line): + return line + else: + stats["num_filtered"] += 1 + else: + stats["num_empty"] += 1 + return None + + for i, lines in enumerate(zip(*inputs), start=1): + enc_lines = list(map(encode_line, lines)) + if not any(enc_line is None for enc_line in enc_lines): + for enc_line, output_h in zip(enc_lines, outputs): + print(" ".join(enc_line), file=output_h) + if i % 10000 == 0: + print("processed {} lines".format(i), file=sys.stderr) + + print("skipped {} empty lines".format(stats["num_empty"]), file=sys.stderr) + print("filtered {} lines".format(stats["num_filtered"]), file=sys.stderr) + + +if __name__ == "__main__": + main() diff --git a/fairseq-tools/fairseq/scripts/spm_train.py b/fairseq-tools/fairseq/scripts/spm_train.py new file mode 100644 index 00000000..9db668fd --- /dev/null +++ b/fairseq-tools/fairseq/scripts/spm_train.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# Copyright (c) Facebook, Inc. and its affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. + +from __future__ import absolute_import, division, print_function, unicode_literals + +import sys + +import sentencepiece as spm + + +if __name__ == "__main__": + spm.SentencePieceTrainer.Train(" ".join(sys.argv[1:])) diff --git a/fairseq-tools/fairseq/setup.py b/fairseq-tools/fairseq/setup.py new file mode 100644 index 00000000..02ee1f11 --- /dev/null +++ b/fairseq-tools/fairseq/setup.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import sys + +from setuptools import Extension, find_packages, setup + + +if sys.version_info < (3, 6): + sys.exit("Sorry, Python >= 3.6 is required for fairseq.") + + +with open("README.md") as f: + readme = f.read() + + +if sys.platform == "darwin": + extra_compile_args = ["-stdlib=libc++", "-O3"] +else: + extra_compile_args = ["-std=c++11", "-O3"] + + +class NumpyExtension(Extension): + """Source: https://stackoverflow.com/a/54128391""" + + def __init__(self, *args, **kwargs): + self.__include_dirs = [] + super().__init__(*args, **kwargs) + + @property + def include_dirs(self): + import numpy + + return self.__include_dirs + [numpy.get_include()] + + @include_dirs.setter + def include_dirs(self, dirs): + self.__include_dirs = dirs + + +extensions = [ + Extension( + "fairseq.libbleu", + sources=[ + "fairseq/clib/libbleu/libbleu.cpp", + "fairseq/clib/libbleu/module.cpp", + ], + extra_compile_args=extra_compile_args, + ), + NumpyExtension( + "fairseq.data.data_utils_fast", + sources=["fairseq/data/data_utils_fast.pyx"], + language="c++", + extra_compile_args=extra_compile_args, + ), + NumpyExtension( + "fairseq.data.token_block_utils_fast", + sources=["fairseq/data/token_block_utils_fast.pyx"], + language="c++", + extra_compile_args=extra_compile_args, + ), +] + + +cmdclass = {} + + +try: + # torch is not available when generating docs + from torch.utils import cpp_extension + + extensions.extend( + [ + cpp_extension.CppExtension( + "fairseq.libnat", + sources=[ + "fairseq/clib/libnat/edit_dist.cpp", + ], + ) + ] + ) + + if "CUDA_HOME" in os.environ: + extensions.extend( + [ + cpp_extension.CppExtension( + "fairseq.libnat_cuda", + sources=[ + "fairseq/clib/libnat_cuda/edit_dist.cu", + "fairseq/clib/libnat_cuda/binding.cpp", + ], + ) + ] + ) + cmdclass["build_ext"] = cpp_extension.BuildExtension + +except ImportError: + pass + + +if "READTHEDOCS" in os.environ: + # don't build extensions when generating docs + extensions = [] + if "build_ext" in cmdclass: + del cmdclass["build_ext"] + + # use CPU build of PyTorch + dependency_links = [ + "https://download.pytorch.org/whl/cpu/torch-1.7.0%2Bcpu-cp36-cp36m-linux_x86_64.whl" + ] +else: + dependency_links = [] + + +if "clean" in sys.argv[1:]: + # Source: https://bit.ly/2NLVsgE + print("deleting Cython files...") + import subprocess + + subprocess.run( + ["rm -f fairseq/*.so fairseq/**/*.so fairseq/*.pyd fairseq/**/*.pyd"], + shell=True, + ) + + +extra_packages = [] +if os.path.exists(os.path.join("fairseq", "model_parallel", "megatron", "mpu")): + extra_packages.append("fairseq.model_parallel.megatron.mpu") + + +def do_setup(package_data): + setup( + name="fairseq", + version="0.10.2", + description="Facebook AI Research Sequence-to-Sequence Toolkit", + url="https://github.com/pytorch/fairseq", + classifiers=[ + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3.6", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + ], + long_description=readme, + long_description_content_type="text/markdown", + setup_requires=[ + "cython", + "numpy", + "setuptools>=18.0", + ], + install_requires=[ + "cffi", + "cython", + "dataclasses", + "hydra-core", + "numpy", + "regex", + "sacrebleu>=1.4.12", + "torch", + "tqdm", + ], + dependency_links=dependency_links, + packages=find_packages( + exclude=[ + "examples", + "examples.*", + "scripts", + "scripts.*", + "tests", + "tests.*", + ] + ) + extra_packages, + package_data=package_data, + ext_modules=extensions, + test_suite="tests", + entry_points={ + "console_scripts": [ + "fairseq-eval-lm = fairseq_cli.eval_lm:cli_main", + "fairseq-generate = fairseq_cli.generate:cli_main", + "fairseq-interactive = fairseq_cli.interactive:cli_main", + "fairseq-preprocess = fairseq_cli.preprocess:cli_main", + "fairseq-score = fairseq_cli.score:cli_main", + "fairseq-train = fairseq_cli.train:cli_main", + "fairseq-validate = fairseq_cli.validate:cli_main", + ], + }, + cmdclass=cmdclass, + zip_safe=False, + ) + + +def get_files(path, relative_to="fairseq"): + all_files = [] + for root, _dirs, files in os.walk(path, followlinks=True): + root = os.path.relpath(root, relative_to) + for file in files: + if file.endswith(".pyc"): + continue + all_files.append(os.path.join(root, file)) + return all_files + + +try: + # symlink examples into fairseq package so package_data accepts them + fairseq_examples = os.path.join("fairseq", "examples") + if "build_ext" not in sys.argv[1:] and not os.path.exists(fairseq_examples): + os.symlink(os.path.join("..", "examples"), fairseq_examples) + package_data = { + "fairseq": get_files("fairseq/config") + get_files("fairseq/examples"), + } + do_setup(package_data) +finally: + if "build_ext" not in sys.argv[1:] and os.path.exists(fairseq_examples): + os.unlink(fairseq_examples) diff --git a/fairseq-tools/fairseq/tests/__init__.py b/fairseq-tools/fairseq/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/tests/gpu/__init__.py b/fairseq-tools/fairseq/tests/gpu/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/tests/gpu/test_binaries_gpu.py b/fairseq-tools/fairseq/tests/gpu/test_binaries_gpu.py new file mode 100644 index 00000000..2ac60a09 --- /dev/null +++ b/fairseq-tools/fairseq/tests/gpu/test_binaries_gpu.py @@ -0,0 +1,305 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import logging +import os +import tempfile +import unittest +from io import StringIO + +import torch +from fairseq import options +from fairseq_cli import train +from tests.utils import ( + create_dummy_data, + generate_main, + preprocess_lm_data, + preprocess_translation_data, + train_translation_model, +) + + +class TestTranslationGPU(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_fp16(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_fp16") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model(data_dir, "fconv_iwslt_de_en", ["--fp16"]) + generate_main(data_dir) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_memory_efficient_fp16(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_memory_efficient_fp16") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, "fconv_iwslt_de_en", ["--memory-efficient-fp16"] + ) + generate_main(data_dir) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_transformer_fp16(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_transformer") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "transformer_iwslt_de_en", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "64", + "--decoder-embed-dim", + "64", + "--fp16", + ], + run_validation=True, + ) + generate_main(data_dir) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_levenshtein_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_levenshtein_transformer" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--joined-dictionary"]) + train_translation_model( + data_dir, + "levenshtein_transformer", + [ + "--apply-bert-init", + "--early-exit", + "6,6,6", + "--criterion", + "nat_loss", + ], + task="translation_lev", + ) + generate_main( + data_dir, + [ + "--task", + "translation_lev", + "--iter-decode-max-iter", + "9", + "--iter-decode-eos-penalty", + "0", + "--print-step", + ], + ) + + +def _quantize_language_model(data_dir, arch, extra_flags=None, run_validation=False): + train_parser = options.get_training_parser() + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "language_modeling", + data_dir, + "--arch", + arch, + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "adaptive_loss", + "--adaptive-softmax-cutoff", + "5,10,15", + "--max-tokens", + "500", + "--tokens-per-sample", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + ] + + (extra_flags or []), + ) + train.main(train_args) + + # try scalar quantization + scalar_quant_train_parser = options.get_training_parser() + scalar_quant_train_args = options.parse_args_and_arch( + scalar_quant_train_parser, + [ + "--task", + "language_modeling", + data_dir, + "--arch", + arch, + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "adaptive_loss", + "--adaptive-softmax-cutoff", + "5,10,15", + "--max-tokens", + "500", + "--tokens-per-sample", + "500", + "--save-dir", + data_dir, + "--max-update", + "3", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + "--quant-noise-scalar", + "0.5", + ] + + (extra_flags or []), + ) + train.main(scalar_quant_train_args) + + # try iterative PQ quantization + quantize_parser = options.get_training_parser() + quantize_args = options.parse_args_and_arch( + quantize_parser, + [ + "--task", + "language_modeling", + data_dir, + "--arch", + arch, + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "adaptive_loss", + "--adaptive-softmax-cutoff", + "5,10,15", + "--max-tokens", + "50", + "--tokens-per-sample", + "50", + "--max-update", + "6", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + "--restore-file", + os.path.join(data_dir, "checkpoint_last.pt"), + "--reset-optimizer", + "--quantization-config-path", + os.path.join( + os.path.dirname(__file__), "transformer_quantization_config.yaml" + ), + ] + + (extra_flags or []), + ) + train.main(quantize_args) + + +class TestQuantization(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_quantization(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_quantization") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + # tests both scalar and iterative PQ quantization + _quantize_language_model(data_dir, "transformer_lm") + + +class TestOptimizersGPU(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_flat_grads(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_flat_grads") as data_dir: + # Use just a bit of data and tiny model to keep this test runtime reasonable + create_dummy_data(data_dir, num_examples=10, maxlen=5) + preprocess_translation_data(data_dir) + with self.assertRaises(RuntimeError): + # adafactor isn't compatible with flat grads, which + # are used by default with --fp16 + train_translation_model( + data_dir, + "lstm", + [ + "--required-batch-size-multiple", + "1", + "--encoder-layers", + "1", + "--encoder-hidden-size", + "32", + "--decoder-layers", + "1", + "--optimizer", + "adafactor", + "--fp16", + ], + ) + # but it should pass once we set --fp16-no-flatten-grads + train_translation_model( + data_dir, + "lstm", + [ + "--required-batch-size-multiple", + "1", + "--encoder-layers", + "1", + "--encoder-hidden-size", + "32", + "--decoder-layers", + "1", + "--optimizer", + "adafactor", + "--fp16", + "--fp16-no-flatten-grads", + ], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/gpu/transformer_quantization_config.yaml b/fairseq-tools/fairseq/tests/gpu/transformer_quantization_config.yaml new file mode 100644 index 00000000..de31d811 --- /dev/null +++ b/fairseq-tools/fairseq/tests/gpu/transformer_quantization_config.yaml @@ -0,0 +1,28 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This file defines example configuration arguments for quantizing +# a transformer model with product quantization + +n_centroids: + Linear: + key: in_features + value: {"*": 8} + Embedding: + key: embedding_dim + value: {"*": 8} + +block_sizes: + Linear: + key: fuzzy_name + value: {fc: 8, attn: 4, emb: 4} + Embedding: + key: fuzzy_name + value: {emb: 8} + +layers_to_quantize: + - decoder\\.layers\\.\d+\\.fc[12] + - decoder\\.embed_tokens\\.embeddings\\.[012]\\.[01] + - decoder\\.layers\\.\d+\\.self_attn\\.(k_proj|v_proj|q_proj|out_proj) diff --git a/fairseq-tools/fairseq/tests/speech_recognition/__init__.py b/fairseq-tools/fairseq/tests/speech_recognition/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/fairseq-tools/fairseq/tests/speech_recognition/asr_test_base.py b/fairseq-tools/fairseq/tests/speech_recognition/asr_test_base.py new file mode 100644 index 00000000..03410313 --- /dev/null +++ b/fairseq-tools/fairseq/tests/speech_recognition/asr_test_base.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python3 + +import argparse +import os +import unittest +from inspect import currentframe, getframeinfo + +import numpy as np +import torch +from examples.speech_recognition.data.data_utils import lengths_to_encoder_padding_mask +from fairseq.data import data_utils as fairseq_data_utils +from fairseq.data.dictionary import Dictionary +from fairseq.models import ( + BaseFairseqModel, + FairseqDecoder, + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqEncoderModel, + FairseqModel, +) +from fairseq.tasks.fairseq_task import LegacyFairseqTask + + +DEFAULT_TEST_VOCAB_SIZE = 100 + + +# /////////////////////////////////////////////////////////////////////////// +# utility function to setup dummy dict/task/input +# /////////////////////////////////////////////////////////////////////////// + + +def get_dummy_dictionary(vocab_size=DEFAULT_TEST_VOCAB_SIZE): + dummy_dict = Dictionary() + # add dummy symbol to satisfy vocab size + for id, _ in enumerate(range(vocab_size)): + dummy_dict.add_symbol("{}".format(id), 1000) + return dummy_dict + + +class DummyTask(LegacyFairseqTask): + def __init__(self, args): + super().__init__(args) + self.dictionary = get_dummy_dictionary() + if getattr(self.args, "ctc", False): + self.dictionary.add_symbol("<ctc_blank>") + self.tgt_dict = self.dictionary + + @property + def target_dictionary(self): + return self.dictionary + + +def get_dummy_task_and_parser(): + """ + to build a fariseq model, we need some dummy parse and task. This function + is used to create dummy task and parser to faciliate model/criterion test + + Note: we use FbSpeechRecognitionTask as the dummy task. You may want + to use other task by providing another function + """ + parser = argparse.ArgumentParser( + description="test_dummy_s2s_task", argument_default=argparse.SUPPRESS + ) + DummyTask.add_args(parser) + args = parser.parse_args([]) + task = DummyTask.setup_task(args) + return task, parser + + +def get_dummy_input(T=100, D=80, B=5, K=100): + forward_input = {} + # T max sequence length + # D feature vector dimension + # B batch size + # K target dimension size + feature = torch.randn(B, T, D) + # this (B, T, D) layout is just a convention, you can override it by + # write your own _prepare_forward_input function + src_lengths = torch.from_numpy( + np.random.randint(low=1, high=T, size=B, dtype=np.int64) + ) + src_lengths[0] = T # make sure the maximum length matches + prev_output_tokens = [] + for b in range(B): + token_length = np.random.randint(low=1, high=src_lengths[b].item() + 1) + tokens = np.random.randint(low=0, high=K, size=token_length, dtype=np.int64) + prev_output_tokens.append(torch.from_numpy(tokens)) + + prev_output_tokens = fairseq_data_utils.collate_tokens( + prev_output_tokens, + pad_idx=1, + eos_idx=2, + left_pad=False, + move_eos_to_beginning=False, + ) + src_lengths, sorted_order = src_lengths.sort(descending=True) + forward_input["src_tokens"] = feature.index_select(0, sorted_order) + forward_input["src_lengths"] = src_lengths + forward_input["prev_output_tokens"] = prev_output_tokens + + return forward_input + + +def get_dummy_encoder_output(encoder_out_shape=(100, 80, 5)): + """ + This only provides an example to generate dummy encoder output + """ + (T, B, D) = encoder_out_shape + encoder_out = {} + + encoder_out["encoder_out"] = torch.from_numpy( + np.random.randn(*encoder_out_shape).astype(np.float32) + ) + seq_lengths = torch.from_numpy(np.random.randint(low=1, high=T, size=B)) + # some dummy mask + encoder_out["encoder_padding_mask"] = torch.arange(T).view(1, T).expand( + B, -1 + ) >= seq_lengths.view(B, 1).expand(-1, T) + encoder_out["encoder_padding_mask"].t_() + + # encoer_padding_mask is (T, B) tensor, with (t, b)-th element indicate + # whether encoder_out[t, b] is valid (=0) or not (=1) + return encoder_out + + +def _current_postion_info(): + cf = currentframe() + frameinfo = " (at {}:{})".format( + os.path.basename(getframeinfo(cf).filename), cf.f_back.f_lineno + ) + return frameinfo + + +def check_encoder_output(encoder_output, batch_size=None): + """we expect encoder_output to be a dict with the following + key/value pairs: + - encoder_out: a Torch.Tensor + - encoder_padding_mask: a binary Torch.Tensor + """ + if not isinstance(encoder_output, dict): + msg = ( + "FairseqEncoderModel.forward(...) must be a dict" + _current_postion_info() + ) + return False, msg + + if "encoder_out" not in encoder_output: + msg = ( + "FairseqEncoderModel.forward(...) must contain encoder_out" + + _current_postion_info() + ) + return False, msg + + if "encoder_padding_mask" not in encoder_output: + msg = ( + "FairseqEncoderModel.forward(...) must contain encoder_padding_mask" + + _current_postion_info() + ) + return False, msg + + if not isinstance(encoder_output["encoder_out"], torch.Tensor): + msg = "encoder_out must be a torch.Tensor" + _current_postion_info() + return False, msg + + if encoder_output["encoder_out"].dtype != torch.float32: + msg = "encoder_out must have float32 dtype" + _current_postion_info() + return False, msg + + mask = encoder_output["encoder_padding_mask"] + if mask is not None: + if not isinstance(mask, torch.Tensor): + msg = ( + "encoder_padding_mask must be a torch.Tensor" + _current_postion_info() + ) + return False, msg + if mask.dtype != torch.uint8 and ( + not hasattr(torch, "bool") or mask.dtype != torch.bool + ): + msg = ( + "encoder_padding_mask must have dtype of uint8" + + _current_postion_info() + ) + return False, msg + + if mask.dim() != 2: + msg = ( + "we expect encoder_padding_mask to be a 2-d tensor, in shape (T, B)" + + _current_postion_info() + ) + return False, msg + + if batch_size is not None and mask.size(1) != batch_size: + msg = ( + "we expect encoder_padding_mask to be a 2-d tensor, with size(1)" + + " being the batch size" + + _current_postion_info() + ) + return False, msg + return True, None + + +def check_decoder_output(decoder_output): + """we expect output from a decoder is a tuple with the following constraint: + - the first element is a torch.Tensor + - the second element can be anything (reserved for future use) + """ + if not isinstance(decoder_output, tuple): + msg = "FariseqDecoder output must be a tuple" + _current_postion_info() + return False, msg + + if len(decoder_output) != 2: + msg = "FairseqDecoder output must be 2-elem tuple" + _current_postion_info() + return False, msg + + if not isinstance(decoder_output[0], torch.Tensor): + msg = ( + "FariseqDecoder output[0] must be a torch.Tensor" + _current_postion_info() + ) + return False, msg + + return True, None + + +# /////////////////////////////////////////////////////////////////////////// +# Base Test class +# /////////////////////////////////////////////////////////////////////////// + + +class TestBaseFairseqModelBase(unittest.TestCase): + """ + This class is used to facilitate writing unittest for any class derived from + `BaseFairseqModel`. + """ + + @classmethod + def setUpClass(cls): + if cls is TestBaseFairseqModelBase: + raise unittest.SkipTest("Skipping test case in base") + super().setUpClass() + + def setUpModel(self, model): + self.assertTrue(isinstance(model, BaseFairseqModel)) + self.model = model + + def setupInput(self): + pass + + def setUp(self): + self.model = None + self.forward_input = None + pass + + +class TestFairseqEncoderDecoderModelBase(TestBaseFairseqModelBase): + """ + base code to test FairseqEncoderDecoderModel (formally known as + `FairseqModel`) must be derived from this base class + """ + + @classmethod + def setUpClass(cls): + if cls is TestFairseqEncoderDecoderModelBase: + raise unittest.SkipTest("Skipping test case in base") + super().setUpClass() + + def setUpModel(self, model_cls, extra_args_setters=None): + self.assertTrue( + issubclass(model_cls, (FairseqEncoderDecoderModel, FairseqModel)), + msg="This class only tests for FairseqModel subclasses", + ) + + task, parser = get_dummy_task_and_parser() + model_cls.add_args(parser) + + args = parser.parse_args([]) + if extra_args_setters is not None: + for args_setter in extra_args_setters: + args_setter(args) + model = model_cls.build_model(args, task) + self.model = model + + def setUpInput(self, input=None): + self.forward_input = get_dummy_input() if input is None else input + + def setUp(self): + super().setUp() + + def test_forward(self): + if self.model and self.forward_input: + forward_output = self.model.forward(**self.forward_input) + # for FairseqEncoderDecoderModel, forward returns a tuple of two + # elements, the first one is a Torch.Tensor + succ, msg = check_decoder_output(forward_output) + if not succ: + self.assertTrue(succ, msg=msg) + self.forward_output = forward_output + + def test_get_normalized_probs(self): + if self.model and self.forward_input: + forward_output = self.model.forward(**self.forward_input) + logprob = self.model.get_normalized_probs(forward_output, log_probs=True) + prob = self.model.get_normalized_probs(forward_output, log_probs=False) + + # in order for different models/criterion to play with each other + # we need to know whether the logprob or prob output is batch_first + # or not. We assume an additional attribute will be attached to logprob + # or prob. If you find your code failed here, simply override + # FairseqModel.get_normalized_probs, see example at + # https://fburl.com/batch_first_example + self.assertTrue(hasattr(logprob, "batch_first")) + self.assertTrue(hasattr(prob, "batch_first")) + + self.assertTrue(torch.is_tensor(logprob)) + self.assertTrue(torch.is_tensor(prob)) + + +class TestFairseqEncoderModelBase(TestBaseFairseqModelBase): + """ + base class to test FairseqEncoderModel + """ + + @classmethod + def setUpClass(cls): + if cls is TestFairseqEncoderModelBase: + raise unittest.SkipTest("Skipping test case in base") + super().setUpClass() + + def setUpModel(self, model_cls, extra_args_setters=None): + self.assertTrue( + issubclass(model_cls, FairseqEncoderModel), + msg="This class is only used for testing FairseqEncoderModel", + ) + task, parser = get_dummy_task_and_parser() + model_cls.add_args(parser) + args = parser.parse_args([]) + if extra_args_setters is not None: + for args_setter in extra_args_setters: + args_setter(args) + + model = model_cls.build_model(args, task) + self.model = model + + def setUpInput(self, input=None): + self.forward_input = get_dummy_input() if input is None else input + # get_dummy_input() is originally for s2s, here we delete extra dict + # items, so it can be used for EncoderModel / Encoder as well + self.forward_input.pop("prev_output_tokens", None) + + def setUp(self): + super().setUp() + + def test_forward(self): + if self.forward_input and self.model: + bsz = self.forward_input["src_tokens"].size(0) + forward_output = self.model.forward(**self.forward_input) + + # we expect forward_output to be a dict with the following + # key/value pairs: + # - encoder_out: a Torch.Tensor + # - encoder_padding_mask: a binary Torch.Tensor + succ, msg = check_encoder_output(forward_output, batch_size=bsz) + if not succ: + self.assertTrue(succ, msg=msg) + self.forward_output = forward_output + + def test_get_normalized_probs(self): + if self.model and self.forward_input: + forward_output = self.model.forward(**self.forward_input) + logprob = self.model.get_normalized_probs(forward_output, log_probs=True) + prob = self.model.get_normalized_probs(forward_output, log_probs=False) + + # in order for different models/criterion to play with each other + # we need to know whether the logprob or prob output is batch_first + # or not. We assume an additional attribute will be attached to logprob + # or prob. If you find your code failed here, simply override + # FairseqModel.get_normalized_probs, see example at + # https://fburl.com/batch_first_example + self.assertTrue(hasattr(logprob, "batch_first")) + self.assertTrue(hasattr(prob, "batch_first")) + + self.assertTrue(torch.is_tensor(logprob)) + self.assertTrue(torch.is_tensor(prob)) + + +class TestFairseqEncoderBase(unittest.TestCase): + """ + base class to test FairseqEncoder + """ + + @classmethod + def setUpClass(cls): + if cls is TestFairseqEncoderBase: + raise unittest.SkipTest("Skipping test case in base") + super().setUpClass() + + def setUpEncoder(self, encoder): + self.assertTrue( + isinstance(encoder, FairseqEncoder), + msg="This class is only used for test FairseqEncoder", + ) + self.encoder = encoder + + def setUpInput(self, input=None): + self.forward_input = get_dummy_input() if input is None else input + # get_dummy_input() is originally for s2s, here we delete extra dict + # items, so it can be used for EncoderModel / Encoder as well + self.forward_input.pop("prev_output_tokens", None) + + def setUp(self): + self.encoder = None + self.forward_input = None + + def test_forward(self): + if self.encoder and self.forward_input: + bsz = self.forward_input["src_tokens"].size(0) + + forward_output = self.encoder.forward(**self.forward_input) + succ, msg = check_encoder_output(forward_output, batch_size=bsz) + if not succ: + self.assertTrue(succ, msg=msg) + self.forward_output = forward_output + + +class TestFairseqDecoderBase(unittest.TestCase): + """ + base class to test FairseqDecoder + """ + + @classmethod + def setUpClass(cls): + if cls is TestFairseqDecoderBase: + raise unittest.SkipTest("Skipping test case in base") + super().setUpClass() + + def setUpDecoder(self, decoder): + self.assertTrue( + isinstance(decoder, FairseqDecoder), + msg="This class is only used for test FairseqDecoder", + ) + self.decoder = decoder + + def setUpInput(self, input=None): + self.forward_input = get_dummy_encoder_output() if input is None else input + + def setUpPrevOutputTokens(self, tokens=None): + if tokens is None: + self.encoder_input = get_dummy_input() + self.prev_output_tokens = self.encoder_input["prev_output_tokens"] + else: + self.prev_output_tokens = tokens + + def setUp(self): + self.decoder = None + self.forward_input = None + self.prev_output_tokens = None + + def test_forward(self): + if ( + self.decoder is not None + and self.forward_input is not None + and self.prev_output_tokens is not None + ): + forward_output = self.decoder.forward( + prev_output_tokens=self.prev_output_tokens, + encoder_out=self.forward_input, + ) + succ, msg = check_decoder_output(forward_output) + if not succ: + self.assertTrue(succ, msg=msg) + self.forward_input = forward_output + + +class DummyEncoderModel(FairseqEncoderModel): + def __init__(self, encoder): + super().__init__(encoder) + + @classmethod + def build_model(cls, args, task): + return cls(DummyEncoder()) + + def get_logits(self, net_output): + # Inverse of sigmoid to use with BinaryCrossEntropyWithLogitsCriterion as + # F.binary_cross_entropy_with_logits combines sigmoid and CE + return torch.log( + torch.div(net_output["encoder_out"], 1 - net_output["encoder_out"]) + ) + + def get_normalized_probs(self, net_output, log_probs, sample=None): + lprobs = super().get_normalized_probs(net_output, log_probs, sample=sample) + lprobs.batch_first = True + return lprobs + + +class DummyEncoder(FairseqEncoder): + def __init__(self): + super().__init__(None) + + def forward(self, src_tokens, src_lengths): + mask, max_len = lengths_to_encoder_padding_mask(src_lengths) + return {"encoder_out": src_tokens, "encoder_padding_mask": mask} + + +class CrossEntropyCriterionTestBase(unittest.TestCase): + @classmethod + def setUpClass(cls): + if cls is CrossEntropyCriterionTestBase: + raise unittest.SkipTest("Skipping base class test case") + super().setUpClass() + + def setUpArgs(self): + args = argparse.Namespace() + args.sentence_avg = False + args.threshold = 0.1 # to use with BinaryCrossEntropyWithLogitsCriterion + return args + + def setUp(self): + args = self.setUpArgs() + self.model = DummyEncoderModel(encoder=DummyEncoder()) + self.criterion = self.criterion_cls.build_criterion( + args=args, task=DummyTask(args) + ) + + def get_src_tokens(self, correct_prediction, aggregate): + """ + correct_prediction: True if the net_output (src_tokens) should + predict the correct target + aggregate: True if the criterion expects net_output (src_tokens) + aggregated across time axis + """ + predicted_idx = 0 if correct_prediction else 1 + if aggregate: + src_tokens = torch.zeros((2, 2), dtype=torch.float) + for b in range(2): + src_tokens[b][predicted_idx] = 1.0 + else: + src_tokens = torch.zeros((2, 10, 2), dtype=torch.float) + for b in range(2): + for t in range(10): + src_tokens[b][t][predicted_idx] = 1.0 + return src_tokens + + def get_target(self, soft_target): + if soft_target: + target = torch.zeros((2, 2), dtype=torch.float) + for b in range(2): + target[b][0] = 1.0 + else: + target = torch.zeros((2, 10), dtype=torch.long) + return target + + def get_test_sample(self, correct, soft_target, aggregate): + src_tokens = self.get_src_tokens(correct, aggregate) + target = self.get_target(soft_target) + L = src_tokens.size(1) + return { + "net_input": {"src_tokens": src_tokens, "src_lengths": torch.tensor([L])}, + "target": target, + "ntokens": src_tokens.size(0) * src_tokens.size(1), + } diff --git a/fairseq-tools/fairseq/tests/speech_recognition/test_collaters.py b/fairseq-tools/fairseq/tests/speech_recognition/test_collaters.py new file mode 100644 index 00000000..6a5029a4 --- /dev/null +++ b/fairseq-tools/fairseq/tests/speech_recognition/test_collaters.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import numpy as np +import torch +from examples.speech_recognition.data.collaters import Seq2SeqCollater + + +class TestSeq2SeqCollator(unittest.TestCase): + def test_collate(self): + + eos_idx = 1 + pad_idx = 0 + collater = Seq2SeqCollater( + feature_index=0, label_index=1, pad_index=pad_idx, eos_index=eos_idx + ) + + # 2 frames in the first sample and 3 frames in the second one + frames1 = np.array([[7, 8], [9, 10]]) + frames2 = np.array([[1, 2], [3, 4], [5, 6]]) + target1 = np.array([4, 2, 3, eos_idx]) + target2 = np.array([3, 2, eos_idx]) + sample1 = {"id": 0, "data": [frames1, target1]} + sample2 = {"id": 1, "data": [frames2, target2]} + batch = collater.collate([sample1, sample2]) + + # collate sort inputs by frame's length before creating the batch + self.assertTensorEqual(batch["id"], torch.tensor([1, 0])) + self.assertEqual(batch["ntokens"], 7) + self.assertTensorEqual( + batch["net_input"]["src_tokens"], + torch.tensor( + [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [pad_idx, pad_idx]]] + ), + ) + self.assertTensorEqual( + batch["net_input"]["prev_output_tokens"], + torch.tensor([[eos_idx, 3, 2, pad_idx], [eos_idx, 4, 2, 3]]), + ) + self.assertTensorEqual(batch["net_input"]["src_lengths"], torch.tensor([3, 2])) + self.assertTensorEqual( + batch["target"], + torch.tensor([[3, 2, eos_idx, pad_idx], [4, 2, 3, eos_idx]]), + ) + self.assertEqual(batch["nsentences"], 2) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/speech_recognition/test_cross_entropy.py b/fairseq-tools/fairseq/tests/speech_recognition/test_cross_entropy.py new file mode 100644 index 00000000..b05400ed --- /dev/null +++ b/fairseq-tools/fairseq/tests/speech_recognition/test_cross_entropy.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from examples.speech_recognition.criterions.cross_entropy_acc import ( + CrossEntropyWithAccCriterion, +) + +from .asr_test_base import CrossEntropyCriterionTestBase + + +class CrossEntropyWithAccCriterionTest(CrossEntropyCriterionTestBase): + def setUp(self): + self.criterion_cls = CrossEntropyWithAccCriterion + super().setUp() + + def test_cross_entropy_all_correct(self): + sample = self.get_test_sample(correct=True, soft_target=False, aggregate=False) + loss, sample_size, logging_output = self.criterion( + self.model, sample, "sum", log_probs=True + ) + assert logging_output["correct"] == 20 + assert logging_output["total"] == 20 + assert logging_output["sample_size"] == 20 + assert logging_output["ntokens"] == 20 + + def test_cross_entropy_all_wrong(self): + sample = self.get_test_sample(correct=False, soft_target=False, aggregate=False) + loss, sample_size, logging_output = self.criterion( + self.model, sample, "sum", log_probs=True + ) + assert logging_output["correct"] == 0 + assert logging_output["total"] == 20 + assert logging_output["sample_size"] == 20 + assert logging_output["ntokens"] == 20 diff --git a/fairseq-tools/fairseq/tests/speech_recognition/test_data_utils.py b/fairseq-tools/fairseq/tests/speech_recognition/test_data_utils.py new file mode 100644 index 00000000..a72e0b66 --- /dev/null +++ b/fairseq-tools/fairseq/tests/speech_recognition/test_data_utils.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +import unittest + +import torch +from examples.speech_recognition.data import data_utils + + +class DataUtilsTest(unittest.TestCase): + def test_normalization(self): + sample_len1 = torch.tensor( + [ + [ + -0.7661, + -1.3889, + -2.0972, + -0.9134, + -0.7071, + -0.9765, + -0.8700, + -0.8283, + 0.7512, + 1.3211, + 2.1532, + 2.1174, + 1.2800, + 1.2633, + 1.6147, + 1.6322, + 2.0723, + 3.1522, + 3.2852, + 2.2309, + 2.5569, + 2.2183, + 2.2862, + 1.5886, + 0.8773, + 0.8725, + 1.2662, + 0.9899, + 1.1069, + 1.3926, + 1.2795, + 1.1199, + 1.1477, + 1.2687, + 1.3843, + 1.1903, + 0.8355, + 1.1367, + 1.2639, + 1.4707, + ] + ] + ) + out = data_utils.apply_mv_norm(sample_len1) + assert not torch.isnan(out).any() + assert (out == sample_len1).all() diff --git a/fairseq-tools/fairseq/tests/speech_recognition/test_vggtransformer.py b/fairseq-tools/fairseq/tests/speech_recognition/test_vggtransformer.py new file mode 100644 index 00000000..4dc73b8c --- /dev/null +++ b/fairseq-tools/fairseq/tests/speech_recognition/test_vggtransformer.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python3 + +# import models/encoder/decoder to be tested +from examples.speech_recognition.models.vggtransformer import ( + TransformerDecoder, + VGGTransformerEncoder, + VGGTransformerModel, + vggtransformer_1, + vggtransformer_2, + vggtransformer_base, +) + +# import base test class +from .asr_test_base import ( + DEFAULT_TEST_VOCAB_SIZE, + TestFairseqDecoderBase, + TestFairseqEncoderBase, + TestFairseqEncoderDecoderModelBase, + get_dummy_dictionary, + get_dummy_encoder_output, + get_dummy_input, +) + + +class VGGTransformerModelTest_mid(TestFairseqEncoderDecoderModelBase): + def setUp(self): + def override_config(args): + """ + vggtrasformer_1 use 14 layers of transformer, + for testing purpose, it is too expensive. For fast turn-around + test, reduce the number of layers to 3. + """ + args.transformer_enc_config = ( + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 3" + ) + + super().setUp() + extra_args_setter = [vggtransformer_1, override_config] + + self.setUpModel(VGGTransformerModel, extra_args_setter) + self.setUpInput(get_dummy_input(T=50, D=80, B=5, K=DEFAULT_TEST_VOCAB_SIZE)) + + +class VGGTransformerModelTest_big(TestFairseqEncoderDecoderModelBase): + def setUp(self): + def override_config(args): + """ + vggtrasformer_2 use 16 layers of transformer, + for testing purpose, it is too expensive. For fast turn-around + test, reduce the number of layers to 3. + """ + args.transformer_enc_config = ( + "((1024, 16, 4096, True, 0.15, 0.15, 0.15),) * 3" + ) + + super().setUp() + extra_args_setter = [vggtransformer_2, override_config] + + self.setUpModel(VGGTransformerModel, extra_args_setter) + self.setUpInput(get_dummy_input(T=50, D=80, B=5, K=DEFAULT_TEST_VOCAB_SIZE)) + + +class VGGTransformerModelTest_base(TestFairseqEncoderDecoderModelBase): + def setUp(self): + def override_config(args): + """ + vggtrasformer_base use 12 layers of transformer, + for testing purpose, it is too expensive. For fast turn-around + test, reduce the number of layers to 3. + """ + args.transformer_enc_config = ( + "((512, 8, 2048, True, 0.15, 0.15, 0.15),) * 3" + ) + + super().setUp() + extra_args_setter = [vggtransformer_base, override_config] + + self.setUpModel(VGGTransformerModel, extra_args_setter) + self.setUpInput(get_dummy_input(T=50, D=80, B=5, K=DEFAULT_TEST_VOCAB_SIZE)) + + +class VGGTransformerEncoderTest(TestFairseqEncoderBase): + def setUp(self): + super().setUp() + + self.setUpInput(get_dummy_input(T=50, D=80, B=5)) + + def test_forward(self): + print("1. test standard vggtransformer") + self.setUpEncoder(VGGTransformerEncoder(input_feat_per_channel=80)) + super().test_forward() + print("2. test vggtransformer with limited right context") + self.setUpEncoder( + VGGTransformerEncoder( + input_feat_per_channel=80, transformer_context=(-1, 5) + ) + ) + super().test_forward() + print("3. test vggtransformer with limited left context") + self.setUpEncoder( + VGGTransformerEncoder( + input_feat_per_channel=80, transformer_context=(5, -1) + ) + ) + super().test_forward() + print("4. test vggtransformer with limited right context and sampling") + self.setUpEncoder( + VGGTransformerEncoder( + input_feat_per_channel=80, + transformer_context=(-1, 12), + transformer_sampling=(2, 2), + ) + ) + super().test_forward() + print("5. test vggtransformer with windowed context and sampling") + self.setUpEncoder( + VGGTransformerEncoder( + input_feat_per_channel=80, + transformer_context=(12, 12), + transformer_sampling=(2, 2), + ) + ) + + +class TransformerDecoderTest(TestFairseqDecoderBase): + def setUp(self): + super().setUp() + + dict = get_dummy_dictionary(vocab_size=DEFAULT_TEST_VOCAB_SIZE) + decoder = TransformerDecoder(dict) + dummy_encoder_output = get_dummy_encoder_output(encoder_out_shape=(50, 5, 256)) + + self.setUpDecoder(decoder) + self.setUpInput(dummy_encoder_output) + self.setUpPrevOutputTokens() diff --git a/fairseq-tools/fairseq/tests/test_average_checkpoints.py b/fairseq-tools/fairseq/tests/test_average_checkpoints.py new file mode 100644 index 00000000..f348b56b --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_average_checkpoints.py @@ -0,0 +1,134 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import collections +import os +import shutil +import tempfile +import unittest + +import numpy as np +import torch +from scripts.average_checkpoints import average_checkpoints +from torch import nn + + +class ModelWithSharedParameter(nn.Module): + def __init__(self): + super(ModelWithSharedParameter, self).__init__() + self.embedding = nn.Embedding(1000, 200) + self.FC1 = nn.Linear(200, 200) + self.FC2 = nn.Linear(200, 200) + # tie weight in FC2 to FC1 + self.FC2.weight = nn.Parameter(self.FC1.weight) + self.FC2.bias = nn.Parameter(self.FC1.bias) + + self.relu = nn.ReLU() + + def forward(self, input): + return self.FC2(self.ReLU(self.FC1(input))) + self.FC1(input) + + +class TestAverageCheckpoints(unittest.TestCase): + def test_average_checkpoints(self): + params_0 = collections.OrderedDict( + [ + ("a", torch.DoubleTensor([100.0])), + ("b", torch.FloatTensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])), + ("c", torch.IntTensor([7, 8, 9])), + ] + ) + params_1 = collections.OrderedDict( + [ + ("a", torch.DoubleTensor([1.0])), + ("b", torch.FloatTensor([[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]])), + ("c", torch.IntTensor([2, 2, 2])), + ] + ) + params_avg = collections.OrderedDict( + [ + ("a", torch.DoubleTensor([50.5])), + ("b", torch.FloatTensor([[1.0, 1.5, 2.0], [2.5, 3.0, 3.5]])), + # We expect truncation for integer division + ("c", torch.IntTensor([4, 5, 5])), + ] + ) + + fd_0, path_0 = tempfile.mkstemp() + fd_1, path_1 = tempfile.mkstemp() + torch.save(collections.OrderedDict([("model", params_0)]), path_0) + torch.save(collections.OrderedDict([("model", params_1)]), path_1) + + output = average_checkpoints([path_0, path_1])["model"] + + os.close(fd_0) + os.remove(path_0) + os.close(fd_1) + os.remove(path_1) + + for (k_expected, v_expected), (k_out, v_out) in zip( + params_avg.items(), output.items() + ): + self.assertEqual( + k_expected, + k_out, + "Key mismatch - expected {} but found {}. " + "(Expected list of keys: {} vs actual list of keys: {})".format( + k_expected, k_out, params_avg.keys(), output.keys() + ), + ) + np.testing.assert_allclose( + v_expected.numpy(), + v_out.numpy(), + err_msg="Tensor value mismatch for key {}".format(k_expected), + ) + + def test_average_checkpoints_with_shared_parameters(self): + def _construct_model_with_shared_parameters(path, value): + m = ModelWithSharedParameter() + nn.init.constant_(m.FC1.weight, value) + torch.save({"model": m.state_dict()}, path) + return m + + tmpdir = tempfile.mkdtemp() + paths = [] + path = os.path.join(tmpdir, "m1.pt") + m1 = _construct_model_with_shared_parameters(path, 1.0) + paths.append(path) + + path = os.path.join(tmpdir, "m2.pt") + m2 = _construct_model_with_shared_parameters(path, 2.0) + paths.append(path) + + path = os.path.join(tmpdir, "m3.pt") + m3 = _construct_model_with_shared_parameters(path, 3.0) + paths.append(path) + + new_model = average_checkpoints(paths) + self.assertTrue( + torch.equal( + new_model["model"]["embedding.weight"], + (m1.embedding.weight + m2.embedding.weight + m3.embedding.weight) / 3.0, + ) + ) + + self.assertTrue( + torch.equal( + new_model["model"]["FC1.weight"], + (m1.FC1.weight + m2.FC1.weight + m3.FC1.weight) / 3.0, + ) + ) + + self.assertTrue( + torch.equal( + new_model["model"]["FC2.weight"], + (m1.FC2.weight + m2.FC2.weight + m3.FC2.weight) / 3.0, + ) + ) + shutil.rmtree(tmpdir) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_backtranslation_dataset.py b/fairseq-tools/fairseq/tests/test_backtranslation_dataset.py new file mode 100644 index 00000000..dffc3b49 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_backtranslation_dataset.py @@ -0,0 +1,123 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import tests.utils as test_utils +import torch +from fairseq.data import ( + BacktranslationDataset, + LanguagePairDataset, + TransformEosDataset, +) +from fairseq.sequence_generator import SequenceGenerator + + +class TestBacktranslationDataset(unittest.TestCase): + def setUp(self): + ( + self.tgt_dict, + self.w1, + self.w2, + self.src_tokens, + self.src_lengths, + self.model, + ) = test_utils.sequence_generator_setup() + + dummy_src_samples = self.src_tokens + + self.tgt_dataset = test_utils.TestDataset(data=dummy_src_samples) + self.cuda = torch.cuda.is_available() + + def _backtranslation_dataset_helper( + self, + remove_eos_from_input_src, + remove_eos_from_output_src, + ): + tgt_dataset = LanguagePairDataset( + src=self.tgt_dataset, + src_sizes=self.tgt_dataset.sizes, + src_dict=self.tgt_dict, + tgt=None, + tgt_sizes=None, + tgt_dict=None, + ) + + generator = SequenceGenerator( + [self.model], + tgt_dict=self.tgt_dict, + max_len_a=0, + max_len_b=200, + beam_size=2, + unk_penalty=0, + ) + + backtranslation_dataset = BacktranslationDataset( + tgt_dataset=TransformEosDataset( + dataset=tgt_dataset, + eos=self.tgt_dict.eos(), + # remove eos from the input src + remove_eos_from_src=remove_eos_from_input_src, + ), + src_dict=self.tgt_dict, + backtranslation_fn=( + lambda sample: generator.generate([self.model], sample) + ), + output_collater=TransformEosDataset( + dataset=tgt_dataset, + eos=self.tgt_dict.eos(), + # if we remove eos from the input src, then we need to add it + # back to the output tgt + append_eos_to_tgt=remove_eos_from_input_src, + remove_eos_from_src=remove_eos_from_output_src, + ).collater, + cuda=self.cuda, + ) + dataloader = torch.utils.data.DataLoader( + backtranslation_dataset, + batch_size=2, + collate_fn=backtranslation_dataset.collater, + ) + backtranslation_batch_result = next(iter(dataloader)) + + eos, pad, w1, w2 = self.tgt_dict.eos(), self.tgt_dict.pad(), self.w1, self.w2 + + # Note that we sort by src_lengths and add left padding, so actually + # ids will look like: [1, 0] + expected_src = torch.LongTensor([[w1, w2, w1, eos], [pad, pad, w1, eos]]) + if remove_eos_from_output_src: + expected_src = expected_src[:, :-1] + expected_tgt = torch.LongTensor([[w1, w2, eos], [w1, w2, eos]]) + generated_src = backtranslation_batch_result["net_input"]["src_tokens"] + tgt_tokens = backtranslation_batch_result["target"] + + self.assertTensorEqual(expected_src, generated_src) + self.assertTensorEqual(expected_tgt, tgt_tokens) + + def test_backtranslation_dataset_no_eos_in_output_src(self): + self._backtranslation_dataset_helper( + remove_eos_from_input_src=False, + remove_eos_from_output_src=True, + ) + + def test_backtranslation_dataset_with_eos_in_output_src(self): + self._backtranslation_dataset_helper( + remove_eos_from_input_src=False, + remove_eos_from_output_src=False, + ) + + def test_backtranslation_dataset_no_eos_in_input_src(self): + self._backtranslation_dataset_helper( + remove_eos_from_input_src=True, + remove_eos_from_output_src=False, + ) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_binaries.py b/fairseq-tools/fairseq/tests/test_binaries.py new file mode 100644 index 00000000..ca18adea --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_binaries.py @@ -0,0 +1,1571 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import logging +import os +import random +import sys +import tempfile +import unittest +from io import StringIO + +import torch +from fairseq import options +from fairseq_cli import eval_lm, train, validate +from tests.utils import ( + create_dummy_data, + generate_main, + preprocess_lm_data, + preprocess_summarization_data, + preprocess_translation_data, + train_translation_model, +) + + +class TestTranslation(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_fconv(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_fconv") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model(data_dir, "fconv_iwslt_de_en") + generate_main(data_dir) + + def test_raw(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_fconv_raw") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--dataset-impl", "raw"]) + train_translation_model( + data_dir, "fconv_iwslt_de_en", ["--dataset-impl", "raw"] + ) + generate_main(data_dir, ["--dataset-impl", "raw"]) + + def test_update_freq(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_update_freq") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, "fconv_iwslt_de_en", ["--update-freq", "3"] + ) + generate_main(data_dir) + + def test_max_positions(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_max_positions") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + with self.assertRaises(Exception) as context: + train_translation_model( + data_dir, + "fconv_iwslt_de_en", + ["--max-target-positions", "5"], + ) + self.assertTrue( + "skip this example with --skip-invalid-size-inputs-valid-test" + in str(context.exception) + ) + train_translation_model( + data_dir, + "fconv_iwslt_de_en", + [ + "--max-target-positions", + "5", + "--skip-invalid-size-inputs-valid-test", + ], + ) + with self.assertRaises(Exception) as context: + generate_main(data_dir) + generate_main(data_dir, ["--skip-invalid-size-inputs-valid-test"]) + + def test_generation(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_sampling") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model(data_dir, "fconv_iwslt_de_en") + generate_main( + data_dir, + [ + "--sampling", + "--temperature", + "2", + "--beam", + "2", + "--nbest", + "2", + ], + ) + generate_main( + data_dir, + [ + "--sampling", + "--sampling-topk", + "3", + "--beam", + "2", + "--nbest", + "2", + ], + ) + generate_main( + data_dir, + [ + "--sampling", + "--sampling-topp", + "0.2", + "--beam", + "2", + "--nbest", + "2", + ], + ) + generate_main( + data_dir, + [ + "--diversity-rate", + "0.5", + "--beam", + "6", + ], + ) + with self.assertRaises(ValueError): + generate_main( + data_dir, + [ + "--diverse-beam-groups", + "4", + "--match-source-len", + ], + ) + generate_main(data_dir, ["--prefix-size", "2"]) + generate_main(data_dir, ["--retain-dropout"]) + + def test_eval_bleu(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_eval_bleu") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "fconv_iwslt_de_en", + [ + "--eval-bleu", + "--eval-bleu-print-samples", + "--eval-bleu-remove-bpe", + "--eval-bleu-detok", + "space", + "--eval-bleu-args", + '{"beam": 4, "min_len": 10}', + ], + ) + + def test_lstm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lstm") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "lstm_wiseman_iwslt_de_en", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--decoder-out-embed-dim", + "8", + ], + ) + generate_main(data_dir) + + def test_lstm_bidirectional(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lstm_bidirectional") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "lstm", + [ + "--encoder-layers", + "2", + "--encoder-bidirectional", + "--encoder-hidden-size", + "16", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--decoder-out-embed-dim", + "8", + "--decoder-layers", + "2", + ], + ) + generate_main(data_dir) + + def test_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_transformer") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "transformer_iwslt_de_en", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + ], + run_validation=True, + ) + generate_main(data_dir) + + def test_multilingual_transformer(self): + # test with all combinations of encoder/decoder lang tokens + encoder_langtok_flags = [ + [], + ["--encoder-langtok", "src"], + ["--encoder-langtok", "tgt"], + ] + decoder_langtok_flags = [[], ["--decoder-langtok"]] + with contextlib.redirect_stdout(StringIO()): + for i in range(len(encoder_langtok_flags)): + for j in range(len(decoder_langtok_flags)): + enc_ltok_flag = encoder_langtok_flags[i] + dec_ltok_flag = decoder_langtok_flags[j] + with tempfile.TemporaryDirectory( + f"test_multilingual_transformer_{i}_{j}" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + arch="multilingual_transformer", + task="multilingual_translation", + extra_flags=[ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + ] + + enc_ltok_flag + + dec_ltok_flag, + lang_flags=["--lang-pairs", "in-out,out-in"], + run_validation=True, + extra_valid_flags=enc_ltok_flag + dec_ltok_flag, + ) + generate_main( + data_dir, + extra_flags=[ + "--task", + "multilingual_translation", + "--lang-pairs", + "in-out,out-in", + "--source-lang", + "in", + "--target-lang", + "out", + ] + + enc_ltok_flag + + dec_ltok_flag, + ) + + @unittest.skipIf(sys.platform.lower() == "darwin", "skip latent depth test on MacOS") + def test_multilingual_translation_latent_depth(self): + # test with latent depth in encoder, decoder, or both + encoder_latent_layer = [[], ["--encoder-latent-layer"]] + decoder_latent_layer = [[], ["--decoder-latent-layer"]] + with contextlib.redirect_stdout(StringIO()): + for i in range(len(encoder_latent_layer)): + for j in range(len(decoder_latent_layer)): + if i == 0 and j == 0: + continue + enc_ll_flag = encoder_latent_layer[i] + dec_ll_flag = decoder_latent_layer[j] + with tempfile.TemporaryDirectory( + f"test_multilingual_translation_latent_depth_{i}_{j}" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data( + data_dir, extra_flags=["--joined-dictionary"] + ) + train_translation_model( + data_dir, + arch="latent_multilingual_transformer", + task="multilingual_translation_latent_depth", + extra_flags=[ + "--user-dir", + "examples/latent_depth/latent_depth_src", + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--share-encoders", + "--share-decoders", + "--sparsity-weight", + "0.1", + ] + + enc_ll_flag + + dec_ll_flag, + lang_flags=["--lang-pairs", "in-out,out-in"], + run_validation=True, + extra_valid_flags=[ + "--user-dir", + "examples/latent_depth/latent_depth_src", + ] + + enc_ll_flag + + dec_ll_flag, + ) + generate_main( + data_dir, + extra_flags=[ + "--user-dir", + "examples/latent_depth/latent_depth_src", + "--task", + "multilingual_translation_latent_depth", + "--lang-pairs", + "in-out,out-in", + "--source-lang", + "in", + "--target-lang", + "out", + ] + + enc_ll_flag + + dec_ll_flag, + ) + + def test_translation_multi_simple_epoch(self): + # test with all combinations of encoder/decoder lang tokens + encoder_langtok_flags = [ + [], + ["--encoder-langtok", "src"], + ["--encoder-langtok", "tgt"], + ] + decoder_langtok_flags = [[], ["--decoder-langtok"]] + with contextlib.redirect_stdout(StringIO()): + for i in range(len(encoder_langtok_flags)): + for j in range(len(decoder_langtok_flags)): + enc_ltok_flag = encoder_langtok_flags[i] + dec_ltok_flag = decoder_langtok_flags[j] + with tempfile.TemporaryDirectory( + f"test_translation_multi_simple_epoch_{i}_{j}" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data( + data_dir, extra_flags=["--joined-dictionary"] + ) + train_translation_model( + data_dir, + arch="transformer", + task="translation_multi_simple_epoch", + extra_flags=[ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--sampling-method", + "temperature", + "--sampling-temperature", + "1.5", + "--virtual-epoch-size", + "1000", + ] + + enc_ltok_flag + + dec_ltok_flag, + lang_flags=["--lang-pairs", "in-out,out-in"], + run_validation=True, + extra_valid_flags=enc_ltok_flag + dec_ltok_flag, + ) + generate_main( + data_dir, + extra_flags=[ + "--task", + "translation_multi_simple_epoch", + "--lang-pairs", + "in-out,out-in", + "--source-lang", + "in", + "--target-lang", + "out", + ] + + enc_ltok_flag + + dec_ltok_flag, + ) + + def test_transformer_cross_self_attention(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_transformer_cross_self_attention" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "transformer_iwslt_de_en", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--no-cross-attention", + "--cross-self-attention", + ], + run_validation=True, + ) + generate_main(data_dir, extra_flags=[]) + + def test_transformer_pointer_generator(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_transformer_pointer_generator" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_summarization_data(data_dir) + train_translation_model( + data_dir, + "transformer_pointer_generator", + extra_flags=[ + "--user-dir", + "examples/pointer_generator/pointer_generator_src", + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--alignment-layer", + "-1", + "--alignment-heads", + "1", + "--source-position-markers", + "0", + ], + run_validation=True, + extra_valid_flags=["--user-dir", "examples/pointer_generator/pointer_generator_src"], + ) + generate_main( + data_dir, + extra_flags=["--user-dir", "examples/pointer_generator/pointer_generator_src"], + ) + + def test_lightconv(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lightconv") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "lightconv_iwslt_de_en", + [ + "--encoder-conv-type", + "lightweight", + "--decoder-conv-type", + "lightweight", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + ], + ) + generate_main(data_dir) + + def test_dynamicconv(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_dynamicconv") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "lightconv_iwslt_de_en", + [ + "--encoder-conv-type", + "dynamic", + "--decoder-conv-type", + "dynamic", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + ], + ) + generate_main(data_dir) + + def test_cmlm_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_cmlm_transformer") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--joined-dictionary"]) + train_translation_model( + data_dir, + "cmlm_transformer", + [ + "--apply-bert-init", + "--criterion", + "nat_loss", + "--noise", + "full_mask", + "--pred-length-offset", + "--length-loss-factor", + "0.1", + ], + task="translation_lev", + ) + generate_main( + data_dir, + [ + "--task", + "translation_lev", + "--iter-decode-max-iter", + "9", + "--iter-decode-eos-penalty", + "0", + "--print-step", + ], + ) + + def test_nonautoregressive_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_nonautoregressive_transformer" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--joined-dictionary"]) + train_translation_model( + data_dir, + "nonautoregressive_transformer", + [ + "--apply-bert-init", + "--src-embedding-copy", + "--criterion", + "nat_loss", + "--noise", + "full_mask", + "--pred-length-offset", + "--length-loss-factor", + "0.1", + ], + task="translation_lev", + ) + generate_main( + data_dir, + [ + "--task", + "translation_lev", + "--iter-decode-max-iter", + "0", + "--iter-decode-eos-penalty", + "0", + "--print-step", + ], + ) + + # def test_nat_crf_transformer(self): + # with contextlib.redirect_stdout(StringIO()): + # with tempfile.TemporaryDirectory('test_nat_crf_transformer') as data_dir: + # create_dummy_data(data_dir) + # preprocess_translation_data(data_dir, ['--joined-dictionary']) + # train_translation_model(data_dir, 'nacrf_transformer', [ + # '--apply-bert-init', '--criterion', + # 'nat_loss', '--noise', 'full_mask', '--pred-length-offset', + # '--length-loss-factor', '0.1', + # '--word-ins-loss-factor', '0.5', + # '--crf-lowrank-approx', '1', + # '--crf-beam-approx', '1' + # ], task='translation_lev') + # generate_main(data_dir, [ + # '--task', 'translation_lev', + # '--iter-decode-max-iter', '0', + # '--iter-decode-eos-penalty', '0', + # '--print-step', + # ]) + + def test_iterative_nonautoregressive_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_iterative_nonautoregressive_transformer" + ) as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--joined-dictionary"]) + train_translation_model( + data_dir, + "iterative_nonautoregressive_transformer", + [ + "--apply-bert-init", + "--src-embedding-copy", + "--criterion", + "nat_loss", + "--noise", + "full_mask", + "--stochastic-approx", + "--dae-ratio", + "0.5", + "--train-step", + "3", + ], + task="translation_lev", + ) + generate_main( + data_dir, + [ + "--task", + "translation_lev", + "--iter-decode-max-iter", + "9", + "--iter-decode-eos-penalty", + "0", + "--print-step", + ], + ) + + def test_insertion_transformer(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_insertion_transformer") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir, ["--joined-dictionary"]) + train_translation_model( + data_dir, + "insertion_transformer", + [ + "--apply-bert-init", + "--criterion", + "nat_loss", + "--noise", + "random_mask", + ], + task="translation_lev", + ) + generate_main( + data_dir, + [ + "--task", + "translation_lev", + "--iter-decode-max-iter", + "9", + "--iter-decode-eos-penalty", + "0", + "--print-step", + ], + ) + + def test_mixture_of_experts(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_moe") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + train_translation_model( + data_dir, + "transformer_iwslt_de_en", + [ + "--task", + "translation_moe", + "--user-dir", + "examples/translation_moe/translation_moe_src", + "--method", + "hMoElp", + "--mean-pool-gating-network", + "--num-experts", + "3", + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + ], + ) + generate_main( + data_dir, + [ + "--task", + "translation_moe", + "--user-dir", + "examples/translation_moe/translation_moe_src", + "--method", + "hMoElp", + "--mean-pool-gating-network", + "--num-experts", + "3", + "--gen-expert", + "0", + ], + ) + + def test_alignment(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_alignment") as data_dir: + create_dummy_data(data_dir, alignment=True) + preprocess_translation_data(data_dir, ["--align-suffix", "align"]) + train_translation_model( + data_dir, + "transformer_align", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--load-alignments", + "--alignment-layer", + "1", + "--criterion", + "label_smoothed_cross_entropy_with_alignment", + ], + run_validation=True, + ) + generate_main(data_dir) + + def test_alignment_full_context(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_alignment") as data_dir: + create_dummy_data(data_dir, alignment=True) + preprocess_translation_data(data_dir, ["--align-suffix", "align"]) + train_translation_model( + data_dir, + "transformer_align", + [ + "--encoder-layers", + "2", + "--decoder-layers", + "2", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--load-alignments", + "--alignment-layer", + "1", + "--criterion", + "label_smoothed_cross_entropy_with_alignment", + "--full-context-alignment", + ], + run_validation=True, + ) + generate_main(data_dir) + + +class TestStories(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_fconv_self_att_wp(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_fconv_self_att_wp") as data_dir: + create_dummy_data(data_dir) + preprocess_translation_data(data_dir) + config = [ + "--encoder-layers", + "[(128, 3)] * 2", + "--decoder-layers", + "[(128, 3)] * 2", + "--decoder-attention", + "True", + "--encoder-attention", + "False", + "--gated-attention", + "True", + "--self-attention", + "True", + "--project-input", + "True", + "--encoder-embed-dim", + "8", + "--decoder-embed-dim", + "8", + "--decoder-out-embed-dim", + "8", + "--multihead-self-attention-nheads", + "2", + ] + train_translation_model(data_dir, "fconv_self_att_wp", config) + generate_main(data_dir) + + # fusion model + os.rename( + os.path.join(data_dir, "checkpoint_last.pt"), + os.path.join(data_dir, "pretrained.pt"), + ) + config.extend( + [ + "--pretrained", + "True", + "--pretrained-checkpoint", + os.path.join(data_dir, "pretrained.pt"), + "--save-dir", + os.path.join(data_dir, "fusion_model"), + ] + ) + train_translation_model(data_dir, "fconv_self_att_wp", config) + + +class TestLanguageModeling(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_fconv_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_fconv_lm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_language_model( + data_dir, + "fconv_lm", + [ + "--decoder-layers", + "[(850, 3)] * 2 + [(1024,4)]", + "--decoder-embed-dim", + "280", + "--optimizer", + "nag", + "--lr", + "0.1", + ], + ) + eval_lm_main(data_dir) + generate_main( + data_dir, + [ + "--task", + "language_modeling", + "--sample-break-mode", + "eos", + "--tokens-per-sample", + "500", + ], + ) + + def test_transformer_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_transformer_lm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_language_model( + data_dir, + "transformer_lm", + ["--add-bos-token"], + run_validation=True, + ) + eval_lm_main(data_dir) + generate_main( + data_dir, + [ + "--task", + "language_modeling", + "--sample-break-mode", + "eos", + "--tokens-per-sample", + "500", + ], + ) + + def test_lightconv_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lightconv_lm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_language_model( + data_dir, + "lightconv_lm", + ["--add-bos-token"], + run_validation=True, + ) + eval_lm_main(data_dir) + generate_main( + data_dir, + [ + "--task", + "language_modeling", + "--sample-break-mode", + "eos", + "--tokens-per-sample", + "500", + ], + ) + + def test_lstm_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lstm_lm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_language_model( + data_dir, + "lstm_lm", + ["--add-bos-token"], + run_validation=True, + ) + eval_lm_main(data_dir) + generate_main( + data_dir, + [ + "--task", + "language_modeling", + "--sample-break-mode", + "eos", + "--tokens-per-sample", + "500", + ], + ) + + def test_lstm_lm_residuals(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_lstm_lm_residuals") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_language_model( + data_dir, + "lstm_lm", + ["--add-bos-token", "--residuals"], + run_validation=True, + ) + eval_lm_main(data_dir) + generate_main( + data_dir, + [ + "--task", + "language_modeling", + "--sample-break-mode", + "eos", + "--tokens-per-sample", + "500", + ], + ) + + +class TestMaskedLanguageModel(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_legacy_masked_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_legacy_mlm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_legacy_masked_language_model(data_dir, "masked_lm") + + def test_roberta_masked_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_roberta_mlm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_masked_lm( + data_dir, "roberta_base", extra_flags=["--encoder-layers", "2"] + ) + + def test_roberta_sentence_prediction(self): + num_classes = 3 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_roberta_head") as data_dir: + create_dummy_roberta_head_data(data_dir, num_classes=num_classes) + preprocess_lm_data(os.path.join(data_dir, "input0")) + preprocess_lm_data(os.path.join(data_dir, "label")) + train_roberta_head(data_dir, "roberta_base", num_classes=num_classes) + + def test_roberta_regression_single(self): + num_classes = 1 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_roberta_regression_single" + ) as data_dir: + create_dummy_roberta_head_data( + data_dir, num_classes=num_classes, regression=True + ) + preprocess_lm_data(os.path.join(data_dir, "input0")) + train_roberta_head( + data_dir, + "roberta_base", + num_classes=num_classes, + extra_flags=["--regression-target"], + ) + + def test_roberta_regression_multiple(self): + num_classes = 3 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_roberta_regression_multiple" + ) as data_dir: + create_dummy_roberta_head_data( + data_dir, num_classes=num_classes, regression=True + ) + preprocess_lm_data(os.path.join(data_dir, "input0")) + train_roberta_head( + data_dir, + "roberta_base", + num_classes=num_classes, + extra_flags=["--regression-target"], + ) + + def test_linformer_roberta_masked_lm(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_linformer_roberta_mlm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_masked_lm( + data_dir, + "linformer_roberta_base", + extra_flags=[ + "--user-dir", + "examples/linformer/linformer_src", + "--encoder-layers", + "2", + ], + ) + + def test_linformer_roberta_sentence_prediction(self): + num_classes = 3 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_linformer_roberta_head") as data_dir: + create_dummy_roberta_head_data(data_dir, num_classes=num_classes) + preprocess_lm_data(os.path.join(data_dir, "input0")) + preprocess_lm_data(os.path.join(data_dir, "label")) + train_roberta_head( + data_dir, + "linformer_roberta_base", + num_classes=num_classes, + extra_flags=["--user-dir", "examples/linformer/linformer_src"], + ) + + def test_linformer_roberta_regression_single(self): + num_classes = 1 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_linformer_roberta_regression_single" + ) as data_dir: + create_dummy_roberta_head_data( + data_dir, num_classes=num_classes, regression=True + ) + preprocess_lm_data(os.path.join(data_dir, "input0")) + train_roberta_head( + data_dir, + "linformer_roberta_base", + num_classes=num_classes, + extra_flags=[ + "--regression-target", + "--user-dir", + "examples/linformer/linformer_src", + ], + ) + + def test_linformer_roberta_regression_multiple(self): + num_classes = 3 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory( + "test_linformer_roberta_regression_multiple" + ) as data_dir: + create_dummy_roberta_head_data( + data_dir, num_classes=num_classes, regression=True + ) + preprocess_lm_data(os.path.join(data_dir, "input0")) + train_roberta_head( + data_dir, + "linformer_roberta_base", + num_classes=num_classes, + extra_flags=[ + "--regression-target", + "--user-dir", + "examples/linformer/linformer_src", + ], + ) + + def _test_pretrained_masked_lm_for_translation(self, learned_pos_emb, encoder_only): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_mlm") as data_dir: + create_dummy_data(data_dir) + preprocess_lm_data(data_dir) + train_legacy_masked_language_model( + data_dir, + arch="masked_lm", + extra_args=("--encoder-learned-pos",) if learned_pos_emb else (), + ) + with tempfile.TemporaryDirectory( + "test_mlm_translation" + ) as translation_dir: + create_dummy_data(translation_dir) + preprocess_translation_data( + translation_dir, extra_flags=["--joined-dictionary"] + ) + # Train transformer with data_dir/checkpoint_last.pt + train_translation_model( + translation_dir, + arch="transformer_from_pretrained_xlm", + extra_flags=[ + "--decoder-layers", + "1", + "--decoder-embed-dim", + "32", + "--decoder-attention-heads", + "1", + "--decoder-ffn-embed-dim", + "32", + "--encoder-layers", + "1", + "--encoder-embed-dim", + "32", + "--encoder-attention-heads", + "1", + "--encoder-ffn-embed-dim", + "32", + "--pretrained-xlm-checkpoint", + "{}/checkpoint_last.pt".format(data_dir), + "--activation-fn", + "gelu", + "--max-source-positions", + "500", + "--max-target-positions", + "500", + ] + + ( + ["--encoder-learned-pos", "--decoder-learned-pos"] + if learned_pos_emb + else [] + ) + + (["--init-encoder-only"] if encoder_only else []), + task="translation_from_pretrained_xlm", + ) + + def test_pretrained_masked_lm_for_translation_learned_pos_emb(self): + self._test_pretrained_masked_lm_for_translation(True, False) + + def test_pretrained_masked_lm_for_translation_sinusoidal_pos_emb(self): + self._test_pretrained_masked_lm_for_translation(False, False) + + def test_pretrained_masked_lm_for_translation_encoder_only(self): + self._test_pretrained_masked_lm_for_translation(True, True) + + def test_r4f_roberta(self): + num_classes = 3 + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_r4f_roberta_head") as data_dir: + create_dummy_roberta_head_data(data_dir, num_classes=num_classes) + preprocess_lm_data(os.path.join(data_dir, "input0")) + preprocess_lm_data(os.path.join(data_dir, "label")) + train_roberta_head( + data_dir, + "roberta_base", + num_classes=num_classes, + extra_flags=[ + "--user-dir", + "examples/rxf/rxf_src", + "--criterion", + "sentence_prediction_r3f", + "--spectral-norm-classification-head", + ], + ) + + +def train_legacy_masked_language_model(data_dir, arch, extra_args=()): + train_parser = options.get_training_parser() + # TODO: langs should be in and out right? + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "cross_lingual_lm", + data_dir, + "--arch", + arch, + # Optimizer args + "--optimizer", + "adam", + "--lr-scheduler", + "reduce_lr_on_plateau", + "--lr-shrink", + "0.5", + "--lr", + "0.0001", + "--min-lr", + "1e-09", + # dropout, attention args + "--dropout", + "0.1", + "--attention-dropout", + "0.1", + # MLM args + "--criterion", + "legacy_masked_lm_loss", + "--masked-lm-only", + "--monolingual-langs", + "in,out", + "--num-segment", + "5", + # Transformer args: use a small transformer model for fast training + "--encoder-layers", + "1", + "--encoder-embed-dim", + "32", + "--encoder-attention-heads", + "1", + "--encoder-ffn-embed-dim", + "32", + # Other training args + "--max-tokens", + "500", + "--tokens-per-sample", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--dataset-impl", + "raw", + "--num-workers", + "0", + ] + + list(extra_args), + ) + train.main(train_args) + + +class TestOptimizers(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_optimizers(self): + with contextlib.redirect_stdout(StringIO()): + with tempfile.TemporaryDirectory("test_optimizers") as data_dir: + # Use just a bit of data and tiny model to keep this test runtime reasonable + create_dummy_data(data_dir, num_examples=10, maxlen=5) + preprocess_translation_data(data_dir) + optimizers = ["adafactor", "adam", "nag", "adagrad", "sgd", "adadelta"] + last_checkpoint = os.path.join(data_dir, "checkpoint_last.pt") + for optimizer in optimizers: + if os.path.exists(last_checkpoint): + os.remove(last_checkpoint) + train_translation_model( + data_dir, + "lstm", + [ + "--required-batch-size-multiple", + "1", + "--encoder-layers", + "1", + "--encoder-hidden-size", + "32", + "--decoder-layers", + "1", + "--optimizer", + optimizer, + ], + ) + generate_main(data_dir) + + +def create_dummy_roberta_head_data( + data_dir, num_examples=100, maxlen=10, num_classes=2, regression=False +): + input_dir = "input0" + + def _create_dummy_data(filename): + random_data = torch.rand(num_examples * maxlen) + input_data = 97 + torch.floor(26 * random_data).int() + if regression: + output_data = torch.rand((num_examples, num_classes)) + else: + output_data = 1 + torch.floor(num_classes * torch.rand(num_examples)).int() + with open(os.path.join(data_dir, input_dir, filename + ".out"), "w") as f_in: + label_filename = filename + ".label" if regression else filename + ".out" + with open(os.path.join(data_dir, "label", label_filename), "w") as f_out: + offset = 0 + for i in range(num_examples): + # write example input + ex_len = random.randint(1, maxlen) + ex_str = " ".join(map(chr, input_data[offset : offset + ex_len])) + print(ex_str, file=f_in) + # write example label + if regression: + class_str = " ".join(map(str, output_data[i].numpy())) + print(class_str, file=f_out) + else: + class_str = "class{}".format(output_data[i]) + print(class_str, file=f_out) + offset += ex_len + + os.mkdir(os.path.join(data_dir, input_dir)) + os.mkdir(os.path.join(data_dir, "label")) + _create_dummy_data("train") + _create_dummy_data("valid") + _create_dummy_data("test") + + +def train_masked_lm(data_dir, arch, extra_flags=None): + train_parser = options.get_training_parser() + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "masked_lm", + data_dir, + "--arch", + arch, + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "masked_lm", + "--batch-size", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + ] + + (extra_flags or []), + ) + train.main(train_args) + + +def train_roberta_head(data_dir, arch, num_classes=2, extra_flags=None): + train_parser = options.get_training_parser() + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "sentence_prediction", + data_dir, + "--arch", + arch, + "--encoder-layers", + "2", + "--num-classes", + str(num_classes), + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "sentence_prediction", + "--max-tokens", + "500", + "--max-positions", + "500", + "--batch-size", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + ] + + (extra_flags or []), + ) + train.main(train_args) + + +def train_language_model(data_dir, arch, extra_flags=None, run_validation=False): + train_parser = options.get_training_parser() + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "language_modeling", + data_dir, + "--arch", + arch, + "--optimizer", + "adam", + "--lr", + "0.0001", + "--criterion", + "adaptive_loss", + "--adaptive-softmax-cutoff", + "5,10,15", + "--max-tokens", + "500", + "--tokens-per-sample", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--ddp-backend", + "no_c10d", + "--num-workers", + "0", + ] + + (extra_flags or []), + ) + train.main(train_args) + + if run_validation: + # test validation + validate_parser = options.get_validation_parser() + validate_args = options.parse_args_and_arch( + validate_parser, + [ + "--task", + "language_modeling", + data_dir, + "--path", + os.path.join(data_dir, "checkpoint_last.pt"), + "--valid-subset", + "valid", + "--max-tokens", + "500", + "--no-progress-bar", + "--num-workers", + "0", + ], + ) + validate.main(validate_args) + + +def eval_lm_main(data_dir): + eval_lm_parser = options.get_eval_lm_parser() + eval_lm_args = options.parse_args_and_arch( + eval_lm_parser, + [ + data_dir, + "--path", + os.path.join(data_dir, "checkpoint_last.pt"), + "--no-progress-bar", + "--num-workers", + "0", + ], + ) + eval_lm.main(eval_lm_args) + + +def train_masked_language_model(data_dir, arch, extra_args=()): + train_parser = options.get_training_parser() + # TODO: langs should be in and out right? + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + "cross_lingual_lm", + data_dir, + "--arch", + arch, + # Optimizer args + "--optimizer", + "adam", + "--lr-scheduler", + "reduce_lr_on_plateau", + "--lr-shrink", + "0.5", + "--lr", + "0.0001", + "--min-lr", + "1e-09", + # dropout, attention args + "--dropout", + "0.1", + "--attention-dropout", + "0.1", + # MLM args + "--criterion", + "masked_lm_loss", + "--masked-lm-only", + "--monolingual-langs", + "in,out", + "--num-segment", + "5", + # Transformer args: use a small transformer model for fast training + "--encoder-layers", + "1", + "--encoder-embed-dim", + "32", + "--encoder-attention-heads", + "1", + "--encoder-ffn-embed-dim", + "32", + # Other training args + "--max-tokens", + "500", + "--tokens-per-sample", + "500", + "--save-dir", + data_dir, + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--dataset-impl", + "raw", + "--num-workers", + "0", + ] + + list(extra_args), + ) + train.main(train_args) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_bmuf.py b/fairseq-tools/fairseq/tests/test_bmuf.py new file mode 100644 index 00000000..0165b295 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_bmuf.py @@ -0,0 +1,172 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import random +import unittest +from multiprocessing import Manager + +import torch +import torch.nn as nn +from fairseq import distributed_utils, optim + + +class Model(nn.Module): + def __init__(self, input_size, output_size): + super(Model, self).__init__() + self.fc = nn.Linear(input_size, output_size) + + def forward(self, input): + output = self.fc(input) + return output + + +def setup_model_loss_criterion(args, rank, is_cuda): + """ + setup model, criterion and optimizer based on input args + """ + args.distributed_rank = rank + if args.distributed_world_size > 1: + distributed_utils.distributed_init(args) + torch.manual_seed(1) + model = Model(args.input_size, args.nb_classes) + loss_fn = nn.CrossEntropyLoss() + if is_cuda: + model = model.cuda() + loss_fn = loss_fn.cuda() + + optimizer = optim.sgd.SGD(args, model.parameters()) + optimizer = optim.FairseqBMUF(args, optimizer) + + return model, loss_fn, optimizer + + +def train_step(input, target, model, loss_fn, optimizer, **unused): + """Do forward, backward and parameter update.""" + model.train() + output = model(input) + loss = loss_fn(output, target) + optimizer.backward(loss) + optimizer.step() + + +def single_gpu_training(args, rank, iterations, shared_results): + + is_cuda = torch.cuda.is_available() + if is_cuda: + torch.cuda.set_device(rank) + + model, loss_fn, optimizer = setup_model_loss_criterion(args, rank, is_cuda) + + for _ in range(iterations): + input = torch.randn(1, args.input_size) + target = torch.empty(args.batch_size, dtype=torch.long).random_(args.nb_classes) + + if is_cuda: + input = input.cuda() + target = target.cuda() + train_step(input, target, model, loss_fn, optimizer) + + results = [] + for param in model.parameters(): + if len(results) == 0: + results = param.flatten().cpu().data + else: + results = torch.cat((results, param.flatten().cpu().data), 0) + + shared_results[rank] = results + + +def setup_args(): + args = argparse.Namespace() + args.global_sync_iter = 20 + args.block_momentum = 0.875 + args.block_lr = 0.5 + args.input_size = 5 + args.nb_classes = 2 + args.batch_size = 1 + args.lr = [1e-3] + args.momentum = 0 + args.weight_decay = 0 + args.warmup_iterations = 0 + args.use_nbm = True + args.average_sync = True + args.global_sync_iter = 1 + args.model_parallel_size = 1 + args.distributed_backend = "gloo" + + args.distributed_world_size = 2 + port = random.randint(10000, 20000) + args.distributed_init_method = "tcp://localhost:{port}".format(port=port) + args.distributed_init_host = "localhost" + args.distributed_port = port + 1 + args.local_world_size = args.distributed_world_size + return args + + +@unittest.skipIf(torch.cuda.device_count() < 2, "test requires 2 GPUs") +class TestBMUF(unittest.TestCase): + def bmuf_process(self, args, iterations): + processes = [] + results = Manager().dict() + ctx = torch.multiprocessing.get_context("spawn") + for rank in range(args.distributed_world_size): + p = ctx.Process( + target=single_gpu_training, args=(args, rank, iterations, results) + ) + p.start() + processes.append(p) + + for p in processes: + p.join() + return results + + def test_bmuf_sync(self): + # Train model for 1 iteration and do bmuf sync without doing warmup + args = setup_args() + iterations = 1 + results = self.bmuf_process(args, iterations) + # Make sure params in both machines are same + assert len(results) == 2 + self.assertAlmostEqual(results[0], results[1]) + + def test_warmup_sync(self): + # Train model for 20 iteration and do warmup sync without doing bmuf sync + args = setup_args() + args.warmup_iterations = 20 + iterations = 20 + results = self.bmuf_process(args, iterations) + # Make sure params in both machines are same + assert len(results) == 2 + self.assertAlmostEqual(results[0], results[1]) + + def test_warmup_sync_bmuf_sync(self): + # Train model for 25 iteration and do warmup sync after 20 iteration + # and bmuf sync after 25 iteration + args = setup_args() + args.warmup_iterations = 20 + args.global_sync_iter = 5 + iterations = 25 + results = self.bmuf_process(args, iterations) + # Make sure params in both machines are same + assert len(results) == 2 + self.assertAlmostEqual(results[0], results[1]) + + def test_single_gpu_bmuf(self): + # Train model for 5 iterations and use GPU 1 + args = setup_args() + args.distributed_world_size = 1 + args.warmup_iterations = 5 + iterations = 20 + results = self.bmuf_process(args, iterations) + assert len(results) == 1 + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-4) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_character_token_embedder.py b/fairseq-tools/fairseq/tests/test_character_token_embedder.py new file mode 100644 index 00000000..24940ebd --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_character_token_embedder.py @@ -0,0 +1,48 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +from fairseq.data import Dictionary +from fairseq.modules import CharacterTokenEmbedder + + +class TestCharacterTokenEmbedder(unittest.TestCase): + def test_character_token_embedder(self): + vocab = Dictionary() + vocab.add_symbol("hello") + vocab.add_symbol("there") + + embedder = CharacterTokenEmbedder( + vocab, [(2, 16), (4, 32), (8, 64), (16, 2)], 64, 5, 2 + ) + + test_sents = [["hello", "unk", "there"], ["there"], ["hello", "there"]] + max_len = max(len(s) for s in test_sents) + input = torch.LongTensor(len(test_sents), max_len + 2).fill_(vocab.pad()) + for i in range(len(test_sents)): + input[i][0] = vocab.eos() + for j in range(len(test_sents[i])): + input[i][j + 1] = vocab.index(test_sents[i][j]) + input[i][j + 2] = vocab.eos() + embs = embedder(input) + + assert embs.size() == (len(test_sents), max_len + 2, 5) + self.assertAlmostEqual(embs[0][0], embs[1][0]) + self.assertAlmostEqual(embs[0][0], embs[0][-1]) + self.assertAlmostEqual(embs[0][1], embs[2][1]) + self.assertAlmostEqual(embs[0][3], embs[1][1]) + + embs.sum().backward() + assert embedder.char_embeddings.weight.grad is not None + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-6) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_concat_dataset.py b/fairseq-tools/fairseq/tests/test_concat_dataset.py new file mode 100644 index 00000000..d94aeffd --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_concat_dataset.py @@ -0,0 +1,58 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +from fairseq.data import LanguagePairDataset, TokenBlockDataset +from fairseq.data.concat_dataset import ConcatDataset +from tests.test_train import mock_dict + + +class TestConcatDataset(unittest.TestCase): + def setUp(self): + d = mock_dict() + tokens_1 = torch.LongTensor([1]).view(1, -1) + tokens_ds1 = TokenBlockDataset( + tokens_1, + sizes=[tokens_1.size(-1)], + block_size=1, + pad=0, + eos=1, + include_targets=False, + ) + self.dataset_1 = LanguagePairDataset( + tokens_ds1, tokens_ds1.sizes, d, shuffle=False + ) + tokens_2 = torch.LongTensor([2]).view(1, -1) + tokens_ds2 = TokenBlockDataset( + tokens_2, + sizes=[tokens_2.size(-1)], + block_size=1, + pad=0, + eos=1, + include_targets=False, + ) + self.dataset_2 = LanguagePairDataset( + tokens_ds2, tokens_ds2.sizes, d, shuffle=False + ) + + def test_concat_dataset_basics(self): + d = ConcatDataset([self.dataset_1, self.dataset_2]) + assert len(d) == 2 + assert d[0]["source"][0] == 1 + assert d[1]["source"][0] == 2 + + d = ConcatDataset([self.dataset_1, self.dataset_2], sample_ratios=[1, 2]) + assert len(d) == 3 + assert d[0]["source"][0] == 1 + assert d[1]["source"][0] == 2 + assert d[2]["source"][0] == 2 + + d = ConcatDataset([self.dataset_1, self.dataset_2], sample_ratios=[2, 1]) + assert len(d) == 3 + assert d[0]["source"][0] == 1 + assert d[1]["source"][0] == 1 + assert d[2]["source"][0] == 2 diff --git a/fairseq-tools/fairseq/tests/test_constraints.py b/fairseq-tools/fairseq/tests/test_constraints.py new file mode 100644 index 00000000..1c37f7e1 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_constraints.py @@ -0,0 +1,269 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import sys +import unittest + +import torch +from fairseq.token_generation_constraints import * + + +def tensorize(constraints: List[List[int]]) -> torch.Tensor: + return [torch.tensor(x) for x in constraints] + + +class TestHelperRoutines(unittest.TestCase): + def setUp(self): + self.examples = [ + ([[]], torch.tensor([[0]])), + ([[], []], torch.tensor([[0], [0]])), + ([[torch.tensor([1, 2])], []], torch.tensor([[1, 1, 2, 0], [0, 0, 0, 0]])), + ( + [ + [ + torch.tensor([3, 1, 2]), + torch.tensor([3]), + torch.tensor([4, 5, 6, 7]), + ], + [], + [torch.tensor([1, 8, 9, 10, 1, 4, 11, 12])], + ], + torch.tensor( + [ + [3, 3, 1, 2, 0, 3, 0, 4, 5, 6, 7, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 1, 8, 9, 10, 1, 4, 11, 12, 0, 0, 0], + ] + ), + ), + ] + + def test_packing(self): + """Ensures the list of lists of tensors gets packed correctly.""" + for batch_constraints, expected_tensor in self.examples: + packed = pack_constraints(batch_constraints) + assert torch.equal(packed, expected_tensor) + + +class TestUnorderedConstraintState(unittest.TestCase): + def setUp(self): + # Tuples of (contraint set, expected printed graph, token counts per node) + self.examples = [ + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + "([None].False#6 ([1].True#4 ([2].False#1 [3].True#1) [3].True#1 [4].True#1) ([4].False#2 ([5].True#2 ([6].False#1 [7].True#1))))", + {1: 4, 2: 1, 3: 2, 4: 3, 5: 2, 6: 1, 7: 1}, + ), + ([], "[None].False#0", {}), + (tensorize([[0]]), "([None].False#1 [0].True#1)", {0: 1}), + ( + tensorize([[100000, 1, 2, 3, 4, 5]]), + "([None].False#1 ([100000].False#1 ([1].False#1 ([2].False#1 ([3].False#1 ([4].False#1 [5].True#1))))))", + {100000: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1}, + ), + ( + tensorize([[1, 2], [1, 2]]), + "([None].False#2 ([1].False#2 [2].True#2))", + {1: 2, 2: 2}, + ), + ( + tensorize([[1, 2], [3, 4]]), + "([None].False#2 ([1].False#1 [2].True#1) ([3].False#1 [4].True#1))", + {1: 1, 2: 1, 3: 1, 4: 1}, + ), + ] + + self.sequences = [ + ( + self.examples[0][0], + [], + {"bank": 0, "num_completed": 0, "finished": False, "is_root": True}, + ), + ( + self.examples[0][0], + [1, 2], + {"bank": 2, "num_completed": 0, "finished": False, "is_root": False}, + ), + ( + self.examples[0][0], + [1, 2, 94], + {"bank": 1, "num_completed": 1, "finished": False, "is_root": True}, + ), + ( + self.examples[0][0], + [1, 3, 999, 1, 4], + {"bank": 4, "num_completed": 2, "finished": False, "is_root": False}, + ), + ( + self.examples[0][0], + [1, 3, 999, 1, 4, 999], + {"bank": 4, "num_completed": 2, "finished": False, "is_root": True}, + ), + ( + self.examples[0][0], + [4, 5, 6, 8], + {"bank": 2, "num_completed": 1, "finished": False, "is_root": True}, + ), + ( + self.examples[0][0], + # Tricky, because in last three, goes down [1->4] branch, could miss [1] and [4->5] + # [[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]], + [1, 2, 3, 1, 3, 1, 4, 4, 5, 6, 7, 1, 4, 5], + {"bank": 14, "num_completed": 6, "finished": True, "is_root": False}, + ), + ( + self.examples[0][0], + [1, 2, 3, 999, 1, 3, 1, 4, 4, 5, 6, 7, 1, 4, 5, 117], + {"bank": 14, "num_completed": 6, "finished": True, "is_root": True}, + ), + ( + tensorize([[1], [2, 3]]), + # Should not be able to get credit for entering 1 a second time + [1, 1], + {"bank": 1, "num_completed": 1, "finished": False, "is_root": True}, + ), + ( + self.examples[4][0], + [1, 2, 1, 2], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": False}, + ), + ( + self.examples[4][0], + [1, 2, 1, 2, 1], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": True}, + ), + ( + self.examples[5][0], + [1, 2, 3, 4, 5], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": True}, + ), + ] + + def test_graphs(self): + """ + Test whether unordered graph systems are created correctly. + """ + for example in self.examples: + constraints, expected, gold_counts = example + c = ConstraintNode.create(constraints) + assert ( + ConstraintNode.print_graph(c) == expected + ), f"got {ConstraintNode.print_graph(c)}, expected {expected}" + assert ( + c.token_counts() == gold_counts + ), f"{c} got {c.token_counts()} wanted {gold_counts}" + + def test_next_tokens(self): + """ + Tests that the set of next tokens is correct. + """ + for example in self.examples: + constraints, expected, gold_counts = example + root = ConstraintNode.create(constraints) + + root_tokens = set(root.children.keys()) + for sequence in constraints: + state = UnorderedConstraintState(root) + for token in sequence: + all_tokens = root_tokens.union(state.node.children.keys()) + assert ( + all_tokens == state.next_tokens() + ), f"ALL {all_tokens} NEXT {state.next_tokens()}" + state = state.advance(token) + + def test_sequences(self): + for constraints, tokens, expected in self.sequences: + state = UnorderedConstraintState.create(pack_constraints([constraints])[0]) + for token in tokens: + state = state.advance(token) + result = {} + for attr in expected.keys(): + result[attr] = getattr(state, attr) + + assert ( + result == expected + ), f"TEST({tokens}) GOT: {result} WANTED: {expected}" + + +class TestOrderedConstraintState(unittest.TestCase): + def setUp(self): + self.sequences = [ + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [], + {"bank": 0, "num_completed": 0, "finished": False, "is_root": True}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2], + {"bank": 2, "num_completed": 0, "finished": False, "is_root": False}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2, 94], + {"bank": 0, "num_completed": 0, "finished": False, "is_root": True}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 3, 999, 1, 4], + {"bank": 0, "num_completed": 0, "finished": False, "is_root": True}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2, 3, 999, 999], + {"bank": 3, "num_completed": 1, "finished": False, "is_root": False}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2, 3, 77, 1, 3, 1], + {"bank": 6, "num_completed": 2, "finished": False, "is_root": False}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2, 3, 1, 3, 1, 4, 4, 5, 6, 7, 1, 4, 5], + {"bank": 14, "num_completed": 6, "finished": True, "is_root": False}, + ), + ( + tensorize([[1, 2, 3], [1, 3], [1, 4], [4, 5, 6, 7], [1], [4, 5]]), + [1, 2, 999, 1, 2, 3, 999, 1, 3, 1, 4, 4, 5, 6, 7, 1, 4, 5, 117], + {"bank": 14, "num_completed": 6, "finished": True, "is_root": False}, + ), + ( + tensorize([[1], [2, 3]]), + [1, 1], + {"bank": 1, "num_completed": 1, "finished": False, "is_root": False}, + ), + ( + tensorize([[1, 2], [1, 2]]), + [1, 2, 1, 2], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": False}, + ), + ( + tensorize([[1, 2], [1, 2]]), + [1, 2, 1, 2, 1], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": False}, + ), + ( + tensorize([[1, 2], [3, 4]]), + [1, 2, 3, 4, 5], + {"bank": 4, "num_completed": 2, "finished": True, "is_root": False}, + ), + ] + + def test_sequences(self): + for i, (constraints, tokens, expected) in enumerate(self.sequences): + state = OrderedConstraintState.create(pack_constraints([constraints])[0]) + for token in tokens: + state = state.advance(token) + result = {} + for attr in expected.keys(): + result[attr] = getattr(state, attr) + assert ( + result == expected + ), f"TEST({tokens}) GOT: {result} WANTED: {expected}" + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_convtbc.py b/fairseq-tools/fairseq/tests/test_convtbc.py new file mode 100644 index 00000000..3a3c9b91 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_convtbc.py @@ -0,0 +1,54 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +import torch.nn as nn +from fairseq.modules import ConvTBC + + +class TestConvTBC(unittest.TestCase): + def test_convtbc(self): + # ksz, in_channels, out_channels + conv_tbc = ConvTBC(4, 5, kernel_size=3, padding=1) + # out_channels, in_channels, ksz + conv1d = nn.Conv1d(4, 5, kernel_size=3, padding=1) + + conv_tbc.weight.data.copy_(conv1d.weight.data.transpose(0, 2)) + conv_tbc.bias.data.copy_(conv1d.bias.data) + + input_tbc = torch.randn(7, 2, 4, requires_grad=True) + input1d = input_tbc.data.transpose(0, 1).transpose(1, 2) + input1d.requires_grad = True + + output_tbc = conv_tbc(input_tbc) + output1d = conv1d(input1d) + + self.assertAlmostEqual( + output_tbc.data.transpose(0, 1).transpose(1, 2), output1d.data + ) + + grad_tbc = torch.randn(output_tbc.size()) + grad1d = grad_tbc.transpose(0, 1).transpose(1, 2).contiguous() + + output_tbc.backward(grad_tbc) + output1d.backward(grad1d) + + self.assertAlmostEqual( + conv_tbc.weight.grad.data.transpose(0, 2), conv1d.weight.grad.data + ) + self.assertAlmostEqual(conv_tbc.bias.grad.data, conv1d.bias.grad.data) + self.assertAlmostEqual( + input_tbc.grad.data.transpose(0, 1).transpose(1, 2), input1d.grad.data + ) + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-4) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_dictionary.py b/fairseq-tools/fairseq/tests/test_dictionary.py new file mode 100644 index 00000000..81ce102f --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_dictionary.py @@ -0,0 +1,116 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import io +import tempfile +import unittest + +import torch +from fairseq.data import Dictionary + + +class TestDictionary(unittest.TestCase): + def test_finalize(self): + txt = [ + "A B C D", + "B C D", + "C D", + "D", + ] + ref_ids1 = list( + map( + torch.IntTensor, + [ + [4, 5, 6, 7, 2], + [5, 6, 7, 2], + [6, 7, 2], + [7, 2], + ], + ) + ) + ref_ids2 = list( + map( + torch.IntTensor, + [ + [7, 6, 5, 4, 2], + [6, 5, 4, 2], + [5, 4, 2], + [4, 2], + ], + ) + ) + + # build dictionary + d = Dictionary() + for line in txt: + d.encode_line(line, add_if_not_exist=True) + + def get_ids(dictionary): + ids = [] + for line in txt: + ids.append(dictionary.encode_line(line, add_if_not_exist=False)) + return ids + + def assertMatch(ids, ref_ids): + for toks, ref_toks in zip(ids, ref_ids): + self.assertEqual(toks.size(), ref_toks.size()) + self.assertEqual(0, (toks != ref_toks).sum().item()) + + ids = get_ids(d) + assertMatch(ids, ref_ids1) + + # check finalized dictionary + d.finalize() + finalized_ids = get_ids(d) + assertMatch(finalized_ids, ref_ids2) + + # write to disk and reload + with tempfile.NamedTemporaryFile(mode="w") as tmp_dict: + d.save(tmp_dict.name) + d = Dictionary.load(tmp_dict.name) + reload_ids = get_ids(d) + assertMatch(reload_ids, ref_ids2) + assertMatch(finalized_ids, reload_ids) + + def test_overwrite(self): + # for example, Camembert overwrites <unk>, <s> and </s> + dict_file = io.StringIO( + "<unk> 999 #fairseq:overwrite\n" + "<s> 999 #fairseq:overwrite\n" + "</s> 999 #fairseq:overwrite\n" + ", 999\n" + "▁de 999\n" + ) + d = Dictionary() + d.add_from_file(dict_file) + self.assertEqual(d.index("<pad>"), 1) + self.assertEqual(d.index("foo"), 3) + self.assertEqual(d.index("<unk>"), 4) + self.assertEqual(d.index("<s>"), 5) + self.assertEqual(d.index("</s>"), 6) + self.assertEqual(d.index(","), 7) + self.assertEqual(d.index("▁de"), 8) + + def test_no_overwrite(self): + # for example, Camembert overwrites <unk>, <s> and </s> + dict_file = io.StringIO( + "<unk> 999\n" "<s> 999\n" "</s> 999\n" ", 999\n" "▁de 999\n" + ) + d = Dictionary() + with self.assertRaisesRegex(RuntimeError, "Duplicate"): + d.add_from_file(dict_file) + + def test_space(self): + # for example, character models treat space as a symbol + dict_file = io.StringIO(" 999\n" "a 999\n" "b 999\n") + d = Dictionary() + d.add_from_file(dict_file) + self.assertEqual(d.index(" "), 4) + self.assertEqual(d.index("a"), 5) + self.assertEqual(d.index("b"), 6) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_export.py b/fairseq-tools/fairseq/tests/test_export.py new file mode 100644 index 00000000..87e52bd7 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_export.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import tempfile +import unittest + +import torch +from fairseq.data.dictionary import Dictionary +from fairseq.models.transformer import TransformerModel +from fairseq.modules import multihead_attention, sinusoidal_positional_embedding +from fairseq.tasks.fairseq_task import LegacyFairseqTask + + +DEFAULT_TEST_VOCAB_SIZE = 100 + + +class DummyTask(LegacyFairseqTask): + def __init__(self, args): + super().__init__(args) + self.dictionary = get_dummy_dictionary() + if getattr(self.args, "ctc", False): + self.dictionary.add_symbol("<ctc_blank>") + self.src_dict = self.dictionary + self.tgt_dict = self.dictionary + + @property + def source_dictionary(self): + return self.src_dict + + @property + def target_dictionary(self): + return self.dictionary + + +def get_dummy_dictionary(vocab_size=DEFAULT_TEST_VOCAB_SIZE): + dummy_dict = Dictionary() + # add dummy symbol to satisfy vocab size + for id, _ in enumerate(range(vocab_size)): + dummy_dict.add_symbol("{}".format(id), 1000) + return dummy_dict + + +def get_dummy_task_and_parser(): + """ + Return a dummy task and argument parser, which can be used to + create a model/criterion. + """ + parser = argparse.ArgumentParser( + description="test_dummy_s2s_task", argument_default=argparse.SUPPRESS + ) + DummyTask.add_args(parser) + args = parser.parse_args([]) + task = DummyTask.setup_task(args) + return task, parser + + +def _test_save_and_load(scripted_module): + with tempfile.NamedTemporaryFile() as f: + scripted_module.save(f.name) + torch.jit.load(f.name) + + +class TestExportModels(unittest.TestCase): + def test_export_multihead_attention(self): + module = multihead_attention.MultiheadAttention(embed_dim=8, num_heads=2) + scripted = torch.jit.script(module) + _test_save_and_load(scripted) + + def test_incremental_state_multihead_attention(self): + module1 = multihead_attention.MultiheadAttention(embed_dim=8, num_heads=2) + module1 = torch.jit.script(module1) + module2 = multihead_attention.MultiheadAttention(embed_dim=8, num_heads=2) + module2 = torch.jit.script(module2) + + state = {} + state = module1.set_incremental_state(state, "key", {"a": torch.tensor([1])}) + state = module2.set_incremental_state(state, "key", {"a": torch.tensor([2])}) + v1 = module1.get_incremental_state(state, "key")["a"] + v2 = module2.get_incremental_state(state, "key")["a"] + + self.assertEqual(v1, 1) + self.assertEqual(v2, 2) + + def test_positional_embedding(self): + module = sinusoidal_positional_embedding.SinusoidalPositionalEmbedding( + embedding_dim=8, padding_idx=1 + ) + scripted = torch.jit.script(module) + _test_save_and_load(scripted) + + @unittest.skipIf( + torch.__version__ < "1.6.0", "Targeting OSS scriptability for the 1.6 release" + ) + def test_export_transformer(self): + task, parser = get_dummy_task_and_parser() + TransformerModel.add_args(parser) + args = parser.parse_args([]) + model = TransformerModel.build_model(args, task) + scripted = torch.jit.script(model) + _test_save_and_load(scripted) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_file_io.py b/fairseq-tools/fairseq/tests/test_file_io.py new file mode 100644 index 00000000..aef5b80d --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_file_io.py @@ -0,0 +1,47 @@ +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import shutil +import sys +import tempfile +import unittest +from typing import Optional +from unittest.mock import MagicMock + + +class TestFileIO(unittest.TestCase): + + _tmpdir: Optional[str] = None + _tmpfile: Optional[str] = None + _tmpfile_contents = "Hello, World" + + @classmethod + def setUpClass(cls) -> None: + cls._tmpdir = tempfile.mkdtemp() + with open(os.path.join(cls._tmpdir, "test.txt"), "w") as f: + cls._tmpfile = f.name + f.write(cls._tmpfile_contents) + f.flush() + + @classmethod + def tearDownClass(cls) -> None: + # Cleanup temp working dir. + if cls._tmpdir is not None: + shutil.rmtree(cls._tmpdir) # type: ignore + + def test_file_io(self): + from fairseq.file_io import PathManager + + with PathManager.open(os.path.join(self._tmpdir, "test.txt"), "r") as f: + s = f.read() + self.assertEqual(s, self._tmpfile_contents) + + def test_file_io_oss(self): + # Mock fvcore to simulate oss environment. + sys.modules["fvcore"] = MagicMock() + from fairseq.file_io import PathManager + + with PathManager.open(os.path.join(self._tmpdir, "test.txt"), "r") as f: + s = f.read() + self.assertEqual(s, self._tmpfile_contents) diff --git a/fairseq-tools/fairseq/tests/test_fp16_optimizer.py b/fairseq-tools/fairseq/tests/test_fp16_optimizer.py new file mode 100644 index 00000000..c4195273 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_fp16_optimizer.py @@ -0,0 +1,98 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import copy +import unittest + +import torch +from fairseq.optim.fp16_optimizer import FP16Optimizer, MemoryEfficientFP16Optimizer + + +@unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") +class TestGradientScaling(unittest.TestCase): + def setUp(self): + self.x = torch.tensor([2.0]).cuda().half() + weight = 3.0 + bias = 5.0 + self.error = 1.0 + self.target = torch.tensor([self.x * weight + bias + self.error]).cuda().half() + self.loss_fn = torch.nn.L1Loss() + + self.model = torch.nn.Linear(1, 1) + self.model.weight.data = torch.tensor([[weight]]) + self.model.bias.data = torch.tensor([bias]) + self.model.cuda().half() + self.params = list(self.model.parameters()) + + self.namespace_dls = argparse.Namespace( + optimizer="adam", + lr=[0.1], + adam_betas="(0.9, 0.999)", + adam_eps=1e-8, + weight_decay=0.0, + fp16_init_scale=1, + fp16_scale_window=1, + fp16_scale_tolerance=1, + threshold_loss_scale=1, + min_loss_scale=1e-4, + ) + + def run_iter(self, model, params, optimizer): + optimizer.zero_grad() + y = model(self.x) + loss = self.loss_fn(y, self.target) + optimizer.backward(loss) + self.assertEqual(loss, torch.tensor(1.0, device="cuda:0", dtype=torch.float16)) + + grad_norm = optimizer.clip_grad_norm(0) + self.assertAlmostEqual(grad_norm.item(), 2.2361, 4) + + optimizer.step() + self.assertEqual( + model.weight, + torch.tensor( + [[3.0996]], device="cuda:0", dtype=torch.float16, requires_grad=True + ), + ) + self.assertEqual( + model.bias, + torch.tensor( + [5.1016], device="cuda:0", dtype=torch.float16, requires_grad=True + ), + ) + self.assertEqual(optimizer.scaler.loss_scale, 2.0) + + def test_mixed_precision(self): + model = copy.deepcopy(self.model) + params = list(model.parameters()) + optimizer = FP16Optimizer.build_optimizer(self.namespace_dls, params) + + self.run_iter(model, params, optimizer) + self.assertTrue( + all( + torch.all( + fp32_params.eq( + torch.tensor( + [3.1000, 5.1000], device="cuda:0", requires_grad=True + ) + ) + ) + for fp32_params in optimizer.fp32_params.values() + ) + ) + + def test_memory_efficient(self): + model = copy.deepcopy(self.model) + params = list(model.parameters()) + optimizer = MemoryEfficientFP16Optimizer.build_optimizer( + self.namespace_dls, params + ) + + self.run_iter(model, params, optimizer) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_inference_dropout.py b/fairseq-tools/fairseq/tests/test_inference_dropout.py new file mode 100644 index 00000000..fd5edd43 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_inference_dropout.py @@ -0,0 +1,66 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import logging +import unittest + +from fairseq.models.transformer import TransformerModel +from tests.test_sequence_generator import get_dummy_task_and_parser + + +class TestInferenceDropout(unittest.TestCase): + def setUp(self): + self.task, self.parser = get_dummy_task_and_parser() + TransformerModel.add_args(self.parser) + self.args = self.parser.parse_args([]) + self.args.encoder_layers = 2 + self.args.decoder_layers = 1 + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_sets_inference_dropout_to_true(self): + self.args.retain_dropout = True + self.transformer_model = TransformerModel.build_model(self.args, self.task) + self.transformer_model.prepare_for_inference_(self.args) + assert self.transformer_model.encoder.dropout_module.apply_during_inference + assert self.transformer_model.decoder.dropout_module.apply_during_inference + for layer in self.transformer_model.encoder.layers: + assert layer.dropout_module.apply_during_inference + + def test_inference_dropout_false_by_default(self): + self.transformer_model = TransformerModel.build_model(self.args, self.task) + self.transformer_model.prepare_for_inference_(self.args) + assert not self.transformer_model.encoder.dropout_module.apply_during_inference + assert not self.transformer_model.decoder.dropout_module.apply_during_inference + for layer in self.transformer_model.encoder.layers: + assert not layer.dropout_module.apply_during_inference + for layer in self.transformer_model.decoder.layers: + assert not layer.dropout_module.apply_during_inference + + def test_applies_training_mode(self): + self.transformer_model = TransformerModel.build_model(self.args, self.task) + assert self.transformer_model.encoder.dropout_module.training + for layer in self.transformer_model.encoder.layers: + assert layer.dropout_module.training + + self.transformer_model.eval() + assert not self.transformer_model.decoder.dropout_module.training + for layer in self.transformer_model.encoder.layers: + assert not layer.dropout_module.training + + def test_retain_modules(self): + self.args.retain_dropout = True + self.args.retain_dropout_modules = [ + "TransformerEncoder", + "TransformerEncoderLayer", + ] + self.transformer_model = TransformerModel.build_model(self.args, self.task) + self.transformer_model.prepare_for_inference_(self.args) + assert self.transformer_model.encoder.dropout_module.apply_during_inference + assert not self.transformer_model.decoder.dropout_module.apply_during_inference + for layer in self.transformer_model.decoder.layers: + assert not layer.dropout_module.apply_during_inference diff --git a/fairseq-tools/fairseq/tests/test_iterators.py b/fairseq-tools/fairseq/tests/test_iterators.py new file mode 100644 index 00000000..3d2c4d62 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_iterators.py @@ -0,0 +1,123 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +from fairseq.data import iterators + + +class TestIterators(unittest.TestCase): + def test_counting_iterator(self, ref=None, itr=None): + if ref is None: + assert itr is None + ref = list(range(10)) + itr = iterators.CountingIterator(ref) + else: + assert len(ref) == 10 + assert itr is not None + self.assertTrue(itr.has_next()) + self.assertEqual(itr.n, 0) + self.assertEqual(next(itr), ref[0]) + self.assertEqual(itr.n, 1) + self.assertEqual(next(itr), ref[1]) + self.assertEqual(itr.n, 2) + itr.skip(3) + self.assertEqual(itr.n, 5) + self.assertEqual(next(itr), ref[5]) + itr.skip(3) + self.assertEqual(itr.n, 9) + self.assertEqual(next(itr), ref[9]) + self.assertFalse(itr.has_next()) + + def test_grouped_iterator(self): + # test correctness + x = list(range(10)) + itr = iterators.GroupedIterator(x, 1) + self.assertEqual(list(itr), [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]]) + itr = iterators.GroupedIterator(x, 4) + self.assertEqual(list(itr), [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]) + itr = iterators.GroupedIterator(x, 5) + self.assertEqual(list(itr), [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) + + # test CountingIterator functionality + x = list(range(30)) + ref = list(iterators.GroupedIterator(x, 3)) + itr = iterators.GroupedIterator(x, 3) + self.test_counting_iterator(ref, itr) + + def test_sharded_iterator(self): + # test correctness + x = list(range(10)) + itr = iterators.ShardedIterator(x, num_shards=1, shard_id=0) + self.assertEqual(list(itr), x) + itr = iterators.ShardedIterator(x, num_shards=2, shard_id=0) + self.assertEqual(list(itr), [0, 2, 4, 6, 8]) + itr = iterators.ShardedIterator(x, num_shards=2, shard_id=1) + self.assertEqual(list(itr), [1, 3, 5, 7, 9]) + itr = iterators.ShardedIterator(x, num_shards=3, shard_id=0) + self.assertEqual(list(itr), [0, 3, 6, 9]) + itr = iterators.ShardedIterator(x, num_shards=3, shard_id=1) + self.assertEqual(list(itr), [1, 4, 7, None]) + itr = iterators.ShardedIterator(x, num_shards=3, shard_id=2) + self.assertEqual(list(itr), [2, 5, 8, None]) + + # test CountingIterator functionality + x = list(range(30)) + ref = list(iterators.ShardedIterator(x, num_shards=3, shard_id=0)) + itr = iterators.ShardedIterator(x, num_shards=3, shard_id=0) + self.test_counting_iterator(ref, itr) + + def test_counting_iterator_take(self): + ref = list(range(10)) + itr = iterators.CountingIterator(ref) + itr.take(5) + self.assertEqual(len(itr), len(list(iter(itr)))) + self.assertEqual(len(itr), 5) + + itr = iterators.CountingIterator(ref) + itr.take(5) + self.assertEqual(next(itr), ref[0]) + self.assertEqual(next(itr), ref[1]) + itr.skip(2) + self.assertEqual(next(itr), ref[4]) + self.assertFalse(itr.has_next()) + + def test_counting_iterator_buffered_iterator_take(self): + ref = list(range(10)) + buffered_itr = iterators.BufferedIterator(2, ref) + itr = iterators.CountingIterator(buffered_itr) + itr.take(5) + self.assertEqual(len(itr), len(list(iter(itr)))) + self.assertEqual(len(itr), 5) + + buffered_itr = iterators.BufferedIterator(2, ref) + itr = iterators.CountingIterator(buffered_itr) + itr.take(5) + self.assertEqual(len(buffered_itr), 5) + self.assertEqual(len(list(iter(buffered_itr))), 5) + + buffered_itr = iterators.BufferedIterator(2, ref) + itr = iterators.CountingIterator(buffered_itr) + itr.take(5) + self.assertEqual(next(itr), ref[0]) + self.assertEqual(next(itr), ref[1]) + itr.skip(2) + self.assertEqual(next(itr), ref[4]) + self.assertFalse(itr.has_next()) + self.assertRaises(StopIteration, next, buffered_itr) + + ref = list(range(4, 10)) + buffered_itr = iterators.BufferedIterator(2, ref) + itr = iterators.CountingIterator(buffered_itr, start=4) + itr.take(5) + self.assertEqual(len(itr), 5) + self.assertEqual(len(buffered_itr), 1) + self.assertEqual(next(itr), ref[0]) + self.assertFalse(itr.has_next()) + self.assertRaises(StopIteration, next, buffered_itr) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_label_smoothing.py b/fairseq-tools/fairseq/tests/test_label_smoothing.py new file mode 100644 index 00000000..04c0f974 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_label_smoothing.py @@ -0,0 +1,123 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import copy +import unittest + +import tests.utils as test_utils +import torch +from fairseq.criterions.cross_entropy import CrossEntropyCriterion +from fairseq.criterions.label_smoothed_cross_entropy import ( + LabelSmoothedCrossEntropyCriterion, +) + + +class TestLabelSmoothing(unittest.TestCase): + def setUp(self): + # build dictionary + self.d = test_utils.dummy_dictionary(3) + vocab = len(self.d) + self.assertEqual(vocab, 4 + 3) # 4 special + 3 tokens + self.assertEqual(self.d.pad(), 1) + self.assertEqual(self.d.eos(), 2) + self.assertEqual(self.d.unk(), 3) + pad, eos, unk, w1, w2, w3 = 1, 2, 3, 4, 5, 6 # noqa: F841 + + # build dataset + self.data = [ + # the first batch item has padding + { + "source": torch.LongTensor([w1, eos]), + "target": torch.LongTensor([w1, eos]), + }, + { + "source": torch.LongTensor([w1, eos]), + "target": torch.LongTensor([w1, w1, eos]), + }, + ] + self.sample = next(test_utils.dummy_dataloader(self.data)) + + # build model + self.args = argparse.Namespace() + self.args.sentence_avg = False + self.args.report_accuracy = False + self.args.probs = ( + torch.FloatTensor( + [ + # pad eos unk w1 w2 w3 + [0.05, 0.05, 0.1, 0.05, 0.3, 0.4, 0.05], + [0.05, 0.10, 0.2, 0.05, 0.2, 0.3, 0.10], + [0.05, 0.15, 0.3, 0.05, 0.1, 0.2, 0.15], + ] + ) + .unsqueeze(0) + .expand(2, 3, 7) + ) # add batch dimension + self.task = test_utils.TestTranslationTask.setup_task(self.args, self.d, self.d) + self.model = self.task.build_model(self.args) + + def test_nll_loss(self): + self.args.label_smoothing = 0.1 + nll_crit = CrossEntropyCriterion.build_criterion(self.args, self.task) + smooth_crit = LabelSmoothedCrossEntropyCriterion.build_criterion( + self.args, self.task + ) + nll_loss, nll_sample_size, nll_logging_output = nll_crit( + self.model, self.sample + ) + smooth_loss, smooth_sample_size, smooth_logging_output = smooth_crit( + self.model, self.sample + ) + self.assertLess(abs(nll_loss - nll_logging_output["loss"]), 1e-6) + self.assertLess(abs(nll_loss - smooth_logging_output["nll_loss"]), 1e-6) + + def test_padding(self): + self.args.label_smoothing = 0.1 + crit = LabelSmoothedCrossEntropyCriterion.build_criterion(self.args, self.task) + loss, _, logging_output = crit(self.model, self.sample) + + def get_one_no_padding(idx): + # create a new sample with just a single batch item so that there's + # no padding + sample1 = next(test_utils.dummy_dataloader([self.data[idx]])) + args1 = copy.copy(self.args) + args1.probs = args1.probs[idx, :, :].unsqueeze(0) + model1 = self.task.build_model(args1) + loss1, _, _ = crit(model1, sample1) + return loss1 + + loss1 = get_one_no_padding(0) + loss2 = get_one_no_padding(1) + self.assertAlmostEqual(loss, loss1 + loss2) + + def test_reduction(self): + self.args.label_smoothing = 0.1 + crit = LabelSmoothedCrossEntropyCriterion.build_criterion(self.args, self.task) + loss, _, logging_output = crit(self.model, self.sample, reduce=True) + unreduced_loss, _, _ = crit(self.model, self.sample, reduce=False) + self.assertAlmostEqual(loss, unreduced_loss.sum()) + + def test_zero_eps(self): + self.args.label_smoothing = 0.0 + nll_crit = CrossEntropyCriterion.build_criterion(self.args, self.task) + smooth_crit = LabelSmoothedCrossEntropyCriterion.build_criterion( + self.args, self.task + ) + nll_loss, nll_sample_size, nll_logging_output = nll_crit( + self.model, self.sample + ) + smooth_loss, smooth_sample_size, smooth_logging_output = smooth_crit( + self.model, self.sample + ) + self.assertAlmostEqual(nll_loss, smooth_loss) + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-6) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_lstm_jitable.py b/fairseq-tools/fairseq/tests/test_lstm_jitable.py new file mode 100644 index 00000000..38f79d17 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_lstm_jitable.py @@ -0,0 +1,115 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import tempfile +import unittest + +import torch +from fairseq.data.dictionary import Dictionary +from fairseq.models.lstm import LSTMModel +from fairseq.tasks.fairseq_task import LegacyFairseqTask + + +DEFAULT_TEST_VOCAB_SIZE = 100 + + +class DummyTask(LegacyFairseqTask): + def __init__(self, args): + super().__init__(args) + self.dictionary = get_dummy_dictionary() + if getattr(self.args, "ctc", False): + self.dictionary.add_symbol("<ctc_blank>") + self.src_dict = self.dictionary + self.tgt_dict = self.dictionary + + @property + def source_dictionary(self): + return self.src_dict + + @property + def target_dictionary(self): + return self.dictionary + + +def get_dummy_dictionary(vocab_size=DEFAULT_TEST_VOCAB_SIZE): + dummy_dict = Dictionary() + # add dummy symbol to satisfy vocab size + for id, _ in enumerate(range(vocab_size)): + dummy_dict.add_symbol("{}".format(id), 1000) + return dummy_dict + + +def get_dummy_task_and_parser(): + """ + to build a fariseq model, we need some dummy parse and task. This function + is used to create dummy task and parser to faciliate model/criterion test + + Note: we use FbSpeechRecognitionTask as the dummy task. You may want + to use other task by providing another function + """ + parser = argparse.ArgumentParser( + description="test_dummy_s2s_task", argument_default=argparse.SUPPRESS + ) + DummyTask.add_args(parser) + args = parser.parse_args([]) + task = DummyTask.setup_task(args) + return task, parser + + +class TestJitLSTMModel(unittest.TestCase): + def _test_save_and_load(self, scripted_module): + with tempfile.NamedTemporaryFile() as f: + scripted_module.save(f.name) + torch.jit.load(f.name) + + def assertTensorEqual(self, t1, t2): + t1 = t1[~torch.isnan(t1)] # can cause size mismatch errors if there are NaNs + t2 = t2[~torch.isnan(t2)] + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + def test_jit_and_export_lstm(self): + task, parser = get_dummy_task_and_parser() + LSTMModel.add_args(parser) + args = parser.parse_args([]) + args.criterion = "" + model = LSTMModel.build_model(args, task) + scripted_model = torch.jit.script(model) + self._test_save_and_load(scripted_model) + + def test_assert_jit_vs_nonjit_(self): + task, parser = get_dummy_task_and_parser() + LSTMModel.add_args(parser) + args = parser.parse_args([]) + args.criterion = "" + model = LSTMModel.build_model(args, task) + model.eval() + scripted_model = torch.jit.script(model) + scripted_model.eval() + idx = len(task.source_dictionary) + iter = 100 + # Inject random input and check output + seq_len_tensor = torch.randint(1, 10, (iter,)) + num_samples_tensor = torch.randint(1, 10, (iter,)) + for i in range(iter): + seq_len = seq_len_tensor[i] + num_samples = num_samples_tensor[i] + src_token = (torch.randint(0, idx, (num_samples, seq_len)),) + src_lengths = torch.randint(1, seq_len + 1, (num_samples,)) + src_lengths, _ = torch.sort(src_lengths, descending=True) + # Force the first sample to have seq_len + src_lengths[0] = seq_len + prev_output_token = (torch.randint(0, idx, (num_samples, 1)),) + result = model(src_token[0], src_lengths, prev_output_token[0], None) + scripted_result = scripted_model( + src_token[0], src_lengths, prev_output_token[0], None + ) + self.assertTensorEqual(result[0], scripted_result[0]) + self.assertTensorEqual(result[1], scripted_result[1]) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_memory_efficient_fp16.py b/fairseq-tools/fairseq/tests/test_memory_efficient_fp16.py new file mode 100644 index 00000000..e10636d9 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_memory_efficient_fp16.py @@ -0,0 +1,66 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import logging +import unittest + +import torch +from fairseq.optim.adam import FairseqAdam +from fairseq.optim.fp16_optimizer import MemoryEfficientFP16Optimizer + + +@unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") +class TestMemoryEfficientFP16(unittest.TestCase): + def setUp(self): + logging.disable(logging.CRITICAL) + + def tearDown(self): + logging.disable(logging.NOTSET) + + def test_load_state_dict(self): + # define simple FP16 model + model = torch.nn.Linear(5, 5).cuda().half() + params = list(model.parameters()) + + # initialize memory efficient FP16 optimizer + optimizer = FairseqAdam( + argparse.Namespace( + lr=[0.00001], + adam_betas="(0.9, 0.999)", + adam_eps=1e-8, + weight_decay=0.0, + ), + params, + ) + me_optimizer = MemoryEfficientFP16Optimizer( + argparse.Namespace( + fp16_init_scale=1, + fp16_scale_window=1, + fp16_scale_tolerance=1, + threshold_loss_scale=1, + min_loss_scale=1e-4, + ), + params, + optimizer, + ) + + # optimizer state is created in the first step + loss = model(torch.rand(5).cuda().half()).sum() + me_optimizer.backward(loss) + me_optimizer.step() + + # reload state + state = me_optimizer.state_dict() + me_optimizer.load_state_dict(state) + for k, v in me_optimizer.optimizer.state.items(): + self.assertTrue(k.dtype == torch.float16) + for v_i in v.values(): + if torch.is_tensor(v_i): + self.assertTrue(v_i.dtype == torch.float32) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_metrics.py b/fairseq-tools/fairseq/tests/test_metrics.py new file mode 100644 index 00000000..2de6969c --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_metrics.py @@ -0,0 +1,77 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest +import uuid + +from fairseq import metrics + + +class TestMetrics(unittest.TestCase): + def test_nesting(self): + with metrics.aggregate() as a: + metrics.log_scalar("loss", 1) + with metrics.aggregate() as b: + metrics.log_scalar("loss", 2) + + self.assertEqual(a.get_smoothed_values()["loss"], 1.5) + self.assertEqual(b.get_smoothed_values()["loss"], 2) + + def test_new_root(self): + with metrics.aggregate() as a: + metrics.log_scalar("loss", 1) + with metrics.aggregate(new_root=True) as b: + metrics.log_scalar("loss", 2) + + self.assertEqual(a.get_smoothed_values()["loss"], 1) + self.assertEqual(b.get_smoothed_values()["loss"], 2) + + def test_nested_new_root(self): + with metrics.aggregate() as layer1: + metrics.log_scalar("loss", 1) + with metrics.aggregate(new_root=True) as layer2: + metrics.log_scalar("loss", 2) + with metrics.aggregate() as layer3: + metrics.log_scalar("loss", 3) + with metrics.aggregate(new_root=True) as layer4: + metrics.log_scalar("loss", 4) + metrics.log_scalar("loss", 1.5) + + self.assertEqual(layer4.get_smoothed_values()["loss"], 4) + self.assertEqual(layer3.get_smoothed_values()["loss"], 3) + self.assertEqual(layer2.get_smoothed_values()["loss"], 2.5) + self.assertEqual(layer1.get_smoothed_values()["loss"], 1.25) + + def test_named(self): + name = str(uuid.uuid4()) + metrics.reset_meters(name) + + with metrics.aggregate(name): + metrics.log_scalar("loss", 1) + + metrics.log_scalar("loss", 3) + + with metrics.aggregate(name): + metrics.log_scalar("loss", 2) + + self.assertEqual(metrics.get_smoothed_values(name)["loss"], 1.5) + + def test_nested_duplicate_names(self): + name = str(uuid.uuid4()) + metrics.reset_meters(name) + + with metrics.aggregate(name): + metrics.log_scalar("loss", 1) + with metrics.aggregate() as other: + with metrics.aggregate(name): + metrics.log_scalar("loss", 2) + metrics.log_scalar("loss", 6) + + self.assertEqual(metrics.get_smoothed_values(name)["loss"], 3) + self.assertEqual(other.get_smoothed_values()["loss"], 2) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_multi_corpus_sampled_dataset.py b/fairseq-tools/fairseq/tests/test_multi_corpus_sampled_dataset.py new file mode 100644 index 00000000..05b20328 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_multi_corpus_sampled_dataset.py @@ -0,0 +1,95 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest +from collections import OrderedDict + +import numpy as np +import torch +from fairseq.data import LanguagePairDataset, TokenBlockDataset +from fairseq.data.multi_corpus_sampled_dataset import MultiCorpusSampledDataset +from tests.test_train import mock_dict + + +class TestMultiCorpusSampledDataset(unittest.TestCase): + def setUp(self): + d = mock_dict() + tokens_1 = torch.LongTensor([1]).view(1, -1) + tokens_ds1 = TokenBlockDataset( + tokens_1, + sizes=[tokens_1.size(-1)], + block_size=1, + pad=0, + eos=1, + include_targets=False, + ) + self.dataset_1 = LanguagePairDataset( + tokens_ds1, tokens_ds1.sizes, d, shuffle=False + ) + tokens_2 = torch.LongTensor([2]).view(1, -1) + tokens_ds2 = TokenBlockDataset( + tokens_2, + sizes=[tokens_2.size(-1)], + block_size=1, + pad=0, + eos=1, + include_targets=False, + ) + self.dataset_2 = LanguagePairDataset( + tokens_ds2, tokens_ds2.sizes, d, shuffle=False + ) + + def _test_sample_helper( + self, + expected_sample_from_first_ds_percentage, + num_samples=1000, + sampling_func=None, + ): + # To make sure test is not flaky + np.random.seed(0) + if sampling_func is None: + m = MultiCorpusSampledDataset( + OrderedDict({0: self.dataset_1, 1: self.dataset_2}), + ) + else: + m = MultiCorpusSampledDataset( + OrderedDict({0: self.dataset_1, 1: self.dataset_2}), + sampling_func=sampling_func, + ) + m.ordered_indices() + count_sample_from_first_dataset = 0 + for _ in range(num_samples): + if m.collater([m[0], m[1]])["net_input"]["src_tokens"][0] == 1: + count_sample_from_first_dataset += 1 + sample_from_first_ds_percentage = ( + 1.0 * count_sample_from_first_dataset / num_samples + ) + self.assertLess( + abs( + sample_from_first_ds_percentage + - expected_sample_from_first_ds_percentage + ), + 0.01, + ) + + def test_multi_corpus_sampled_dataset_uniform_sample(self): + self._test_sample_helper(expected_sample_from_first_ds_percentage=0.5) + + def test_multi_corpus_sampled_dataset_weighted_sample(self): + def naive_weighted_sample(weights): + def f(l): + v = np.random.random() + agg = 0 + for i, weight in enumerate(weights): + agg += weight + if agg > v: + return i + + return f + + self._test_sample_helper( + expected_sample_from_first_ds_percentage=0.9, + sampling_func=naive_weighted_sample(weights=[0.9, 0.1]), + ) diff --git a/fairseq-tools/fairseq/tests/test_multihead_attention.py b/fairseq-tools/fairseq/tests/test_multihead_attention.py new file mode 100644 index 00000000..9aa9cb2f --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_multihead_attention.py @@ -0,0 +1,61 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +from fairseq.modules.multihead_attention import MultiheadAttention + + +class TestMultiheadAttention(unittest.TestCase): + def test_append_prev_key_padding_mask(self): + bsz = 1 + src_len = 4 + + cases = [ + # no padding mask + (None, None, None), + # current padding mask only + ( + torch.tensor([[1]]).bool(), + None, + torch.tensor([[0, 0, 0, 1]]).bool(), + ), + # previous padding mask only + ( + None, + torch.tensor([[0, 1, 0]]).bool(), + torch.tensor([[0, 1, 0, 0]]).bool(), + ), + # both padding masks + ( + torch.tensor([[1]]).bool(), + torch.tensor([[0, 1, 0]]).bool(), + torch.tensor([[0, 1, 0, 1]]).bool(), + ), + ] + for c in cases: + key_padding_mask = MultiheadAttention._append_prev_key_padding_mask( + c[0], + c[1], + batch_size=bsz, + src_len=src_len, + static_kv=False, + ) + + if key_padding_mask is not None: + self.assertTrue( + torch.all(torch.eq(key_padding_mask, c[2])), + f"Unexpected resultant key padding mask: {key_padding_mask}" + f" given current: {c[0]} and previous: {c[1]}", + ) + self.assertEqual(key_padding_mask.size(0), bsz) + self.assertEqual(key_padding_mask.size(1), src_len) + else: + self.assertIsNone(c[2]) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_noising.py b/fairseq-tools/fairseq/tests/test_noising.py new file mode 100644 index 00000000..b3d0d123 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_noising.py @@ -0,0 +1,530 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest +from typing import Dict, List + +import tests.utils as test_utils +import torch +from fairseq import utils +from fairseq.data import ( + Dictionary, + LanguagePairDataset, + TransformEosDataset, + data_utils, + noising, +) + + +class TestDataNoising(unittest.TestCase): + def _get_test_data_with_bpe_cont_marker(self, append_eos=True): + """ + Args: + append_eos: if True, each input sentence in the source tokens tensor + will have an EOS appended to the end. + + Returns: + vocabs: BPE vocab with continuation markers as suffixes to denote + non-end of word tokens. This is the standard BPE format used in + fairseq's preprocessing. + x: input tensor containing numberized source tokens, with EOS at the + end if append_eos is true + src_lengths: and source lengths. + """ + vocab = Dictionary() + vocab.add_symbol("he@@") + vocab.add_symbol("llo") + vocab.add_symbol("how") + vocab.add_symbol("are") + vocab.add_symbol("y@@") + vocab.add_symbol("ou") + vocab.add_symbol("n@@") + vocab.add_symbol("ew") + vocab.add_symbol("or@@") + vocab.add_symbol("k") + + src_tokens = [ + ["he@@", "llo", "n@@", "ew", "y@@", "or@@", "k"], + ["how", "are", "y@@", "ou"], + ] + x, src_lengths = x, src_lengths = self._convert_src_tokens_to_tensor( + vocab=vocab, src_tokens=src_tokens, append_eos=append_eos + ) + return vocab, x, src_lengths + + def _get_test_data_with_bpe_end_marker(self, append_eos=True): + """ + Args: + append_eos: if True, each input sentence in the source tokens tensor + will have an EOS appended to the end. + + Returns: + vocabs: BPE vocab with end-of-word markers as suffixes to denote + tokens at the end of a word. This is an alternative to fairseq's + standard preprocessing framework and is not generally supported + within fairseq. + x: input tensor containing numberized source tokens, with EOS at the + end if append_eos is true + src_lengths: and source lengths. + """ + vocab = Dictionary() + vocab.add_symbol("he") + vocab.add_symbol("llo_EOW") + vocab.add_symbol("how_EOW") + vocab.add_symbol("are_EOW") + vocab.add_symbol("y") + vocab.add_symbol("ou_EOW") + vocab.add_symbol("n") + vocab.add_symbol("ew_EOW") + vocab.add_symbol("or") + vocab.add_symbol("k_EOW") + + src_tokens = [ + ["he", "llo_EOW", "n", "ew_EOW", "y", "or", "k_EOW"], + ["how_EOW", "are_EOW", "y", "ou_EOW"], + ] + x, src_lengths = x, src_lengths = self._convert_src_tokens_to_tensor( + vocab=vocab, src_tokens=src_tokens, append_eos=append_eos + ) + return vocab, x, src_lengths + + def _get_test_data_with_word_vocab(self, append_eos=True): + """ + Args: + append_eos: if True, each input sentence in the source tokens tensor + will have an EOS appended to the end. + + Returns: + vocabs: word vocab + x: input tensor containing numberized source tokens, with EOS at the + end if append_eos is true + src_lengths: and source lengths. + """ + vocab = Dictionary() + + vocab.add_symbol("hello") + vocab.add_symbol("how") + vocab.add_symbol("are") + vocab.add_symbol("you") + vocab.add_symbol("new") + vocab.add_symbol("york") + src_tokens = [ + ["hello", "new", "york", "you"], + ["how", "are", "you", "new", "york"], + ] + x, src_lengths = self._convert_src_tokens_to_tensor( + vocab=vocab, src_tokens=src_tokens, append_eos=append_eos + ) + return vocab, x, src_lengths + + def _convert_src_tokens_to_tensor( + self, vocab: Dictionary, src_tokens: List[List[str]], append_eos: bool + ): + src_len = [len(x) for x in src_tokens] + # If we have to append EOS, we include EOS in counting src length + if append_eos: + src_len = [length + 1 for length in src_len] + + x = torch.LongTensor(len(src_tokens), max(src_len)).fill_(vocab.pad()) + for i in range(len(src_tokens)): + for j in range(len(src_tokens[i])): + x[i][j] = vocab.index(src_tokens[i][j]) + if append_eos: + x[i][j + 1] = vocab.eos() + + x = x.transpose(1, 0) + return x, torch.LongTensor(src_len) + + def assert_eos_at_end(self, x, x_len, eos): + """Asserts last token of every sentence in x is EOS """ + for i in range(len(x_len)): + self.assertEqual( + x[x_len[i] - 1][i], + eos, + ( + "Expected eos (token id {eos}) at the end of sentence {i} " + "but got {other} instead" + ).format(i=i, eos=eos, other=x[i][-1]), + ) + + def assert_word_dropout_correct(self, x, x_noised, x_len, l_noised): + # Expect only the first word (2 bpe tokens) of the first example + # was dropped out + self.assertEqual(x_len[0] - 2, l_noised[0]) + for i in range(l_noised[0]): + self.assertEqual(x_noised[i][0], x[i + 2][0]) + + def test_word_dropout_with_eos(self): + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=True) + + with data_utils.numpy_seed(1234): + noising_gen = noising.WordDropout(vocab) + x_noised, l_noised = noising_gen.noising(x, x_len, 0.2) + self.assert_word_dropout_correct( + x=x, x_noised=x_noised, x_len=x_len, l_noised=l_noised + ) + self.assert_eos_at_end(x=x_noised, x_len=l_noised, eos=vocab.eos()) + + def assert_word_blanking_correct(self, x, x_noised, x_len, l_noised, unk): + # Expect only the first word (2 bpe tokens) of the first example + # was blanked out + self.assertEqual(x_len[0], l_noised[0]) + for i in range(l_noised[0]): + if i < 2: + self.assertEqual(x_noised[i][0], unk) + else: + self.assertEqual(x_noised[i][0], x[i][0]) + + def test_word_blank_with_eos(self): + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=True) + + with data_utils.numpy_seed(1234): + noising_gen = noising.WordDropout(vocab) + x_noised, l_noised = noising_gen.noising(x, x_len, 0.2, vocab.unk()) + self.assert_word_blanking_correct( + x=x, x_noised=x_noised, x_len=x_len, l_noised=l_noised, unk=vocab.unk() + ) + self.assert_eos_at_end(x=x_noised, x_len=l_noised, eos=vocab.eos()) + + def generate_unchanged_shuffle_map(self, length): + return {i: i for i in range(length)} + + def assert_word_shuffle_matches_expected( + self, + x, + x_len, + max_shuffle_distance: int, + vocab: Dictionary, + expected_shufle_maps: List[Dict[int, int]], + expect_eos_at_end: bool, + bpe_end_marker=None, + ): + """ + This verifies that with a given x, x_len, max_shuffle_distance, and + vocab, we get the expected shuffle result. + + Args: + x: Tensor of shape (T x B) = (sequence_length, batch_size) + x_len: Tensor of length B = batch_size + max_shuffle_distance: arg to pass to noising + expected_shuffle_maps: List[mapping] where mapping is a + Dict[old_index, new_index], mapping x's elements from their + old positions in x to their new positions in x. + expect_eos_at_end: if True, check the output to make sure there is + an EOS at the end. + bpe_end_marker: str denoting the BPE end token. If this is not None, we + set the BPE cont token to None in the noising classes. + """ + bpe_cont_marker = None + if bpe_end_marker is None: + bpe_cont_marker = "@@" + + with data_utils.numpy_seed(1234): + word_shuffle = noising.WordShuffle( + vocab, bpe_cont_marker=bpe_cont_marker, bpe_end_marker=bpe_end_marker + ) + x_noised, l_noised = word_shuffle.noising( + x, x_len, max_shuffle_distance=max_shuffle_distance + ) + + # For every example, we have a different expected shuffle map. We check + # that each example is shuffled as expected according to each + # corresponding shuffle map. + for i in range(len(expected_shufle_maps)): + shuffle_map = expected_shufle_maps[i] + for k, v in shuffle_map.items(): + self.assertEqual(x[k][i], x_noised[v][i]) + + # Shuffling should not affect the length of each example + for pre_shuffle_length, post_shuffle_length in zip(x_len, l_noised): + self.assertEqual(pre_shuffle_length, post_shuffle_length) + if expect_eos_at_end: + self.assert_eos_at_end(x=x_noised, x_len=l_noised, eos=vocab.eos()) + + def test_word_shuffle_with_eos(self): + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=True) + + # Assert word shuffle with max shuffle distance 0 causes input to be + # unchanged + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + max_shuffle_distance=0, + vocab=vocab, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(example_len) + for example_len in x_len + ], + expect_eos_at_end=True, + ) + + # Assert word shuffle with max shuffle distance 3 matches our expected + # shuffle order + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + vocab=vocab, + max_shuffle_distance=3, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(x_len[0]), + {0: 0, 1: 3, 2: 1, 3: 2}, + ], + expect_eos_at_end=True, + ) + + def test_word_shuffle_with_eos_nonbpe(self): + """The purpose of this is to test shuffling logic with word vocabs""" + vocab, x, x_len = self._get_test_data_with_word_vocab(append_eos=True) + + # Assert word shuffle with max shuffle distance 0 causes input to be + # unchanged + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + max_shuffle_distance=0, + vocab=vocab, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(example_len) + for example_len in x_len + ], + expect_eos_at_end=True, + ) + + # Assert word shuffle with max shuffle distance 3 matches our expected + # shuffle order + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + vocab=vocab, + max_shuffle_distance=3, + expected_shufle_maps=[ + {0: 0, 1: 1, 2: 3, 3: 2}, + {0: 0, 1: 2, 2: 1, 3: 3, 4: 4}, + ], + expect_eos_at_end=True, + ) + + def test_word_shuffle_without_eos(self): + """Same result as word shuffle with eos except no EOS at end""" + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=False) + + # Assert word shuffle with max shuffle distance 0 causes input to be + # unchanged + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + max_shuffle_distance=0, + vocab=vocab, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(example_len) + for example_len in x_len + ], + expect_eos_at_end=False, + ) + + # Assert word shuffle with max shuffle distance 3 matches our expected + # shuffle order + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + vocab=vocab, + max_shuffle_distance=3, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(x_len[0]), + {0: 0, 1: 3, 2: 1, 3: 2}, + ], + expect_eos_at_end=False, + ) + + def test_word_shuffle_without_eos_with_bpe_end_marker(self): + """Same result as word shuffle without eos except using BPE end token""" + vocab, x, x_len = self._get_test_data_with_bpe_end_marker(append_eos=False) + + # Assert word shuffle with max shuffle distance 0 causes input to be + # unchanged + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + max_shuffle_distance=0, + vocab=vocab, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(example_len) + for example_len in x_len + ], + expect_eos_at_end=False, + bpe_end_marker="_EOW", + ) + + # Assert word shuffle with max shuffle distance 3 matches our expected + # shuffle order + self.assert_word_shuffle_matches_expected( + x=x, + x_len=x_len, + vocab=vocab, + max_shuffle_distance=3, + expected_shufle_maps=[ + self.generate_unchanged_shuffle_map(x_len[0]), + {0: 0, 1: 3, 2: 1, 3: 2}, + ], + expect_eos_at_end=False, + bpe_end_marker="_EOW", + ) + + def assert_no_eos_at_end(self, x, x_len, eos): + """Asserts that the last token of each sentence in x is not EOS """ + for i in range(len(x_len)): + self.assertNotEqual( + x[x_len[i] - 1][i], + eos, + "Expected no eos (token id {eos}) at the end of sentence {i}.".format( + eos=eos, i=i + ), + ) + + def test_word_dropout_without_eos(self): + """Same result as word dropout with eos except no EOS at end""" + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=False) + + with data_utils.numpy_seed(1234): + noising_gen = noising.WordDropout(vocab) + x_noised, l_noised = noising_gen.noising(x, x_len, 0.2) + self.assert_word_dropout_correct( + x=x, x_noised=x_noised, x_len=x_len, l_noised=l_noised + ) + self.assert_no_eos_at_end(x=x_noised, x_len=l_noised, eos=vocab.eos()) + + def test_word_blank_without_eos(self): + """Same result as word blank with eos except no EOS at end""" + vocab, x, x_len = self._get_test_data_with_bpe_cont_marker(append_eos=False) + + with data_utils.numpy_seed(1234): + noising_gen = noising.WordDropout(vocab) + x_noised, l_noised = noising_gen.noising(x, x_len, 0.2, vocab.unk()) + self.assert_word_blanking_correct( + x=x, x_noised=x_noised, x_len=x_len, l_noised=l_noised, unk=vocab.unk() + ) + self.assert_no_eos_at_end(x=x_noised, x_len=l_noised, eos=vocab.eos()) + + def _get_noising_dataset_batch( + self, + src_tokens_no_pad, + src_dict, + append_eos_to_tgt=False, + ): + """ + Constructs a NoisingDataset and the corresponding + ``LanguagePairDataset(NoisingDataset(src), src)``. If + *append_eos_to_tgt* is True, wrap the source dataset in + :class:`TransformEosDataset` to append EOS to the clean source when + using it as the target. + """ + src_dataset = test_utils.TestDataset(data=src_tokens_no_pad) + + noising_dataset = noising.NoisingDataset( + src_dataset=src_dataset, + src_dict=src_dict, + seed=1234, + max_word_shuffle_distance=3, + word_dropout_prob=0.2, + word_blanking_prob=0.2, + noising_class=noising.UnsupervisedMTNoising, + ) + tgt = src_dataset + language_pair_dataset = LanguagePairDataset( + src=noising_dataset, tgt=tgt, src_sizes=None, src_dict=src_dict + ) + language_pair_dataset = TransformEosDataset( + language_pair_dataset, + src_dict.eos(), + append_eos_to_tgt=append_eos_to_tgt, + ) + + dataloader = torch.utils.data.DataLoader( + dataset=language_pair_dataset, + batch_size=2, + collate_fn=language_pair_dataset.collater, + ) + denoising_batch_result = next(iter(dataloader)) + return denoising_batch_result + + def test_noising_dataset_with_eos(self): + src_dict, src_tokens, _ = self._get_test_data_with_bpe_cont_marker( + append_eos=True + ) + + # Format data for src_dataset + src_tokens = torch.t(src_tokens) + src_tokens_no_pad = [] + for src_sentence in src_tokens: + src_tokens_no_pad.append( + utils.strip_pad(tensor=src_sentence, pad=src_dict.pad()) + ) + denoising_batch_result = self._get_noising_dataset_batch( + src_tokens_no_pad=src_tokens_no_pad, src_dict=src_dict + ) + + eos, pad = src_dict.eos(), src_dict.pad() + + # Generated noisy source as source + expected_src = torch.LongTensor( + [[4, 5, 10, 11, 8, 12, 13, eos], [pad, pad, pad, 6, 8, 9, 7, eos]] + ) + # Original clean source as target (right-padded) + expected_tgt = torch.LongTensor( + [[4, 5, 10, 11, 8, 12, 13, eos], [6, 7, 8, 9, eos, pad, pad, pad]] + ) + generated_src = denoising_batch_result["net_input"]["src_tokens"] + tgt_tokens = denoising_batch_result["target"] + + self.assertTensorEqual(expected_src, generated_src) + self.assertTensorEqual(expected_tgt, tgt_tokens) + + def test_noising_dataset_without_eos(self): + """ + Similar to test noising dataset with eos except that we have to set + *append_eos_to_tgt* to ``True``. + """ + + src_dict, src_tokens, _ = self._get_test_data_with_bpe_cont_marker( + append_eos=False + ) + + # Format data for src_dataset + src_tokens = torch.t(src_tokens) + src_tokens_no_pad = [] + for src_sentence in src_tokens: + src_tokens_no_pad.append( + utils.strip_pad(tensor=src_sentence, pad=src_dict.pad()) + ) + denoising_batch_result = self._get_noising_dataset_batch( + src_tokens_no_pad=src_tokens_no_pad, + src_dict=src_dict, + append_eos_to_tgt=True, + ) + + eos, pad = src_dict.eos(), src_dict.pad() + + # Generated noisy source as source + expected_src = torch.LongTensor( + [[4, 5, 10, 11, 8, 12, 13], [pad, pad, pad, 6, 8, 9, 7]] + ) + # Original clean source as target (right-padded) + expected_tgt = torch.LongTensor( + [[4, 5, 10, 11, 8, 12, 13, eos], [6, 7, 8, 9, eos, pad, pad, pad]] + ) + + generated_src = denoising_batch_result["net_input"]["src_tokens"] + tgt_tokens = denoising_batch_result["target"] + + self.assertTensorEqual(expected_src, generated_src) + self.assertTensorEqual(expected_tgt, tgt_tokens) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_reproducibility.py b/fairseq-tools/fairseq/tests/test_reproducibility.py new file mode 100644 index 00000000..517e23c3 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_reproducibility.py @@ -0,0 +1,138 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import json +import os +import tempfile +import unittest +from io import StringIO + +import torch + +from . import test_binaries + + +class TestReproducibility(unittest.TestCase): + def _test_reproducibility( + self, + name, + extra_flags=None, + delta=0.0001, + resume_checkpoint="checkpoint1.pt", + max_epoch=3, + ): + def get_last_log_stats_containing_string(log_records, search_string): + for log_record in logs.records[::-1]: + if search_string in log_record.msg: + return json.loads(log_record.msg) + + if extra_flags is None: + extra_flags = [] + + with tempfile.TemporaryDirectory(name) as data_dir: + with self.assertLogs() as logs: + test_binaries.create_dummy_data(data_dir) + test_binaries.preprocess_translation_data(data_dir) + + # train epochs 1 and 2 together + with self.assertLogs() as logs: + test_binaries.train_translation_model( + data_dir, + "fconv_iwslt_de_en", + [ + "--dropout", + "0.0", + "--log-format", + "json", + "--log-interval", + "1", + "--max-epoch", + str(max_epoch), + ] + + extra_flags, + ) + train_log = get_last_log_stats_containing_string(logs.records, "train_loss") + valid_log = get_last_log_stats_containing_string(logs.records, "valid_loss") + + # train epoch 2, resuming from previous checkpoint 1 + os.rename( + os.path.join(data_dir, resume_checkpoint), + os.path.join(data_dir, "checkpoint_last.pt"), + ) + with self.assertLogs() as logs: + test_binaries.train_translation_model( + data_dir, + "fconv_iwslt_de_en", + [ + "--dropout", + "0.0", + "--log-format", + "json", + "--log-interval", + "1", + "--max-epoch", + str(max_epoch), + ] + + extra_flags, + ) + train_res_log = get_last_log_stats_containing_string( + logs.records, "train_loss" + ) + valid_res_log = get_last_log_stats_containing_string( + logs.records, "valid_loss" + ) + + for k in ["train_loss", "train_ppl", "train_num_updates", "train_gnorm"]: + self.assertAlmostEqual( + float(train_log[k]), float(train_res_log[k]), delta=delta + ) + for k in [ + "valid_loss", + "valid_ppl", + "valid_num_updates", + "valid_best_loss", + ]: + self.assertAlmostEqual( + float(valid_log[k]), float(valid_res_log[k]), delta=delta + ) + + def test_reproducibility(self): + self._test_reproducibility("test_reproducibility") + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_reproducibility_fp16(self): + self._test_reproducibility( + "test_reproducibility_fp16", + [ + "--fp16", + "--fp16-init-scale", + "4096", + ], + delta=0.011, + ) + + @unittest.skipIf(not torch.cuda.is_available(), "test requires a GPU") + def test_reproducibility_memory_efficient_fp16(self): + self._test_reproducibility( + "test_reproducibility_memory_efficient_fp16", + [ + "--memory-efficient-fp16", + "--fp16-init-scale", + "4096", + ], + ) + + def test_mid_epoch_reproducibility(self): + self._test_reproducibility( + "test_mid_epoch_reproducibility", + ["--save-interval-updates", "3"], + resume_checkpoint="checkpoint_1_3.pt", + max_epoch=1, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_resampling_dataset.py b/fairseq-tools/fairseq/tests/test_resampling_dataset.py new file mode 100644 index 00000000..ccb53a25 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_resampling_dataset.py @@ -0,0 +1,103 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import collections +import unittest + +import numpy as np +from fairseq.data import ListDataset, ResamplingDataset + + +class TestResamplingDataset(unittest.TestCase): + def setUp(self): + self.strings = ["ab", "c", "def", "ghij"] + self.weights = [4.0, 2.0, 7.0, 1.5] + self.size_ratio = 2 + self.dataset = ListDataset( + self.strings, np.array([len(s) for s in self.strings]) + ) + + def _test_common(self, resampling_dataset, iters): + assert len(self.dataset) == len(self.strings) == len(self.weights) + assert len(resampling_dataset) == self.size_ratio * len(self.strings) + + results = {"ordered_by_size": True, "max_distribution_diff": 0.0} + + totalfreqs = 0 + freqs = collections.defaultdict(int) + + for epoch_num in range(iters): + resampling_dataset.set_epoch(epoch_num) + + indices = resampling_dataset.ordered_indices() + assert len(indices) == len(resampling_dataset) + + prev_size = -1 + + for i in indices: + cur_size = resampling_dataset.size(i) + # Make sure indices map to same sequences within an epoch + assert resampling_dataset[i] == resampling_dataset[i] + + # Make sure length of sequence is correct + assert cur_size == len(resampling_dataset[i]) + + freqs[resampling_dataset[i]] += 1 + totalfreqs += 1 + + if prev_size > cur_size: + results["ordered_by_size"] = False + + prev_size = cur_size + + assert set(freqs.keys()) == set(self.strings) + for s, weight in zip(self.strings, self.weights): + freq = freqs[s] / totalfreqs + expected_freq = weight / sum(self.weights) + results["max_distribution_diff"] = max( + results["max_distribution_diff"], abs(expected_freq - freq) + ) + + return results + + def test_resampling_dataset_batch_by_size_false(self): + resampling_dataset = ResamplingDataset( + self.dataset, + self.weights, + size_ratio=self.size_ratio, + batch_by_size=False, + seed=0, + ) + + results = self._test_common(resampling_dataset, iters=1000) + + # For batch_by_size = False, the batches should be returned in + # arbitrary order of size. + assert not results["ordered_by_size"] + + # Allow tolerance in distribution error of 2%. + assert results["max_distribution_diff"] < 0.02 + + def test_resampling_dataset_batch_by_size_true(self): + resampling_dataset = ResamplingDataset( + self.dataset, + self.weights, + size_ratio=self.size_ratio, + batch_by_size=True, + seed=0, + ) + + results = self._test_common(resampling_dataset, iters=1000) + + # For batch_by_size = True, the batches should be returned in + # increasing order of size. + assert results["ordered_by_size"] + + # Allow tolerance in distribution error of 2%. + assert results["max_distribution_diff"] < 0.02 + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_sequence_generator.py b/fairseq-tools/fairseq/tests/test_sequence_generator.py new file mode 100644 index 00000000..c890b655 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_sequence_generator.py @@ -0,0 +1,647 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import tempfile +import unittest + +import tests.utils as test_utils +import torch +from fairseq import search +from fairseq.data.dictionary import Dictionary +from fairseq.models.transformer import TransformerModel +from fairseq.sequence_generator import EnsembleModel, SequenceGenerator +from fairseq.tasks.fairseq_task import LegacyFairseqTask + + +DEFAULT_TEST_VOCAB_SIZE = 100 + + +class DummyTask(LegacyFairseqTask): + def __init__(self, args): + super().__init__(args) + self.dictionary = get_dummy_dictionary() + if getattr(self.args, "ctc", False): + self.dictionary.add_symbol("<ctc_blank>") + self.src_dict = self.dictionary + self.tgt_dict = self.dictionary + + @property + def source_dictionary(self): + return self.src_dict + + @property + def target_dictionary(self): + return self.dictionary + + +def get_dummy_dictionary(vocab_size=DEFAULT_TEST_VOCAB_SIZE): + dummy_dict = Dictionary() + # add dummy symbol to satisfy vocab size + for id, _ in enumerate(range(vocab_size)): + dummy_dict.add_symbol("{}".format(id), 1000) + return dummy_dict + + +def get_dummy_task_and_parser(): + """ + to build a fariseq model, we need some dummy parse and task. This function + is used to create dummy task and parser to faciliate model/criterion test + + Note: we use FbSpeechRecognitionTask as the dummy task. You may want + to use other task by providing another function + """ + parser = argparse.ArgumentParser( + description="test_dummy_s2s_task", argument_default=argparse.SUPPRESS + ) + DummyTask.add_args(parser) + args = parser.parse_args([]) + task = DummyTask.setup_task(args) + return task, parser + + +class TestJitSequenceGeneratorBase(unittest.TestCase): + def setUp(self): + self.task, self.parser = get_dummy_task_and_parser() + eos = self.task.tgt_dict.eos() + src_tokens = torch.randint(3, 50, (2, 10)).long() + src_tokens = torch.cat((src_tokens, torch.LongTensor([[eos], [eos]])), -1) + src_lengths = torch.LongTensor([2, 10]) + self.sample = { + "net_input": {"src_tokens": src_tokens, "src_lengths": src_lengths} + } + TransformerModel.add_args(self.parser) + args = self.parser.parse_args([]) + args.encoder_layers = 2 + args.decoder_layers = 1 + self.transformer_model = TransformerModel.build_model(args, self.task) + + def assertOutputEqual(self, hypo, pos_probs): + pos_scores = torch.FloatTensor(pos_probs).log() + self.assertTensorSizeEqual(hypo["positional_scores"], pos_scores) + self.assertTensorSizeEqual(pos_scores.numel(), hypo["tokens"].numel()) + + def assertTensorSizeEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-4) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + def assertHypoEqual(self, h1, h2): + "Check two hypos are equal" + self.assertTensorEqual(h1["tokens"], h2["tokens"]) + self.assertAlmostEqual(h1["positional_scores"], h2["positional_scores"]) + self.assertLess(abs(h1["score"] - h2["score"]), 1e-6) + self.assertAlmostEqual(h1["attention"], h2["attention"]) + + def _test_save_and_load(self, scripted_module): + with tempfile.NamedTemporaryFile() as f: + scripted_module.save(f.name) + torch.jit.load(f.name) + + +class TestJitSequeneceGenerator(TestJitSequenceGeneratorBase): + @unittest.skipIf( + torch.__version__ < "1.6.0", "Targeting OSS scriptability for the 1.6 release" + ) + def test_export_transformer(self): + model = self.transformer_model + torch.jit.script(model) + + @unittest.skipIf( + torch.__version__ < "1.6.0", "Targeting OSS scriptability for the 1.6 release" + ) + def test_ensemble_sequence_generator(self): + model = self.transformer_model + generator = SequenceGenerator( + [model], self.task.tgt_dict, beam_size=2, no_repeat_ngram_size=2 + ) + scripted_model = torch.jit.script(generator) + self._test_save_and_load(scripted_model) + + +class TestJitEnsemble(TestJitSequenceGeneratorBase): + @unittest.skipIf( + torch.__version__ < "1.6.0", "Targeting OSS scriptability for the 1.6 release" + ) + def test_export_ensemble_model(self): + model = self.transformer_model + ensemble_models = EnsembleModel([model]) + torch.jit.script(ensemble_models) + + +class TestExportSearch(unittest.TestCase): + def setUp(self): + task, _ = get_dummy_task_and_parser() + self.tgt_dict = task.tgt_dict + self.min_top1_prob = 0.4 + + def test_export_diverse_bs(self): + search_strategy = search.DiverseBeamSearch( + self.tgt_dict, num_groups=2, diversity_strength=0.0 + ) + torch.jit.script(search_strategy) + + def test_export_sampling(self): + low_sampling_topp = self.min_top1_prob / 2.0 + search_strategy = search.Sampling( + self.tgt_dict, sampling_topp=low_sampling_topp + ) + torch.jit.script(search_strategy) + + def test_export_diverse_siblings_search(self): + search_strategy = search.DiverseSiblingsSearch( + self.tgt_dict, diversity_rate=0.5 + ) + torch.jit.script(search_strategy) + + +class TestSequenceGeneratorBase(unittest.TestCase): + def assertHypoTokens(self, hypo, tokens): + self.assertTensorEqual(hypo["tokens"], torch.LongTensor(tokens)) + + def assertHypoScore(self, hypo, pos_probs, normalized=True, lenpen=1.0): + pos_scores = torch.FloatTensor(pos_probs).log() + self.assertAlmostEqual(hypo["positional_scores"], pos_scores) + self.assertEqual(pos_scores.numel(), hypo["tokens"].numel()) + score = pos_scores.sum() + if normalized: + score /= pos_scores.numel() ** lenpen + self.assertLess(abs(score - hypo["score"]), 1e-6) + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-4) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + +class TestSequeneceGenerator(TestSequenceGeneratorBase): + def setUp(self): + ( + self.tgt_dict, + self.w1, + self.w2, + src_tokens, + src_lengths, + self.model, + ) = test_utils.sequence_generator_setup() + self.sample = { + "net_input": {"src_tokens": src_tokens, "src_lengths": src_lengths} + } + + def test_with_normalization(self): + generator = SequenceGenerator([self.model], self.tgt_dict, beam_size=2) + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 1.0]) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w2, w1, w2, eos]) + self.assertHypoScore(hypos[0][1], [0.1, 0.9, 0.9, 1.0]) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, w1, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.4, 1.0]) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w2, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.4, 0.6]) + + def test_without_normalization(self): + # Sentence 1: unchanged from the normalized case + # Sentence 2: beams swap order + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, normalize_scores=False + ) + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 1.0], normalized=False) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w2, w1, w2, eos]) + self.assertHypoScore(hypos[0][1], [0.1, 0.9, 0.9, 1.0], normalized=False) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.6], normalized=False) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w2, w1, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.4, 0.4, 1.0], normalized=False) + + def test_with_lenpen_favoring_short_hypos(self): + lenpen = 0.6 + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, len_penalty=lenpen + ) + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 1.0], lenpen=lenpen) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w2, w1, w2, eos]) + self.assertHypoScore(hypos[0][1], [0.1, 0.9, 0.9, 1.0], lenpen=lenpen) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.6], lenpen=lenpen) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w2, w1, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.4, 0.4, 1.0], lenpen=lenpen) + + def test_with_lenpen_favoring_long_hypos(self): + lenpen = 5.0 + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, len_penalty=lenpen + ) + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w2, w1, w2, eos]) + self.assertHypoScore(hypos[0][0], [0.1, 0.9, 0.9, 1.0], lenpen=lenpen) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w1, eos]) + self.assertHypoScore(hypos[0][1], [0.9, 1.0], lenpen=lenpen) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, w1, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.4, 1.0], lenpen=lenpen) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w2, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.4, 0.6], lenpen=lenpen) + + def test_maxlen(self): + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, max_len_b=2 + ) + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 1.0]) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w2, w2, eos]) + self.assertHypoScore(hypos[0][1], [0.1, 0.1, 0.6]) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.6]) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w2, w2, eos]) + self.assertHypoScore(hypos[1][1], [0.3, 0.9, 0.01]) + + def test_encoder_with_different_output_len(self): + args = self.model.encoder.args + task = test_utils.TestTranslationTask.setup_task( + args, self.tgt_dict, self.tgt_dict + ) + reshaping_model = test_utils.TestReshapingModel.build_model(args, task) + generator = SequenceGenerator( + [reshaping_model], self.tgt_dict, beam_size=2, max_len_b=2 + ) + hypos = generator.forward(self.sample) + for sent in [0, 1]: + for beam in [0, 1]: + assert hypos[sent][beam]["attention"] is not None + + def test_generation_with_additional_input(self): + args = self.model.encoder.args + task = test_utils.TestTranslationTask.setup_task( + args, self.tgt_dict, self.tgt_dict + ) + add_input_model = test_utils.TestAdditionalInputModel.build_model(args, task) + generator = SequenceGenerator([add_input_model], self.tgt_dict, beam_size=2) + sample = self.sample.copy() + sample["net_input"]["fancy_other_input"] = sample["net_input"]["src_tokens"] + hypos = generator.forward(self.sample) + eos, w1, w2 = self.tgt_dict.eos(), self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 1.0]) + + +class TestDiverseBeamSearch(TestSequenceGeneratorBase): + def setUp(self): + # construct dummy dictionary + d = test_utils.dummy_dictionary(vocab_size=2) + self.assertEqual(d.pad(), 1) + self.assertEqual(d.eos(), 2) + self.assertEqual(d.unk(), 3) + self.eos = d.eos() + self.w1 = 4 + self.w2 = 5 + + # construct source data + self.src_tokens = torch.LongTensor( + [ + [self.w1, self.w2, self.eos], + [self.w1, self.w2, self.eos], + ] + ) + self.src_lengths = torch.LongTensor([2, 2]) + + args = argparse.Namespace() + unk = 0.0 + args.beam_probs = [ + # step 0: + torch.FloatTensor( + [ + # eos w1 w2 + # sentence 1: + [0.0, unk, 0.9, 0.1], # beam 1 + [0.0, unk, 0.9, 0.1], # beam 2 + # sentence 2: + [0.0, unk, 0.7, 0.3], + [0.0, unk, 0.7, 0.3], + ] + ), + # step 1: + torch.FloatTensor( + [ + # eos w1 w2 + # sentence 1: + [0.0, unk, 0.6, 0.4], + [0.0, unk, 0.6, 0.4], + # sentence 2: + [0.25, unk, 0.35, 0.4], + [0.25, unk, 0.35, 0.4], + ] + ), + # step 2: + torch.FloatTensor( + [ + # eos w1 w2 + # sentence 1: + [1.0, unk, 0.0, 0.0], + [1.0, unk, 0.0, 0.0], + # sentence 2: + [0.9, unk, 0.1, 0.0], + [0.9, unk, 0.1, 0.0], + ] + ), + ] + + task = test_utils.TestTranslationTask.setup_task(args, d, d) + self.model = task.build_model(args) + self.tgt_dict = task.target_dictionary + + def test_diverse_beam_search(self): + search_strategy = search.DiverseBeamSearch( + self.tgt_dict, num_groups=2, diversity_strength=0.0 + ) + generator = SequenceGenerator( + [self.model], + self.tgt_dict, + beam_size=2, + search_strategy=search_strategy, + ) + sample = { + "net_input": { + "src_tokens": self.src_tokens, + "src_lengths": self.src_lengths, + } + } + hypos = generator.forward(sample) + eos, w1, w2 = self.eos, self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 0.6, 1.0]) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w1, w1, eos]) + self.assertHypoScore(hypos[0][1], [0.9, 0.6, 1.0]) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.9]) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w2, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.4, 0.9]) + + +class TestDiverseSiblingsSearch(TestDiverseBeamSearch): + def assertHypoScore( + self, hypo, pos_probs, sibling_rank, diversity_rate, normalized=True, lenpen=1.0 + ): + pos_scores = torch.FloatTensor(pos_probs).log() + pos_scores.sub_(torch.Tensor(sibling_rank) * diversity_rate) + self.assertAlmostEqual(hypo["positional_scores"], pos_scores) + self.assertEqual(pos_scores.numel(), hypo["tokens"].numel()) + score = pos_scores.sum() + if normalized: + score /= pos_scores.numel() ** lenpen + self.assertLess(abs(score - hypo["score"]), 1e-6) + + def test_diverse_beam_search(self): + search_strategy = search.DiverseSiblingsSearch( + self.tgt_dict, diversity_rate=0.5 + ) + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, search_strategy=search_strategy + ) + sample = { + "net_input": { + "src_tokens": self.src_tokens, + "src_lengths": self.src_lengths, + } + } + hypos = generator.forward(sample) + eos, w1, w2 = self.eos, self.w1, self.w2 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, w1, eos]) + self.assertHypoScore(hypos[0][0], [0.9, 0.6, 1.0], [0, 1, 1], 0.5) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w1, w2, eos]) + self.assertHypoScore(hypos[0][1], [0.9, 0.4, 1.0], [0, 2, 1], 0.5) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w2, eos]) + self.assertHypoScore(hypos[1][0], [0.7, 0.4, 0.9], [0, 1, 1], 0.5) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w1, eos]) + self.assertHypoScore(hypos[1][1], [0.7, 0.35, 0.9], [0, 2, 1], 0.5) + + +class TestTopPSamplingSearch(TestSequenceGeneratorBase): + def setUp(self): + # construct dummy dictionary + d = test_utils.dummy_dictionary(vocab_size=2) + self.assertEqual(d.pad(), 1) + self.assertEqual(d.eos(), 2) + self.assertEqual(d.unk(), 3) + self.eos = d.eos() + self.w1 = 4 + self.w2 = 5 + + # construct source data + self.src_tokens = torch.LongTensor( + [ + [self.w1, self.w2, self.eos], + [self.w1, self.w2, self.eos], + ] + ) + self.src_lengths = torch.LongTensor([2, 2]) + + args = argparse.Namespace() + unk = 0.0 + # The minimal probability of top 2 tokens. + self.min_top2_prob = 0.75 + # The minimal probability of the top 1 token. + self.min_top1_prob = 0.4 + + w1_prob = self.min_top1_prob + w2_prob = self.min_top2_prob - self.min_top1_prob + eos_prob = 1 - self.min_top2_prob + + args.beam_probs = [ + # step 0: + torch.FloatTensor( + [ + # eos w1 w2 + [0.0, unk, 1.0, 0.0], + [0.0, unk, 1.0, 0.0], + [0.0, unk, 1.0, 0.0], + [0.0, unk, 1.0, 0.0], + ] + ), + # step 1: + torch.FloatTensor( + [ + # eos w1 w2 + [eos_prob, unk, w1_prob, w2_prob], + [eos_prob, unk, w1_prob, w2_prob], + [eos_prob, unk, w1_prob, w2_prob], + [eos_prob, unk, w1_prob, w2_prob], + ] + ), + # step 2: + torch.FloatTensor( + [ + # eos w1 w2 + [1.0, unk, 0.0, 0.0], + [1.0, unk, 0.0, 0.0], + [1.0, unk, 0.0, 0.0], + [1.0, unk, 0.0, 0.0], + ] + ), + ] + + task = test_utils.TestTranslationTask.setup_task(args, d, d) + self.model = task.build_model(args) + self.tgt_dict = task.target_dictionary + + def test_topp_sampling_search_low_prob(self): + # Given a prob low enough to top-P sampling, we expect only the top + # 1 token to be sampled, which always results in the same output. + low_sampling_topp = self.min_top1_prob / 2.0 + search_strategy = search.Sampling( + self.tgt_dict, sampling_topp=low_sampling_topp + ) + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, search_strategy=search_strategy + ) + sample = { + "net_input": { + "src_tokens": self.src_tokens, + "src_lengths": self.src_lengths, + } + } + hypos = generator.forward(sample) + eos, w1 = self.eos, self.w1 + # sentence 1, beam 1 + self.assertHypoTokens(hypos[0][0], [w1, w1, eos]) + self.assertHypoScore(hypos[0][0], [1.0, 0.4, 1.0]) + # sentence 1, beam 2 + self.assertHypoTokens(hypos[0][1], [w1, w1, eos]) + self.assertHypoScore(hypos[0][1], [1.0, 0.4, 1.0]) + # sentence 2, beam 1 + self.assertHypoTokens(hypos[1][0], [w1, w1, eos]) + self.assertHypoScore(hypos[1][0], [1.0, 0.4, 1.0]) + # sentence 2, beam 2 + self.assertHypoTokens(hypos[1][1], [w1, w1, eos]) + self.assertHypoScore(hypos[1][1], [1.0, 0.4, 1.0]) + + def test_topp_sampling_search_high_prob(self): + # Given a prob high enough to top-P sampling, any of the top 2 + # tokens could be sampled. This can cause different outputs. + high_sampling_topp = (self.min_top1_prob + self.min_top2_prob) / 2.0 + search_strategy = search.Sampling( + self.tgt_dict, sampling_topp=high_sampling_topp + ) + generator = SequenceGenerator( + [self.model], self.tgt_dict, beam_size=2, search_strategy=search_strategy + ) + sample = { + "net_input": { + "src_tokens": self.src_tokens, + "src_lengths": self.src_lengths, + } + } + hypos = generator.forward(sample) + eos, w1, w2 = self.eos, self.w1, self.w2 + # sentence 1, beam 1 + self.assertTrue( + self.hypoTokens(hypos[0][0], [w1, w1, eos]) + or self.hypoTokens(hypos[0][0], [w1, w2, eos]) + ) + self.assertTrue( + self.hypoScore(hypos[0][0], [1.0, 0.4, 1.0]) + or self.hypoScore(hypos[0][0], [1.0, 0.35, 1.0]) + ) + + # sentence 1, beam 2 + self.assertTrue( + self.hypoTokens(hypos[0][1], [w1, w1, eos]) + or self.hypoTokens(hypos[0][1], [w1, w2, eos]) + ) + self.assertTrue( + self.hypoScore(hypos[0][1], [1.0, 0.4, 1.0]) + or self.hypoScore(hypos[0][1], [1.0, 0.35, 1.0]) + ) + + # sentence 2, beam 1 + self.assertTrue( + self.hypoTokens(hypos[1][0], [w1, w1, eos]) + or self.hypoTokens(hypos[1][0], [w1, w2, eos]) + ) + self.assertTrue( + self.hypoScore(hypos[1][0], [1.0, 0.4, 1.0]) + or self.hypoScore(hypos[1][0], [1.0, 0.35, 1.0]) + ) + + # sentence 2, beam 2 + self.assertTrue( + self.hypoTokens(hypos[1][1], [w1, w1, eos]) + or self.hypoTokens(hypos[1][1], [w1, w2, eos]) + ) + self.assertTrue( + self.hypoScore(hypos[1][1], [1.0, 0.4, 1.0]) + or self.hypoScore(hypos[1][1], [1.0, 0.35, 1.0]) + ) + + def hypoTokens(self, hypo, tokens): + return self.tensorEqual(hypo["tokens"], torch.LongTensor(tokens)) + + def hypoScore(self, hypo, pos_probs, normalized=True, lenpen=1.0): + pos_scores = torch.FloatTensor(pos_probs).log() + if not self.almostEqual(hypo["positional_scores"], pos_scores): + return False + if pos_scores.numel() != hypo["tokens"].numel(): + return False + score = pos_scores.sum() + if normalized: + score /= pos_scores.numel() ** lenpen + return abs(score - hypo["score"]) < 1e-6 + + def almostEqual(self, t1, t2): + return t1.size() == t2.size() and (t1 - t2).abs().max() < 1e-4 + + def tensorEqual(self, t1, t2): + return t1.size() == t2.size() and t1.ne(t2).long().sum() == 0 + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_sequence_scorer.py b/fairseq-tools/fairseq/tests/test_sequence_scorer.py new file mode 100644 index 00000000..42f9447b --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_sequence_scorer.py @@ -0,0 +1,120 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import unittest + +import tests.utils as test_utils +import torch +from fairseq.sequence_scorer import SequenceScorer + + +class TestSequenceScorer(unittest.TestCase): + def test_sequence_scorer(self): + # construct dummy dictionary + d = test_utils.dummy_dictionary(vocab_size=2) + self.assertEqual(d.pad(), 1) + self.assertEqual(d.eos(), 2) + self.assertEqual(d.unk(), 3) + eos = d.eos() + w1 = 4 + w2 = 5 + + # construct dataloader + data = [ + { + "source": torch.LongTensor([w1, w2, eos]), + "target": torch.LongTensor([w1, w2, w1, eos]), + }, + { + "source": torch.LongTensor([w2, eos]), + "target": torch.LongTensor([w2, w1, eos]), + }, + { + "source": torch.LongTensor([w2, eos]), + "target": torch.LongTensor([w2, eos]), + }, + ] + data_itr = test_utils.dummy_dataloader(data) + + # specify expected output probabilities + args = argparse.Namespace() + unk = 0.0 + args.beam_probs = [ + # step 0: + torch.FloatTensor( + [ + # eos w1 w2 + [0.0, unk, 0.6, 0.4], # sentence 1 + [0.0, unk, 0.4, 0.6], # sentence 2 + [0.0, unk, 0.7, 0.3], # sentence 3 + ] + ), + # step 1: + torch.FloatTensor( + [ + # eos w1 w2 + [0.0, unk, 0.2, 0.7], # sentence 1 + [0.0, unk, 0.8, 0.2], # sentence 2 + [0.7, unk, 0.1, 0.2], # sentence 3 + ] + ), + # step 2: + torch.FloatTensor( + [ + # eos w1 w2 + [0.10, unk, 0.50, 0.4], # sentence 1 + [0.15, unk, 0.15, 0.7], # sentence 2 + [0.00, unk, 0.00, 0.0], # sentence 3 + ] + ), + # step 3: + torch.FloatTensor( + [ + # eos w1 w2 + [0.9, unk, 0.05, 0.05], # sentence 1 + [0.0, unk, 0.00, 0.0], # sentence 2 + [0.0, unk, 0.00, 0.0], # sentence 3 + ] + ), + ] + expected_scores = [ + [0.6, 0.7, 0.5, 0.9], # sentence 1 + [0.6, 0.8, 0.15], # sentence 2 + [0.3, 0.7], # sentence 3 + ] + + task = test_utils.TestTranslationTask.setup_task(args, d, d) + model = task.build_model(args) + scorer = SequenceScorer(task.target_dictionary) + for sample in data_itr: + hypos = task.inference_step(scorer, [model], sample) + for id, hypos_id in zip(sample["id"].tolist(), hypos): + self.assertHypoTokens(hypos_id[0], data[id]["target"]) + self.assertHypoScore(hypos_id[0], expected_scores[id]) + + def assertHypoTokens(self, hypo, tokens): + self.assertTensorEqual(hypo["tokens"], torch.LongTensor(tokens)) + + def assertHypoScore(self, hypo, pos_probs, normalized=True, lenpen=1.0): + pos_scores = torch.FloatTensor(pos_probs).log() + self.assertAlmostEqual(hypo["positional_scores"], pos_scores) + self.assertEqual(pos_scores.numel(), hypo["tokens"].numel()) + score = pos_scores.sum() + if normalized: + score /= pos_scores.numel() ** lenpen + self.assertLess(abs(score - hypo["score"]), 1e-6) + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess((t1 - t2).abs().max(), 1e-4) + + def assertTensorEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertEqual(t1.ne(t2).long().sum(), 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_sparse_multihead_attention.py b/fairseq-tools/fairseq/tests/test_sparse_multihead_attention.py new file mode 100644 index 00000000..3e32b25a --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_sparse_multihead_attention.py @@ -0,0 +1,114 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +from fairseq.modules.sparse_multihead_attention import SparseMultiheadAttention + + +class TestSparseMultiheadAttention(unittest.TestCase): + def test_sparse_multihead_attention(self): + attn_weights = torch.randn(1, 8, 8) + bidirectional_sparse_mask = torch.tensor( + [ + [0, 0, 0, 0, 0, float("-inf"), float("-inf"), 0], + [0, 0, 0, 0, 0, float("-inf"), float("-inf"), 0], + [0, 0, 0, 0, 0, float("-inf"), float("-inf"), 0], + [0, 0, 0, 0, 0, float("-inf"), float("-inf"), 0], + [float("-inf"), float("-inf"), float("-inf"), 0, 0, 0, 0, 0], + [float("-inf"), float("-inf"), float("-inf"), 0, 0, 0, 0, 0], + [float("-inf"), float("-inf"), float("-inf"), 0, 0, 0, 0, 0], + [float("-inf"), float("-inf"), float("-inf"), 0, 0, 0, 0, 0], + ] + ) + + bidirectional_attention = SparseMultiheadAttention( + 16, 1, stride=4, expressivity=1, is_bidirectional=True + ) + bidirectional_attention_sparse_mask = ( + bidirectional_attention.buffered_sparse_mask(attn_weights, 8, 8) + ) + torch.all( + torch.eq(bidirectional_attention_sparse_mask, bidirectional_sparse_mask) + ) + + sparse_mask = torch.tensor( + [ + [ + 0, + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + ], + [ + 0, + 0, + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + ], + [ + 0, + 0, + 0, + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + ], + [ + 0, + 0, + 0, + 0, + float("-inf"), + float("-inf"), + float("-inf"), + float("-inf"), + ], + [0, 0, 0, 0, 0, float("-inf"), float("-inf"), float("-inf")], + [ + float("-inf"), + float("-inf"), + float("-inf"), + 0, + 0, + 0, + float("-inf"), + float("-inf"), + ], + [ + float("-inf"), + float("-inf"), + float("-inf"), + 0, + 0, + 0, + 0, + float("-inf"), + ], + [float("-inf"), float("-inf"), float("-inf"), 0, 0, 0, 0, 0], + ] + ) + + attention = SparseMultiheadAttention( + 16, 1, stride=4, expressivity=1, is_bidirectional=False + ) + attention_sparse_mask = attention.buffered_sparse_mask(attn_weights, 8, 8) + + torch.all(torch.eq(attention_sparse_mask, sparse_mask)) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_token_block_dataset.py b/fairseq-tools/fairseq/tests/test_token_block_dataset.py new file mode 100644 index 00000000..ea315b4e --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_token_block_dataset.py @@ -0,0 +1,79 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import tests.utils as test_utils +import torch +from fairseq.data import TokenBlockDataset + + +class TestTokenBlockDataset(unittest.TestCase): + def _build_dataset(self, data, **kwargs): + sizes = [len(x) for x in data] + underlying_ds = test_utils.TestDataset(data) + return TokenBlockDataset(underlying_ds, sizes, **kwargs) + + def test_eos_break_mode(self): + data = [ + torch.tensor([5, 4, 3, 2, 1], dtype=torch.long), + torch.tensor([1], dtype=torch.long), + torch.tensor([8, 7, 6, 1], dtype=torch.long), + ] + ds = self._build_dataset(data, block_size=None, pad=0, eos=1, break_mode="eos") + self.assertEqual(ds[0].tolist(), [5, 4, 3, 2, 1]) + self.assertEqual(ds[1].tolist(), [1]) + self.assertEqual(ds[2].tolist(), [8, 7, 6, 1]) + + data = [ + torch.tensor([5, 4, 3, 2, 1], dtype=torch.long), + torch.tensor([8, 7, 6, 1], dtype=torch.long), + torch.tensor([1], dtype=torch.long), + ] + ds = self._build_dataset(data, block_size=None, pad=0, eos=1, break_mode="eos") + self.assertEqual(ds[0].tolist(), [5, 4, 3, 2, 1]) + self.assertEqual(ds[1].tolist(), [8, 7, 6, 1]) + self.assertEqual(ds[2].tolist(), [1]) + + def test_block_break_mode(self): + data = [ + torch.tensor([5, 4, 3, 2, 1], dtype=torch.long), + torch.tensor([8, 7, 6, 1], dtype=torch.long), + torch.tensor([9, 1], dtype=torch.long), + ] + ds = self._build_dataset(data, block_size=3, pad=0, eos=1, break_mode="none") + self.assertEqual(ds[0].tolist(), [5, 4, 3]) + self.assertEqual(ds[1].tolist(), [2, 1, 8]) + self.assertEqual(ds[2].tolist(), [7, 6, 1]) + self.assertEqual(ds[3].tolist(), [9, 1]) + + def test_complete_break_mode(self): + data = [ + torch.tensor([5, 4, 3, 2, 1], dtype=torch.long), + torch.tensor([8, 7, 6, 1], dtype=torch.long), + torch.tensor([9, 1], dtype=torch.long), + ] + ds = self._build_dataset( + data, block_size=6, pad=0, eos=1, break_mode="complete" + ) + self.assertEqual(ds[0].tolist(), [5, 4, 3, 2, 1]) + self.assertEqual(ds[1].tolist(), [8, 7, 6, 1, 9, 1]) + + data = [ + torch.tensor([4, 3, 2, 1], dtype=torch.long), + torch.tensor([5, 1], dtype=torch.long), + torch.tensor([1], dtype=torch.long), + torch.tensor([6, 1], dtype=torch.long), + ] + ds = self._build_dataset( + data, block_size=3, pad=0, eos=1, break_mode="complete" + ) + self.assertEqual(ds[0].tolist(), [4, 3, 2, 1]) + self.assertEqual(ds[1].tolist(), [5, 1, 1]) + self.assertEqual(ds[2].tolist(), [6, 1]) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_train.py b/fairseq-tools/fairseq/tests/test_train.py new file mode 100644 index 00000000..1b7e027c --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_train.py @@ -0,0 +1,228 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import contextlib +import logging +import unittest +from io import StringIO +from unittest.mock import MagicMock, patch + +import torch +from fairseq import checkpoint_utils, data + + +def mock_trainer(epoch, num_updates, iterations_in_epoch): + trainer = MagicMock() + trainer.load_checkpoint.return_value = { + "train_iterator": { + "epoch": epoch, + "iterations_in_epoch": iterations_in_epoch, + "shuffle": False, + }, + } + trainer.get_num_updates.return_value = num_updates + return trainer + + +def mock_dict(): + d = MagicMock() + d.pad.return_value = 1 + d.eos.return_value = 2 + d.unk.return_value = 3 + return d + + +def get_trainer_and_epoch_itr(epoch, epoch_size, num_updates, iterations_in_epoch): + tokens = torch.LongTensor(list(range(epoch_size))).view(1, -1) + tokens_ds = data.TokenBlockDataset( + tokens, + sizes=[tokens.size(-1)], + block_size=1, + pad=0, + eos=1, + include_targets=False, + ) + trainer = mock_trainer(epoch, num_updates, iterations_in_epoch) + dataset = data.LanguagePairDataset( + tokens_ds, tokens_ds.sizes, mock_dict(), shuffle=False + ) + epoch_itr = data.EpochBatchIterator( + dataset=dataset, + collate_fn=dataset.collater, + batch_sampler=[[i] for i in range(epoch_size)], + ) + return trainer, epoch_itr + + +def get_mock_args(finetune_from_model=None): + args_mock = MagicMock() + args_mock.optimizer_overrides = "{}" + args_mock.reset_dataloader = False + args_mock.reset_meters = False + args_mock.reset_optimizer = False + args_mock.reset_lr_scheduler = False + args_mock.finetune_from_model = finetune_from_model + args_mock.model_parallel_size = 1 + return args_mock + + +class TestLoadCheckpoint(unittest.TestCase): + def setUp(self): + self.args_mock = get_mock_args() + self.patches = { + "os.makedirs": MagicMock(), + "os.path.join": MagicMock(), + "os.path.isfile": MagicMock(return_value=True), + "os.path.isabs": MagicMock(return_value=False), + "fairseq.file_io.PathManager.exists": MagicMock(return_value=False), + } + self.applied_patches = [patch(p, d) for p, d in self.patches.items()] + [p.start() for p in self.applied_patches] + logging.disable(logging.CRITICAL) + + def tearDown(self): + patch.stopall() + logging.disable(logging.NOTSET) + + def test_load_partial_checkpoint(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(2, 150, 200, 50) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + + _, epoch_itr = checkpoint_utils.load_checkpoint(self.args_mock, trainer) + + self.assertEqual(epoch_itr.epoch, 2) + self.assertEqual(epoch_itr.iterations_in_epoch, 50) + + itr = epoch_itr.next_epoch_itr(shuffle=False) + self.assertEqual(epoch_itr.epoch, 2) + self.assertEqual(epoch_itr.iterations_in_epoch, 50) + + self.assertEqual(next(itr)["net_input"]["src_tokens"][0].item(), 50) + self.assertEqual(epoch_itr.iterations_in_epoch, 51) + + for _ in range(150 - 52): + next(itr) + self.assertEqual(epoch_itr.iterations_in_epoch, 149) + self.assertTrue(itr.has_next()) + next(itr) + self.assertFalse(itr.has_next()) + + itr = epoch_itr.next_epoch_itr(shuffle=False) + self.assertTrue(itr.has_next()) + self.assertEqual(epoch_itr.epoch, 3) + self.assertEqual(epoch_itr.iterations_in_epoch, 0) + + def test_load_full_checkpoint(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(2, 150, 300, 150) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + + _, epoch_itr = checkpoint_utils.load_checkpoint(self.args_mock, trainer) + itr = epoch_itr.next_epoch_itr(shuffle=False) + + self.assertEqual(epoch_itr.epoch, 3) + self.assertEqual(epoch_itr.iterations_in_epoch, 0) + self.assertEqual(next(itr)["net_input"]["src_tokens"][0].item(), 0) + + def test_load_no_checkpoint(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(1, 150, 0, 0) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + self.patches["os.path.isfile"].return_value = False + + _, epoch_itr = checkpoint_utils.load_checkpoint(self.args_mock, trainer) + itr = epoch_itr.next_epoch_itr(shuffle=False) + + self.assertEqual(epoch_itr.epoch, 1) + self.assertEqual(epoch_itr.iterations_in_epoch, 0) + self.assertEqual(next(itr)["net_input"]["src_tokens"][0].item(), 0) + + def test_finetune_from_model_args_conflict(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(1, 150, 0, 0) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + + for arg in [ + "reset_optimizer", + "reset_lr_scheduler", + "reset_meters", + "reset_dataloader", + ]: + with self.subTest(arg=arg): + args_mock = get_mock_args("/temp/checkpoint_pretrained.pt") + setattr(args_mock, arg, True) + with self.assertRaises(Exception) as context: + _, _ = checkpoint_utils.load_checkpoint(args_mock, trainer) + + self.assertTrue( + "--finetune-from-model can not be set together with either --reset-optimizer" + " or reset_lr_scheduler or reset_meters or reset_dataloader" + in str(context.exception) + ) + + def test_finetune_from_model(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(1, 150, 0, 0) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + from_model_path = "/temp/checkpoint_pretrained.pt" + args_mock = get_mock_args(from_model_path) + args_mock.restore_file = "checkpoint_last.pt" + + def mock_finetune_exist(path): + if path == from_model_path: + return True + else: + return False + + self.patches[ + "fairseq.file_io.PathManager.exists" + ].side_effect = mock_finetune_exist + _, _ = checkpoint_utils.load_checkpoint(args_mock, trainer) + ( + checkpoint_path, + reset_optimizer, + reset_lr_scheduler, + optimizer_overrides, + ) = trainer.load_checkpoint.call_args[0] + reset_meters = trainer.load_checkpoint.call_args[1]["reset_meters"] + self.assertTrue(reset_optimizer) + self.assertTrue(reset_lr_scheduler) + self.assertTrue(reset_meters) + + def test_finetune_from_model_resume(self): + with contextlib.redirect_stdout(StringIO()): + trainer, epoch_itr = get_trainer_and_epoch_itr(1, 150, 0, 0) + trainer.get_train_iterator = MagicMock(return_value=epoch_itr) + from_model_path = "/temp/checkpoint_pretrained.pt" + args_mock = get_mock_args(from_model_path) + args_mock.restore_file = "checkpoint_last.pt" + + # launch second time + # both restore_file=checkpoint_last.pt and finetune_from_model are set + def mock_finetune_exist(path): + if path == from_model_path or path.endsWith("checkpoint_last.pt"): + return True + else: + return False + + self.patches[ + "fairseq.file_io.PathManager.exists" + ].side_effect = mock_finetune_exist + _, _ = checkpoint_utils.load_checkpoint(args_mock, trainer) + ( + checkpoint_path, + reset_optimizer, + reset_lr_scheduler, + optimizer_overrides, + ) = trainer.load_checkpoint.call_args[0] + reset_meters = trainer.load_checkpoint.call_args[1]["reset_meters"] + self.assertFalse(reset_optimizer) + self.assertFalse(reset_lr_scheduler) + self.assertFalse(reset_meters) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/test_utils.py b/fairseq-tools/fairseq/tests/test_utils.py new file mode 100644 index 00000000..79195903 --- /dev/null +++ b/fairseq-tools/fairseq/tests/test_utils.py @@ -0,0 +1,114 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +import torch +from fairseq import utils + + +class TestUtils(unittest.TestCase): + def test_convert_padding_direction(self): + pad = 1 + left_pad = torch.LongTensor( + [ + [2, 3, 4, 5, 6], + [1, 7, 8, 9, 10], + [1, 1, 1, 11, 12], + ] + ) + right_pad = torch.LongTensor( + [ + [2, 3, 4, 5, 6], + [7, 8, 9, 10, 1], + [11, 12, 1, 1, 1], + ] + ) + + self.assertAlmostEqual( + right_pad, + utils.convert_padding_direction( + left_pad, + pad, + left_to_right=True, + ), + ) + self.assertAlmostEqual( + left_pad, + utils.convert_padding_direction( + right_pad, + pad, + right_to_left=True, + ), + ) + + def test_make_positions(self): + pad = 1 + left_pad_input = torch.LongTensor( + [ + [9, 9, 9, 9, 9], + [1, 9, 9, 9, 9], + [1, 1, 1, 9, 9], + ] + ) + left_pad_output = torch.LongTensor( + [ + [2, 3, 4, 5, 6], + [1, 2, 3, 4, 5], + [1, 1, 1, 2, 3], + ] + ) + right_pad_input = torch.LongTensor( + [ + [9, 9, 9, 9, 9], + [9, 9, 9, 9, 1], + [9, 9, 1, 1, 1], + ] + ) + right_pad_output = torch.LongTensor( + [ + [2, 3, 4, 5, 6], + [2, 3, 4, 5, 1], + [2, 3, 1, 1, 1], + ] + ) + + self.assertAlmostEqual( + left_pad_output, + utils.make_positions(left_pad_input, pad), + ) + self.assertAlmostEqual( + right_pad_output, + utils.make_positions(right_pad_input, pad), + ) + + def test_clip_grad_norm_(self): + params = torch.nn.Parameter(torch.zeros(5)).requires_grad_(False) + grad_norm = utils.clip_grad_norm_(params, 1.0) + self.assertTrue(torch.is_tensor(grad_norm)) + self.assertEqual(grad_norm, 0.0) + + params = [torch.nn.Parameter(torch.zeros(5)) for i in range(3)] + for p in params: + p.grad = torch.full((5,), fill_value=2.0) + grad_norm = utils.clip_grad_norm_(params, 1.0) + exp_grad_norm = torch.full((15,), fill_value=2.0).norm() + self.assertTrue(torch.is_tensor(grad_norm)) + self.assertEqual(grad_norm, exp_grad_norm) + + grad_norm = utils.clip_grad_norm_(params, 1.0) + self.assertAlmostEqual(grad_norm, torch.tensor(1.0)) + + def test_resolve_max_positions_with_tuple(self): + resolved = utils.resolve_max_positions(None, (2000, 100, 2000), 12000) + self.assertEqual(resolved, (2000, 100, 2000)) + + def assertAlmostEqual(self, t1, t2): + self.assertEqual(t1.size(), t2.size(), "size mismatch") + self.assertLess(utils.item((t1 - t2).abs().max()), 1e-4) + + +if __name__ == "__main__": + unittest.main() diff --git a/fairseq-tools/fairseq/tests/utils.py b/fairseq-tools/fairseq/tests/utils.py new file mode 100644 index 00000000..91feca6b --- /dev/null +++ b/fairseq-tools/fairseq/tests/utils.py @@ -0,0 +1,608 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import argparse +import os +import random +import sys +from io import StringIO + +import torch +import torch.nn.functional as F +from fairseq import options, utils +from fairseq.data import Dictionary +from fairseq.data.language_pair_dataset import collate +from fairseq.models import ( + FairseqEncoder, + FairseqEncoderDecoderModel, + FairseqIncrementalDecoder, +) +from fairseq.models.fairseq_encoder import EncoderOut +from fairseq.tasks import FairseqTask, LegacyFairseqTask +from fairseq_cli import generate, interactive, preprocess, train, validate + + +def dummy_dictionary(vocab_size, prefix="token_"): + d = Dictionary() + for i in range(vocab_size): + token = prefix + str(i) + d.add_symbol(token) + d.finalize(padding_factor=1) # don't add extra padding symbols + return d + + +def dummy_dataloader( + samples, + padding_idx=1, + eos_idx=2, + batch_size=None, +): + if batch_size is None: + batch_size = len(samples) + + # add any missing data to samples + for i, sample in enumerate(samples): + if "id" not in sample: + sample["id"] = i + + # create dataloader + dataset = TestDataset(samples) + dataloader = torch.utils.data.DataLoader( + dataset, + batch_size=batch_size, + collate_fn=(lambda samples: collate(samples, padding_idx, eos_idx)), + ) + return iter(dataloader) + + +def sequence_generator_setup(): + # construct dummy dictionary + d = dummy_dictionary(vocab_size=2) + + eos = d.eos() + w1 = 4 + w2 = 5 + + # construct source data + src_tokens = torch.LongTensor([[w1, w2, eos], [w1, w2, eos]]) + src_lengths = torch.LongTensor([2, 2]) + + args = argparse.Namespace() + unk = 0.0 + args.beam_probs = [ + # step 0: + torch.FloatTensor( + [ + # eos w1 w2 + # sentence 1: + [0.0, unk, 0.9, 0.1], # beam 1 + [0.0, unk, 0.9, 0.1], # beam 2 + # sentence 2: + [0.0, unk, 0.7, 0.3], + [0.0, unk, 0.7, 0.3], + ] + ), + # step 1: + torch.FloatTensor( + [ + # eos w1 w2 prefix + # sentence 1: + [1.0, unk, 0.0, 0.0], # w1: 0.9 (emit: w1 <eos>: 0.9*1.0) + [0.0, unk, 0.9, 0.1], # w2: 0.1 + # sentence 2: + [0.25, unk, 0.35, 0.4], # w1: 0.7 (don't emit: w1 <eos>: 0.7*0.25) + [0.00, unk, 0.10, 0.9], # w2: 0.3 + ] + ), + # step 2: + torch.FloatTensor( + [ + # eos w1 w2 prefix + # sentence 1: + [0.0, unk, 0.1, 0.9], # w2 w1: 0.1*0.9 + [ + 0.6, + unk, + 0.2, + 0.2, + ], # w2 w2: 0.1*0.1 (emit: w2 w2 <eos>: 0.1*0.1*0.6) + # sentence 2: + [ + 0.60, + unk, + 0.4, + 0.00, + ], # w1 w2: 0.7*0.4 (emit: w1 w2 <eos>: 0.7*0.4*0.6) + [0.01, unk, 0.0, 0.99], # w2 w2: 0.3*0.9 + ] + ), + # step 3: + torch.FloatTensor( + [ + # eos w1 w2 prefix + # sentence 1: + [ + 1.0, + unk, + 0.0, + 0.0, + ], # w2 w1 w2: 0.1*0.9*0.9 (emit: w2 w1 w2 <eos>: 0.1*0.9*0.9*1.0) + [ + 1.0, + unk, + 0.0, + 0.0, + ], # w2 w1 w1: 0.1*0.9*0.1 (emit: w2 w1 w1 <eos>: 0.1*0.9*0.1*1.0) + # sentence 2: + [ + 0.1, + unk, + 0.5, + 0.4, + ], # w2 w2 w2: 0.3*0.9*0.99 (emit: w2 w2 w2 <eos>: 0.3*0.9*0.99*0.1) + [ + 1.0, + unk, + 0.0, + 0.0, + ], # w1 w2 w1: 0.7*0.4*0.4 (emit: w1 w2 w1 <eos>: 0.7*0.4*0.4*1.0) + ] + ), + ] + + task = TestTranslationTask.setup_task(args, d, d) + model = task.build_model(args) + tgt_dict = task.target_dictionary + + return tgt_dict, w1, w2, src_tokens, src_lengths, model + + +def create_dummy_data(data_dir, num_examples=100, maxlen=20, alignment=False): + def _create_dummy_data(filename): + data = torch.rand(num_examples * maxlen) + data = 97 + torch.floor(26 * data).int() + with open(os.path.join(data_dir, filename), "w") as h: + offset = 0 + for _ in range(num_examples): + ex_len = random.randint(1, maxlen) + ex_str = " ".join(map(chr, data[offset : offset + ex_len])) + print(ex_str, file=h) + offset += ex_len + + def _create_dummy_alignment_data(filename_src, filename_tgt, filename): + with open(os.path.join(data_dir, filename_src), "r") as src_f, open( + os.path.join(data_dir, filename_tgt), "r" + ) as tgt_f, open(os.path.join(data_dir, filename), "w") as h: + for src, tgt in zip(src_f, tgt_f): + src_len = len(src.split()) + tgt_len = len(tgt.split()) + avg_len = (src_len + tgt_len) // 2 + num_alignments = random.randint(avg_len // 2, 2 * avg_len) + src_indices = torch.floor(torch.rand(num_alignments) * src_len).int() + tgt_indices = torch.floor(torch.rand(num_alignments) * tgt_len).int() + ex_str = " ".join( + [ + "{}-{}".format(src, tgt) + for src, tgt in zip(src_indices, tgt_indices) + ] + ) + print(ex_str, file=h) + + _create_dummy_data("train.in") + _create_dummy_data("train.out") + _create_dummy_data("valid.in") + _create_dummy_data("valid.out") + _create_dummy_data("test.in") + _create_dummy_data("test.out") + + if alignment: + _create_dummy_alignment_data("train.in", "train.out", "train.align") + _create_dummy_alignment_data("valid.in", "valid.out", "valid.align") + _create_dummy_alignment_data("test.in", "test.out", "test.align") + + +def preprocess_lm_data(data_dir): + preprocess_parser = options.get_preprocessing_parser() + preprocess_args = preprocess_parser.parse_args( + [ + "--only-source", + "--trainpref", + os.path.join(data_dir, "train.out"), + "--validpref", + os.path.join(data_dir, "valid.out"), + "--testpref", + os.path.join(data_dir, "test.out"), + "--destdir", + data_dir, + ] + ) + preprocess.main(preprocess_args) + + +def preprocess_translation_data(data_dir, extra_flags=None): + preprocess_parser = options.get_preprocessing_parser() + preprocess_args = preprocess_parser.parse_args( + [ + "--source-lang", + "in", + "--target-lang", + "out", + "--trainpref", + os.path.join(data_dir, "train"), + "--validpref", + os.path.join(data_dir, "valid"), + "--testpref", + os.path.join(data_dir, "test"), + "--thresholdtgt", + "0", + "--thresholdsrc", + "0", + "--destdir", + data_dir, + ] + + (extra_flags or []), + ) + preprocess.main(preprocess_args) + + +def preprocess_summarization_data(data_dir, extra_flags=None): + preprocess_parser = options.get_preprocessing_parser() + preprocess_args = preprocess_parser.parse_args( + [ + "--source-lang", + "in", + "--target-lang", + "out", + "--trainpref", + os.path.join(data_dir, "train"), + "--validpref", + os.path.join(data_dir, "valid"), + "--testpref", + os.path.join(data_dir, "test"), + "--thresholdtgt", + "0", + "--thresholdsrc", + "0", + "--joined-dictionary", + "--destdir", + data_dir, + ] + + (extra_flags or []), + ) + preprocess.main(preprocess_args) + + +def train_translation_model( + data_dir, + arch, + extra_flags=None, + task="translation", + run_validation=False, + lang_flags=None, + extra_valid_flags=None, +): + if lang_flags is None: + lang_flags = [ + "--source-lang", + "in", + "--target-lang", + "out", + ] + train_parser = options.get_training_parser() + train_args = options.parse_args_and_arch( + train_parser, + [ + "--task", + task, + data_dir, + "--save-dir", + data_dir, + "--arch", + arch, + "--optimizer", + "nag", + "--lr", + "0.05", + "--max-tokens", + "500", + "--max-epoch", + "1", + "--no-progress-bar", + "--distributed-world-size", + "1", + "--num-workers", + "0", + ] + + lang_flags + + (extra_flags or []), + ) + train.main(train_args) + + if run_validation: + # test validation + validate_parser = options.get_validation_parser() + validate_args = options.parse_args_and_arch( + validate_parser, + [ + "--task", + task, + data_dir, + "--path", + os.path.join(data_dir, "checkpoint_last.pt"), + "--valid-subset", + "valid", + "--max-tokens", + "500", + "--no-progress-bar", + "--num-workers", + "0", + ] + + lang_flags + + (extra_valid_flags or []), + ) + validate.main(validate_args) + + +def generate_main(data_dir, extra_flags=None): + if extra_flags is None: + extra_flags = [ + "--print-alignment", + ] + generate_parser = options.get_generation_parser() + generate_args = options.parse_args_and_arch( + generate_parser, + [ + data_dir, + "--path", + os.path.join(data_dir, "checkpoint_last.pt"), + "--beam", + "3", + "--batch-size", + "64", + "--max-len-b", + "5", + "--gen-subset", + "valid", + "--no-progress-bar", + "--num-workers", + "0", + ] + + (extra_flags or []), + ) + + # evaluate model in batch mode + generate.main(generate_args) + + # evaluate model interactively + generate_args.buffer_size = 0 + generate_args.input = "-" + generate_args.batch_size = None + orig_stdin = sys.stdin + sys.stdin = StringIO("h e l l o\n") + interactive.main(generate_args) + sys.stdin = orig_stdin + + +class TestDataset(torch.utils.data.Dataset): + def __init__(self, data): + super().__init__() + self.data = data + self.sizes = None + + def __getitem__(self, index): + return self.data[index] + + def __len__(self): + return len(self.data) + + +class TestTranslationTask(LegacyFairseqTask): + def __init__(self, args, src_dict, tgt_dict, model): + super().__init__(args) + self.src_dict = src_dict + self.tgt_dict = tgt_dict + self.model = model + + @classmethod + def setup_task(cls, args, src_dict=None, tgt_dict=None, model=None): + return cls(args, src_dict, tgt_dict, model) + + def build_model(self, args): + return TestModel.build_model(args, self) + + @property + def source_dictionary(self): + return self.src_dict + + @property + def target_dictionary(self): + return self.tgt_dict + + +class TestModel(FairseqEncoderDecoderModel): + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @classmethod + def build_model(cls, args, task): + encoder = TestEncoder(args, task.source_dictionary) + decoder = TestIncrementalDecoder(args, task.target_dictionary) + return cls(encoder, decoder) + + +class TestEncoder(FairseqEncoder): + def __init__(self, args, dictionary): + super().__init__(dictionary) + self.args = args + + def forward(self, src_tokens, src_lengths=None, **kwargs): + return EncoderOut( + encoder_out=src_tokens, + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + def reorder_encoder_out(self, encoder_out, new_order): + return EncoderOut( + encoder_out=encoder_out.encoder_out.index_select(0, new_order), + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + +class TestIncrementalDecoder(FairseqIncrementalDecoder): + def __init__(self, args, dictionary): + super().__init__(dictionary) + assert hasattr(args, "beam_probs") or hasattr(args, "probs") + args.max_decoder_positions = getattr(args, "max_decoder_positions", 100) + self.args = args + + def forward(self, prev_output_tokens, encoder_out=None, incremental_state=None): + if incremental_state is not None: + prev_output_tokens = prev_output_tokens[:, -1:] + bbsz = prev_output_tokens.size(0) + vocab = len(self.dictionary) + src_len = encoder_out.encoder_out.size(1) + tgt_len = prev_output_tokens.size(1) + + # determine number of steps + if incremental_state is not None: + # cache step number + step = utils.get_incremental_state(self, incremental_state, "step") + if step is None: + step = 0 + utils.set_incremental_state(self, incremental_state, "step", step + 1) + steps = [step] + else: + steps = list(range(tgt_len)) + + # define output in terms of raw probs + if hasattr(self.args, "probs"): + assert ( + self.args.probs.dim() == 3 + ), "expected probs to have size bsz*steps*vocab" + probs = self.args.probs.index_select(1, torch.LongTensor(steps)) + else: + probs = torch.FloatTensor(bbsz, len(steps), vocab).zero_() + for i, step in enumerate(steps): + # args.beam_probs gives the probability for every vocab element, + # starting with eos, then unknown, and then the rest of the vocab + if step < len(self.args.beam_probs): + probs[:, i, self.dictionary.eos() :] = self.args.beam_probs[step] + else: + probs[:, i, self.dictionary.eos()] = 1.0 + + # random attention + attn = torch.rand(bbsz, tgt_len, src_len) + + dev = prev_output_tokens.device + return probs.to(dev), {"attn": [attn.to(dev)]} + + def get_normalized_probs(self, net_output, log_probs, _): + # the decoder returns probabilities directly + probs = net_output[0] + if log_probs: + return probs.log() + else: + return probs + + def max_positions(self): + return self.args.max_decoder_positions + + +class TestReshapingEncoder(FairseqEncoder): + def __init__(self, args, dictionary): + super().__init__(dictionary) + self.args = args + + def forward(self, src_tokens, src_lengths=None, **kwargs): + b_sz, t_sz = src_tokens.shape + padding_needed = t_sz % 2 + x = src_tokens + if padding_needed > 0: + padding_needed = 2 - padding_needed + x = F.pad(x, (0, padding_needed)) + + return EncoderOut( + encoder_out=x.view(b_sz, -1, 2), + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + def reorder_encoder_out(self, encoder_out, new_order): + return EncoderOut( + encoder_out=encoder_out.encoder_out.index_select(0, new_order), + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + +class TestReshapingModel(FairseqEncoderDecoderModel): + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @classmethod + def build_model(cls, args, task): + encoder = TestReshapingEncoder(args, task.source_dictionary) + decoder = TestIncrementalDecoder(args, task.target_dictionary) + return cls(encoder, decoder) + + +class TestAdditionalInputEncoder(FairseqEncoder): + def __init__(self, args, dictionary): + super().__init__(dictionary) + self.args = args + + def forward(self, src_tokens, src_lengths=None, **kwargs): + assert "fancy_other_input" in kwargs + assert kwargs["fancy_other_input"] is not None + return EncoderOut( + encoder_out=src_tokens, + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + def reorder_encoder_out(self, encoder_out, new_order): + return EncoderOut( + encoder_out=encoder_out.encoder_out.index_select(0, new_order), + encoder_padding_mask=None, + encoder_embedding=None, + encoder_states=None, + src_tokens=None, + src_lengths=None, + ) + + +class TestAdditionalInputModel(FairseqEncoderDecoderModel): + def __init__(self, encoder, decoder): + super().__init__(encoder, decoder) + + @classmethod + def build_model(cls, args, task): + encoder = TestAdditionalInputEncoder(args, task.source_dictionary) + decoder = TestIncrementalDecoder(args, task.target_dictionary) + return cls(encoder, decoder) + + def forward(self, src_tokens, src_lengths, prev_output_tokens, **kwargs): + encoder_out = self.encoder(src_tokens, src_lengths=src_lengths, **kwargs) + decoder_out = self.decoder( + prev_output_tokens, encoder_out=encoder_out, **kwargs + ) + return decoder_out diff --git a/fairseq-tools/fairseq/train.py b/fairseq-tools/fairseq/train.py new file mode 100644 index 00000000..321de3d9 --- /dev/null +++ b/fairseq-tools/fairseq/train.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 -u +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. +""" +Legacy entry point. Use fairseq_cli/train.py or fairseq-train instead. +""" + +from fairseq_cli.train import cli_main + + +if __name__ == "__main__": + cli_main() diff --git a/gnn/GCN/README.md b/gnn/GCN/README.md old mode 100755 new mode 100644 diff --git a/gnn/GCN/ascend310_infer/CMakeLists.txt b/gnn/GCN/ascend310_infer/CMakeLists.txt old mode 100755 new mode 100644 diff --git a/gnn/GCN/ascend310_infer/build.sh b/gnn/GCN/ascend310_infer/build.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/ascend310_infer/inc/utils.h b/gnn/GCN/ascend310_infer/inc/utils.h old mode 100755 new mode 100644 diff --git a/gnn/GCN/ascend310_infer/src/main.cc b/gnn/GCN/ascend310_infer/src/main.cc old mode 100755 new mode 100644 diff --git a/gnn/GCN/ascend310_infer/src/utils.cc b/gnn/GCN/ascend310_infer/src/utils.cc old mode 100755 new mode 100644 diff --git a/gnn/GCN/default_config.yaml b/gnn/GCN/default_config.yaml old mode 100755 new mode 100644 diff --git a/gnn/GCN/eval.py b/gnn/GCN/eval.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/export.py b/gnn/GCN/export.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/mindspore_hub_conf.py b/gnn/GCN/mindspore_hub_conf.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/model_utils/__init__.py b/gnn/GCN/model_utils/__init__.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/model_utils/config.py b/gnn/GCN/model_utils/config.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/model_utils/device_adapter.py b/gnn/GCN/model_utils/device_adapter.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/model_utils/local_adapter.py b/gnn/GCN/model_utils/local_adapter.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/model_utils/moxing_adapter.py b/gnn/GCN/model_utils/moxing_adapter.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/postprocess.py b/gnn/GCN/postprocess.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/preprocess.py b/gnn/GCN/preprocess.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/requirements.txt b/gnn/GCN/requirements.txt old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_distribute_train_gpu.sh b/gnn/GCN/scripts/run_distribute_train_gpu.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_eval_gpu.sh b/gnn/GCN/scripts/run_eval_gpu.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_infer_310.sh b/gnn/GCN/scripts/run_infer_310.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_process_data.sh b/gnn/GCN/scripts/run_process_data.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_train.sh b/gnn/GCN/scripts/run_train.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/run_train_gpu.sh b/gnn/GCN/scripts/run_train_gpu.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/scripts/train_gcn_1p.sh b/gnn/GCN/scripts/train_gcn_1p.sh old mode 100755 new mode 100644 diff --git a/gnn/GCN/src/config.py b/gnn/GCN/src/config.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/src/dataset.py b/gnn/GCN/src/dataset.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/src/eval_callback.py b/gnn/GCN/src/eval_callback.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/src/gcn.py b/gnn/GCN/src/gcn.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/src/metrics.py b/gnn/GCN/src/metrics.py old mode 100755 new mode 100644 diff --git a/gnn/GCN/t-SNE_visualization_on_Cora.gif b/gnn/GCN/t-SNE_visualization_on_Cora.gif old mode 100755 new mode 100644 diff --git a/gnn/GCN/train.py b/gnn/GCN/train.py old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/IMG/multi.png b/multimodal/diffusion/stable-diffusion/training/IMG/multi.png old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/IMG/pokemon.png b/multimodal/diffusion/stable-diffusion/training/IMG/pokemon.png old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/IMG/single.png b/multimodal/diffusion/stable-diffusion/training/IMG/single.png old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/README.md b/multimodal/diffusion/stable-diffusion/training/README.md old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/requirements.txt b/multimodal/diffusion/stable-diffusion/training/requirements.txt old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/test.py b/multimodal/diffusion/stable-diffusion/training/test.py old mode 100755 new mode 100644 diff --git a/multimodal/diffusion/stable-diffusion/training/train_text_to_image.py b/multimodal/diffusion/stable-diffusion/training/train_text_to_image.py old mode 100755 new mode 100644 diff --git a/nlp/cloze_test/glm/pytorch/GLMForMultiTokenCloze/base/data_preprocessing/utils/wordpiece.py b/nlp/cloze_test/glm/pytorch/GLMForMultiTokenCloze/base/data_preprocessing/utils/wordpiece.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/BaseDockerfile b/nlp/dialogue_generation/cpm/pytorch/base/BaseDockerfile old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/bind_pyt.py b/nlp/dialogue_generation/cpm/pytorch/base/bind_pyt.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/cleanup_image_container.sh b/nlp/dialogue_generation/cpm/pytorch/base/cleanup_image_container.sh old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/config/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/config/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/config/_base.py b/nlp/dialogue_generation/cpm/pytorch/base/config/_base.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/config/config_manager.py b/nlp/dialogue_generation/cpm/pytorch/base/config/config_manager.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/config/mutable_params.py b/nlp/dialogue_generation/cpm/pytorch/base/config/mutable_params.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/change_mp.py b/nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/change_mp.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/preprocess_stc_finetune.py b/nlp/dialogue_generation/cpm/pytorch/base/data_preprocessing/preprocess_stc_finetune.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.model b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.model old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.vocab b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/chinese_vocab.vocab old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/vocab.json b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/bpe_3w_new/vocab.json old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/dataloader.py b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/dataloader.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/samplers.py b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/samplers.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/tokenization_gpt2.py b/nlp/dialogue_generation/cpm/pytorch/base/dataloaders/tokenization_gpt2.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/model/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16.py b/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16util.py b/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/fp16util.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/loss_scaler.py b/nlp/dialogue_generation/cpm/pytorch/base/model/fp16/loss_scaler.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/layers/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/model/layers/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/layers/layers.py b/nlp/dialogue_generation/cpm/pytorch/base/model/layers/layers.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/losses/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/model/losses/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/losses/cross_entropy.py b/nlp/dialogue_generation/cpm/pytorch/base/model/losses/cross_entropy.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/models/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/model/models/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/models/checkpoint.py b/nlp/dialogue_generation/cpm/pytorch/base/model/models/checkpoint.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/models/gpt2_modeling.py b/nlp/dialogue_generation/cpm/pytorch/base/model/models/gpt2_modeling.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/model/models/transformer.py b/nlp/dialogue_generation/cpm/pytorch/base/model/models/transformer.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/optimizers/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/optimizers/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/optimizers/factory.py b/nlp/dialogue_generation/cpm/pytorch/base/optimizers/factory.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/prepare.py b/nlp/dialogue_generation/cpm/pytorch/base/prepare.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/requirements.txt b/nlp/dialogue_generation/cpm/pytorch/base/requirements.txt old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/run_pretraining.py b/nlp/dialogue_generation/cpm/pytorch/base/run_pretraining.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/run_training.sh b/nlp/dialogue_generation/cpm/pytorch/base/run_training.sh old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/run_with_docker.sh b/nlp/dialogue_generation/cpm/pytorch/base/run_with_docker.sh old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/schedulers/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/schedulers/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/schedulers/factory.py b/nlp/dialogue_generation/cpm/pytorch/base/schedulers/factory.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/schedulers/learning_rates.py b/nlp/dialogue_generation/cpm/pytorch/base/schedulers/learning_rates.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/setup.py b/nlp/dialogue_generation/cpm/pytorch/base/setup.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/train/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/evaluator.py b/nlp/dialogue_generation/cpm/pytorch/base/train/evaluator.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/event/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/train/event/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/event/base.py b/nlp/dialogue_generation/cpm/pytorch/base/train/event/base.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/event/base_adapter.py b/nlp/dialogue_generation/cpm/pytorch/base/train/event/base_adapter.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/event/compose.py b/nlp/dialogue_generation/cpm/pytorch/base/train/event/compose.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/event/log.py b/nlp/dialogue_generation/cpm/pytorch/base/train/event/log.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/metrics.py b/nlp/dialogue_generation/cpm/pytorch/base/train/metrics.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/trainer.py b/nlp/dialogue_generation/cpm/pytorch/base/train/trainer.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/train/training_state.py b/nlp/dialogue_generation/cpm/pytorch/base/train/training_state.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/utils/__init__.py b/nlp/dialogue_generation/cpm/pytorch/base/utils/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/utils/check.py b/nlp/dialogue_generation/cpm/pytorch/base/utils/check.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/utils/dist.py b/nlp/dialogue_generation/cpm/pytorch/base/utils/dist.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/utils/logging.py b/nlp/dialogue_generation/cpm/pytorch/base/utils/logging.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/base/utils/paths.py b/nlp/dialogue_generation/cpm/pytorch/base/utils/paths.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x1.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x1.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x8.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x1x8.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x2x8.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_V100x2x8.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_common.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/config_common.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/converter.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/converter.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/__init__.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/__init__.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/attention.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/attention.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/fast_self_multihead_attn_func.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/fast_self_multihead_attn_func.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/layernorm.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/layernorm.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn_func.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/layers/self_multihead_attn_func.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/optimizers_adam.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/optimizers_adam.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/training_event.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/config/training_event.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/dropout.h b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/dropout.h old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/fast_self_multihead_attn_func.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/fast_self_multihead_attn_func.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/layer_norm.h b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/layer_norm.h old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/philox.h b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/philox.h old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias.cpp b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias.cpp old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias_cuda.cu b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_bias_cuda.cu old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_func.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/self_multihead_attn_func.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/setup.py b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/setup.py old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/softmax.h b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/softmax.h old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/strided_batched_gemm.h b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/csrc/strided_batched_gemm.h old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/packages/files.txt b/nlp/dialogue_generation/cpm/pytorch/iluvatar/cpm/packages/files.txt old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/gen_docker_image.sh b/nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/gen_docker_image.sh old mode 100755 new mode 100644 diff --git a/nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/install.sh b/nlp/dialogue_generation/cpm/pytorch/iluvatar/docker_image/install.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/NOTICE b/nlp/language_model/bert/pytorch/NOTICE old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/bind.sh b/nlp/language_model/bert/pytorch/bind.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/bmm1.py b/nlp/language_model/bert/pytorch/bmm1.py old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/bmm2.py b/nlp/language_model/bert/pytorch/bmm2.py old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/cleanup_scripts/clean.sh b/nlp/language_model/bert/pytorch/cleanup_scripts/clean.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/cleanup_scripts/create_pretraining_data_wrapper.sh b/nlp/language_model/bert/pytorch/cleanup_scripts/create_pretraining_data_wrapper.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/cleanup_scripts/extract_test_set_articles.py b/nlp/language_model/bert/pytorch/cleanup_scripts/extract_test_set_articles.py old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/cleanup_scripts/parallel_create_hdf5.sh b/nlp/language_model/bert/pytorch/cleanup_scripts/parallel_create_hdf5.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/cleanup_scripts/process_wiki.sh b/nlp/language_model/bert/pytorch/cleanup_scripts/process_wiki.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/data_scripts/clean.sh b/nlp/language_model/bert/pytorch/data_scripts/clean.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/data_scripts/create_pretraining_data_wrapper.sh b/nlp/language_model/bert/pytorch/data_scripts/create_pretraining_data_wrapper.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/data_scripts/parallel_create_hdf5.sh b/nlp/language_model/bert/pytorch/data_scripts/parallel_create_hdf5.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/data_scripts/process_wiki.sh b/nlp/language_model/bert/pytorch/data_scripts/process_wiki.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/init.sh b/nlp/language_model/bert/pytorch/init.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/input_preprocessing/clean.sh b/nlp/language_model/bert/pytorch/input_preprocessing/clean.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/input_preprocessing/create_pretraining_data_wrapper.sh b/nlp/language_model/bert/pytorch/input_preprocessing/create_pretraining_data_wrapper.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/input_preprocessing/parallel_create_hdf5.sh b/nlp/language_model/bert/pytorch/input_preprocessing/parallel_create_hdf5.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/input_preprocessing/process_wiki.sh b/nlp/language_model/bert/pytorch/input_preprocessing/process_wiki.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mhalib/mha_funcs.cu b/nlp/language_model/bert/pytorch/mhalib/mha_funcs.cu old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mhalib/setup.py b/nlp/language_model/bert/pytorch/mhalib/setup.py old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/pack_submission.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/pack_submission.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v0.7_training.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v0.7_training.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_hpc.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_hpc.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_training.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.0_training.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.1_training.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v1.1_training.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v2.0_training.sh b/nlp/language_model/bert/pytorch/mlperf-logging/scripts/verify_for_v2.0_training.sh old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/padding.py b/nlp/language_model/bert/pytorch/padding.py old mode 100755 new mode 100644 diff --git a/nlp/language_model/bert/pytorch/softmax.py b/nlp/language_model/bert/pytorch/softmax.py old mode 100755 new mode 100644 diff --git a/nlp/ner/bert/pytorch/run.sh b/nlp/ner/bert/pytorch/run.sh old mode 100755 new mode 100644 diff --git a/nlp/ner/bert/pytorch/run_dist.sh b/nlp/ner/bert/pytorch/run_dist.sh old mode 100755 new mode 100644 diff --git a/nlp/ner/bert/pytorch/run_ner.py b/nlp/ner/bert/pytorch/run_ner.py old mode 100755 new mode 100644 diff --git a/recommendation/collaborative_filtering/ncf/pytorch/download_dataset.sh b/recommendation/collaborative_filtering/ncf/pytorch/download_dataset.sh old mode 100755 new mode 100644 diff --git a/recommendation/collaborative_filtering/ncf/pytorch/ncf_16.py b/recommendation/collaborative_filtering/ncf/pytorch/ncf_16.py old mode 100755 new mode 100644 diff --git a/recommendation/collaborative_filtering/ncf/pytorch/ncf_32.py b/recommendation/collaborative_filtering/ncf/pytorch/ncf_32.py old mode 100755 new mode 100644 diff --git a/recommendation/collaborative_filtering/ncf/pytorch/run_train_fp16.sh b/recommendation/collaborative_filtering/ncf/pytorch/run_train_fp16.sh old mode 100755 new mode 100644 diff --git a/recommendation/collaborative_filtering/ncf/pytorch/run_train_fp32.sh b/recommendation/collaborative_filtering/ncf/pytorch/run_train_fp32.sh old mode 100755 new mode 100644 diff --git a/recommendation/ctr/dlrm/pytorch/scripts/dot_based_interact/run.sh b/recommendation/ctr/dlrm/pytorch/scripts/dot_based_interact/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/README.md b/speech/speech_recognition/conformer/pytorch/README.md old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/conf/train_conformer.yaml b/speech/speech_recognition/conformer/pytorch/conf/train_conformer.yaml old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/local/aishell_data_prep.sh b/speech/speech_recognition/conformer/pytorch/local/aishell_data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/local/aishell_train_lms.sh b/speech/speech_recognition/conformer/pytorch/local/aishell_train_lms.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/local/download_and_untar.sh b/speech/speech_recognition/conformer/pytorch/local/download_and_untar.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/run.sh b/speech/speech_recognition/conformer/pytorch/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/compute-wer.py b/speech/speech_recognition/conformer/pytorch/tools/compute-wer.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/compute_cmvn_stats.py b/speech/speech_recognition/conformer/pytorch/tools/compute_cmvn_stats.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/filter_scp.pl b/speech/speech_recognition/conformer/pytorch/tools/filter_scp.pl old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/make_raw_list.py b/speech/speech_recognition/conformer/pytorch/tools/make_raw_list.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/parse_options.sh b/speech/speech_recognition/conformer/pytorch/tools/parse_options.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/tools/text2token.py b/speech/speech_recognition/conformer/pytorch/tools/text2token.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/wenet/bin/recognize.py b/speech/speech_recognition/conformer/pytorch/wenet/bin/recognize.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/wenet/bin/train.py b/speech/speech_recognition/conformer/pytorch/wenet/bin/train.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/wenet/dataset/dataset.py b/speech/speech_recognition/conformer/pytorch/wenet/dataset/dataset.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/conformer/pytorch/wenet/transformer/convolution.py b/speech/speech_recognition/conformer/pytorch/wenet/transformer/convolution.py old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/install.sh b/speech/speech_recognition/rnnt/pytorch/install.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/requirements.txt b/speech/speech_recognition/rnnt/pytorch/requirements.txt old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/docker/Dockerfile b/speech/speech_recognition/rnnt/pytorch/scripts/docker/Dockerfile old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/docker/build.sh b/speech/speech_recognition/rnnt/pytorch/scripts/docker/build.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/docker/launch.sh b/speech/speech_recognition/rnnt/pytorch/scripts/docker/launch.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/download_librispeech.sh b/speech/speech_recognition/rnnt/pytorch/scripts/download_librispeech.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/inference.sh b/speech/speech_recognition/rnnt/pytorch/scripts/inference.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/preprocess_librispeech.sh b/speech/speech_recognition/rnnt/pytorch/scripts/preprocess_librispeech.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x1.sh b/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x1.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x4.sh b/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x4.sh old mode 100755 new mode 100644 diff --git a/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x8.sh b/speech/speech_recognition/rnnt/pytorch/scripts/train_rnnt_1x8.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/demo.wav b/speech/speech_synthesis/tacotron2/pytorch/demo.wav old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_test_filelist.txt b/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_test_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_train_filelist.txt b/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_train_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_val_filelist.txt b/speech/speech_synthesis/tacotron2/pytorch/filelists/ljs_audio_text_val_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/waveglow/README.md b/speech/speech_synthesis/tacotron2/pytorch/waveglow/README.md old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/waveglow/config.json b/speech/speech_synthesis/tacotron2/pytorch/waveglow/config.json old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/tacotron2/pytorch/waveglow/waveglow_logo.png b/speech/speech_synthesis/tacotron2/pytorch/waveglow/waveglow_logo.png old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/arctic/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/csmsc/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jnas/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsss/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/jsut/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/libritts/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/ljspeech/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/speech_commands/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_multi_spk/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/template_single_spk/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/vctk/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_download.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_download.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_prep.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/local/data_prep.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/run.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/run.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils deleted file mode 120000 index 973afe67..00000000 --- a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils +++ /dev/null @@ -1 +0,0 @@ -../../../utils \ No newline at end of file diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/combine_data.sh new file mode 100644 index 00000000..7ceb1703 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/combine_data.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Combine data direcotries into a single data direcotry + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +if [ $# -lt 2 ]; then + echo "Usage: $0 <dist_dir> <src_dir_1> <src_dir_2> ..." + echo "e.g.: $0 data/all data/spk_1 data/spk_2 data/spk_3" + exit 1 +fi + +set -euo pipefail + +dist_dir=$1 +shift +first_src_dir=$1 + + +[ ! -e "${dist_dir}" ] && mkdir -p "${dist_dir}" + +if [ -e "${first_src_dir}/segments" ]; then + has_segments=true + segments=${dist_dir}/segments + segments_tmp=${dist_dir}/segments.unsorted + [ -e "${segments_tmp}" ] && rm "${segments_tmp}" +else + has_segments=false +fi +scp=${dist_dir}/wav.scp +scp_tmp=${dist_dir}/wav.scp.unsorted +[ -e "${scp_tmp}" ] && rm "${scp_tmp}" + +# concatenate all of wav.scp and segments file +for _ in $(seq 1 ${#}); do + src_dir=$1 + + if "${has_segments}"; then + [ ! -e "${src_dir}/segments" ] && echo "WARN: Not found segments in ${src_dir}. Skipped." >&2 && shift && continue + cat "${src_dir}/segments" >> "${segments_tmp}" + fi + + [ ! -e "${src_dir}/wav.scp" ] && echo "Not found wav.scp in ${src_dir}." >&2 && exit 1; + cat "${src_dir}/wav.scp" >> "${scp_tmp}" + + shift +done + +# sort +sort "${scp_tmp}" > "${scp}" +if "${has_segments}"; then + sort "${segments_tmp}" > "${segments}" +fi +rm "${dist_dir}"/*.unsorted + +echo "Successfully combined data direcotries." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/download_from_google_drive.sh new file mode 100644 index 00000000..844a5595 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/download_from_google_drive.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# Download zip, tar, or tar.gz file from google drive + +# shellcheck disable=SC1091 +. ./path.sh || eixit 1 + +share_url=$1 +download_dir=${2:-"downloads"} +file_ext=${3:-"zip"} + +if [ "$1" = "--help" ] || [ $# -lt 1 ] || [ $# -gt 3 ]; then + echo "Usage: $0 <share-url> [<download_dir> <file_ext>]"; + echo "e.g.: $0 https://drive.google.com/open?id=xxxxxxxxxxxxxx downloads zip" + echo "Options:" + echo " <download_dir>: directory to save downloaded file. (Default=downloads)" + echo " <file_ext>: file extension of the file to be downloaded. (Default=zip)" + exit 1; +fi + +set -euo pipefail + +[ ! -e "${download_dir}" ] && mkdir -p "${download_dir}" +tmp=$(mktemp "${download_dir}/XXXXXXXX.${file_ext}") + +file_id=$(echo "${share_url}" | cut -d"=" -f 2) + +# define decompressor +decompress () { + filename=$1 + decompress_dir=$2 + if echo "${filename}" | grep -q ".zip"; then + unzip "${filename}" -d "${decompress_dir}" + elif echo "${filename}" | grep -q -e ".tar" -e ".tar.gz" -e ".tgz"; then + tar xvzf "${filename}" -C "${decompress_dir}" + else + echo "Unsupported file extension." >&2 && exit 1 + fi +} + +set -e +# Solution from https://github.com/wkentaro/gdown +gdown --id "${file_id}" -O "${tmp}" +decompress "${tmp}" "${download_dir}" + +# remove tmpfiles +rm "${tmp}" +echo "Sucessfully downloaded ${file_ext} file from ${share_url}" diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/make_subset_data.sh new file mode 100644 index 00000000..2487aef5 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/make_subset_data.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# Make subset files located in data direcoty. + +# Copyright 2020 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <num_split> <dst_dir>" + echo "e.g.: $0 data/train_nodev 16 data/train_nodev/split16" + exit 1 +fi + +set -eu + +src_dir=$1 +num_split=$2 +dst_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments +else + has_segments=false +fi + +if ! ${has_segments}; then + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/wav.${i}.scp" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_scp}" ${split_scps} +else + split_scps="" + for i in $(seq 1 "${num_split}"); do + split_scps+=" ${dst_dir}/segments.${i}" + done + # shellcheck disable=SC2086 + utils/split_scp.pl "${src_segments}" ${split_scps} + for i in $(seq 1 "${num_split}"); do + awk '{print $2}' < "${dst_dir}/segments.${i}" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${dst_dir}/wav.${i}.scp" + done + done +fi +echo "Successfully make subsets." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/parse_options.sh new file mode 100644 index 00000000..fdc8a362 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/parse_options.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey); +# Arnab Ghoshal, Karel Vesely + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# Parse command-line options. +# To be sourced by another script (as in ". parse_options.sh"). +# Option format is: --option-name arg +# and shell variable "option_name" gets set to value "arg." +# The exception is --help, which takes no arguments, but prints the +# $help_message variable (if defined). + + +### +### The --config file options have lower priority to command line +### options, so we need to import them first... +### + +# Now import all the configs specified by command-line, in left-to-right order +for ((argpos=1; argpos<$#; argpos++)); do + if [ "${!argpos}" == "--config" ]; then + argpos_plus1=$((argpos+1)) + config=${!argpos_plus1} + [ ! -r $config ] && echo "$0: missing config '$config'" && exit 1 + . $config # source the config file. + fi +done + + +### +### No we process the command line options +### +while true; do + [ -z "${1:-}" ] && break; # break if there are no arguments + case "$1" in + # If the enclosing script is called with --help option, print the help + # message and exit. Scripts should put help messages in $help_message + --help|-h) if [ -z "$help_message" ]; then echo "No help found." 1>&2; + else printf "$help_message\n" 1>&2 ; fi; + exit 0 ;; + --*=*) echo "$0: options to scripts must be of the form --name value, got '$1'" + exit 1 ;; + # If the first command-line argument begins with "--" (e.g. --foo-bar), + # then work out the variable name as $name, which will equal "foo_bar". + --*) name=`echo "$1" | sed s/^--// | sed s/-/_/g`; + # Next we test whether the variable in question is undefned-- if so it's + # an invalid option and we die. Note: $0 evaluates to the name of the + # enclosing script. + # The test [ -z ${foo_bar+xxx} ] will return true if the variable foo_bar + # is undefined. We then have to wrap this test inside "eval" because + # foo_bar is itself inside a variable ($name). + eval '[ -z "${'$name'+xxx}" ]' && echo "$0: invalid option $1" 1>&2 && exit 1; + + oldval="`eval echo \\$$name`"; + # Work out whether we seem to be expecting a Boolean argument. + if [ "$oldval" == "true" ] || [ "$oldval" == "false" ]; then + was_bool=true; + else + was_bool=false; + fi + + # Set the variable to the right value-- the escaped quotes make it work if + # the option had spaces, like --cmd "queue.pl -sync y" + eval $name=\"$2\"; + + # Check that Boolean-valued arguments are really Boolean. + if $was_bool && [[ "$2" != "true" && "$2" != "false" ]]; then + echo "$0: expected \"true\" or \"false\": $1 $2" 1>&2 + exit 1; + fi + shift 2; + ;; + *) break; + esac +done + + +# Check for an empty argument to the --cmd option, which can easily occur as a +# result of scripting errors. +[ ! -z "${cmd+xxx}" ] && [ -z "$cmd" ] && echo "$0: empty argument to --cmd option" 1>&2 && exit 1; + + +true; # so this script returns exit code 0. diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/queue.pl new file mode 100644 index 00000000..bddcb4fe --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/queue.pl @@ -0,0 +1,624 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +# option mem=* -l mem_free=$0,ram_free=$0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* -pe smp $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -q all.q +# option gpu=* -l gpu=$0 -q g.q + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $gpu = 0; + +my $config = "conf/queue.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; +my $array_job = 0; +my $sge_job_id; + +sub print_usage() { + print STDERR + "Usage: queue.pl [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: queue.pl foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: queue.pl -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: queue.pl -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses qstat to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub caught_signal { + if ( defined $sge_job_id ) { # Signal trapped after submitting jobs + my $signal = $!; + system ("qdel $sge_job_id"); + print STDERR "Caught a signal: $signal , deleting SGE task: $sge_job_id and exiting\n"; + exit(2); + } +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "queue.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "queue.pl: Warning: suspicious first argument to queue.pl: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command qsub -v PATH -cwd -S /bin/bash -j y -l arch=*64* +option mem=* -l mem_free=$0,ram_free=$0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* -pe smp $0 +option num_threads=1 # Do not add anything to qsub_opts +option max_jobs_run=* -tc $0 +default gpu=0 +option gpu=0 +option gpu=* -l gpu=$0 -q '*.q' +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +$SIG{INT} = \&caught_signal; +$SIG{TERM} = \&caught_signal; + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + die "Unable to parse line '$line' in config file ($config)\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "queue.pl: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "queue.pl: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + if ($option eq "max_jobs_run" && $array_job != 1) { next; } + my $value = $cli_options{$option}; + + if (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } else { + if ($opened_config_file == 0) { $config = "default config file"; } + die "queue.pl: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "queue.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to queue.pl, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +# in $qdir/sync we'll put the done.* files... we try to keep this +# directory small because it's transmitted over NFS many times. +if (! -d "$qdir/sync") { + system "mkdir -p $qdir/sync 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + $queue_array_opt = "-t $jobstart:$jobend"; + $logfile =~ s/$jobname/\$SGE_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SGE_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/sync/done.$$"; + +unlink($queue_logfile, $syncfile); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) 2>>$logfile >>$logfile\n"; +print Q "ret=\$?\n"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SGE_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= "-o $queue_logfile $qsub_opts $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} +chmod 0755, $queue_scriptfile; + +# This block submits the job to the queue. +for (my $try = 1; $try < 5; $try++) { + my $ret = system ($qsub_cmd); + if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/*/g; + } + print STDERR "queue.pl: job writing to $logfile failed\n"; + exit(1); + } else { + print STDERR "queue.pl: Error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + my $err = `tail $queue_logfile`; + print STDERR "Output of qsub was: $err\n"; + if ($err =~ m/gdi request/ || $err =~ m/qmaster/) { + # When we get queue connectivity problems we usually see a message like: + # Unable to run job: failed receiving gdi request response for mid=1 (got + # syncron message receive timeout error).. + my $waitfor = 20; + print STDERR "queue.pl: It looks like the queue master may be inaccessible. " . + " Trying again after $waitfor seconts\n"; + sleep($waitfor); + # ... and continue throught the loop. + } else { + exit(1); + } + } + } else { + last; # break from the loop. + } +} + +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # This block extracts the numeric SGE job-id from the log file in q/. + # It may be used later to query 'qstat' about the job. + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Your job\S* (\d+)[. ].+ has been submitted/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SGE job-id."; + } + } + my $check_sge_job_ctr=1; + + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for the jobs to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/sync/.kick"); + } else { + unlink("$qdir/sync/.kick"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir/sync >/dev/null"); + } + } + + # The purpose of the next block is so that queue.pl can exit if the job + # was killed without terminating. It's a bit complicated because (a) we + # don't want to overload the qmaster by querying it too frequently), and + # (b) sometimes the qmaster is unreachable or temporarily down, and we + # don't want this to necessarily kill the job. + if (($check_sge_job_ctr < 100 && ($check_sge_job_ctr++ % 10) == 0) || + ($check_sge_job_ctr >= 100 && ($check_sge_job_ctr++ % 50) == 0)) { + # Don't run qstat too often, avoid stress on SGE; the if-condition above + # is designed to check every 10 waits at first, and eventually every 50 + # waits. + if ( -f $f ) { next; } #syncfile appeared: OK. + my $output = `qstat -j $sge_job_id 2>&1`; + my $ret = $?; + if ($ret >> 8 == 1 && $output !~ m/qmaster/ && + $output !~ m/gdi request/) { + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + + sleep(3); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/sync/.kick"); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/sync/.kick"); + sleep(1); + unlink("$qdir/sync/.kick"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SGE_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**queue.pl: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "queue.pl: Error, unfinished job no " . + "longer exists, log is in $logfile, last line is '$last_line', " . + "syncfile is $f, return status of qstat was $ret\n" . + "Possible reasons: a) Exceeded time limit? -> Use more jobs!" . + " b) Shutdown/Frozen machine? -> Run again! Qmaster output " . + "was: $output\n"; + exit(1); + } + } elsif ($ret != 0) { + print STDERR "queue.pl: Warning: qstat command returned status $ret (qstat -j $sge_job_id,$!)\n"; + print STDERR "queue.pl: output was: $output"; + } + } + } + } + unlink(@syncfiles); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SGE_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/$jobstart/g; } + print STDERR "queue.pl: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "queue.pl: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SGE_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "queue.pl: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/run.pl new file mode 100644 index 00000000..f23bb8dc --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/run.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") 2>>$logfile >> $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/slurm.pl new file mode 100644 index 00000000..27e5fce9 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/slurm.pl @@ -0,0 +1,627 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +# Copyright 2012 Johns Hopkins University (Author: Daniel Povey). +# 2014 Vimal Manohar (Johns Hopkins University) +# 2015 Johns Hopkins University (Yenda Trmal <jtrmal@gmail.com>>) +# Apache 2.0. + +use File::Basename; +use Cwd; +use Getopt::Long; + +# slurm.pl was created from the queue.pl +# queue.pl has the same functionality as run.pl, except that +# it runs the job in question on the queue (Sun GridEngine). +# This version of queue.pl uses the task array functionality +# of the grid engine. Note: it's different from the queue.pl +# in the s4 and earlier scripts. + +# The script now supports configuring the queue system using a config file +# (default in conf/queue.conf; but can be passed specified with --config option) +# and a set of command line options. +# The current script handles: +# 1) Normal configuration arguments +# For e.g. a command line option of "--gpu 1" could be converted into the option +# "-q g.q -l gpu=1" to qsub. How the CLI option is handled is determined by a +# line in the config file like +# gpu=* -q g.q -l gpu=$0 +# $0 here in the line is replaced with the argument read from the CLI and the +# resulting string is passed to qsub. +# 2) Special arguments to options such as +# gpu=0 +# If --gpu 0 is given in the command line, then no special "-q" is given. +# 3) Default argument +# default gpu=0 +# If --gpu option is not passed in the command line, then the script behaves as +# if --gpu 0 was passed since 0 is specified as the default argument for that +# option +# 4) Arbitrary options and arguments. +# Any command line option starting with '--' and its argument would be handled +# as long as its defined in the config file. +# 5) Default behavior +# If the config file that is passed using is not readable, then the script +# behaves as if the queue has the following config file: +# $ cat conf/queue.conf +# # Default configuration +# command sbatch --export=PATH -S /bin/bash -j y -l arch=*64* +# option mem=* --mem-per-cpu $0 +# option mem=0 # Do not add anything to qsub_opts +# option num_threads=* --cpus-per-task $0 +# option num_threads=1 # Do not add anything to qsub_opts +# option max_jobs_run=* -tc $0 +# default gpu=0 +# option gpu=0 -p shared +# option gpu=* -p gpu #this has to be figured out + +#print STDERR "$0 " . join(" ", @ARGV) . "\n"; + +my $qsub_opts = ""; +my $sync = 0; +my $num_threads = 1; +my $max_jobs_run; +my $gpu = 0; + +my $config = "conf/slurm.conf"; + +my %cli_options = (); + +my $jobname; +my $jobstart; +my $jobend; + +my $array_job = 0; + +sub print_usage() { + print STDERR + "Usage: $0 [options] [JOB=1:n] log-file command-line arguments...\n" . + "e.g.: $0 foo.log echo baz\n" . + " (which will echo \"baz\", with stdout and stderr directed to foo.log)\n" . + "or: $0 -q all.q\@xyz foo.log echo bar \| sed s/bar/baz/ \n" . + " (which is an example of using a pipe; you can provide other escaped bash constructs)\n" . + "or: $0 -q all.q\@qyz JOB=1:10 foo.JOB.log echo JOB \n" . + " (which illustrates the mechanism to submit parallel jobs; note, you can use \n" . + " another string other than JOB)\n" . + "Note: if you pass the \"-sync y\" option to qsub, this script will take note\n" . + "and change its behavior. Otherwise it uses squeue to work out when the job finished\n" . + "Options:\n" . + " --config <config-file> (default: $config)\n" . + " --mem <mem-requirement> (e.g. --mem 2G, --mem 500M, \n" . + " also support K and numbers mean bytes)\n" . + " --num-threads <num-threads> (default: $num_threads)\n" . + " --max-jobs-run <num-jobs>\n" . + " --gpu <0|1> (default: $gpu)\n"; + exit 1; +} + +sub exec_command { + # Execute command and return a tuple of stdout and exit code + my $command = join ' ', @_; + # To get the actual exit value, shift right by eight bits. + ($_ = `$command 2>&1`, $? >> 8); +} + +if (@ARGV < 2) { + print_usage(); +} + +for (my $x = 1; $x <= 3; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + my $switch = shift @ARGV; + + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $sync = 1; + $qsub_opts .= "$switch $argument "; + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $qsub_opts .= "$switch $argument $argument2 "; + $num_threads = $argument2; + } elsif ($switch =~ m/^--/) { # Config options + # Convert CLI option to variable name + # by removing '--' from the switch and replacing any + # '-' with a '_' + $switch =~ s/^--//; + $switch =~ s/-/_/g; + $cli_options{$switch} = $argument; + } else { # Other qsub options - passed as is + $qsub_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "$0: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "$0: invalid job range $ARGV[0], start must be strictly positive (this is a GridEngine limitation)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $array_job = 1; + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to $0: $ARGV[0]\n"; + } +} + +if (@ARGV < 2) { + print_usage(); +} + +if (exists $cli_options{"config"}) { + $config = $cli_options{"config"}; +} + +my $default_config_file = <<'EOF'; +# Default configuration +command sbatch --export=PATH --ntasks-per-node=1 +option time=* --time $0 +option mem=* --mem-per-cpu $0 +option mem=0 # Do not add anything to qsub_opts +option num_threads=* --cpus-per-task $0 --ntasks-per-node=1 +option num_threads=1 --cpus-per-task 1 --ntasks-per-node=1 # Do not add anything to qsub_opts +default gpu=0 +option gpu=0 -p shared +option gpu=* -p gpu --gres=gpu:$0 --time 4:0:0 # this has to be figured out +# note: the --max-jobs-run option is supported as a special case +# by slurm.pl and you don't have to handle it in the config file. +EOF + +# Here the configuration options specified by the user on the command line +# (e.g. --mem 2G) are converted to options to the qsub system as defined in +# the config file. (e.g. if the config file has the line +# "option mem=* -l ram_free=$0,mem_free=$0" +# and the user has specified '--mem 2G' on the command line, the options +# passed to queue system would be "-l ram_free=2G,mem_free=2G +# A more detailed description of the ways the options would be handled is at +# the top of this file. + +my $opened_config_file = 1; + +open CONFIG, "<$config" or $opened_config_file = 0; + +my %cli_config_options = (); +my %cli_default_options = (); + +if ($opened_config_file == 0 && exists($cli_options{"config"})) { + print STDERR "Could not open config file $config\n"; + exit(1); +} elsif ($opened_config_file == 0 && !exists($cli_options{"config"})) { + # Open the default config file instead + open (CONFIG, "echo '$default_config_file' |") or die "Unable to open pipe\n"; + $config = "Default config"; +} + +my $qsub_cmd = ""; +my $read_command = 0; + +while(<CONFIG>) { + chomp; + my $line = $_; + $_ =~ s/\s*#.*//g; + if ($_ eq "") { next; } + if ($_ =~ /^command (.+)/) { + $read_command = 1; + $qsub_cmd = $1 . " "; + } elsif ($_ =~ m/^option ([^=]+)=\* (.+)$/) { + # Config option that needs replacement with parameter value read from CLI + # e.g.: option mem=* -l mem_free=$0,ram_free=$0 + my $option = $1; # mem + my $arg= $2; # -l mem_free=$0,ram_free=$0 + if ($arg !~ m:\$0:) { + print STDERR "Warning: the line '$line' in config file ($config) does not substitution variable \$0\n"; + } + if (exists $cli_options{$option}) { + # Replace $0 with the argument read from command line. + # e.g. "-l mem_free=$0,ram_free=$0" -> "-l mem_free=2G,ram_free=2G" + $arg =~ s/\$0/$cli_options{$option}/g; + $cli_config_options{$option} = $arg; + } + } elsif ($_ =~ m/^option ([^=]+)=(\S+)\s?(.*)$/) { + # Config option that does not need replacement + # e.g. option gpu=0 -q all.q + my $option = $1; # gpu + my $value = $2; # 0 + my $arg = $3; # -q all.q + if (exists $cli_options{$option}) { + $cli_default_options{($option,$value)} = $arg; + } + } elsif ($_ =~ m/^default (\S+)=(\S+)/) { + # Default options. Used for setting default values to options i.e. when + # the user does not specify the option on the command line + # e.g. default gpu=0 + my $option = $1; # gpu + my $value = $2; # 0 + if (!exists $cli_options{$option}) { + # If the user has specified this option on the command line, then we + # don't have to do anything + $cli_options{$option} = $value; + } + } else { + print STDERR "$0: unable to parse line '$line' in config file ($config)\n"; + exit(1); + } +} + +close(CONFIG); + +if ($read_command != 1) { + print STDERR "$0: config file ($config) does not contain the line \"command .*\"\n"; + exit(1); +} + +for my $option (keys %cli_options) { + if ($option eq "config") { next; } + + my $value = $cli_options{$option}; + + if ($option eq "max_jobs_run") { + if ($array_job != 1) { + print STDERR "Ignoring $option since this is not an array task."; + } else { + $max_jobs_run = $value; + } + } elsif (exists $cli_default_options{($option,$value)}) { + $qsub_opts .= "$cli_default_options{($option,$value)} "; + } elsif (exists $cli_config_options{$option}) { + $qsub_opts .= "$cli_config_options{$option} "; + } elsif (exists $cli_default_options{($option,"*")}) { + $qsub_opts .= $cli_default_options{($option,"*")} . " "; + } else { + if ($opened_config_file == 0) { + $config = "default config file"; + } + die "$0: Command line option $option not described in $config (or value '$value' not allowed)\n"; + } +} + +my $cwd = getcwd(); +my $logfile = shift @ARGV; + +if ($array_job == 1 && $logfile !~ m/$jobname/ + && $jobend > $jobstart) { + print STDERR "$0: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +# +# Work out the command; quote escaping is done here. +# Note: the rules for escaping stuff are worked out pretty +# arbitrarily, based on what we want it to do. Some things that +# we pass as arguments to $0, such as "|", we want to be +# interpreted by bash, so we don't escape them. Other things, +# such as archive specifiers like 'ark:gunzip -c foo.gz|', we want +# to be passed, in quotes, to the Kaldi program. Our heuristic +# is that stuff with spaces in should be quoted. This doesn't +# always work. +# +my $cmd = ""; + +foreach my $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } # If string contains no spaces, take + # as-is. + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } # else if no dbl-quotes, use single + else { $cmd .= "\"$x\" "; } # else use double. +} + +# +# Work out the location of the script file, and open it for writing. +# +my $dir = dirname($logfile); +my $base = basename($logfile); +my $qdir = "$dir/q"; +$qdir =~ s:/(log|LOG)/*q:/q:; # If qdir ends in .../log/q, make it just .../q. +my $queue_logfile = "$qdir/$base"; + +if (!-d $dir) { system "mkdir -p $dir 2>/dev/null"; } # another job may be doing this... +if (!-d $dir) { die "Cannot make the directory $dir\n"; } +# make a directory called "q", +# where we will put the log created by qsub... normally this doesn't contain +# anything interesting, evertyhing goes to $logfile. +if (! -d "$qdir") { + system "mkdir $qdir 2>/dev/null"; + sleep(5); ## This is to fix an issue we encountered in denominator lattice creation, + ## where if e.g. the exp/tri2b_denlats/log/15/q directory had just been + ## created and the job immediately ran, it would die with an error because nfs + ## had not yet synced. I'm also decreasing the acdirmin and acdirmax in our + ## NFS settings to something like 5 seconds. +} + +my $queue_array_opt = ""; +if ($array_job == 1) { # It's an array job. + if ($max_jobs_run) { + $queue_array_opt = "--array ${jobstart}-${jobend}%${max_jobs_run}"; + } else { + $queue_array_opt = "--array ${jobstart}-${jobend}"; + } + $logfile =~ s/$jobname/\$SLURM_ARRAY_TASK_ID/g; # This variable will get + # replaced by qsub, in each job, with the job-id. + $cmd =~ s/$jobname/\$\{SLURM_ARRAY_TASK_ID\}/g; # same for the command... + $queue_logfile =~ s/\.?$jobname//; # the log file in the q/ subdirectory + # is for the queue to put its log, and this doesn't need the task array subscript + # so we remove it. +} + +# queue_scriptfile is as $queue_logfile [e.g. dir/q/foo.log] but +# with the suffix .sh. +my $queue_scriptfile = $queue_logfile; +($queue_scriptfile =~ s/\.[a-zA-Z]{1,5}$/.sh/) || ($queue_scriptfile .= ".sh"); +if ($queue_scriptfile !~ m:^/:) { + $queue_scriptfile = $cwd . "/" . $queue_scriptfile; # just in case. +} + +# We'll write to the standard input of "qsub" (the file-handle Q), +# the job that we want it to execute. +# Also keep our current PATH around, just in case there was something +# in it that we need (although we also source ./path.sh) + +my $syncfile = "$qdir/done.$$"; + +system("rm $queue_logfile $syncfile 2>/dev/null"); +# +# Write to the script file, and then close it. +# +open(Q, ">$queue_scriptfile") || die "Failed to write to $queue_scriptfile"; + +print Q "#!/bin/bash\n"; +print Q "cd $cwd\n"; +print Q ". ./path.sh\n"; +print Q "( echo '#' Running on \`hostname\`\n"; +print Q " echo '#' Started at \`date\`\n"; +print Q " set | grep SLURM | while read line; do echo \"# \$line\"; done\n"; +print Q " echo -n '# '; cat <<EOF\n"; +print Q "$cmd\n"; # this is a way of echoing the command into a comment in the log file, +print Q "EOF\n"; # without having to escape things like "|" and quote characters. +print Q ") >$logfile\n"; +print Q "if [ \"\$CUDA_VISIBLE_DEVICES\" == \"NoDevFiles\" ]; then\n"; +print Q " ( echo CUDA_VISIBLE_DEVICES set to NoDevFiles, unsetting it... \n"; +print Q " )>>$logfile\n"; +print Q " unset CUDA_VISIBLE_DEVICES.\n"; +print Q "fi\n"; +print Q "time1=\`date +\"%s\"\`\n"; +print Q " ( $cmd ) &>>$logfile\n"; +print Q "ret=\$?\n"; +print Q "sync || true"; +print Q "time2=\`date +\"%s\"\`\n"; +print Q "echo '#' Accounting: begin_time=\$time1 >>$logfile\n"; +print Q "echo '#' Accounting: end_time=\$time2 >>$logfile\n"; +print Q "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=$num_threads >>$logfile\n"; +print Q "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; +print Q "[ \$ret -eq 137 ] && exit 100;\n"; # If process was killed (e.g. oom) it will exit with status 137; + # let the script return with status 100 which will put it to E state; more easily rerunnable. +if ($array_job == 0) { # not an array job + print Q "touch $syncfile\n"; # so we know it's done. +} else { + print Q "touch $syncfile.\$SLURM_ARRAY_TASK_ID\n"; # touch a bunch of sync-files. +} +print Q "exit \$[\$ret ? 1 : 0]\n"; # avoid status 100 which grid-engine +print Q "## submitted with:\n"; # treats specially. +$qsub_cmd .= " $qsub_opts --open-mode=append -e ${queue_logfile} -o ${queue_logfile} $queue_array_opt $queue_scriptfile >>$queue_logfile 2>&1"; +print Q "# $qsub_cmd\n"; +if (!close(Q)) { # close was not successful... || die "Could not close script file $shfile"; + die "Failed to close the script file (full disk?)"; +} + +my $ret = system ($qsub_cmd); +if ($ret != 0) { + if ($sync && $ret == 256) { # this is the exit status when a job failed (bad exit status) + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + print STDERR "$0: job writing to $logfile failed\n"; + } else { + print STDERR "$0: error submitting jobs to queue (return status was $ret)\n"; + print STDERR "queue log file is $queue_logfile, command was $qsub_cmd\n"; + print STDERR `tail $queue_logfile`; + } + exit(1); +} + +my $sge_job_id; +if (! $sync) { # We're not submitting with -sync y, so we + # need to wait for the jobs to finish. We wait for the + # sync-files we "touched" in the script to exist. + my @syncfiles = (); + if (!defined $jobname) { # not an array job. + push @syncfiles, $syncfile; + } else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + push @syncfiles, "$syncfile.$jobid"; + } + } + # We will need the sge_job_id, to check that job still exists + { # Get the SLURM job-id from the log file in q/ + open(L, "<$queue_logfile") || die "Error opening log file $queue_logfile"; + undef $sge_job_id; + while (<L>) { + if (m/Submitted batch job (\d+)/) { + if (defined $sge_job_id) { + die "Error: your job was submitted more than once (see $queue_logfile)"; + } else { + $sge_job_id = $1; + } + } + } + close(L); + if (!defined $sge_job_id) { + die "Error: log file $queue_logfile does not specify the SLURM job-id."; + } + } + my $check_sge_job_ctr=1; + # + my $wait = 0.1; + my $counter = 0; + foreach my $f (@syncfiles) { + # wait for them to finish one by one. + while (! -f $f) { + sleep($wait); + $wait *= 1.2; + if ($wait > 3.0) { + $wait = 3.0; # never wait more than 3 seconds. + # the following (.kick) commands are basically workarounds for NFS bugs. + if (rand() < 0.25) { # don't do this every time... + if (rand() > 0.5) { + system("touch $qdir/.kick"); + } else { + system("rm $qdir/.kick 2>/dev/null"); + } + } + if ($counter++ % 10 == 0) { + # This seems to kick NFS in the teeth to cause it to refresh the + # directory. I've seen cases where it would indefinitely fail to get + # updated, even though the file exists on the server. + # Only do this every 10 waits (every 30 seconds) though, or if there + # are many jobs waiting they can overwhelm the file server. + system("ls $qdir >/dev/null"); + } + } + + # Check that the job exists in SLURM. Job can be killed if duration + # exceeds some hard limit, or in case of a machine shutdown. + if (($check_sge_job_ctr++ % 10) == 0) { # Don't run qstat too often, avoid stress on SGE. + if ( -f $f ) { next; }; #syncfile appeared: OK. + # system(...) : To get the actual exit value, shift $ret right by eight bits. + my ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + if ($squeue_status == 1) { + # Don't consider immediately missing job as error, first wait some + sleep(4); + ($squeue_output, $squeue_status) = exec_command("squeue -j $sge_job_id"); + } + if ($squeue_status == 1) { + # time to make sure it is not just delayed creation of the syncfile. + + # Don't consider immediately missing job as error, first wait some + # time to make sure it is not just delayed creation of the syncfile. + sleep(4); + # Sometimes NFS gets confused and thinks it's transmitted the directory + # but it hasn't, due to timestamp issues. Changing something in the + # directory will usually fix that. + system("touch $qdir/.kick"); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(7); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + sleep(60); + system("touch $qdir/.kick"); + sleep(1); + system("rm $qdir/.kick 2>/dev/null"); + if ( -f $f ) { next; } #syncfile appeared, ok + $f =~ m/\.(\d+)$/ || die "Bad sync-file name $f"; + my $job_id = $1; + if (defined $jobname) { + $logfile =~ s/\$SLURM_ARRAY_TASK_ID/$job_id/g; + } + my $last_line = `tail -n 1 $logfile`; + if ($last_line =~ m/status 0$/ && (-M $logfile) < 0) { + # if the last line of $logfile ended with "status 0" and + # $logfile is newer than this program [(-M $logfile) gives the + # time elapsed between file modification and the start of this + # program], then we assume the program really finished OK, + # and maybe something is up with the file system. + print STDERR "**$0: syncfile $f was not created but job seems\n" . + "**to have finished OK. Probably your file-system has problems.\n" . + "**This is just a warning.\n"; + last; + } else { + chop $last_line; + print STDERR "$0: Error: Job $sge_job_id seems to no longer exists:\n" . + "'squeue -j $sge_job_id' returned error code $squeue_status and said:\n" . + " $squeue_output\n" . + "Syncfile $f does not exist, meaning that the job did not finish.\n" . + "Log is in $logfile. Last line '$last_line' does not end in 'status 0'.\n" . + "Possible reasons:\n" . + " a) Exceeded time limit? -> Use more jobs!\n" . + " b) Shutdown/Frozen machine? -> Run again! squeue:\n"; + system("squeue -j $sge_job_id"); + exit(1); + } + } elsif ($ret != 0) { + print STDERR "$0: Warning: squeue command returned status $ret (squeue -j $sge_job_id,$!)\n"; + } + } + } + } + my $all_syncfiles = join(" ", @syncfiles); + system("rm $all_syncfiles 2>/dev/null"); +} + +# OK, at this point we are synced; we know the job is done. +# But we don't know about its exit status. We'll look at $logfile for this. +# First work out an array @logfiles of file-locations we need to +# read (just one, unless it's an array job). +my @logfiles = (); +if (!defined $jobname) { # not an array job. + push @logfiles, $logfile; +} else { + for (my $jobid = $jobstart; $jobid <= $jobend; $jobid++) { + my $l = $logfile; + $l =~ s/\$SLURM_ARRAY_TASK_ID/$jobid/g; + push @logfiles, $l; + } +} + +my $num_failed = 0; +my $status = 1; +foreach my $l (@logfiles) { + my @wait_times = (0.1, 0.2, 0.2, 0.3, 0.5, 0.5, 1.0, 2.0, 5.0, 5.0, 5.0, 10.0, 25.0); + for (my $iter = 0; $iter <= @wait_times; $iter++) { + my $line = `tail -10 $l 2>/dev/null`; # Note: although this line should be the last + # line of the file, I've seen cases where it was not quite the last line because + # of delayed output by the process that was running, or processes it had called. + # so tail -10 gives it a little leeway. + if ($line =~ m/with status (\d+)/) { + $status = $1; + last; + } else { + if ($iter < @wait_times) { + sleep($wait_times[$iter]); + } else { + if (! -f $l) { + print STDERR "Log-file $l does not exist.\n"; + } else { + print STDERR "The last line of log-file $l does not seem to indicate the " + . "return status as expected\n"; + } + exit(1); # Something went wrong with the queue, or the + # machine it was running on, probably. + } + } + } + # OK, now we have $status, which is the return-status of + # the command in the job. + if ($status != 0) { $num_failed++; } +} +if ($num_failed == 0) { exit(0); } +else { # we failed. + if (@logfiles == 1) { + if (defined $jobname) { $logfile =~ s/\$SLURM_TASK_ARRAY_ID/$jobstart/g; } + print STDERR "$0: job failed with status $status, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "$0: probably you forgot to put JOB=1:\$nj in your script.\n"; + } + } else { + if (defined $jobname) { $logfile =~ s/\$SLURM_ARRAY_TASK_ID/*/g; } + my $numjobs = 1 + $jobend - $jobstart; + print STDERR "$0: $num_failed / $numjobs failed, log is in $logfile\n"; + } + exit(1); +} diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_data.sh new file mode 100644 index 00000000..baf97b66 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_data.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Split data direcoty into two data direcotries + +# Copyright 2019 Tomoki Hayashi +# MIT License (https://opensource.org/licenses/MIT) + +# shellcheck disable=SC1091 +. ./path.sh || exit 1; + +shuffle=false +num_first=0 +num_second=0 + +# shellcheck disable=SC1091 +. utils/parse_options.sh || exit 1; + +if [ $# -ne 3 ]; then + echo "Usage: $0 <src_dir> <dist_dir_1> <dist_dir_2> ..." + echo "e.g.: $0 data/all data/train data/deveval" + echo "" + echo "Options:" + echo " --shuffle: Whether to perform shuffle (default=false)." + echo " --num_first: Number of utts in the first dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + echo " --num_second: Number of utts in the second dist dir." + echo " If set to 0, it will be automatically decided (default=0)." + exit 1 +fi + +set -eu + +src_dir=$1 +first_dist_dir=$2 +second_dist_dir=$3 + +src_scp=${src_dir}/wav.scp +if [ -e "${src_dir}/segments" ]; then + has_segments=true + src_segments=${src_dir}/segments + num_src_utts=$(wc -l < "${src_segments}") +else + has_segments=false + num_src_utts=$(wc -l < "${src_scp}") +fi + +# check number of utts +if [ "${num_first}" -eq 0 ] && [ "${num_second}" -eq 0 ]; then + num_first=$((num_src_utts / 2 )) + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -eq 0 ]; then + [ "${num_src_utts}" -le "${num_first}" ] && \ + echo "ERROR: num_first must be less than # utts in src. (${num_first} vs ${num_src_utts})" >&2 && \ + exit 1 + num_second=$((num_src_utts - num_first)) +elif [ "${num_first}" -eq 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -le "${num_second}" ] && \ + echo "ERROR: num_second must be less than # utts in src. (${num_second} vs ${num_src_utts})" >&2 && \ + exit 1 + num_first=$((num_src_utts - num_second)) +elif [ "${num_first}" -gt 0 ] && [ "${num_second}" -gt 0 ]; then + [ "${num_src_utts}" -ne "$((num_first + num_second))" ] && \ + echo "ERROR: num_first + num_second must be the same # utts in src. ($((num_first + num_second)) vs ${num_src_utts})" >&2 && \ + exit 1 +fi + +# check directory existence +[ ! -e "${first_dist_dir}" ] && mkdir -p "${first_dist_dir}" +[ ! -e "${second_dist_dir}" ] && mkdir -p "${second_dist_dir}" + +# split +if ! "${has_segments}"; then + if "${shuffle}"; then + sort -R "${src_scp}" > "${src_scp}.unsorted" + head -n "${num_first}" "${src_scp}.unsorted" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}.unsorted" | sort > "${second_dist_dir}/wav.scp" + rm "${src_scp}.unsorted" + else + head -n "${num_first}" "${src_scp}" | sort > "${first_dist_dir}/wav.scp" + tail -n "${num_second}" "${src_scp}" | sort > "${second_dist_dir}/wav.scp" + fi +else + # split segments at first + if "${shuffle}"; then + sort -R "${src_segments}" > "${src_segments}.unsorted" + head -n "${num_first}" "${src_segments}.unsorted" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}.unsorted" | sort > "${second_dist_dir}/segments" + rm "${src_segments}.unsorted" + else + head -n "${num_first}" "${src_segments}" | sort > "${first_dist_dir}/segments" + tail -n "${num_second}" "${src_segments}" | sort > "${second_dist_dir}/segments" + fi + # split wav.scp + rm -rf "${first_dist_dir}/wav.scp" + awk '{print $2}' < "${first_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${first_dist_dir}/wav.scp" + done + rm -rf "${second_dist_dir}/wav.scp" + awk '{print $2}' < "${second_dist_dir}/segments" | sort | uniq | while read -r wav_id; do + grep "^${wav_id} " < "${src_scp}" >> "${second_dist_dir}/wav.scp" + done +fi + +echo "Successfully split data directory." diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_scp.pl new file mode 100644 index 00000000..dc798282 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/split_scp.pl @@ -0,0 +1,246 @@ +#!/usr/bin/env perl + +# Copyright 2010-2011 Microsoft Corporation + +# See ../../COPYING for clarification regarding multiple authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +# WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +# MERCHANTABLITY OR NON-INFRINGEMENT. +# See the Apache 2 License for the specific language governing permissions and +# limitations under the License. + + +# This program splits up any kind of .scp or archive-type file. +# If there is no utt2spk option it will work on any text file and +# will split it up with an approximately equal number of lines in +# each but. +# With the --utt2spk option it will work on anything that has the +# utterance-id as the first entry on each line; the utt2spk file is +# of the form "utterance speaker" (on each line). +# It splits it into equal size chunks as far as it can. If you use the utt2spk +# option it will make sure these chunks coincide with speaker boundaries. In +# this case, if there are more chunks than speakers (and in some other +# circumstances), some of the resulting chunks will be empty and it will print +# an error message and exit with nonzero status. +# You will normally call this like: +# split_scp.pl scp scp.1 scp.2 scp.3 ... +# or +# split_scp.pl --utt2spk=utt2spk scp scp.1 scp.2 scp.3 ... +# Note that you can use this script to split the utt2spk file itself, +# e.g. split_scp.pl --utt2spk=utt2spk utt2spk utt2spk.1 utt2spk.2 ... + +# You can also call the scripts like: +# split_scp.pl -j 3 0 scp scp.0 +# [note: with this option, it assumes zero-based indexing of the split parts, +# i.e. the second number must be 0 <= n < num-jobs.] + +use warnings; + +$num_jobs = 0; +$job_id = 0; +$utt2spk_file = ""; +$one_based = 0; + +for ($x = 1; $x <= 3 && @ARGV > 0; $x++) { + if ($ARGV[0] eq "-j") { + shift @ARGV; + $num_jobs = shift @ARGV; + $job_id = shift @ARGV; + } + if ($ARGV[0] =~ /--utt2spk=(.+)/) { + $utt2spk_file=$1; + shift; + } + if ($ARGV[0] eq '--one-based') { + $one_based = 1; + shift @ARGV; + } +} + +if ($num_jobs != 0 && ($num_jobs < 0 || $job_id - $one_based < 0 || + $job_id - $one_based >= $num_jobs)) { + die "$0: Invalid job number/index values for '-j $num_jobs $job_id" . + ($one_based ? " --one-based" : "") . "'\n" +} + +$one_based + and $job_id--; + +if(($num_jobs == 0 && @ARGV < 2) || ($num_jobs > 0 && (@ARGV < 1 || @ARGV > 2))) { + die +"Usage: split_scp.pl [--utt2spk=<utt2spk_file>] in.scp out1.scp out2.scp ... + or: split_scp.pl -j num-jobs job-id [--one-based] [--utt2spk=<utt2spk_file>] in.scp [out.scp] + ... where 0 <= job-id < num-jobs, or 1 <= job-id <- num-jobs if --one-based.\n"; +} + +$error = 0; +$inscp = shift @ARGV; +if ($num_jobs == 0) { # without -j option + @OUTPUTS = @ARGV; +} else { + for ($j = 0; $j < $num_jobs; $j++) { + if ($j == $job_id) { + if (@ARGV > 0) { push @OUTPUTS, $ARGV[0]; } + else { push @OUTPUTS, "-"; } + } else { + push @OUTPUTS, "/dev/null"; + } + } +} + +if ($utt2spk_file ne "") { # We have the --utt2spk option... + open($u_fh, '<', $utt2spk_file) || die "$0: Error opening utt2spk file $utt2spk_file: $!\n"; + while(<$u_fh>) { + @A = split; + @A == 2 || die "$0: Bad line $_ in utt2spk file $utt2spk_file\n"; + ($u,$s) = @A; + $utt2spk{$u} = $s; + } + close $u_fh; + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + @spkrs = (); + while(<$i_fh>) { + @A = split; + if(@A == 0) { die "$0: Empty or space-only line in scp file $inscp\n"; } + $u = $A[0]; + $s = $utt2spk{$u}; + defined $s || die "$0: No utterance $u in utt2spk file $utt2spk_file\n"; + if(!defined $spk_count{$s}) { + push @spkrs, $s; + $spk_count{$s} = 0; + $spk_data{$s} = []; # ref to new empty array. + } + $spk_count{$s}++; + push @{$spk_data{$s}}, $_; + } + # Now split as equally as possible .. + # First allocate spks to files by allocating an approximately + # equal number of speakers. + $numspks = @spkrs; # number of speakers. + $numscps = @OUTPUTS; # number of output files. + if ($numspks < $numscps) { + die "$0: Refusing to split data because number of speakers $numspks " . + "is less than the number of output .scp files $numscps\n"; + } + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scparray[$scpidx] = []; # [] is array reference. + } + for ($spkidx = 0; $spkidx < $numspks; $spkidx++) { + $scpidx = int(($spkidx*$numscps) / $numspks); + $spk = $spkrs[$spkidx]; + push @{$scparray[$scpidx]}, $spk; + $scpcount[$scpidx] += $spk_count{$spk}; + } + + # Now will try to reassign beginning + ending speakers + # to different scp's and see if it gets more balanced. + # Suppose objf we're minimizing is sum_i (num utts in scp[i] - average)^2. + # We can show that if considering changing just 2 scp's, we minimize + # this by minimizing the squared difference in sizes. This is + # equivalent to minimizing the absolute difference in sizes. This + # shows this method is bound to converge. + + $changed = 1; + while($changed) { + $changed = 0; + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + # First try to reassign ending spk of this scp. + if($scpidx < $numscps-1) { + $sz = @{$scparray[$scpidx]}; + if($sz > 0) { + $spk = $scparray[$scpidx]->[$sz-1]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx]; + $nutt2 = $scpcount[$scpidx+1]; + if( abs( ($nutt2+$count) - ($nutt1-$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx+1] += $count; + $scpcount[$scpidx] -= $count; + pop @{$scparray[$scpidx]}; + unshift @{$scparray[$scpidx+1]}, $spk; + $changed = 1; + } + } + } + if($scpidx > 0 && @{$scparray[$scpidx]} > 0) { + $spk = $scparray[$scpidx]->[0]; + $count = $spk_count{$spk}; + $nutt1 = $scpcount[$scpidx-1]; + $nutt2 = $scpcount[$scpidx]; + if( abs( ($nutt2-$count) - ($nutt1+$count)) + < abs($nutt2 - $nutt1)) { # Would decrease + # size-diff by reassigning spk... + $scpcount[$scpidx-1] += $count; + $scpcount[$scpidx] -= $count; + shift @{$scparray[$scpidx]}; + push @{$scparray[$scpidx-1]}, $spk; + $changed = 1; + } + } + } + } + # Now print out the files... + for($scpidx = 0; $scpidx < $numscps; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($f_fh, '>', $scpfile) + : open($f_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + $count = 0; + if(@{$scparray[$scpidx]} == 0) { + print STDERR "$0: eError: split_scp.pl producing empty .scp file " . + "$scpfile (too many splits and too few speakers?)\n"; + $error = 1; + } else { + foreach $spk ( @{$scparray[$scpidx]} ) { + print $f_fh @{$spk_data{$spk}}; + $count += $spk_count{$spk}; + } + $count == $scpcount[$scpidx] || die "Count mismatch [code error]"; + } + close($f_fh); + } +} else { + # This block is the "normal" case where there is no --utt2spk + # option and we just break into equal size chunks. + + open($i_fh, '<', $inscp) || die "$0: Error opening input scp file $inscp: $!\n"; + + $numscps = @OUTPUTS; # size of array. + @F = (); + while(<$i_fh>) { + push @F, $_; + } + $numlines = @F; + if($numlines == 0) { + print STDERR "$0: error: empty input scp file $inscp\n"; + $error = 1; + } + $linesperscp = int( $numlines / $numscps); # the "whole part".. + $linesperscp >= 1 || die "$0: You are splitting into too many pieces! [reduce \$nj]\n"; + $remainder = $numlines - ($linesperscp * $numscps); + ($remainder >= 0 && $remainder < $numlines) || die "bad remainder $remainder"; + # [just doing int() rounds down]. + $n = 0; + for($scpidx = 0; $scpidx < @OUTPUTS; $scpidx++) { + $scpfile = $OUTPUTS[$scpidx]; + ($scpfile ne '-' ? open($o_fh, '>', $scpfile) + : open($o_fh, '>&', \*STDOUT)) || + die "$0: Could not open scp file $scpfile for writing: $!\n"; + for($k = 0; $k < $linesperscp + ($scpidx < $remainder ? 1 : 0); $k++) { + print $o_fh $F[$n++]; + } + close($o_fh) || die "$0: Eror closing scp file $scpfile: $!\n"; + } + $n == $numlines || die "$n != $numlines [code error]"; +} + +exit ($error); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/ssh.pl new file mode 100644 index 00000000..5d3e3e44 --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/ssh.pl @@ -0,0 +1,219 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +use Cwd; +use File::Basename; + +# This program is like run.pl except rather than just running on a local +# machine, it can be configured to run on remote machines via ssh. +# It requires that you have set up passwordless access to those machines, +# and that Kaldi is running from a location that is accessible via the +# same path on those machines (presumably via an NFS mount). +# +# It looks for a file .queue/machines that should have, on each line, the name +# of a machine that you can ssh to (which may include this machine). It doesn't +# have to be a fully qualified name. +# +# Later we may extend this so that on each line of .queue/machines you +# can specify various resources that each machine has, such as how +# many slots and how much memory, and make it wait if machines are +# busy. But for now it simply ssh's to a machine from those in the list. + +# The command-line interface of this program is the same as run.pl; +# see run.pl for more information about the usage. + + +@ARGV < 2 && die "usage: ssh.pl log-file command-line arguments..."; + +$jobstart = 1; +$jobend = 1; +$qsub_opts=""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# ssh.pl, which we will just discard. + +if (@ARGV > 0) { + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { # parse any options + # that would normally go to qsub, but which will be ignored here. + $switch = shift @ARGV; + if ($switch eq "-V") { + $qsub_opts .= "-V "; + } else { + $option = shift @ARGV; + if ($switch eq "-sync" && $option =~ m/^[yY]/) { + $qsub_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } + $qsub_opts .= "$switch $option "; + if ($switch eq "-pe") { # e.g. -pe smp 5 + $option2 = shift @ARGV; + $qsub_opts .= "$option2 "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:10 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)"; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +if ($qsub_opts ne "") { + print STDERR "Warning: ssh.pl ignoring options \"$qsub_opts\"\n"; +} + +{ # Read .queue/machines + if (!open(Q, "<.queue/machines")) { + print STDERR "ssh.pl: expected the file .queue/machines to exist.\n"; + exit(1); + } + @machines = (); + while (<Q>) { + chop; + if ($_ ne "") { + @A = split; + if (@A != 1) { + die "ssh.pl: bad line '$_' in .queue/machines."; + } + if ($A[0] !~ m/^[a-z0-9\.\-]+/) { + die "ssh.pl: invalid machine name '$A[0]'"; + } + push @machines, $A[0]; + } + } + if (@machines == 0) { die "ssh.pl: no machines listed in .queue/machines"; } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "ssh.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +{ + $offset = 0; # $offset will be an offset added to any index from the job-id + # specified if the user does JOB=1:10. The main point of this is + # that there are instances where a script will manually submit a + # number of jobs to the queue, e.g. with log files foo.1.log, + # foo.2.log and so on, and we don't want all of these to go + # to the first machine. + @A = split(".", basename($logfile)); + # if $logfile looks like foo.9.log, add 9 to $offset. + foreach $a (@A) { if ($a =~ m/^\d+$/) { $offset += $a; } } +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + + +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $childpid = fork(); + if (!defined $childpid) { die "Error forking in ssh.pl (writing to $logfile)"; } + if ($childpid == 0) { + # We're in the child... this branch executes the job and returns (possibly + # with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + { # work out the machine to ssh to. + $local_offset = $offset + $jobid - 1; # subtract 1 since jobs never start + # from 0; we'd like the first job + # to normally run on the first + # machine. + $num_machines = scalar @machines; + # in the next line, the "+ $num_machines" is in case $local_offset is + # negative, to ensure the modulus is calculated in the mathematical way, not + # in the C way where (negative number % positive number) is negative. + $machines_index = ($local_offset + $num_machines) % $num_machines; + $machine = $machines[$machines_index]; + } + if (!open(S, "|ssh $machine bash")) { + print STDERR "ssh.pl failed to ssh to $machine"; + exit(1); # exits from the forked process within ssh.pl. + } + $cwd = getcwd(); + $logdir = dirname($logfile); + # Below, we're printing into ssh which has opened a bash session; these are + # bash commands. + print S "set -e\n"; # if any of the later commands fails, we want it to exit. + print S "cd $cwd\n"; + print S ". ./path.sh\n"; + print S "mkdir -p $logdir\n"; + print S "time1=\`date +\"%s\"\`\n"; + print S "( echo '#' Running on \`hostname\`\n"; + print S " echo '#' Started at \`date\`\n"; + print S " echo -n '# '; cat <<EOF\n"; + print S "$cmd\n"; + print S "EOF\n"; + print S ") >$logfile\n"; + print S "set +e\n"; # we don't want bash to exit if the next line fails. + # in the next line, || true means allow this one to fail and not have bash exit immediately. + print S " ( $cmd ) 2>>$logfile >>$logfile\n"; + print S "ret=\$?\n"; + print S "set -e\n"; # back into mode where it will exit on error. + print S "time2=\`date +\"%s\"\`\n"; + print S "echo '#' Accounting: time=\$((\$time2-\$time1)) threads=1 >>$logfile\n"; + print S "echo '#' Finished at \`date\` with status \$ret >>$logfile\n"; + print S "exit \$ret"; # return with the status the command exited with. + $ret = close(S); + $ssh_return_status = $?; + # see http://perldoc.perl.org/functions/close.html for explanation of return + # status of close() and the variables it sets. + if (! $ret && $! != 0) { die "ssh.pl: unexpected problem ssh'ing to machine $machine"; } + if ($ssh_return_status != 0) { exit(1); } # exit with error status from this forked process. + else { exit(0); } # else exit with non-error status. + } +} + +$ret = 0; +$numfail = 0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $r = wait(); + if ($r == -1) { die "Error waiting for child process"; } # should never happen. + if ($? != 0) { $numfail++; $ret = 1; } # The child process failed. +} + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "ssh.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "ssh.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/stdout.pl new file mode 100644 index 00000000..1636406b --- /dev/null +++ b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/egs/yesno/voc1/utils/stdout.pl @@ -0,0 +1,282 @@ +#!/usr/bin/env perl +use warnings; #sed replacement for -w perl parameter + +# In general, doing +# run.pl some.log a b c is like running the command a b c in +# the bash shell, and putting the standard error and output into some.log. +# To run parallel jobs (backgrounded on the host machine), you can do (e.g.) +# run.pl JOB=1:4 some.JOB.log a b c JOB is like running the command a b c JOB +# and putting it in some.JOB.log, for each one. [Note: JOB can be any identifier]. +# If any of the jobs fails, this script will fail. + +# A typical example is: +# run.pl some.log my-prog "--opt=foo bar" foo \| other-prog baz +# and run.pl will run something like: +# ( my-prog '--opt=foo bar' foo | other-prog baz ) >& some.log +# +# Basically it takes the command-line arguments, quotes them +# as necessary to preserve spaces, and evaluates them with bash. +# In addition it puts the command line at the top of the log, and +# the start and end times of the command at the beginning and end. +# The reason why this is useful is so that we can create a different +# version of this program that uses a queueing system instead. + +# use Data::Dumper; + +@ARGV < 2 && die "usage: run.pl log-file command-line arguments..."; + + +$max_jobs_run = -1; +$jobstart = 1; +$jobend = 1; +$ignored_opts = ""; # These will be ignored. + +# First parse an option like JOB=1:4, and any +# options that would normally be given to +# queue.pl, which we will just discard. + +for (my $x = 1; $x <= 2; $x++) { # This for-loop is to + # allow the JOB=1:n option to be interleaved with the + # options to qsub. + while (@ARGV >= 2 && $ARGV[0] =~ m:^-:) { + # parse any options that would normally go to qsub, but which will be ignored here. + my $switch = shift @ARGV; + if ($switch eq "-V") { + $ignored_opts .= "-V "; + } elsif ($switch eq "--max-jobs-run" || $switch eq "-tc") { + # we do support the option --max-jobs-run n, and its GridEngine form -tc n. + $max_jobs_run = shift @ARGV; + if (! ($max_jobs_run > 0)) { + die "run.pl: invalid option --max-jobs-run $max_jobs_run"; + } + } else { + my $argument = shift @ARGV; + if ($argument =~ m/^--/) { + print STDERR "run.pl: WARNING: suspicious argument '$argument' to $switch; starts with '-'\n"; + } + if ($switch eq "-sync" && $argument =~ m/^[yY]/) { + $ignored_opts .= "-sync "; # Note: in the + # corresponding code in queue.pl it says instead, just "$sync = 1;". + } elsif ($switch eq "-pe") { # e.g. -pe smp 5 + my $argument2 = shift @ARGV; + $ignored_opts .= "$switch $argument $argument2 "; + } elsif ($switch eq "--gpu") { + $using_gpu = $argument; + } else { + # Ignore option. + $ignored_opts .= "$switch $argument "; + } + } + } + if ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+):(\d+)$/) { # e.g. JOB=1:20 + $jobname = $1; + $jobstart = $2; + $jobend = $3; + shift; + if ($jobstart > $jobend) { + die "run.pl: invalid job range $ARGV[0]"; + } + if ($jobstart <= 0) { + die "run.pl: invalid job range $ARGV[0], start must be strictly positive (this is required for GridEngine compatibility)."; + } + } elsif ($ARGV[0] =~ m/^([\w_][\w\d_]*)+=(\d+)$/) { # e.g. JOB=1. + $jobname = $1; + $jobstart = $2; + $jobend = $2; + shift; + } elsif ($ARGV[0] =~ m/.+\=.*\:.*$/) { + print STDERR "run.pl: Warning: suspicious first argument to run.pl: $ARGV[0]\n"; + } +} + +# Users found this message confusing so we are removing it. +# if ($ignored_opts ne "") { +# print STDERR "run.pl: Warning: ignoring options \"$ignored_opts\"\n"; +# } + +if ($max_jobs_run == -1) { # If --max-jobs-run option not set, + # then work out the number of processors if possible, + # and set it based on that. + $max_jobs_run = 0; + if ($using_gpu) { + if (open(P, "nvidia-smi -L |")) { + $max_jobs_run++ while (<P>); + close(P); + } + if ($max_jobs_run == 0) { + $max_jobs_run = 1; + print STDERR "run.pl: Warning: failed to detect number of GPUs from nvidia-smi, using ${max_jobs_run}\n"; + } + } elsif (open(P, "</proc/cpuinfo")) { # Linux + while (<P>) { if (m/^processor/) { $max_jobs_run++; } } + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from /proc/cpuinfo\n"; + $max_jobs_run = 10; # reasonable default. + } + close(P); + } elsif (open(P, "sysctl -a |")) { # BSD/Darwin + while (<P>) { + if (m/hw\.ncpu\s*[:=]\s*(\d+)/) { # hw.ncpu = 4, or hw.ncpu: 4 + $max_jobs_run = $1; + last; + } + } + close(P); + if ($max_jobs_run == 0) { + print STDERR "run.pl: Warning: failed to detect any processors from sysctl -a\n"; + $max_jobs_run = 10; # reasonable default. + } + } else { + # allow at most 32 jobs at once, on non-UNIX systems; change this code + # if you need to change this default. + $max_jobs_run = 32; + } + # The just-computed value of $max_jobs_run is just the number of processors + # (or our best guess); and if it happens that the number of jobs we need to + # run is just slightly above $max_jobs_run, it will make sense to increase + # $max_jobs_run to equal the number of jobs, so we don't have a small number + # of leftover jobs. + $num_jobs = $jobend - $jobstart + 1; + if (!$using_gpu && + $num_jobs > $max_jobs_run && $num_jobs < 1.4 * $max_jobs_run) { + $max_jobs_run = $num_jobs; + } +} + +$logfile = shift @ARGV; + +if (defined $jobname && $logfile !~ m/$jobname/ && + $jobend > $jobstart) { + print STDERR "run.pl: you are trying to run a parallel job but " + . "you are putting the output into just one log file ($logfile)\n"; + exit(1); +} + +$cmd = ""; + +foreach $x (@ARGV) { + if ($x =~ m/^\S+$/) { $cmd .= $x . " "; } + elsif ($x =~ m:\":) { $cmd .= "'$x' "; } + else { $cmd .= "\"$x\" "; } +} + +#$Data::Dumper::Indent=0; +$ret = 0; +$numfail = 0; +%active_pids=(); + +use POSIX ":sys_wait_h"; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + if (scalar(keys %active_pids) >= $max_jobs_run) { + + # Lets wait for a change in any child's status + # Then we have to work out which child finished + $r = waitpid(-1, 0); + $code = $?; + if ($r < 0 ) { die "run.pl: Error waiting for child process"; } # should never happen. + if ( defined $active_pids{$r} ) { + $jid=$active_pids{$r}; + $fail[$jid]=$code; + if ($code !=0) { $numfail++;} + delete $active_pids{$r}; + # print STDERR "Finished: $r/$jid " . Dumper(\%active_pids) . "\n"; + } else { + die "run.pl: Cannot find the PID of the chold process that just finished."; + } + + # In theory we could do a non-blocking waitpid over all jobs running just + # to find out if only one or more jobs finished during the previous waitpid() + # However, we just omit this and will reap the next one in the next pass + # through the for(;;) cycle + } + $childpid = fork(); + if (!defined $childpid) { die "run.pl: Error forking in run.pl (writing to $logfile)"; } + if ($childpid == 0) { # We're in the child... this branch + # executes the job and returns (possibly with an error status). + if (defined $jobname) { + $cmd =~ s/$jobname/$jobid/g; + $logfile =~ s/$jobname/$jobid/g; + } + system("mkdir -p `dirname $logfile` 2>/dev/null"); + open(F, ">$logfile") || die "run.pl: Error opening log file $logfile"; + print F "# " . $cmd . "\n"; + print F "# Started at " . `date`; + $starttime = `date +'%s'`; + print F "#\n"; + close(F); + + # Pipe into bash.. make sure we're not using any other shell. + open(B, "|bash") || die "run.pl: Error opening shell command"; + print B "( " . $cmd . ") |& tee -a $logfile"; + close(B); # If there was an error, exit status is in $? + $ret = $?; + + $lowbits = $ret & 127; + $highbits = $ret >> 8; + if ($lowbits != 0) { $return_str = "code $highbits; signal $lowbits" } + else { $return_str = "code $highbits"; } + + $endtime = `date +'%s'`; + open(F, ">>$logfile") || die "run.pl: Error opening log file $logfile (again)"; + $enddate = `date`; + chop $enddate; + print F "# Accounting: time=" . ($endtime - $starttime) . " threads=1\n"; + print F "# Ended ($return_str) at " . $enddate . ", elapsed time " . ($endtime-$starttime) . " seconds\n"; + close(F); + exit($ret == 0 ? 0 : 1); + } else { + $pid[$jobid] = $childpid; + $active_pids{$childpid} = $jobid; + # print STDERR "Queued: " . Dumper(\%active_pids) . "\n"; + } +} + +# Now we have submitted all the jobs, lets wait until all the jobs finish +foreach $child (keys %active_pids) { + $jobid=$active_pids{$child}; + $r = waitpid($pid[$jobid], 0); + $code = $?; + if ($r == -1) { die "run.pl: Error waiting for child process"; } # should never happen. + if ($r != 0) { $fail[$jobid]=$code; $numfail++ if $code!=0; } # Completed successfully +} + +# Some sanity checks: +# The $fail array should not contain undefined codes +# The number of non-zeros in that array should be equal to $numfail +# We cannot do foreach() here, as the JOB ids do not necessarily start by zero +$failed_jids=0; +for ($jobid = $jobstart; $jobid <= $jobend; $jobid++) { + $job_return = $fail[$jobid]; + if (not defined $job_return ) { + # print Dumper(\@fail); + + die "run.pl: Sanity check failed: we have indication that some jobs are running " . + "even after we waited for all jobs to finish" ; + } + if ($job_return != 0 ){ $failed_jids++;} +} +if ($failed_jids != $numfail) { + die "run.pl: Sanity check failed: cannot find out how many jobs failed ($failed_jids x $numfail)." +} +if ($numfail > 0) { $ret = 1; } + +if ($ret != 0) { + $njobs = $jobend - $jobstart + 1; + if ($njobs == 1) { + if (defined $jobname) { + $logfile =~ s/$jobname/$jobstart/; # only one numbered job, so replace name with + # that job. + } + print STDERR "run.pl: job failed, log is in $logfile\n"; + if ($logfile =~ m/JOB/) { + print STDERR "run.pl: probably you forgot to put JOB=1:\$nj in your script."; + } + } + else { + $logfile =~ s/$jobname/*/g; + print STDERR "run.pl: $numfail / $njobs failed, log is in $logfile\n"; + } +} + + +exit ($ret); diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/compute_statistics.py b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/compute_statistics.py old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/decode.py b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/decode.py old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/normalize.py b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/normalize.py old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/preprocess.py b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/preprocess.py old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/train.py b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/parallel_wavegan/bin/train.py old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/combine_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/combine_data.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/download_from_google_drive.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/download_from_google_drive.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/make_subset_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/make_subset_data.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/parse_options.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/parse_options.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/queue.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/queue.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/run.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/run.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/slurm.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/slurm.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_data.sh b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_data.sh old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_scp.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/split_scp.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/ssh.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/ssh.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/stdout.pl b/speech/speech_synthesis/vqmivc/pytorch/ParallelWaveGAN/utils/stdout.pl old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/config.json b/speech/speech_synthesis/waveglow/pytorch/config.json old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/tacotron2/README.md b/speech/speech_synthesis/waveglow/pytorch/tacotron2/README.md old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/tacotron2/demo.wav b/speech/speech_synthesis/waveglow/pytorch/tacotron2/demo.wav old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_test_filelist.txt b/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_test_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_train_filelist.txt b/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_train_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_val_filelist.txt b/speech/speech_synthesis/waveglow/pytorch/tacotron2/filelists/ljs_audio_text_val_filelist.txt old mode 100755 new mode 100644 diff --git a/speech/speech_synthesis/waveglow/pytorch/waveglow_logo.png b/speech/speech_synthesis/waveglow/pytorch/waveglow_logo.png old mode 100755 new mode 100644 -- Gitee

G;o=@i=Z1O(oM{()(WV07m|8S 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
Dsm#==2=JVe9%Q^g}CeTlTP7LK6+ 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
~tsS-O63SlpbwBZrA;Zr=t|RO>A`z9PQ` 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